NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/42917: ftp(1) fails to preserve HTTP modfication time in non-C locales



>Number:         42917
>Category:       bin
>Synopsis:       ftp(1) fails to preserve HTTP modfication time in non-C locales
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Mar 03 21:55:00 +0000 2010
>Originator:     KAMADA Ken'ichi
>Release:        NetBSD 5.0 and -current
>Organization:
>Environment:
NetBSD mitana.nanohz.org 5.99.24 NetBSD 5.99.24 (MITANA) #200: Mon Mar  1 
15:10:27 CST 2010  
ken%mitana.nanohz.org@localhost:/usr/src/sys/arch/i386/compile/MITANA i386

>Description:
ftp(1) fails to parse Last-Modified HTTP header fields
when it runs in non-C (non-English, more precisely) locales.
This is because the representation of %a of strptime() depends on locales.
Patch attached.

FWIW, while fixing this, I found that rfc2822time() in util.c generates
locale-dependent day of the week in contrast to its name, "RFC 2822".
However, further reading of codes revealed that the function is
only used for human interaction regardless of its name, "RFC 2822" :-)
So I did not touch it.

>How-To-Repeat:
LANG=ja_JP.eucJP /usr/bin/ftp http://something-that-returns-Last-Modified
and look at the mtime of the resulting file.

>Fix:
The patch is against 5.0 and also applied cleanly to the current.

Index: extern.h
===================================================================
RCS file: /cvsroot/src/usr.bin/ftp/extern.h,v
retrieving revision 1.75
diff -u -r1.75 extern.h
--- extern.h    10 May 2008 00:05:31 -0000      1.75
+++ extern.h    3 Mar 2010 19:50:47 -0000
@@ -166,6 +166,7 @@
 void   opts(int, char **);
 void   newer(int, char **);
 void   page(int, char **);
+const char *parse_httpdate(struct tm *parsed, const char *httpdate);
 int    parserate(int, char **, int);
 char   *prompt(void);
 void   proxabort(int);
Index: fetch.c
===================================================================
RCS file: /cvsroot/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.185
diff -u -r1.185 fetch.c
--- fetch.c     28 Apr 2008 20:24:13 -0000      1.185
+++ fetch.c     3 Mar 2010 19:50:48 -0000
@@ -931,21 +931,11 @@
 
                        } else if (match_token(&cp, "Last-Modified:")) {
                                struct tm parsed;
-                               char *t;
+                               const char *t;
 
                                memset(&parsed, 0, sizeof(parsed));
-                                                       /* RFC1123 */
-                               if ((t = strptime(cp,
-                                               "%a, %d %b %Y %H:%M:%S GMT",
-                                               &parsed))
-                                                       /* RFC0850 */
-                                   || (t = strptime(cp,
-                                               "%a, %d-%b-%y %H:%M:%S GMT",
-                                               &parsed))
-                                                       /* asctime */
-                                   || (t = strptime(cp,
-                                               "%a, %b %d %H:%M:%S %Y",
-                                               &parsed))) {
+                               t = parse_httpdate(&parsed, cp);
+                               if (t != NULL) {
                                        parsed.tm_isdst = -1;
                                        if (*t == '\0')
                                                mtime = timegm(&parsed);
Index: util.c
===================================================================
RCS file: /cvsroot/src/usr.bin/ftp/util.c,v
retrieving revision 1.148
diff -u -r1.148 util.c
--- util.c      13 Aug 2008 04:59:13 -0000      1.148
+++ util.c      3 Mar 2010 19:50:49 -0000
@@ -85,6 +85,7 @@
 #include <signal.h>
 #include <libgen.h>
 #include <limits.h>
+#include <locale.h>
 #include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -791,6 +792,31 @@
 }
 
 /*
+ * Parse HTTP-date as per RFC 2616.
+ * Return a pointer to the next character of the consumed date string,
+ * or NULL if failed.
+ */
+const char *
+parse_httpdate(struct tm *parsed, const char *httpdate)
+{
+       const char *t;
+       const char *curlocale;
+
+       /* The representation of %a depends on the current locale. */
+       curlocale = setlocale(LC_TIME, NULL);
+       (void)setlocale(LC_TIME, "C");
+                                                               /* RFC1123 */
+       if ((t = strptime(httpdate, "%a, %d %b %Y %H:%M:%S GMT", parsed)) ||
+                                                               /* RFC0850 */
+           (t = strptime(httpdate, "%a, %d-%b-%y %H:%M:%S GMT", parsed)) ||
+                                                               /* asctime */
+           (t = strptime(httpdate, "%a, %b %d %H:%M:%S %Y", parsed)))
+               ;                       /* do nothing */
+       (void)setlocale(LC_TIME, curlocale);
+       return t;
+}
+
+/*
  * Update global `localcwd', which contains the state of the local cwd
  */
 void



Home | Main Index | Thread Index | Old Index