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

📄 ftp-basic.c

📁 Wget很好的处理了http和ftp的下载,很值得学习的经典代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* Parse the response.  */  s = respline;  for (s += 4; *s && !ISDIGIT (*s); s++)    ;  if (!*s)    return FTPINVPASV;  /* First, get the address family */  af = 0;  for (; ISDIGIT (*s); s++)    af = (*s - '0') + 10 * af;  if (af != 4 && af != 6)    {      xfree (respline);      return FTPINVPASV;    }  if (!*s || *s++ != ',')    {      xfree (respline);      return FTPINVPASV;    }  /* Then, get the address length */  addrlen = 0;  for (; ISDIGIT (*s); s++)    addrlen = (*s - '0') + 10 * addrlen;  if (!*s || *s++ != ',')    {      xfree (respline);      return FTPINVPASV;    }  if (addrlen > 16)    {      xfree (respline);      return FTPINVPASV;    }  if ((af == 4 && addrlen != 4)      || (af == 6 && addrlen != 16))    {      xfree (respline);      return FTPINVPASV;    }  /* Now, we get the actual address */  for (i = 0; i < addrlen; i++)    {      tmp[i] = 0;      for (; ISDIGIT (*s); s++)        tmp[i] = (*s - '0') + 10 * tmp[i];      if (*s == ',')        s++;      else        {          xfree (respline);          return FTPINVPASV;        }    }  /* Now, get the port length */  portlen = 0;  for (; ISDIGIT (*s); s++)    portlen = (*s - '0') + 10 * portlen;  if (!*s || *s++ != ',')    {      xfree (respline);      return FTPINVPASV;    }  if (portlen > 2)    {      xfree (respline);      return FTPINVPASV;    }  /* Finally, we get the port number */  tmpprt[0] = 0;  for (; ISDIGIT (*s); s++)    tmpprt[0] = (*s - '0') + 10 * tmpprt[0];  if (!*s || *s++ != ',')    {      xfree (respline);      return FTPINVPASV;    }  tmpprt[1] = 0;  for (; ISDIGIT (*s); s++)    tmpprt[1] = (*s - '0') + 10 * tmpprt[1];  assert (s != NULL);  if (af == 4)    {      addr->family = AF_INET;      memcpy (IP_INADDR_DATA (addr), tmp, 4);      *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];      DEBUGP (("lpsv addr is: %s\n", print_address(addr)));      DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));      DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));      DEBUGP (("*port is: %d\n", *port));    }  else    {      assert (af == 6);      addr->family = AF_INET6;      memcpy (IP_INADDR_DATA (addr), tmp, 16);      *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];      DEBUGP (("lpsv addr is: %s\n", print_address(addr)));      DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));      DEBUGP (("tmpprt[1] is: %d\n", tmpprt[1]));      DEBUGP (("*port is: %d\n", *port));    }  xfree (respline);  return FTPOK;}/* Similar to ftp_eprt, but uses `EPSV' to initiate the passive FTP   transfer.  Reads the response from server and parses it.  Reads the   host and port addresses and returns them.  */uerr_tftp_epsv (int csock, ip_address *ip, int *port){  char *request, *respline, *start, delim, *s;  int nwritten, i;  uerr_t err;  int tport;  assert (ip != NULL);  assert (port != NULL);  /* IP already contains the IP address of the control connection's     peer, so we don't need to call socket_ip_address here.  */  /* Form the request.  */  /* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */  request = ftp_request ("EPSV", (ip->family == AF_INET ? "1" : "2"));  /* And send it.  */  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      return WRITEFAILED;    }  xfree (request);  /* Get the server response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    return err;  if (*respline != '2')    {      xfree (respline);      return FTPNOPASV;    }    assert (respline != NULL);  DEBUGP(("respline is %s\n", respline));  /* Parse the response.  */  s = respline;  /* Skip the useless stuff and get what's inside the parentheses */  start = strchr (respline, '(');  if (start == NULL)    {      xfree (respline);      return FTPINVPASV;    }    /* Skip the first two void fields */  s = start + 1;  delim = *s++;  if (delim < 33 || delim > 126)    {      xfree (respline);      return FTPINVPASV;    }    for (i = 0; i < 2; i++)    {      if (*s++ != delim)         {          xfree (respline);        return FTPINVPASV;        }      }  /* Finally, get the port number */  tport = 0;   for (i = 1; ISDIGIT (*s); s++)     {      if (i > 5)        {          xfree (respline);          return FTPINVPASV;        }        tport = (*s - '0') + 10 * tport;    }  /* Make sure that the response terminates correcty */  if (*s++ != delim)    {      xfree (respline);      return FTPINVPASV;    }    if (*s++ != ')')    {      xfree (respline);      return FTPINVPASV;    }    *port = tport;  xfree (respline);  return FTPOK;}#endif/* Sends the TYPE request to the server.  */uerr_tftp_type (int csock, int type){  char *request, *respline;  int nwritten;  uerr_t err;  char stype[2];  /* Construct argument.  */  stype[0] = type;  stype[1] = 0;  /* Send TYPE request.  */  request = ftp_request ("TYPE", stype);  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      return WRITEFAILED;    }  xfree (request);  /* Get appropriate response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    return err;  if (*respline != '2')    {      xfree (respline);      return FTPUNKNOWNTYPE;    }  xfree (respline);  /* All OK.  */  return FTPOK;}/* Changes the working directory by issuing a CWD command to the   server.  */uerr_tftp_cwd (int csock, const char *dir){  char *request, *respline;  int nwritten;  uerr_t err;  /* Send CWD request.  */  request = ftp_request ("CWD", dir);  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      return WRITEFAILED;    }  xfree (request);  /* Get appropriate response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    return err;  if (*respline == '5')    {      xfree (respline);      return FTPNSFOD;    }  if (*respline != '2')    {      xfree (respline);      return FTPRERR;    }  xfree (respline);  /* All OK.  */  return FTPOK;}/* Sends REST command to the FTP server.  */uerr_tftp_rest (int csock, wgint offset){  char *request, *respline;  int nwritten;  uerr_t err;  request = ftp_request ("REST", number_to_static_string (offset));  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      return WRITEFAILED;    }  xfree (request);  /* Get appropriate response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    return err;  if (*respline != '3')    {      xfree (respline);      return FTPRESTFAIL;    }  xfree (respline);  /* All OK.  */  return FTPOK;}/* Sends RETR command to the FTP server.  */uerr_tftp_retr (int csock, const char *file){  char *request, *respline;  int nwritten;  uerr_t err;  /* Send RETR request.  */  request = ftp_request ("RETR", file);  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      return WRITEFAILED;    }  xfree (request);  /* Get appropriate response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    return err;  if (*respline == '5')    {      xfree (respline);      return FTPNSFOD;    }  if (*respline != '1')    {      xfree (respline);      return FTPRERR;    }  xfree (respline);  /* All OK.  */  return FTPOK;}/* Sends the LIST command to the server.  If FILE is NULL, send just   `LIST' (no space).  */uerr_tftp_list (int csock, const char *file){  char *request, *respline;  int nwritten;  uerr_t err;  bool ok = false;  int i = 0;  /* Try `LIST -a' first and revert to `LIST' in case of failure.  */  const char *list_commands[] = { "LIST -a",                                   "LIST" };  do {    /* Send request.  */    request = ftp_request (list_commands[i], file);    nwritten = fd_write (csock, request, strlen (request), -1);    if (nwritten < 0)      {        xfree (request);        return WRITEFAILED;      }    xfree (request);    /* Get appropriate response.  */    err = ftp_response (csock, &respline);    if (err == FTPOK)      {        if (*respline == '5')          {            err = FTPNSFOD;          }        else if (*respline == '1')          {            err = FTPOK;            ok = true;          }        else           {            err = FTPRERR;          }        xfree (respline);      }    ++i;  } while (i < countof (list_commands) && !ok);    return err;}/* Sends the SYST command to the server. */uerr_tftp_syst (int csock, enum stype *server_type){  char *request, *respline;  int nwritten;  uerr_t err;  /* Send SYST request.  */  request = ftp_request ("SYST", NULL);  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      return WRITEFAILED;    }  xfree (request);  /* Get appropriate response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    return err;  if (*respline == '5')    {      xfree (respline);      return FTPSRVERR;    }  /* Skip the number (215, but 200 (!!!) in case of VMS) */  strtok (respline, " ");  /* Which system type has been reported (we are interested just in the     first word of the server response)?  */  request = strtok (NULL, " ");  if (request == NULL)    *server_type = ST_OTHER;  else if (!strcasecmp (request, "VMS"))    *server_type = ST_VMS;  else if (!strcasecmp (request, "UNIX"))    *server_type = ST_UNIX;  else if (!strcasecmp (request, "WINDOWS_NT")           || !strcasecmp (request, "WINDOWS2000"))    *server_type = ST_WINNT;  else if (!strcasecmp (request, "MACOS"))    *server_type = ST_MACOS;  else if (!strcasecmp (request, "OS/400"))    *server_type = ST_OS400;  else    *server_type = ST_OTHER;  xfree (respline);  /* All OK.  */  return FTPOK;}/* Sends the PWD command to the server. */uerr_tftp_pwd (int csock, char **pwd){  char *request, *respline;  int nwritten;  uerr_t err;  /* Send PWD request.  */  request = ftp_request ("PWD", NULL);  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      return WRITEFAILED;    }  xfree (request);  /* Get appropriate response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    return err;  if (*respline == '5')    {    err:      xfree (respline);      return FTPSRVERR;    }  /* Skip the number (257), leading citation mark, trailing citation mark     and everything following it. */  strtok (respline, "\"");  request = strtok (NULL, "\"");  if (!request)    /* Treat the malformed response as an error, which the caller has       to handle gracefully anyway.  */    goto err;  /* Has the `pwd' been already allocated?  Free! */  xfree_null (*pwd);  *pwd = xstrdup (request);  xfree (respline);  /* All OK.  */  return FTPOK;}/* Sends the SIZE command to the server, and returns the value in 'size'. * If an error occurs, size is set to zero. */uerr_tftp_size (int csock, const char *file, wgint *size){  char *request, *respline;  int nwritten;  uerr_t err;  /* Send PWD request.  */  request = ftp_request ("SIZE", file);  nwritten = fd_write (csock, request, strlen (request), -1);  if (nwritten < 0)    {      xfree (request);      *size = 0;      return WRITEFAILED;    }  xfree (request);  /* Get appropriate response.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    {      *size = 0;      return err;    }  if (*respline == '5')    {      /*        * Probably means SIZE isn't supported on this server.       * Error is nonfatal since SIZE isn't in RFC 959        */      xfree (respline);      *size = 0;      return FTPOK;    }  errno = 0;  *size = str_to_wgint (respline + 4, NULL, 10);  if (errno)    {      /*        * Couldn't parse the response for some reason.  On the (few)       * tests I've done, the response is 213 <SIZE> with nothing else -       * maybe something a bit more resilient is necessary.  It's not a       * fatal error, however.       */      xfree (respline);      *size = 0;      return FTPOK;    }  xfree (respline);  /* All OK.  */  return FTPOK;}/* If URL's params are of the form "type=X", return character X.   Otherwise, return 'I' (the default type).  */charftp_process_type (const char *params){  if (params      && 0 == strncasecmp (params, "type=", 5)      && params[5] != '\0')    return TOUPPER (params[5]);  else    return 'I';}

⌨️ 快捷键说明

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