lynx-dev
[Top][All Lists]
Advanced

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

lynx-dev [PATCH 2.8.5-dev14] File upload with \0


From: Ilya Zakharevich
Subject: lynx-dev [PATCH 2.8.5-dev14] File upload with \0
Date: Tue, 18 Feb 2003 14:57:48 -0800
User-agent: Mutt/1.4i

This patch implement upload of files with embedded 0s.  It has the following
shortcomings:

a) I do not know the correct syntax of mime headers, so use a very protective
   coding ;-).  It definitely works with Mime generated by lynx (the only
   flavor it needs to work with!).

b) I could not demangle where strncasecmp() is set, so I hardcode it (see the
   first line of the patch);

c) I assume that FREE() is compatible with realloc() (it is now);

d) It is very silly to spend a lot of effort to base64 things, then convert
   it back...

Enjoy,
Ilya

P.S.  Can somebody disable an extra ENTER one needs to press on the upload
      fields?

--- ./WWW/Library/Implementation/HTTP.c-pre     Tue Feb  4 18:00:16 2003
+++ ./WWW/Library/Implementation/HTTP.c Tue Feb 18 14:39:40 2003
@@ -365,6 +365,179 @@ PRIVATE void strip_userid ARGS1(
     }
 }
 
+#define strncasecmp strnicmp
+
+/* Returns BOUNDARY of multipart data or NULL */
+PRIVATE char * get_delim ARGS1(
+       char *,         content_type)
+{
+    static char delim[80];
+    char *s = "multipart/form-data;";
+    int l = strlen(s);
+    
+    if (strncasecmp(content_type, s, l))
+       return NULL;
+    content_type += l;
+    while (*content_type == ' ' || *content_type == '\t')
+       content_type++;
+    s = "boundary=";
+    l = strlen(s);
+    if (strncasecmp(content_type, s, l))
+       return NULL;
+    content_type += l;
+    s = content_type;
+    while (*s && *s != ';')
+       s++;
+    l = s - content_type;
+    if (l + 4 >= sizeof(delim)) {
+       HTAlert ("boundary of multipart/form-data too long to demangle base64");
+       return NULL;
+    }
+    delim[0] = CR;
+    delim[1] = LF;
+    delim[2] = '-';
+    delim[3] = '-';    
+    memcpy(delim + 4, content_type, l);
+    delim[l + 4] = 0;
+    return delim;
+}
+
+/* Demangles base64 part of multipart/form-data in place if needed.  Returns
+   length of the resulting post_data.
+   XXXX: How to make compatible with NOT_ASCII? */
+PRIVATE int demangle_base64 ARGS2(
+       char *,         post_data,
+       char *,         delim)
+{
+    char *s = post_data, *ss, *sss = "base64", *source_e = NULL, *target_e;
+    int l, ll, skip = 2;               /* No CRLF on the first occurence */
+    int is_base64, lll = strlen(sss);
+    char *pre_encoding, *post_encoding;
+
+    delim = get_delim(delim);
+    if (!delim)
+       goto finish;
+    l = strlen(delim);
+    while (s) {
+       s = strstr(s, delim + skip);
+       if (!s) {                       /* Should not happen... */
+           HTAlert ("boundary of multipart/form-data not present");    
+           goto finish;
+       }
+       s += l - skip + 2;              /* Skip CRLF too */
+       skip = 0;                       /* Next should start with CRLF */
+       if (s[-2] == '-' && s[-1] == '-') /* No parts? */
+           goto finish;
+       if (s[-2] != CR || s[-1] != LF) { /* Should not happen... */
+           HTAlert ("boundary of multipart/form-data not CRLF-terminated");
+           goto finish;
+       }
+       ss = "Content-Disposition:";
+       ll = strlen(ss);
+       if (strncasecmp(s, ss, ll)) {
+           HTAlert ("Part of multipart/form-data not Content-Disposition: 
form-data");
+           goto finish;
+       }
+       s += ll;
+       while (*s == ' ' || *s == '\t')
+           s++;
+       ss = "form-data;";
+       ll = strlen(ss);
+       if (strncasecmp(s, ss, ll)) {
+           HTAlert ("Part of multipart/form-data not Content-Disposition: 
form-data");
+           goto finish;
+       }
+       s += ll;
+       while (*s && *s != CR)
+           s++;
+       if (s[0] != CR || s[1] != LF) {
+           HTAlert ("Content-Disposition of a part of multipart/form-data not 
CRLF-terminated");
+           goto finish;
+       }
+       s += 2;
+       /* Skip other headers until Content-Transfer-Encoding */
+       is_base64 = 0;
+       pre_encoding = post_encoding = NULL;
+       ss = "Content-Transfer-Encoding:";
+       ll = strlen(ss);
+       while (1) {
+           if (s[0] == CR && s[1] == LF) {
+               s += 2;                 /* Skip to body */
+               break;
+           }
+           if (!strncasecmp(s, ss, ll)) {
+               if (pre_encoding) {
+                   HTAlert ("Duplicate Content-Transfer-Encoding in a part of 
multipart/form-data");
+                   goto finish;
+               }
+               pre_encoding = s;
+               s += ll;
+               while (*s == ' ' || *s == '\t')
+                   s++;
+               if (!strncasecmp(s, sss, lll)) {
+                   s += lll;
+                   while (*s == ' ' || *s == '\t')
+                       s++;
+                   if (*s == ';' || *s == CR) {
+                       is_base64 = 1;  /* found! */
+                   } else
+                       HTAlert ("Content-Transfer-Encoding: base64 in a part 
of multipart/form-data not CRLF-terminated");
+               }
+           }
+           while (*s && *s != CR)
+               s++;
+           if (s[0] != CR || s[1] != LF) {
+               HTAlert ("Mime header of a part of multipart/form-data not 
CRLF-terminated");
+               goto finish;
+           }
+           s += 2;
+           if (pre_encoding && !post_encoding)
+               post_encoding = s;
+       }
+       if (is_base64) {                /* Now the actual work starts */
+           char *e = strstr(s, delim), c;
+           int cnt;
+
+           if (!e) {
+               HTAlert ("Can't find the end of base64 part of 
multipart/form-data");
+               goto finish;
+           }
+           if (source_e) {             /* Move the skipped part */
+               memmove(target_e, source_e, pre_encoding - source_e);
+               target_e += pre_encoding - source_e;
+           } else {
+               target_e = source_e = pre_encoding;
+           }
+           memmove(target_e, post_encoding, s - post_encoding);
+           target_e += s - post_encoding;
+           source_e = s;
+           while (s != e) {
+               while (s != e && *s != ' ' && *s != '\t' && *s != CR && *s != 
LF)
+                   s++;
+               c = *s;                 /* if s == e */
+               *s = 0;
+               target_e += HTmmdec_base64(target_e, source_e);
+               *s = c;                 /* Will never overwrite output */
+               s++;
+               while (s != e && 
+                      (*s == ' ' || *s == '\t' || *s == CR || *s == LF))
+                   s++;
+               source_e = s;
+           }
+       }
+    }
+  finish:
+    if (source_e) {
+       int rem = strlen(source_e);
+
+       memmove(target_e, source_e, rem);
+       return rem + target_e - post_data;
+    } else
+       return strlen(post_data);
+}
+
+
+
 /*             Load Document from HTTP Server                  HTLoadHTTP()
 **             ==============================
 **
@@ -418,6 +591,7 @@ PRIVATE int HTLoadHTTP ARGS4 (
   int server_status;
   BOOL doing_redirect, already_retrying = FALSE;
   int len = 0;
+  int post_len = 0, command_len;
 
 #ifdef USE_SSL
   BOOL do_connect = FALSE;     /* ARE WE going to use a proxy tunnel ? */
@@ -440,8 +614,10 @@ PRIVATE int HTLoadHTTP ARGS4 (
 
   if (anAnchor->isHEAD)
       do_head = TRUE;
-  else if (anAnchor->post_data)
+  else if (anAnchor->post_data) {
       do_post = TRUE;
+      post_len = demangle_base64(anAnchor->post_data, 
anAnchor->post_content_type);
+  }
 
   if (!url) {
       status = -3;
@@ -1067,18 +1243,21 @@ use_tunnel:
        /*
         * FIXME: Ack!  This assumes non-binary data!  Icky!
         */
-       HTSprintf(&command, "Content-length: %d%c%c",
-                 (anAnchor->post_data)
-                  ? strlen (anAnchor->post_data)
-                  : 0,
-                 CR, LF);
+       HTSprintf(&command, "Content-length: %d%c%c", post_len, CR, LF);
 
        StrAllocCat(command, crlf);     /* Blank line means "end" of headers */
 
-       StrAllocCat(command, anAnchor->post_data);
+       /* XXXX This assumes FREE() is compatible with realloc */
+       command_len = strlen(command);
+       command = realloc(command, command_len + post_len);
+       memcpy(command + command_len, anAnchor->post_data, post_len);
+       command_len += post_len;
     }
-    else
+    else {
        StrAllocCat(command, crlf);     /* Blank line means "end" of headers */
+       command_len = strlen(command);
+    }
+    
 
 #ifdef USE_SSL
   CTRACE((tfp, "Writing:\n%s%s----------------------------------\n",
@@ -1095,11 +1274,11 @@ use_tunnel:
 #ifdef    NOT_ASCII  /* S/390 -- gil -- 0548 */
   {   char *p;
 
-      for ( p = command; p < command + strlen(command); p++ )
+      for ( p = command; p < command + command_len; p++ )
          *p = TOASCII(*p);
   }
 #endif /* NOT_ASCII */
-  status = HTTP_NETWRITE(s, command, (int)strlen(command), handle);
+  status = HTTP_NETWRITE(s, command, (int)command_len, handle);
   FREE(command);
   FREE(linebuf);
   if (status <= 0) {
--- ./WWW/Library/Implementation/HTMIME.h-pre   Wed Jan 22 01:43:12 2003
+++ ./WWW/Library/Implementation/HTMIME.h       Tue Feb 18 13:27:00 2003
@@ -67,7 +67,7 @@ extern HTStream * HTMIMERedirect PARAMS(
   For handling Japanese headers.
 
 */
-extern void HTmmdec_base64 PARAMS((
+extern int HTmmdec_base64 PARAMS((
        char *  t,
        char *  s));
 
--- ./WWW/Library/Implementation/HTMIME.c-pre   Wed Jan 22 01:43:12 2003
+++ ./WWW/Library/Implementation/HTMIME.c       Tue Feb 18 13:33:08 2003
@@ -2080,12 +2080,13 @@ PRIVATE char HTmm64[] =
 PRIVATE char HTmmquote[] = "0123456789ABCDEF";
 PRIVATE int HTmmcont = 0;
 
-PUBLIC void HTmmdec_base64 ARGS2(
+PUBLIC int HTmmdec_base64 ARGS2(
        char *,         t,
        char *,         s)
 {
     int   d, count, j, val;
-    char  buf[LINE_LENGTH], *bp, nw[4], *p;
+    char  *bp, nw[4], *p;
+    char  buf[LINE_LENGTH];
 
     for (bp = buf; *s; s += 4) {
        val = 0;
@@ -2098,6 +2099,7 @@ PUBLIC void HTmmdec_base64 ARGS2(
 
        for (j = 0; j <= count; j++) {
                if (!(p = strchr(HTmm64, s[j]))) {
+                       HTAlert("unexpected char in base64 string");
                        return;
                }
                d = p - HTmm64;
@@ -2116,7 +2118,8 @@ PUBLIC void HTmmdec_base64 ARGS2(
            *bp++ = nw[2];
     }
     *bp = '\0';
-    strcpy(t, buf);
+    memcpy(t, buf, bp + 1 - buf);
+    return bp - buf;
 }
 
 PUBLIC void HTmmdec_quote ARGS2(

; To UNSUBSCRIBE: Send "unsubscribe lynx-dev" to address@hidden

reply via email to

[Prev in Thread] Current Thread [Next in Thread]