Программа: Перечень каталогов веб-сервера

Программа web-ls.php, показанная в примере 19.4, выводит сведения о файлах корневого каталога документов веб-сервера, отформатированные аналогично выводу UNIX-команды ls. Ссылки на имена файлов выполнены так, чтобы можно было загрузить каждый файл, а
ссылки на имена каталогов позволяют просматривать каждый каталог.

Большинство строк предназначены для построения легкого для чтения представления прав доступа к файлу, но суть программы в цикле while в ее конце. Метод $d->read() дает имя каждого файла в каталоге.

Затем функция lstat() извлекает информацию, а функция printf() выводит отформатированную информацию об этом файле. Функция mode_string() и константы, которые она использует, преобразуют восьмеричное представление режима файла (т. е. 35316) в более легкую для чтения строку (т. е. -rwsrw-r--).

Пример 19.4. web-ls.php

/* Битовые маски для определения прав доступа к файлу и типа.
* Имена и значения, перечисленные ниже, POSIX-совместимы, отдельные системы
* могут иметь свои собственные расширения.
*/
define('S_IFMT',0170000); // маска для всех типов
define('S_IFSOCK',0140000); // тип: сокет
define('S_IFLNK',0120000); // тип: символическая ссылка
define('S_IFREG',0100000); // тип: обычный файл
define('S_IFBLK',0060000); // тип: блочное устройство
define('S_IFDIR',0040000); // тип: каталог
define('S_IFCHR',0020000); // тип: символьное устройство
define('S_IFIFO',0010000); // тип: fifo
define('S_ISUID',0004000); // бит смены идентификатора
пользователя (set-uid)
define('S_ISGID',0002000); // бит смены идентификатора группы (set-gid)
define('S_ISVTX',0001000); // sticky-бит (липкий бит)
define('S_IRWXU',00700); // маска для прав доступа владельца
define('S_IRUSR',00400); // владелец: право на чтение
define('S_IWUSR',00200); // владелец: право на запись
define('S_IXUSR',00100); // владелец: право на выполнение
define('S_IRWXG',00070); // маска для прав доступа группы
define('S_IRGRP',00040); // группа: право на чтение
define('S_IWGRP',00020); // группа: право на запись
define('S_IXGRP',00010); // группа: право на выполнение
define('S_IRWXO',00007); // маска для прав доступа остальных
define('S_IROTH',00004); // остальные: право на чтение
define('S_IWOTH',00002); // остальные: право на запись
define('S_IXOTH',00001); // остальные: право на выполнение

/* mode_string() – это вспомогательная функция, которая принимает
* восьмеричный режим и возвращает десятисимвольную строку, представляющую
* тип файла и права доступа, которые соответствуют восьмеричному режиму.
* Это PHP-версия функции mode_string() в пакете файловых утилит GNU.
*/
function mode_string($mode) {
$s = array();
// set type letter
if (($mode & S_IFMT) == S_IFBLK) {
$s[0] = 'b';
} elseif (($mode & S_IFMT) == S_IFCHR) {
$s[0] = 'c';
} elseif (($mode & S_IFMT) == S_IFDIR) {
$s[0] = 'd';
} elseif (($mode & S_IFMT) == S_IFREG) {
$s[0] = '-';
} elseif (($mode & S_IFMT) == S_IFIFO) {
$s[0] = 'p';
} elseif (($mode & S_IFMT) == S_IFLNK) {
$s[0] = 'l';
} elseif (($mode & S_IFMT) == S_IFSOCK) {
$s[0] = 's';
}
// устанавливаем права доступа пользователя
$s[1] = $mode & S_IRUSR ? 'r' : '-';
$s[2] = $mode & S_IWUSR ? 'w' : '-';
$s[3] = $mode & S_IXUSR ? 'x' : '-';
// устанавливаем права доступа группы
$s[4] = $mode & S_IRGRP ? 'r' : '-';
$s[5] = $mode & S_IWGRP ? 'w' : '-';
$s[6] = $mode & S_IXGRP ? 'x' : '-';
// устанавливаем права доступа остальных
$s[7] = $mode & S_IROTH ? 'r' : '-';
$s[8] = $mode & S_IWOTH ? 'w' : '-';
$s[9] = $mode & S_IXOTH ? 'x' : '-';
// устанавливаем символы выполнения для set-uid, set-gid и sticky
if ($mode & S_ISUID) {
if ($s[3] != 'x') {
// set-uid, но не исполняемый владельцем
$s[3] = 'S';
} else {
$s[3] = 's';
}
}
if ($mode & S_ISGID) {
if ($s[6] != 'x') {
// set-gid, но не исполняемый группой
$s[6] = 'S';
} else {
$s[6] = 's';
}
}
if ($mode & S_ISVTX) {
if ($s[9] != 'x') {
// sticky, но не исполняемый остальными
$s[9] = 'T';
} else {
$s[9] = 't';
}
}
// возвращаем отформатированную строку
return join('',$s);
}
// Начинаем в корневом документальном каталоге, если ничего не указано
if (isset($_REQUEST['dir'])) {
$dir = $_REQUEST['dir'];
} else {
$dir = '';
}
// находим $dir в файловой системе
$real_dir = realpath($_SERVER['DOCUMENT_ROOT'].$dir);
// проверяем, что $real_dir находится в документальном корневом каталоге
if (! preg_match('/^'.preg_quote($_SERVER['DOCUMENT_ROOT'],'/').'/',
$real_dir)) {
die("$dir is not inside the document root");
}
// канонизируем $dir, удаляя из его начала корневой документальный каталог
$dir = substr_replace($real_dir,'',0,strlen($_SERVER['DOCUMENT_ROOT']));
// мы открываем каталог?
if (! is_dir($real_dir)) {
die("$real_dir is not a directory");
}
// открываем указанный каталог
$d = dir($real_dir) or die("can't open $real_dir: $php_errormsg");
print '';
// читаем каждое вхождение в каталоге
while (false !== ($f = $d->read())) {
// получаем информацию об этом файле
$s = lstat($d->path.'/'.$f);
// переводим идентификатор пользователя в имя пользователя
$user_info = posix_getpwuid($s['uid']);
// переводим идентификатор группы в имя группы
$group_info = posix_getgrgid($s['gid']);
// форматируем данные для улучшения читаемости
$date = strftime('%b %e %H:%M',$s['mtime']);
// переводим восьмеричный режим в читаемую строку
$mode = mode_string($s['mode']);
$mode_type = substr($mode,0,1);
if (($mode_type == 'c') || ($mode_type == 'b')) {
/* если это блочное или символьное устройство, то выводим старший
* и младший тип устройства вместо размера файла */
$major = ($s['rdev'] >> 8) & 0xff;
$minor = $s['rdev'] & 0xff;
$size = sprintf('%3u, %3u',$major,$minor);
} else {
$size = $s['size'];
}
// форматируем вокруг имени файла
// нет ссылки на текущий каталог
if ('.' == $f) {
$href = $f;
} else {
// не включаем «..» в ссылку на родительский каталог
if ('..' == $f) {
$href = urlencode(dirname($dir));
} else {
$href = urlencode($dir) .


'/' . urlencode($f);
}
/* все, за исключением "/", должно быть в кодировке URL */
$href = str_replace('%2F','/',$href);
// просматриваем другие каталоги с помощью веб-команды ls
if (is_dir(realpath($d->path . '/' . $f))) {
$href = sprintf('
%s',
$_SERVER['PHP_SELF'],$href,$f);
} else {
// ссылка на файлы для их загрузки
$href= sprintf('%s',$href,$f);
}
// если это ссылка, то показываем также цель
if ('l' == $mode_type) {
$href .= ' -> ' . readlink($d->path.'/'.$f);
}
}
// выводим соответствующую информацию об этом файле
printf('',
$mode, // форматированная строка режима
$s['nlink'], // количество ссылок на этот файл
$user_info['name'], // имя пользователя-владельца
$group_info['name'], // имя группы
$size, // размер файла (или номера устройства)
$date, // дата и время последнего изменения
$href); // ссылка для просмотра или загрузки
}
print '
%s%3u%s %s%s %s%s
';.



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Изменение прав доступа к файлу или его владельца
Копирование и перемещение файла
Обработка всех файлов в каталоге
Обработка всех файлов в каталоге
Получение и установка меток даты/времени файла

Вернуться в раздел: PHP / 19. Каталоги