rfc2068.c
上传用户:tjfeida
上传日期:2013-03-10
资源大小:1917k
文件大小:22k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. /*****************************************************************************/
  2. /*  rfc2068.c - General purpose routines for the HTTP protocol               */
  3. /*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
  4. /*                                                                           */
  5. /*  This program is free software; you can redistribute it and/or modify     */
  6. /*  it under the terms of the GNU General Public License as published by     */
  7. /*  the Free Software Foundation; either version 2 of the License, or        */
  8. /*  (at your option) any later version.                                      */
  9. /*                                                                           */
  10. /*  This program is distributed in the hope that it will be useful,          */
  11. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  12. /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  13. /*  GNU General Public License for more details.                             */
  14. /*                                                                           */
  15. /*  You should have received a copy of the GNU General Public License        */
  16. /*  along with this program; if not, write to the Free Software              */
  17. /*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
  18. /*****************************************************************************/
  19. #include "gftp.h"
  20. static const char cvsid[] = "$Id: rfc2068.c,v 1.10 2002/11/23 13:45:04 masneyb Exp $";
  21. typedef struct rfc2068_params_tag
  22. {
  23.   unsigned long read_bytes,
  24.                 max_bytes;
  25.   int chunked_transfer : 1;
  26. } rfc2068_params;
  27. static char *
  28. base64_encode (char *str)
  29. {
  30. /* The standard to Base64 encoding can be found in RFC2045 */
  31.   char *newstr, *newpos, *fillpos, *pos;
  32.   unsigned char table[64], encode[3];
  33.   int i, num;
  34.   for (i = 0; i < 26; i++)
  35.     {
  36.       table[i] = 'A' + i;
  37.       table[i + 26] = 'a' + i;
  38.     }
  39.   for (i = 0; i < 10; i++)
  40.     table[i + 52] = '0' + i;
  41.   table[62] = '+';
  42.   table[63] = '-';
  43.   num = strlen (str) / 3;
  44.   if (strlen (str) % 3 > 0)
  45.     num++;
  46.   newstr = g_malloc (num * 4 + 1);
  47.   newstr[num * 4] = '';
  48.   newpos = newstr;
  49.   pos = str;
  50.   while (*pos != '')
  51.     {
  52.       memset (encode, 0, sizeof (encode));
  53.       for (i = 0; i < 3 && *pos != ''; i++)
  54. encode[i] = *pos++;
  55.       fillpos = newpos;
  56.       *newpos++ = table[encode[0] >> 2];
  57.       *newpos++ = table[(encode[0] & 3) << 4 | encode[1] >> 4];
  58.       *newpos++ = table[(encode[1] & 0xF) << 2 | encode[2] >> 6];
  59.       *newpos++ = table[encode[2] & 0x3F];
  60.       while (i < 3)
  61. fillpos[++i] = '=';
  62.     }
  63.   return (newstr);
  64. }
  65. static off_t 
  66. rfc2068_read_response (gftp_request * request)
  67. {
  68.   gftp_getline_buffer * rbuf;
  69.   rfc2068_params * params;
  70.   char tempstr[255];
  71.   params = request->protocol_data;
  72.   params->max_bytes = 0;
  73.   rbuf = NULL;
  74.   if (gftp_get_line (request, &rbuf, tempstr, sizeof (tempstr), 
  75.                      request->sockfd) < 0)
  76.     return (-1);
  77.   if (request->last_ftp_response)
  78.     g_free (request->last_ftp_response);
  79.   request->last_ftp_response = g_malloc (strlen (tempstr) + 1);
  80.   strcpy (request->last_ftp_response, tempstr);
  81.   request->logging_function (gftp_logging_recv, request->user_data, "%s",
  82.                              tempstr);
  83.   params->chunked_transfer = 0;
  84.   while (1) 
  85.     {
  86.       /* Read rest of proxy header */
  87.       if (gftp_get_line (request, &rbuf, tempstr, sizeof (tempstr), 
  88.                          request->sockfd) < 0)
  89. return (-1);
  90.       if (*tempstr == 'r' || *tempstr == 'n')
  91.         break;
  92.       request->logging_function (gftp_logging_recv, request->user_data, "%s",
  93.                                  tempstr);
  94.       if (strncmp (tempstr, "Content-Length:", 15) == 0)
  95. params->max_bytes = strtol (tempstr + 16, NULL, 10);
  96.       if (strncmp (tempstr, "Transfer-Encoding: chunked", 26) == 0)
  97.         params->chunked_transfer = 1;
  98.     }
  99.   return (params->max_bytes);
  100. }
  101. static off_t 
  102. rfc2068_send_command (gftp_request * request, const char *command,
  103.                       const char *extrahdr)
  104. {
  105.   char *tempstr, *str;
  106.   ssize_t ret;
  107.   g_return_val_if_fail (request != NULL, -2);
  108.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  109.   g_return_val_if_fail (command != NULL, -2);
  110.   tempstr = g_strdup_printf ("%sUser-Agent: %snHost: %sn", command,
  111.                              version, request->hostname);
  112.   request->logging_function (gftp_logging_send, request->user_data,
  113.                              "%s", tempstr);
  114.   ret = gftp_write (request, tempstr, strlen (tempstr), request->sockfd);
  115.   g_free (tempstr);
  116.   if (ret < 0)
  117.     return (-1);
  118.   if (request->use_proxy && request->proxy_username != NULL &&
  119.       *request->proxy_username != '')
  120.     {
  121.       tempstr = g_strconcat (request->proxy_username, ":", 
  122.                              request->proxy_password, NULL);
  123.       str = base64_encode (tempstr);
  124.       g_free (tempstr);
  125.       request->logging_function (gftp_logging_send, request->user_data,
  126.                                  "Proxy-authorization: Basic xxxx:xxxxn");
  127.       ret = gftp_writefmt (request, request->sockfd, 
  128.                            "Proxy-authorization: Basic %sn", str);
  129.       g_free (str);
  130.       if (ret < 0)
  131. return (-2);
  132.     }
  133.   if (request->username != NULL && *request->username != '')
  134.     {
  135.       tempstr = g_strconcat (request->username, ":", request->password, NULL);
  136.       str = base64_encode (tempstr);
  137.       g_free (tempstr);
  138.       request->logging_function (gftp_logging_send, request->user_data,
  139.                                  "Authorization: Basic xxxxn");
  140.       ret = gftp_writefmt (request, request->sockfd, 
  141.                            "Authorization: Basic %sn", str);
  142.       g_free (str);
  143.       if (ret < 0)
  144. return (-2);
  145.     }
  146.   if (extrahdr)
  147.     {
  148.       request->logging_function (gftp_logging_send, request->user_data, "%s",
  149.                                  extrahdr);
  150.       if (gftp_write (request, extrahdr, strlen (extrahdr), request->sockfd) < 0)
  151.         return (-1);
  152.     }
  153.   if (gftp_write (request, "n", 1, request->sockfd) < 0)
  154.     return (-1);
  155.   return (rfc2068_read_response (request));
  156. }
  157. static int
  158. rfc2068_connect (gftp_request * request)
  159. {
  160.   char *service;
  161.   g_return_val_if_fail (request != NULL, -2);
  162.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  163.   g_return_val_if_fail (request->hostname != NULL, -2);
  164.   if (request->sockfd > 0)
  165.     return (0);
  166.   service = request->use_proxy && request->proxy_config != NULL && 
  167.             *request->proxy_config != '' ? request->proxy_config : "http";
  168.   if ((request->sockfd = gftp_connect_server (request, service)) < 0)
  169.     return (-1);
  170.   if (request->directory && *request->directory == '')
  171.     {
  172.       g_free (request->directory);
  173.       request->directory = NULL;
  174.     }
  175.   if (!request->directory)
  176.     {
  177.       request->directory = g_malloc (2);
  178.       strcpy (request->directory, "/");
  179.     }
  180.   return (0);
  181. }
  182. static void
  183. rfc2068_disconnect (gftp_request * request)
  184. {
  185.   g_return_if_fail (request != NULL);
  186.   g_return_if_fail (request->protonum == GFTP_HTTP_NUM);
  187.   if (request->sockfd > 0)
  188.     {
  189.       request->logging_function (gftp_logging_misc, request->user_data,
  190.  _("Disconnecting from site %sn"),
  191.  request->hostname);
  192.       if (close (request->sockfd) < 0)
  193.         request->logging_function (gftp_logging_error, request->user_data,
  194.                                    _("Error closing file descriptor: %sn"),
  195.                                    g_strerror (errno));
  196.       request->sockfd = -1;
  197.     }
  198. }
  199. static off_t
  200. rfc2068_get_file (gftp_request * request, const char *filename, int fd,
  201.                   off_t startsize)
  202. {
  203.   char *tempstr, *extrahdr, *pos, *proto;
  204.   int restarted;
  205.   off_t size;
  206.   g_return_val_if_fail (request != NULL, -2);
  207.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  208.   g_return_val_if_fail (filename != NULL, -2);
  209.   if (fd > 0)
  210.     request->sockfd = fd;
  211.   if (request->sockfd < 0 && rfc2068_connect (request) != 0)
  212.     return (-2);
  213.   if (request->proxy_config != NULL && *request->proxy_config != '')
  214.     proto = request->proxy_config;
  215.   else
  216.     proto = "http";
  217.   if (request->username == NULL || *request->username == '')
  218.     tempstr = g_strconcat ("GET ", proto, "://", 
  219.                      request->hostname, "/", filename, 
  220.                      use_http11 ? " HTTP/1.1n" : " HTTP/1.0n", NULL);
  221.   else 
  222.     tempstr = g_strconcat ("GET ", proto, "://", 
  223.                      request->username, "@", request->hostname, "/", filename, 
  224.                      use_http11 ? " HTTP/1.1n" : " HTTP/1.0n", NULL);
  225.   if ((pos = strstr (tempstr, "://")) != NULL)
  226.     remove_double_slashes (pos + 3);
  227.   else
  228.     remove_double_slashes (tempstr);
  229.   if (!use_http11 || startsize == 0)
  230.     extrahdr = NULL;
  231.   else
  232.     {
  233. #if defined (_LARGEFILE_SOURCE)
  234.       extrahdr = g_strdup_printf ("Range: bytes=%lld-n", startsize);
  235.       request->logging_function (gftp_logging_misc, request->user_data,
  236.                               _("Starting the file transfer at offset %lldn"),
  237.                               startsize);
  238. #else
  239.       extrahdr = g_strdup_printf ("Range: bytes=%ld-n", startsize);
  240.       request->logging_function (gftp_logging_misc, request->user_data,
  241.        _("Starting the file transfer at offset %ldn"), 
  242.                                startsize);
  243. #endif
  244.     }
  245.   size = rfc2068_send_command (request, tempstr, extrahdr);
  246.   g_free (tempstr);
  247.   if (extrahdr)
  248.     g_free (extrahdr);
  249.   if (size < 0)
  250.     return (-1);
  251.   restarted = 0;
  252.   if (strlen (request->last_ftp_response) > 9 
  253.       && strncmp (request->last_ftp_response + 9, "206", 3) == 0)
  254.     restarted = 1;
  255.   else if (strlen (request->last_ftp_response) < 9 ||
  256.            strncmp (request->last_ftp_response + 9, "200", 3) != 0)
  257.     {
  258.       request->logging_function (gftp_logging_error, request->user_data,
  259.          _("Cannot retrieve file %sn"), filename);
  260.       return (-2);
  261.     }
  262.   return (restarted ? size + startsize : size);
  263. }
  264. static ssize_t
  265. rfc2068_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
  266. {
  267.   rfc2068_params * params;
  268.   size_t len;
  269.   g_return_val_if_fail (request != NULL, -2);
  270.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  271.   params = request->protocol_data;
  272.   if (params->max_bytes == params->read_bytes)
  273.     return (0);
  274.   if (params->max_bytes > 0 && 
  275.       size + params->read_bytes > params->max_bytes)
  276.     size = params->max_bytes - params->read_bytes;
  277.   if ((len = gftp_read (request, buf, size, request->sockfd)) < 0)
  278.     return (-2);
  279.   return (len);
  280. }
  281. static int
  282. rfc2068_end_transfer (gftp_request * request)
  283. {
  284.   rfc2068_params * params;
  285.   g_return_val_if_fail (request != NULL, -2);
  286.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  287.   if (request->sockfd < 0)
  288.     return (-2);
  289.   if (close (request->sockfd) < 0)
  290.     request->logging_function (gftp_logging_error, request->user_data,
  291.                                _("Error closing file descriptor: %sn"),
  292.                                g_strerror (errno));
  293.   request->sockfd = -1;
  294.   params = request->protocol_data;
  295.   params->max_bytes = 0;
  296.   request->logging_function (gftp_logging_misc, request->user_data,
  297.                              _("Finished retrieving datan"));
  298.   return (0);
  299. }
  300. static int
  301. rfc2068_list_files (gftp_request * request)
  302. {
  303.   char *tempstr, *pos, *proto;
  304.   rfc2068_params *params;
  305.   off_t ret;
  306.   g_return_val_if_fail (request != NULL, -2);
  307.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  308.   params = request->protocol_data;
  309.   if (request->sockfd < 0 && rfc2068_connect (request) != 0)
  310.     return (-2);
  311.   if (request->proxy_config != NULL && *request->proxy_config != '')
  312.     proto = request->proxy_config;
  313.   else
  314.     proto = "http";
  315.   if (request->username == NULL || *request->username == '')
  316.     tempstr = g_strconcat ("GET ", proto, "://", 
  317.                            request->hostname, "/", request->directory, 
  318.                            use_http11 ? "/ HTTP/1.1n" : "/ HTTP/1.0n", NULL);
  319.   else
  320.     tempstr = g_strconcat ("GET ", proto, "://", request->username, "@", 
  321.                            request->hostname, "/", request->directory, 
  322.                            use_http11 ? "/ HTTP/1.1n" : "/ HTTP/1.0n", NULL);
  323.   if ((pos = strstr (tempstr, "://")) != NULL)
  324.     remove_double_slashes (pos + 3);
  325.   else
  326.     remove_double_slashes (tempstr);
  327.   ret = rfc2068_send_command (request, tempstr, NULL);
  328.   g_free (tempstr);
  329.   if (ret < 0)
  330.     return (-1);
  331.   params->read_bytes = 0;
  332.   if (strlen (request->last_ftp_response) > 9 &&
  333.       strncmp (request->last_ftp_response + 9, "200", 3) == 0)
  334.     {
  335.       request->logging_function (gftp_logging_misc, request->user_data,
  336.                                  _("Retrieving directory listing...n"));
  337.       return (0);
  338.     }
  339.   
  340.   return (-2);
  341. }
  342. static off_t 
  343. rfc2068_get_file_size (gftp_request * request, const char *filename)
  344. {
  345.   char *tempstr, *pos, *proto;
  346.   off_t size;
  347.   g_return_val_if_fail (request != NULL, -2);
  348.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  349.   g_return_val_if_fail (filename != NULL, -2);
  350.   if (request->sockfd < 0 && rfc2068_connect (request) != 0)
  351.     return (-2);
  352.   if (request->proxy_config != NULL && *request->proxy_config != '')
  353.     proto = request->proxy_config;
  354.   else
  355.     proto = "http";
  356.   if (request->username == NULL || *request->username == '')
  357.     tempstr = g_strconcat ("HEAD ", proto, request->hostname, "/", filename, 
  358.                            use_http11 ? " HTTP/1.1n" : " HTTP/1.0n", NULL);
  359.   else
  360.     tempstr = g_strconcat ("HEAD ", proto, request->username, "@", 
  361.                            request->hostname, "/", filename, 
  362.                            use_http11 ? " HTTP/1.1n" : " HTTP/1.0n", NULL);
  363.   if ((pos = strstr (tempstr, "://")) != NULL)
  364.     remove_double_slashes (pos + 3);
  365.   else
  366.     remove_double_slashes (tempstr);
  367.   size = rfc2068_send_command (request, tempstr, NULL);
  368.   g_free (tempstr);
  369.   if (size < 0)
  370.     return (-2);
  371.   return (size);
  372. }
  373. static int
  374. parse_html_line (char *tempstr, gftp_file * fle)
  375. {
  376.   char months[13][3] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
  377.                         "Sep", "Oct", "Nov", "Dec"};
  378.   char *stpos, *pos, month[4];
  379.   struct tm t;
  380.   long units;
  381.   int i;
  382.   memset (fle, 0, sizeof (*fle));
  383.   if ((pos = strstr (tempstr, "<A HREF=")) == NULL && 
  384.       (pos = strstr (tempstr, "<a href=")) == NULL)
  385.     return (0);
  386.   /* Find the filename */
  387.   while (*pos != '"' && *pos != '')
  388.     pos++;
  389.   if (*pos == '')
  390.     return (0);
  391.   pos++;
  392.   for (stpos = pos; *pos != '"' && *pos != ''; pos++);
  393.   if (*pos == '')
  394.     return (0);
  395.   *pos = '';
  396.   /* Copy file attributes. Just about the only thing we can get is whether it
  397.      is a directory or not */
  398.   fle->attribs = g_malloc (11);
  399.   strcpy (fle->attribs, "----------");
  400.   if (*(pos - 1) == '/')
  401.     {
  402.       *(pos - 1) = '';
  403.       *fle->attribs = 'd';
  404.       fle->isdir = 1;
  405.     }
  406.   /* Copy filename */
  407.   if (strchr (stpos, '/') != NULL || strncmp (stpos, "mailto:", 7) == 0 ||
  408.       *stpos == '' || *stpos == '?')
  409.     return (0);
  410.   fle->file = g_malloc (strlen (stpos) + 1);
  411.   strcpy (fle->file, stpos);
  412.   if (*(pos - 1) == '')
  413.     *(pos - 1) = '/';
  414.   *pos = '"';
  415.   pos++;
  416.   /* Skip whitespace and html tags after file and before date */
  417.   stpos = pos;
  418.   if ((pos = strstr (stpos, "</A>")) == NULL &&
  419.       (pos = strstr (stpos, "</a>")) == NULL)
  420.     return (0);
  421.   pos += 4;
  422.   while (*pos == ' ' || *pos == '.' || *pos == '<')
  423.     {
  424.       if (*pos == '<')
  425. {
  426.   if (strncmp (pos, "<A ", 3) == 0 || strncmp (pos, "<a ", 3) == 0)
  427.     {
  428.       stpos = pos;
  429.       if ((pos = strstr (stpos, "</A>")) == NULL 
  430.                    && (pos = strstr (stpos, "</a>")) == NULL)
  431. return (0);
  432.       pos += 4;
  433.     }
  434.   else
  435.     {
  436.       while (*pos != '>' && *pos != '')
  437. pos++;
  438.       if (*pos == '')
  439. return (0);
  440.     }
  441. }
  442.       pos++;
  443.     }
  444.   /* Now get the date */
  445.   memset (&t, 0, sizeof (t));
  446.   memset (month, 0, sizeof (month));
  447.   if (strchr (pos, ':') != NULL)
  448.     {
  449.       if (*pos == '[')
  450. pos++;
  451.       sscanf (pos, "%02d-%3s-%04d %02d:%02d", &t.tm_mday, month, &t.tm_year,
  452.       &t.tm_hour, &t.tm_min);
  453.       while (*pos != ' ' && *pos != '')
  454. pos++;
  455.       if (*pos == '')
  456. return (1);
  457.       while (*pos == ' ')
  458. pos++;
  459.       while (*pos != ' ' && *pos != '')
  460. pos++;
  461.       if (*pos == '')
  462. return (1);
  463.       t.tm_year -= 1900;
  464.     }
  465.   else
  466.     {
  467.       pos++;
  468.       strncpy (month, pos, 3);
  469.       for (i=0; i<3 && *pos != ''; i++)
  470.         pos++;
  471.       if (*pos == '')
  472. return (1);
  473.       while (*pos == ' ')
  474. pos++;
  475.       t.tm_mday = strtol (pos, NULL, 10);
  476.       while (*pos != ' ' && *pos != '')
  477. pos++;
  478.       if (*pos == '')
  479. return (1);
  480.       while (*pos == ' ')
  481. pos++;
  482.       t.tm_year = strtol (pos, NULL, 10) - 1900;
  483.       while (*pos != ' ' && *pos != '')
  484. pos++;
  485.       if (*pos == '')
  486. return (1);
  487.     }
  488.   for (i=0; i<12; i++)
  489.     {
  490.       if (strncmp (month, months[i], 3) == 0)
  491.         {
  492.           t.tm_mon = i;
  493.           break;
  494.         }
  495.     }
  496.   fle->datetime = mktime (&t);
  497.   while (*pos == ' ' || *pos == ']')
  498.     pos++;
  499.   /* Get the size */
  500.   /* This gets confusing on lines like "... 1.1M RedHat RPM package" */
  501.   /* We need to avoid finding the 'k' in package */
  502.  
  503.   stpos = strchr (pos, 'k');
  504.   if (stpos == NULL || !isdigit (*(stpos - 1)))
  505.      stpos = strchr (pos, 'M');
  506.   if (stpos == NULL || !isdigit (*(stpos - 1)))
  507.      return (1); /* Return successfully
  508.    since we got the file */
  509.   if (*stpos == 'k')
  510.     units = 1024;
  511.   else
  512.     units = 1048576;
  513.   fle->size = 0;
  514.   while (*(stpos - 1) != ' ' && *(stpos - 1) != 't' && stpos > tempstr) 
  515.     {
  516.       stpos--;
  517.       if ((*stpos == '.') && isdigit (*(stpos + 1)) ) 
  518.         {  /* found decimal point */
  519.           fle->size = units * strtol (stpos + 1, NULL, 10);
  520.           fle->size /= 10;
  521.         }
  522.     }
  523.   fle->size += units * strtol (stpos, NULL, 10);
  524.   return (1);
  525. }
  526. static int
  527. rfc2068_get_next_file (gftp_request * request, gftp_file * fle, int fd)
  528. {
  529.   gftp_getline_buffer * rbuf;
  530.   rfc2068_params * params;
  531.   char tempstr[255];
  532.   size_t len;
  533.   g_return_val_if_fail (request != NULL, -2);
  534.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  535.   g_return_val_if_fail (fle != NULL, -2);
  536.   params = request->protocol_data;
  537.   if (request->last_dir_entry)
  538.     {
  539.       g_free (request->last_dir_entry);
  540.       request->last_dir_entry = NULL;
  541.     }
  542.   rbuf = NULL;
  543.   while (1)
  544.     {
  545.       if (gftp_get_line (request, &rbuf, tempstr, sizeof (tempstr), fd) < 0)
  546.         return (-2);
  547.       tempstr[sizeof (tempstr) - 1] = '';
  548.       params->read_bytes += strlen (tempstr);
  549.       if (params->chunked_transfer && strcmp (tempstr, "0rn") == 0)
  550.         {
  551.           while ((len = gftp_get_line (request, &rbuf, tempstr, 
  552.                                        sizeof (tempstr), fd)) > 0)
  553.             {
  554.               if (strcmp (tempstr, "rn") == 0)
  555.                 break;
  556.             }
  557.   gftp_file_destroy (fle);
  558.           if (len < 0)
  559.             return (-1);
  560.           return (0);
  561.         }
  562.       if (parse_html_line (tempstr, fle) == 0 || fle->file == NULL)
  563. gftp_file_destroy (fle);
  564.       else
  565. break;
  566.       if (params->max_bytes != 0 && params->read_bytes == params->max_bytes)
  567. break;
  568.     }
  569.   if (fle->file == NULL)
  570.     {
  571.       gftp_file_destroy (fle);
  572.       return (-2);
  573.     }
  574.   len = strlen (tempstr);
  575.   if (!request->cached)
  576.     {
  577.       request->last_dir_entry = g_strdup_printf ("%sn", tempstr);
  578.       request->last_dir_entry_len = len + 1;
  579.     }
  580.   return (len);
  581. }
  582. static int
  583. rfc2068_chdir (gftp_request * request, const char *directory)
  584. {
  585.   g_return_val_if_fail (request != NULL, -2);
  586.   g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, -2);
  587.   g_return_val_if_fail (directory != NULL, -2);
  588.   if (request->directory != directory)
  589.     {
  590.       if (request->directory)
  591.         g_free (request->directory);
  592.       request->directory = g_malloc (strlen (directory) + 1);
  593.       strcpy (request->directory, directory);
  594.     }
  595.   return (0);
  596. }
  597. static void
  598. rfc2068_set_config_options (gftp_request * request)
  599. {
  600.   gftp_set_proxy_hostname (request, http_proxy_host);
  601.   gftp_set_proxy_port (request, http_proxy_port);
  602.   gftp_set_proxy_username (request, http_proxy_username);
  603.   gftp_set_proxy_password (request, http_proxy_password);
  604.   if (request->proxy_config == NULL)
  605.     {
  606.       request->proxy_config = g_malloc (5);
  607.       strcpy (request->proxy_config, "http");
  608.     }
  609. }
  610. void
  611. rfc2068_init (gftp_request * request)
  612. {
  613.   g_return_if_fail (request != NULL);
  614.   request->protonum = GFTP_HTTP_NUM;
  615.   request->init = rfc2068_init;
  616.   request->destroy = NULL;
  617.   request->connect = rfc2068_connect;
  618.   request->disconnect = rfc2068_disconnect;
  619.   request->get_file = rfc2068_get_file;
  620.   request->put_file = NULL;
  621.   request->transfer_file = NULL;
  622.   request->get_next_file_chunk = rfc2068_get_next_file_chunk;
  623.   request->put_next_file_chunk = NULL;
  624.   request->end_transfer = rfc2068_end_transfer;
  625.   request->abort_transfer = rfc2068_end_transfer; /* NOTE: uses end_transfer */
  626.   request->list_files = rfc2068_list_files;
  627.   request->get_next_file = rfc2068_get_next_file;
  628.   request->set_data_type = NULL;
  629.   request->get_file_size = rfc2068_get_file_size;
  630.   request->chdir = rfc2068_chdir;
  631.   request->rmdir = NULL;
  632.   request->rmfile = NULL;
  633.   request->mkdir = NULL;
  634.   request->rename = NULL;
  635.   request->chmod = NULL;
  636.   request->site = NULL;
  637.   request->parse_url = NULL;
  638.   request->swap_socks = NULL;
  639.   request->set_config_options = rfc2068_set_config_options;
  640.   request->url_prefix = "http";
  641.   request->protocol_name = "HTTP";
  642.   request->need_hostport = 1;
  643.   request->need_userpass = 0;
  644.   request->use_cache = 1;
  645.   request->use_threads = 1;
  646.   request->always_connected = 0;
  647.   request->protocol_data = g_malloc0 (sizeof (rfc2068_params));
  648.   gftp_set_config_options (request);
  649. }