]> sjero.net Git - wget/commitdiff
[svn] Commit my url.c fix (space as unsafe character) and Jan's
authorhniksic <devnull@localhost>
Tue, 5 Dec 2000 22:29:47 +0000 (14:29 -0800)
committerhniksic <devnull@localhost>
Tue, 5 Dec 2000 22:29:47 +0000 (14:29 -0800)
winnt directory listing parsing.

src/ChangeLog
src/ftp-basic.c
src/ftp-ls.c
src/ftp.c
src/ftp.h
src/url.c

index 324f0b7502f57c64260c44a852bb15604c98db5f..d5acdc160e808b3247c843f2cd555c6f40f74585 100644 (file)
@@ -1,3 +1,8 @@
+2000-12-05  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * url.c (init_unsafe_char_table): Reinstate space as an unsafe
+       char.
+
 2000-11-29  John Summerfield  <summer@OS2.ami.com.au>
 
        * netrc.c (parse_netrc): Get rid of line ending.
index 1b2680ff89110a37398b5b35a4270607c6537af0..8f6f25e1ba207a4fecf1165ed77c79b62df3a341 100644 (file)
@@ -541,7 +541,7 @@ ftp_list (struct rbuf *rbuf, const char *file)
 
 /* Sends the SYST command to the server. */
 uerr_t
-ftp_syst (struct rbuf *rbuf, enum stype *host_type)
+ftp_syst (struct rbuf *rbuf, enum stype *server_type)
 {
   char *request, *respline;
   int nwritten;
@@ -577,12 +577,15 @@ ftp_syst (struct rbuf *rbuf, enum stype *host_type)
   request = strtok (NULL, " ");
 
   if (!strcasecmp (request, "VMS"))
-    *host_type = ST_VMS;
+    *server_type = ST_VMS;
   else
     if (!strcasecmp (request, "UNIX"))
-      *host_type = ST_UNIX;
+      *server_type = ST_UNIX;
     else
-      *host_type = ST_OTHER;
+      if (!strcasecmp (request, "WINDOWS_NT"))
+        *server_type = ST_WINNT;
+      else
+        *server_type = ST_OTHER;
 
   xfree (respline);
   /* All OK.  */
index 61fdfa2a70148aeebb7ca4ab53b29cf2cacde2aa..4f0878f2afed26565853c98fc2ca9c179ab74b1e 100644 (file)
@@ -76,7 +76,7 @@ symperms (const char *s)
    The time stamps are stored in a separate variable, time_t
    compatible (I hope).  The timezones are ignored.  */
 static struct fileinfo *
-ftp_parse_unix_ls (const char *file)
+ftp_parse_unix_ls (const char *file, int ignore_perms)
 {
   FILE *fp;
   static const char *months[] = {
@@ -149,10 +149,28 @@ ftp_parse_unix_ls (const char *file)
          break;
        }
 
-      cur.perms = symperms (tok + 1);
-      DEBUGP (("perms %0o; ", cur.perms));
+      if (ignore_perms)
+       {
+         switch (cur.type)
+           {
+           case FT_PLAINFILE:
+             cur.perms = 420;
+             break;
+           case FT_DIRECTORY:
+             cur.perms = 493;
+             break;
+           default:
+             cur.perms = 1023;
+           }
+         DEBUGP (("implicite perms %0o; ", cur.perms));
+       }
+       else
+         {
+          cur.perms = symperms (tok + 1);
+          DEBUGP (("perms %0o; ", cur.perms));
+        }
 
-      error = ignore = 0;       /* Errnoeous and ignoring entries are
+      error = ignore = 0;       /* Erroneous and ignoring entries are
                                   treated equally for now.  */
       year = hour = min = sec = 0; /* Silence the compiler.  */
       month = day = 0;
@@ -385,6 +403,133 @@ ftp_parse_unix_ls (const char *file)
   return dir;
 }
 
+static struct fileinfo *
+ftp_parse_winnt_ls (const char *file)
+{
+  FILE *fp;
+  int len;
+  int year, month, day;         /* for time analysis */
+  int hour, min, sec;
+  struct tm timestruct;
+
+  char *line, *tok;             /* tokenizer */
+  struct fileinfo *dir, *l, cur; /* list creation */
+
+  fp = fopen (file, "rb");
+  if (!fp)
+    {
+      logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
+      return NULL;
+    }
+  dir = l = NULL;
+
+  /* Line loop to end of file: */
+  while ((line = read_whole_line (fp)))
+    {
+      DEBUGP (("%s\n", line));
+      len = strlen (line);
+      /* Destroy <CR><LF> if present.  */
+      if (len && line[len - 1] == '\n')
+        line[--len] = '\0';
+      if (len && line[len - 1] == '\r')
+        line[--len] = '\0';
+
+      /* Extracting name is a bit of black magic and we have to do it
+         before `strtok' inserted extra \0 characters in the line
+         string. For the moment let us just suppose that the name starts at
+         column 39 of the listing. This way we could also recognize
+         filenames that begin with a series of space characters (but who
+         really wants to use such filenames anyway?). */
+      if (len < 40) continue;
+      tok = line + 39;
+      cur.name = xstrdup(tok);
+      DEBUGP(("Name: '%s'\n", cur.name));
+
+      /* First column: mm-dd-yy */
+      tok = strtok(line, "-");
+      month = atoi(tok);
+      tok = strtok(NULL, "-");
+      day = atoi(tok);
+      tok = strtok(NULL, " ");
+      year = atoi(tok);
+      /* Assuming the epoch starting at 1.1.1970 */
+      if (year <= 70) year += 100;
+
+      /* Second column: hh:mm[AP]M */
+      tok = strtok(NULL,  ":");
+      hour = atoi(tok);
+      tok = strtok(NULL,  "M");
+      min = atoi(tok);
+      /* Adjust hour from AM/PM */
+      tok+=2;
+      if (*tok == 'P') hour += 12;
+      /* Listing does not contain value for seconds */
+      sec = 0;
+
+      DEBUGP(("YYYY/MM/DD HH:MM - %d/%02d/%02d %02d:%02d\n", 
+              year+1900, month, day, hour, min));
+      
+      /* Build the time-stamp (copy & paste from above) */
+      timestruct.tm_sec   = sec;
+      timestruct.tm_min   = min;
+      timestruct.tm_hour  = hour;
+      timestruct.tm_mday  = day;
+      timestruct.tm_mon   = month;
+      timestruct.tm_year  = year;
+      timestruct.tm_wday  = 0;
+      timestruct.tm_yday  = 0;
+      timestruct.tm_isdst = -1;
+      cur.tstamp = mktime (&timestruct); /* store the time-stamp */
+
+      DEBUGP(("Timestamp: %ld\n", cur.tstamp));
+
+      /* Third column: Either file length, or <DIR>. We also set the
+         permissions (guessed as 0644 for plain files and 0755 for
+         directories as the listing does not give us a clue) and filetype
+         here. */
+      tok = strtok(NULL, " ");
+      while (*tok == '\0')  tok = strtok(NULL, " ");
+      if (*tok == '<')
+      {
+        cur.type  = FT_DIRECTORY;
+        cur.size  = 0;
+        cur.perms = 493; /* my gcc does not like 0755 ?? */
+        DEBUGP(("Directory\n"));
+      }
+      else
+      {
+        cur.type  = FT_PLAINFILE;
+        cur.size  = atoi(tok);
+        cur.perms = 420; /* 0664 octal */
+        DEBUGP(("File, size %ld bytes\n", cur.size));
+      }
+
+      cur.linkto = NULL;
+
+      /* And put everything into the linked list */
+      if (!dir)
+      {
+        l = dir = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+        memcpy (l, &cur, sizeof (cur));
+        l->prev = l->next = NULL;
+      }
+      else
+      {
+        cur.prev = l;
+        l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+        l = l->next;
+        memcpy (l, &cur, sizeof (cur));
+        l->next = NULL;
+      }
+
+      xfree(line);
+    }
+
+  fclose(fp);
+  return dir;
+}
+
+
 #ifdef HAVE_FTPPARSE
 
 /* This is a "glue function" that connects the ftpparse interface to
@@ -477,12 +622,31 @@ ftp_parse_nonunix_ls (const char *file)
 struct fileinfo *
 ftp_parse_ls (const char *file, const enum stype system_type)
 {
-  if (system_type == ST_UNIX)
+  switch (system_type)
     {
-      return ftp_parse_unix_ls (file);
+    case ST_UNIX:
+      return ftp_parse_unix_ls (file, FALSE);
+    case ST_WINNT:
+      {
+       /* Detect whether the listing is simulating the UNIX format */
+       FILE *fp;
+       int   c;
+       fp = fopen (file, "rb");
+       if (!fp)
+       {
+         logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
+         return NULL;
     }
+       c = fgetc(fp);
+       fclose(fp);
+       /* If the first character of the file is '0'-'9', it's WINNT
+          format. */
+       if (c >= '0' && c <='9')
+         return ftp_parse_winnt_ls (file);
   else
-    {
+         return ftp_parse_unix_ls (file, TRUE);
+      }
+    default:
 #ifdef HAVE_FTPPARSE
       return ftp_parse_nonunix_ls (file);
 #else
index 46677d6b5be5382ce28c67b00d74eee1a4f97aa5..8ce71fd66b89bdf340d882ce118afc4abbba6d68 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -353,6 +353,7 @@ Error in server response, closing control connection.\n"));
          /* Change working directory. If the FTP host runs VMS and
              the path specified is absolute, we will have to convert
              it to VMS style as VMS does not like leading slashes */
+         DEBUGP (("changing working directory\n"));
          if (*(u->dir) == '/')
            {
              int pwd_len = strlen (pwd);
@@ -375,6 +376,7 @@ Error in server response, closing control connection.\n"));
                  }
                  break;
                case ST_UNIX:
+               case ST_WINNT:
                  /* pwd_len == 1 means pwd = "/", but u->dir begins with '/'
                     already */
                  if (pwd_len > 1)
index 61c7240006545f3b67588b5301ccb60d80cc426b..0fa0a164c15ea5ea725169f6f3fb60036a8aacfd 100644 (file)
--- a/src/ftp.h
+++ b/src/ftp.h
@@ -26,6 +26,7 @@ enum stype
 {
   ST_UNIX,
   ST_VMS,
+  ST_WINNT,
   ST_OTHER
 };
   
index dbd19a82713711dd80393bda81f9d89e9c23b22e..eea36a10d865d0e7ad7cea42735921a73ca560d2 100644 (file)
--- a/src/url.c
+++ b/src/url.c
@@ -176,6 +176,7 @@ init_unsafe_char_table (void)
   int i;
   for (i = 0; i < 256; i++)
     if (i < 32 || i >= 127
+       || i == ' '
        || i == '<'
        || i == '>'
        || i == '\"'