xsendfile期望什么编码?

时间:2014-11-05 23:31:26

标签: php apache encoding x-sendfile

似乎谷歌搜索xsendfile问题产生了许多相互矛盾/过时的点击。

为了充分披露,我正在考虑xsendfile 1.0 beta,记录在https://tn123.org/mod_xsendfile/beta/(此网站通常不会显示在搜索结果中,只是没有/ beta的网站)。我在Linux和Windows上使用apache 2.4和php 5.4.34。除了是最新版本之外,我还需要使用测试版,因为只有测试版网站有使用VC9为apache 2.4构建的Windows二进制文件。

我错误地阅读了文档,其中标题中文件名值的描述如下:

  

在   标题给出的值(文件名)被定义为url编码,   即将执行unescaping / url-decoding。请参阅XSendFileUnescape。   如果您碰巧使用已经url编码的文件名存储文件,那么   必须“加倍”编码名称...%20 - > %2520

XSendFIleUnescape的描述说:

  

关闭XSendFileUnescape将恢复1.0之前的行为   使用原始标头值,而不是尝试unescape / url-decode   第一

有关相对路径的文档清楚地表明X-SendFile标题上的文件名应该是完整路径名。所以我通过php的urlencode函数小心地运行了我的路径名。

对我而言,最终结果总是在Linux和Windows上出现服务器内部错误(500状态代码)。当我在server config上下文中使用我的XSendFilePath指令时,文档说明是允许的,我的错误日志中没有更具体的内容。但是当我(最终)将该指令移到Directory上下文时,我毕业于我的错误日志中:

(404)Unknown error: [client 127.0.0.1:20742] xsendfile: bad file name encoding

最终,出于绝望,我说“搞抄了文档”,并删除了路径名上的urlencode。突然间它开始完美运行(Windows和Linux)!!!

我没有任何带有非ASCII字符的路径名,所以我已经完成了设置。但我确实想知道应该采用什么样的编码来允许非ASCII字符工作。如果您使用Google xsendfile: bad file name encoding,则可以在https://github.com/nmaier/mod_xsendfile/blob/master/mod_xsendfile.c找到以下源代码,其中该消息字符串是通过采用以下的真正分支生成的:

   rv = ap_unescape_url(file);
      if (rv != OK) {

但是我找不到ap_unescape_url()的好描述或源代码。除非github上的源已过时,否则该函数将对象为PHP的urlencode()函数执行的简单%编码。作为一个疯狂的猜测我尝试调用ap_escape_url(),但它没有在PHP中定义。因此,将 假设的 编码应用于X-SendFile标题中的pathname参数?

再观察一次/问题 使用“apache internals”发送文件的XSendFile的描述可能会让您认为它将使用Content-Type从文件扩展名构造mod_mime标头。但事实上它没有,并且示例显示header()Content-Type的明确X-SendFile调用。所以我的后续是从传递给mod_mime的路径名构造头的“正确”方法,这样可以保证匹配X-SendFile如果我们不使用的话会做什么fileinfo?我能想到的最好的是使用PHP的 $finfo = new finfo(FILEINFO_MIME); $mime_info = $finfo->file($pathname); if (! strlen($mime_info)) { $mime_info = 'application/octet-stream; charset=binary'; } $basename = basename($pathname); $encoded = "$pathname"; header("Content-Type: $mime_info"); header("Content-Disposition: attachment; filename=\"$basename\""); header("X-SendFile: $encoded"); 扩展的以下代码 - 但据我所知,没有特别的理由期望它实际上与apache在给出文件名的url时所做的相符。

{{1}}

1 个答案:

答案 0 :(得分:2)

我不会接受这个作为问题的答案,因为我还没有找到"""预期使用的编码函数。但我确实找到了这个古老的Apache API文档:http://pedrowa.weba.sk/docs/ApiDoc/apidoc_ap_unescape_url.html。它将ap_unescape_url()的retuen值记录为:

  

成功时返回0,如果找到错误的转义序列则返回BAD_REQUEST,   如果找到%2F(/),则为NOT_FOUND。

但当然在PHP中,urlencode()和rawurlencode()编码' /'如%2F。

很明显,XSendFile标头中使用的任何完整路径名都必须 NOT 使用其中任何一个函数进行urlencoded !!

我猜测最好的"我可以使用的解决方案:

$encoded = str_replace('%2F', '/', rawurlencode($pathname));

我必须承认,我很惊讶XSendFile文档没有提到这一点。而且我更惊讶的是这个问题在这里没有得到任何答案。我应该将其发布在不同的Stack Exchange站点吗?