ftplib.cpp

  1. /*************************************************************************** 
  2.                           ftplib.cpp  –  description 
  3.                              ——————- 
  4.     begin                : lin lu 27 2005 
  5.     copyright            : (C) 2003 by mkulke 
  6.     email                : thinking_nlp@163.com 
  7.  ***************************************************************************/
  8. #include “ftplib.h” 
  9. #include <unistd.h> 
  10. #include <stdio.h> 
  11. #include <stdlib.h> 
  12. #include <string.h> 
  13. #include <errno.h> 
  14. #include <ctype.h> 
  15. #include <sys/types.h> 
  16. #include <sys/socket.h> 
  17. #include <netinet/in.h> 
  18. #include <netdb.h> 
  19. #include <arpa/inet.h> 
  20. #include <string> 
  21. using namespace std;
  22. /* io function names */
  23. #define net_read read 
  24. #define net_write write 
  25. #define net_close close 
  26. /* socket values */
  27. #define SETSOCKOPT_OPTVAL_TYPE (void *) 
  28. #define FTPLIB_BUFSIZ 1024 
  29. #define ACCEPT_TIMEOUT 30 
  30. /* io types */
  31. #define FTPLIB_CONTROL 0 
  32. #define FTPLIB_READ 1 
  33. #define FTPLIB_WRITE 2 
  34. /* 
  35.  * Constructor 
  36.  */
  37. ftplib::ftplib()
  38. {
  39.     SSL_library_init();
  40.     mp_netbuf = static_cast<netbuf *>(calloc(1,sizeof(netbuf)));
  41.     if (mp_netbuf == NULL) perror(“calloc”);
  42.     mp_netbuf->buf = static_cast<char *>(malloc(FTPLIB_BUFSIZ));
  43.     if (mp_netbuf->buf == NULL)
  44.     {
  45.         perror(“calloc”);
  46.         free(mp_netbuf);
  47.     }
  48.     mp_netbuf->ctx = SSL_CTX_new(SSLv23_method());
  49.     SSL_CTX_set_verify(mp_netbuf->ctx, SSL_VERIFY_NONE, NULL);
  50.     mp_netbuf->ssl = SSL_new(mp_netbuf->ctx);
  51.     ClearNetbuf();
  52. }
  53. /* 
  54.  * Destructor 
  55.  */
  56. ftplib::~ftplib()
  57. {
  58.     SSL_free(mp_netbuf->ssl);
  59.     SSL_CTX_free(mp_netbuf->ctx);
  60.    free(mp_netbuf->buf);
  61.    free(mp_netbuf);
  62. }
  63. /* 
  64.  * socket_wait – wait for socket to receive or flush data 
  65.  * 
  66.  * return 1 if no user callback, otherwise, return value returned by 
  67.  * user callback 
  68.  */
  69. int ftplib::socket_wait(netbuf *ctl)
  70. {
  71.     fd_set fd,*rfd = NULL,*wfd = NULL;
  72.     struct timeval tv;
  73.     int rv = 0;
  74.     if (ctl->idlecb == NULL) return 1;
  75.     /*if ((ctl->dir == FTPLIB_CONTROL) 
  76.         || (ctl->idlecb == NULL) 
  77.         || ((ctl->idletime.tv_sec == 0) 
  78.         && //(ctl->idletime.tv_usec 0)) 
  79.     return 1;*/
  80.     if (ctl->dir == FTPLIB_WRITE) wfd = &fd;
  81.     else rfd = &fd;
  82.     FD_ZERO(&fd);
  83.     do
  84.     {
  85.         FD_SET(ctl->handle,&fd);
  86.         tv = ctl->idletime;
  87.         rv = select(ctl->handle+1, rfd, wfd, NULL, &tv);
  88.         if (rv == -1)
  89.         {
  90.             rv = 0;
  91.             strncpy(ctl->ctrl->response, strerror(errno), sizeof(ctl->ctrl->response));
  92.             break;
  93.         }
  94.         else if (rv > 0)
  95.         {
  96.             rv = 1;
  97.             break;
  98.         }
  99.     } while ((rv = ctl->idlecb(ctl->cbarg)));
  100.     return rv;
  101. }
  102. /* 
  103.  * read a line of text 
  104.  * 
  105.  * return -1 on error or bytecount 
  106.  */
  107. int ftplib::readline(char *buf,int max,netbuf *ctl)
  108. {
  109.     int x,retval = 0;
  110.     char *end,*bp=buf;
  111.     int eof = 0;
  112.     if ((ctl->dir != FTPLIB_CONTROL) && (ctl->dir != FTPLIB_READ))
  113.     return -1;
  114.     if (max == 0)
  115.     return 0;
  116.     do
  117.     {
  118.         if (ctl->cavail > 0)
  119.         {
  120.             x = (max >= ctl->cavail) ? ctl->cavail : max-1;
  121.             end = static_cast<char*>(memccpy(bp,ctl->cget,‘\n’,x));
  122.             if (end != NULL)
  123.             x = end – bp;
  124.             retval += x;
  125.             bp += x;
  126.             *bp = ‘\0’;
  127.             max -= x;
  128.             ctl->cget += x;
  129.             ctl->cavail -= x;
  130.             if (end != NULL)
  131.             {
  132.                 bp -= 2;
  133.                 if (strcmp(bp,“\r\n”) == 0)
  134.                 {
  135.                     *bp++ = ‘\n’;
  136.                     *bp++ = ‘\0’;
  137.                     –retval;
  138.                 }
  139.                 break;
  140.             }
  141.         }
  142.         if (max == 1)
  143.         {
  144.             *buf = ‘\0’;
  145.             break;
  146.         }
  147.         if (ctl->cput == ctl->cget)
  148.         {
  149.             ctl->cput = ctl->cget = ctl->buf;
  150.             ctl->cavail = 0;
  151.             ctl->cleft = FTPLIB_BUFSIZ;
  152.         }
  153.         if (eof)
  154.         {
  155.             if (retval == 0)
  156.             retval = -1;
  157.             break;
  158.         }
  159.         if (!socket_wait(ctl)) return retval;
  160.         if (ctl->tlsdata) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft);
  161.         else
  162.         {
  163.             if (ctl->tlsctrl) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft);
  164.             else x = net_read(ctl->handle,ctl->cput,ctl->cleft);
  165.         }
  166.         if ( x == -1)
  167.         {
  168.             perror(“read”);
  169.             retval = -1;
  170.             break;
  171.         }
  172.         // LOGGING FUNCTIONALITY!!! 
  173.         if ((ctl->dir == FTPLIB_CONTROL) && (mp_netbuf->logcb != NULL))
  174.         {
  175.             *((ctl->cput)+x) = ‘\0’;
  176.             mp_netbuf->logcb(ctl->cput, mp_netbuf->cbarg, true);
  177.         }
  178.         if (x == 0) eof = 1;
  179.         ctl->cleft -= x;
  180.         ctl->cavail += x;
  181.         ctl->cput += x;
  182.     } while (1);
  183.     return retval;
  184. }
  185. /* 
  186.  * write lines of text 
  187.  * 
  188.  * return -1 on error or bytecount 
  189.  */
  190. int ftplib::writeline(char *buf, int len, netbuf *nData)
  191. {
  192.     int x, nb=0, w;
  193.     char *ubp = buf, *nbp;
  194.     char lc=0;
  195.     if (nData->dir != FTPLIB_WRITE)
  196.     return -1;
  197.     nbp = nData->buf;
  198.     for (x=0; x < len; x++)
  199.     {
  200.         if ((*ubp == ‘\n’) && (lc != ‘\r’))
  201.         {
  202.             if (nb == FTPLIB_BUFSIZ)
  203.             {
  204.                 if (!socket_wait(nData)) return x;
  205.                 if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ);
  206.                 else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
  207.                 if (w != FTPLIB_BUFSIZ)
  208.                 {
  209.                     printf(“net_write(1) returned %d, errno = %d\n”, w, errno);
  210.                     return(-1);
  211.                 }
  212.                 nb = 0;
  213.             }
  214.             nbp[nb++] = ‘\r’;
  215.         }
  216.         if (nb == FTPLIB_BUFSIZ)
  217.         {
  218.             if (!socket_wait(nData))
  219.             return x;
  220.             if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ);
  221.             else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
  222.             if (w != FTPLIB_BUFSIZ)
  223.             {
  224.                 printf(“net_write(2) returned %d, errno = %d\n”, w, errno);
  225.                 return(-1);
  226.             }
  227.             nb = 0;
  228.         }
  229.         nbp[nb++] = lc = *ubp++;
  230.     }
  231.     if (nb)
  232.     {
  233.         if (!socket_wait(nData)) return x;
  234.         if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, nb);
  235.         else w = net_write(nData->handle, nbp, nb);
  236.         if (w != nb)
  237.         {
  238.             printf(“net_write(3) returned %d, errno = %d\n”, w, errno);
  239.             return(-1);
  240.         }
  241.     }
  242.     return len;
  243. }
  244. /* 
  245.  * read a response from the server 
  246.  * 
  247.  * return 0 if first char doesn’t match 
  248.  * return 1 if first char matches 
  249.  */
  250. int ftplib::readresp(char c, netbuf *nControl)
  251. {
  252.     char match[5];
  253.     if (readline(nControl->response,256,nControl) == -1)
  254.     {
  255.         perror(“Control socket read failed”);
  256.         return 0;
  257.     }
  258.     if (nControl->response[3] == ‘-‘)
  259.     {
  260.         strncpy(match,nControl->response,3);
  261.         match[3] = ‘ ‘;
  262.         match[4] = ‘\0’;
  263.         do
  264.         {
  265.             if (readline(nControl->response,256,nControl) == -1)
  266.             {
  267.                 perror(“Control socket read failed”);
  268.                 return 0;
  269.             }
  270.         } while (strncmp(nControl->response,match,4));
  271.     }
  272.     if (nControl->response[0] == c) return 1;
  273.     return 0;
  274. }
  275. /* 
  276.  * FtpLastResponse – return a pointer to the last response received 
  277.  */
  278. char* ftplib::LastResponse()
  279. {
  280.     if ((mp_netbuf) && (mp_netbuf->dir == FTPLIB_CONTROL)) return mp_netbuf->response;
  281.     return NULL;
  282. }
  283. /* 
  284.  * ftplib::Connect – connect to remote server 
  285.  * 
  286.  * return 1 if connected, 0 if not 
  287.  */
  288. int ftplib::Connect(const char *host)
  289. {
  290.     int sControl;
  291.     struct sockaddr_in sin;
  292.     struct hostent *phe;
  293.     struct servent *pse;
  294.     int on=1;
  295.     int ret;
  296.     char *lhost;
  297.     char *pnum;
  298.     mp_netbuf->dir = FTPLIB_CONTROL;
  299.     mp_netbuf->ctrl = NULL;
  300.     mp_netbuf->xfered = 0;
  301.     mp_netbuf->xfered1 = 0;
  302.     mp_netbuf->tlsctrl = 0;
  303.     mp_netbuf->tlsdata = 0;
  304.     mp_netbuf->offset = 0;
  305.     mp_netbuf->handle = 0;
  306.     memset(&sin,0,sizeof(sin));
  307.     sin.sin_family = AF_INET;
  308.     lhost = strdup(host);
  309.     pnum = strchr(lhost,‘:’);
  310.     if (pnum == NULL)
  311.     {
  312.         if ((pse = getservbyname(“ftp”,“tcp”)) == NULL)
  313.         {
  314.         perror(“getservbyname”);
  315.         return 0;
  316.         }
  317.         sin.sin_port = pse->s_port;
  318.     }
  319.     else
  320.     {
  321.         *pnum++ = ‘\0’;
  322.         if (isdigit(*pnum)) sin.sin_port = htons(atoi(pnum));
  323.         else
  324.         {
  325.             pse = getservbyname(pnum,“tcp”);
  326.             sin.sin_port = pse->s_port;
  327.         }
  328.     }
  329.     ret = inet_aton(lhost, &sin.sin_addr);
  330.     if (ret == 0)
  331.     {
  332.         if ((phe = gethostbyname(lhost)) == NULL)
  333.         {
  334.         perror(“gethostbyname”);
  335.         return 0;
  336.         }
  337.         memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
  338.     }
  339.     free(lhost);
  340.     sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  341.     if (sControl == -1)
  342.     {
  343.         perror(“socket”);
  344.         return 0;
  345.     }
  346.     if (setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
  347.     {
  348.         perror(“setsockopt”);
  349.         net_close(sControl);
  350.         return 0;
  351.     }
  352.     if (connect(sControl, (struct sockaddr *)&sin, sizeof(sin)) == -1)
  353.     {
  354.         perror(“connect”);
  355.         net_close(sControl);
  356.         return 0;
  357.     }
  358.     mp_netbuf->handle = sControl;
  359.     if (readresp(‘2’, mp_netbuf) == 0)
  360.     {
  361.         net_close(sControl);
  362.         mp_netbuf->handle = 0;
  363.         return 0;
  364.     }
  365.     return 1;
  366. }
  367. /* 
  368.  * FtpSendCmd – send a command and wait for expected response 
  369.  * 
  370.  * return 1 if proper response received, 0 otherwise 
  371.  */
  372. int ftplib::FtpSendCmd(const char *cmd, char expresp, netbuf *nControl)
  373. {
  374.     char buf[256];
  375.     int x;
  376.     if (!nControl->handle) return 0;
  377.     if (nControl->dir != FTPLIB_CONTROL) return 0;
  378.     sprintf(buf,“%s\r\n”,cmd);
  379.     if (nControl->tlsctrl) x = SSL_write(nControl->ssl,buf,strlen(buf));
  380.     else x = net_write(nControl->handle,buf,strlen(buf));
  381.     if (x <= 0)
  382.     {
  383.         perror(“write”);
  384.         return 0;
  385.     }
  386.     if (mp_netbuf->logcb != NULL) mp_netbuf->logcb(buf, mp_netbuf->cbarg, false);
  387.     return readresp(expresp, nControl);
  388. }
  389. /* 
  390.  * FtpLogin – log in to remote server 
  391.  * 
  392.  * return 1 if logged in, 0 otherwise 
  393.  */
  394. int ftplib::Login(const char *user, const char *pass)
  395. {
  396.     char tempbuf[64];
  397.     if (((strlen(user) + 7) > sizeof(tempbuf)) || ((strlen(pass) + 7) > sizeof(tempbuf))) return 0;
  398.     sprintf(tempbuf, “USER %s”, user);
  399.     if (!FtpSendCmd(tempbuf,‘3’,mp_netbuf))
  400.     {
  401.         if (mp_netbuf->ctrl != NULL) return 1;
  402.         if (*LastResponse() == ‘2’return 1;
  403.         return 0;
  404.     }
  405.     sprintf(tempbuf,“PASS %s”,pass);
  406.     return FtpSendCmd(tempbuf,‘2’,mp_netbuf);
  407. }
  408. /* 
  409.  * FtpAcceptConnection – accept connection from server 
  410.  * 
  411.  * return 1 if successful, 0 otherwise 
  412.  */
  413. int ftplib::FtpAcceptConnection(netbuf *nData, netbuf *nControl)
  414. {
  415.     int sData;
  416.     struct sockaddr addr;
  417.     unsigned int l;
  418.     int i;
  419.     struct timeval tv;
  420.     fd_set mask;
  421.     int rv = 0;
  422.     FD_ZERO(&mask);
  423.     FD_SET(nControl->handle, &mask);
  424.     FD_SET(nData->handle, &mask);
  425.     tv.tv_usec = 0;
  426.     tv.tv_sec = ACCEPT_TIMEOUT;
  427.     i = nControl->handle;
  428.     if (i < nData->handle) i = nData->handle;
  429.     i = select(i+1, &mask, NULL, NULL, &tv);
  430.     if (i == -1)
  431.     {
  432.         strncpy(nControl->response, strerror(errno), sizeof(nControl->response));
  433.         net_close(nData->handle);
  434.         nData->handle = 0;
  435.         rv = 0;
  436.     }
  437.     else if (i == 0)
  438.     {
  439.         strcpy(nControl->response, “timed out waiting for connection”);
  440.         net_close(nData->handle);
  441.         nData->handle = 0;
  442.         rv = 0;
  443.     }
  444.     else
  445.     {
  446.         if (FD_ISSET(nData->handle, &mask))
  447.         {
  448.             l = sizeof(addr);
  449.             sData = accept(nData->handle, &addr, &l);
  450.             i = errno;
  451.             net_close(nData->handle);
  452.             if (sData > 0)
  453.             {
  454.                 rv = 1;
  455.                 nData->handle = sData;
  456.                 nData->ctrl = nControl;
  457.             }
  458.             else
  459.             {
  460.                 strncpy(nControl->response, strerror(i), sizeof(nControl->response));
  461.                 nData->handle = 0;
  462.                 rv = 0;
  463.             }
  464.         }
  465.         else if (FD_ISSET(nControl->handle, &mask))
  466.         {
  467.             net_close(nData->handle);
  468.             nData->handle = 0;
  469.             readresp(‘2’, nControl);
  470.             rv = 0;
  471.         }
  472.     }
  473.     return rv;
  474. }
  475. /* 
  476.  * FtpAccess – return a handle for a data stream 
  477.  * 
  478.  * return 1 if successful, 0 otherwise 
  479.  */
  480. int ftplib::FtpAccess(const char *path, int typ, int mode, netbuf *nControl, netbuf **nData)
  481. //int ftplib::FtpAccess(const char *path, int typ, int mode) 
  482. {
  483.     char buf[256];
  484.     int dir, ret;
  485.     if ((path == NULL) && ((typ == FTPLIB_FILE_WRITE)
  486.         || (typ == FTPLIB_FILE_READ)
  487.         || (typ == FTPLIB_FILE_READ_APPEND)
  488.         || (typ == FTPLIB_FILE_WRITE_APPEND)))
  489.     {
  490.         sprintf(nControl->response,“Missing path argument for file transfer\n”);
  491.         return 0;
  492.     }
  493.     sprintf(buf, “TYPE %c”, mode);
  494.     if (!FtpSendCmd(buf, ‘2’, nControl)) return 0;
  495.     switch (typ)
  496.     {
  497.     case FTPLIB_DIR:
  498.         strcpy(buf,“NLST”);
  499.         dir = FTPLIB_READ;
  500.         break;
  501.     case FTPLIB_DIR_VERBOSE:
  502.         strcpy(buf,“LIST -aL”);
  503.         dir = FTPLIB_READ;
  504.         break;
  505.     case FTPLIB_FILE_READ_APPEND:
  506.     case FTPLIB_FILE_READ:
  507.         strcpy(buf,“RETR”);
  508.         dir = FTPLIB_READ;
  509.         break;
  510.     case FTPLIB_FILE_WRITE_APPEND:
  511.     case FTPLIB_FILE_WRITE:
  512.         strcpy(buf,“STOR”);
  513.         dir = FTPLIB_WRITE;
  514.         break;
  515.     default:
  516.         sprintf(nControl->response, “Invalid open type %d\n”, typ);
  517.         return 0;
  518.     }
  519.     if (path != NULL)
  520.     {
  521.         int i = strlen(buf);
  522.         buf[i++] = ‘ ‘;
  523.         if ((strlen(path) + i) >= sizeof(buf)) return 0;
  524.         strcpy(&buf[i],path);
  525.     }
  526.     if (nControl->cmode == ftplib::pasv)
  527.     {
  528.         if (FtpOpenPasv(nControl, nData, mode, dir, buf) == -1) return 0;
  529.     }
  530.     if (nControl->cmode == ftplib::port)
  531.     {
  532.         if (FtpOpenPort(nControl, nData, mode, dir, buf) == -1) return 0;
  533.         if (!FtpAcceptConnection(*nData,nControl))
  534.         {
  535.             FtpClose(*nData);
  536.             *nData = NULL;
  537.             return 0;
  538.         }
  539.     }
  540.     if (nControl->tlsdata)
  541.     {
  542.         (*nData)->ssl = SSL_new(nControl->ctx);
  543.         (*nData)->sbio = BIO_new_socket((*nData)->handle, BIO_NOCLOSE);
  544.         SSL_set_bio((*nData)->ssl,(*nData)->sbio,(*nData)->sbio);
  545.         ret = SSL_connect((*nData)->ssl);
  546.         if (ret != 1) return 0;
  547.         (*nData)->tlsdata = 1;
  548.     }
  549.     return 1;
  550. }
  551. /* 
  552.  * FtpOpenPort – Establishes a PORT connection for data transfer 
  553.  * 
  554.  * return 1 if successful, -1 otherwise 
  555.  */
  556. int ftplib::FtpOpenPort(netbuf *nControl, netbuf **nData, int mode, int dir, char *cmd)
  557. {
  558.     int sData;
  559.     union {
  560.     struct sockaddr sa;
  561.     struct sockaddr_in in;
  562.     } sin;
  563.     struct linger lng = { 0, 0 };
  564.     unsigned int l;
  565.     int on=1;
  566.     netbuf *ctrl;
  567.     char buf[256];
  568.     if (nControl->dir != FTPLIB_CONTROL) return -1;
  569.     if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE))
  570.     {
  571.         sprintf(nControl->response, “Invalid direction %d\n”, dir);
  572.         return -1;
  573.     }
  574.     if ((mode != ftplib::ascii) && (mode != ftplib::image))
  575.     {
  576.         sprintf(nControl->response, “Invalid mode %c\n”, mode);
  577.         return -1;
  578.     }
  579.     l = sizeof(sin);
  580.     if (getsockname(nControl->handle, &sin.sa, &l) < 0)
  581.     {
  582.         perror(“getsockname”);
  583.         return -1;
  584.     }
  585.     sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  586.     if (sData == -1)
  587.     {
  588.         perror(“socket”);
  589.         return -1;
  590.     }
  591.     if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1)
  592.     {
  593.         perror(“setsockopt”);
  594.         net_close(sData);
  595.         return -1;
  596.     }
  597.     if (setsockopt(sData,SOL_SOCKET,SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1)
  598.     {
  599.         perror(“setsockopt”);
  600.         net_close(sData);
  601.         return -1;
  602.     }
  603.     sin.in.sin_port = 0;
  604.     if (bind(sData, &sin.sa, sizeof(sin)) == -1)
  605.     {
  606.         perror(“bind”);
  607.         net_close(sData);
  608.         return -1;
  609.     }
  610.     if (listen(sData, 1) < 0)
  611.     {
  612.         perror(“listen”);
  613.         net_close(sData);
  614.         return -1;
  615.     }
  616.     if (getsockname(sData, &sin.sa, &l) < 0) return 0;
  617.     sprintf(buf, “PORT %d,%d,%d,%d,%d,%d”,
  618.         (unsigned char) sin.sa.sa_data[2],
  619.         (unsigned char) sin.sa.sa_data[3],
  620.         (unsigned char) sin.sa.sa_data[4],
  621.         (unsigned char) sin.sa.sa_data[5],
  622.         (unsigned char) sin.sa.sa_data[0],
  623.         (unsigned char) sin.sa.sa_data[1]);
  624.     if (!FtpSendCmd(buf,‘2’,nControl))
  625.     {
  626.         net_close(sData);
  627.         return -1;
  628.     }
  629.     if (mp_netbuf->offset != 0)
  630.     {
  631.     char buf[256];
  632.     sprintf(buf,“REST %ld”, mp_netbuf->offset);
  633.     if (!FtpSendCmd(buf,‘3’,nControl))
  634.     {
  635.         net_close(sData);
  636.         return 0;
  637.     }
  638.     }
  639.     ctrl = static_cast<netbuf*>(calloc(1,sizeof(netbuf)));
  640.     if (ctrl == NULL)
  641.     {
  642.         perror(“calloc”);
  643.         net_close(sData);
  644.         return -1;
  645.     }
  646.     if ((mode == ‘A’) && ((ctrl->buf = static_cast<char*>(malloc(FTPLIB_BUFSIZ))) == NULL))
  647.     {
  648.         perror(“calloc”);
  649.         net_close(sData);
  650.         free(ctrl);
  651.         return -1;
  652.     }
  653.     if (!FtpSendCmd(cmd, ‘1’, nControl))
  654.     {
  655.         FtpClose(*nData);
  656.         *nData = NULL;
  657.         return -1;
  658.     }
  659.     ctrl->handle = sData;
  660.     ctrl->dir = dir;
  661.     ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL;
  662.     ctrl->idletime = nControl->idletime;
  663.     ctrl->cbarg = nControl->cbarg;
  664.     ctrl->xfered = 0;
  665.     ctrl->xfered1 = 0;
  666.     ctrl->cbbytes = nControl->cbbytes;
  667.     if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb;
  668.     else ctrl->idlecb = NULL;
  669.     if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb;
  670.     else ctrl->xfercb = NULL;
  671.     *nData = ctrl;
  672.     return 1;
  673. }
  674. /* 
  675.  * FtpOpenPasv – Establishes a PASV connection for data transfer 
  676.  * 
  677.  * return 1 if successful, -1 otherwise 
  678.  */
  679. int ftplib::FtpOpenPasv(netbuf *nControl, netbuf **nData, int mode, int dir, char *cmd)
  680. {
  681.     int sData;
  682.     union {
  683.         struct sockaddr sa;
  684.         struct sockaddr_in in;
  685.     } sin;
  686.     struct linger lng = { 0, 0 };
  687.     unsigned int l;
  688.     int on=1;
  689.     netbuf *ctrl;
  690.     char *cp;
  691.     unsigned int v[6];
  692.     int ret;
  693.     if (nControl->dir != FTPLIB_CONTROL) return -1;
  694.     if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE))
  695.     {
  696.         sprintf(nControl->response, “Invalid direction %d\n”, dir);
  697.         return -1;
  698.     }
  699.     if ((mode != ftplib::ascii) && (mode != ftplib::image))
  700.     {
  701.         sprintf(nControl->response, “Invalid mode %c\n”, mode);
  702.         return -1;
  703.     }
  704.     l = sizeof(sin);
  705.     memset(&sin, 0, l);
  706.     sin.in.sin_family = AF_INET;
  707.     if (!FtpSendCmd(“PASV”,‘2’,nControl)) return -1;
  708.     cp = strchr(nControl->response,‘(‘);
  709.     if (cp == NULL) return -1;
  710.     cp++;
  711.     sscanf(cp,“%u,%u,%u,%u,%u,%u”,&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]);
  712.     if (nControl->correctpasv) if (!CorrectPasvResponse(v)) return -1;
  713.     sin.sa.sa_data[2] = v[2];
  714.     sin.sa.sa_data[3] = v[3];
  715.     sin.sa.sa_data[4] = v[4];
  716.     sin.sa.sa_data[5] = v[5];
  717.     sin.sa.sa_data[0] = v[0];
  718.     sin.sa.sa_data[1] = v[1];
  719.     if (mp_netbuf->offset != 0)
  720.     {
  721.         char buf[256];
  722.         sprintf(buf,“REST %ld”,mp_netbuf->offset);
  723.         if (!FtpSendCmd(buf,‘3’,nControl)) return 0;
  724.     }
  725.     sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  726.     if (sData == -1)
  727.     {
  728.         perror(“socket”);
  729.         return -1;
  730.     }
  731.     if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1)
  732.     {
  733.         perror(“setsockopt”);
  734.         net_close(sData);
  735.         return -1;
  736.     }
  737.     if (setsockopt(sData,SOL_SOCKET,SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1)
  738.     {
  739.         perror(“setsockopt”);
  740.         net_close(sData);
  741.         return -1;
  742.     }
  743.     if (nControl->dir != FTPLIB_CONTROL) return -1;
  744.     sprintf(cmd,“%s\r\n”,cmd);
  745.     if (nControl->tlsctrl) ret = SSL_write(nControl->ssl,cmd,strlen(cmd));
  746.     else ret = net_write(nControl->handle,cmd,strlen(cmd));
  747.     if (ret <= 0)
  748.     {
  749.         perror(“write”);
  750.         return -1;
  751.     }
  752.     if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1)
  753.     {
  754.         perror(“connect”);
  755.         net_close(sData);
  756.         return -1;
  757.     }
  758.     if (!readresp(‘1’, nControl))
  759.     {
  760.         net_close(sData);
  761.         return -1;
  762.     }
  763.     ctrl = static_cast<netbuf*>(calloc(1,sizeof(netbuf)));
  764.     if (ctrl == NULL)
  765.     {
  766.         perror(“calloc”);
  767.         net_close(sData);
  768.         return -1;
  769.     }
  770.     if ((mode == ‘A’) && ((ctrl->buf = static_cast<char*>(malloc(FTPLIB_BUFSIZ))) == NULL))
  771.     {
  772.         perror(“calloc”);
  773.         net_close(sData);
  774.         free(ctrl);
  775.         return -1;
  776.     }
  777.     ctrl->handle = sData;
  778.     ctrl->dir = dir;
  779.     ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL;
  780.     ctrl->idletime = nControl->idletime;
  781.     ctrl->cbarg = nControl->cbarg;
  782.     ctrl->xfered = 0;
  783.     ctrl->xfered1 = 0;
  784.     ctrl->cbbytes = nControl->cbbytes;
  785.     if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb;
  786.     else ctrl->idlecb = NULL;
  787.     if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb;
  788.     else ctrl->xfercb = NULL;
  789.     *nData = ctrl;
  790.     return 1;
  791. }
  792. /* 
  793.  * FtpClose – close a data connection 
  794.  */
  795. int ftplib::FtpClose(netbuf *nData)
  796. {
  797.     netbuf *ctrl;
  798.     if (nData->dir == FTPLIB_WRITE)
  799.     {
  800.         if (nData->buf != NULL) writeline(NULL, 0, nData);
  801.     }
  802.     else if (nData->dir != FTPLIB_READ) return 0;
  803.     if (nData->buf) free(nData->buf);
  804.     shutdown(nData->handle,2);
  805.     net_close(nData->handle);
  806.     ctrl = nData->ctrl;
  807.     SSL_free(nData->ssl);
  808.     free(nData);
  809.     if (ctrl) return readresp(‘2’, ctrl);
  810.     return 1;
  811. }
  812. /* 
  813.  * FtpRead – read from a data connection 
  814.  */
  815. int ftplib::FtpRead(void *buf, int max, netbuf *nData)
  816. {
  817.     int i;
  818.     if (nData->dir != FTPLIB_READ)
  819.     return 0;
  820.     if (nData->buf) i = readline(static_cast<char*>(buf), max, nData);
  821.     else
  822.     {
  823.         i = socket_wait(nData);
  824.         if (i != 1) return 0;
  825.         if (nData->tlsdata) i = SSL_read(nData->ssl, buf, max);
  826.         else i = net_read(nData->handle,buf,max);
  827.     }
  828.     if (i == -1) return 0;
  829.     nData->xfered += i;
  830.     if (nData->xfercb && nData->cbbytes)
  831.     {
  832.         nData->xfered1 += i;
  833.         if (nData->xfered1 > nData->cbbytes)
  834.         {
  835.             if (nData->xfercb(nData->xfered, nData->cbarg) == 0) return 0;
  836.             nData->xfered1 = 0;
  837.         }
  838.     }
  839.     return i;
  840. }
  841. /* 
  842.  * FtpWrite – write to a data connection 
  843.  */
  844. int ftplib::FtpWrite(void *buf, int len, netbuf *nData)
  845. {
  846.     int i;
  847.     if (nData->dir != FTPLIB_WRITE) return 0;
  848.     if (nData->buf) i = writeline(static_cast<char*>(buf), len, nData);
  849.     else
  850.     {
  851.         socket_wait(nData);
  852.         if (nData->tlsdata) i = SSL_write(nData->ssl, buf, len);
  853.         else i = net_write(nData->handle, buf, len);
  854.     }
  855.     if (i == -1) return 0;
  856.     nData->xfered += i;
  857.     if (nData->xfercb && nData->cbbytes)
  858.     {
  859.         nData->xfered1 += i;
  860.         if (nData->xfered1 > nData->cbbytes)
  861.         {
  862.             if (nData->xfercb(nData->xfered, nData->cbarg) == 0) return 0;
  863.             nData->xfered1 = 0;
  864.         }
  865.     }
  866.     return i;
  867. }
  868. /* 
  869.  * FtpSite – send a SITE command 
  870.  * 
  871.  * return 1 if command successful, 0 otherwise 
  872.  */
  873. int ftplib::Site(const char *cmd)
  874. {
  875.     char buf[256];
  876.     if ((strlen(cmd) + 7) > sizeof(buf)) return 0;
  877.     sprintf(buf,“SITE %s”,cmd);
  878.     if (!FtpSendCmd(buf,‘2’,mp_netbuf)) return 0;
  879.     return 1;
  880. }
  881. /* 
  882.  * FtpRaw – send a raw string string 
  883.  * 
  884.  * return 1 if command successful, 0 otherwise 
  885.  */
  886. int ftplib::Raw(const char *cmd)
  887. {
  888.     char buf[256];
  889.     strncpy(buf, cmd, 256);
  890.     if (!FtpSendCmd(buf,‘2’,mp_netbuf)) return 0;
  891.     return 1;
  892. }
  893. /* 
  894.  * FtpSysType – send a SYST command 
  895.  * 
  896.  * Fills in the user buffer with the remote system type.  If more 
  897.  * information from the response is required, the user can parse 
  898.  * it out of the response buffer returned by FtpLastResponse(). 
  899.  * 
  900.  * return 1 if command successful, 0 otherwise 
  901.  */
  902. int ftplib::SysType(char *buf, int max)
  903. {
  904.     int l = max;
  905.     char *b = buf;
  906.     char *s;
  907.     if (!FtpSendCmd(“SYST”,‘2’,mp_netbuf)) return 0;
  908.     s = &mp_netbuf->response[4];
  909.     while ((–l) && (*s != ‘ ‘)) *b++ = *s++;
  910.     *b++ = ‘\0’;
  911.     return 1;
  912. }
  913. /* 
  914.  * FtpMkdir – create a directory at server 
  915.  * 
  916.  * return 1 if successful, 0 otherwise 
  917.  */
  918. int ftplib::Mkdir(const char *path)
  919. {
  920.     char buf[256];
  921.     if ((strlen(path) + 6) > sizeof(buf)) return 0;
  922.     sprintf(buf,“MKD %s”,path);
  923.     if (!FtpSendCmd(buf,‘2’, mp_netbuf)) return 0;
  924.     return 1;
  925. }
  926. /* 
  927.  * FtpChdir – change path at remote 
  928.  * 
  929.  * return 1 if successful, 0 otherwise 
  930.  */
  931. int ftplib::Chdir(const char *path)
  932. {
  933.     char buf[256];
  934.     if ((strlen(path) + 6) > sizeof(buf)) return 0;
  935.     sprintf(buf,“CWD %s”,path);
  936.     if (!FtpSendCmd(buf,‘2’,mp_netbuf)) return 0;
  937.     return 1;
  938. }
  939. /* 
  940.  * FtpCDUp – move to parent directory at remote 
  941.  * 
  942.  * return 1 if successful, 0 otherwise 
  943.  */
  944. int ftplib::Cdup()
  945. {
  946.     if (!FtpSendCmd(“CDUP”,‘2’,mp_netbuf)) return 0;
  947.     return 1;
  948. }
  949. /* 
  950.  * FtpRmdir – remove directory at remote 
  951.  * 
  952.  * return 1 if successful, 0 otherwise 
  953.  */
  954. int ftplib::Rmdir(const char *path)
  955. {
  956.     char buf[256];
  957.     if ((strlen(path) + 6) > sizeof(buf)) return 0;
  958.     sprintf(buf,“RMD %s”,path);
  959.     if (!FtpSendCmd(buf,‘2’,mp_netbuf)) return 0;
  960.     return 1;
  961. }
  962. /* 
  963.  * FtpPwd – get working directory at remote 
  964.  * 
  965.  * return 1 if successful, 0 otherwise 
  966.  */
  967. int ftplib::Pwd(char *path, int max)
  968. {
  969.     int l = max;
  970.     char *b = path;
  971.     char *s;
  972.     if (!FtpSendCmd(“PWD”,‘2’,mp_netbuf)) return 0;
  973.     s = strchr(mp_netbuf->response, ‘”‘);
  974.     if (s == NULL) return 0;
  975.    s++;
  976.     while ((–l) && (*s) && (*s != ‘”‘)) *b++ = *s++;
  977.     *b++ = ‘\0’;
  978.     return 1;
  979. }
  980. /* 
  981.  * FtpXfer – issue a command and transfer data 
  982.  * 
  983.  * return 1 if successful, 0 otherwise 
  984.  */
  985. int ftplib::FtpXfer(const char *localfile, const char *path, netbuf *nControl, int typ, int mode)
  986. {
  987.     int l,c;
  988.     char *dbuf;
  989.     FILE *local = NULL;
  990.     netbuf *nData;
  991.     int rv=1; // 3.1-1 
  992.     if (localfile != NULL)
  993.     {
  994.         //local = fopen(localfile, (typ == FTPLIB_FILE_WRITE) ? “r” : “w”); 
  995.         char ac[3] = ”  “;
  996.         if ((typ == FTPLIB_DIR) || (typ == FTPLIB_DIR_VERBOSE)) { ac[0] = ‘w’; ac[1] = ‘\0’; }
  997.         if (typ == FTPLIB_FILE_READ) { ac[0] = ‘w’; ac[1] = ‘\0’; }
  998.         if (typ == FTPLIB_FILE_WRITE_APPEND) { ac[0] = ‘r’; ac[1] = ‘\0’; }
  999.         if (typ == FTPLIB_FILE_READ_APPEND) { ac[0] = ‘a’; ac[1] = ‘\0’; }
  1000.         if (typ == FTPLIB_FILE_WRITE) { ac[0] = ‘r’; ac[1] = ‘\0’; }
  1001.         if (mode == ftplib::image) ac[1] = ‘b’;
  1002.         local = fopen(localfile, ac);
  1003.         if (typ == FTPLIB_FILE_WRITE_APPEND) fseeko(local,mp_netbuf->offset,SEEK_SET);
  1004.         if (local == NULL)
  1005.         {
  1006.             strncpy(nControl->response, strerror(errno), sizeof(nControl->response));
  1007.             return 0;
  1008.         }
  1009.     }
  1010.     if (local == NULL) local = ((typ == FTPLIB_FILE_WRITE)
  1011.         || (typ == FTPLIB_FILE_WRITE_APPEND)) ? stdin : stdout;
  1012.     if (!FtpAccess(path, typ, mode, nControl, &nData)) return 0;
  1013.     dbuf = static_cast<char*>(malloc(FTPLIB_BUFSIZ));
  1014.     if ((typ == FTPLIB_FILE_WRITE) || (typ == FTPLIB_FILE_WRITE_APPEND))
  1015.     {
  1016.         while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0)
  1017.         {
  1018.             if ((c = FtpWrite(dbuf, l, nData)) < l)
  1019.             {
  1020.                 printf(“short write: passed %d, wrote %d\n”, l, c);
  1021.                 rv = 0;
  1022.                 break;
  1023.             }
  1024.         }
  1025.     }
  1026.     else
  1027.     {
  1028.         while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0)
  1029.         {
  1030.             if (fwrite(dbuf, 1, l, local) <= 0)
  1031.             {
  1032.                 perror(“localfile write”);
  1033.                 break;
  1034.             }
  1035.         }
  1036.     }
  1037.     free(dbuf);
  1038.     fflush(local);
  1039.     if (localfile != NULL)
  1040.     fclose(local);
  1041.     return FtpClose(nData);
  1042.     return rv;
  1043. }
  1044. /* 
  1045.  * FtpNlst – issue an NLST command and write response to output 
  1046.  * 
  1047.  * return 1 if successful, 0 otherwise 
  1048.  */
  1049. int ftplib::Nlst(const char *outputfile, const char *path)
  1050. {
  1051.     mp_netbuf->offset = 0;
  1052.     return FtpXfer(outputfile, path, mp_netbuf, FTPLIB_DIR, ftplib::ascii);
  1053. }
  1054. /* 
  1055.  * FtpDir – issue a LIST command and write response to output 
  1056.  * 
  1057.  * return 1 if successful, 0 otherwise 
  1058.  */
  1059. int ftplib::Dir(const char *outputfile, const char *path)
  1060. {
  1061.     mp_netbuf->offset = 0;
  1062.     return FtpXfer(outputfile, path, mp_netbuf, FTPLIB_DIR_VERBOSE, ftplib::ascii);
  1063. }
  1064. /* 
  1065.  * FtpSize – determine the size of a remote file 
  1066.  * 
  1067.  * return 1 if successful, 0 otherwise 
  1068.  */
  1069. //int ftplib::Size(const char *path, int *size, char mode) 
  1070. int ftplib::Size(const char *path, int *size, ftplib::ftp mode)
  1071. {
  1072.    char cmd[256];
  1073.    int resp,sz,rv=1;
  1074.    if ((strlen(path) + 7) > sizeof(cmd)) return 0;
  1075.     sprintf(cmd, “TYPE %c”, mode);
  1076.    if (!FtpSendCmd(cmd, ‘2’, mp_netbuf)) return 0;
  1077.     sprintf(cmd,“SIZE %s”,path);
  1078.    if (!FtpSendCmd(cmd,‘2’,mp_netbuf)) rv = 0;
  1079.    else
  1080.    {
  1081.         if (sscanf(mp_netbuf->response, “%d %d”, &resp, &sz) == 2) *size = sz;
  1082.         else rv = 0;
  1083.    }
  1084.    return rv;
  1085. }
  1086. /* 
  1087.  * FtpModDate – determine the modification date of a remote file 
  1088.  * 
  1089.  * return 1 if successful, 0 otherwise 
  1090.  */
  1091. int ftplib::ModDate(const char *path, char *dt, int max)
  1092. {
  1093.     char buf[256];
  1094.     int rv = 1;
  1095.     if ((strlen(path) + 7) > sizeof(buf)) return 0;
  1096.     sprintf(buf,“MDTM %s”,path);
  1097.    if (!FtpSendCmd(buf,‘2’,mp_netbuf)) rv = 0;
  1098.     else strncpy(dt, &mp_netbuf->response[4], max);
  1099.     return rv;
  1100. }
  1101. /* 
  1102.  * FtpGet – issue a GET command and write received data to output 
  1103.  * 
  1104.  * return 1 if successful, 0 otherwise 
  1105.  */
  1106. int ftplib::Get(const char *outputfile, const char *path, ftplib::ftp mode, off_t offset)
  1107. {
  1108.     mp_netbuf->offset = offset;
  1109.     if (offset == 0) return FtpXfer(outputfile, path, mp_netbuf, FTPLIB_FILE_READ, mode);
  1110.     else return FtpXfer(outputfile, path, mp_netbuf, FTPLIB_FILE_READ_APPEND, mode);
  1111. }
  1112. /* 
  1113.  * FtpPut – issue a PUT command and send data from input 
  1114.  * 
  1115.  * return 1 if successful, 0 otherwise 
  1116.  */
  1117. int ftplib::Put(const char *inputfile, const char *path, ftplib::ftp mode, off_t offset)
  1118. {
  1119.     mp_netbuf->offset = offset;
  1120.     if (offset == 0) return FtpXfer(inputfile, path, mp_netbuf, FTPLIB_FILE_WRITE, mode);
  1121.     else return FtpXfer(inputfile, path, mp_netbuf, FTPLIB_FILE_WRITE_APPEND, mode);
  1122. }
  1123. /* 
  1124.  * FtpRename – rename a file at remote 
  1125.  * 
  1126.  * return 1 if successful, 0 otherwise 
  1127.  */
  1128. int ftplib::Rename(const char *src, const char *dst)
  1129. {
  1130.     char cmd[256];
  1131.     if (((strlen(src) + 7) > sizeof(cmd)) || ((strlen(dst) + 7) > sizeof(cmd))) return 0;
  1132.     sprintf(cmd,“RNFR %s”,src);
  1133.     if (!FtpSendCmd(cmd,‘3’,mp_netbuf)) return 0;
  1134.     sprintf(cmd,“RNTO %s”,dst);
  1135.     if (!FtpSendCmd(cmd,‘2’,mp_netbuf)) return 0;
  1136.     return 1;
  1137. }
  1138. /* 
  1139.  * FtpDelete – delete a file at remote 
  1140.  * 
  1141.  * return 1 if successful, 0 otherwise 
  1142.  */
  1143. int ftplib::Delete(const char *fnm)
  1144. {
  1145.     char cmd[256];
  1146.     if ((strlen(fnm) + 7) > sizeof(cmd)) return 0;
  1147.    sprintf(cmd,“DELE %s”,fnm);
  1148.    if (!FtpSendCmd(cmd,‘2’, mp_netbuf)) return 0;
  1149.    return 1;
  1150. }
  1151. /* 
  1152.  * FtpQuit – disconnect from remote 
  1153.  * 
  1154.  * return 1 if successful, 0 otherwise 
  1155.  */
  1156. int ftplib::Quit()
  1157. {
  1158.     if (mp_netbuf->dir != FTPLIB_CONTROL) return 0;
  1159.     if (mp_netbuf->handle == 0)
  1160.     {
  1161.         strcpy(mp_netbuf->response, “error: no anwser from server\n”);
  1162.         return 0;
  1163.     }
  1164.     if (!FtpSendCmd(“QUIT”,‘2’,mp_netbuf))
  1165.     {
  1166.         net_close(mp_netbuf->handle);
  1167.         return 0;
  1168.     }
  1169.     else
  1170.     {
  1171.         net_close(mp_netbuf->handle);
  1172.         return 1;
  1173.     }
  1174. }
  1175. int ftplib::Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, ftplib::ftp mode, ftplib::ftp method)
  1176. {
  1177.     char *cp;
  1178.     unsigned int v[6];
  1179.     char buf[256];
  1180.     int retval = 0;
  1181.     sprintf(buf, “TYPE %c”, mode);
  1182.     if (!dst->FtpSendCmd(buf,‘2’,dst->mp_netbuf)) return -1;
  1183.     if (!src->FtpSendCmd(buf,‘2’,src->mp_netbuf)) return -1;
  1184.     if (method == ftplib::defaultfxp)
  1185.     {
  1186.         // PASV dst 
  1187.         if (!dst->FtpSendCmd(“PASV”,‘2’,dst->mp_netbuf)) return -1;
  1188.         cp = strchr(dst->mp_netbuf->response,‘(‘);
  1189.         if (cp == NULL) return -1;
  1190.         cp++;
  1191.         sscanf(cp,“%u,%u,%u,%u,%u,%u”,&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]);
  1192.         if (dst->mp_netbuf->correctpasv) if (!dst->CorrectPasvResponse(v)) return -1;
  1193.         // PORT src 
  1194.         sprintf(buf, “PORT %d,%d,%d,%d,%d,%d”, v[2],v[3],v[4],v[5],v[0],v[1]);
  1195.         if (!src->FtpSendCmd(buf,‘2’,src->mp_netbuf)) return -1;
  1196.         // RETR src 
  1197.         strcpy(buf,“RETR”);
  1198.         if (pathSrc != NULL)
  1199.         {
  1200.             int i = strlen(buf);
  1201.             buf[i++] = ‘ ‘;
  1202.             if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0;
  1203.             strcpy(&buf[i],pathSrc);
  1204.         }
  1205.         if (!src->FtpSendCmd(buf, ‘1’, src->mp_netbuf)) return 0;
  1206.         // STOR dst 
  1207.         strcpy(buf,“STOR”);
  1208.         if (pathDst != NULL)
  1209.         {
  1210.             int i = strlen(buf);
  1211.             buf[i++] = ‘ ‘;
  1212.             if ((strlen(pathDst) + i) >= sizeof(buf)) return 0;
  1213.             strcpy(&buf[i],pathDst);
  1214.         }
  1215.         if (!dst->FtpSendCmd(buf, ‘1’, dst->mp_netbuf))
  1216.         {
  1217.             /* this closes the data connection, to abort the RETR on 
  1218.             the source ftp. all hail pftp, it took me several 
  1219.             hours and i was absolutely clueless, playing around with 
  1220.             ABOR and whatever, when i desperately checked the pftp 
  1221.             source which gave me this final hint. thanks dude(s). */
  1222.             dst->FtpSendCmd(“PASV”‘2’, dst->mp_netbuf);
  1223.             src->readresp(‘4’, src->mp_netbuf);
  1224.             return 0;
  1225.         }
  1226.         retval = (src->readresp(‘2’, src->mp_netbuf)) & (dst->readresp(‘2’, dst->mp_netbuf));
  1227.     }
  1228.     else
  1229.     {
  1230.         // PASV src 
  1231.         if (!src->FtpSendCmd(“PASV”,‘2’,src->mp_netbuf)) return -1;
  1232.         cp = strchr(src->mp_netbuf->response,‘(‘);
  1233.         if (cp == NULL) return -1;
  1234.         cp++;
  1235.         sscanf(cp,“%u,%u,%u,%u,%u,%u”,&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]);
  1236.         if (src->mp_netbuf->correctpasv) if (!src->CorrectPasvResponse(v)) return -1;
  1237.         // PORT dst 
  1238.         sprintf(buf, “PORT %d,%d,%d,%d,%d,%d”, v[2],v[3],v[4],v[5],v[0],v[1]);
  1239.         if (!dst->FtpSendCmd(buf,‘2’,dst->mp_netbuf)) return -1;
  1240.         // STOR dest 
  1241.         strcpy(buf,“STOR”);
  1242.         if (pathDst != NULL)
  1243.         {
  1244.             int i = strlen(buf);
  1245.             buf[i++] = ‘ ‘;
  1246.             if ((strlen(pathDst) + i) >= sizeof(buf)) return 0;
  1247.             strcpy(&buf[i],pathDst);
  1248.         }
  1249.         if (!dst->FtpSendCmd(buf, ‘1’, dst->mp_netbuf)) return 0;
  1250.         // RETR src 
  1251.         strcpy(buf,“RETR”);
  1252.         if (pathSrc != NULL)
  1253.         {
  1254.             int i = strlen(buf);
  1255.             buf[i++] = ‘ ‘;
  1256.             if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0;
  1257.             strcpy(&buf[i],pathSrc);
  1258.         }
  1259.         if (!src->FtpSendCmd(buf, ‘1’, src->mp_netbuf))
  1260.         {
  1261.             src->FtpSendCmd(“PASV”‘2’, src->mp_netbuf);
  1262.             dst->readresp(‘4’, dst->mp_netbuf);
  1263.             return 0;
  1264.         }
  1265.         // wait til its finished! 
  1266.         retval = (src->readresp(‘2’, src->mp_netbuf)) & (dst->readresp(‘2’, dst->mp_netbuf));
  1267.     }
  1268.     return retval;
  1269. }
  1270. int ftplib::SetDataEncryption(ftplib::ftp flag)
  1271. {
  1272.     if (!mp_netbuf->tlsctrl) return 0;
  1273.     if (!FtpSendCmd(“PBSZ 0”,‘2’,mp_netbuf)) return 0;
  1274.     switch(flag)
  1275.     {
  1276.     case 0:
  1277.         mp_netbuf->tlsdata = 0;
  1278.         if (!FtpSendCmd(“PROT C”,‘2’,mp_netbuf)) return 0;
  1279.         break;
  1280.     case 1:
  1281.         mp_netbuf->tlsdata = 1;
  1282.         if (!FtpSendCmd(“PROT P”,‘2’,mp_netbuf)) return 0;
  1283.         break;
  1284.     default:
  1285.         return 0;
  1286.     }
  1287.     return 1;
  1288. }
  1289. int ftplib::NegotiateEncryption()
  1290. {
  1291.     int ret;
  1292.     if (!FtpSendCmd(“AUTH TLS”,‘2’,mp_netbuf)) return 0;
  1293.     mp_netbuf->sbio = BIO_new_socket(mp_netbuf->handle, BIO_NOCLOSE);
  1294.     SSL_set_bio(mp_netbuf->ssl,mp_netbuf->sbio,mp_netbuf->sbio);
  1295.     ret = SSL_connect(mp_netbuf->ssl);
  1296.     if (ret == 1) mp_netbuf->tlsctrl = 1;
  1297.     if (ret < 1) return 0;
  1298.     return 1;
  1299. }
  1300. void ftplib::SetCallbackIdleFunction(FtpCallbackIdle pointer)
  1301. {
  1302.     mp_netbuf->idlecb = pointer;
  1303. }
  1304. void ftplib::SetCallbackXferFunction(FtpCallbackXfer pointer)
  1305. {
  1306.     mp_netbuf->xfercb = pointer;
  1307. }
  1308. void ftplib::SetCallbackLogFunction(FtpCallbackLog pointer)
  1309. {
  1310.     mp_netbuf->logcb = pointer;
  1311. }
  1312. void ftplib::SetCallbackArg(void *arg)
  1313. {
  1314.     mp_netbuf->cbarg = arg;
  1315. }
  1316. void ftplib::SetCallbackBytes(off_t bytes)
  1317. {
  1318.     mp_netbuf->cbbytes = bytes;
  1319. }
  1320. void ftplib::SetCallbackIdletime(int time)
  1321. {
  1322.     mp_netbuf->idletime.tv_sec = time / 1000;
  1323.     mp_netbuf->idletime.tv_usec = (time % 1000) * 1000;
  1324. }
  1325. void ftplib::SetConnmode(ftplib::ftp mode)
  1326. {
  1327.     if ((mode != ftplib::pasv) && (mode != ftplib::port)) mode = ftplib::defaultconnmode;
  1328.     mp_netbuf->cmode = mode;
  1329. }
  1330. void ftplib::ClearNetbuf()
  1331. {
  1332.     mp_netbuf->dir = FTPLIB_CONTROL;
  1333.     mp_netbuf->ctrl = NULL;
  1334.     mp_netbuf->cmode = ftplib::defaultconnmode;
  1335.     mp_netbuf->idlecb = NULL;
  1336.     mp_netbuf->idletime.tv_sec = mp_netbuf->idletime.tv_usec = 0;
  1337.     mp_netbuf->cbarg = NULL;
  1338.     mp_netbuf->xfered = 0;
  1339.     mp_netbuf->xfered1 = 0;
  1340.     mp_netbuf->cbbytes = 0;
  1341.     mp_netbuf->tlsctrl = 0;
  1342.     mp_netbuf->tlsdata = 0;
  1343.     mp_netbuf->offset = 0;
  1344.     mp_netbuf->handle = 0;
  1345.     mp_netbuf->logcb = NULL;
  1346.     mp_netbuf->xfercb = NULL;
  1347.     mp_netbuf->correctpasv = true;
  1348. }
  1349. int ftplib::CorrectPasvResponse(unsigned int *v)
  1350. {
  1351.     struct sockaddr ipholder;
  1352.     unsigned int ipholder_size = sizeof(ipholder);
  1353.     if (getpeername(mp_netbuf->handle, &ipholder, &ipholder_size) == -1)
  1354.     {
  1355.         perror(“getpeername”);
  1356.         net_close(mp_netbuf->handle);
  1357.         return 0;
  1358.     }
  1359.     for (int i = 2; i < 6; i++) v[i] = ipholder.sa_data[i];
  1360.     return 1;
  1361. }
© 版权声明
THE END
喜欢就支持一下吧,技术咨询可以联系QQ407933975
点赞0
分享
评论 抢沙发
CPPKU的头像-cppku-C++库

昵称

取消
昵称表情代码图片