PHP отображать / скачивать файлы каталогов вне корня веб-сервера - PullRequest
1 голос
/ 08 декабря 2010

Я скачал и добавил эту очень простую систему для просмотра файлов в формате php (называемую Indexer ) на мой сервер XAMPP.

Мой XAMMP-сервер находится на моем диске C :, но я хочу, чтобы Indexer отображал каталог на моем диске G :. Но когда я меняю (как мне кажется, правильные переменные конфигурации), он не работает должным образом.

Вот код, который, я думаю, связан с проблемой:

// configuration  
$Root = realpath("G:/test");  
$AllowDownload = TRUE;  
$WebServerPath = dirname("G:/test");

и далее в коде ...

elseif ($AllowDownload) {  

        echo "<a href=\"http://".getenv("SERVER_NAME").$WebServerPath."/$rel_path".$item["filename"]."\">".$item["name"]."</a>";
    }

Вот что происходит: скрипт действительно правильно отображает содержимое «тестовой» директории на диске G: не работает, потому что php создает ссылку неправильно (я полагаю). Ссылка выглядит так: http://localhostg//[name файла].

Знаете ли вы, как решить эту проблему?

Этот скрипт отлично работает, если я изменяю переменные конфигурации, чтобы он отображал содержимое относительного подкаталога. Также в нем говорится, что переменная $ Root может находиться за пределами корня веб-сервера.

Кроме того, хотя нажатие на ссылку не работает, щелчок правой кнопкой мыши и выбор «Сохранить объект как» позволяет мне сохранить / загрузить файл.

(Не стесняйтесь спрашивать, нужна ли вам дополнительная информация):)

Ответы [ 3 ]

5 голосов
/ 08 декабря 2010

Ваш веб-сервер не может видеть файлы вне DocRoot, поэтому он не может обслуживать файлы через браузер с прямыми ссылками. Вам необходимо распечатать их содержимое в браузере с помощью readfile() с правильно установленными заголовками.

Чтобы это работало, вам нужно изменить конфигурацию в indexer.php:

// this way it works with accentuated letters in Windows
$Root = utf8_decode("G:\test"); // define the directory the index should be created for (can also be located outside the webserver root)

$AllowDownload = TRUE; // enclose file items with the anchor-tag (only makes sense when the files are in the webserver root)
// you need to place download.php in the same directory as indexer.php
$WebServerPath = dirname($_SERVER['SCRIPT_NAME']) . "/download.php?path="; // path where the indexed files can be accessed via a http URL (only required when $AllowDownload is TRUE)

И вы должны поместить новый файл с именем download.php в тот же каталог, что и indexer.php, с таким содержанием:

<?php

// it must be the same as in indexer.php
$Root = utf8_decode("G:\test");

function checkFileIsInsideRootDirectory($path, $root_directory) {
    $realpath = realpath($path);

    if (!file_exists($realpath))
        die("File is not readable: " . $path);

    // detects insecure path with for example /../ in it
    if (strpos($realpath, $root_directory) === false || strpos($realpath, $root_directory) > 0)
        die("Download from outside of the specified root directory is not allowed!");
}

function forceDownload($path) {
    $realpath = realpath($path);

    if (!is_readable($realpath))
        die("File is not readable: " . $path);

    $savename = (basename($path));

    header("Pragmaes: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private", false);
    header("Content-type: application/force-download");
    header("Content-Transfer-Encoding: Binary");
    header("Content-length: " . filesize($path));
    header("Content-disposition: attachment; filename=\"$savename\"");

    readfile("$path");
    exit;
}

if (!isset($_GET['path']))
    die("Path not specified!");

$fullPath = $Root . $_GET['path'];

checkFileIsInsideRootDirectory($fullPath, $Root);

forceDownload($fullPath);
2 голосов
/ 08 декабря 2010

Вы должны изменить конфигурацию apache. Проблема не в скрипте php, проблема в веб-сервере (который не может обслуживать файлы вне корневого веб-каталога, если вы не настроили его).

Попробуйте что-то подобное в вашей конфигурации apache:

Alias /testalias "G:/test"
<Directory "G:/test">
  Options Indexes FollowSymLinks MultiViews ExecCGI
  AllowOverride All
  Order allow,deny
  Allow from all
</Directory>

Это говорит Apache, что нужно обслуживать файлы из G: / test при доступе к http://localhost/testalias

Затем измените конфигурацию вашего скрипта следующим образом:

$WebServerPath = dirname("testalias");

и оно должно работать!

1 голос
/ 08 декабря 2010

Давайте посмотрим на этот скрипт:

$Root = realpath("."); // define the directory the index should be created for (can also be located outside the webserver root)
$AllowDownload = TRUE; // enclose file items with the anchor-tag (only makes sense when the files are in the webserver root)
$WebServerPath = dirname(getenv("SCRIPT_NAME")); // path where the indexed files can be accessed via a http URL (only required when $AllowDownload is TRUE)

Обратите внимание: «имеет смысл только тогда, когда файлы находятся в корне веб-сервера» и «путь, по которому к индексированным файлам можно получить доступ через URL-адрес http».Это означает, что этот сценарий не предназначен для загрузки файлов, которые находятся за пределами корневого каталога веб-сервера.

Однако вы можете изменить этот сценарий, чтобы сделать это так, как указано вего ответ.Затем вы можете отправить свои изменения автору сценария.

Кстати, я проверял это на своем собственном сервере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...