Функция pfsockopen( ) представляет собой устойчивую (persistent) версию
fsockopen( ). Это означает, что соединение не будет автоматически разорвано по
завершении сценария, в котором была вызвана функция. Синтаксис функции
pfsockopen( ):
int pfsockopen (string узел, int порт [, int код_ошибки [, string текст _ошибки
[, int тайм-аут]]])
В зависимости от конкретных целей вашего приложения может оказаться удобнее
использовать pfsockopen( ) вместо fsockopen( ).
Запуск внешних программ
Сценарии РНР также могут выполнять программы, находящиеся на сервере. Такая
возможность особенно часто используется при администрировании системы через
web-браузер, а также для более удобного получения сводной информации о системе.
ехес( )
Функция ехес( ) запускает заданную программу и возвращает последнюю строку ее
выходных данных. Синтаксис функции ехес( ):
string exec (string команда [, string массив [, int возврат]])
Обратите внимание: функция ехес( ) только выполняет команду, не выводя
результатов ее работы. Все выходные данные команды можно сохранить в
необязательном параметре массив. Кроме того, если при заданном параметре массив
также задается переменная возврат, последней присваивается код возврата
выполненной команды.
Листинг 7.7 показывает, как использовать функцию ехес( ) для выполнения
системной функции UNIX ping.
Листинг 7.7. Проверка связи с сервером с применением функции ехес( )
<?
exec("ping -с 5 www.php.net", $ping);
// В Windows - exec("ping -n 5 www.php.net. $ping);
for ($i=0; $i< count($ping);$i++) :
print "<br>$ping[$i]";
endfor;
?>
Результат:
PING www.php.net (208.247.106.187): 56 data bytes
64 bytes from 208.247.106.187: icmp_seq=0 ttl=243 time=66.602 ms
64 bytes from 208.247.106.187: icmp_seq=1 ttl=243 time=55.723 ms
64 bytes from 208.247.106.187: icmp_seq=2 ttl=243 time=70.779 ms
64 bytes from 208.247.106.187: icmp_seq=3 ttl=243 time=55.339 ms
64 bytes from 208.247.106.187: icmp_seq=4 ttl=243 time=69.865 ms
-- www.php.net ping statistics --
5 packets transmitted. 5 packets received. 0% packet loss
round-trip min/avg/max/stddev - 55.339/63.662/70.779/6.783 ms
Обратные апострофы
Существует и другой способ выполнения системных команд, не требующий вызова
функций, — выполняемая команда заключается в обратные апострофы (` `), а
результаты ее работы отображаются в браузере. Пример:
$output = `ls`;
print "<pre>$output</pre>";
Этот фрагмент выводит в браузер содержимое каталога, в котором находится
сценарий.
Внутренний параметр ping -с 5 (-п 5 в системе Windows) задает количество опросов
сервера.
Если вы хотите просто вернуть неформатированные результаты выполнения команды,
воспользуйтесь функцией passthru( ), описанной ниже.
passthru( )
Функция passthru( ) работает почти так же, как ехес( ), за одним исключением —
она автоматически выводит результаты выполнения команды. Синтаксис функции
passthru( ):
void passthru(string команда [, int возврат])
Если при вызове passthru( ) передается необязательный параметр возврат, этой
переменной присваивается код возврата выполненной команды.
escapeshellcmd( )
Функция escapeshellcmd( ) экранирует все потенциально опасные символы, которые
могут быть введены пользователем (например, на форме HTML), для выполнения
команд exec( ), passthru( ), system( ) или рореn( ). Синтаксис:
string escapeshellcmd (string команда)
К пользовательскому вводу всегда следует относиться с определенной долей
осторожности, но даже в этом случае пользователи могут вводить команды, которые
будут исполняться функциями запуска системных команд. Рассмотрим следующий
фрагмент:
$user_input = `rm -rf *`; // Удалить родительский каталог и все его подкаталоги
ехес($user_input); // Выполнить $user_input !!!
Если не предпринять никаких мер предосторожности, такая команда приведет к
катастрофе. Впрочем, можно воспользоваться функций escapeshellcmd( ) для
экранирования пользовательского ввода:
$user_input = `rm - rf *`; // Удалить родительский каталог и все его подкаталоги
Функция escapeshellcmd( ) экранирует символ *, предотвращая катастрофические
последствия выполнения команды.
Безопасность является одним из важнейших аспектов программирования в среде Web,
поэтому я посвятил целую главу этой теме и ее отношению к программированию РНР.
За дополнительной информацией обращайтесь к главе 16.
Работа с файловой системой
В РНР существуют функции для просмотра и выполнения различных операций с файлами
на сервере. Информация об атрибутах серверных файлов (местонахождение, владелец
и привилегии) часто бывает полезной.
basename( )
Функция basename( ) выделяет имя файла из переданного полного имени. Синтаксис
функции basename( ):
string basename(string полное_имя)
Выделение базового имени файла из полного имени происходит следующим образом:
Фактически эта функция удаляет из полного имени путь и оставляет только имя
файла.
getlastmod( )
Функция getlastmod( ) возвращает дату и время последней модификации страницы, из
которой вызывается функция. Синтаксис функции getlastmod( ):
int getlastmod(void)
Возвращаемое значение соответствует формату даты/времени UNIX, и для его
форматирования можно воспользоваться функцией date( ). Следующий фрагмент
выводит дату последней модификации страницы:
В этом примере я воспользовался конструкцией list () для присваивания имен
каждому возвращаемому значению. Конечно, с таким же успехом можно вернуть
массив, в цикле перебрать элементы и вывести всю необходимую информацию. Как
видите, функция stat ( ) позволяет получить различные полезные сведения о файле.
Отображение и изменение характеристик файлов
У каждого файла в системах семейства UNIX есть три важные характеристики:
· принадлежность группе;
· владелец;
· разрешения (permissions).
Все эти характеристики можно изменить при помощи соответствующих функций РНР.
Функции, описанные в этом разделе, не работают в системах семейства Windows.
Если у вас нет опыта работы в операционных системах UNIX, информацию о
характеристиках файловой системы UNIX можно получить по адресу
http://sunsite.auc.dk/linux-newbie/FAQ2.htm. Темы принадлежности группе,
владения и разрешений рассматриваются в разделе 3.2.6.
chgrp( )
Функция chgrp( ) пытается сменить группу, которой принадлежит заданный файл.
Синтаксис функции chgrp( ):
int chgrp (string имя_файла, mixed группа)
filegroup( )
Функция filegroup( ) возвращает идентификатор группы владельца файла с заданным
именем или FALSE в случае ошибки. Синтаксис функции filegroup( ):
int filegroup (string имя_файла)
chmod( )
Функция chmod( ) изменяет разрешения файла с заданным именем. Синтаксис функции
chmod( ):
int chmod (string имя_файла, int разрешения)
Разрешения задаются в восьмеричной системе. Специфика задания параметра функции
chmod ( ) продемонстрирована в следующем примере:
chmod("data_file.txt", g+r); // He работает
chmod("data_file.txt", 766); // Не работает
chmod("data_file.txt", 0766); // Работает
fileperms( )
Функция fileperms( ) возвращает разрешения файла с заданным именем или FALSE в
случае ошибки. Синтаксис функции fileperms( ):
int fileperms (string имя_файла)
chown( )
Функция chown( ) пытается сменить владельца файла. Право изменения владельца
файла предоставляется только привилегированному пользователю. Синтаксис функции
chown( ):
int chown (string имя_файла, mixed пользователь)
fileowner( )
Функция fileowner( ) возвращает идентификатор пользователя для владельца файла с
заданным именем. Синтаксис функции fileowner( ):
int fileowner (string имя_файла)
Копирование и переименование файлов
К числу других полезных системных функций, которые могут выполняться в сценариях
РНР, относятся копирование и переименование файлов на сервере. Эти операции
выполняются двумя функциями: сору( ) и rename( ).
сору( )
Скопировать файл в сценарии РНР ничуть не сложнее, чем при помощи команды UNIX
ср. Задача решается функцией РНР сору( ). Синтаксис функции сору( ):
int copy (string источник, string приемник)
Функция сору( ) пытается скопировать файл источник в файл приемник; в случае
успеха возвращается TRUE, а при неудаче — FALSE. Если файл приемник не
существует, функция сору( ) создает его. Следующий пример показывает, как
создать резервную копию файла при помощи функции сору( ):
$data_file = "datal.txt";
copy($data_file. $data_file'.bak') or die("Could not copy $data_file");
rename ( )
Функция rename( ) переименовывает файл. В случае успеха возвращается TRUE, a при
неудаче — FALSE. Синтаксис функции rename( ):
bool rename (string старое_имя, string новое_имя)
Пример переименования файла функцией rename( ):
$data_file = "datal.txt";
rename($data file, $datafile'.old') or die ("Could not rename $data file");
Удаление файлов
unlink( )
Функция unlink( ) удаляет файл с заданным именем. Синтаксис:
int unlink (string файл)
Если вы работаете с РНР в системе Windows, при использовании этой функции иногда
возникают проблемы. В этом случае можно воспользоваться описанной выше функцией
system( ) и удалить файл командой DOS del:
system ("del filename.txt");
Работа с каталогами
Функции РНР позволяют просматривать содержимое каталогов и перемещаться по ним.
В листинге 7.8 изображена типичная структура каталогов в системе UNIX.
Листинг 7.8. Типичная структура каталогов
drwxr-xr-x 4 root wheel 512 Aug 13 13:51 book/
drwxr-xr-x 4 root wheel 512 Aug 13 13:51 code/
-rw-r--r-- 1 root wheel 115 Aug 4 09:53 index.html
drwxr-xr-x 7 root wheel 1024 Jun 29 13:03 manual/
-rw-r--r-- 1 root wheel 19 Aug 12 12:15 test.php
dirname( )
Функция dirname( ) дополняет basename( ) — она извлекает путь из полного имени
файла. Синтаксис функции dirname( ):
string dirname (string путь)
Пример использования dirname( ) для извлечения пути из полного имени:
Функция dirname( ) иногда используется в сочетании с переменной $SCRIPT_FILENAME
для получения полного пути к сценарию, из которого выполняется команда:
$dir - dirname($SCRIPT_FILENAME);
is_dir( )
Функция is_dir( ) проверяет, является ли файл с заданным именем каталогом:
bool is_dir (string имя_файла)
В следующем примере используется структура каталогов из листинга 7.8:
Функция mkdir( ) делает то же, что и одноименная команда UNIX, — она создает
новый каталог. Синтаксис функции mkdir( ):
int mkdir (string путь, int режим)
Параметр путь определяет путь для создания нового каталога. Не забудьте
завершить параметр именем нового каталога! Параметр режим определяет разрешения,
назначаемые созданному каталогу.
opendir( )
Подобно тому как функция fopen( ) открывает манипулятор для работы с заданным
файлом, функция opendir( ) открывает манипулятор для работы с каталогом.
Синтаксис функции opendir( ):
int opendir (string путь)
closedir( )
Функция closedir( ) закрывает манипулятор каталога, переданный в качестве
параметра. Синтаксис функции closedir( ):
void closedir(int манипулятор_каталога)
readdir( )
Функция readdir( ) возвращает очередной элемент заданного каталога. Синтаксис:
string readdir(int манипулятор_каталога)
С помощью этой функции можно легко вывести список всех файлов и подкаталогов,
находящихся в текущем каталоге:
$dh = opendir(' . );
while ($file = readdir($dh)) :
print "$file <br>"; endwhile;
closedir($dh);
chdir( )
Функция chdir( ) работает так же, как команда UNIX cd, — она осуществляет
переход в каталог, заданный параметром. Синтаксис функции chdir( ):
int chdir (string каталог)
В следующем примере мы переходим в подкаталог book/ и выводим его содержимое:
$newdir = "book";
chdir($newdir) or die("Could not change to directory ($newdir)"); $dh =
opendir(' . ');
print "Files:";
while ($file = readdir($dh)) ;
print "$file <br>";
endwhile;
closedir($dh);
rewinddir( )
Функция rewlnddir( ) переводит указатель текущей позиции в начало каталога,
открытого функцией opendir( ). Синтаксис функции rewinddir( ):
void rewinddir (int нанипулятор_каталога)
Проект 1: простой счетчик обращений
Сценарий, представленный в этом разделе, подсчитывает количество обращений к
странице, в которой он находится. Прежде чем переходить к программному коду в
листинге 7.9, просмотрите алгоритм, написанный на псевдокоде:
1. Присвоить переменной $access имя файла, в котором будет храниться значение
счетчика.
2. Использовать функцию filе( ) для чтения содержимого $access в массив $visits.
Префикс @ перед именем функции подавляет возможные ошибки (например, отсутствие
файла с заданным именем).
3. Присвоить переменной $current_visitors значение первого (и единственного)
элемента массива $visits.
4. Увеличить значение $current_visitors на 1.
5. Открыть файл $access для записи и установить указатель текущей позиции в
начало файла.
6. Записать значение $current_visitors в файл $access.
7. Закрыть манипулятор, ссылающийся на файл $access.
Листинг 7.9. Простой счетчик обращений
<?
// Сценарий: простой счетчик обращений
// Назначение: сохранение количества обращений в файле
$access = "hits.txt"; // Имя файла выбирается произвольно
$visits = @file($access); // Прочитать содержимое файла в масссив
$current_visitors = $visits[0]; // Извлечь первый (и единственный) элемент
++$current_visitors; // Увеличить счетчик обращений
$fh = fopen($access. "w"); // Открыть файл hits.txt и установить
// указатель текущей позиции в начало файла
@fwrite($fh, $current_visitors);// Записать новое значение счетчика