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 

Generated on Sun Aug 4 21:47:27 2002 for k/os mp3v2 by doxygen1.2.16