Первый сайт на PHP

Файловый менеджер в работе



Рисунок 11.3. Файловый менеджер в работе


Комментарий:

Нетрудно заметить, что подобная конструкция весьма уязвима для взлома. В самом деле, - если подставить вместо имени корневой папки - files — имя любой другой папки, находящейся на том же уровне, что и папка files, то сценарий "Патопотрошилки" тихо-спокойно выведет и ее содержимое, - чего, возможно, делать не следует, а оно для этого может быть совсем не предназначено! А если указать в пути вместо имени каталога символы /../ (двумя точками обозначается родительский каталог, одной - текущий), то посетитель сможет добраться и до корневой папки всего сайта, и фактически получит возможность удалять, переименовывать, просматривать все файлы на сайте-аккаунте, так как весь сайт будет в его распоряжении.

Изменить же адресную строку - задача совсем не сложная, просто наилегчайшая. Поэтому такое положение дел, понятно, не так

и безопасно... Следовательно, поэтому в сценарий вывода списка файлов следует добавить проверку содержимого переменной Sfold, в которой путь к текущей папке и передается. - Наверное, на первое время хватит двух условий: чтобы путь к текущей папке начинался с имени корневой папки, в которой содержатся доступные посетителю файлы, и чтобы в этом пути не было символов "..", т. е. - двух точек подряд (в нормальных именах файлов такового встречаться не должно).

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

На странице со списком файлов в какой-либо директории должна быть также ссылка на список файлов в той папке, в которую текущая папка вложена. Проще всего получать такую ссылку на основании пути к текущей папке, попросту отсекая отдюлного пути ее имя.


Впрочем, все это вы увидите в сценарии. Красивому оформлению страницы со списком файлов времени уделять не будем, его вы сможете сделать самостоятельно. Также в начало сценария файлового менеджера и на каждую его страницу вы можете вставить скрипт авторизации, вроде того, который описан в гл. 8-й (только не забудьте, что помещать такой скрипт надо до какого-либо вывода в браузер, будь то команда echo, текст web-страницы или что-то другое.).

Итак, начинаем:

<htmlx?php

Укажем корневую папку аккаунта посетителя - т. е. ту, с файлами и папками в которой ему разрешено работать, и запишем ее имя в переменную для дальнейшего использования в сценарии. Пусть эта папка называется files.

$begin="files";



Комментарий:

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

Теперь проверим:

  • определена ли вообще содержащая путь к отображаемой папке переменная $fold (т. е. присутствует ли она в адресной строке - ее там не будет, если к странице с файловым менеджером обратились по внешней ссылке, а не с этой же страницы по ссылке на какую-либо папку из списка файлов и папок);


  • не содержит ли она двух точек подряд - признака попытки взлома;


  • начинается ли наличествующий в ней путь с имени корневой папки аккаунта (помещенного строчкой выше в переменную Sbegin):

    if ((strpos($fold,$begin)!=0)| (strpos($fold,"..")!=False)($fold==""))

    {


  • Примечание:

    Функция strpos (строка - объект поиска, искомая комбинация символов) возвращает либо номер позиции, на которой в указанной в ее первом параметре строке находится указанная во втором параметре комбинация символов, либо False - если таковая не найдена вообще.



    Чтобы различить возможные результаты работы функции "комбинация символов найдена в строке на позиции 0" и "комбинация символов в строке не найдена", можно использовать при сравнении сочетание трех знаков равенства — это означает проверку на "тождественность ":

    if (strpos ("строка", "символы") ===0) {... будет верно, если "строка" начинается с "символов".

    Можно также проверять результат на принадлежность к целым числам:

    if (is_integer (strpos ("строка ", "символы")==false) {...

    выполнится, только если в "строке" "символы" не найдены.

    и если переменная не определена или путь в ней не начинается с имени корневой папки или содержит две точки подряд, то выведем содержимое корневой папки - для удобства запишем ее имя в переменную $dirct, с которой мы и будем в дальнейшем работать как с содержащей путь к текущей папке:

    $dirct=$begin;

    }

    else

    {

    а если переменная Sfold "в порядке", то в переменную Sdirct поместим именно ее значение:

    $dirct=$fold;

    }

    Выведем заголовок формы менеджера файлов. Заодно и передадим в ссылке на файл со сценарием-обработчиком этой формы (а этот сценарий, согласно нашему плану, располагается в файле zapros.php) путь к текущей папке - в самом деле, откуда обработчик может его еще узнать? При передаче формы переменные, указанные в ссылке на сценарий-обработчик формы, тоже будут ему переданы - вместе с переменными из формы.

    echo ("<form action=zapros.php?folder=$dirct method=post>");

    В том случае, если текущая папка не является корневой, выведем ссылку на родительскую папку - т. е. ту, которая содержит в себе текущую...

    if ($dirct!=$begin) {

    для чего выделим из пути к текущей папке его часть с начала вплоть до последнего слэша - разделителя директорий; это и будет путь к родительской папке (скажем, если путь к текущей папке -f iles/folderl/papkal, то путь к родительской папке будет выглядеть как f iles/f olderl):



    $back=substr ($dirct, 0, strrpos($dirct, "/"));

    Примечание:

    Команда substr (строка, начало выделения, длина выделения) предназначена для выделения из строки ее части. Строка (или переменная, ее содержащая) должна быть указана в первом параметре команды. Второй параметр - позиция, с которой начинается выделяемая часть (вернее, число символов, которые необходимо пропустить до начала выделения части строки), а третий -количество выделяемых символов.

    Команда strrpos (строка, символ) выдает номер позиции последнего появления указанного в ее втором параметре символа в строке, указанной в ее первом параметре. В вышеприведенной строчке она используется для определения длины вырезаемого из полного пути фрагмента — до последнего слэша.

    и выведем ссылку на родительскую папку, попросту передав полученный путь к ней через переменную $fold:

    echo ("<a href=index.рbр?:?о1с1=$bаск>Корневая папка</а><br>");

    Все это делается, естественно, лишь в том случае, если текущая папка - не корневая.

    }

    Теперь можно и сканировать текущую папку. Получаем список файлов в ней (пояснения смотрите в - в описании сценария "Папкопотрошилка"):

    $hdl=opendir($dirct); while ($file = readdir($hdl)) {

    if (($file!="..")&&($file!=".")) { $a[]=$file;

    } }

    closedir($hdl);

    В том случае, если файлы в папке есть...

    if (sizeof($a)>0) {

    отсортируем массив с их именами по алфавиту. К сожалению, при этом имена папок окажутся перемешанными с именами файлов, но делать специальную функцию сортировки пока не будем: asort($a);

    Теперь надо вывести на страницу имена файлов и папок, причем каждое имя должно быть ссылкой на соответствующий файл или папку, а перед именем должен стоять checkbox для возможности выбора соответствующих файлов и папок для совершения над ними действий.

    С каждым именем файла или папки...

    foreach ($a as $k) { поступим следующим образом.

    Примечание:

    Оператор foreach считывает указанную в его параметрах переменную, в данном случае $к, все элементы массива, в данном случае $а, по очереди выполняя каждый раз указанный после него в фигурных скобках код, в котором может использоваться указанная переменная. Foreach будет работать только в РНР 4.0 и выше. Если вы можете использовать лишь РНРЗ, то вместо него можно использовать цикл for, указав в его параметрах величину массива $1.



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

    $full=$dirct."/". $k; Теперь выведем checkbox:

    echo ("<input name=fl[] value=$k type=checkbox>");

    При передаче формы странице-обработчику будет передан массив $fl, состоящий из значений атрибутов value отмеченных checkbox'oe (только отмеченных - неотмеченные игнорируются). А в качестве значений атрибутов value мы указываем имена файлов. Так что сценарию-обработчику будет полностью ясно, с какими файлами ему работать - путь к текущей папке будет передан в переменной в ссылке на обработчик, указанной в заголовке формы, а имена файлов передадутся в массиве $fl.

    Если очередной элемент массива с именами файлов в текущей директории является папкой...

    if (is__dir ($full)==True)

    Примечание:

    Функция is_dir возвращает True, если указанный в ее параметре объект существует и является папкой.

    то выведем ссылку на нее. Вернее, не на нее, а на этот же файл нашего файлового менеджера - index.php, передав ему в качестве пути к текущей папке - в значении переменной Sfold - записанный нами ранее в переменную Sfull полный путь к данной папке:

    echo ("<a href=index.php?fold=$full><b>nariKa $k</bx/a>") ;

    Ну и укажем в качестве текста ссылки название папки, пояснив, что эта ссылка ведет именно на папку (см. Рисунок 11.4).

    В результате перехода по такой ссылке файлу index.php будет передан новый путь - путь к "открываемой" папке - и посетитель сможет увидеть список файлов в ней.

    Если же очередной элемент массива с именами файлов в текущей директории - всего лишь файл...

    }

    else {

    то просто выведем ссылку на него. Тем более что полный путь к нему мы уже ранее записали в переменную. Ну и, естественно, укажем в качестве текста ссылки его имя.

    echo ("<a href=$full>$k</a>");



    }

    После вывода ссылки - либо на файл, либо на папку - выведем разделитель строк, чтобы список имен файлов и папок представлял из себя аккуратный столбик:

    echo ("<br>");

    и перейдем к следующему элементу с именами файлов в текущей директории.

    }

    Все эти действия производятся, если в текущей папке есть файлы. Ну а если файлов нет - то и делать ничего не надо.

    } ?>

    Теперь отобразим кнопки выбора действия над выделенными файлами. Их будет четыре - "Удалить", "Переименовать", "Копировать", "Создать папку" с именами "udal", "ren", "copy", "md" соответственно.

    <br><input type=submit value="Удaлить" name=udal><br><input type=submit | value="nepeименовать" name=renxbrxinput type=submit value="Koпировать" name=copy><br><input type=submit value="Создать папку" name=md>

    Собственно, сам текст сценария закончен...

    < / f ormx /html>

    хотя, бесспорно, внешний вид страницы с ним будет весьма аскетичным (Рисунок 11.4, 11.5). Но художественное оформление страницы - уже ваша прерогатива.


    Содержание раздела