提问人:mario 提问时间:4/6/2011 最后编辑:Communitymario 更新时间:10/8/2012 访问量:9233
userland multipart/form-data 处理程序
userland multipart/form-data handler
问:
我正在寻找一个插入式包含脚本/类,该脚本/类可以剖析和填充(+原始)并从中解剖和填充。通常PHP自己做。但是由于自动处理对我来说是不够的,并且使 php://input
无法访问[1],我可能会使用这样的东西来防止这种情况:multipart/form-data
$_POST
$_FILES
RewriteRule .* - [E=CONTENT_TYPE:noparsing/for-you-php]
不起作用。实际解决方案需要设置mod_headers和RequestHeader
...
提取过程可能没有那么复杂。但我宁愿使用经过充分测试的解决方案。最重要的是,我更喜欢用于拆分的实现,并密切有效地模拟处理。找到二进制有效负载的末尾对我来说似乎相当棘手,特别是当您必须剥离但可能会遇到仅发送(不允许,但可能)的客户端时。fgets
$_FILES
\r\n
\n
我敢肯定这样的事情存在。但我很难在谷歌上搜索它。有谁知道实现?(PEAR::mimeDecode 可以被黑客入侵以处理表单数据,但这是一个内存消耗。
简而言之,用例:需要保留原始字段名称(包括空格和特殊字符)用于日志记录,但无法始终避免文件上传。
出于装饰目的,POST 请求如下所示:
POST / HTTP/1.1
Host: localhost:8000
Content-Length: 17717
Content-Type: multipart/form-data; boundary=----------3wCuBwquE9P7A4OEylndVx
在一个序列之后,multipart/payload 如下所示:\r\n\r\n
------------3wCuBwquE9P7A4OEylndVx
Content-Disposition: form-data; name="_charset_"
windows-1252
------------3wCuBwquE9P7A4OEylndVx
Content-Disposition: form-data; name=" text field \\ 1 \";inject=1"
text1 te twj sakfkl
------------3wCuBwquE9P7A4OEylndVx
Content-Disposition: form-data; name="file"; filename="dial.png"
Content-Type: image/png
IPNG Z @@@MIHDR@@B`@@B;HF@@@-'.e@@@[email protected]\i@@@FbKGD@?@?@? ='S@@@
@@@GtIMEGYAAU,#}BRU@@@YtEXtComment@Created with GIMPWANW@@ @IDATxZl]w|
答:
已经晚了,我目前无法测试,但以下内容应该可以做你想要的:
//$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>';
评论
name[]
name[]
name[]
boundary=
fgets
;boundary=
$_SERVER["CONTENT_TYPE"]
------whatever
while
$FILES
$FILES[$name][] = array()
$FILES[$name] = array()
--
\r\n
break;
阅读评论,如何在 POST 之前对数据进行编码?让客户端以 UTF8 甚至 URL 编码发送 POST 数据,那么丢失的 ASCII 字符将在不编写您自己的 POST 处理程序的情况下传输,这很可能会引入自己的错误......
评论
application/x-www-urlencoded
multipart/form-data
也许一个新的 php.ini 指令enable_post_data_reading会有所帮助,但似乎它是在 PHP 5.4 中添加的,我仍然有早期版本,所以无法测试它:(
来自PHP手册:
enable_post_data_reading布尔值
禁用此选项会导致 $_POST 和 $_FILES 不填充。读取 postdata 的唯一方法是 然后通过 php://input 流包装器。这可能很有用 代理请求或在内存中高效处理 POST 数据 时尚。
评论
Content-Length
argc
argv
php://stdin
php://input
main/rfc1867.c
_