Какую кодировку ожидает xsendfile?

Похоже, поиск в поиске проблем с xsendfile приводит к ряду совпадений, которые являются противоречивыми / устаревшими.

В целях полного раскрытия информации я беру бета-версию xsendfile 1.0, задокументированную на https://tn123.org/mod_xsendfile/beta/ (этот сайт не часто появляется в результатах поиска, только тот, который не содержит / beta). Я использую его с Apache 2.4 и php 5.4.34 на Linux и Windows. Помимо того, что это последняя версия, мне нужно использовать бета-версию, потому что только бета-версия имеет бинарные файлы Windows, созданные с VC9 для Apache 2.4.

Я сделал ошибку, прочитав документацию, где в описании значения имени файла в заголовке написано:

значение (имя файла), указанное в заголовке, считается закодированным в URL-адресе,
то есть будет выполнено удаление / декодирование URL. Смотрите XSendFileUnescape.
Если вам случится хранить файлы с использованием уже закодированных имен файлов, вы
должен «дважды» кодировать имена …% 20 ->% 2520

И описание XSendFIleUnescape гласит:

Отключение XSendFileUnescape восстановит поведение до версии 1.0
используя необработанное значение заголовка, вместо попытки unescape / url-decode
первый.

Документация об относительных путях ясно показывает, что имя файла на X-SendFile заголовок должен быть полным путем. Поэтому я тщательно проверил свои пути через php urlencode функция.

Конечным результатом для меня всегда была внутренняя ошибка сервера (код состояния 500) как в Linux, так и в Windows. Когда у меня была директива XSendFilePath в server config контекст, о котором говорится в документации, разрешен, я не получил ничего более конкретного в своем журнале ошибок. Но когда я (в конце концов) переместил эту директиву Directory в контексте я получил это в своем журнале ошибок:

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

В конце концов, в отчаянии, я сказал: «Винт документации», и удалил urlencode по пути. И вдруг он начал работать отлично (как Windows, так и Linux) !!!

У меня нет путей с символами не-ASCII, так что все готово. Но я удивляюсь, какой тип кодирования должен применяться, чтобы позволить работать не-ASCII-символам. Если вы гуглите 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 заголовок ??

Еще одно замечание / вопрос
Описание XSendFile использование «apache internals» для отправки файла может заставить вас думать, что он создаст Content-Type заголовок из расширения имени файла, используя mod_mime, Но на самом деле это не так, и примеры показывают явное header() звать Content-Type, Итак, мое продолжение заключается в том, каков «правильный» способ создания этого заголовка из пути, передаваемого в X-SendFileтакой, что гарантированно соответствует тому, что mod_mime будет делать, если мы не использовали X-SendFile? Лучшее, что я мог придумать, это следующий код с использованием PHP fileinfo расширение — но, насколько я знаю, нет особой причины ожидать, что оно будет фактически соответствовать тому, что делает Apache, когда ему дается URL для имени файла.

    $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");

2

Решение

Я не собираюсь принимать это как ответ на вопрос, потому что я все еще не нашел «кодирующую функцию», которая, как ожидают, будет использоваться. Но я нашел эту древнюю документацию по API Apache: http://pedrowa.weba.sk/docs/ApiDoc/apidoc_ap_unescape_url.html. Это документирует возвращаемое значение ap_unescape_url () как:

Возвращает 0 в случае успеха, BAD_REQUEST, если обнаружена неверная escape-последовательность,
или NOT_FOUND, если% 2F (/) найден.

Но, конечно, в PHP и urlencode (), и rawurlencode () кодируют ‘/’ как% 2F.

Очевидно, что любой полный путь, используемый в заголовке XSendFile, должен НЕ быть закодированным с использованием любой из этих функций !!

Мое предположение относительно «лучшего» решения для меня:

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

Я должен признать, что поражен тем, что в документации XSendFile об этом не говорится. И я еще больше удивляюсь тому, что на этот вопрос здесь нет ответов. Должен ли я разместить это на другом сайте Stack Exchange?

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]