|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2002-08-07 14:50 UTC] t dot bubeck at reinform dot de
If you use a HTML form together with multipart/form-data encryption, then the browser will send the form data in a POST request surrounded with boundaries. Microsoft Internet Explorer (MSIE 5.0 at least) is violating the HTTP specification (rfc 2616, paragraph 3.7: "Media Types") by repeating the content-type in a wrong syntax. This will break PHP in looking for boundaries of the multiparts and therefore no global variables will be defined containing the form data. This will make it impossible to use PHP together with MSIE to process any form data encoded with "multipart/form-data". This results in many different bugs reported in large PHP projects (e.g. SquirrelMail) which are impossible to fix. Here is the (broken) HTTP request of MSIE: POST /squirrel/src/compose.php HTTP/1.0 Via: 1.0 NDCSTR16 Connection: Keep-Alive Content-Length: 1889 User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt) Content-Type: multipart/form-data; boundary=---------------------------7d29f1d3bad02b2,multipart/form-data; boundary=---------------------------7d29f1d3bad02b2,multipart/form-data; boundary=---------------------------7d29f1d3bad02b2 Host: reinform.hn.org Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */* Accept-Language: de,de,de Referer: http://reinform.hn.org/squirrel/src/compose.php,http://reinform.hn.org/squirrel/src/compose.php,http://reinform.hn.org/squirrel/src/compose.php Pragma: no-cache Cookie: squirrelmail_language=de_DE; key=AW0RUMJgLK4%3D; PHPSESSID=0afb8733761a1723a006ce1676d9aa7b Accept-Encoding: gzip, deflate,gzip, deflate,gzip, deflate -----------------------------7d29f1d3bad02b2 Content-Disposition: form-data; name="session" 7 -----------------------------7d29f1d3bad02b2 Content-Disposition: form-data; name="send_to" -----------------------------7d29f1d3bad02b2 The wrong part is the Content-Type which contains more than a single boundary statement (which is a rfc2616 violation, because the parameters are not seperated by ","). PHP takes everything after the first '=' as the boundary and will therefore look for a boundary "---------------------------7d29f1d3bad02b2,multipart/form-data; boundary=---------------------------7d29f1d3bad02b2,multipart/form-data; boundary=---------------------------7d29f1d3bad02b2" which is never found in the data stream. Therefore no parts are found and no variables are declared. The following (trivial) patch will fix the bug and is based upong the current CVS version of PHP-4.2.2: diff -r -u php-4.2.2-orig/main/rfc1867.c php-4.2.2/main/rfc1867.c --- php-4.2.2-orig/main/rfc1867.c Sat Jul 20 21:17:52 2002 +++ php-4.2.2/main/rfc1867.c Wed Aug 7 20:26:28 2002 @@ -599,7 +599,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) { - char *boundary, *s=NULL, *start_arr=NULL, *array_index=NULL; + char *boundary, *boundary_end, *s=NULL, *start_arr=NULL, *array_index=NULL; char *temp_filename=NULL, *lbuf=NULL, *abuf=NULL; int boundary_len=0, total_bytes=0, cancel_upload=0, is_arr_upload=0, array_len=0, max_file_size=0; zval *http_post_files=NULL; @@ -620,6 +620,10 @@ sapi_module.sapi_error(E_WARNING, "Missing boundary in multipart/form-data POST data"); return; } + /* search for the end of the boundary */ + boundary_end = strchr(boundary, ','); + if ( boundary_end ) *boundary_end = 0; + boundary++; boundary_len = strlen(boundary); Would you please apply the patch? Thanks, Till +-------+-------------------------------------------------------------+ | | dr. tilmann bubeck reinform medien- und | | rein | informationstechnologie AG | | form | cell.: +49 (172) 8 84 29 72 koenigstrasse 80 | | AG | fax : +49 (711) 7 22 77 34 70173 stuttgart / germany | | | email: t.bubeck@reinform.de http://www.reinform.de | +-------+-------------------------------------------------------------+ PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2026 The PHP GroupAll rights reserved. |
Last updated: Tue May 26 04:00:02 2026 UTC |
Here is the HTML page containing the form to send. It is part of "message compose" of SquirrelMail 1.2.7 and is generated by PHP. Do you need the PHP source, too? <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <LINK REL="stylesheet" TYPE="text/css" HREF="/squirrel/themes/css/sans-10.css"> <title>Squirrelmail</title><script language="JavaScript" type="text/javascript"> <!-- function checkForm() { var f = document.forms.length; var i = 0; var pos = -1; while( pos == -1 && i < f ) { var e = document.forms[i].elements.length; var j = 0; while( pos == -1 && j < e ) { if ( document.forms[i].elements[j].type == 'text' ) { pos = j; } j++; } i++; } if( pos >= 0 ) { document.forms[i-1].elements[pos].focus(); } } // --> </script> </head> <BODY TEXT="#841722" BGCOLOR="#FFFFFF" LINK="#c6204a" VLINK="#c6204a" ALINK="#c6204a" onLoad="checkForm();"> <A NAME=pagetop></A> <TABLE BGCOLOR="#FFFFFF" BORDER=0 WIDTH="100%" CELLSPACING=0 CELLPADDING=2> <TR BGCOLOR="#fad6b6" > <TD ALIGN=left> Aktueller Ordner: <B>inbox </B> </TD> <TD ALIGN=right><b><a href="/squirrel/src/signout.php" target="_top">Abmelden</a></b></TD> </TR> <TR BGCOLOR="#FFFFFF"> <TD ALIGN=left> <a href="/squirrel/src/compose.php?mailbox=%23mh%2Finbox" target="right">Mail schreiben</a> <a href="/squirrel/src/addressbook.php" target="right">Adressen</a> <a href="/squirrel/src/folders.php" target="right">Ordner</a> <a href="/squirrel/src/options.php" target="right">Optionen</a> <a href="/squirrel/src/search.php?mailbox=%23mh%2Finbox" target="right">Suchen</a> <a href="/squirrel/src/help.php" target="right">Hilfe</a> </TD> <TD ALIGN="right"><A HREF="http://www.squirrelmail.org/" TARGET="_blank">SquirrelMail</A></TD> </TR> </TABLE> <FORM name=compose action="compose.php" METHOD=POST ENCTYPE="multipart/form-data"> <input type="hidden" name="session" value="1"> <TABLE WIDTH="100%" ALIGN=center CELLSPACING=0 BORDER=0> <TR> <TD BGCOLOR="#FFFFFF" WIDTH="10%" ALIGN=RIGHT> An: </TD><TD BGCOLOR="#FFFFFF" WIDTH="90%"> <INPUT TYPE=text NAME="send_to" VALUE="" SIZE=60><BR> </TD> </TR> <TR> <TD BGCOLOR="#FFFFFF" ALIGN=RIGHT> CC: </TD><TD BGCOLOR="#FFFFFF" ALIGN=LEFT> <INPUT TYPE=text NAME="send_to_cc" SIZE=60 VALUE=""><BR> </TD> </TR> <TR> <TD BGCOLOR="#FFFFFF" ALIGN=RIGHT> BCC: </TD><TD BGCOLOR="#FFFFFF" ALIGN=LEFT> <INPUT TYPE=text NAME="send_to_bcc" VALUE="" SIZE=60><BR> </TD></TR> <TR> <TD BGCOLOR="#FFFFFF" ALIGN=RIGHT> Betreff: </TD><TD BGCOLOR="#FFFFFF" ALIGN=LEFT> <INPUT TYPE=text NAME=subject SIZE=60 VALUE=""></td></tr> <TR><TD> </TD><TD> Priorität: <select name="mailprio"><option value="1">Hoch</option><option value="3" selected>Normal</option><option value="5">Niedrig</option></select> Receipt: <input type="checkbox" name="request_mdn" value=1>On read <input type="checkbox" name="request_dr" value=1>On Delivery <TR><td> </td><td> <INPUT TYPE=SUBMIT NAME="sigappend" VALUE="Signatur"> <input type=submit name="html_addr_search" value="Adressen"> <INPUT TYPE=SUBMIT NAME=send VALUE="Senden"> <input type="submit" name ="draft" value="Entwurf speichern"> <script type="text/javascript"> <!-- document.write("<input type=\"button\" value=\"Rechtschreibpr?fung\" onclick=\"window.open('../plugins/squirrelspell/sqspell_interface.php', 'sqspell', 'status=yes,width=550,height=370,resizable=yes')\">"); //--> </script> </TD></TR> <TR> <TD BGCOLOR="#FFFFFF" COLSPAN=2> <TEXTAREA NAME=body ROWS=20 COLS="76" WRAP="VIRTUAL"> +-------+-------------------------------------------------------------+ | | dr. tilmann bubeck reinform medien- und | | | informationstechnologie AG | | rein | fon : +49 (711) 7 82 76-52 koenigstrasse 80 | | form | fax : +49 (711) 7 82 76-46 70173 stuttgart / germany | | AG | cell.: +49 (172) 8 84 29 72 fon: +49 (711) 7 82 76-50 | | | email: t.bubeck@reinform.de http://www.reinform.de | +-------+-------------------------------------------------------------+ </TEXTAREA><BR> </TD> </TR> <TR><TD COLSPAN=2 ALIGN=LEFT> <INPUT TYPE=SUBMIT NAME=send VALUE="Senden"></TD></TR> <TR> <TD VALIGN=MIDDLE ALIGN=RIGHT> Anhang: </TD> <TD VALIGN=MIDDLE ALIGN=LEFT> <INPUT NAME="attachfile" SIZE=48 TYPE="file"> <input type="submit" name="attach" value="Hinzufügen"> </TD> </TR> </TABLE> <INPUT TYPE=hidden NAME=mailbox VALUE="#mh/inbox"> </FORM></BODY></HTML>I think that rfc2616, Section 2.2 is important: Many HTTP/1.1 header field values consist of words separated by LWS or special characters. These special characters MUST be in a quoted string to be used within a parameter value (as defined in section 3.6). token = 1*<any CHAR except CTLs or separators> separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT In any case you have to remember, that strings could be quoted by '"', so that it is not enought to terminate the boundary after the next "," (as my patch did). To be fully correct, you should be able to deal with something like that: boundary="XXX\"", param=value. However, it may be enough to check for "," and ";": This is the regular expression used by perl's CGI.pm: my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/; It ends a boundary after ";" or ",". My patch only terminates the boundary string after ",". It may be better to also use ";" together with ",".