/*

    File: ftpp/ctrlcmd.cc

    Copyright (C) 2002  Dmitry Udalov
    Email:uddm@penza.net
  
    This software 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 of the License, 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.
    
 */


#include "ftpproxy.h"


//parse command USER username@hostname:port
int parseaddress(struct ClientParam *Session,char *lpszAddress){
    char *lpszUser=NULL,*lpszStr=NULL,*lpszHost=NULL,*lpszPort=NULL;
    char szUser[STR_SIZE],szHost[STR_SIZE],szPort[STR_SIZE];
    short int wPort;
    lpszStr=lpszAddress;
    lpszHost=strstr(lpszStr,"@");
    if(lpszHost==NULL){//if not exists @ char
         lpszHost=strstr(lpszStr,"%");
         if(lpszHost!=NULL){//if exists % char
              lpszHost=lpszHost+1;
              strncpy(szUser,lpszStr,lpszHost-1-lpszStr);//copy username
              szUser[lpszHost-lpszStr]='\0';
              lpszStr=lpszHost;//copy hostname and port
              lpszPort=strstr(lpszHost,":");
              if(lpszPort==NULL){//if not exists : char then
                  strcpy(szHost,lpszHost);
                  strcpy(szPort,"");
              }
              else{//if exists : char
                  lpszPort=lpszPort+1;
                  strncpy(szHost,lpszStr,lpszPort-1-lpszHost);
                  szHost[lpszPort-lpszHost]='\0';
                  strcpy(szPort,lpszPort);//copy port
              }
         }
    }
    else{//samething
         lpszHost=lpszHost+1;
         strncpy(szUser,lpszStr,lpszHost-1-lpszStr);
         szUser[lpszHost-1-lpszStr]='\0';
         lpszStr=lpszHost;
         lpszPort=strstr(lpszHost,":");
         if(lpszPort==NULL){
              strcpy(szHost,lpszHost);
              strcpy(szPort,"");
         }
         else{
              lpszPort=lpszPort+1;
              strncpy(szHost,lpszStr,lpszPort-1-lpszHost);
              szHost[lpszPort-1-lpszHost]='\0';
              strcpy(szPort,lpszPort);
         }
    }
    strcpy(Session->szUserName,szUser);
    //parse host
    if(strlen(szHost)!=0){//if host name exists
        // get ip addres by host name
        struct hostent *hp;
        if((hp = gethostbyname(szHost)) == NULL) {
            sendreply(Session,S501MSG);
            return FALSE;
        }
        //fill server addres
        memcpy(&(Session->ServerAddr.sin_addr), hp->h_addr, hp->h_length);
    }
    else{
         //if hostname not exists
        sendreply(Session,S501MSG);
        return FALSE;
    }
    if(strlen(szPort)==0)
         wPort=21;//if port not exist then port=standart number e.g. 21
    else
         wPort=atoi(szPort);
    Session->ServerAddr.sin_port=htons(wPort);
    Session->ServerAddr.sin_family=AF_INET;
    return TRUE;
}

//process USER comman
int usercmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam){
    char cBuf[BUF_SIZE];
    strcpy(Session->szUserName,lpszParam);
    
    if(fTransparentFTPProxy!=TRUE){//if not transparent proxy then
        int iRes=parseaddress(Session,lpszParam);//get server addres,user name, port
        if(iRes==FALSE){
            sendreply(Session,S530MSG);
            close(Session->hCtrlClientSocket);
            return FALSE;
        }
        iRes=servconnect(Session);//connect to server
        if(iRes==FALSE){
	    sendreply(Session,S530MSG);
            logex(iClientNum,"Not logged %s(%s) < %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
            close(Session->hCtrlClientSocket);
            return FALSE;
        }
    }
    //else if transparent proxy then
    //send USER command to server
    sprintf(cBuf,"USER %s",Session->szUserName);
    sendcmd(Session,cBuf);
    logex(iClientNum,"Not logged (%s) < %s",inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    int iRetCode=getreply(Session,cBuf);
    sendreply(Session,cBuf);
    while(iRetCode==0){
       iRetCode=getreply(Session,cBuf);
       sendreply(Session,cBuf);
       logex(iClientNum,"Not logged %s(%s) < %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    }
    return TRUE;
}

//process PASS command
int passcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam){
     //send reply
    char cBuf[BUF_SIZE];
    strcpy(Session->szUserPass,lpszParam);
    //send command to server
    sprintf(cBuf,"PASS %s",Session->szUserPass);
    sendcmd(Session,cBuf);
    logex(iClientNum,"Logged %s(%s) > %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    //get server reply
    int iRetCode=getreply(Session,cBuf);
    if(iRetCode==-1)
        return FALSE;
    logex(iClientNum,"Not logged %s(%s) < %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    //send reply to client
    sendreply(Session,cBuf);
    while(iRetCode==0){
       iRetCode=getreply(Session,cBuf);
       sendreply(Session,cBuf);
       logex(iClientNum,"Not logged %s(%s) < %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    }
    if(iRetCode==230){
        Session->fServerConnected=TRUE;
        Session->fUserLogged=TRUE;
        logex(iClientNum,"Logged %s(%s) to (%s).",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),inet_ntoa(Session->ServerAddr.sin_addr));
    }
    else
        logex(iClientNum,"Not logged (%s) > %s",inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    return TRUE;
}

//proccess QUIT command
int quitcmdprocces(struct ClientParam *Session,char *lpszFTPCmd,char* lpszParam){
    char cBuf[BUF_SIZE];
    sprintf(cBuf,"%s %s",lpszFTPCmd,lpszParam);
    trim(cBuf,cBuf);
    //send command to server
    sendcmd(Session,cBuf);
    logex(iClientNum,"Logged %s(%s) > %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    //get reply from server
    int iRetCode=getreply(Session,cBuf);
    //send reply to client
    sendreply(Session,cBuf);
    logex(iClientNum,"Logged %s(%s) < %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    while(iRetCode==0){
       iRetCode=getreply(Session,cBuf);
       sendreply(Session,cBuf);
       logex(iClientNum,"Logged %s(%s) > %s",Session->szUserName,inet_ntoa(Session->ClientAddr.sin_addr),cBuf);
    }
    return FALSE;
}

