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

Ftp客户端

开发平台:

Visual C++

  1. /*****************************************************************************/
  2. /*  protocols.c - Skeleton functions for the protocols gftp supports         */
  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: protocols.c,v 1.21 2002/12/05 00:43:06 masneyb Exp $";
  21. gftp_request *
  22. gftp_request_new (void)
  23. {
  24.   gftp_request *request;
  25.   request = g_malloc0 (sizeof (*request));
  26.   request->sockfd = -1;
  27.   request->datafd = -1;
  28.   request->cachefd = -1;
  29.   request->data_type = GFTP_TYPE_BINARY;
  30.   return (request);
  31. }
  32. void
  33. gftp_request_destroy (gftp_request * request, int free_request)
  34. {
  35.   g_return_if_fail (request != NULL);
  36.   gftp_disconnect (request);
  37.   if (request->destroy != NULL)
  38.     request->destroy (request);
  39.   if (request->hostname)
  40.     g_free (request->hostname);
  41.   if (request->username)
  42.     g_free (request->username);
  43.   if (request->password)
  44.     {
  45.       memset (request->password, 0, strlen (request->password));
  46.       g_free (request->password);
  47.     }
  48.   if (request->account)
  49.     {
  50.       memset (request->account, 0, strlen (request->account));
  51.       g_free (request->account);
  52.     }
  53.   if (request->directory)
  54.     g_free (request->directory);
  55.   if (request->proxy_config)
  56.     g_free (request->proxy_config);
  57.   if (request->proxy_hostname)
  58.     g_free (request->proxy_hostname);
  59.   if (request->proxy_username)
  60.     g_free (request->proxy_username);
  61.   if (request->proxy_password)
  62.     g_free (request->proxy_password);
  63.   if (request->proxy_account)
  64.     g_free (request->proxy_account);
  65.   if (request->last_ftp_response)
  66.     g_free (request->last_ftp_response);
  67.   if (request->protocol_data)
  68.     g_free (request->protocol_data);
  69.   if (request->sftpserv_path)
  70.     g_free (request->sftpserv_path);
  71.   memset (request, 0, sizeof (*request));
  72.   if (free_request)
  73.     g_free (request);
  74.   else
  75.     {
  76.       request->sockfd = -1;
  77.       request->datafd = -1;
  78.       request->cachefd = -1;
  79.       request->data_type = GFTP_TYPE_BINARY;
  80.     }
  81. }
  82. void
  83. gftp_file_destroy (gftp_file * file)
  84. {
  85.   g_return_if_fail (file != NULL);
  86.   if (file->file)
  87.     g_free (file->file);
  88.   if (file->user)
  89.     g_free (file->user);
  90.   if (file->group)
  91.     g_free (file->group);
  92.   if (file->attribs)
  93.     g_free (file->attribs);
  94.   if (file->destfile)
  95.     g_free (file->destfile);
  96.   memset (file, 0, sizeof (*file));
  97. }
  98. int
  99. gftp_connect (gftp_request * request)
  100. {
  101.   g_return_val_if_fail (request != NULL, -2);
  102.   if (request->connect == NULL)
  103.     return (-2);
  104.   gftp_set_config_options (request);
  105.   return (request->connect (request));
  106. }
  107. void
  108. gftp_disconnect (gftp_request * request)
  109. {
  110.   g_return_if_fail (request != NULL);
  111. #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
  112.   if (request->hostp)
  113.     freeaddrinfo (request->hostp);
  114. #endif
  115.   request->hostp = NULL;
  116.   if (request->sftpserv_path != NULL)
  117.     {
  118.       g_free (request->sftpserv_path);
  119.       request->sftpserv_path = NULL;
  120.     }
  121.   request->cached = 0;
  122.   if (request->disconnect == NULL)
  123.     return;
  124.   request->disconnect (request);
  125. }
  126. off_t
  127. gftp_get_file (gftp_request * request, const char *filename, int fd,
  128.                size_t startsize)
  129. {
  130.   g_return_val_if_fail (request != NULL, -2);
  131.   request->cached = 0;
  132.   if (request->get_file == NULL)
  133.     return (-2);
  134.   return (request->get_file (request, filename, fd, startsize));
  135. }
  136. int
  137. gftp_put_file (gftp_request * request, const char *filename, int fd,
  138.                size_t startsize, size_t totalsize)
  139. {
  140.   g_return_val_if_fail (request != NULL, -2);
  141.   request->cached = 0;
  142.   if (request->put_file == NULL)
  143.     return (-2);
  144.   return (request->put_file (request, filename, fd, startsize, totalsize));
  145. }
  146. long
  147. gftp_transfer_file (gftp_request * fromreq, const char *fromfile, 
  148.                     int fromfd, size_t fromsize, 
  149.                     gftp_request * toreq, const char *tofile,
  150.                     int tofd, size_t tosize)
  151. {
  152.   long size;
  153.   g_return_val_if_fail (fromreq != NULL, -2);
  154.   g_return_val_if_fail (fromfile != NULL, -2);
  155.   g_return_val_if_fail (toreq != NULL, -2);
  156.   g_return_val_if_fail (tofile != NULL, -2);
  157.   if (strcmp (fromreq->protocol_name, toreq->protocol_name) == 0)
  158.     {
  159.       if (fromreq->transfer_file == NULL)
  160. return (-2);
  161.       return (fromreq->transfer_file (fromreq, fromfile, fromsize, toreq, 
  162.                                       tofile, tosize));
  163.     }
  164.   fromreq->cached = 0;
  165.   toreq->cached = 0;
  166.   if ((size = gftp_get_file (fromreq, fromfile, fromfd, tosize)) < 0)
  167.     return (-2);
  168.   if (gftp_put_file (toreq, tofile, tofd, tosize, size) != 0)
  169.     {
  170.       if (gftp_abort_transfer (fromreq) != 0)
  171.         gftp_end_transfer (fromreq);
  172.       return (-2);
  173.     }
  174.   return (size);
  175. }
  176. ssize_t 
  177. gftp_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
  178. {
  179.   g_return_val_if_fail (request != NULL, -2);
  180.   g_return_val_if_fail (buf != NULL, -2);
  181.   if (request->get_next_file_chunk != NULL)
  182.     return (request->get_next_file_chunk (request, buf, size));
  183.   return (gftp_read (request, buf, size, request->datafd));
  184. }
  185. ssize_t 
  186. gftp_put_next_file_chunk (gftp_request * request, char *buf, size_t size)
  187. {
  188.   g_return_val_if_fail (request != NULL, -2);
  189.   g_return_val_if_fail (buf != NULL, -2);
  190.   if (request->put_next_file_chunk != NULL)
  191.     return (request->put_next_file_chunk (request, buf, size));
  192.   if (size == 0)
  193.     return (0);
  194.   return (gftp_write (request, buf, size, request->datafd));
  195. }
  196. int
  197. gftp_end_transfer (gftp_request * request)
  198. {
  199.   int ret;
  200.   g_return_val_if_fail (request != NULL, -2);
  201.   if (!request->cached && 
  202.       request->end_transfer != NULL)
  203.     ret = request->end_transfer (request);
  204.   else
  205.     ret = 0;
  206.   if (request->cachefd > 0)
  207.     {
  208.       close (request->cachefd);
  209.       request->cachefd = -1;
  210.     }
  211.   if (request->last_dir_entry)
  212.     {
  213.       g_free (request->last_dir_entry);
  214.       request->last_dir_entry = NULL;
  215.       request->last_dir_entry_len = 0;
  216.     }
  217.   return (ret);
  218. }
  219. int
  220. gftp_abort_transfer (gftp_request * request)
  221. {
  222.   g_return_val_if_fail (request != NULL, -2);
  223.   if (request->abort_transfer == NULL)
  224.     return (-2);
  225.   return (request->abort_transfer (request));
  226. }
  227. int
  228. gftp_list_files (gftp_request * request)
  229. {
  230.   int fd;
  231.   g_return_val_if_fail (request != NULL, -2);
  232.   request->cached = 0;
  233.   if (request->use_cache && (fd = gftp_find_cache_entry (request)) > 0)
  234.     {
  235.       request->logging_function (gftp_logging_misc, request->user_data,
  236.                                  _("Loading directory listing %s from cachen"),
  237.                                  request->directory);
  238.       request->cachefd = fd;
  239.       request->cached = 1;
  240.       return (0);
  241.     }
  242.   else if (request->use_cache)
  243.     {
  244.       request->cachefd = gftp_new_cache_entry (request);
  245.       request->cached = 0; 
  246.     }
  247.   if (request->list_files == NULL)
  248.     return (-2);
  249.   return (request->list_files (request));
  250. }
  251. int
  252. gftp_get_next_file (gftp_request * request, char *filespec, gftp_file * fle)
  253. {
  254.   int fd, ret;
  255. #if GLIB_MAJOR_VERSION > 1
  256.   gsize bread, bwrite;
  257.   char *tempstr;
  258.   GError * error;
  259. #endif
  260.   g_return_val_if_fail (request != NULL, -2);
  261.   if (request->get_next_file == NULL)
  262.     return (-2);
  263.   if (request->cached && request->cachefd > 0)
  264.     fd = request->cachefd;
  265.   else
  266.     fd = request->datafd;
  267.   memset (fle, 0, sizeof (*fle));
  268.   do
  269.     {
  270.       gftp_file_destroy (fle);
  271.       ret = request->get_next_file (request, fle, fd);
  272. #if GLIB_MAJOR_VERSION > 1
  273.       if (fle->file != NULL && !g_utf8_validate (fle->file, -1, NULL))
  274.         {
  275.           error = NULL;
  276.           if ((tempstr = g_locale_to_utf8 (fle->file, -1, &bread, 
  277.                                            &bwrite, &error)) != NULL)
  278.             {
  279.               g_free (fle->file);
  280.               fle->file = tempstr;
  281.             }
  282.           else
  283.             g_warning ("Error when converting %s to UTF-8: %sn", fle->file,
  284.                        error->message);
  285.         }
  286. #endif
  287.       if (ret >= 0 && !request->cached && request->cachefd > 0 && 
  288.           request->last_dir_entry != NULL)
  289.         {
  290.           if (gftp_write (request, request->last_dir_entry,
  291.                           request->last_dir_entry_len, request->cachefd) < 0)
  292.             {
  293.               request->logging_function (gftp_logging_error, request->user_data,
  294.                                         _("Error: Cannot write to cache: %sn"),
  295.                                         g_strerror (errno));
  296.               close (request->cachefd);
  297.               request->cachefd = -1;
  298.             }
  299.         }
  300.     } while (ret > 0 && !gftp_match_filespec (fle->file, filespec));
  301.   return (ret);
  302. }
  303. int
  304. gftp_parse_url (gftp_request * request, const char *url)
  305. {
  306.   char *pos, *endpos, *endhostpos, *str, tempchar;
  307.   gftp_logging_func logging_function;
  308.   const char *stpos;
  309.   int len, i;
  310.   g_return_val_if_fail (request != NULL, -2);
  311.   g_return_val_if_fail (url != NULL, -2);
  312.   logging_function = request->logging_function;
  313.   gftp_request_destroy (request, 0);
  314.   request->logging_function = logging_function;
  315.   for (stpos = url; *stpos == ' '; stpos++);
  316.   if ((pos = strstr (stpos, "://")) != NULL)
  317.     {
  318.       *pos = '';
  319.       for (i = 0; gftp_protocols[i].url_prefix; i++)
  320.         {
  321.           if (strcmp (gftp_protocols[i].url_prefix, stpos) == 0)
  322.             break;
  323.         }
  324.       if (gftp_protocols[i].url_prefix == NULL)
  325.         return (-2);
  326.       *pos = ':';
  327.     }
  328.   else
  329.     {
  330.       for (i = 0; gftp_protocols[i].url_prefix; i++)
  331.         {
  332.           if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
  333.             break;
  334.         }
  335.       if (gftp_protocols[i].url_prefix == NULL)
  336.         i = GFTP_FTP_NUM;
  337.     }
  338.   gftp_protocols[i].init (request);
  339.   if (request->parse_url != NULL)
  340.     return (request->parse_url (request, url));
  341.   if (i == GFTP_LOCAL_NUM)
  342.     {
  343.       request->directory = g_malloc (strlen (stpos + 6) + 1);
  344.       strcpy (request->directory, stpos + 7);
  345.       return (0);
  346.     }
  347.   for (; *stpos == ' '; stpos++);
  348.   str = g_malloc (strlen (stpos) + 1);
  349.   strcpy (str, stpos);
  350.   for (pos = str + strlen (str) - 1; *pos == ' '; pos--)
  351.     *pos = '';
  352.   pos = str;
  353.   len = strlen (request->url_prefix);
  354.   if (strncmp (pos, request->url_prefix, len) == 0
  355.       && strncmp (pos + len, "://", 3) == 0)
  356.     pos += len + 3;
  357.   if ((endhostpos = strchr (pos, '@')) != NULL)
  358.     {
  359.       /* A user/password was entered */
  360.       if ((endpos = strchr (pos, ':')) == NULL || endhostpos < endpos)
  361. {
  362.   /* No password was entered */
  363.   gftp_set_password (request, "");
  364.   endpos = endhostpos;
  365. }
  366.       *endpos = '';
  367.       gftp_set_username (request, pos);
  368.       pos = endpos + 1;
  369.       if ((endpos = strchr (pos, '@')) != NULL)
  370. {
  371.   if (strchr (endpos + 1, '@') != NULL)
  372.     endpos = strchr (endpos + 1, '@');
  373.   *endpos = '';
  374.   gftp_set_password (request, pos);
  375.   pos = endpos + 1;
  376. }
  377.     }
  378.   /* Now get the hostname and an optional port and optional directory */
  379.   endhostpos = pos + strlen (pos);
  380.   if ((endpos = strchr (pos, ':')) != NULL)
  381.     endhostpos = endpos;
  382.   else if ((endpos = strchr (pos, '/')) != NULL)
  383.     endhostpos = endpos;
  384.   tempchar = *endhostpos;
  385.   *endhostpos = '';
  386.   gftp_set_hostname (request, pos);
  387.   *endhostpos = tempchar;
  388.   if ((endpos = strchr (pos, ':')) != NULL)
  389.     {
  390.       /* A port was entered */
  391.       pos = endpos + 1;
  392.       gftp_set_port (request, strtol (pos, NULL, 10));
  393.     }
  394.   if ((endpos = strchr (pos, '/')) != NULL)
  395.     gftp_set_directory (request, endpos);
  396.   g_free (str);
  397.   return (0);
  398. }
  399. int
  400. gftp_set_data_type (gftp_request * request, int data_type)
  401. {
  402.   g_return_val_if_fail (request != NULL, -2);
  403.   if (request->set_data_type == NULL)
  404.     return (0);
  405.   return (request->set_data_type (request, data_type));
  406. }
  407. void
  408. gftp_set_hostname (gftp_request * request, const char *hostname)
  409. {
  410.   g_return_if_fail (request != NULL);
  411.   g_return_if_fail (hostname != NULL);
  412.   if (request->hostname)
  413.     g_free (request->hostname);
  414.   request->hostname = g_malloc (strlen (hostname) + 1);
  415.   strcpy (request->hostname, hostname);
  416. }
  417. void
  418. gftp_set_username (gftp_request * request, const char *username)
  419. {
  420.   g_return_if_fail (request != NULL);
  421.   g_return_if_fail (username != NULL);
  422.   if (request->username)
  423.     g_free (request->username);
  424.   request->username = g_malloc (strlen (username) + 1);
  425.   strcpy (request->username, username);
  426. }
  427. void
  428. gftp_set_password (gftp_request * request, const char *password)
  429. {
  430.   g_return_if_fail (request != NULL);
  431.   g_return_if_fail (password != NULL);
  432.   if (request->password)
  433.     g_free (request->password);
  434.   request->password = g_malloc (strlen (password) + 1);
  435.   strcpy (request->password, password);
  436. }
  437. void
  438. gftp_set_account (gftp_request * request, const char *account)
  439. {
  440.   g_return_if_fail (request != NULL);
  441.   g_return_if_fail (account != NULL);
  442.   if (request->account)
  443.     g_free (request->account);
  444.   request->account = g_malloc (strlen (account) + 1);
  445.   strcpy (request->account, account);
  446. }
  447. int
  448. gftp_set_directory (gftp_request * request, const char *directory)
  449. {
  450.   g_return_val_if_fail (request != NULL, -2);
  451.   g_return_val_if_fail (directory != NULL, -2);
  452.   if (request->sockfd <= 0 && !request->always_connected)
  453.     {
  454.       if (directory != request->directory)
  455. {
  456.   if (request->directory)
  457.     g_free (request->directory);
  458.   request->directory = g_malloc (strlen (directory) + 1);
  459.   strcpy (request->directory, directory);
  460. }
  461.       return (0);
  462.     }
  463.   else if (request->chdir == NULL)
  464.     return (-2);
  465.   return (request->chdir (request, directory));
  466. }
  467. void
  468. gftp_set_port (gftp_request * request, unsigned int port)
  469. {
  470.   g_return_if_fail (request != NULL);
  471.   request->port = port;
  472. }
  473. void
  474. gftp_set_proxy_hostname (gftp_request * request, const char *hostname)
  475. {
  476.   g_return_if_fail (request != NULL);
  477.   g_return_if_fail (hostname != NULL);
  478.   if (request->proxy_hostname)
  479.     g_free (request->proxy_hostname);
  480.   request->proxy_hostname = g_malloc (strlen (hostname) + 1);
  481.   strcpy (request->proxy_hostname, hostname);
  482. }
  483. void
  484. gftp_set_proxy_username (gftp_request * request, const char *username)
  485. {
  486.   g_return_if_fail (request != NULL);
  487.   g_return_if_fail (username != NULL);
  488.   if (request->proxy_username)
  489.     g_free (request->proxy_username);
  490.   request->proxy_username = g_malloc (strlen (username) + 1);
  491.   strcpy (request->proxy_username, username);
  492. }
  493. void
  494. gftp_set_proxy_password (gftp_request * request, const char *password)
  495. {
  496.   g_return_if_fail (request != NULL);
  497.   g_return_if_fail (password != NULL);
  498.   if (request->proxy_password)
  499.     g_free (request->proxy_password);
  500.   request->proxy_password = g_malloc (strlen (password) + 1);
  501.   strcpy (request->proxy_password, password);
  502. }
  503. void
  504. gftp_set_proxy_account (gftp_request * request, const char *account)
  505. {
  506.   g_return_if_fail (request != NULL);
  507.   g_return_if_fail (account != NULL);
  508.   if (request->proxy_account)
  509.     g_free (request->proxy_account);
  510.   request->proxy_account = g_malloc (strlen (account) + 1);
  511.   strcpy (request->proxy_account, account);
  512. }
  513. void
  514. gftp_set_proxy_port (gftp_request * request, unsigned int port)
  515. {
  516.   g_return_if_fail (request != NULL);
  517.   request->proxy_port = port;
  518. }
  519. int
  520. gftp_remove_directory (gftp_request * request, const char *directory)
  521. {
  522.   g_return_val_if_fail (request != NULL, -2);
  523.   if (request->rmdir == NULL)
  524.     return (-2);
  525.   return (request->rmdir (request, directory));
  526. }
  527. int
  528. gftp_remove_file (gftp_request * request, const char *file)
  529. {
  530.   g_return_val_if_fail (request != NULL, -2);
  531.   if (request->rmfile == NULL)
  532.     return (-2);
  533.   return (request->rmfile (request, file));
  534. }
  535. int
  536. gftp_make_directory (gftp_request * request, const char *directory)
  537. {
  538.   g_return_val_if_fail (request != NULL, -2);
  539.   if (request->mkdir == NULL)
  540.     return (-2);
  541.   return (request->mkdir (request, directory));
  542. }
  543. int
  544. gftp_rename_file (gftp_request * request, const char *oldname,
  545.   const char *newname)
  546. {
  547.   g_return_val_if_fail (request != NULL, -2);
  548.   if (request->rename == NULL)
  549.     return (-2);
  550.   return (request->rename (request, oldname, newname));
  551. }
  552. int
  553. gftp_chmod (gftp_request * request, const char *file, int mode)
  554. {
  555.   g_return_val_if_fail (request != NULL, -2);
  556.   if (request->chmod == NULL)
  557.     return (-2);
  558.   return (request->chmod (request, file, mode));
  559. }
  560. int
  561. gftp_set_file_time (gftp_request * request, const char *file, time_t datetime)
  562. {
  563.   g_return_val_if_fail (request != NULL, -2);
  564.   if (request->set_file_time == NULL)
  565.     return (-2);
  566.   return (request->set_file_time (request, file, datetime));
  567. }
  568. char
  569. gftp_site_cmd (gftp_request * request, const char *command)
  570. {
  571.   g_return_val_if_fail (request != NULL, -2);
  572.   if (request->site == NULL)
  573.     return (-2);
  574.   return (request->site (request, command));
  575. }
  576. void
  577. gftp_set_proxy_config (gftp_request * request, const char *proxy_config)
  578. {
  579.   int len;
  580.   g_return_if_fail (request != NULL);
  581.   if (request->proxy_config != NULL)
  582.     g_free (request->proxy_config);
  583.   if (proxy_config == NULL)
  584.     {
  585.       request->proxy_config = NULL;
  586.       return;
  587.     }
  588.   len = strlen (proxy_config);
  589.   if (len > 0 && (proxy_config[len - 1] != 'n' ||
  590.   proxy_config[len - 2] != '%'))
  591.     len += 2;
  592.   request->proxy_config = g_malloc (len + 1);
  593.   strcpy (request->proxy_config, proxy_config);
  594.   if (len != strlen (proxy_config))
  595.     {
  596.       request->proxy_config[len - 2] = '%';
  597.       request->proxy_config[len - 1] = 'n';
  598.       request->proxy_config[len] = '';
  599.     }
  600. }
  601. off_t
  602. gftp_get_file_size (gftp_request * request, const char *filename)
  603. {
  604.   g_return_val_if_fail (request != NULL, 0);
  605.   if (request->get_file_size == NULL)
  606.     return (0);
  607.   return (request->get_file_size (request, filename));
  608. }
  609. int
  610. gftp_need_proxy (gftp_request * request, char *service)
  611. {
  612.   gftp_proxy_hosts * hostname;
  613.   unsigned char addy[4];
  614.   struct sockaddr *addr;
  615.   GList * templist;
  616.   gint32 netaddr;
  617.   char *pos;
  618. #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
  619.   struct addrinfo hints;
  620.   int port, errnum;
  621.   char serv[8];
  622.   request->hostp = NULL;
  623.   if (proxy_hosts == NULL)
  624.     return (request->proxy_hostname != NULL
  625.     && *request->proxy_hostname != ''
  626.     && request->proxy_config != NULL
  627.     && *request->proxy_config != '');
  628.   memset (&hints, 0, sizeof (hints));
  629.   hints.ai_flags = AI_CANONNAME;
  630.   hints.ai_family = AF_INET;
  631.   hints.ai_socktype = SOCK_STREAM;
  632.   port = request->use_proxy ? request->proxy_port : request->port;
  633.   if (port == 0)
  634.     strcpy (serv, service);
  635.   else
  636.     snprintf (serv, sizeof (serv), "%d", port);
  637.   request->logging_function (gftp_logging_misc, request->user_data,
  638.                              _("Looking up %sn"), request->hostname);
  639.   if ((errnum = getaddrinfo (request->hostname, serv, &hints, 
  640.                              &request->hostp)) != 0)
  641.     {
  642.       request->logging_function (gftp_logging_error, request->user_data,
  643.                                  _("Cannot look up hostname %s: %sn"),
  644.                                  request->hostname, gai_strerror (errnum));
  645.       return (-1);
  646.     }
  647.   addr = request->hostp->ai_addr;
  648. #else /* !HAVE_GETADDRINFO */
  649.   request->hostp = NULL;
  650.   if (proxy_hosts == NULL)
  651.     return (request->proxy_hostname != NULL
  652.             && *request->proxy_hostname != ''
  653.             && request->proxy_config != NULL
  654.             && *request->proxy_config != '');
  655.   request->logging_function (gftp_logging_misc, request->user_data,
  656.                              _("Looking up %sn"), request->hostname);
  657.   if (!(request->hostp = r_gethostbyname (request->hostname, &request->host,
  658.                                           NULL)))
  659.     {
  660.       request->logging_function (gftp_logging_error, request->user_data,
  661.                                  _("Cannot look up hostname %s: %sn"),
  662.                                  request->hostname, g_strerror (errno));
  663.       return (-1);
  664.     }
  665.   addr = (struct sockaddr *) request->host.h_addr_list[0];
  666. #endif /* HAVE_GETADDRINFO */
  667.   templist = proxy_hosts;
  668.   while (templist != NULL)
  669.     {
  670.       hostname = templist->data;
  671.       if (hostname->domain && 
  672.           strlen (request->hostname) > strlen (hostname->domain))
  673. {
  674.   pos = request->hostname + strlen (request->hostname) -
  675.                          strlen (hostname->domain);
  676.   if (strcmp (hostname->domain, pos) == 0)
  677.     return (0);
  678. }
  679.       if (hostname->ipv4_network_address != 0)
  680. {
  681.   memcpy (addy, addr, sizeof (addy));
  682.   netaddr =
  683.     (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) |
  684.      ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & 
  685.              hostname->ipv4_netmask;
  686.   if (netaddr == hostname->ipv4_network_address)
  687.     return (0);
  688. }
  689.       templist = templist->next;
  690.     }
  691.   return (request->proxy_hostname != NULL && *request->proxy_hostname != ''
  692.   && request->proxy_config != NULL && *request->proxy_config != '');
  693. }
  694. char *
  695. gftp_convert_ascii (char *buf, ssize_t *len, int direction)
  696. {
  697.   ssize_t i, j, newsize;
  698.   char *tempstr;
  699.   if (direction == GFTP_DIRECTION_DOWNLOAD)
  700.     {
  701.       for (i = 0, j = 0; i < *len; i++)
  702.         {
  703.           if (buf[i] != 'r')
  704.             buf[j++] = buf[i];
  705.           else
  706.             --*len;
  707.         }
  708.       tempstr = buf;
  709.     }
  710.   else
  711.     {
  712.       newsize = 0;
  713.       for (i = 0; i < *len; i++)
  714.         {
  715.           newsize++;
  716.           if (i > 0 && buf[i] == 'n' && buf[i - 1] != 'r')
  717.             newsize++;
  718.         }
  719.       tempstr = g_malloc (newsize);
  720.       for (i = 0, j = 0; i < *len; i++)
  721.         {
  722.           if (i > 0 && buf[i] == 'n' && buf[i - 1] != 'r')
  723.             tempstr[j++] = 'r';
  724.           tempstr[j++] = buf[i];
  725.         }
  726.       *len = newsize;
  727.     }
  728.   return (tempstr);
  729. }
  730. static char *
  731. copy_token (char **dest, char *source)
  732. {
  733.   /* This function is used internally by gftp_parse_ls () */
  734.   char *endpos, savepos;
  735.   endpos = source;
  736.   while (*endpos != ' ' && *endpos != 't' && *endpos != '')
  737.     endpos++;
  738.   if (*endpos == '')
  739.     return (NULL);
  740.   savepos = *endpos;
  741.   *endpos = '';
  742.   *dest = g_malloc (endpos - source + 1);
  743.   strcpy (*dest, source);
  744.   *endpos = savepos;
  745.   /* Skip the blanks till we get to the next entry */
  746.   source = endpos + 1;
  747.   while ((*source == ' ' || *source == 't') && *source != '')
  748.     source++;
  749.   return (source);
  750. }
  751. static char *
  752. goto_next_token (char *pos)
  753. {
  754.   while (*pos != ' ' && *pos != 't' && *pos != '')
  755.     pos++;
  756.   if (pos == '')
  757.     return (pos);
  758.   while ((*pos == ' ' || *pos == 't') && *pos != '')
  759.     pos++;
  760.   return (pos);
  761. }
  762. static time_t
  763. parse_time (char **str)
  764. {
  765.   const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
  766.     "Aug", "Sep", "Oct", "Nov", "Dec" };
  767.   char *startpos, *endpos, *datepos;
  768.   struct tm curtime, tt;
  769.   time_t t;
  770.   int i;
  771.   startpos = *str;
  772.   memset (&tt, 0, sizeof (tt));
  773.   tt.tm_isdst = -1;
  774.   if (isdigit ((int) startpos[0]) && startpos[2] == '-')
  775.     {
  776.       /* This is how DOS will return the date/time */
  777.       /* 07-06-99  12:57PM */
  778.       if ((endpos = strchr (startpos, '-')) == NULL)
  779. {
  780.   g_free (str);
  781.   return (0);
  782. }
  783.       tt.tm_mon = strtol (startpos, NULL, 10) - 1;
  784.       startpos = endpos + 1;
  785.       if ((endpos = strchr (startpos, '-')) == NULL)
  786. {
  787.   g_free (str);
  788.   return (0);
  789. }
  790.       tt.tm_mday = strtol (startpos, NULL, 10);
  791.       startpos = endpos + 1;
  792.       if ((endpos = strchr (startpos, ' ')) == NULL)
  793. {
  794.   g_free (str);
  795.   return (0);
  796. }
  797.       tt.tm_year = strtol (startpos, NULL, 10);
  798.       while (*endpos == ' ')
  799. endpos++;
  800.       startpos = endpos + 1;
  801.       if ((endpos = strchr (startpos, ':')) == NULL)
  802. {
  803.   g_free (str);
  804.   return (0);
  805. }
  806.       tt.tm_hour = strtol (startpos, NULL, 10);
  807.       startpos = endpos + 1;
  808.       while ((*endpos != 'A') && (*endpos != 'P'))
  809. endpos++;
  810.       if (*endpos == 'P')
  811. {
  812.   if (tt.tm_hour == 12)
  813.     tt.tm_hour = 0;
  814.   else
  815.     tt.tm_hour += 12;
  816. }
  817.       tt.tm_min = strtol (startpos, NULL, 10);
  818.     }
  819.   else
  820.     {
  821.       /* This is how most UNIX, Novell, and MacOS ftp servers send their time */
  822.       /* Jul 06 12:57 */
  823.       t = time (NULL);
  824.       curtime = *localtime (&t);
  825.       /* Get the month */
  826.       if ((endpos = strchr (startpos, ' ')) == NULL)
  827. return (0);
  828.       for (i = 0; i < 12; i++)
  829. {
  830.   if (strncmp (months[i], startpos, 3) == 0)
  831.     {
  832.       tt.tm_mon = i;
  833.       break;
  834.     }
  835. }
  836.       /* Skip the blanks till we get to the next entry */
  837.       startpos = endpos + 1;
  838.       while (*startpos == ' ')
  839. startpos++;
  840.       /* Get the day */
  841.       if ((endpos = strchr (startpos, ' ')) == NULL)
  842. return (0);
  843.       tt.tm_mday = strtol (startpos, NULL, 10);
  844.       /* Skip the blanks till we get to the next entry */
  845.       startpos = endpos + 1;
  846.       while (*startpos == ' ')
  847. startpos++;
  848.       if ((datepos = strchr (startpos, ':')) != NULL)
  849. {
  850.   /* No year was specified. We will use the current year */
  851.   tt.tm_year = curtime.tm_year;
  852.   /* If the date is in the future, than the year is from last year */
  853.   if ((tt.tm_mon > curtime.tm_mon) ||
  854.       ((tt.tm_mon == curtime.tm_mon) && tt.tm_mday > curtime.tm_mday))
  855.     tt.tm_year--;
  856.   /* Get the hours and the minutes */
  857.   tt.tm_hour = strtol (startpos, NULL, 10);
  858.   tt.tm_min = strtol (datepos + 1, NULL, 10);
  859. }
  860.       else
  861. {
  862.   /* Get the year. The hours and minutes will be assumed to be 0 */
  863.   tt.tm_year = strtol (startpos, NULL, 10) - 1900;
  864. }
  865.     }
  866.   *str = startpos;
  867.   return (mktime (&tt));
  868. }
  869. static int
  870. gftp_parse_ls_eplf (char *str, gftp_file * fle)
  871. {
  872.   char *startpos;
  873.   startpos = str;
  874.   fle->attribs = g_malloc (11);
  875.   strcpy (fle->attribs, "----------");
  876.   while (startpos)
  877.     {
  878.       startpos++;
  879.       switch (*startpos)
  880. {
  881. case '/':
  882.   *fle->attribs = 'd';
  883.   break;
  884. case 's':
  885.   fle->size = strtol (startpos + 1, NULL, 10);
  886.   break;
  887. case 'm':
  888.   fle->datetime = strtol (startpos + 1, NULL, 10);
  889.   break;
  890. }
  891.       startpos = strchr (startpos, ',');
  892.     }
  893.   if ((startpos = strchr (str, 9)) == NULL)
  894.     return (-2);
  895.   fle->file = g_malloc (strlen (startpos));
  896.   strcpy (fle->file, startpos + 1);
  897.   fle->user = g_malloc (8);
  898.   strcpy (fle->user, _("unknown"));
  899.   fle->group = g_malloc (8);
  900.   strcpy (fle->group, _("unknown"));
  901.   return (0);
  902. }
  903. static int
  904. gftp_parse_ls_unix (char *str, int cols, gftp_file * fle)
  905. {
  906.   char *endpos, *startpos;
  907.   startpos = str;
  908.   /* Copy file attributes */
  909.   if ((startpos = copy_token (&fle->attribs, startpos)) == NULL)
  910.     return (-2);
  911.   if (cols >= 9)
  912.     {
  913.       /* Skip the number of links */
  914.       startpos = goto_next_token (startpos);
  915.       /* Copy the user that owns this file */
  916.       if ((startpos = copy_token (&fle->user, startpos)) == NULL)
  917. return (-2);
  918.       /* Copy the group that owns this file */
  919.       if ((startpos = copy_token (&fle->group, startpos)) == NULL)
  920. return (-2);
  921.     }
  922.   else
  923.     {
  924.       fle->group = g_malloc (8);
  925.       strcpy (fle->group, _("unknown"));
  926.       if (cols == 8)
  927. {
  928.   if ((startpos = copy_token (&fle->user, startpos)) == NULL)
  929.     return (-2);
  930. }
  931.       else
  932. {
  933.   fle->user = g_malloc (8);
  934.   strcpy (fle->user, _("unknown"));
  935. }
  936.       startpos = goto_next_token (startpos);
  937.     }
  938.   /* FIXME - this is a bug if there is some extra spaces in the file */
  939.   /* See if this is a Cray directory listing. It has the following format:
  940.      drwx------     2 feiliu    g913     DK  common      4096 Sep 24  2001 wv */
  941.   if (cols == 11 && strstr (str, "->") == NULL)
  942.     {
  943.       startpos = goto_next_token (startpos);
  944.       startpos = goto_next_token (startpos);
  945.     }
  946.   /* See if this is a block or character device. We will store the major number
  947.      in the high word and the minor number in the low word.  */
  948.   if ((fle->attribs[0] == 'b' || fle->attribs[0] == 'u' || 
  949.        fle->attribs[0] == 'c') &&
  950.       ((endpos = strchr (startpos, ',')) != NULL))
  951.     {
  952.       fle->size = strtol (startpos, NULL, 10) << 16;
  953.       startpos = endpos + 1;
  954.       while (*startpos == ' ')
  955. startpos++;
  956.       /* Get the minor number */
  957.       if ((endpos = strchr (startpos, ' ')) == NULL)
  958. return (-2);
  959.       fle->size |= strtol (startpos, NULL, 10) & 0xFF;
  960.     }
  961.   else
  962.     {
  963.       /* This is a regular file  */
  964.       if ((endpos = strchr (startpos, ' ')) == NULL)
  965. return (-2);
  966.       fle->size = strtol (startpos, NULL, 10);
  967.     }
  968.   /* Skip the blanks till we get to the next entry */
  969.   startpos = endpos + 1;
  970.   while (*startpos == ' ')
  971.     startpos++;
  972.   if ((fle->datetime = parse_time (&startpos)) == 0)
  973.     return (-2);
  974.   /* Skip the blanks till we get to the next entry */
  975.   startpos = goto_next_token (startpos);
  976.   /* Parse the filename. If this file is a symbolic link, remove the -> part */
  977.   if (fle->attribs[0] == 'l' && ((endpos = strstr (startpos, "->")) != NULL))
  978.     *(endpos - 1) = '';
  979.   fle->file = g_malloc (strlen (startpos) + 1);
  980.   strcpy (fle->file, startpos);
  981.   /* Uncomment this if you want to strip the spaces off of the end of the file.
  982.      I don't want to do this by default since there are valid filenames with
  983.      spaces at the end of them. Some broken FTP servers like the Paradyne IPC
  984.      DSLAMS append a bunch of spaces at the end of the file.
  985.   for (endpos = fle->file + strlen (fle->file) - 1; 
  986.        *endpos == ' '; 
  987.        *endpos-- = '');
  988.   */
  989.   return (0);
  990. }
  991. static int
  992. gftp_parse_ls_nt (char *str, gftp_file * fle)
  993. {
  994.   char *startpos;
  995.   startpos = str;
  996.   if ((fle->datetime = parse_time (&startpos)) == 0)
  997.     return (-2);
  998.   /* No such thing on Windoze.. */
  999.   fle->user = g_malloc (8);
  1000.   strcpy (fle->user, _("unknown"));
  1001.   fle->group = g_malloc (8);
  1002.   strcpy (fle->group, _("unknown"));
  1003.   startpos = goto_next_token (startpos);
  1004.   fle->attribs = g_malloc (11);
  1005.   if (startpos[0] == '<')
  1006.     strcpy (fle->attribs, "drwxrwxrwx");
  1007.   else
  1008.     {
  1009.       strcpy (fle->attribs, "-rw-rw-rw-");
  1010.       fle->size = strtol (startpos, NULL, 10);
  1011.     }
  1012.   startpos = goto_next_token (startpos);
  1013.   fle->file = g_malloc (strlen (startpos) + 1);
  1014.   strcpy (fle->file, startpos);
  1015.   return (0);
  1016. }
  1017. static int
  1018. gftp_parse_ls_novell (char *str, gftp_file * fle)
  1019. {
  1020.   char *startpos;
  1021.   if (str[12] != ' ')
  1022.     return (-2);
  1023.   str[12] = '';
  1024.   fle->attribs = g_malloc (13);
  1025.   strcpy (fle->attribs, str);
  1026.   startpos = str + 13;
  1027.   while ((*startpos == ' ' || *startpos == 't') && *startpos != '')
  1028.     startpos++;
  1029.   if ((startpos = copy_token (&fle->user, startpos)) == NULL)
  1030.     return (-2);
  1031.   fle->group = g_malloc (8);
  1032.   strcpy (fle->group, _("unknown"));
  1033.   fle->size = strtol (startpos, NULL, 10);
  1034.   startpos = goto_next_token (startpos);
  1035.   if ((fle->datetime = parse_time (&startpos)) == 0)
  1036.     return (-2);
  1037.   startpos = goto_next_token (startpos);
  1038.   fle->file = g_malloc (strlen (startpos) + 1);
  1039.   strcpy (fle->file, startpos);
  1040.   return (0);
  1041. }
  1042. int
  1043. gftp_parse_ls (const char *lsoutput, gftp_file * fle)
  1044. {
  1045.   int result, cols;
  1046.   char *str, *pos;
  1047.   g_return_val_if_fail (lsoutput != NULL, -2);
  1048.   g_return_val_if_fail (fle != NULL, -2);
  1049.   str = g_malloc (strlen (lsoutput) + 1);
  1050.   strcpy (str, lsoutput);
  1051.   memset (fle, 0, sizeof (*fle));
  1052.   if (str[strlen (str) - 1] == 'n')
  1053.     str[strlen (str) - 1] = '';
  1054.   if (str[strlen (str) - 1] == 'r')
  1055.     str[strlen (str) - 1] = '';
  1056.   if (*lsoutput == '+')  /* EPLF format */
  1057.     result = gftp_parse_ls_eplf (str, fle);
  1058.   else if (isdigit ((int) str[0]) && str[2] == '-')  /* DOS/WinNT format */
  1059.     result = gftp_parse_ls_nt (str, fle);
  1060.   else if (str[1] == ' ' && str[2] == '[')  /* Novell format */
  1061.     result = gftp_parse_ls_novell (str, fle);
  1062.   else
  1063.     {
  1064.       /* UNIX/MacOS format */
  1065.       /* If there is no space between the attribs and links field, just make one */
  1066.       if (strlen (str) > 10)
  1067. str[10] = ' ';
  1068.       /* Determine the number of columns */
  1069.       cols = 0;
  1070.       pos = str;
  1071.       while (*pos != '')
  1072. {
  1073.   while (*pos != '' && *pos != ' ' && *pos != 't')
  1074.     {
  1075.       if (*pos == ':')
  1076. break;
  1077.       pos++;
  1078.     }
  1079.   cols++;
  1080.   if (*pos == ':')
  1081.     {
  1082.       cols++;
  1083.       break;
  1084.     }
  1085.   while (*pos == ' ' || *pos == 't')
  1086.     pos++;
  1087. }
  1088.       if (cols > 6)
  1089. result = gftp_parse_ls_unix (str, cols, fle);
  1090.       else
  1091. result = -2;
  1092.     }
  1093.   g_free (str);
  1094.   if (fle->attribs == NULL)
  1095.     return (result);
  1096.   if (*fle->attribs == 'd')
  1097.     fle->isdir = 1;
  1098.   if (*fle->attribs == 'l')
  1099.     fle->islink = 1;
  1100.   if (strchr (fle->attribs, 'x') != NULL && !fle->isdir && !fle->islink)
  1101.     fle->isexe = 1;
  1102.   if (*fle->attribs == 'b')
  1103.     fle->isblock = 1;
  1104.   if (*fle->attribs == 'c')
  1105.     fle->ischar = 1;
  1106.   if (*fle->attribs == 's')
  1107.     fle->issocket = 1;
  1108.   if (*fle->attribs == 'p')
  1109.     fle->isfifo = 1;
  1110.   return (result);
  1111. }
  1112. static GHashTable *
  1113. gftp_gen_dir_hash (gftp_request * request)
  1114. {
  1115.   unsigned long *newsize;
  1116.   GHashTable * dirhash;
  1117.   gftp_file * fle;
  1118.   char * newname;
  1119.   dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
  1120.   if (gftp_list_files (request) == 0)
  1121.     {
  1122.       fle = g_malloc0 (sizeof (*fle));
  1123.       while (gftp_get_next_file (request, NULL, fle) > 0)
  1124.         {
  1125.           newname = fle->file;
  1126.           newsize = g_malloc (sizeof (unsigned long));
  1127.           *newsize = fle->size;
  1128.           g_hash_table_insert (dirhash, newname, newsize);
  1129.           fle->file = NULL;
  1130.           gftp_file_destroy (fle);
  1131.         }
  1132.       gftp_end_transfer (request);
  1133.       g_free (fle);
  1134.     }
  1135.   else
  1136.     {
  1137.       g_hash_table_destroy (dirhash);
  1138.       dirhash = NULL;
  1139.     }
  1140.   return (dirhash);
  1141. }
  1142. static void
  1143. destroy_hash_ent (gpointer key, gpointer value, gpointer user_data)
  1144. {
  1145.   g_free (key);
  1146.   g_free (value);
  1147. }
  1148. static void
  1149. gftp_destroy_dir_hash (GHashTable * dirhash)
  1150. {
  1151.   g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
  1152.   g_hash_table_destroy (dirhash);
  1153. }
  1154. static GList *
  1155. gftp_get_dir_listing (gftp_transfer * transfer, int getothdir)
  1156. {
  1157.   unsigned long *newsize;
  1158.   GHashTable * dirhash;
  1159.   GList * templist;
  1160.   gftp_file * fle;
  1161.   char *newname;
  1162.   if (getothdir && transfer->toreq)
  1163.     dirhash = gftp_gen_dir_hash (transfer->toreq);
  1164.   else 
  1165.     dirhash = NULL; 
  1166.   if (gftp_list_files (transfer->fromreq) != 0)
  1167.     return (NULL);
  1168.   fle = g_malloc (sizeof (*fle));
  1169.   templist = NULL;
  1170.   while (gftp_get_next_file (transfer->fromreq, NULL, fle) > 0)
  1171.     {
  1172.       if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
  1173.         {
  1174.           gftp_file_destroy (fle);
  1175.           continue;
  1176.         }
  1177.       if (dirhash && 
  1178.           (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL)
  1179.         fle->startsize = *newsize;
  1180.       if (transfer->toreq)
  1181.         fle->destfile = g_strconcat (transfer->toreq->directory, "/", 
  1182.                                      fle->file, NULL);
  1183.       newname = g_strconcat (transfer->fromreq->directory, "/", fle->file, NULL);
  1184.       g_free (fle->file);
  1185.       fle->file = newname;
  1186.       templist = g_list_append (templist, fle);
  1187.       fle = g_malloc (sizeof (*fle));
  1188.     }
  1189.   gftp_end_transfer (transfer->fromreq);
  1190.   gftp_file_destroy (fle);
  1191.   g_free (fle);
  1192.   if (dirhash)
  1193.     gftp_destroy_dir_hash (dirhash);
  1194.   return (templist);
  1195. }
  1196. int
  1197. gftp_get_all_subdirs (gftp_transfer * transfer,
  1198.                       void (*update_func) (gftp_transfer * transfer))
  1199. {
  1200.   char *oldfromdir, *oldtodir, *newname;
  1201.   GList * templist, * lastlist;
  1202.   int forcecd, remotechanged;
  1203.   unsigned long *newsize;
  1204.   GHashTable * dirhash;
  1205.   gftp_file * curfle;
  1206.   g_return_val_if_fail (transfer != NULL, -1);
  1207.   g_return_val_if_fail (transfer->fromreq != NULL, -1);
  1208.   g_return_val_if_fail (transfer->files != NULL, -1);
  1209.   if (transfer->toreq != NULL)
  1210.     dirhash = gftp_gen_dir_hash (transfer->toreq);
  1211.   else
  1212.     dirhash = NULL;
  1213.   for (lastlist = transfer->files; ; lastlist = lastlist->next)
  1214.     {
  1215.       curfle = lastlist->data;
  1216.       if (dirhash && 
  1217.           (newsize = g_hash_table_lookup (dirhash, curfle->file)) != NULL)
  1218.         curfle->startsize = *newsize;
  1219.       if (transfer->toreq)
  1220.         curfle->destfile = g_strconcat (transfer->toreq->directory, "/", 
  1221.                                         curfle->file, NULL);
  1222.       newname = g_strconcat (transfer->fromreq->directory, transfer->fromreq->directory[strlen (transfer->fromreq->directory) - 1] == '/' ? "" : "/", curfle->file, NULL);
  1223.       g_free (curfle->file);
  1224.       curfle->file = newname;
  1225.       if (lastlist->next == NULL)
  1226.         break;
  1227.     }
  1228.   if (dirhash)
  1229.     gftp_destroy_dir_hash (dirhash);
  1230.   oldfromdir = oldtodir = NULL;
  1231.   remotechanged = 0;
  1232.   forcecd = 0;
  1233.   for (templist = transfer->files; templist != NULL; templist = templist->next)
  1234.     {
  1235.       curfle = templist->data;
  1236.       if (curfle->isdir)
  1237.         {
  1238.           oldfromdir = transfer->fromreq->directory;
  1239.           transfer->fromreq->directory = curfle->file;
  1240.           if (transfer->toreq)
  1241.             {
  1242.               oldtodir = transfer->toreq->directory;
  1243.               transfer->toreq->directory = curfle->destfile;
  1244.             } 
  1245.           forcecd = 1;
  1246.           if (gftp_set_directory (transfer->fromreq, 
  1247.                                   transfer->fromreq->directory) == 0)
  1248.             {
  1249.               if (curfle->startsize > 0 && transfer->toreq)
  1250.                 {
  1251.                   remotechanged = 1;
  1252.                   if (gftp_set_directory (transfer->toreq, 
  1253.                                           transfer->toreq->directory) != 0)
  1254.                     curfle->startsize = 0;
  1255.                 } 
  1256.               lastlist->next = gftp_get_dir_listing (transfer, 
  1257.                                                      curfle->startsize > 0);
  1258.               if (lastlist->next != NULL)
  1259.                 {
  1260.                   lastlist->next->prev = lastlist;
  1261.                   for (; lastlist->next != NULL; lastlist = lastlist->next);
  1262.                 }
  1263.               transfer->numdirs++;
  1264.               if (update_func)
  1265.                 update_func (transfer);
  1266.             }
  1267.           else
  1268.             curfle->transfer_action = GFTP_TRANS_ACTION_SKIP;
  1269.           transfer->fromreq->directory = oldfromdir;
  1270.           if (transfer->toreq)
  1271.             transfer->toreq->directory = oldtodir;
  1272.         }
  1273.       else
  1274.         {
  1275.           curfle->ascii = gftp_get_file_transfer_mode (curfle->file, 
  1276.                               transfer->fromreq->data_type) == GFTP_TYPE_ASCII;
  1277.           transfer->numfiles++;
  1278.         }
  1279.     }
  1280.   if (forcecd)
  1281.     gftp_set_directory (transfer->fromreq, transfer->fromreq->directory);
  1282.   if (remotechanged && transfer->toreq)
  1283.     gftp_set_directory (transfer->toreq, transfer->toreq->directory);
  1284.   if (update_func)
  1285.     {
  1286.       transfer->numfiles = transfer->numdirs = -1;
  1287.       update_func (transfer);
  1288.     }
  1289.   return (0);
  1290. }
  1291. int
  1292. gftp_get_file_transfer_mode (char *filename, int def)
  1293. {
  1294.   gftp_file_extensions * tempext;
  1295.   GList * templist;
  1296.   int stlen, ret;
  1297.   ret = def;
  1298.   stlen = strlen (filename);
  1299.   for (templist = registered_exts; templist != NULL; templist = templist->next)
  1300.     {
  1301.       tempext = templist->data;
  1302.       if (stlen >= tempext->stlen &&
  1303.           strcmp (&filename[stlen - tempext->stlen], tempext->ext) == 0)
  1304.         {
  1305.           if (toupper (*tempext->ascii_binary == 'A'))
  1306.             ret = GFTP_TYPE_ASCII;
  1307.           else if (toupper (*tempext->ascii_binary == 'B'))
  1308.             ret = GFTP_TYPE_BINARY;
  1309.           break;
  1310.         }
  1311.     }
  1312.   return (ret);
  1313. }
  1314. #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
  1315. int
  1316. get_port (struct addrinfo *addr)
  1317. {
  1318.   struct sockaddr_in * saddr;
  1319.   int port;
  1320.   if (addr->ai_family == AF_INET)
  1321.     {
  1322.       saddr = (struct sockaddr_in *) addr->ai_addr;
  1323.       port = ntohs (saddr->sin_port);
  1324.     }
  1325.   else
  1326.     port = 0;
  1327.   return (port);
  1328. }
  1329. #endif
  1330. int
  1331. gftp_connect_server (gftp_request * request, char *service)
  1332. {
  1333.   char *connect_host, *disphost;
  1334.   int port, sock;
  1335. #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
  1336.   struct addrinfo hints, *res;
  1337.   char serv[8];
  1338.   int errnum;
  1339.   if ((request->use_proxy = gftp_need_proxy (request, service)) < 0)
  1340.     return (-1);
  1341.   else if (request->use_proxy == 1)
  1342.     request->hostp = NULL;
  1343.   memset (&hints, 0, sizeof (hints));
  1344.   hints.ai_flags = AI_CANONNAME;
  1345.   hints.ai_family = AF_INET;
  1346.   hints.ai_socktype = SOCK_STREAM;
  1347.   connect_host = request->use_proxy ? request->proxy_hostname : 
  1348.                                       request->hostname;
  1349.   port = request->use_proxy ? request->proxy_port : request->port;
  1350.   if (request->hostp == NULL)
  1351.     {
  1352.       if (port == 0)
  1353.         strcpy (serv, service); 
  1354.       else
  1355.         snprintf (serv, sizeof (serv), "%d", port);
  1356.       request->logging_function (gftp_logging_misc, request->user_data,
  1357.  _("Looking up %sn"), connect_host);
  1358.       if ((errnum = getaddrinfo (connect_host, serv, &hints, 
  1359.                                  &request->hostp)) != 0)
  1360. {
  1361.   request->logging_function (gftp_logging_error, request->user_data,
  1362.      _("Cannot look up hostname %s: %sn"),
  1363.      connect_host, gai_strerror (errnum));
  1364.   return (-1);
  1365. }
  1366.     }
  1367.   disphost = connect_host;
  1368.   for (res = request->hostp; res != NULL; res = res->ai_next)
  1369.     {
  1370.       disphost = res->ai_canonname ? res->ai_canonname : connect_host;
  1371.       port = get_port (res);
  1372.       if (!request->use_proxy)
  1373.         request->port = port;
  1374.       if ((sock = socket (res->ai_family, res->ai_socktype, 
  1375.                           res->ai_protocol)) < 0)
  1376.         {
  1377.   request->logging_function (gftp_logging_error, request->user_data,
  1378.                                      _("Failed to create a socket: %sn"),
  1379.                                      g_strerror (errno));
  1380.           continue; 
  1381.         } 
  1382.       request->logging_function (gftp_logging_misc, request->user_data,
  1383.  _("Trying %s:%dn"), disphost, port);
  1384.       if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
  1385. {
  1386.   request->logging_function (gftp_logging_error, request->user_data,
  1387.      _("Cannot connect to %s: %sn"),
  1388.      disphost, g_strerror (errno));
  1389.           close (sock);
  1390.           continue;
  1391. }
  1392.       break;
  1393.     }
  1394.   if (res == NULL)
  1395.     {
  1396.       if (request->hostp != NULL)
  1397.         {
  1398.           freeaddrinfo (request->hostp);
  1399.           request->hostp = NULL;
  1400.         }
  1401.       return (-1);
  1402.     }
  1403. #else /* !HAVE_GETADDRINFO */
  1404.   struct sockaddr_in remote_address;
  1405.   struct servent serv_struct;
  1406.   int curhost;
  1407.   if ((request->use_proxy = gftp_need_proxy (request, service)) < 0)
  1408.     return (-1);
  1409.   else if (request->use_proxy == 1)
  1410.     request->hostp = NULL;
  1411.   if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  1412.     {
  1413.       request->logging_function (gftp_logging_error, request->user_data,
  1414.                                  _("Failed to create a socket: %sn"),
  1415.                                  g_strerror (errno));
  1416.       return (-1);
  1417.     }
  1418.   memset (&remote_address, 0, sizeof (remote_address));
  1419.   remote_address.sin_family = AF_INET;
  1420.   connect_host = request->use_proxy ? request->proxy_hostname : 
  1421.                                       request->hostname;
  1422.   port = htons (request->use_proxy ? request->proxy_port : request->port);
  1423.   if (port == 0)
  1424.     {
  1425.       if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
  1426.         {
  1427.           port = htons (21);
  1428.           request->port = 21;
  1429.         }
  1430.       else
  1431.         {
  1432.           port = serv_struct.s_port;
  1433.           request->port = ntohs (serv_struct.s_port);
  1434.         }
  1435.       if (!request->use_proxy)
  1436.         request->port = ntohs (port);
  1437.     }
  1438.   remote_address.sin_port = port;
  1439.   if (request->hostp == NULL)
  1440.     {
  1441.       request->logging_function (gftp_logging_misc, request->user_data,
  1442.  _("Looking up %sn"), connect_host);
  1443.       if (!(request->hostp = r_gethostbyname (connect_host, &request->host,
  1444.                                               NULL)))
  1445.         {
  1446.           request->logging_function (gftp_logging_error, request->user_data,
  1447.                                      _("Cannot look up hostname %s: %sn"),
  1448.                                      connect_host, g_strerror (errno));
  1449.           close (sock);
  1450.           return (-1);
  1451.         }
  1452.     }
  1453.   disphost = NULL;
  1454.   for (curhost = 0; request->host.h_addr_list[curhost] != NULL; curhost++)
  1455.     {
  1456.       disphost = request->host.h_name;
  1457.       memcpy (&remote_address.sin_addr, request->host.h_addr_list[curhost],
  1458.               request->host.h_length);
  1459.       request->logging_function (gftp_logging_misc, request->user_data,
  1460.                                  _("Trying %s:%dn"),
  1461.                                  request->host.h_name, ntohs (port));
  1462.       if (connect (sock, (struct sockaddr *) &remote_address,
  1463.                    sizeof (remote_address)) == -1)
  1464.         {
  1465.           request->logging_function (gftp_logging_error, request->user_data,
  1466.                                      _("Cannot connect to %s: %sn"),
  1467.                                      connect_host, g_strerror (errno));
  1468.         }
  1469.       break;
  1470.     }
  1471.   if (request->host.h_addr_list[curhost] == NULL)
  1472.     {
  1473.       close (sock);
  1474.       return (-1);
  1475.     }
  1476.   port = ntohs (port);
  1477. #endif /* HAVE_GETADDRINFO */
  1478.   request->logging_function (gftp_logging_misc, request->user_data,
  1479.      _("Connected to %s:%dn"), connect_host, port);
  1480.   if (gftp_set_sockblocking (request, sock, 1) == -1)
  1481.     {
  1482.       close (sock);
  1483.       return (-1);
  1484.     }
  1485.   return (sock);
  1486. }
  1487. void
  1488. gftp_set_config_options (gftp_request * request)
  1489. {
  1490.   request->network_timeout = network_timeout;
  1491.   request->retries = retries;
  1492.   request->sleep_time = sleep_time;
  1493.   request->maxkbs = maxkbs;
  1494.   if (request->set_config_options != NULL)
  1495.     request->set_config_options (request);
  1496. }
  1497. void
  1498. gftp_set_sftpserv_path (gftp_request * request, char *path)
  1499. {
  1500.   g_return_if_fail (request != NULL);
  1501.   if (request->sftpserv_path)
  1502.     g_free (request->sftpserv_path);
  1503.   if (path != NULL && *path != '')
  1504.     {
  1505.       request->sftpserv_path = g_malloc (strlen (path) + 1);
  1506.       strcpy (request->sftpserv_path, path);
  1507.     }
  1508.   else
  1509.     request->sftpserv_path = NULL;
  1510. }
  1511. void
  1512. print_file_list (GList * list)
  1513. {
  1514.   gftp_file * tempfle;
  1515.   GList * templist;
  1516.   printf ("--START OF FILE LISTING - TOP TO BOTTOM--n");
  1517.   for (templist = list; ; templist = templist->next)
  1518.     {
  1519.       tempfle = templist->data;
  1520. #if defined (_LARGEFILE_SOURCE)
  1521.       printf ("%s:%s:%lld:%lld:%s:%s:%sn", 
  1522. #else
  1523.       printf ("%s:%s:%ld:%ld:%s:%s:%sn", 
  1524. #endif
  1525.               tempfle->file, tempfle->destfile, 
  1526.               tempfle->size, tempfle->startsize, 
  1527.               tempfle->user, tempfle->group, tempfle->attribs);
  1528.       if (templist->next == NULL)
  1529.         break;
  1530.     }
  1531.   printf ("--START OF FILE LISTING - BOTTOM TO TOP--n");
  1532.   for (; ; templist = templist->prev)
  1533.     {
  1534.       tempfle = templist->data;
  1535. #if defined (_LARGEFILE_SOURCE)
  1536.       printf ("%s:%s:%lld:%lld:%s:%s:%sn", 
  1537. #else
  1538.       printf ("%s:%s:%ld:%ld:%s:%s:%sn", 
  1539. #endif
  1540.               tempfle->file, tempfle->destfile, 
  1541.               tempfle->size, tempfle->startsize, 
  1542.               tempfle->user, tempfle->group, tempfle->attribs);
  1543.       if (templist == list)
  1544.         break;
  1545.     }
  1546.   printf ("--END OF FILE LISTING--n");
  1547. }
  1548. static void
  1549. gftp_free_getline_buffer (gftp_getline_buffer ** rbuf)
  1550. {
  1551.   g_free ((*rbuf)->buffer);
  1552.   g_free (*rbuf);
  1553.   *rbuf = NULL;
  1554. }
  1555. ssize_t
  1556. gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, 
  1557.                char * str, size_t len, int fd)
  1558. {
  1559.   ssize_t ret, retval, rlen, copysize;
  1560.   char *pos, *nextpos;
  1561.   if (*rbuf == NULL)
  1562.     {
  1563.       *rbuf = g_malloc0 (sizeof (**rbuf));
  1564.       (*rbuf)->max_bufsize = len;
  1565.       (*rbuf)->buffer = g_malloc ((*rbuf)->max_bufsize + 1);
  1566.       if ((ret = gftp_read (request, (*rbuf)->buffer, (*rbuf)->max_bufsize, 
  1567.                             fd)) <= 0)
  1568.         {
  1569.           gftp_free_getline_buffer (rbuf);
  1570.           return (ret);
  1571.         }
  1572.       (*rbuf)->buffer[ret] = '';
  1573.       (*rbuf)->cur_bufsize = ret;
  1574.       (*rbuf)->curpos = (*rbuf)->buffer;
  1575.     }
  1576.   retval = -2;
  1577.   do
  1578.     {
  1579.       if ((*rbuf)->cur_bufsize > 0 &&
  1580.           ((pos = strchr ((*rbuf)->curpos, 'n')) != NULL ||
  1581.            ((*rbuf)->curpos == (*rbuf)->buffer && 
  1582.             (*rbuf)->max_bufsize == (*rbuf)->cur_bufsize)))
  1583.         {
  1584.           if (pos != NULL)
  1585.             {
  1586.               nextpos = pos + 1;
  1587.               if (pos > (*rbuf)->curpos && *(pos - 1) == 'r')
  1588.                 pos--;
  1589.               *pos = '';
  1590.             }
  1591.           else
  1592.             nextpos = NULL;
  1593.           strncpy (str, (*rbuf)->curpos, len);
  1594.           retval = pos - (*rbuf)->curpos > len ? len : pos - (*rbuf)->curpos;
  1595.           if (pos != NULL)
  1596.             {
  1597.               if (nextpos - (*rbuf)->buffer >= (*rbuf)->cur_bufsize)
  1598.                 (*rbuf)->cur_bufsize = 0;
  1599.               else
  1600.                 (*rbuf)->curpos = nextpos;
  1601.             }
  1602.           break;
  1603.         }
  1604.       else
  1605.         {
  1606.           if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '')
  1607.             {
  1608.               rlen = (*rbuf)->max_bufsize;
  1609.               pos = (*rbuf)->buffer;
  1610.               copysize = 0;
  1611.             }
  1612.           else
  1613.             {
  1614.               copysize = (*rbuf)->cur_bufsize - ((*rbuf)->curpos - (*rbuf)->buffer);
  1615.               memmove ((*rbuf)->buffer, (*rbuf)->curpos, copysize);
  1616.               pos = (*rbuf)->buffer + copysize;
  1617.               rlen = (*rbuf)->max_bufsize - copysize;
  1618.             }
  1619.           (*rbuf)->curpos = (*rbuf)->buffer;
  1620.           if ((ret = gftp_read (request, pos, rlen, fd)) <= 0)
  1621.             {
  1622.               gftp_free_getline_buffer (rbuf);
  1623.               return (ret);
  1624.             }
  1625.           (*rbuf)->buffer[ret + copysize] = '';
  1626.           (*rbuf)->cur_bufsize = ret + copysize;
  1627.         }
  1628.     }
  1629.   while (retval == -2);
  1630.   return (retval);
  1631. }
  1632. ssize_t 
  1633. gftp_read (gftp_request * request, void *ptr, size_t size, int fd)
  1634. {
  1635.   struct timeval tv;
  1636.   fd_set fset;
  1637.   ssize_t ret;
  1638.   errno = 0;
  1639.   ret = 0;
  1640.   do
  1641.     {
  1642.       FD_ZERO (&fset);
  1643.       FD_SET (fd, &fset);
  1644.       if (request != NULL)
  1645.         tv.tv_sec = request->network_timeout;
  1646.       else
  1647.         tv.tv_sec = network_timeout;
  1648.       tv.tv_usec = 0;
  1649.       ret = select (fd + 1, &fset, NULL, NULL, &tv);
  1650.       if (ret == -1 && errno == EINTR)
  1651.         {
  1652.           if (request && request->cancel)
  1653.             break;
  1654.           else
  1655.             continue;
  1656.         }
  1657.       else if (ret <= 0)
  1658.         {
  1659.           if (request != NULL)
  1660.             {
  1661.               request->logging_function (gftp_logging_error, request->user_data,
  1662.                                          _("Connection to %s timed outn"),
  1663.                                          request->hostname);
  1664.               gftp_disconnect (request);
  1665.             }
  1666.           return (-1);
  1667.         }
  1668.       if ((ret = read (fd, ptr, size)) < 0)
  1669.         {
  1670.           if (errno == EINTR)
  1671.             {
  1672.               if (request != NULL && request->cancel)
  1673.                 break;
  1674.               else
  1675.                 continue;
  1676.              }
  1677.  
  1678.           if (request != NULL)
  1679.             {
  1680.               request->logging_function (gftp_logging_error, request->user_data,
  1681.                                    _("Error: Could not read from socket: %sn"),
  1682.                                     g_strerror (errno));
  1683.               gftp_disconnect (request);
  1684.             }
  1685.           return (-1);
  1686.         }
  1687.     }
  1688.   while (errno == EINTR && !(request != NULL && request->cancel));
  1689.   if (errno == EINTR && request != NULL && request->cancel)
  1690.     {
  1691.       gftp_disconnect (request);
  1692.       return (-1);
  1693.     }
  1694.   return (ret);
  1695. }
  1696. ssize_t 
  1697. gftp_write (gftp_request * request, const char *ptr, size_t size, int fd)
  1698. {
  1699.   struct timeval tv;
  1700.   size_t ret, w_ret;
  1701.   fd_set fset;
  1702.   errno = 0;
  1703.   ret = 0;
  1704.   do
  1705.     {
  1706.       FD_ZERO (&fset);
  1707.       FD_SET (fd, &fset);
  1708.       if (request != NULL)
  1709.         tv.tv_sec = request->network_timeout;
  1710.       else
  1711.         tv.tv_sec = network_timeout;
  1712.       tv.tv_usec = 0;
  1713.       ret = select (fd + 1, NULL, &fset, NULL, &tv);
  1714.       if (ret == -1 && errno == EINTR)
  1715.         {
  1716.           if (request != NULL && request->cancel)
  1717.             break;
  1718.           else
  1719.             continue;
  1720.         }
  1721.       else if (ret <= 0)
  1722.         {
  1723.           if (request != NULL)
  1724.             {
  1725.               request->logging_function (gftp_logging_error, request->user_data,
  1726.                                          _("Connection to %s timed outn"),
  1727.                                          request->hostname);
  1728.               gftp_disconnect (request);
  1729.             }
  1730.           return (-1);
  1731.         }
  1732.       if ((w_ret = write (fd, ptr, size)) < 0)
  1733.         {
  1734.           if (errno == EINTR)
  1735.             {
  1736.               if (request != NULL && request->cancel)
  1737.                 break;
  1738.               else
  1739.                 continue;
  1740.              }
  1741.  
  1742.           if (request != NULL)
  1743.             {
  1744.               request->logging_function (gftp_logging_error, request->user_data,
  1745.                                     _("Error: Could not write to socket: %sn"),
  1746.                                     g_strerror (errno));
  1747.               gftp_disconnect (request);
  1748.             }
  1749.           return (-1);
  1750.         }
  1751.       ptr += w_ret;
  1752.       size -= w_ret;
  1753.       ret += w_ret;
  1754.     }
  1755.   while (size > 0);
  1756.   if (errno == EINTR && request != NULL && request->cancel)
  1757.     {
  1758.       gftp_disconnect (request);
  1759.       return (-1);
  1760.     }
  1761.   return (ret);
  1762. }
  1763. ssize_t 
  1764. gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...)
  1765. {
  1766.   char *tempstr;
  1767.   va_list argp;
  1768.   ssize_t ret;
  1769.   va_start (argp, fmt);
  1770.   tempstr = g_strdup_vprintf (fmt, argp);
  1771.   va_end (argp);
  1772.   ret = gftp_write (request, tempstr, strlen (tempstr), fd);
  1773.   g_free (tempstr);
  1774.   return (ret);
  1775. }
  1776. int
  1777. gftp_set_sockblocking (gftp_request * request, int fd, int non_blocking)
  1778. {
  1779.   int flags;
  1780.   if ((flags = fcntl (fd, F_GETFL, 0)) == -1)
  1781.     {
  1782.       request->logging_function (gftp_logging_error, request->user_data,
  1783.                                  _("Cannot get socket flags: %sn"),
  1784.                                  g_strerror (errno));
  1785.       gftp_disconnect (request);
  1786.       return (-1);
  1787.     }
  1788.   if (non_blocking)
  1789.     flags |= O_NONBLOCK;
  1790.   else
  1791.     flags &= ~O_NONBLOCK;
  1792.   if (fcntl (fd, F_SETFL, flags) == -1)
  1793.     {
  1794.       request->logging_function (gftp_logging_error, request->user_data,
  1795.                                  _("Cannot set socket to non-blocking: %sn"),
  1796.                                  g_strerror (errno));
  1797.       gftp_disconnect (request);
  1798.       return (-1);
  1799.     }
  1800.   return (0);
  1801. }
  1802. void
  1803. gftp_swap_socks (gftp_request * dest, gftp_request * source)
  1804. {
  1805.   g_return_if_fail (dest != NULL);
  1806.   g_return_if_fail (source != NULL);
  1807.   g_return_if_fail (dest->protonum == source->protonum);
  1808.   dest->sockfd = source->sockfd;
  1809.   dest->datafd = source->datafd;
  1810.   dest->cached = 0;
  1811.   if (!source->always_connected)
  1812.     {
  1813.       source->sockfd = -1;
  1814.       source->datafd = -1;
  1815.       source->cached = 1;
  1816.     }
  1817.   if (dest->swap_socks)
  1818.     dest->swap_socks (dest, source);
  1819. }