/* Copyright (C) 1999 Beau Kuiper

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include "ftpd.h"
#include "ftpcmd.h"

/*	command, proc,	needsparam, needlogin, dataportok */

FTPCMD siteftpcmd[] = {
#ifdef DUMPCMD
	{"DUMP", ftpsite_dump, TRUE, TRUE, FALSE, "Display a file over control connection." }, */
#endif
	{"UMASK", ftpsite_umask, FALSE, TRUE, FALSE, "Change the umask." },
	{"CHMOD", ftpsite_chmod, TRUE, TRUE, FALSE, "Change the permissions on a file." },
	{"HELP", ftpsite_help, FALSE, TRUE, TRUE, "Get help on SITE commands." },
#ifdef ACCESSCMD
	{"ACCESS", ftpsite_access, FALSE, TRUE, TRUE, "Show access list that is enforced." }, */
#endif
	{"IDLE", ftpsite_idle, FALSE, TRUE, FALSE, "Change the current timeout." },
	{"", NULL, FALSE, FALSE, FALSE, ""}
};

FTPCMD mainftpcmd[] = {
	{"PORT", ftp_port, TRUE , TRUE , FALSE, "Specify data port connection." },
	{"PASV", ftp_pasv, FALSE, TRUE , FALSE, "Specify a passive data port connection." },
	{"RETR", ftp_retr, TRUE , TRUE , FALSE, "Download a file." },
	{"STOR", ftp_stor, TRUE , TRUE , FALSE, "Upload a file." },
	{"STOU", ftp_stou, TRUE , TRUE , FALSE, "Upload a file, storing it with a unique filename." },
	{"APPE", ftp_appe, TRUE , TRUE , FALSE, "Append to a file on the server." },
	{"TYPE", ftp_type, TRUE , TRUE , FALSE, "Specify type of file transfer." },
	{"QUIT", ftp_quit, FALSE, FALSE, TRUE , "Quit control connection." },
	{"PASS", ftp_pass, FALSE, FALSE, FALSE, "Specify password." },
	{"USER", ftp_user, TRUE , FALSE, FALSE, "Specify username." },
	{"HOST", ftp_host, TRUE , FALSE, FALSE, "Specify virtual host." },
	{"SYST", ftp_syst, FALSE, FALSE, FALSE, "Return the system type." },
	{"LIST", ftp_list, FALSE, TRUE , FALSE, "Do a long file list." },
	{"NLST", ftp_nlst, FALSE, TRUE , FALSE, "Do a short file list." },
	{"PWD" , ftp_pwd , FALSE, TRUE , FALSE, "Get the current directory." },
	{"XPWD", ftp_pwd , FALSE, TRUE , FALSE, "Get the current directory." },
	{"CWD" , ftp_cwd , TRUE , TRUE , FALSE, "Change the current directory." },
	{"XCWD", ftp_cwd , TRUE , TRUE , FALSE, "Change the current directory." },
	{"ABOR", ftp_abor, FALSE, TRUE , TRUE , "Abort a file transfer." },
	{"CDUP", ftp_cdup, FALSE, TRUE , FALSE, "Change to parent directory." },
	{"XCUP", ftp_cdup, FALSE, TRUE , FALSE, "Change to parent directory." },
	{"STAT", ftp_stat, FALSE, TRUE , TRUE , "Get server status." },
	{"NOOP", ftp_noop, FALSE, FALSE, TRUE , "No-operation." },
	{"REIN", ftp_rein, FALSE, FALSE, TRUE , "Re-initialize server." },
	{"REST", ftp_rest, TRUE , TRUE , FALSE, "Specify resume postion for file transfer." },
	{"DELE", ftp_dele, TRUE , TRUE , FALSE, "Delete a file." },
	{"MKD" , ftp_mkd , TRUE , TRUE , FALSE, "Make a new directory." },
	{"XMKD", ftp_mkd , TRUE , TRUE , FALSE, "Make a new directory." },
	{"XRMD", ftp_rmd , TRUE , TRUE , FALSE, "Remove a directory." },
	{"RMD" , ftp_rmd , TRUE , TRUE , FALSE, "Remove a directory." },
	{"RNFR", ftp_rnfr, TRUE , TRUE , FALSE, "Specify a file to rename from." },
	{"RNTO", ftp_rnto, TRUE , TRUE , FALSE, "Specify a file to rename to." },
	{"SIZE", ftp_size, TRUE , TRUE , FALSE, "Get the size of a file." },
	{"MDTM", ftp_mdtm, TRUE , TRUE , FALSE, "Get the modified data of a file." },
	{"HELP", ftp_help, FALSE, FALSE, TRUE , "Get help on commands." },
	{"SITE", ftp_site, FALSE, TRUE , TRUE , "Site specific commands. See SITE HELP." }, 
	{"ALLO", ftp_allo, FALSE, TRUE , FALSE, "Allocate space (redundant)." },
	{"ACCT", ftp_acct, FALSE, TRUE , FALSE, "Specify account (redundant)." },
	{"STRU", ftp_stru, FALSE, TRUE , FALSE, "Specify structure (redundant)."},
	{"EPRT", ftp_eprt, TRUE , TRUE , FALSE, "Specify an extended data port connection."},
	{"EPSV", ftp_epsv, FALSE, TRUE , FALSE, "Specify an extended passive port connection."},
	{"",     NULL    , FALSE, FALSE, FALSE, ""}
};

int *disableset_create(void)
{
	int *set;
	int count = 0;
	
	while(mainftpcmd[count].ftpfunc != NULL)
		count++;
	count++;
	set = mallocwrapper(sizeof(int) * count);
	
	memset(set, 0, sizeof(int) * count);
	return(set);
}

void disableset_disablecmd(int *set, FTPCMD *ctable, char *cmd)
{
	int count = 0;
	
	while((strcasecmp(ctable[count].command, cmd) != 0) && 
	      (ctable[count].ftpfunc != NULL))
		count++;
		
	if (ctable[count].ftpfunc != NULL)
		set[count] = TRUE;
	else
		log_giveentry(MYLOG_INFO, NULL, safe_snprintf("Could not find command '%s' to disable.", cmd));
}

char *getkeyword(char **iline)
{
	char *data, *param;
	
	/* move to the first non-space stuff */
	
	while ((**iline == ' ') || ((unsigned char)**iline > 128))
		(*iline)++;
	
	data = strdupwrapper(*iline);
	
	param = strchr(data, ' ');
	if (param != NULL)
		*param = 0;

	*iline = strchr(*iline, ' ');
	if (*iline != NULL)
		(*iline)++;
	return(data);
}   
	
void cmd_split(FTPSTATE *peer, INPUTLINE *cmd, char* inpline, FTPCMD *ctable, int log,
		int *disableset)
{
	char *command;
	char *param = inpline;
	int counter;
			
	command = getkeyword(&param);
	 
	if (param != NULL)
		cmd->parameters = strdupwrapper(param);
	else
		cmd->parameters = NULL;
	
	counter = 0;
	
	/* while (command not found && not end of table) || command is disabled */
	/* this causes the parser to drop past disabled commands */
	while( ((strcasecmp(ctable[counter].command, command) != 0)
		&& (ctable[counter].ftpfunc != NULL)) ||
		((disableset ? disableset[counter] : ctable[counter].needslogin)))
	{
		counter++;
	}

	cmd->command = &(ctable[counter]);

	if (log)
		if (cmd->command->ftpfunc != ftp_none)
		{
			if (cmd->command->ftpfunc == ftp_pass)
				log_addentry(MYLOG_COMMAND, peer, "PASS *");
			else
				log_addentry(MYLOG_COMMAND, peer, inpline);
		}
	
	freewrapper(command);
}
