#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include "unitools.h"
#include <ctype.h>
#include <time.h>
#include <stdarg.h>

//config params
#define REPLY_TIMEOUT 5
#define SECTIMEOUT 1
#define MSECTIMEOUT 0
#define MAXCLIENTCOUNT 200
#define MAXFILESIZE 100000000
#define ADBMREADTIMEOUT 500
#define ADBMDELTIMEOUT 60
#define WORKINGADDR "127.0.0.1"
#define WORKINGPORT 3021

//program consts
#define SOCKET_ERROR -1

#define LOGNAME "ftpp.log"
#define ACCESSLOG "access.log"
#define CONFNAME "ftpp.conf"

#define FTPPROMT "220 FTP Proxy Ready..."
#define FTPNPROMT "421 Access denied."
#define	S331MSG "331 User name okay, need password"
#define S230MSG "230 User logged, in procced"
#define S215MSG "215 UNIX System type"
#define S221MSG "221 Service closing control connection.\nLogged out if appropriate."
#define S530MSG "530 Not logged in"
#define S502MSG "502 Command not implemented."
#define S500MSG "500 Syntax error, command unrecognized."
#define S501MSG "501 Syntax error, in parameters or arguments."
#define S150MSG "150 File status okay; about to open data connection."
#define S226MSG "226 Closing data connection."
#define S425MSG "425 Can't open data connection"
#define S227MSG "227 Entering passive mode (%s)"
#define S426MSG "426 Transfer aborted, connection closed."
#define S452MSG "452 Requested action aborted"
#define S226AMSG "226 Abort succeful."
#define S500AMSG "500 No command to abort."
#define S421MSG "421 No Transfer Timeout (300 seconds): closing control connection."
#define S421MSG1 "421 Service not available."
#define S450MSG "450 Requested file action not taken."

#define USERCMD "USER"
#define PASSCMD "PASS"
#define PWDCMD "PWD"
#define SYSTCMD "SYST"
#define QUITCMD "QUIT"
#define NOOPCMD "NOOP"
#define PORTCMD "PORT"
#define LISTCMD "LIST"
#define CWDCMD "CWD"
#define PASVCMD "PASV"
#define NLSTCMD "NLST"
#define RNFRCMD "RNFR"
#define RNTOCMD "RNTO"
#define DELECMD "DELE"
#define RMDCMD "RMD"
#define MKDCMD "MKD"
#define CDUPCMD "CDUP"
#define HELPCMD "HELP"
#define SITECMD "SITE"
#define SIZECMD "SIZE"
#define REINCMD "REIN"
#define ABORCMD "ABOR"
#define TYPECMD "TYPE"
#define ACCTCMD "ACCT"
#define STRUCMD "STRU"
#define MODECMD "MODE"
#define STATCMD "STAT"
#define ALLOCMD "ALLO"
#define RESTCMD "REST"
#define RETRCMD "RETR"
#define STORCMD "STOR"
#define SMNTCMD "SMNT"
#define STOUCMD "STOU"
#define APPECMD "APPE"
#define ABORCMD "ABOR"

struct ClientParam{
     int hCtrlClientSocket;
     int hCtrlServerSocket;
     int hDataClientSocket;
     int hListeningClientSocket;
     int hListeningServerSocket;
     int hDataServerSocket;
     int fUserLogged;
     int fServerConnected;
     int fActiveMode;
     struct sockaddr_in ClientAddr;
     struct sockaddr_in ServerAddr;
     struct sockaddr_in ClientDataAddr;
     struct sockaddr_in ServerDataAddr;
     struct sockaddr_in ListeningDataAddr;
     char szUserName[STR_SIZE];
     char szUserPass[STR_SIZE];
};

extern int fNeedTerm,fServerDisconnected,fClientDisconnected,fTransparentFTPProxy;
extern int iWorkingPort,iMaxClients,iClientNum,iClientCnt,iMaxFileSize;
extern char szNetInterface[STR_SIZE],szLogPath[STR_SIZE],szLogFileName[STR_SIZE];
extern char szWorkingAddr[STR_SIZE],szAccessLogPath[STR_SIZE],szAccessLogFileName[STR_SIZE];
extern int iADBMReadTimeOut;

//ftpproxy.cc
void handleclient(int hControlSocket,struct sockaddr_in);
int servicecmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);

//conrol command for ctrlcmd.cc
int parseaddress(struct ClientParam *Session,char *lpszAddress);
int usercmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);
int passcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);
int quitcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);

//socket tools socktool.cc
int servconnect(struct ClientParam *Session);
int waitclient(struct ClientParam *Session);
int waitserver(struct ClientParam *Session);
int waitread(int hHandle,struct timeval TimeOut);
int waitwrite(int hHandle,struct timeval TimeOut);
int sendcmd(struct ClientParam *Session,const char *lpszCmd);
int sendreply(struct ClientParam *Session,const char *lpszReply);
int getreply(struct ClientParam *Session,char *lpszReply);
int getipbyhost(char *lpszHostName);

//Data transfer commands datacmd.cc
int isAbort(struct ClientParam *Session);
int portcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);
int pasvcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);
int aborcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);
int retrcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);
int storcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);
int listcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam);

//logtool.cc
void log(struct ClientParam *Session,const char *lpszMsg,int fReply);
void logex(int iClientN,const char *fmt, ...);
void SaveLog(const char *lpszMsg,const char *lpszFileName);
void accesslog(struct ClientParam *Session,time_t tmtime,int iSize,int iResult,const char *lpszResource);

//ftpproxy.cc
int proccescmd(struct ClientParam *Session,char *lpszBuf);
int parsecmd(struct ClientParam *Session,char* lpszFTPCmd,char* lpszParam);

//configuration cfgtool.cc
void loadcfg();
int getparam(const char *paramname,char *paramvalue);
int getiprights(const char* szIP);

