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

📄 ftp.c

📁 harvest是一个下载html网页得机器人
💻 C
📖 第 1 页 / 共 5 页
字号:
/*************************************************************************** *                                  _   _ ____  _      *  Project                     ___| | | |  _ \| |     *                             / __| | | | |_) | |     *                            | (__| |_| |  _ <| |___  *                             \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. *  * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id: ftp.c,v 1.207 2003/10/31 21:36:43 bagder Exp $ ***************************************************************************/#include "setup.h"#ifndef CURL_DISABLE_FTP#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#include <ctype.h>#include <errno.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)#else /* some kind of unix */#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#include <sys/types.h>#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#include <sys/utsname.h>#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef	VMS#include <in.h>#include <inet.h>#endif#endif#if defined(WIN32) && defined(__GNUC__) || defined(__MINGW32__)#include <errno.h>#endif#include <curl/curl.h>#include "urldata.h"#include "sendf.h"#include "if2ip.h"#include "hostip.h"#include "progress.h"#include "transfer.h"#include "escape.h"#include "http.h" /* for HTTP proxy tunnel stuff */#include "ftp.h"#ifdef KRB4#include "security.h"#include "krb4.h"#endif#include "strequal.h"#include "ssluse.h"#include "connect.h"#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)#include "inet_ntoa_r.h"#endif#define _MPRINTF_REPLACE /* use our functions only */#include <curl/mprintf.h>/* The last #include file should be: */#ifdef CURLDEBUG#include "memdebug.h"#endif/* Local API functions */static CURLcode ftp_sendquote(struct connectdata *conn,                              struct curl_slist *quote);static CURLcode ftp_cwd(struct connectdata *conn, char *path);static CURLcode ftp_mkd(struct connectdata *conn, char *path);static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);/* easy-to-use macro: */#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return resultstatic void freedirs(struct FTP *ftp){  int i;  for (i=0; ftp->dirs[i]; i++){    free(ftp->dirs[i]);    ftp->dirs[i]=NULL;  }}/*********************************************************************** * * AllowServerConnect() * * When we've issue the PORT command, we have told the server to connect * to us. This function will sit and wait here until the server has * connected. * */static CURLcode AllowServerConnect(struct SessionHandle *data,                                   struct connectdata *conn,                                   int sock){  fd_set rdset;  struct timeval dt;    FD_ZERO(&rdset);  FD_SET(sock, &rdset);  /* we give the server 10 seconds to connect to us */  dt.tv_sec = 10;  dt.tv_usec = 0;  switch (select(sock+1, &rdset, NULL, NULL, &dt)) {  case -1: /* error */    /* let's die here */    failf(data, "Error while waiting for server connect");    return CURLE_FTP_PORT_FAILED;  case 0:  /* timeout */    /* let's die here */    failf(data, "Timeout while waiting for server connect");    return CURLE_FTP_PORT_FAILED;  default:    /* we have received data here */    {      int s;      size_t size = sizeof(struct sockaddr_in);      struct sockaddr_in add;      getsockname(sock, (struct sockaddr *) &add, (socklen_t *)&size);      s=accept(sock, (struct sockaddr *) &add, (socklen_t *)&size);      sclose(sock); /* close the first socket */      if (-1 == s) {        /* DIE! */        failf(data, "Error accept()ing server connect");      	return CURLE_FTP_PORT_FAILED;      }      infof(data, "Connection accepted from server\n");      conn->secondarysocket = s;      Curl_nonblock(s, TRUE); /* enable non-blocking */    }    break;  }  return CURLE_OK;}/* --- parse FTP server responses --- *//* * Curl_GetFTPResponse() is supposed to be invoked after each command sent to * a remote FTP server. This function will wait and read all lines of the * response and extract the relevant return code for the invoking function. */CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */                             struct connectdata *conn,                             int *ftpcode) /* return the ftp-code */{  /* Brand new implementation.   * We cannot read just one byte per read() and then go back to select()   * as it seems that the OpenSSL read() stuff doesn't grok that properly.   *   * Alas, read as much as possible, split up into lines, use the ending   * line in a response or continue reading.  */  int sockfd = conn->firstsocket;  int perline; /* count bytes per line */  bool keepon=TRUE;  ssize_t gotbytes;  char *ptr;  int timeout;              /* timeout in seconds */  struct timeval interval;  fd_set rkeepfd;  fd_set readfd;  struct SessionHandle *data = conn->data;  char *line_start;  int code=0; /* default ftp "error code" to return */  char *buf = data->state.buffer;  CURLcode result = CURLE_OK;  struct FTP *ftp = conn->proto.ftp;  struct timeval now = Curl_tvnow();  if (ftpcode)    *ftpcode = 0; /* 0 for errors */  FD_ZERO (&readfd);		/* clear it */  FD_SET (sockfd, &readfd);     /* read socket */  /* get this in a backup variable to be able to restore it on each lap in the     select() loop */  rkeepfd = readfd;  ptr=buf;  line_start = buf;  *nreadp=0;  perline=0;  keepon=TRUE;  while((*nreadp<BUFSIZE) && (keepon && !result)) {    /* check and reset timeout value every lap */    if(data->set.ftp_response_timeout )      /* if CURLOPT_FTP_RESPONSE_TIMEOUT is set, use that to determine         remaining time.  Also, use "now" as opposed to "conn->now"         because ftp_response_timeout is only supposed to govern         the response for any given ftp response, not for the time         from connect to the given ftp response. */      timeout = data->set.ftp_response_timeout - /* timeout time */        Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */    else if(data->set.timeout)      /* if timeout is requested, find out how much remaining time we have */      timeout = data->set.timeout - /* timeout time */        Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */    else      /* Even without a requested timeout, we only wait response_time         seconds for the full response to arrive before we bail out */      timeout = ftp->response_time -        Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */    if(timeout <=0 ) {      failf(data, "Transfer aborted due to timeout");      return CURLE_OPERATION_TIMEDOUT; /* already too little time */    }    if(!ftp->cache) {      readfd = rkeepfd;		   /* set every lap */      interval.tv_sec = 1; /* use 1 second timeout intervals */      interval.tv_usec = 0;      switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) {      case -1: /* select() error, stop reading */        result = CURLE_RECV_ERROR;        failf(data, "Transfer aborted due to select() error: %d", errno);        break;      case 0: /* timeout */        if(Curl_pgrsUpdate(conn))          return CURLE_ABORTED_BY_CALLBACK;        continue; /* just continue in our loop for the timeout duration */      default:        break;      }    }    if(CURLE_OK == result) {      /*       * This code previously didn't use the kerberos sec_read() code       * to read, but when we use Curl_read() it may do so. Do confirm       * that this is still ok and then remove this comment!       */      if(ftp->cache) {        /* we had data in the "cache", copy that instead of doing an actual           read */        memcpy(ptr, ftp->cache, ftp->cache_size);        gotbytes = ftp->cache_size;        free(ftp->cache);    /* free the cache */        ftp->cache = NULL;   /* clear the pointer */        ftp->cache_size = 0; /* zero the size just in case */      }      else {        int res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp, &gotbytes);        if(res < 0)          /* EWOULDBLOCK */          continue; /* go looping again */        if(CURLE_OK != res)          keepon = FALSE;      }      if(!keepon)        ;      else if(gotbytes <= 0) {        keepon = FALSE;        result = CURLE_RECV_ERROR;        failf(data, "Connection aborted");      }      else {        /* we got a whole chunk of data, which can be anything from one         * byte to a set of lines and possible just a piece of the last         * line */        int i;        *nreadp += gotbytes;        for(i = 0; i < gotbytes; ptr++, i++) {          perline++;          if(*ptr=='\n') {            /* a newline is CRLF in ftp-talk, so the CR is ignored as               the line isn't really terminated until the LF comes */            /* output debug output if that is requested */            if(data->set.verbose)              Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline);            /*             * We pass all response-lines to the callback function registered             * for "headers". The response lines can be seen as a kind of             * headers.             */            result = Curl_client_write(data, CLIENTWRITE_HEADER,                                       line_start, perline);            if(result)              return result;                                       #define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \			isdigit((int)line[2]) && (' ' == line[3]))            if(perline>3 && lastline(line_start)) {              /* This is the end of the last line, copy the last               * line to the start of the buffer and zero terminate,               * for old times sake (and krb4)! */              char *meow;              int n;              for(meow=line_start, n=0; meow<ptr; meow++, n++)                buf[n] = *meow;              *meow=0; /* zero terminate */              keepon=FALSE;              line_start = ptr+1; /* advance pointer */              i++; /* skip this before getting out */              break;            }            perline=0; /* line starts over here */            line_start = ptr+1;          }        }        if(!keepon && (i != gotbytes)) {          /* We found the end of the response lines, but we didn't parse the             full chunk of data we have read from the server. We therefore             need to store the rest of the data to be checked on the next             invoke as it may actually contain another end of response             already!  Cleverly figured out by Eric Lavigne in December             2001. */          ftp->cache_size = gotbytes - i;          ftp->cache = (char *)malloc(ftp->cache_size);          if(ftp->cache)            memcpy(ftp->cache, line_start, ftp->cache_size);          else            return CURLE_OUT_OF_MEMORY; /**BANG**/        }      } /* there was data */    } /* if(no error) */  } /* while there's buffer left and loop is requested */  if(!result)    code = atoi(buf);#ifdef KRB4  /* handle the security-oriented responses 6xx ***/  /* FIXME: some errorchecking perhaps... ***/  switch(code) {  case 631:    Curl_sec_read_msg(conn, buf, prot_safe);    break;  case 632:    Curl_sec_read_msg(conn, buf, prot_private);    break;  case 633:    Curl_sec_read_msg(conn, buf, prot_confidential);    break;  default:    /* normal ftp stuff we pass through! */    break;  }#endif  if(ftpcode)    *ftpcode=code; /* return the initial number like this */  /* store the latest code for later retrieval */  conn->data->info.httpcode=code;  return result;}/* * Curl_ftp_connect() should do everything that is to be considered a part of * the connection phase. */CURLcode Curl_ftp_connect(struct connectdata *conn){  /* this is FTP and no proxy */  ssize_t nread;  struct SessionHandle *data=conn->data;  char *buf = data->state.buffer; /* this is our buffer */  struct FTP *ftp;  CURLcode result;  int ftpcode;  ftp = (struct FTP *)malloc(sizeof(struct FTP));  if(!ftp)    return CURLE_OUT_OF_MEMORY;  memset(ftp, 0, sizeof(struct FTP));  conn->proto.ftp = ftp;  /* We always support persistant connections on ftp */  conn->bits.close = FALSE;  /* get some initial data into the ftp struct */  ftp->bytecountp = &conn->bytecount;  /* no need to duplicate them, this connectdata struct won't change */  ftp->user = conn->user;

⌨️ 快捷键说明

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