PHP-4 Эффективная работа


Управление передачей HTTP-заголовков
Установка «плюшек»: setcookie
Взаимодействие с сервером WWW
Загрузка файлов на сервер
Работа с удаленными файлами
Управление соединениями
Аутентификация пользователей

15.5. Работа с удаленными файлами

Как правило, PHP-машина по умолчанию конфигурируется с поддержкой режима «URL fopen wrapper», что позволяет вам использовать в большинстве операций работы с файлами URL HTTP- или FTP-адреса, включая даже операторы require() (см. раздел 6.11) и include() (см. раздел 6.12).

примечание
       К жертвам РНР для Windows это не относится. В этой версии механизм URL wrapper работает с серьезными ограничениями.

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

Извлечем, например, заголовок страницы с удаленного сервера:
<?php
$file = fopen ("http://www.php.net/", "r");
if (!$file) {
       echo "<p>He удается открыть удаленный узел сети.\n";
       exit;
}
while (!feof ($file)) {
       $line = fgets ($file, 1024);
       /* Ограничиваемся строкой заголовка страницы */
       if (eregi ( "<title>( . *)</title>" , $line, $out)) {
          $title = $out[l] ;
          break;
               }
          }
fclose($f ile) ;
?>

Теперь предположим, что у вас есть права на запись в некоторый каталог удаленного FTP-сервера, и вы пытаетесь поместить на этот сервер новый файл. Понятно, что для этого вы должны зарегистрироваться на сервере, а уже потом приступать к работе, но эта задача выполняется достаточно просто (см. раздел 15.7).

Вот как можно организовать запись файла на удаленном сервере:
<?php
$file = fopen ("ftp://ftp.php.net/incoming/outputfile", "w");
if (!$file) {
          echo "<p>He могу открыть файл для записи на удаленном сервере. \n";
          exit ;
}
/* Приступаем к записи данных. */
fputs ($file, "$HTTP_USER_AGENT\n") ;
fclose ($file);

15.6. Управление соединениями

Прежде всего я напомню, что HTTP-протокол не предусматривает запоминания информации об удаленном клиенте, а работает по правилу «выстрелил и забыл». После генерации HTML-страницы по запросу клиента сервер может просто забыть о нем и даже «прикончить» обслуживавший запрос клиента процесс. Это происходит только после завершения работы РНР-программы.

Но пока программа на РНР работает, она поддерживает внутри себя информацию о состоянии соединения с удаленным клиентом. Существует три возможных состояния:

0NORMALНормальное состояние, соединение установлено
1 ABORTED Соединение разорвано
2TIMEOUT Соединение разорвано по превышению порогового времени работы программы

При нормальной работе РНР-программы состояние соединения равно NORMAL. Если удаленный клиент в процессе работы РНР-программы отключился, нажав кнопку STOP на программе-навигаторе, состояние становится равным ABORTED. А если выполнение программы затянулось свыше лимита, установленного функцией set_time_limit () (см. раздел 15.6.5), состояние соединения устанавливается равным TIMEOUT.

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

Автоматическое прерывание работы PHP-программы можно отменить как с помощью директив конфигурационных файлов php.ini или httpd.conf, так и с помощью специальной функции ignore_user_abort () (см. раздел 15.6.4). Кроме того, вы можете зарегистрировать regi ster_shutdown_function () — собственную функцию завершения, которая будет активизироваться как при аварийном завершении программы, так и в конце ее штатной работы. Таким образом, чтобы распознать состояние программы, в котором вызвана эта функция, вы можете использовать, например, connection_aborted() (см. раздел 15.6.1).

Кроме того, завершение программы может наступать по срабатыванию встроенного таймера. По умолчанию он установлен на 30 секунд, но может быть изменен директивами конфигурационных файлов php.ini или httpd.conf, а также функцией set_time_limit () (см. раздел 15.6.5). Если в момент срабатывания таймера выясняется, что вы зарегистрировали функцию завершения, она будет вызвана автоматически. Чтобы выделить состояние завершения по таймауту, вы можете воспользоваться функцией connection_timeout () (см. раздел 15.6.3).

Может случиться, что оба состояния —ABORTED и TIMEOUT — активны в одно и то же время. Так происходит в том случае, когда РНР проинструктирован игнорировать прерывания от удаленного пользователя. Конечно, такая инструкция не может запретить пользователю отказаться от загрузки программы (разорвать соединение), но программа при этом продолжит свое выполнение. Но если программа достигнет прерывания по таймауту, ее выполнение будет все же прекращено, и будет запущена функция завершения, если таковая была зарегистрирована. При этом вы обнаружите, что и connection_timeout(), и connection_aborted() возвращают true.

совет
       Вы можете также использовать вызов connection_status(), который возвращает текущее состояние в виде битовой маски. В результате, если активны оба состояния, эта функция вернет.

15.6.1. Клиент отключен: connection_aborted

int connection_aborted ()

Функция возвращает true, если на момент ее вызова клиент разорвал соединение с WWW-сервером.

15.6.2. Состояние соединения:connection status

int connection_status ()

15.6.3. Прерывание по таймеру:connection_timeout

bool connection_timeout ()

Функция возвращает true, если программа завершилась по прерыванию от таймера. К сожалению, эта функция считается устаревшей и начиная с РНР 4.0.5 из состава PHP-машины исключена, поэтому для обработки этого состояния вам придется использовать функцию connection_status() (см. раздел 15.6.2).

15.6.4. Игнорирование разрыва соединения:ignore_user_abort

int ignore_user_abort ([int setting])

Функция определяет, должна ли программа немедленно завершить выполнение при разрыве соединения по инициативе удаленного пользователя. Функция возвращает свое предыдущее состояние и может вызываться без аргументов для проверки текущего значения.

15.6.5. Установка ограничителя времени: set_time_limit

void set_time_limit (int seconds)

Устанавливает максимальную продолжительность выполнения программы в секундах. При достижении этого предела программа завершается с сообщением о фатальной ошибке. По умолчанию предел устанавливается равным 30 секундам либо определяется директивой max_executi on_ti me в конфигурационном файле php.ini. Если значение этой переменной или аргумент функции равны нулю, то прерывание по таймеру просто отключается.

При вызове set_time_limi't() перезапускает счетчик таймаута с нуля. Иначе говоря, если таймер установлен на тридцать секунд и эта функция запускается на 25-й секунде выполнения программы, ей тем самым выделяется еще 30 секунд машинного времени.

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

15.7. Аутентификация пользователей

Прежде всего отметим, что описываемый в этом разделе механизм аутентификации работает только при установке РНР в качестве модуля Apache, как описано в главе 1.

В этом случае вы можете использовать для запроса аутентификации функцию header( ) для отправки клиенту запроса «Authentication Required», который инициализирует вывод на экран окна запроса имени пользователя и регистрационного пароля. После заполнения данных в этом окне эта же программа вызывается повторно, но на этот раз переменные $PHP_AUTH_USER, $PHP_AUTH_PW и $ PHP_AUTH_TYPE уже получают значения имени пользователя, пароля и типа аутентификации соответственно. На сегодняшний день тип аутентификации только один — «Basic».

Вот пример программы, которая принудительно запрашивает аутентификацию пользователя:
<?php
       if (!isset($PHP_AUTH_USER)) {
          Header ("WWW-Authenticate: Basic realm=\"My Realm\" ");
          Header("HTTP/1.0 401 Unauthorized");
          echo "Противный! Ты отказался зарегистрироваться ... \n" ;
          exit;
       } else {
          echo "Привет $PHP_AUTH_USER. <P>" ;
          echo "Вы ввели пароль $PHP_AUTH_PW. <P>" ;

В чем хитрость этой программы? Стандартный механизм аутентификации, основанный на директивах конфигурационного файла Apache, требует использования парольного файла .htpasswd, заполнять который не всегда удобно. А вы можете воспользоваться этими переменными по своему усмотрению, например для извлечения профиля пользователя из специализированной базы данных.

В случае использования внешней аутентификации для идентификации пользователя необходимо использовать переменную $REMOTE_USER. Переменные PHP_AUTH_* попросту не будут устанавливаться PHP-машиной для страниц, которые требуют внешней аутентификации.

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

Обе популярные клиентские программы — Netscape Navigator и Internet Explorer — автоматически очищают локальный кэш аутентификационной информации при получении с сервера отклика с кодом 401. Это приводит к окончательному завершению сеанса работы пользователя, принуждая его тем самым повторно ввести имя пользователя и пароль. Это может быть реализовано как специальной кнопкой «Завершить работу», так и прерыванием по таймеру.

Вот пример такой программы:
<?php
       function authenticate () {
          Header( "WWW-authenticate: basic realm=\"Test System\"");
          Header( "HTTP/1.0 401 Unauthorized");
          echo "Для доступа к этому ресурсу вы должны ввести имя ".
                 "пользователя и пароль!\n";
       exit;
       }
if(! isset($PHP_AUTH_USER) || ($SeenBefore == 1 &&
                  !strcmp($OldAuth, $PHP_AUTH_USER)) ) {
                           authenticate () ;
                                     }
else {
       echo "Добро пожаловать: $PHP_AUTH_USER<BR>";
       echo "Старый: $OldAuth";
       echo "<FORM ACTION=\"$PHP_SELF\" METHOD=POST>\n"
       echo "<INPUT TYPE=HIDDEN NAME=\"SeenBefore\"
                  VALUE=\"l\">\n";
       echo "<INPUT TYPE=HIDDEN NAME=\"OldAuth\"";
       echo " VALUE=\"$PHP_AUTH_USER\">\n";
       echo "<INPUT TYPE=Submit
                  VALUE=\"Повторная регистрация\">\n";
      echo "</FORM>\n";
       }
       ?>
назад
далее

Сайт управляется системой uCoz