[PHP-BUG] Req #68605 [NEW]: $_FILES should not only be filled when POST
[email protected] ("lewiscowles at me dot com")
| Newsgroups | php.standards |
|---|---|
| Message-ID | <[email protected]> |
From: lewiscowles at me dot com
Operating system: ALL
PHP version: Irrelevant
Package: PHP Language Specification
Bug Type: Feature/Change Request
Bug description:$_FILES should not only be filled when POST
Description:
------------
basically I am going to have to switch a major part of my app to Python
because I cannot PUT multiple files via CURL custom request. Made worse
by the fact PHP seems to have a bug that cuts off php:/input after the
first file (probably to do with C strings and EOF)
Test script:
---------------
// server receiving data (putEcho.php was used)
<?php $reqMeth = ( isset( $_SERVER['REQUEST_METHOD'] ) ? strtoupper(
$_SERVER['REQUEST_METHOD'] ) : 'GET' ); ?>
<?php
$_PUT = array();
if( $reqMeth == 'PUT' ) {
$putF = fopen( "php://input", "r" );
$tmp = fread( $putF, MAX_POST_SIZE*10 ); // limit maximum PUT size to
maximum POST size (seems reasonable)
fclose($putF);
$_PUT = parse_raw_http_request( $tmp );
}
?>
put:
<?php var_dump( $_PUT ); ?>
file:
<?php var_dump( $_FILES ); ?>
<?php
//
// Functions
//
function parse_raw_http_request($input) {
//var_dump($input);
$a_data = array();
// grab multipart boundary from content type header
$matches = explode( str_ireplace( 'multipart/form-data; boundary=', '',
$_SERVER['CONTENT_TYPE'] ), $input ); //preg_match('/boundary=(.*)$/',
$_SERVER['CONTENT_TYPE'], $matches);
// content type is probably regular form-encoded
if (!count($matches)) {
// we expect regular puts to containt a query string containing data
parse_str(urldecode($input), $a_data);
return $a_data;
}
$boundary = $matches[0];
// split content by boundary and get rid of last -- element
$a_blocks = explode($boundary,$input);//preg_split("/-+$boundary/",
$input);
//array_pop($a_blocks);
// loop data blocks
foreach ($a_blocks as $id => $block) {
if (empty($block)) { continue; }
//var_dump( $block );
// you'll have to var_dump $block to understand this and maybe replace
\n or \r with a visibile char
// parse uploaded files
if (mb_strpos($block, 'application/octet-stream') !== FALSE) {
//var_dump( $block );
// match "name", then everything after "stream" (optional) except for
prepending newlines
preg_match("/name=\"([^\"]*)\".*filename=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/ms",
$block, $matches);
$a_data['files'][$matches[1]]['filename'] = basename( $matches[2] );
//for some reason CURL can send files with an absolute path
$a_data['files'][$matches[1]]['data'] = $matches[3];
} else { // parse all other fields
// match "name" and optional value in between newline sequences
preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/su', $block,
$matches);
$a_data[$matches[1]] = $matches[2];
}
}
return $a_data;
}
// client to send data (name does not matter)
<?php
$data = array(
'text'=>'bob
bob
漢字</textarea>
ghghg
表外字?
表外字?表外字?',
'file1' => new CURLFile( __DIR__.'/need a second monicle.jpg' ),
'kanji'=>'漢字表外字?表外字?表外字?',
'file2' => new CURLFile(
__DIR__.'/10620539_301923573265336_9157682394656180014_n.jpg' )
);
?>
<pre><?php var_dump( json_decode( CURL_REQ(
'http://censored/putEcho.php', 'PUT', $data/*$_POST*/ ), true ) );
?></pre>
<?php
//
// CURL lightweight helper Function...
//
function CURL_REQ( $url, $method, &$data ) {
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $data );
$response = curl_exec( $ch );
return $response;
}
Expected result:
----------------
I expected (although I think I understand why) to be able to manually
parse the results of my request, even if PHP did not support populating
the $_FILES array...
Basically within 15minutes I was able to get this to work with Python,
but a large part of my system is PHP. I am always telling people PHP is
a great language and developers are part of the problem, but it seems to
me that the decision to not populate $_FILES is a bit mad
for desired outcome, I like how python FLASK is able to give me
request.args ($_GET)
request.form ($_PUT or $_POST)
request.files ($_FILES)
and wondered if it was something that could be easily patched into PHP.
In any case I have the C code and will try custom compiling, then
patching, but my weekend is now dead, so it may be some time before I
come up with something and after 20mins python working, it might just be
easier for me to convert HTTP methods to python =(
Actual result:
--------------
well in the example given everything after the first file is missing
from php://input stream, so not even the second var gets through... I
can mitigate this by moving the posted form field values easily, but I
never get more than one file, and I am unsure if it is complete (seems
to end if 255 and 0 if I run ord on the last two bytes)
--
Edit bug report at https://bugs.php.net/bug.php?id=68605&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=68605&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=68605&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=68605&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=68605&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=68605&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=68605&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=68605&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=68605&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=68605&r=support
Expected behavior: https://bugs.php.net/fix.php?id=68605&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=68605&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=68605&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=68605&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=68605&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=68605&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=68605&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=68605&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=68605&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=68605&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=68605&r=mysqlcfg