[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
- lynx-dev [PATCH 2.8.5-dev14] File upload with \0,
Ilya Zakharevich <=