Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛР_4_5_6.doc
Скачиваний:
4
Добавлен:
23.08.2019
Размер:
2.75 Mб
Скачать

Лабораторная работа № 6 Взаимодействие с сервером

Цель работы: Изучить некоторые приемы взаимодействия с сервером

Базовые сведения

Функция file_exists

Синтаксис:

bool file_exists (имя файла или директории)

Функция file_exist() проверяет, существует ли файл или директория, имя которой передано ей в качестве аргумента. Если директория или файл в файловой системе сервера существует, то функция возвращает TRUE, в противном случае – FALSE. Результат работы этой функции кэшируется. Соответственно очистить кэш можно с помощью функции clearstatcache(). Для нелокальных файлов использовать функцию file_exists() нельзя.

Пример 1.

<?php

$filename = 'c:/users/files/my_file.html';

if (file_exists($filename)) {

print "Файл <b>$filename</b> существует";}

else {

print "Файл <b>$filename</b>

НЕ существует";}

?>

Функция is_writable

Если кроме проверки существования файла нужно узнать еще, разрешено ли записывать информацию в этот файл, следует использовать функцию is_writable() или ее псевдоним – функцию is_writeable().

Синтаксис:

bool is_writable (имя файла или директории)

Эта функция возвращает TRUE, если файл (или директория) существует и доступен для записи. Доступ к файлу осуществляется под той учетной записью пользователя, под которой работает сервер (чаще всего это пользователь nobody или www). Результаты работы функции is_writable кэшируются.

Функция is_readable

Если кроме проверки существования файла нужно узнать еще, разрешено ли читать информацию из него, нужно использовать функцию is_readable().

Синтаксис:

bool is_readable (имя файла)

Эта функция работает подобно функции is_writable().

Пример 2.

<?php

$filename = 'c:/users/files/my_file.html';

if (is_readable($filename)) {

print "Файл <b>$filename</b> существует

и доступен для чтения";}

else {

print "Файл <b>$filename</b>

НЕ существует или

НЕ доступен для чтения";}

?>

Удаление файла

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

bool unlink (имя_файла)

Данная функция удаляет файл, имеющий имя имя_файла, возвращает TRUE в случае успеха этой операции и FALSE – в случае ошибки. Чтобы удалить файл, нужно тоже иметь соответствующие права доступа к нему (например, доступа только на чтение для удаления файла недостаточно).

Пример 3.

<?php

$filename = 'c:/users/files/my_file.html';

unlink($filename);

// удаляем файл с именем

// c:/users/files/my_file.html

?>

Загрузка файла на сервер

Теперь решим более сложную и часто возникающую на практике задачу загрузки файла на сервер. Первое, что нужно сделать, чтобы загрузить файл на сервер, это создать html-форму. Для того чтобы с помощью этой формы можно было загружать файлы, она должна содержать атрибут enctype в теге form со значением multipart/form-data, а также элемент input типа file.

<form enctype="multipart/form-data" action="_URL_" method="post">

<input type="hidden" name="MAX_FILE_SIZE" value="30000" />

Отправить этот файл: <input name="userfile" type="file" />

<input type="submit" value="Send File" />

</form>

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

Теперь нужно написать скрипт, который будет обрабатывать полученный файл.

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

Если мы загрузили с компьютера-клиента файл с именем critics.htm размером 15136 байт, то скрипт с единственной командой print_r($_FILES); выведет на экран следующее:

Array ( [myfile] =>

Array ( [name] => critics.htm

[type] => text/html

[tmp_name] => C:\WINDOWS\TEMP\php49F.tmp

[error] => 0

[size] => 15136

)

)

Вообще говоря, массив $_FILES всегда имеет следующие элементы:

$_FILES['myfile']['name'] – имя, которое имел файл на машине клиента.

$_FILES['myfile']['type'] – mime-тип отправленного файла, если браузер предоставил эту информацию. В нашем примере это text/html.

$_FILES['myfile']['size'] – размер загруженного файла в байтах.

$_FILES['myfile']['tmp_name'] – временное имя файла, под которым он был сохранен на сервере.

$_FILES['myfile']['error'] – код ошибки, появившейся при загрузке. Здесь 'myfile' – это имя элемента формы, с помощью которого была произведена загрузка файла на сервер. То есть оно может быть другим, если элемент формы назвать иначе. Но вот другие ключи (name, type и т. д.) остаются неизменными для любой формы.

Если register_globals=On, то доступны также дополнительные переменные, такие как $myfile_name, которая эквивалентна $_FILES['myfile']['name'], и т.п.

Ошибок при загрузке в PHP выделяют пять типов и соответственно

$_FILES['myfile']['error'] может иметь пять значений:

0 – ошибки не произошло, файл загружен успешно

1 – загружаемый файл превышает размер, установленный директивой upload_max_filesize в файле настроек php.ini

2 – загружаемый файл превышает размер, установленный элементом MAX_FILE_SIZE формы html

3 – файл был загружен частично

4 – файл загружен не был

По умолчанию загруженные файлы сохраняются во временной директории сервера, если другая директория не указана с помощью опции upload_tmp_dir в файле настроек php.ini. Переместить загруженный файл в нужную директорию можно с помощью функции move_uploaded_file().

Функция move_uploaded_file() имеет следующий синтаксис:

bool move_uploaded_file

(временное_имя_файла, место_назначения )

Эта функция проверяет, действительно ли файл, обозначенный строкой временное_имя_файла, был загружен через механизм загрузки HTTP методом POST. Если это так, то файл перемещается в файл, заданный параметром место_назначения (этот параметр содержит как путь к новой директории для хранения, так и новое имя файла).

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

Пример 4.

<? PHP

$uploaddir = 'c:/uploads/';

// будем сохранять загружаемые

// файлы в эту директорию

$destination = $uploaddir .

$_FILES['myfile']['name'];

// имя файла оставим неизменным

print "<pre>";

if (move_uploaded_file(

$_FILES['myfile']['tmp_name'],

$destination)) {

/* перемещаем файл из временной папки в выбранную директорию для хранения */

print "Файл успешно загружен <br>";

} else {

echo "Произошла ошибка при загрузке файла.

Некоторая отладочная информация:<br>";

print_r($_FILES);

} print "</pre>"; ?>

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

В случае, если опция allow_url_fopen включена в конфигурационном файле php.ini, вы можете использовать HTTP и FTP ссылки в большинстве функций, принимающих в качестве параметра имя файла. Также вы можете использовать ссылки в операторах include(), include_once(), require() и require_once().

В 4.0.3 и более ранних версиях при сборке необходимо использовать опцию --enable-url-fopen-wrapper для активации возможности работать с удаленными файлами.

Дистрибутивы PHP для Windows-платформ до версии 4.3 не поддерживают возможности работы с удаленными файлами для следующих операторов: include(), include_once(), require(), require_once(), и функций вида imagecreatefromXXX (Ссылка LXII, Image Functions).

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

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

Для того, что бы авторизироваться под пользователем, отличным от 'anonymous', вам необходимо указать логин (и, возможно, пароль) в адресной строке, например так: 'ftp://user:password@ftp.example.com/path/to/file'. (Вы можете использовать этот же синтаксис для доступа к удаленным файлам по HTTP-протоколу, если необходима Basic-авторизация.)

Пример 5. Сохранение данных на удаленном сервере

<?php

$file = fopen ("ftp://ftp.example.com/incoming/outputfile", "w");

if (!$file)

{

echo "<p>Unable to open remote file for writing.\n";

exit;

}

/* Запись данных. */

fputs ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");

fclose ($file);

?>

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

Работа с соединениями

Статус соединения сохраняется внутренними механизмами PHP. Ниже перечислены три возможные состояния:

0 - NORMAL

1 - ABORTED

2 - TIMEOUT

Во время штатного выполнения PHP-скрипта установлен статус NORMAL. В случае, если удаленный клиент разорвал соединение, статус изменяется на ABORTED. Чаще всего отсоединение удаленного клиента происходит при нажатии кнопки "Stop" в браузере. В случае, если достигается установленный временной лимит (ознакомьтесь с функцией set_time_limit()), будет установлен статус TIMEOUT.

Вы можете решать, приводит ли отключение клиента к завершению вашего скрипта. Иногда бывает необходимо, чтобы скрипт выполнился до конца, даже если отсутствует удаленный браузер, которому адресован весь вывод. По умолчанию скрипт завершает свою работу при отключении клиента. Это поведение может быть изменено при помощи опции ignore_user_abort в конфигурационном файле php.ini. Такого же результата можно добиться, указав "php_value ignore_user_abort" в конфигурационном файле или воспользовавшись функцией ignore_user_abort(). Если вы явно не указали на необходимость игнорировать разрыв соединения с клиентом, выполнение скрипта будет прервано. Исключением является тот случай, если используя register_shutdown_function(), вы указали специальную функцию, вызываемую при завершении скрипта. В таком случае после того, как пользователь нажал кнопку "Stop" в своем браузере, при первой же попытке что-либо вывести PHP обнаруживает, что соединение с клиентом было утеряно, и вызывает завершающую функцию. Эта функция также вызывается при нормальном завершении работы вашего скрипта, поэтому для того, чтобы выполнить некоторые специфические действия при отсоединении клиента, вам понадобится функция connection_aborted(), которая возвращает TRUE, если соединение было разорвано.

Выполнение скрипта также может быть прервано встроенным таймером. Стандартное ограничение по времени составляет 30 секунд, изменить его можно при помощи директивы max_execution_time в конфигурационном файле php.ini. Такого же результата можно достичь, добавив php_value max_execution_time в конфигурационный файл или воспользовавщись функцией set_time_limit(). При достижении скриптом временного лимита выполнение скрипта прерывается и вызывается завершающая функция, если она была указана. Уточнить причину завершения скрипта вы можете при помощи функции connection_timeout(), которая возвращает TRUE, если скрипт был прерван по достижению временного ограничения.

Кроме этого, следует заметить, что оба статуса: ABORTED и TIMEOUT, могут быть установлены одновременно. Это может произойти в том случае, если вы явно указали необходимость игнорировать отсоединение удаленного клиента. В таком случае после разрыва соединения, отметив этот факт, PHP продолжит выполнение скрипта, и при достижении временного лимита будет вызвана завершающая функция, если таковая была указана. В этой точке вы можете обнаружить, что и connection_timeout(), и connection_aborted() возвращают TRUE. Вы также можете проверить оба статуса одновременно, вызвав функцию connection_status(), которая возвращает битовые значения для активных статусов. В случае, если оба статуса активны, она, к примеру, вернет значение 3.

Безопасность и защищенный режим

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

Таблица 1

Конфигурационные опции, управляющие защищенным режимом и вопросами безопасности

Для получения более детальной информации о константах вида PHP_INI_* ознакомьтесь с функцией ini_set().

Далее целесообразно провести краткое разъяснение конфигурационных директив.

safe_mode boolean

Включает/отключает защищенный режим в PHP.

safe_mode_gid boolean

По умолчанию в защищенном режиме при открытии файла выполняется проверка значения UID. Для того, чтобы немного смягчить это условие и выполнять проверку GID, необходимо установить значение “on” для флага safe_mode_gid. Определяет, использовать или нет проверку UID (FALSE) или GID (TRUE) проверку при обращении к файлу.

safe_mode_include_dir string

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

Значением этой директивы может быть список каталогов, разделенных двоеточием (точкой с запятой на windows-системах), что аналогично синтаксису include_path.

Указанное значение в действительности является префиксом, а не названием директории. Это означает, что запись "safe_mode_include_dir = /dir/incl" позволяет подключать файлы, находящиеся в директориях "/dir/include" и "/dir/incls", в случае, если они существуют. Если вы хотите указать доступ к конкретной директории, используйте завершающий слеш, например: "safe_mode_include_dir = /dir/incl/".

safe_mode_exec_dir string

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

safe_mode_allowed_env_vars string

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

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

safe_mode_protected_env_vars string

Эта директива содержит список переменных окружения, разделенных двоеточием, значение которых пользователь не сможет изменить, используя функцию putenv(). Значения этих переменных остаются защищенными, даже если их модификация разрешена директивой safe_mode_allowed_env_vars.

open_basedir string

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

Каждый раз, когда скрипт пытается открыть файл, например, при помощи функции fopen() или gzopen(), проверяется месторасположение файла. В случае, если он находится вне указанного дерева директорий, PHP отказывает в открытия файла. Все символические ссылки распознаются и преобразуются, поэтому обойти это ограничение при помощи символических ссылок невозможно.

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

Опция open_basedir может быть отключена в конфигурационном файле httpd.conf (например, для некоторых виртуальных хостов) точно таким же образом как и любая другая директива: "php_admin_value open_basedir none".

Для Windows-систем разделителем списка директорий служит точка с запятой. Для всех других операционных систем в качестве разделителя используется двоеточие. В случае, если PHP работает как модуль веб-сервера Apache, все указания open_basedir для родительских директорий наследуются.

Указанное значение в действительности является префиксом, а не названием директории. Это означает, что запись "safe_mode_include_dir = /dir/incl" позволяет открывать файлы, находящиеся в директориях "/dir/include" и "/dir/incls", в случае, если они существуют. Если вы хотите указать доступ к конкретной директории, используйте завершающий слеш, например: "safe_mode_include_dir = /dir/incl/".

По умолчанию разрешен доступ ко всем файлам.

disable_functions string

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

Эта директива должна быть указана в php.ini. Вы не можете использовать ее, например, в httpd.conf.

disable_classes string

Эта директива позволяет вам запретить некоторые классы из соображений безопасности. В качестве значения она принимает список классов, разделенных двоеточием. disable_classes не зависит от того, используется Защищенный режим или нет.

Эта директива должна быть указана в php.ini. Вы не можете использовать ее, например, в httpd.conf.

Ознакомьтесь также со следующими конфигурационными директивами: register_globals, display_errors, и log_errors

В случае, если директива safe_mode установлена значением “on”, PHP проверит, совпадает ли владелец скрипта и владелец файла или директории, которыми оперирует скрипт. Например:

-rw-rw-r-- 1 rasmus rasmus 33 Jul 1 19:20 script.php

-rw-r--r-- 1 root root 1116 May 26 18:01 /etc/passwd

выполние срипта script.php

<?php

readfile('/etc/passwd');

?>

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

Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2

Тем не менее, предусмотрена возможность вместо проверки на соответствие UID использовать более мягкую проверку на соответствие GID. Для этого необходимо использовать директиву safe_mode_gid. В случае, если она установлена значением On, используется более мягкая проверка GID. В противном случае, если установлено значение Off (значение по умолчанию), выполняется более строгая проверка на соответствие UID.

В качестве альтернативы директиве safe_mode вы можете ограничить все выполняемые скрипты жестко заданным деревом директорий при помощи опции open_basedir. Например (фрагмент конфигурационного файла httpd.conf):

<Directory /docroot>

php_admin_value open_basedir /docroot

</Directory>

При попытке выполнить тот же самый скрипт script.php с указанной опцией open_basedir вы получите следующий результат:

Warning: open_basedir restriction in effect. File is in wrong directory in /docroot/script.php on line 2

Вы также можете запретить отдельные функции. Следует заметить, что директива disable_functions может быть указана исключительно в конфигурационном файле php.ini, это означает, что вы не можете, отредактировав httpd.conf, установить индивидуальные значения для конкретного виртуального хоста или каталога. Если добавить в php.ini следующую строку:

disable_functions readfile,system

Результатом работы скрипта будет следующий вывод:

Warning: readfile() has been disabled for security reasons in /docroot/script.php on line 2

Переменные сервера

В РНР существует специальный суперглобальный массив SSERVER, который содержит различные переменные web-сервера, которые могут быть полезны при разработке web-приложений. Например, переменная SSERVER ["PHPSELF"] содержит имя текущего скрипта, переменная SSERVER [ "REQUEST ME I HOD" ] содержит название метода передачи данных («GET» или «POST»), и т.п.

Наиболее употребительные серверные переменные в табл. 1.

Таблица 1

Серверные переменные

Переменная

Описание

'AUTH_TYPE'

Если РНР используется вместе с web-сервером Apache в режиме модуля, переменная содержит тип аутентификации.

' DOCUMENT_ROOT '

Корневой каталог web-сервера, предназначенный для хранения HTML-документов, в соответствии с его конфигурацией — т.н. корень.

'GATEWAY_INTERFACE'

Версия спецификации CCI, которая поддерживается web-сервером, например ' СGI / 1 . 1 '.

' PATH_TRANSLATED '

Полное локальное имя файла текущего скрипта.

' PHP_AUTH_PW '

Если РНР используется вместе с web-сервером Apache в режиме модуля, переменная содержит пароль пользователя, введенный в окне аутентификации.

' PHP_AUTH_USER '

Если РНР используется вместе с web-сервером Apache в режиме модуля, переменная содержит имя пользователя, введенное в окне аутентификации.

' PHP_SELF'

Путь к текущему скрипту относительно корня.

'QUERY_STRING'

Строка эапроса, переданная скрипту. Задается для метода передачи данных GЕТ, имеет вид: namel = valuel&name2 = value2...

' REMOTE_ATTR '

IР-адрес удаленного пользователя, который запросил данный скрипт.

' REMOTE_HOST'

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

' REMOTE_PORT '

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

' REQUEST_METHOD'

Метод передачи данных, при помощи которого был загружен данный скрипт — GET', HEAD, POST или PUT.

'REQUEST_URI'

URI текущего скрипта, например '/index, php' .

' SCRIPT_FILENAME '

Полное абсолютное локальное имя скрипта.

'SCRIPT_NAME'

Путь к текущему скрипту относительно корня.

' SERVER_ ADMIN '

E-mail администратора web-сервера.

' SERVER_ NAME'

Имя хоста web-сервера.

' SERVER_PORT '

Порт web-сервера (обычно 80).

' SERVER_PROTOCOL'

Наименование и версия протокола, используемого web-сервером для обмена информацией с браузером, например, 'НТТР/1.0'.

'SERVER_SIGNATURE'

Строка, содержащая версию web-сервера и название хоста, которая добавляется к автоматически генерируемым страницам.

'SERVER_SOFTWARE'

Строка, идентифицирующая название и версию программного обеспечения web-сервера.