userland multipart/form-data handler userland multipart/form-data handler php php

userland multipart/form-data handler


It's late and I can't test this at the moment but the following should do what you want:

//$boundary = null;if (is_resource($input = fopen('php://input', 'rb')) === true){    while ((feof($input) !== true) && (($line = fgets($input)) !== false))    {        if (isset($boundary) === true)        {            $content = null;            while ((feof($input) !== true) && (($line = fgets($input)) !== false))            {                $line = trim($line);                if (strlen($line) > 0)                {                    $content .= $line . ' ';                }                else if (empty($line) === true)                {                    if (stripos($content, 'name=') !== false)                    {                        $name = trim(stripcslashes(preg_replace('~.*name="?(.+)"?.*~i', '$1', $content)));                        if (stripos($content, 'Content-Type:') !== false)                        {                            $tmpname = tempnam(sys_get_temp_dir(), '');                            if (is_resource($temp = fopen($tmpname, 'wb')) === true)                            {                                while ((feof($input) !== true) && (($line = fgets($input)) !== false) && (strpos($line, $boundary) !== 0))                                {                                    fwrite($temp, preg_replace('~(?:\r\n|\n)$~', '', $line));                                }                                fclose($temp);                            }                            $FILES[$name] = array                            (                                'name' => trim(stripcslashes(preg_replace('~.*filename="?(.+)"?.*~i', '$1', $content))),                                'type' => trim(preg_replace('~.*Content-Type: ([^\s]*).*~i', '$1', $content)),                                'size' => sprintf('%u', filesize($tmpname)),                                'tmp_name' => $tmpname,                                'error' => UPLOAD_ERR_OK,                            );                        }                        else                        {                            $result = null;                            while ((feof($input) !== true) && (($line = fgets($input)) !== false) && (strpos($line, $boundary) !== 0))                            {                                $result .= preg_replace('~(?:\r\n|\n)$~', '', $line);                            }                            if (array_key_exists($name, $POST) === true)                            {                                if (is_array($POST[$name]) === true)                                {                                    $POST[$name][] = $result;                                }                                else                                {                                    $POST[$name] = array($POST[$name], $result);                                }                            }                            else                            {                                $POST[$name] = $result;                            }                        }                    }                    if (strpos($line, $boundary) === 0)                    {                        //break;                    }                }            }        }        else if ((is_null($boundary) === true) && (strpos($line, 'boundary=') !== false))        {            $boundary = "--" . trim(preg_replace('~.*boundary="?(.+)"?.*~i', '$1', $line));        }    }    fclose($input);}echo '<pre>';print_r($POST);echo '</pre>';echo '<hr />';echo '<pre>';print_r($FILES);echo '</pre>';


Maybe a new php.ini directive enable_post_data_reading could help, but it seems it was added in PHP 5.4, I still have the earlier version so could not test it :(

From PHP Manual:

enable_post_data_reading boolean

Disabling this option causes $_POST and $_FILES not to be populated. The only way to read postdata will then be through the php://input stream wrapper. This can be useful to proxy requests or to process the POST data in a memory efficient fashion.


Reading the comments, how about encoding the data before it is POSTed instead? Get the client to send the POST data in UTF8 or even URLencoded, then the ASCII characters that got lost will be transmitted without writing your own POST handler, which could well introduce its own bugs...