Mercurial > gftp.yaz
diff lib/protocols.c @ 950:c7d7a081cd9c
2008-03-04 Brian Masney <masneyb@gftp.org>
* lib/gftp.h lib/socket-connect.c lib/sockutils.c lib/protocols.c
lib/Makefile.am lib/charset-conv.c lib/parse-dir-listing.c - split
protocols.c into smaller files. No changes were made to the moved
functions.
author | masneyb |
---|---|
date | Tue, 04 Mar 2008 12:28:40 +0000 |
parents | 5b681cba67b2 |
children | 63555c9744c2 |
line wrap: on
line diff
--- a/lib/protocols.c Tue Mar 04 12:02:47 2008 +0000 +++ b/lib/protocols.c Tue Mar 04 12:28:40 2008 +0000 @@ -413,246 +413,6 @@ } -#if GLIB_MAJOR_VERSION > 1 - -static /*@null@*/ char * -_gftp_get_next_charset (char **curpos) -{ - char *ret, *endpos; - size_t len, retlen; - - if (**curpos == '\0') - return (NULL); - - for (; **curpos == ' ' || **curpos == '\t'; (*curpos)++); - - if ((endpos = strchr (*curpos, ',')) == NULL) - len = strlen (*curpos) - 1; /* the trailing ',' should be omitted */ - else - len = endpos - *curpos; - - for (retlen = len - 1; - (*curpos)[retlen - 1] == ' ' || (*curpos)[retlen - 1] == '\t'; - retlen--); - - retlen++; /* Needed due to the len - 1 above... */ - ret = g_malloc0 (retlen + 1); - memcpy (ret, *curpos, retlen); - - for (*curpos += len; **curpos == ','; (*curpos)++); - - return (ret); -} - - -static void -_do_show_iconv_error (const char *str, char *charset, int from_utf8, - GError * error) -{ - const char *fromset, *toset; - - if (from_utf8) - { - fromset = "UTF-8"; - toset = charset; - } - else - { - fromset = charset; - toset = "UTF-8"; - } - - printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"), - str, fromset, toset, error->message); -} - - -/*@null@*/ char * -_do_convert_string (gftp_request * request, int is_filename, int force_local, - const char *str, size_t *dest_len, int from_utf8) -{ - char *remote_charsets, *ret, *fromset, *toset, *stpos, *cur_charset; - GError * error; - gsize bread; - - if (request == NULL) - return (NULL); - - if (g_utf8_validate (str, -1, NULL) != from_utf8) - return (NULL); - - error = NULL; - gftp_lookup_request_option (request, "remote_charsets", &remote_charsets); - if (*remote_charsets == '\0' || request->use_local_encoding || - force_local == 1) - { - if (from_utf8) - { - if (is_filename) - ret = g_filename_from_utf8 (str, -1, &bread, dest_len, &error); - else - ret = g_locale_from_utf8 (str, -1, &bread, dest_len, &error); - } - else - { - if (is_filename) - ret = g_filename_to_utf8 (str, -1, &bread, dest_len, &error); - else - ret = g_locale_to_utf8 (str, -1, &bread, dest_len, &error); - } - - if (ret == NULL) - _do_show_iconv_error (str, request->iconv_charset, from_utf8, error); - - return (ret); - } - - if (from_utf8) - { - if (request->iconv_from_initialized) - { - ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread, dest_len, - &error); - if (ret == NULL) - _do_show_iconv_error (str, request->iconv_charset, from_utf8, error); - - return (ret); - } - } - else - { - if (request->iconv_to_initialized) - { - ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread, dest_len, - &error); - if (ret == NULL) - _do_show_iconv_error (str, request->iconv_charset, from_utf8, error); - - return (ret); - } - } - - stpos = remote_charsets; - while ((cur_charset = _gftp_get_next_charset (&stpos)) != NULL) - { - if (from_utf8) - { - fromset = "UTF-8"; - toset = cur_charset; - if ((request->iconv_from = g_iconv_open (toset, fromset)) == (GIConv) -1) - { - g_free (cur_charset); - continue; - } - - error = NULL; - if ((ret = g_convert_with_iconv (str, -1, request->iconv_from, &bread, - dest_len, &error)) == NULL) - { - g_iconv_close (request->iconv_from); - request->iconv_from = NULL; - _do_show_iconv_error (str, cur_charset, from_utf8, error); - g_free (cur_charset); - continue; - } - - request->iconv_from_initialized = 1; - } - else - { - fromset = cur_charset; - toset = "UTF-8"; - if ((request->iconv_to = g_iconv_open (toset, fromset)) == (GIConv) -1) - { - g_free (cur_charset); - continue; - } - - error = NULL; - if ((ret = g_convert_with_iconv (str, -1, request->iconv_to, &bread, - dest_len, &error)) == NULL) - { - g_iconv_close (request->iconv_to); - request->iconv_to = NULL; - _do_show_iconv_error (str, cur_charset, from_utf8, error); - g_free (cur_charset); - continue; - } - - request->iconv_to_initialized = 1; - } - - request->iconv_charset = cur_charset; - return (ret); - } - - return (NULL); -} - -char * -gftp_string_to_utf8 (gftp_request * request, const char *str, size_t *dest_len) -{ - return (_do_convert_string (request, 0, 0, str, dest_len, 0)); -} - - -char * -gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str, - size_t *dest_len) -{ - return (_do_convert_string (request, 0, force_local, str, dest_len, 1)); -} - - -char * -gftp_filename_to_utf8 (gftp_request * request, const char *str, - size_t *dest_len) -{ - return (_do_convert_string (request, 1, 0, str, dest_len, 0)); -} - - -char * -gftp_filename_from_utf8 (gftp_request * request, const char *str, - size_t *dest_len) -{ - return (_do_convert_string (request, 1, 0, str, dest_len, 1)); -} - -#else - -char * -gftp_string_to_utf8 (gftp_request * request, const char *str, size_t dest_len) -{ - return (NULL); -} - - -char * -gftp_string_from_utf8 (gftp_request * request, int force_local, const char *str, - size_t dest_len) -{ - return (NULL); -} - - -char * -gftp_filename_to_utf8 (gftp_request * request, const char *str, size_t dest_len) -{ - return (NULL); -} - - -char * -gftp_filename_from_utf8 (gftp_request * request, int force_local, - const char *str, size_t dest_len) -{ - return (NULL); -} - -#endif - - int gftp_get_next_file (gftp_request * request, const char *filespec, gftp_file * fle) @@ -1157,746 +917,6 @@ } -/* FIXME - clean up this function */ -static int -gftp_need_proxy (gftp_request * request, char *service, char *proxy_hostname, - unsigned int proxy_port) -{ - gftp_config_list_vars * proxy_hosts; - gftp_proxy_hosts * hostname; - size_t hostlen, domlen; - unsigned char addy[4]; - struct sockaddr *addr; - GList * templist; - gint32 netaddr; - char *pos; -#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) - struct addrinfo hints, *hostp; - unsigned int port; - int errnum; - char serv[8]; -#else - struct hostent host, *hostp; -#endif - - gftp_lookup_global_option ("dont_use_proxy", &proxy_hosts); - - if (proxy_hostname == NULL || *proxy_hostname == '\0') - return (0); - else if (proxy_hosts->list == NULL) - return (proxy_hostname != NULL && - *proxy_hostname != '\0'); - - hostp = NULL; -#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) - memset (&hints, 0, sizeof (hints)); - hints.ai_flags = AI_CANONNAME; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - port = request->use_proxy ? proxy_port : request->port; - if (port == 0) - strcpy (serv, service); - else - snprintf (serv, sizeof (serv), "%d", port); - - request->logging_function (gftp_logging_misc, request, - _("Looking up %s\n"), request->hostname); - - if ((errnum = getaddrinfo (request->hostname, serv, &hints, - &hostp)) != 0) - { - request->logging_function (gftp_logging_error, request, - _("Cannot look up hostname %s: %s\n"), - request->hostname, gai_strerror (errnum)); - return (GFTP_ERETRYABLE); - } - - addr = hostp->ai_addr; - -#else /* !HAVE_GETADDRINFO */ - request->logging_function (gftp_logging_misc, request, - _("Looking up %s\n"), request->hostname); - - if (!(hostp = r_gethostbyname (request->hostname, &host, NULL))) - { - request->logging_function (gftp_logging_error, request, - _("Cannot look up hostname %s: %s\n"), - request->hostname, g_strerror (errno)); - return (GFTP_ERETRYABLE); - } - - addr = (struct sockaddr *) host.h_addr_list[0]; - -#endif /* HAVE_GETADDRINFO */ - - templist = proxy_hosts->list; - while (templist != NULL) - { - hostname = templist->data; - if (hostname->domain != NULL) - { - hostlen = strlen (request->hostname); - domlen = strlen (hostname->domain); - if (hostlen > domlen) - { - pos = request->hostname + hostlen - domlen; - if (strcmp (hostname->domain, pos) == 0) - return (0); - } - } - - if (hostname->ipv4_network_address != 0) - { - memcpy (addy, addr, sizeof (*addy)); - netaddr = - (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) | - ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & - hostname->ipv4_netmask; - if (netaddr == hostname->ipv4_network_address) - return (0); - } - templist = templist->next; - } - - return (proxy_hostname != NULL && *proxy_hostname != '\0'); -} - - -static char * -copy_token (/*@out@*/ char **dest, char *source) -{ - /* This function is used internally by gftp_parse_ls () */ - char *endpos, savepos; - - endpos = source; - while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0') - endpos++; - if (*endpos == '\0') - { - *dest = NULL; - return (NULL); - } - - savepos = *endpos; - *endpos = '\0'; - *dest = g_malloc0 ((gulong) (endpos - source + 1)); - strcpy (*dest, source); - *endpos = savepos; - - /* Skip the blanks till we get to the next entry */ - source = endpos + 1; - while ((*source == ' ' || *source == '\t') && *source != '\0') - source++; - return (source); -} - - -static char * -goto_next_token (char *pos) -{ - while (*pos != ' ' && *pos != '\t' && *pos != '\0') - pos++; - - while (*pos == ' ' || *pos == '\t') - pos++; - - return (pos); -} - - -static time_t -parse_vms_time (char *str, char **endpos) -{ - struct tm curtime; - time_t ret; - - /* 8-JUN-2004 13:04:14 */ - memset (&curtime, 0, sizeof (curtime)); - - *endpos = strptime (str, "%d-%b-%Y %H:%M:%S", &curtime); - if (*endpos == NULL) - *endpos = strptime (str, "%d-%b-%Y %H:%M", &curtime); - - if (*endpos != NULL) - { - ret = mktime (&curtime); - for (; **endpos == ' ' || **endpos == '\t'; (*endpos)++); - } - else - { - ret = 0; - *endpos = goto_next_token (str); - if (*endpos != NULL) - *endpos = goto_next_token (*endpos); - } - - return (ret); -} - - -time_t -parse_time (char *str, char **endpos) -{ - struct tm curtime, *loctime; - time_t t, ret; - char *tmppos; - size_t slen; - int i, num; - - slen = strlen (str); - memset (&curtime, 0, sizeof (curtime)); - curtime.tm_isdst = -1; - - if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' && - isdigit ((int) str[3])) - { - /* This is how DOS will return the date/time */ - /* 07-06-99 12:57PM */ - - tmppos = strptime (str, "%m-%d-%y %I:%M%p", &curtime); - } - else if (slen > 4 && isdigit ((int) str[0]) && str[2] == '-' && - isalpha (str[3])) - { - /* 10-Jan-2003 09:14 */ - tmppos = strptime (str, "%d-%h-%Y %H:%M", &curtime); - } - else if (slen > 4 && isdigit ((int) str[0]) && str[4] == '/') - { - /* 2003/12/25 */ - tmppos = strptime (str, "%Y/%m/%d", &curtime); - } - else - { - /* This is how most UNIX, Novell, and MacOS ftp servers send their time */ - /* Jul 06 12:57 or Jul 6 1999 */ - - if (strchr (str, ':') != NULL) - { - tmppos = strptime (str, "%h %d %H:%M", &curtime); - t = time (NULL); - loctime = localtime (&t); - - if (curtime.tm_mon > loctime->tm_mon) - curtime.tm_year = loctime->tm_year - 1; - else - curtime.tm_year = loctime->tm_year; - } - else - tmppos = strptime (str, "%h %d %Y", &curtime); - } - - if (tmppos != NULL) - ret = mktime (&curtime); - else - ret = 0; - - if (endpos != NULL) - { - if (tmppos == NULL) - { - /* We cannot parse this date format. So, just skip this date field - and continue to the next token. This is mainly for the HTTP - support */ - - *endpos = str; - for (num = 0; num < 2 && **endpos != '\0'; num++) - { - for (i=0; - (*endpos)[i] != ' ' && (*endpos)[i] != '\t' && - (*endpos)[i] != '\0'; - i++); - *endpos += i; - - for (i=0; (*endpos)[i] == ' ' || (*endpos)[i] == '\t'; i++); - *endpos += i; - } - } - else - *endpos = tmppos; - } - - return (ret); -} - - -static mode_t -gftp_parse_vms_attribs (char **src, mode_t mask) -{ - char *endpos; - mode_t ret; - - if (*src == NULL) - return (0); - - if ((endpos = strchr (*src, ',')) != NULL) - *endpos = '\0'; - - ret = 0; - if (strchr (*src, 'R') != NULL) - ret |= S_IRUSR | S_IRGRP | S_IROTH; - if (strchr (*src, 'W') != NULL) - ret |= S_IWUSR | S_IWGRP | S_IWOTH; - if (strchr (*src, 'E') != NULL) - ret |= S_IXUSR | S_IXGRP | S_IXOTH; - - *src = endpos + 1; - - return (ret & mask); -} - - -static int -gftp_parse_ls_vms (gftp_request * request, int fd, char *str, gftp_file * fle) -{ - char *curpos, *endpos, tempstr[1024]; - int multiline; - ssize_t len; - - /* .PINE-DEBUG1;1 9 21-AUG-2002 20:06 [MYERSRG] (RWED,RWED,,) */ - /* WWW.DIR;1 1 23-NOV-1999 05:47 [MYERSRG] (RWE,RWE,RE,E) */ - - /* Multiline VMS - $MAIN.TPU$JOURNAL;1 - 1/18 8-JUN-2004 13:04:14 [NUCLEAR,FISSION] (RWED,RWED,RE,) - TCPIP$FTP_SERVER.LOG;29 - 0/18 8-JUN-2004 14:42:04 [NUCLEAR,FISSION] (RWED,RWED,RE,) - TCPIP$FTP_SERVER.LOG;28 - 5/18 8-JUN-2004 13:05:11 [NUCLEAR,FISSION] (RWED,RWED,RE,) - TCPIP$FTP_SERVER.LOG;27 - 5/18 8-JUN-2004 13:03:51 [NUCLEAR,FISSION] (RWED,RWED,RE,) */ - - if ((curpos = strchr (str, ';')) == NULL) - return (GFTP_EFATAL); - - multiline = strchr (str, ' ') == NULL; - - *curpos = '\0'; - if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0) - { - fle->st_mode |= S_IFDIR; - *(curpos - 4) = '\0'; - } - - fle->file = g_strdup (str); - - if (multiline) - { - if (request->get_next_dirlist_line == NULL) - return (GFTP_EFATAL); - - len = request->get_next_dirlist_line (request, fd, tempstr, - sizeof (tempstr)); - if (len <= 0) - return ((int) len); - - for (curpos = tempstr; *curpos == ' ' || *curpos == '\t'; curpos++); - } - else - curpos = goto_next_token (curpos + 1); - - fle->size = gftp_parse_file_size (curpos) * 512; /* Is this correct? */ - - curpos = goto_next_token (curpos); - - fle->datetime = parse_vms_time (curpos, &curpos); - - if (*curpos != '[') - return (GFTP_EFATAL); - - if ((endpos = strchr (curpos, ']')) == NULL) - return (GFTP_EFATAL); - - curpos = goto_next_token (endpos + 1); - if ((curpos = strchr (curpos, ',')) == NULL) - return (0); - curpos++; - - fle->st_mode = gftp_parse_vms_attribs (&curpos, S_IRWXU); - fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXG); - fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXO); - - fle->user = g_strdup (""); - fle->group = g_strdup (""); - - return (0); -} - - -static int -gftp_parse_ls_mvs (char *str, gftp_file * fle) -{ - char *curpos; - - /* Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname */ - /* SVI52A 3390 2003/12/10 8 216 FB 80 27920 PS CARDS.DELETES */ - /* SVI528 3390 2003/12/12 1 5 FB 80 24000 PO CLIST */ - - curpos = goto_next_token (str + 1); - if (curpos == NULL) - return (GFTP_EFATAL); - - curpos = goto_next_token (curpos + 1); - if (curpos == NULL) - return (GFTP_EFATAL); - - fle->datetime = parse_time (curpos, &curpos); - - curpos = goto_next_token (curpos); - if (curpos == NULL) - return (GFTP_EFATAL); - - curpos = goto_next_token (curpos + 1); - if (curpos == NULL) - return (GFTP_EFATAL); - - fle->size = gftp_parse_file_size (curpos) * 55996; - curpos = goto_next_token (curpos + 1); - if (curpos == NULL) - return (GFTP_EFATAL); - - curpos = goto_next_token (curpos + 1); - if (curpos == NULL) - return (GFTP_EFATAL); - - curpos = goto_next_token (curpos + 1); - if (curpos == NULL) - return (GFTP_EFATAL); - - curpos = goto_next_token (curpos + 1); - if (curpos == NULL) - return (GFTP_EFATAL); - - if (strncmp (curpos, "PS", 2) == 0) - fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - else if (strncmp (curpos, "PO", 2) == 0) - fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - else - return (GFTP_EFATAL); - - curpos = goto_next_token (curpos + 1); - - fle->user = g_strdup (_("unknown")); - fle->group = g_strdup (_("unknown")); - fle->file = g_strdup (curpos); - - return (0); -} - - -static int -gftp_parse_ls_eplf (char *str, gftp_file * fle) -{ - char *startpos; - int isdir = 0; - - startpos = str; - while (startpos) - { - startpos++; - switch (*startpos) - { - case '/': - isdir = 1; - break; - case 's': - fle->size = gftp_parse_file_size (startpos + 1); - break; - case 'm': - fle->datetime = strtol (startpos + 1, NULL, 10); - break; - } - startpos = strchr (startpos, ','); - } - - if ((startpos = strchr (str, 9)) == NULL) - return (GFTP_EFATAL); - - if (isdir) - fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - else - fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - - fle->file = g_strdup (startpos + 1); - fle->user = g_strdup (_("unknown")); - fle->group = g_strdup (_("unknown")); - return (0); -} - - -static int -gftp_parse_ls_unix (gftp_request * request, char *str, size_t slen, - gftp_file * fle) -{ - char *endpos, *startpos, *pos, *attribs; - int cols; - - /* If there is no space between the attribs and links field, just make one */ - if (slen > 10) - str[10] = ' '; - - /* Determine the number of columns */ - cols = 0; - pos = str; - while (*pos != '\0') - { - while (*pos != '\0' && *pos != ' ' && *pos != '\t') - { - if (*pos == ':') - break; - pos++; - } - - cols++; - - if (*pos == ':') - { - cols++; - break; - } - - while (*pos == ' ' || *pos == '\t') - pos++; - } - - startpos = str; - /* Copy file attributes */ - if ((startpos = copy_token (&attribs, startpos)) == NULL) - return (GFTP_EFATAL); - - if (strlen (attribs) < 10) - return (GFTP_EFATAL); - - fle->st_mode = gftp_convert_attributes_to_mode_t (attribs); - g_free (attribs); - - if (cols >= 9) - { - /* Skip the number of links */ - startpos = goto_next_token (startpos); - - /* Copy the user that owns this file */ - if ((startpos = copy_token (&fle->user, startpos)) == NULL) - return (GFTP_EFATAL); - - /* Copy the group that owns this file */ - if ((startpos = copy_token (&fle->group, startpos)) == NULL) - return (GFTP_EFATAL); - } - else - { - fle->group = g_strdup (_("unknown")); - if (cols == 8) - { - if ((startpos = copy_token (&fle->user, startpos)) == NULL) - return (GFTP_EFATAL); - } - else - fle->user = g_strdup (_("unknown")); - startpos = goto_next_token (startpos); - } - - if (request->server_type == GFTP_DIRTYPE_CRAY) - { - /* See if this is a Cray directory listing. It has the following format: - drwx------ 2 feiliu g913 DK common 4096 Sep 24 2001 wv */ - if (cols == 11 && strstr (str, "->") == NULL) - { - startpos = goto_next_token (startpos); - startpos = goto_next_token (startpos); - } - } - - /* See if this is a block or character device. We will store the major number - in the high word and the minor number in the low word. */ - if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode) && - (endpos = strchr (startpos, ',')) != NULL) - { - fle->size = (unsigned long) strtol (startpos, NULL, 10) << 16; - - startpos = endpos + 1; - while (*startpos == ' ') - startpos++; - - /* Get the minor number */ - if ((endpos = strchr (startpos, ' ')) == NULL) - return (GFTP_EFATAL); - fle->size |= strtol (startpos, NULL, 10) & 0xFF; - } - else - { - /* This is a regular file */ - if ((endpos = strchr (startpos, ' ')) == NULL) - return (GFTP_EFATAL); - fle->size = gftp_parse_file_size (startpos); - } - - /* Skip the blanks till we get to the next entry */ - startpos = endpos + 1; - while (*startpos == ' ') - startpos++; - - fle->datetime = parse_time (startpos, &startpos); - - /* Skip the blanks till we get to the next entry */ - startpos = goto_next_token (startpos); - - /* Parse the filename. If this file is a symbolic link, remove the -> part */ - if (S_ISLNK (fle->st_mode) && ((endpos = strstr (startpos, "->")) != NULL)) - *(endpos - 1) = '\0'; - - fle->file = g_strdup (startpos); - - /* Uncomment this if you want to strip the spaces off of the end of the file. - I don't want to do this by default since there are valid filenames with - spaces at the end of them. Some broken FTP servers like the Paradyne IPC - DSLAMS append a bunch of spaces at the end of the file. - for (endpos = fle->file + strlen (fle->file) - 1; - *endpos == ' '; - *endpos-- = '\0'); - */ - - return (0); -} - - -static int -gftp_parse_ls_nt (char *str, gftp_file * fle) -{ - char *startpos; - - startpos = str; - fle->datetime = parse_time (startpos, &startpos); - - fle->user = g_strdup (_("unknown")); - fle->group = g_strdup (_("unknown")); - - startpos = goto_next_token (startpos); - - if (startpos[0] == '<') - fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - else - { - fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - fle->size = gftp_parse_file_size (startpos); - } - - startpos = goto_next_token (startpos); - fle->file = g_strdup (startpos); - return (0); -} - - -static int -gftp_parse_ls_novell (char *str, gftp_file * fle) -{ - char *startpos; - - if (str[12] != ' ') - return (GFTP_EFATAL); - - str[12] = '\0'; - fle->st_mode = gftp_convert_attributes_to_mode_t (str); - startpos = str + 13; - - while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0') - startpos++; - - if ((startpos = copy_token (&fle->user, startpos)) == NULL) - return (GFTP_EFATAL); - - fle->group = g_strdup (_("unknown")); - - while (*startpos != '\0' && !isdigit (*startpos)) - startpos++; - - fle->size = gftp_parse_file_size (startpos); - - startpos = goto_next_token (startpos); - fle->datetime = parse_time (startpos, &startpos); - - startpos = goto_next_token (startpos); - fle->file = g_strdup (startpos); - return (0); -} - - -int -gftp_parse_ls (gftp_request * request, const char *lsoutput, gftp_file * fle, - int fd) -{ - char *str, *endpos, tmpchar; - int result, is_vms; - size_t len; - - g_return_val_if_fail (lsoutput != NULL, GFTP_EFATAL); - g_return_val_if_fail (fle != NULL, GFTP_EFATAL); - - str = g_strdup (lsoutput); - memset (fle, 0, sizeof (*fle)); - - len = strlen (str); - if (len > 0 && str[len - 1] == '\n') - str[--len] = '\0'; - if (len > 0 && str[len - 1] == '\r') - str[--len] = '\0'; - - switch (request->server_type) - { - case GFTP_DIRTYPE_CRAY: - case GFTP_DIRTYPE_UNIX: - result = gftp_parse_ls_unix (request, str, len, fle); - break; - case GFTP_DIRTYPE_EPLF: - result = gftp_parse_ls_eplf (str, fle); - break; - case GFTP_DIRTYPE_NOVELL: - result = gftp_parse_ls_novell (str, fle); - break; - case GFTP_DIRTYPE_DOS: - result = gftp_parse_ls_nt (str, fle); - break; - case GFTP_DIRTYPE_VMS: - result = gftp_parse_ls_vms (request, fd, str, fle); - break; - case GFTP_DIRTYPE_MVS: - result = gftp_parse_ls_mvs (str, fle); - break; - default: /* autodetect */ - if (*lsoutput == '+') - result = gftp_parse_ls_eplf (str, fle); - else if (isdigit ((int) str[0]) && str[2] == '-') - result = gftp_parse_ls_nt (str, fle); - else if (str[1] == ' ' && str[2] == '[') - result = gftp_parse_ls_novell (str, fle); - else - { - if ((endpos = strchr (str, ' ')) != NULL) - { - /* If the first token in the string has a ; in it, then */ - /* we'll assume that this is a VMS directory listing */ - tmpchar = *endpos; - *endpos = '\0'; - is_vms = strchr (str, ';') != NULL; - *endpos = tmpchar; - } - else - is_vms = 0; - - if (is_vms) - result = gftp_parse_ls_vms (request, fd, str, fle); - else - result = gftp_parse_ls_unix (request, str, len, fle); - } - break; - } - g_free (str); - - return (result); -} - - static GHashTable * gftp_gen_dir_hash (gftp_request * request, int *ret) { @@ -2322,280 +1342,6 @@ } -#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) -static int -get_port (struct addrinfo *addr) -{ - struct sockaddr_in * saddr; - int port; - - if (addr->ai_family == AF_INET) - { - saddr = (struct sockaddr_in *) addr->ai_addr; - port = ntohs (saddr->sin_port); - } - else - port = 0; - - return (port); -} - - -int -gftp_connect_server_with_getaddr (gftp_request * request, char *service, - char *proxy_hostname, unsigned int proxy_port) -{ - struct addrinfo *hostp, *current_hostp; - char *connect_host, *disphost; - struct addrinfo hints, *res; - intptr_t enable_ipv6; - unsigned int port; - int ret, sock = -1; - char serv[8]; - - if ((ret = gftp_need_proxy (request, service, proxy_hostname, - proxy_port)) < 0) - return (ret); - else - request->use_proxy = ret; - - gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6); - - memset (&hints, 0, sizeof (hints)); - hints.ai_flags = AI_CANONNAME; - - hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET; - hints.ai_socktype = SOCK_STREAM; - - if (request->use_proxy) - { - connect_host = proxy_hostname; - port = proxy_port; - } - else - { - connect_host = request->hostname; - port = request->port; - } - - if (port == 0) - strcpy (serv, service); - else - snprintf (serv, sizeof (serv), "%d", port); - - request->logging_function (gftp_logging_misc, request, - _("Looking up %s\n"), connect_host); - if ((ret = getaddrinfo (connect_host, serv, &hints, - &hostp)) != 0) - { - request->logging_function (gftp_logging_error, request, - _("Cannot look up hostname %s: %s\n"), - connect_host, gai_strerror (ret)); - return (GFTP_ERETRYABLE); - } - - disphost = connect_host; - for (res = hostp; res != NULL; res = res->ai_next) - { - disphost = res->ai_canonname ? res->ai_canonname : connect_host; - port = get_port (res); - if (!request->use_proxy) - request->port = port; - - if ((sock = socket (res->ai_family, res->ai_socktype, - res->ai_protocol)) < 0) - { - request->logging_function (gftp_logging_error, request, - _("Failed to create a socket: %s\n"), - g_strerror (errno)); - continue; - } - - request->logging_function (gftp_logging_misc, request, - _("Trying %s:%d\n"), disphost, port); - - if (connect (sock, res->ai_addr, res->ai_addrlen) == -1) - { - request->logging_function (gftp_logging_error, request, - _("Cannot connect to %s: %s\n"), - disphost, g_strerror (errno)); - close (sock); - continue; - } - - current_hostp = res; - request->ai_family = res->ai_family; - break; - } - - if (res == NULL) - { - if (hostp != NULL) - freeaddrinfo (hostp); - - return (GFTP_ERETRYABLE); - } - - request->remote_addr_len = current_hostp->ai_addrlen; - request->remote_addr = g_malloc0 (request->remote_addr_len); - memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr, - request->remote_addr_len); - - request->logging_function (gftp_logging_misc, request, - _("Connected to %s:%d\n"), connect_host, port); - - return (sock); -} -#endif - - -int -gftp_connect_server_legacy (gftp_request * request, char *service, - char *proxy_hostname, unsigned int proxy_port) -{ - struct sockaddr_in remote_address; - char *connect_host, *disphost; - struct hostent host, *hostp; - struct servent serv_struct; - int ret, sock, curhost; - unsigned int port; - - if ((ret = gftp_need_proxy (request, service, proxy_hostname, - proxy_port)) < 0) - return (ret); - - request->use_proxy = ret; - if (request->use_proxy == 1) - hostp = NULL; - - request->ai_family = AF_INET; - if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - { - request->logging_function (gftp_logging_error, request, - _("Failed to create a IPv4 socket: %s\n"), - g_strerror (errno)); - return (GFTP_ERETRYABLE); - } - - memset (&remote_address, 0, sizeof (remote_address)); - remote_address.sin_family = AF_INET; - - if (request->use_proxy) - { - connect_host = proxy_hostname; - port = proxy_port; - } - else - { - connect_host = request->hostname; - port = request->port; - } - - if (port == 0) - { - if (!r_getservbyname (service, "tcp", &serv_struct, NULL)) - { - request->logging_function (gftp_logging_error, request, - _("Cannot look up service name %s/tcp. Please check your services file\n"), - service); - close (sock); - return (GFTP_EFATAL); - } - - port = ntohs (serv_struct.s_port); - - if (!request->use_proxy) - request->port = port; - } - - remote_address.sin_port = htons (port); - - request->logging_function (gftp_logging_misc, request, - _("Looking up %s\n"), connect_host); - - if (!(hostp = r_gethostbyname (connect_host, &host, NULL))) - { - request->logging_function (gftp_logging_error, request, - _("Cannot look up hostname %s: %s\n"), - connect_host, g_strerror (errno)); - close (sock); - return (GFTP_ERETRYABLE); - } - - disphost = NULL; - for (curhost = 0; - host.h_addr_list[curhost] != NULL; - curhost++) - { - disphost = host.h_name; - memcpy (&remote_address.sin_addr, - host.h_addr_list[curhost], - host.h_length); - request->logging_function (gftp_logging_misc, request, - _("Trying %s:%d\n"), - host.h_name, port); - - if (connect (sock, (struct sockaddr *) &remote_address, - sizeof (remote_address)) == -1) - { - request->logging_function (gftp_logging_error, request, - _("Cannot connect to %s: %s\n"), - connect_host, g_strerror (errno)); - } - break; - } - - if (host.h_addr_list[curhost] == NULL) - { - close (sock); - return (GFTP_ERETRYABLE); - } - - return (sock); -} - - -int -gftp_connect_server (gftp_request * request, char *service, - char *proxy_hostname, unsigned int proxy_port) -{ - int sock; - -#if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR) - sock = gftp_connect_server_with_getaddr (request, service, proxy_hostname, - proxy_port); -#else - sock = gftp_connect_server_legacy (request, service, proxy_hostname, - proxy_port); -#endif - - if (sock < 0) - return (sock); - - if (fcntl (sock, F_SETFD, 1) == -1) - { - request->logging_function (gftp_logging_error, request, - _("Error: Cannot set close on exec flag: %s\n"), - g_strerror (errno)); - close (sock); - return (GFTP_ERETRYABLE); - } - - if (gftp_fd_set_sockblocking (request, sock, 1) < 0) - { - close (sock); - return (GFTP_ERETRYABLE); - } - - request->datafd = sock; - - if (request->post_connect != NULL) - return (request->post_connect (request)); - - return (0); -} - - int gftp_set_config_options (gftp_request * request) { @@ -2649,345 +1395,6 @@ void -gftp_free_getline_buffer (gftp_getline_buffer ** rbuf) -{ - g_free ((*rbuf)->buffer); - g_free (*rbuf); - *rbuf = NULL; -} - - -ssize_t -gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, - char * str, size_t len, int fd) -{ - ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size, - int fd); - char *pos, *nextpos; - size_t rlen, nslen; - int end_of_buffer; - ssize_t ret; - - if (request == NULL || request->read_function == NULL) - read_function = gftp_fd_read; - else - read_function = request->read_function; - - if (*rbuf == NULL) - { - *rbuf = g_malloc0 (sizeof (**rbuf)); - (*rbuf)->max_bufsize = len; - (*rbuf)->buffer = g_malloc0 ((gulong) ((*rbuf)->max_bufsize + 1)); - - if ((ret = read_function (request, (*rbuf)->buffer, - (*rbuf)->max_bufsize, fd)) <= 0) - { - gftp_free_getline_buffer (rbuf); - return (ret); - } - (*rbuf)->buffer[ret] = '\0'; - (*rbuf)->cur_bufsize = ret; - (*rbuf)->curpos = (*rbuf)->buffer; - } - - ret = 0; - while (1) - { - pos = strchr ((*rbuf)->curpos, '\n'); - end_of_buffer = (*rbuf)->curpos == (*rbuf)->buffer && - ((*rbuf)->max_bufsize == (*rbuf)->cur_bufsize || (*rbuf)->eof); - - if ((*rbuf)->cur_bufsize > 0 && (pos != NULL || end_of_buffer)) - { - if (pos != NULL) - { - nslen = pos - (*rbuf)->curpos + 1; - nextpos = pos + 1; - if (pos > (*rbuf)->curpos && *(pos - 1) == '\r') - pos--; - *pos = '\0'; - } - else - { - nslen = (*rbuf)->cur_bufsize; - nextpos = NULL; - - /* This is not an overflow since we allocated one extra byte to - buffer above */ - ((*rbuf)->buffer)[nslen] = '\0'; - } - - strncpy (str, (*rbuf)->curpos, len); - str[len - 1] = '\0'; - (*rbuf)->cur_bufsize -= nslen; - - if (nextpos != NULL) - (*rbuf)->curpos = nextpos; - else - (*rbuf)->cur_bufsize = 0; - - ret = nslen; - break; - } - else - { - if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0') - { - rlen = (*rbuf)->max_bufsize; - pos = (*rbuf)->buffer; - } - else - { - memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize); - pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize; - rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize; - } - - (*rbuf)->curpos = (*rbuf)->buffer; - - if ((*rbuf)->eof) - ret = 0; - else - { - ret = read_function (request, pos, rlen, fd); - if (ret < 0) - { - gftp_free_getline_buffer (rbuf); - return (ret); - } - } - - if (ret == 0) - { - if ((*rbuf)->cur_bufsize == 0) - { - gftp_free_getline_buffer (rbuf); - return (ret); - } - - (*rbuf)->eof = 1; - } - - (*rbuf)->cur_bufsize += ret; - (*rbuf)->buffer[(*rbuf)->cur_bufsize] = '\0'; - } - } - - return (ret); -} - - -ssize_t -gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd) -{ - intptr_t network_timeout; - struct timeval tv; - fd_set fset; - ssize_t ret; - int s_ret; - - g_return_val_if_fail (fd >= 0, GFTP_EFATAL); - - gftp_lookup_request_option (request, "network_timeout", &network_timeout); - - errno = 0; - ret = 0; - FD_ZERO (&fset); - - do - { - FD_SET (fd, &fset); - tv.tv_sec = network_timeout; - tv.tv_usec = 0; - s_ret = select (fd + 1, &fset, NULL, NULL, &tv); - if (s_ret == -1 && (errno == EINTR || errno == EAGAIN)) - { - if (request != NULL && request->cancel) - { - gftp_disconnect (request); - return (GFTP_ERETRYABLE); - } - - continue; - } - else if (s_ret <= 0) - { - if (request != NULL) - { - request->logging_function (gftp_logging_error, request, - _("Connection to %s timed out\n"), - request->hostname); - gftp_disconnect (request); - } - - return (GFTP_ERETRYABLE); - } - - if ((ret = read (fd, ptr, size)) < 0) - { - if (errno == EINTR || errno == EAGAIN) - { - if (request != NULL && request->cancel) - { - gftp_disconnect (request); - return (GFTP_ERETRYABLE); - } - - continue; - } - - if (request != NULL) - { - request->logging_function (gftp_logging_error, request, - _("Error: Could not read from socket: %s\n"), - g_strerror (errno)); - gftp_disconnect (request); - } - - return (GFTP_ERETRYABLE); - } - - break; - } - while (1); - - return (ret); -} - - -ssize_t -gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd) -{ - intptr_t network_timeout; - struct timeval tv; - int ret, s_ret; - ssize_t w_ret; - fd_set fset; - - g_return_val_if_fail (fd >= 0, GFTP_EFATAL); - - gftp_lookup_request_option (request, "network_timeout", &network_timeout); - - errno = 0; - ret = 0; - FD_ZERO (&fset); - - do - { - FD_SET (fd, &fset); - tv.tv_sec = network_timeout; - tv.tv_usec = 0; - s_ret = select (fd + 1, NULL, &fset, NULL, &tv); - if (s_ret == -1 && (errno == EINTR || errno == EAGAIN)) - { - if (request != NULL && request->cancel) - { - gftp_disconnect (request); - return (GFTP_ERETRYABLE); - } - - continue; - } - else if (s_ret <= 0) - { - if (request != NULL) - { - request->logging_function (gftp_logging_error, request, - _("Connection to %s timed out\n"), - request->hostname); - gftp_disconnect (request); - } - - return (GFTP_ERETRYABLE); - } - - w_ret = write (fd, ptr, size); - if (w_ret < 0) - { - if (errno == EINTR || errno == EAGAIN) - { - if (request != NULL && request->cancel) - { - gftp_disconnect (request); - return (GFTP_ERETRYABLE); - } - - continue; - } - - if (request != NULL) - { - request->logging_function (gftp_logging_error, request, - _("Error: Could not write to socket: %s\n"), - g_strerror (errno)); - gftp_disconnect (request); - } - - return (GFTP_ERETRYABLE); - } - - ptr += w_ret; - size -= w_ret; - ret += w_ret; - } - while (size > 0); - - return (ret); -} - - -ssize_t -gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...) -{ - char *tempstr; - va_list argp; - ssize_t ret; - - va_start (argp, fmt); - tempstr = g_strdup_vprintf (fmt, argp); - va_end (argp); - - ret = request->write_function (request, tempstr, strlen (tempstr), fd); - g_free (tempstr); - return (ret); -} - - -int -gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking) -{ - int flags; - - g_return_val_if_fail (fd >= 0, GFTP_EFATAL); - - if ((flags = fcntl (fd, F_GETFL, 0)) < 0) - { - request->logging_function (gftp_logging_error, request, - _("Cannot get socket flags: %s\n"), - g_strerror (errno)); - gftp_disconnect (request); - return (GFTP_ERETRYABLE); - } - - if (non_blocking) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - - if (fcntl (fd, F_SETFL, flags) < 0) - { - request->logging_function (gftp_logging_error, request, - _("Cannot set socket to non-blocking: %s\n"), - g_strerror (errno)); - gftp_disconnect (request); - return (GFTP_ERETRYABLE); - } - - return (0); -} - - -void gftp_swap_socks (gftp_request * dest, gftp_request * source) { g_return_if_fail (dest != NULL);