john pfeiffer
  • Home
  • Categories
  • Tags
  • Archives

ftp client in c

/* john pfeiffer june 2007 my own ftp client in c */

#include <winsock.h>    /*important to load object files C:\devcpp\Lib\libwsock32.a*/
#include <stdio.h>
#include <stdlib.h>     /* for atoi() - char to int function */

#define BUFFERMAX 1024
#define CMDPORT 21
#define DATAPORT 20
#define SITENAME "localhost"
/*#define IPADDRESS "127.0.0.1"   */
#define IPADDRESS "209.85.5.187"  /* beyondcalifornia.com */

void exit_all( SOCKET s )
{       shutdown(s,1);          /*better than close()  */
        closesocket(s);
        WSACleanup();
}/*end func exit_all()    Cleans up the WSA & closes the socket */

int get_digits( int* buffer_index, char buffer[BUFFERMAX], char digits[16], int* digits_index )
{   int exit_loop = 0;
    do
    {   if( buffer[ *buffer_index ] == ',' || buffer[ *buffer_index ] == ')')
        {   exit_loop = 1;  }        
        digits[ *digits_index ] = buffer[ *buffer_index ];
        *digits_index = *digits_index + 1;
        *buffer_index = *buffer_index + 1;

    }while( exit_loop != 1 ) ;
    digits[ *digits_index - 1 ] = '.';   /*digits now contains up to 3 digits and '.'*/
}/*end func get_digits()  Copies chars from buffer to digits until ',' or ')' */

void pasv_parse( int d, char buffer[BUFFERMAX], char PASVaddress[16], int* PASVport)  
{   int exit_loop = 0;
    int buffer_index=0;
    int address_index=0;
    char cPort[8];
    int nPort[2];
    int i;

    do                 /*find first parenthesis  */
    {   if( (buffer[buffer_index] == '(') || (buffer_index == strlen(buffer)) )
        {   exit_loop=1;    }                /*there should be 5 groups of */
        buffer_index = buffer_index + 1;     /*up to 3 digits, ',' delimited  */
    }while( exit_loop != 1 );                /*Starting and finishing with '( )' */

    if( buffer_index < strlen(buffer))    /* to make sure everything's OK  */
    {        
        for( i=0; i<4; i++)     /* get the 4 digits IP address*/
        {   get_digits( &buffer_index, buffer, PASVaddress, &address_index );      }
        PASVaddress[ address_index-1 ] = '\0';

        address_index = 0;
        get_digits( &buffer_index, buffer, cPort, &address_index );          
        cPort[ address_index-1 ] = '\0';
        nPort[0] = atoi(cPort);      /*get the first paramater about the port */

        address_index = 0;
        get_digits( &buffer_index, buffer, cPort, &address_index );          
        cPort[ address_index-1 ] = '\0';
        nPort[1] = atoi(cPort);      /*get the second paramater about the port*/

        *PASVport = (256*(nPort[0])) + (nPort[1]);  /* 8 highbits + 8 bits    */
    }
}/*end func pasv_parse()  Formats the server response to PASV command */

/* SPECIAL CASE FROM RFC 959
123-First line                           //one received buffer
Second line                              //next received buffer
234 A line beginning with numbers        //next received buffer
123 The last line                        //finally end of message    */

int process_buffer( int nReceived, char buffer[BUFFERMAX], char server_response_code[4], 
                        int msg_finished )
{   char display[512];
    int display_counter=0;
    int i=0;
    int end_line = 0;
/*    printf("%d bytes received from SERVER\n",nReceived);    /*DBEUGGING ONLY*/
    do
    {   do
        {   if( buffer[i]==13 && buffer[i+1]==10 ) 
            {   end_line = 1;   }
            else
            {   display[display_counter] = buffer[i];
                i = i + 1;
            }
            display_counter = display_counter + 1;
        }while( end_line == 0 );
        display[display_counter-1] = '\0';
        puts(display);

        if( msg_finished == 0 )                       /*if multi line message */
        {   if( (server_response_code[0] == display[0]) && /* our original resp code */
                (server_response_code[1] == display[1]) &&
                (server_response_code[2] == display[2]) &&
                (display[3] == ' ') )        /*blank means end multi-line msg */
            {   msg_finished = -1;  }          /*end the recv loop in main    */
        }
        display_counter = 0;                  /* reset our variables          */
        end_line = 0;               /* reset so we can get another whole line */

        i=i+2;             /* skip the '/r' and '/n' */
    }while( i < nReceived );                       
    return( msg_finished );
}/* end func process_buffer() puts on screen buffer's contents */

int begin_server_reply( int nReceived, char buffer[BUFFERMAX], char server_response_code[4])
{   int msg_finished = -1;                   /* if -1 then full msg received  */

    server_response_code[0] = buffer[0]; 
    server_response_code[1] = buffer[1]; 
    server_response_code[2] = buffer[2]; 
    server_response_code[3] = buffer[3];  /* if is a '-', then multi line msg */
    if( server_response_code[3] == '-' )
    {   msg_finished = 0;   
        printf("multi line message\n");
    }
    msg_finished = process_buffer( nReceived, buffer, server_response_code, msg_finished );
    return( msg_finished );
}/*end func server_reply();  Formats and displays the server's reply on screen*/

int cmd( char* usercommand, char buffer[BUFFERMAX] )
{   strcpy(buffer,usercommand); 
    puts(buffer);
    strcat(buffer,"\r\n\r\n");
    if( strlen(buffer) < 512)
    {   return( 512 );  }
    else
    {     return( strlen(buffer) );   }
}/*end func cmd() Formats string const, puts it in the buffer & on the screen */

/*must pass by reference for Structs!!!!*/
void setup_socket_connect_data( SOCKADDR_IN* ptraData, char ip[16], int port )
{   (*ptraData).sin_family = AF_INET;        /*internet protocol addressing  */
    (*ptraData).sin_port = htons(port);   /*connect to port - change to big endian */
    (*ptraData).sin_addr.s_addr = inet_addr(ip);  /*needs a null terminated string*/
    memset(&((*ptraData).sin_zero), '\0', 8); /* zero the rest of the struct*/
    printf("Connecting to %s at port %d...\n",ip,port);
}/*end func setup_socket_connect_data()  */

/*////MAIN////////////////////////////////////////////////////////////////////*/
int main(void)
{   char buffer[BUFFERMAX];
    char server_response_code[4];               /*250-                 */
    char ipaddress[16];                         /*255.255.255.255'\0'  */
    int port=0;
    WSADATA ws;                               /*defined in winsock - before socket usage!*/
    int nReceived = WSAStartup(0x0202,&ws);   /*starts winsock 2 (windows only)*/
    printf("WSASTARTUP = %d  ",nReceived);    /*shows the result (error?)*/

    SOCKADDR_IN SockAddrInData;          /*easy struct for socket addressing internals*/
    SOCKET sCMD = socket(AF_INET,SOCK_STREAM,0); /*get the handle to socket (should be > 0) */
    SOCKET sDATA = socket(AF_INET,SOCK_STREAM,0); 
    SOCKET sPASV = socket(AF_INET,SOCK_STREAM,0); /*to connect to a server with PASV*/

/*Make Connection/////////////////////////////////////////////////////////////*/
    strcpy(ipaddress,IPADDRESS); /*must pass by ref for structs*/
    setup_socket_connect_data( &SockAddrInData, ipaddress, CMDPORT );
                                 /*must cast  */
    nReceived = connect( sCMD, (SOCKADDR*) &SockAddrInData, sizeof(SockAddrInData) );  
    printf(" SOCKET = %d, Connected? %d (should be: 0)\n",sCMD,nReceived);                           
    if( nReceived < 0 ){    printf("\nERROR GETTING SOCKET\n");  exit(1);  }

    memset(&buffer, '\0', BUFFERMAX);                     /* clear the buffer */
    nReceived = recv(sCMD,buffer,sizeof(buffer),0);
    /* if multi line response from server this will get it all */
    if( begin_server_reply(nReceived,buffer,server_response_code) == 0 )
    {   do
        {   nReceived = recv(sCMD,buffer,sizeof(buffer),0);
            nReceived = process_buffer(nReceived,buffer,server_response_code,0);
        }while( nReceived != -1 );     /* process_buffer returns -1 when done */
    }
/*Logging In//////////////////////////////////////////////////////////////////*/
    send(sCMD,buffer,    cmd("USER myusername",buffer)    ,0);        
    nReceived = recv(sCMD,buffer,sizeof(buffer),0);    
    if( begin_server_reply(nReceived,buffer,server_response_code) == 0 )
    {   do
        {   nReceived = recv(sCMD,buffer,sizeof(buffer),0);
            nReceived = process_buffer(nReceived,buffer,server_response_code,0);
        }while( nReceived != -1 );     /* process_buffer returns -1 when done */
    }

    memset(&buffer, '\0', BUFFERMAX);                     /* clear the buffer */
    send(sCMD,"PASS mypassword\r\n\r\n",512,0);

    nReceived = recv(sCMD,buffer,sizeof(buffer),0);    
//    printf("\nhello\n");
//    puts(buffer);
    if( begin_server_reply(nReceived,buffer,server_response_code) == 0 )
    {   do
        {   nReceived = recv(sCMD,buffer,sizeof(buffer),0);
            nReceived = process_buffer(nReceived,buffer,server_response_code,0);
        }while( nReceived != -1 );     /* process_buffer returns -1 when done */
    }
/*Passive Setup///////////////////////////////////////////////////////////////*/
/*    send(sCMD,buffer,  cmd("PASV",buffer)   ,0);        
    nReceived = recv(sCMD,buffer,sizeof(buffer),0);    
    begin_server_reply(nReceived,buffer,server_response_code);

    pasv_parse(nReceived, buffer, ipaddress, &port);
    setup_socket_connect_data( &SockAddrInData, ipaddress, port );

    nReceived = connect( sPASV, (SOCKADDR*) &SockAddrInData, sizeof(SockAddrInData) );
    printf(" SOCKET = %d, Connected? %d (should be: 0)\n",sPASV,nReceived);                           
    if( nReceived < 0 ){    printf("\nERROR GETTING SOCKET\n");  exit(1);  }
/*Changing Directory//////////////////////////////////////////////////////////*/
//    send(sCMD,buffer,  cmd("PWD",buffer)   ,0);        /*PWD too*/
//    send(sCMD,buffer,  cmd("CWD html/temp",buffer)   ,0);        /*PWD too*/
//    nReceived = recv(sCMD,buffer,sizeof(buffer),0);    
//    begin_server_reply(nReceived,buffer,server_response_code);
/*Listing File Names//////////////////////////////////////////////////////////*/
/*    send(sCMD,buffer,  cmd("LIST",buffer)   ,0);        
    nReceived = recv(sCMD,buffer,sizeof(buffer),0);    
    begin_server_reply(nReceived,buffer,server_response_code);

    nReceived = recv(sPASV,buffer,sizeof(buffer),0);    
    printf("%d bytes received from SERVER\n",nReceived);    
    begin_server_reply(nReceived,buffer,server_response_code);


/*////QUIT////////////////////////////////////////////////////////////////////*/
    send(sCMD,buffer,  cmd("QUIT",buffer)   ,0);        
    nReceived = recv(sCMD,buffer,sizeof(buffer),0);    
    begin_server_reply(nReceived,buffer,server_response_code);

    exit_all(sPASV);
    exit_all(sCMD);                     /*clean up socket, ws, etc.  */
    return 0;                           /*rumor is, ALWAYS RETURN    */
}/*end main   */
/*////END OF PROGRAM//////////////////////////////////////////////////////////*/

/*socket,receive buffer,cmd,0 - i don't know why 0*/
//    printf("%d\n",strlen("USER foupfeiffer_fun\r\n\r\n"));
//    send(s,"USER foupfeiffer_fun\r\n\r\n",24,0);    
//  send(s,buffer, cmd(strcpy(buffer,"USER foupfeiffer_fun"), buffer),0); 
//    strcpy(buffer,"USER foupfeiffer_fun\r\n\r\n");

/*
    do{
        gets(buffer);
        if( buffer[0] != 'q' )
        {   send(s,buffer,cmd(buffer, buffer),0);     
            nReceived = recv(s,buffer,sizeof(buffer),0);    
            server_reply(s,nReceived,buffer);
        }else{   printf("Thank you, now closing socket and quitting.");   }

    }while( buffer[0]!='q' );

/*
    Default Data? port 20?
    setup_socket_connect_data( &SockAddrInData, ipaddress, DATAPORT );
    nReceived = connect( sDATA, (SOCKADDR*) &SockAddrInData, sizeof(SockAddrInData) );  
    printf(" SOCKET = %d, Connected? %d (should be: 0)\n",sDATA,nReceived);
    if( nReceived < 0 ){    printf("\nERROR GETTING SOCKET\n");  exit(1);  }


ACTIVE PORT COMMAND
    send(s,buffer, cmd(strcpy(buffer,"PORT 127,0,0,1,0,88"), buffer),0);

COMMANDS TO IMITATE
rename      RNFR/RNTO
mkdir       MKD
rmdir       RMD
delete      DELE
send        STOR        
recv        RETR
ascii
binary

help site
help
status      STAT    used only during transfer
*/

  • « file remove baddata
  • ascii char int printout »

Published

Jun 1, 2007

Category

c

~903 words

Tags

  • c 95
  • cftp 2
  • client 14
  • ftp 6