Main Page Data Structures File List Data Fields Globals Related Pages

# clib/ftp.c

Go to the documentation of this file.

    00001 /****************************************************************************
    00002 *
    00003 * (C) 2001 by Beck IPC GmbH
    00004 *
    00005 *  Beck IPC GmbH
    00006 *  Garbenheimerstr. 36-38
    00007 *  D-35578 Wetzlar
    00008 *
    00009 *  Phone : (49)-6441-905-240
    00010 *  Fax   : (49)-6441-905-245
    00011 *
    00012 * ---------------------------------------------------------------------------
    00013 * Module        : ftp.c
    00014 *
    00015 * Function      : FTP API functions
    00016 *                 Use memory model large!!
    00017 *
    00018 * Compiler    : Tested with Borland C 5.02
    00019 *
    00020 * Author        : Detlef Gerhardt
    00021 * Date          : 20.01.01
    00022 * ---------------------------------------------------------------------------
    00023
    00024 $Header: ftp.c, 3, 16.01.2002 11:51:54, Christoph Stoidner$
    00025
    00026
    00027 $Log:
    00028  3    IPC@CHIP  1.2         16.01.2002 11:51:54  Christoph Stoidner add starteam
    00029       directives
    00030  2    IPC@CHIP  1.1         08.03.2001 15:44:03  Christoph Stoidner
    00031  1    IPC@CHIP  1.0         08.03.2001 15:30:02  Christoph Stoidner
    00032 $
    00033
    00034
    00035 * History       :
    00036 *
    00037 *  Vx.yy                   Author  Changes
    00038 *
    00039 *             11.01.01      dg    create
    00040 *             20.01.01      dg    error handling, malloc ftp connection desc.
    00041 /****************************************************************************/
    00042
    00043 #include <dos.h>
    00044 #include <stdio.h>
    00045 #include <stdlib.h>
    00046 #include <string.h>
    00047 #include <alloc.h>
    00048 #include "ftp.h"
    00049 #include "tcpip.h"
    00050 #include "rtos.h"
    00051
    00052 /****************************************************************************/
    00053
    00054 //#define FTP_DEBUG
    00055
    00056 #define BYTE unsigned char
    00057 #define WORD unsigned int
    00058
    00059 #define FTP_BUF_LEN 512
    00060 char ftp_buf[FTP_BUF_LEN+1];
    00061
    00062 /****************************************************************************/
    00063
    00064 char *strip_crlf(char *s)
    00065 {
    00066   int i;
    00067
    00068   for (i=strlen(s)-1; i>=0; i--)
    00069   {
    00070     if (s[i]=='\r' || s[i]=='\n')
    00071       s[i] = 0;
    00072     else
    00073       break;
    00074   }
    00075   return s;
    00076
    00077 } // strip_crlf()
    00078
    00079 /****************************************************************************/
    00080
    00081 int ftp_send(int sd, char *buffer, int buflen)
    00082 {
    00083   int cnt,error;
    00084
    00085   //printf("ftp_send: %s\r\n",buffer);
    00086   cnt = send(sd,buffer,buflen,0,&error);
    00087   if (error!=0)
    00088   {
    00089     //printf("ftp_send: send error %d\r\n",error);
    00090     return -1;
    00091   }
    00092   return cnt;
    00093
    00094 } // ftp_send()
    00095
    00096 /****************************************************************************/
    00097
    00098 int ftp_recv(int sd, char *recv_buf, int recv_len, int *error)
    00099 {
    00100   int cnt;
    00101
    00102   cnt = recv(sd,recv_buf,recv_len,MSG_TIMEOUT,10000l,error);
    00103   //printf("ftp_recv: sd=%d, cnt=%4d, error=%d\r\n",sd,cnt,*error);
    00104   return cnt;
    00105
    00106 } // ftp_recv()
    00107
    00108 /****************************************************************************/
    00109
    00110 int ftp_recv_msg(int sd, char *buffer, int buflen, int *error)
    00111 {
    00112   int idx,cnt;
    00113
    00114   buffer[0] = 0;
    00115   idx = 0;
    00116   do
    00117   {
    00118     cnt = recv(sd,buffer+idx,buflen-idx,MSG_TIMEOUT,5000l,error);
    00119     if (*error!=0)
    00120     {
    00121 #ifdef FTP_DEBUG
    00122       //printf("ftp_recv_msg: cnt=%d, error=%d\r\n",cnt,*error);
    00123 #endif
    00124       return -1;
    00125     }
    00126     else
    00127     {
    00128       //printf("ftp_recv_msg: cnt=%d\r\n",cnt);
    00129       if (cnt>0)
    00130       {
    00131         idx = idx + cnt;
    00132         buffer[idx] = 0;
    00133       }
    00134     }
    00135   } while( GetWaitingBytes(sd,error)>0 );
    00136
    00137   return idx;
    00138
    00139 } // ftp_recv_msg()
    00140
    00141 /****************************************************************************/
    00142
    00143 int ftp_command(int sd, char *cmd, char *response, int resp_len, int *error)
    00144 {
    00145   int stat;
    00146
    00147   if (strlen(cmd)>0)
    00148   {
    00149     stat = ftp_send(sd,cmd,strlen(cmd));
    00150     if (stat<0)
    00151       return -1;
    00152   }
    00153   stat = ftp_recv_msg(sd,response,resp_len,error);
    00154   strip_crlf(response);
    00155   if (stat<0)
    00156     return -2;
    00157   stat = atoi(ftp_buf);
    00158   return stat;
    00159
    00160 } // ftp_command()
    00161
    00162 /*****************************************************************************
    00163 *
    00164 * open a tcp connection
    00165 *
    00166 * DestIPStr: destionation IP address format xxx.xxx.xxx.xxx
    00167 * ClientPort: local port (0=random port)
    00168 * HostPort: remote port
    00169 * error: TCP/IP error
    00170 *
    00171 * return: socket descriptor (-1 = error)
    00172 */
    00173
    00174 int ftp_connect(char *DestIPStr, unsigned int ClientPort, unsigned int HostPort, int *error)
    00175 {
    00176   struct sockaddr_in addr;
    00177   unsigned long DestIPAddr;
    00178   int sd; // socket descriptor
    00179
    00180 #ifdef FTP_DEBUG
    00181   printf("ftp_connect %u -> %s:%u\r\n",ClientPort,DestIPStr,HostPort);
    00182 #endif
    00183
    00184   // open socket
    00185   sd = opensocket(SOCK_STREAM,error);
    00186   if (sd==-1 || *error!=0)
    00187   {
    00188 #ifdef FTP_DEBUG
    00189     printf("ftp_connect: error: open socket failed, error=%d\r\n",*error);
    00190 #endif
    00191     return -1;
    00192   }
    00193
    00194   addr.sin_family = PF_INET;
    00195   addr.sin_port = htons(ClientPort);  // convert byte order
    00196   addr.sin_addr.s_addr =  0;
    00197   if (ClientPort!=0)
    00198   { // force client port
    00199     bind(sd, (struct sockaddr*)&addr,error);
    00200     if (*error!=0)
    00201     {
    00202 #ifdef FTP_DEBUG
    00203       printf("ftp_connect: error: socket bind failed, error=%d\r\n",*error);
    00204 #endif
    00205       return -1;
    00206     }
    00207   }
    00208   addr.sin_port = htons(HostPort);  // convert byte order
    00209
    00210   // convert server IP address string to binary
    00211   *error = inet_addr(DestIPStr,&DestIPAddr);
    00212   if (*error!=0)
    00213   {
    00214 #ifdef FTP_DEBUG
    00215     printf("ftp_connect: error: ip address convert failed ('%s'), error=%d)\r\n",DestIPStr,*error);
    00216 #endif
    00217     return -1;
    00218   }
    00219   addr.sin_addr.s_addr = DestIPAddr;
    00220
    00221   // establish a connection to the FTP server
    00222   connect(sd,(struct sockaddr*)&addr,error);
    00223   if (*error!=0)
    00224   {
    00225 #ifdef FTP_DEBUG
    00226     printf("ftp_connect: error: TCP connect failed, error=%d\r\n",*error);
    00227 #endif
    00228     return -1;
    00229   };
    00230
    00231 #ifdef FTP_DEBUG
    00232   printf("ftp_connect: connection established\r\n");
    00233 #endif
    00234   *error = 0;
    00235   return sd;
    00236
    00237 } // ftp_connect()
    00238
    00239 /*****************************************************************************
    00240 *
    00241 * open ftp connection
    00242 * creates ftp descriptor entry and returns pointer to it
    00243 *
    00244 * DestIPStr: destination ip address, format: xxx.xxxx.xxx.xxx
    00245 * ClientCtrlPort: local port for control connection (0=use random port)
    00246 * ClientDataPort: local port for data connection (0=use random port)
    00247 * HostCtrlPort: server port for control connection (standard ftp port = 21)
    00248 * stat: return code from ftp server
    00249 * error: TCP/IP error
    00250 *
    00251 * return: pointer to ftp connection descriptor (NULL = error)
    00252 */
    00253
    00254 ftp_desc *ftp_open(char *DestIPStr, unsigned int ClientCtrlPort,
    00255         unsigned int ClientDataPort, unsigned int HostCtrlPort,
    00256         int *stat, int *error)
    00257 {
    00258   unsigned long DestIPAddr;
    00259   int sd;
    00260   ftp_desc *fd; // pointer to ftp connection descriptor
    00261
    00262   *stat = 0;
    00263 #ifdef FTP_DEBUG
    00264   printf("ftp_open %u,%u -> %s:%u\r\n",
    00265     ClientCtrlPort,ClientDataPort,DestIPStr,HostCtrlPort);
    00266 #endif
    00267
    00268   // set ftp connection descriptor
    00269   fd = malloc(sizeof(ftp_desc));
    00270   if (fd==NULL)
    00271   {
    00272 #ifdef FTP_DEBUG
    00273     printf("ftp_open: error: malloc failed\r\n");
    00274 #endif
    00275     return NULL;
    00276   }
    00277
    00278   sd = ftp_connect(DestIPStr,ClientCtrlPort,HostCtrlPort,error);
    00279   if (sd<=0)
    00280   {
    00281 #ifdef FTP_DEBUG
    00282     printf("ftp_open: error: no ftp connection, error=%d\r\n",sd,*error);
    00283 #endif
    00284     return 0;
    00285   }
    00286 #ifdef FTP_DEBUG
    00287   printf("ftp_open: connected\r\n");
    00288 #endif
    00289
    00290   // Server is connected - wait a bit to receive the first sign on message string from the email server
    00291   api_sleep(300);
    00292
    00293   // receive connect message from ftp server
    00294   *stat = ftp_command(sd,"",ftp_buf,FTP_BUF_LEN,error);
    00295 #ifdef FTP_DEBUG
    00296   printf("ftp_open: %s\r\n",ftp_buf);
    00297 #endif
    00298   if (*stat!=FTP_MSG_SERVER_READY)
    00299   {
    00300     closesocket(sd,error);
    00301     return 0;
    00302   }
    00303
    00304   // set ftp connection descriptor
    00305   inet_addr(DestIPStr,&DestIPAddr);
    00306   fd->sd_ctrl = sd; // socket descriptor for control connection
    00307   fd->sd_data = 0; // no data connection
    00308   fd->local_ctrl_port = ClientCtrlPort;
    00309   fd->local_data_port = ClientDataPort;
    00310   fd->host_ctrl_port = HostCtrlPort;
    00311   fd->host_data_port = 0; // no data port
    00312   fd->HostIPAddr = DestIPAddr;
    00313   strcpy(fd->HostIPStr,DestIPStr);
    00314 #ifdef FTP_DEBUG
    00315   printf("ftp_open: ftp connection established\r\n");
    00316 #endif
    00317   return fd;
    00318
    00319 } // ftp_open()
    00320
    00321 /*****************************************************************************
    00322 *
    00323 * close ftp connection
    00324 *
    00325 * ftp_desc: pointer to ftp connection descriptor
    00326 * error: tcp/ip error
    00327 *
    00328 * return: 1=ok, 0=error
    00329 */
    00330
    00331 int ftp_close(ftp_desc *fd, int *error)
    00332 {
    00333   int sd;
    00334
    00335   sd = fd->sd_ctrl; // get socket descriptor from ftp connection descriptor
    00336   closesocket(sd,error);
    00337
    00338   // remove ftp connection descriptor
    00339   free(fd);
    00340
    00341 #ifdef FTP_DEBUG
    00342   printf("ftp_close: connection closed\r\n",fd);
    00343 #endif
    00344   return 1;
    00345
    00346 } // ftp_close()
    00347
    00348 /*****************************************************************************
    00349 *
    00350 * ftp login (USER, PASS)
    00351 *
    00352 * ftp_desc: pointer to ftp connection descriptor
    00353 * user: username
    00354 * pass: password
    00355 * stat: return code of ftp server
    00356 * error: error code from tcp/ip
    00357 *
    00358 * return: 1=ok, 0=error
    00359 */
    00360
    00361 int ftp_login(ftp_desc *fd, char *user, char *pass, int *stat, int *error)
    00362 {
    00363   int sd;
    00364
    00365 #ifdef FTP_DEBUG
    00366   //printf("ftp_login: ftp descriptor=%d",fd);
    00367 #endif
    00368
    00369   sd = fd->sd_ctrl; // get socket descriptor from ftp connection descriptor
    00370
    00371   strcpy(ftp_buf,"USER ");
    00372   strncat(ftp_buf,user,50);
    00373   ftp_buf[5+50] = 0;
    00374   strcat(ftp_buf,"\r\n");
    00375 #ifdef FTP_DEBUG
    00376   printf("ftp_login: %s",ftp_buf);
    00377 #endif
    00378   *stat = ftp_command(sd,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00379 #ifdef FTP_DEBUG
    00380   printf("ftp_login: %s\r\n",ftp_buf);
    00381 #endif
    00382   if (*stat!=FTP_MSG_USERNAME_OK && *stat!=FTP_MSG_USER_LOGGED_IN)
    00383     return 0; // error
    00384
    00385   strcpy(ftp_buf,"PASS ");
    00386   strncat(ftp_buf,pass,50);
    00387   ftp_buf[5+50] = 0;
    00388   strcat(ftp_buf,"\r\n");
    00389 #ifdef FTP_DEBUG
    00390   printf("ftp_login: %s",ftp_buf);
    00391 #endif
    00392   *stat = ftp_command(sd,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00393 #ifdef FTP_DEBUG
    00394   printf("ftp_login: %s\r\n",ftp_buf);
    00395 #endif
    00396   if (*stat==FTP_MSG_USER_LOGGED_IN)
    00397     return 1; // ok
    00398   else
    00399     return 0; // error
    00400
    00401 } // ftp_login()
    00402
    00403 /*****************************************************************************
    00404 *
    00405 * ftp logout (QUIT)
    00406 *
    00407 * ftp_desc: pointer to ftp connection descriptor
    00408 * stat: return code of ftp server
    00409 * error: error code from tcp/ip
    00410 *
    00411 * return: 1=ok, 0=error
    00412 */
    00413
    00414 int ftp_logout(ftp_desc *fd, int *stat, int *error)
    00415 {
    00416   int sd;
    00417
    00418   sd = fd->sd_ctrl;
    00419
    00420 #ifdef FTP_DEBUG
    00421   printf("ftp_logout: QUIT\r\n",fd);
    00422 #endif
    00423   *stat = ftp_command(sd,"QUIT\r\n",ftp_buf,FTP_BUF_LEN,error);
    00424 #ifdef FTP_DEBUG
    00425   printf("ftp_logout: %s\r\n",ftp_buf);
    00426 #endif
    00427   if (*stat!=FTP_MSG_USERNAME_OK)
    00428     return 1;
    00429   else
    00430     return 0;
    00431
    00432 } // ftp_logout()
    00433
    00434 /*****************************************************************************
    00435 *
    00436 * get current directory (PWD)
    00437 *
    00438 * ftp_desc: pointer to ftp connection descriptor
    00439 * dirstr: directory string
    00440 * dirlen: max. length for dirstr
    00441 * stat: return code of ftp server
    00442 * error: error code from tcp/ip
    00443 *
    00444 * return: 1=ok, 0=error
    00445 *
    00446 * reports '/...' or  '\...' depending on the ftp server software and
    00447 * server operating system
    00448 */
    00449
    00450 int ftp_pwd(ftp_desc *fd, char *dirstr, int dirlen, int *stat, int *error)
    00451 {
    00452   char *p1,*p2;
    00453   int sd,n;
    00454
    00455   sd = fd->sd_ctrl;
    00456
    00457 #ifdef FTP_DEBUG
    00458   printf("ftp_pwd: PWD\r\n",fd);
    00459 #endif
    00460   *stat = ftp_command(sd,"PWD\r\n",ftp_buf,FTP_BUF_LEN,error);
    00461 #ifdef FTP_DEBUG
    00462   printf("ftp_pwd: %s\r\n",ftp_buf);
    00463 #endif
    00464   if (*stat!=FTP_MSG_CURRENT_DIRECTORY)
    00465     return 0;
    00466   p1 = strchr(ftp_buf,'"');
    00467   p2 = strchr(p1+1,'"');
    00468   n = (int) (p2-p1-1);
    00469   if (n>dirlen)
    00470     n = dirlen;
    00471   strncpy(dirstr,p1+1,n);
    00472   dirstr[n] = 0;
    00473   return 1;
    00474
    00475 } // ftp_pwd()
    00476
    00477 /*****************************************************************************
    00478 *
    00479 * change current directory (CWD)
    00480 *
    00481 * fd: pointer to ftp connection descriptor
    00482 * cwdstr: directory string
    00483 * stat: return code of ftp server
    00484 * error: error code from tcp/ip
    00485 *
    00486 * return: 1=ok, 0=error
    00487 *
    00488 * be sure to use  '/' or  '\' depending on the ftp server software and
    00489 * server operating system
    00490 */
    00491
    00492 int ftp_cwd(ftp_desc *fd, char *cwdstr, int *stat, int *error)
    00493 {
    00494   int sd;
    00495
    00496   sd = fd->sd_ctrl;
    00497
    00498   strcpy(ftp_buf,"CWD ");
    00499   strncat(ftp_buf,cwdstr,128);
    00500   ftp_buf[4+128] = 0;
    00501   strcat(ftp_buf,"\r\n");
    00502 #ifdef FTP_DEBUG
    00503   printf("ftp_cwd: %s",ftp_buf);
    00504 #endif
    00505   *stat = ftp_command(sd,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00506 #ifdef FTP_DEBUG
    00507   printf("ftp_pwd: %s\r\n",ftp_buf);
    00508 #endif
    00509   if (*stat==FTP_MSG_REQ_FILE_ACTION_OK)
    00510     return 1; // ok
    00511   else
    00512     return 0; // error
    00513
    00514 } // ftp_cwd()
    00515
    00516 /*****************************************************************************
    00517 *
    00518 * make directory (MKD)
    00519 *
    00520 * fd: pointer to ftp connection descriptor
    00521 * mkdstr: directory string
    00522 * stat: return code of ftp server
    00523 * error: error code from tcp/ip
    00524 *
    00525 * return: 1=ok, 0=error
    00526 *
    00527 * be sure to use  '/' or  '\' depending on the ftp server software and
    00528 * server operating system
    00529 */
    00530
    00531 int ftp_mkd(ftp_desc *fd, char *mkdstr, int *stat, int *error)
    00532 {
    00533   int sd;
    00534
    00535   sd = fd->sd_ctrl;
    00536
    00537   strcpy(ftp_buf,"MKD ");
    00538   strncat(ftp_buf,mkdstr,128);
    00539   ftp_buf[4+128] = 0;
    00540   strcat(ftp_buf,"\r\n");
    00541 #ifdef FTP_DEBUG
    00542   printf("ftp_mkd: %s",ftp_buf);
    00543 #endif
    00544   *stat = ftp_command(sd,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00545 #ifdef FTP_DEBUG
    00546   printf("ftp_mkd: %s\r\n",ftp_buf);
    00547 #endif
    00548   if (*stat==FTP_MSG_DIRECTORY_CREATED)
    00549     return 1; // ok
    00550   else
    00551     return 0; // error
    00552
    00553 } // ftp_mkd()
    00554
    00555 /*****************************************************************************
    00556 *
    00557 * remove directory (RMD)
    00558 *
    00559 * fd: pointer to ftp connection descriptor
    00560 * rmdstr: directory string
    00561 * stat: return code of ftp server
    00562 * error: error code from tcp/ip
    00563 *
    00564 * return: 1=ok, 0=error
    00565 *
    00566 * be sure to use  '/' or  '\' depending on the ftp server software and
    00567 * server operating system
    00568 */
    00569
    00570 int ftp_rmd(ftp_desc *fd, char *rmdstr, int *stat, int *error)
    00571 {
    00572   int sd;
    00573
    00574   sd = fd->sd_ctrl;
    00575
    00576   strcpy(ftp_buf,"RMD ");
    00577   strncat(ftp_buf,rmdstr,128);
    00578   ftp_buf[4+128] = 0;
    00579   strcat(ftp_buf,"\r\n");
    00580 #ifdef FTP_DEBUG
    00581   printf("ftp_rmd: %s",ftp_buf);
    00582 #endif
    00583   *stat = ftp_command(sd,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00584 #ifdef FTP_DEBUG
    00585   printf("ftp_rmd: %s\r\n",ftp_buf);
    00586 #endif
    00587   if (*stat==FTP_MSG_REQ_FILE_ACTION_OK)
    00588     return 1; // ok
    00589   else
    00590     return 0; // error
    00591
    00592 } // ftp_rmd()
    00593
    00594 /*****************************************************************************
    00595 *
    00596 * delete file (DELE)
    00597 *
    00598 * fd: pointer to ftp connection descriptor
    00599 * rmdstr: directory string
    00600 * stat: return code of ftp server
    00601 * error: error code from tcp/ip
    00602 *
    00603 * return: 1=ok, 0=error
    00604 */
    00605
    00606 int ftp_dele(ftp_desc *fd, char *filename, int *stat, int *error)
    00607 {
    00608   int sd;
    00609
    00610   sd = fd->sd_ctrl;
    00611
    00612   strcpy(ftp_buf,"DELE ");
    00613   strncat(ftp_buf,filename,128);
    00614   ftp_buf[4+128] = 0;
    00615   strcat(ftp_buf,"\r\n");
    00616 #ifdef FTP_DEBUG
    00617   printf("ftp_delete: %s",ftp_buf);
    00618 #endif
    00619   *stat = ftp_command(sd,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00620 #ifdef FTP_DEBUG
    00621   printf("ftp_delete: %s\r\n",ftp_buf);
    00622 #endif
    00623   if (*stat==FTP_MSG_REQ_FILE_ACTION_OK)
    00624     return 1; // ok
    00625   else
    00626     return 0; // error
    00627
    00628 } // ftp_dele()
    00629
    00630 /*****************************************************************************
    00631 *
    00632 * Send a file to ftp server in ascii or binary mode (passiv)
    00633 *
    00634 * fd: pointer to ftp connection discriptor
    00635 * LocalName: local filename
    00636 * RemoteName: remote filename
    00637 * mode: 0 = ascii, 1=binary
    00638 * stat: return code of ftp server
    00639 * error: error code from tcp/ip
    00640 *
    00641 * return: 1=ok, 0=error
    00642 *
    00643 * Please consider that the FTP protocol often causes trouble with local
    00644 * firewalls because it uses a seperate data connection for file transfer.
    00645 *
    00646 * This procedure uses passiv mode to open the data connection. This means
    00647 * that the server determines the host port for the data connection.
    00648 * This can possibly cause trouble with a local firewall, because you can not
    00649 * ask your network administrator to enable a fixed port for your ftp
    00650 * communication.
    00651 * To handle this we will implement active mode in one of the next versions of
    00652 * this example. In active mode the client can tell the server, which port to
    00653 * use for the data connection.
    00654 *
    00655 * Another work-around is to ask your network administrator to enable outgoing
    00656 * ftp connections on all ports.
    00657 */
    00658
    00659 int ftp_sendfile(ftp_desc *fd, char *LocalName, char *RemoteName, int mode,
    00660           int *stat, int *error)
    00661 {
    00662   int sd_ctrl,sd_data,i;
    00663   char *p;
    00664   unsigned int i1,i2,host_data_port;
    00665   long trans;
    00666   FILE *fp;
    00667
    00668 #ifdef FTP_DEBUG
    00669   printf("ftp_sendfile: %s -> %s, fd=%d, mode=%d\r\n",LocalName,RemoteName,fd,mode);
    00670 #endif
    00671   sd_ctrl = fd->sd_ctrl;
    00672
    00673   // set transfer mode ascii/binary
    00674   if (mode==FTP_ASCII)
    00675     strcpy(ftp_buf,"TYPE A\r\n");
    00676   else
    00677     strcpy(ftp_buf,"TYPE I\r\n");
    00678 #ifdef FTP_DEBUG
    00679   printf("ftp_sendfile: %s",ftp_buf);
    00680 #endif
    00681   *stat = ftp_command(sd_ctrl,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00682 #ifdef FTP_DEBUG
    00683   printf("ftp_sendfile: %s\r\n",ftp_buf);
    00684 #endif
    00685   if (*stat!=FTP_MSG_TYPE_COMMAND_OK)
    00686     return 0;
    00687
    00688   // set passiv mode
    00689 #ifdef FTP_DEBUG
    00690   printf("ftp_sendfile: PASV\r\n");
    00691 #endif
    00692   *stat = ftp_command(sd_ctrl,"PASV\r\n",ftp_buf,FTP_BUF_LEN,error);
    00693 #ifdef FTP_DEBUG
    00694   printf("ftp_sendfile: %s\r\n",ftp_buf);
    00695 #endif
    00696   if (*stat!=FTP_MSG_ENTERING_PASSIV_MODE)
    00697     return 0;
    00698
    00699   // retrieve portnumber for data connection from response string
    00700   // format: "227 Entering Passiv Mode (ip1,ip2,ip3,ip4,highbyte,lowbyte)."
    00701   // ip1..ip4: ftp server ip-address
    00702   // highbyte,lowbyte: portnumber for data connection
    00703   p = strchr(ftp_buf,'(') + 1;
    00704   if (p==NULL) return 0;
    00705   for (i=0; i<4; i++)
    00706   {
    00707     p = strchr(p,',') + 1;
    00708     if (p==NULL) return 0;
    00709   }
    00710   i1 = atoi(p);
    00711   p = strchr(p,',') + 1;
    00712   if (p==NULL) return 0;
    00713   i2 = atoi(p);
    00714   p = strchr(p,')');
    00715   if (p==NULL) return 0;
    00716   host_data_port = i1*256+i2;
    00717
    00718 #ifdef FTP_DEBUG
    00719   printf("ftp_sendfile: Open data connection: %u -> %s:%u\r\n",
    00720     fd->local_data_port,fd->HostIPStr,host_data_port);
    00721 #endif
    00722   // open data connection to port host_data_port
    00723   sd_data = ftp_connect(fd->HostIPStr,fd->local_data_port,host_data_port,error);
    00724   if (sd_data==-1)
    00725     return 0;
    00726   fd->sd_data = sd_data;
    00727   fd->host_data_port = host_data_port;
    00728 #ifdef FTP_DEBUG
    00729   printf("ftp_sendfile: data connection established\r\n");
    00730 #endif
    00731
    00732   // send STOR command
    00733   strcpy(ftp_buf,"STOR ");
    00734   strncat(ftp_buf,RemoteName,128);
    00735   ftp_buf[5+128] = 0;
    00736   strcat(ftp_buf,"\r\n");
    00737 #ifdef FTP_DEBUG
    00738   printf("ftp_sendfile: %s",ftp_buf);
    00739 #endif
    00740   *stat = ftp_command(sd_ctrl,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00741 #ifdef FTP_DEBUG
    00742   printf("ftp_sendfile: %s\r\n",ftp_buf);
    00743 #endif
    00744   if (*stat!=FTP_MSG_FILE_STATUS_OK &&
    00745     *stat!=FTP_MSG_DATA_CONNECTION_ALREADY_OPEN)
    00746   {
    00747 #ifdef FTP_DEBUG
    00748     printf("ftp_sendfile: error STOR %s (%d)\r\n",RemoteName,*stat);
    00749 #endif
    00750     error = 0;  // error !
    00751     goto close_data_conn;
    00752   }
    00753
    00754   // send file
    00755   fp = fopen(LocalName,"rb");
    00756   if (fp==NULL)
    00757   {
    00758     printf("ftp_sendfile: error opening %s\r\n",LocalName);
    00759     error = 0;  // error !
    00760     goto close_data_conn;
    00761   }
    00762   trans = 0;
    00763   while (!feof(fp))
    00764   {
    00765     i = fread(ftp_buf,1,FTP_BUF_LEN,fp);
    00766     if (i==0)
    00767       break;
    00768     i = ftp_send(sd_data,ftp_buf,i);
    00769     trans = trans + i;
    00770 #ifdef FTP_DEBUG
    00771     printf("ftp_sendfile: %6ld\r",trans);
    00772 #endif
    00773   }
    00774 #ifdef FTP_DEBUG
    00775   printf("\r\n");
    00776 #endif
    00777   fclose(fp);
    00778
    00779
    00780 close_data_conn:
    00781   closesocket(sd_data,error);
    00782 #ifdef FTP_DEBUG
    00783   printf("ftp_sendfile: closesocket error=%d\r\n",*error);
    00784 #endif
    00785   fd->sd_data = 0;
    00786   fd->host_data_port = 0;
    00787
    00788   // receive status message from ftp server
    00789   *stat = ftp_command(sd_ctrl,"",ftp_buf,FTP_BUF_LEN,error);
    00790 #ifdef FTP_DEBUG
    00791   printf("ftp_sendfile: %s\r\n",ftp_buf);
    00792 #endif
    00793   if (*stat!=FTP_MSG_TRANSFER_COMPLETED)
    00794     return 0; // error
    00795   else
    00796     return 1; // ok
    00797
    00798 } // ftp_sendfile()
    00799
    00800 /*****************************************************************************
    00801 *
    00802 * receive a file from ftp server in ascii or binary mode (passiv)
    00803 *
    00804 * fd: pointer to ftp connection discriptor
    00805 * RemoteName: remote filename
    00806 * LocalName: local filename
    00807 * mode: 0 = ascii, 1=binary
    00808 * stat: return code of ftp server
    00809 * error: error code from tcp/ip
    00810 *
    00811 * return: 1=ok, 0=error
    00812 *
    00813 * Please consider that the FTP protocol often causes trouble with local
    00814 * firewalls because it uses a seperate data connection for file transfer.
    00815 *
    00816 * This procedure uses passiv mode to open the data connection. This means
    00817 * that the server determines the host port for the data connection.
    00818 * This can possibly cause trouble with a local firewall, because you can not
    00819 * ask your network administrator to enable a fixed port for your ftp
    00820 * communication.
    00821 * To handle this we will implement active mode in one of the next versions of
    00822 * this example. In active mode the client can tell the server, which port to
    00823 * use for the data connection.
    00824 *
    00825 * Another work-around is to ask your network administrator to enable outgoing
    00826 * ftp connections on all ports.
    00827 */
    00828
    00829 int ftp_recvfile(ftp_desc *fd, char *RemoteName, char *LocalName, int mode,
    00830           int *stat, int *error)
    00831 {
    00832   int sd_ctrl,sd_data,i;
    00833   char *p;
    00834   unsigned int i1,i2,host_data_port;
    00835   long trans;
    00836   FILE *fp;
    00837
    00838 #ifdef FTP_DEBUG
    00839   printf("ftp_recvfile: %s -> %s, fd=%d, mode=%d\r\n",RemoteName,LocalName,fd,mode);
    00840 #endif
    00841   sd_ctrl = fd->sd_ctrl;
    00842
    00843   // set transfer mode ascii/binary
    00844   if (mode==FTP_ASCII)
    00845     strcpy(ftp_buf,"TYPE A\r\n");
    00846   else
    00847     strcpy(ftp_buf,"TYPE I\r\n");
    00848 #ifdef FTP_DEBUG
    00849   printf("ftp_recvfile: %s",ftp_buf);
    00850 #endif
    00851   *stat = ftp_command(sd_ctrl,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00852 #ifdef FTP_DEBUG
    00853   printf("ftp_recvfile: %s\r\n",ftp_buf);
    00854 #endif
    00855   if (*stat!=FTP_MSG_TYPE_COMMAND_OK)
    00856     return 0;
    00857
    00858   // set passiv mode
    00859 #ifdef FTP_DEBUG
    00860   printf("ftp_recvfile: PASV\r\n");
    00861 #endif
    00862   *stat = ftp_command(sd_ctrl,"PASV\r\n",ftp_buf,FTP_BUF_LEN,error);
    00863 #ifdef FTP_DEBUG
    00864   printf("ftp_recvfile: %s\r\n",ftp_buf);
    00865 #endif
    00866   if (*stat!=FTP_MSG_ENTERING_PASSIV_MODE)
    00867     return 0;
    00868
    00869   // retrieve portnumber for data connection from response string
    00870   // format: "227 Entering Passiv Mode (ip1,ip2,ip3,ip4,highbyte,lowbyte)."
    00871   // ip1..ip4: ftp server ip-address
    00872   // highbyte,lowbyte: portnumber for data connection
    00873   p = strchr(ftp_buf,'(') + 1;
    00874   if (p==NULL) return 0;
    00875   for (i=0; i<4; i++)
    00876   {
    00877     p = strchr(p,',') + 1;
    00878     if (p==NULL) return 0;
    00879   }
    00880   i1 = atoi(p);
    00881   p = strchr(p,',') + 1;
    00882   if (p==NULL) return 0;
    00883   i2 = atoi(p);
    00884   p = strchr(p,')');
    00885   if (p==NULL) return 0;
    00886   host_data_port = i1*256+i2;
    00887
    00888 #ifdef FTP_DEBUG
    00889   printf("ftp_recvfile: Open data connection: %u -> %s:%u\r\n",
    00890     fd->local_data_port,fd->HostIPStr,host_data_port);
    00891 #endif
    00892   // open data connection to port host_data_port
    00893   sd_data = ftp_connect(fd->HostIPStr,fd->local_data_port,host_data_port,error);
    00894   fd->sd_data = sd_data;
    00895   fd->host_data_port = host_data_port;
    00896 #ifdef FTP_DEBUG
    00897   printf("ftp_recvfile: data connection established\r\n");
    00898 #endif
    00899
    00900   // send RETR command
    00901   strcpy(ftp_buf,"RETR ");
    00902   strncat(ftp_buf,RemoteName,128);
    00903   ftp_buf[5+128] = 0;
    00904   strcat(ftp_buf,"\r\n");
    00905 #ifdef FTP_DEBUG
    00906   printf("ftp_recvfile: %s",ftp_buf);
    00907 #endif
    00908   *stat = ftp_command(sd_ctrl,ftp_buf,ftp_buf,FTP_BUF_LEN,error);
    00909 #ifdef FTP_DEBUG
    00910   printf("ftp_recvfile: %s\r\n",ftp_buf);
    00911 #endif
    00912   if (*stat!=FTP_MSG_FILE_STATUS_OK &&
    00913     *stat!=FTP_MSG_DATA_CONNECTION_ALREADY_OPEN)
    00914   {
    00915 #ifdef FTP_DEBUG
    00916     printf("ftp_recvfile: error RETR %s (%d)\r\n",RemoteName,*stat);
    00917 #endif
    00918     goto close_data_conn;
    00919   }
    00920
    00921   // receive file
    00922   fp = fopen(LocalName,"wb");
    00923   if (fp==NULL)
    00924   {
    00925 #ifdef FTP_DEBUG
    00926     printf("ftp_recvfile: error opening %s\r\n",LocalName);
    00927 #endif
    00928     error = 0;  // error !
    00929     goto close_data_conn;
    00930   }
    00931   trans = 0;
    00932   do
    00933   {
    00934     i = ftp_recv(sd_data,ftp_buf,512,error);
    00935     if (i==0)
    00936       break;
    00937     if (fwrite(ftp_buf,1,i,fp)!=i)
    00938     {
    00939 #ifdef FTP_DEBUG
    00940       printf("ftp_recvfile: error writing file to local drive\r\n");
    00941 #endif
    00942       break;
    00943     }
    00944     trans = trans + i;
    00945 #ifdef FTP_DEBUG
    00946     printf("ftp_recvfile: %6ld\r",trans);
    00947 #endif
    00948     api_sleep(50);
    00949   } while (i>0);
    00950
    00951 #ifdef FTP_DEBUG
    00952   printf("\r\n");
    00953 #endif
    00954   fclose(fp);
    00955
    00956
    00957 close_data_conn:
    00958   closesocket(sd_data,error);
    00959 #ifdef FTP_DEBUG
    00960   printf("ftp_recvfile: closesocket error=%d\r\n",error);
    00961 #endif
    00962   fd->sd_data = 0;
    00963   fd->host_data_port = 0;
    00964   *stat = ftp_command(sd_ctrl,"",ftp_buf,FTP_BUF_LEN,error);
    00965 #ifdef FTP_DEBUG
    00966   printf("ftp_recvfile: %s\r\n",ftp_buf);
    00967 #endif
    00968   if (*stat!=FTP_MSG_TRANSFER_COMPLETED)
    00969     return 0; // error
    00970   else
    00971     return 1; // ok
    00972
    00973 } // ftp_recvfile()
    00974
    00975 /*****************************************************************************
    00976 * end of file
    00977 *****************************************************************************/
    00978