⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.c

📁 harvest是一个下载html网页得机器人
💻 C
📖 第 1 页 / 共 5 页
字号:
    }  }  else {    failf(data, "could't find my own IP address (%s)", myhost);    return CURLE_FTP_PORT_FAILED;  }  {#ifdef HAVE_INET_NTOA_R    char ntoa_buf[64];#endif    struct in_addr in;    unsigned short ip[5];    (void) memcpy(&in.s_addr,                  h?*h->addr->h_addr_list:(char *)&sa.sin_addr.s_addr,                  sizeof (in.s_addr));#ifdef HAVE_INET_NTOA_R    /* ignore the return code from inet_ntoa_r() as it is int or       char * depending on system */    inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf));    sscanf( ntoa_buf, "%hu.%hu.%hu.%hu",            &ip[0], &ip[1], &ip[2], &ip[3]);#else    sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu",            &ip[0], &ip[1], &ip[2], &ip[3]);#endif    infof(data, "Telling server to connect to %d.%d.%d.%d:%d\n",          ip[0], ip[1], ip[2], ip[3], porttouse);      result=Curl_ftpsendf(conn, "PORT %d,%d,%d,%d,%d,%d",                         ip[0], ip[1], ip[2], ip[3],                         porttouse >> 8,                         porttouse & 255);    if(result)      return result;  }  result = Curl_GetFTPResponse(&nread, conn, &ftpcode);  if(result)    return result;  if(ftpcode != 200) {    failf(data, "Server does not grok PORT, try without it!");    return CURLE_FTP_PORT_FAILED;  }#endif /* end of ipv4-specific code */  return CURLE_OK;}/*********************************************************************** * * ftp_use_pasv() * * Send the PASV command. PASV is the ftp client's way of asking the server to * open a second port that we can connect to (for the data transfer). This is * the opposite of PORT. */staticCURLcode ftp_use_pasv(struct connectdata *conn,                      bool *connected){  struct SessionHandle *data = conn->data;  ssize_t nread;  char *buf = data->state.buffer; /* this is our buffer */  int ftpcode; /* receive FTP response codes in this */  CURLcode result;  struct Curl_dns_entry *addr=NULL;  Curl_ipconnect *conninfo;  int rc;  /*    Here's the excecutive summary on what to do:    PASV is RFC959, expect:    227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)    LPSV is RFC1639, expect:    228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)    EPSV is RFC2428, expect:    229 Entering Extended Passive Mode (|||port|)  */#if 1  const char *mode[] = { "EPSV", "PASV", NULL };  int results[] = { 229, 227, 0 };#else#if 0  char *mode[] = { "EPSV", "LPSV", "PASV", NULL };  int results[] = { 229, 228, 227, 0 };#else  const char *mode[] = { "PASV", NULL };  int results[] = { 227, 0 };#endif#endif  int modeoff;  unsigned short connectport; /* the local port connect() should use! */  unsigned short newport=0; /* remote port, not necessary the local one */    /* newhost must be able to hold a full IP-style address in ASCII, which     in the IPv6 case means 5*8-1 = 39 letters */  char newhost[48];  char *newhostp=NULL;    for (modeoff = (data->set.ftp_use_epsv?0:1);       mode[modeoff]; modeoff++) {    result = Curl_ftpsendf(conn, "%s", mode[modeoff]);    if(result)      return result;    result = Curl_GetFTPResponse(&nread, conn, &ftpcode);    if(result)      return result;    if (ftpcode == results[modeoff])      break;  }  if (!mode[modeoff]) {    failf(data, "Odd return code after PASV");    return CURLE_FTP_WEIRD_PASV_REPLY;  }  else if (227 == results[modeoff]) {    int ip[4];    int port[2];    char *str=buf;    /*     * New 227-parser June 3rd 1999.     * It now scans for a sequence of six comma-separated numbers and     * will take them as IP+port indicators.     *     * Found reply-strings include:     * "227 Entering Passive Mode (127,0,0,1,4,51)"     * "227 Data transfer will passively listen to 127,0,0,1,4,51"     * "227 Entering passive mode. 127,0,0,1,4,51"     */          while(*str) {      if (6 == sscanf(str, "%d,%d,%d,%d,%d,%d",                      &ip[0], &ip[1], &ip[2], &ip[3],                      &port[0], &port[1]))        break;      str++;    }    if(!*str) {      failf(data, "Couldn't interpret this 227-reply: %s", buf);      return CURLE_FTP_WEIRD_227_FORMAT;    }    sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);    newhostp = newhost;    newport = (port[0]<<8) + port[1];  }#if 1  else if (229 == results[modeoff]) {    char *ptr = strchr(buf, '(');    if(ptr) {      unsigned int num;      char separator[4];      ptr++;      if(5  == sscanf(ptr, "%c%c%c%u%c",                      &separator[0],                      &separator[1],                      &separator[2],                      &num,                      &separator[3])) {        /* the four separators should be identical */        newport = num;        /* we should use the same host we already are connected to */        newhostp = conn->name;      }                            else        ptr=NULL;    }    if(!ptr) {      failf(data, "Weirdly formatted EPSV reply");      return CURLE_FTP_WEIRD_PASV_REPLY;    }  }#endif  else    return CURLE_FTP_CANT_RECONNECT;  if(data->change.proxy && *data->change.proxy) {    /*     * This is a tunnel through a http proxy and we need to connect to the     * proxy again here.     *     * We don't want to rely on a former host lookup that might've expired     * now, instead we remake the lookup here and now!     */    rc = Curl_resolv(conn, conn->proxyhost, conn->port, &addr);    if(rc == 1)      rc = Curl_wait_for_resolv(conn, &addr);    connectport =      (unsigned short)conn->port; /* we connect to the proxy's port */      }  else {    /* normal, direct, ftp connection */    rc = Curl_resolv(conn, newhostp, newport, &addr);    if(rc == 1)      rc = Curl_wait_for_resolv(conn, &addr);    if(!addr) {      failf(data, "Can't resolve new host %s:%d", newhostp, newport);      return CURLE_FTP_CANT_GET_HOST;    }    connectport = newport; /* we connect to the remote port */  }      result = Curl_connecthost(conn,                            addr,                            connectport,                            &conn->secondarysocket,                            &conninfo,                            connected);  Curl_resolv_unlock(data, addr); /* we're done using this address */  if(result)    return result;  /*   * When this is used from the multi interface, this might've returned with   * the 'connected' set to FALSE and thus we are now awaiting a non-blocking   * connect to connect and we should not be "hanging" here waiting.   */    if(data->set.verbose)    /* this just dumps information about this second connection */    ftp_pasv_verbose(conn, conninfo, newhostp, connectport);    if (data->set.tunnel_thru_httpproxy) {    /* We want "seamless" FTP operations through HTTP proxy tunnel */    result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,                                         newhostp, newport);    if(CURLE_OK != result)      return result;  }  return CURLE_OK;}/* * Curl_ftp_nextconnect() * * This function shall be called when the second FTP connection has been * established and is confirmed connected. */CURLcode Curl_ftp_nextconnect(struct connectdata *conn){  struct SessionHandle *data=conn->data;  char *buf = data->state.buffer; /* this is our buffer */  CURLcode result;  ssize_t nread;  int ftpcode; /* for ftp status */  /* the ftp struct is already inited in Curl_ftp_connect() */  struct FTP *ftp = conn->proto.ftp;  long *bytecountp = ftp->bytecountp;  if(data->set.upload) {    /* Set type to binary (unless specified ASCII) */    result = ftp_transfertype(conn, data->set.ftp_ascii);    if(result)      return result;    /* Send any PREQUOTE strings after transfer type is set? (Wesley Laxton)*/    if(data->set.prequote) {      if ((result = ftp_sendquote(conn, data->set.prequote)) != CURLE_OK)        return result;    }    if(conn->resume_from) {      /* we're about to continue the uploading of a file */      /* 1. get already existing file's size. We use the SIZE         command for this which may not exist in the server!         The SIZE command is not in RFC959. */      /* 2. This used to set REST. But since we can do append, we         don't another ftp command. We just skip the source file         offset and then we APPEND the rest on the file instead */      /* 3. pass file-size number of bytes in the source file */      /* 4. lower the infilesize counter */      /* => transfer as usual */      if(conn->resume_from < 0 ) {        /* we could've got a specified offset from the command line,           but now we know we didn't */        ssize_t gottensize;        if(CURLE_OK != ftp_getsize(conn, ftp->file, &gottensize)) {          failf(data, "Couldn't get remote file size");          return CURLE_FTP_COULDNT_GET_SIZE;        }        conn->resume_from = gottensize;      }      if(conn->resume_from) {        /* do we still game? */        int passed=0;        /* enable append instead */        data->set.ftp_append = 1;        /* Now, let's read off the proper amount of bytes from the           input. If we knew it was a proper file we could've just           fseek()ed but we only have a stream here */        do {          int readthisamountnow = (conn->resume_from - passed);          int actuallyread;          if(readthisamountnow > BUFSIZE)            readthisamountnow = BUFSIZE;          actuallyread =            conn->fread(data->state.buffer, 1, readthisamountnow,                        conn->fread_in);          passed += actuallyread;          if(actuallyread != readthisamountnow) {            failf(data, "Could only read %d bytes from the input", passed);            return CURLE_FTP_COULDNT_USE_REST;          }        }        while(passed != conn->resume_from);        /* now, decrease the size of the read */        if(data->set.infilesize>0) {          data->set.infilesize -= conn->resume_from;          if(data->set.infilesize <= 0) {            infof(data, "File already completely uploaded\n");            /* no data to transfer */            result=Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);                        /* Set no_transfer so that we won't get any error in             * Curl_ftp_done() because we didn't transfer anything! */            ftp->no_transfer = TRUE;             return CURLE_OK;          }        }        /* we've passed, proceed as normal */      }    }    /* Send everything on data->state.in to the socket */    if(data->set.ftp_append) {      /* we append onto the file instead of rewriting it */      FTPSENDF(conn, "APPE %s", ftp->file);    }    else {      FTPSENDF(conn, "STOR %s", ftp->file);    }    result = Curl_GetFTPResponse(&nread, conn, &ftpcode);    if(result)      return result;    if(ftpcode>=400) {      failf(data, "Failed FTP upload:%s", buf+3);      /* oops, we never close the sockets! */      return CURLE_FTP_COULDNT_STOR_FILE;    }    if(data->set.ftp_use_port) {      /* PORT means we are now awaiting the server to connect to us. */      result = AllowServerConnect(data, conn, conn->secondarysocket);      if( result )        return result;    }    *bytecountp=0;    /* When we know we're uploading a specified file, we can get the file       size prior to the actual upload. */    Curl_pgrsSetUploadSize(data, data->set.infilesize);    result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */                      conn->secondarysocket, bytecountp);    if(result)      return result;        }  else if(!data->set.no_body) {    /* Retrieve file or directory */    bool dirlist=FALSE;    long downloadsize=-1;    if(conn->bits.use_range && conn->range) {      long from, to;      int totalsize=-1;      char *ptr;      char *ptr2;      from=strtol(conn->range, &ptr, 0);      while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-')))        ptr++;      to=strtol(ptr, &ptr2, 0);      if(ptr == ptr2) {        /* we didn't get any digit */        to=-1;      }      if((-1 == to) && (from>=0)) {        /* X - */        conn->resume_from = from;        infof(data, "FTP RANGE %d to end of file\n", from);      }      else if(from < 0) {        /* -Y */        totalsize = -from;        conn->maxdownload = -from;        conn->resume_from = from;        infof(data, "FTP RANGE the last %d bytes\n", totalsize);      }      else {        /* X-Y */        totalsize = to-from;        conn->maxdownload = totalsize+1; /* include the last mentioned byte */        conn->resume_from = from;        infof(data, "FTP RANGE from %d getting %d bytes\n", from,              conn->maxdownload);      }      infof(data, "range-download from %d to %d, totally %d bytes\n",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -