Практика применения Perl, PHP, Apache, MySQL для активных Web-сайтов (С) Александр Фролов, Григорий Фролов, 2002 5. Создание программ CGI на языке Perl 5. Создание программ CGI на языке Perl Выполнение установки в RedHat Linux Выполнение установки в Microsoft Windows Установка дополнительных модулей Perl Загрузка дистрибутива с Web-узла CPAN Утилита PPM для Microsoft Windows Создание виртуального каталога программ CGI Определение виртуального каталога программ CGI Права доступа к каталогу программ CGI Права доступа к файлам программ CGI Параметры виртуального Web-узла Документ HTML со ссылкой на программу CGI Извлечение содержимого текстовых полей формы Обработка флажков с независимой фиксацией Обработка флажков с зависимой фиксацией Обработка данных от графической кнопки Работа с Cookie в программах CGI Заголовок HTTP для создания Cookie Изменение значения параметра Cookie Ограничения на использование Cookie Обмен данными с сервером электронной почты Внутренняя структура электронного сообщения Наборы символов и кодировка сообщения Отправка данных из формы по электронной почте Исходный текст программы urgent_mail.pl Использование модуля Net::POP3 Использование модуля Mail::POP3Client
Как мы уже говорили, программы CGI можно создавать с применением различных языков программирования. Язык Perl, на наш взгляд, наиболее удобен для этого. Так как Perl — интерпретируемый язык, то в некоторых случаях можно добиться более высокой скорости работы программ CGI, если составлять их на С или С++. Однако большинство Web-приложений, в том числе такие сложные как Интернет-мгазины, могут быть с успехом реализованы на Perl. В чем преимущества применения Perl для создания программ CGI? Вот только некоторые из них: · удобные средства извлечения данных из полей форм; · мощные функции для работы с текстовыми строками и датами; · удобные средства интеграции программ CGI с базами данных; · способность программ CGI, составленных на языке Perl, работать на различных компьютерных платформах под управлением самых разных операционных систем; · огромное количество готовых модулей Perl, предназначенных для решения самых разных задач программирования, от общесистемных до специализированных, характерных только для Web-приложений; · применяя готовые модули, можно значительно сократить размер листингов программ CGI, составленных на Perl, по сравнению с аналогичными программами, но написанными на С или С++; · открытость платформы — все модули Perl доступны с исходными текстами и могут быть положены в основу Ваших собственных разработок. Изучение языка Perl может стать предметом отдельной книги или даже несколько книг. Если Вы никогда не использовали этот язык в своей работе, то мы рекомендуем Вам обратиться к литературе, список которой приведен в библиографическом указателе нашей книги. Перед тем как продолжить работу с нашей книгой, Вы, например, можете начать изучение Perl с книги [12] или с любой другой книги, ориентированной на начинающего программиста Perl. При изложении материала мы, тем не менее, будем рассказывать о тех или иных возможностях Perl, имеющих отношение к обсуждаемой теме. Если при установке операционной системы Red Hat Linux 7.1, описанной нами в главе 2 этой книге, Вы следовали нашим рекомендациям, то интерпретатор Perl уже установлен. Что же касается ОС Microsoft Windows, то для нее придется выполнять установку отдельно. Прежде пытаться работать с Perl в Red Hat Linux, проверьте, были ли установлен Perl в процессе установки ОС или нет. Проще всего это сделать, если ввести в системном приглашении следующую команду: perl -v Если в ответ появится показанное ниже сообщение с номером версии Perl, и этот номер не ниже 5.6, можно продолжать работу: # perl -v В том случае, когда на экране появляется только сообщение об ошибке «perl: command not found», необходимо установить Perl. Мы рассмотрим процедуру установки Perl в RedHat Linux и в Microsoft Windows. Выполнение установки в RedHat Linux Интерпретатор Perl практически для всех распространенных компьютерных платформ можно загрузить с Web-узла http://www.perl.com. Для операционной системы RedHat Linux можно загрузить RPM-дистрибутив интерпретатора Perl с Web-узла компании ActiveState. Этот узел расположен в Интернете по адресу http://www/activestate.com (рис. 5-1). Дистрибутив хранится в файле ActivePerl-5.6.1.629-i686-linux-thread-multi.rpm и его можно установить при помощи утилиты RPM. Вот команда установки, которую следует ввести в системном приглашении: rpm -i ActivePerl-5.6.1.629-i686-linux-thread-multi.rpm Рис. 5-1. Web-узел компании ActiveState Завершив установку, снова введите команду «perl –v» для проверки правильности установки интерпретатора Perl. Выполнение установки в Microsoft Windows Для установки интерпретатора Perl в операционной системе Microsoft Windows 2000 загрузите с Web-узла компании Active State файл ActivePerl-5.6.1.629-MSWin32-x86-multi-thread.msi (или файл более новой версии) и запустите его на выполнение. Чтобы установить данную версию дистрибутива в ОС Microsoft Windows NT, необходимо дополнительно загрузить и установить программу Microsoft Windows Installer версии 1.1. Ссылку на эту программу можно найти на странице загрузки дистрибутива Perl. Итак, начнем установку. Запустите на выполнение загруженный файл ActivePerl-5.6.1.629-MSWin32-x86-multi-thread.msi. На экране появится первое окно мастера установки, показанное на рис. 5-2.
Рис. 5-2. Мастер установки ActivePerl Щелкните кнопку Next чтобы продолжить работу мастера установки. Вы увидите окно с текстом лицензионного соглашения на использование интерпретатора Perl. Прочитав его, отметьте флажок I accept the terms of the License Agreement (рис. 5-3) и щелкните кнопку Next.
Рис. 5-3. Просмотр текста лицензионного соглашения Обратите внимание, что хотя Perl и бесплатен, лицензионное соглашение разрешает Вам распространять его дистрибутив только с письменного разрешения компании Active State. Далее Вам нужно выбрать устанавливаемые компоненты (рис. 5-4). Рис. 5-4. Выбор устанавливаемых компонентов Если на данном компьютере не планируется установка Microsoft Internet Information Server, а роль Web-сервера будет играть Apache, компонент Perl ISAPI можно не устанавливать. Рабочий сервер также не нуждается в установке примеров программ и документации, но на компьютер разработчика Web-приложений мы рекомендуем установить эти компоненты. В следующем окне нужно указать параметры установки Perl (рис. 5-5). Рис. 5-5. Выбор параметров установки Если Perl будет использован с Microsoft IIS, отметьте все флажки, расположенные в этом окне. В том случае, если на сервере будет установлен Apache, два нижних флажка отмечать не нужно. Указав параметры установки, щелкните кнопку Next. На экране появится сообщение о том, что мастер установки готов к копированию дистрибутивных файлов (рис. 5-6). Рис. 5-6. Запуск процедура копирования дистрибутивных файлов Для запуска процесса копирования щелкните кнопку Install. Ход копирования будет отображаться в окне, показанном на рис. 5-7. Рис. 5-7. Идет копирование дистрибутивных файлов После завершения процесса копирования Вы увидите сообщение о завершении установки (рис. 5-8). Рис. 5-8. Работа мастера установки завершена Щелкните кнопку Finish и перезагрузите компьютер. На этом установку Perl можно считать оконченной. Теперь в ответ на команду «perl –v», введенную в системном приглашении, Вы должны увидеть следующее сообщение: D:\>perl -v Установка дополнительных модулей Perl Как мы уже говорили, удобство применения Perl для создания программ CGI во многом определяется наличием большого количества готовых модулей, решающих типичные задачи CGI-программирования. Часть этих модулей устанавливается вместе с дистрибутивом Perl, другие нужно устанавливать дополнительно. Модули Perl можно бесплатно установить из сети архива Comprehensive Perl Archive Network (CPAN), расположенного в Интернете по адресу http://www.perl.com/CPAN-local/README.html (рис. 5-9). Рис. 5-9. Главная страница сети CPAN У Вас есть две возможности установить дополнительный модуль Perl — загрузив его дистрибутив с Web-узла архива CPAN и запустив процедуру инсталляции, или установив его непосредственно через Интернет с помощью специальных утилит установки. Второй способ, очевидно, подходит только в том случае, если Ваш компьютер подключен к Интернету. Сравнивая различные методы установки, заметим, что если Вы пользуетесь первым методом, то в Вашем распоряжении оказывается дистрибутив модуля. При помощи этого дистрибутива Вы всегда сможете установить модуль, даже если компьютер не подключен к Интернету. Далее, Вы можете включить дистрибутивный файл модулей Perl, необходимых для работы Вашего Web-приложения, в общий дистрибутивный архив этого Web-приложения. Это может в дальнейшем упростить установку Web-приложения на другой компьютер или его переустановку. Дистрибутив модуля необходим, если Ваше Web-приложение разрабатывается для интрасети, не подключенной к Интернету. С другой стороны, при использовании прямой установки Вы всегда сможете загрузить самую новую версию модуля непосредственно из архива CPAN. Рассмотрим использование обоих способов в ОС Linux и Microsoft Windows. Загрузка дистрибутива с Web-узла CPAN Каждый модуль Perl идентифицируется по имени. Например, в наших примерах широко используется модуль HTML:Template, значительно упрощающий создание Web-приложений. Это происходит благодаря разделению процессов разработки дизайна Web-узла и программирования активных компонентов. Мы также будем использовать модули драйвера СУБД MySQL с именем DBD:MySQL и некоторый другие. Чтобы найти нужный модуль, воспользуйтесь ссылкой modules, показанной на рис. 5-9. Далее в появившейся странице выберите ссылку Modules by name. В результате Вы получите доступ к архиву модулей, сгруппированных по именам. На рис. 5-10 мы показали страницу, с которой можно загрузить упомянутый выше модуль HTML:Template. Обратите внимание, что здесь имеется несколько версий модуля, каждый из которых снабжен файлом документации с именем HTML-Template-x.x.readme. Вам нужно выбрать самую новую версию модуля, загрузив архив tar.gz.
Рис. 5-10. Выбор модуля по имени Загрузив архивный файл, распакуйте его во временном каталоге. В среде ОС Microsoft Windows архив можно распаковать при помощи широко распространенной утилиты WinZip или бесплатной программы Win-GZ (ее можно найти на http://www.download.com). Что же касается ОС Linux, то там эту операцию можно выполнить либо с помощью утилит gunzip и tar, либо программой Midnight Commander. Вот пример применения утилит gunzip и tar: # gunzip HTML-Template-2.3.tar.gz В результате во временном каталоге будет создан каталог с именем HTML-Template-2.3. Сделайте его текущим и введите следующие команды в системном приглашении ОС Linux: # perl Makefile.pl Если все было сделано правильно и на экране не появилось никаких сообщений об ошибках, модуль установлен и готов к использованию. Установка модуля из временного каталога в среде Microsoft Windows выполняется аналогично, однако вместо утилиты make необходимо использовать утилиту nmake. Она входит, например, в комплект Microsoft Visual Studio. Утилита PPM для Microsoft Windows Если Вам нужно установить дополнительные модули для Active Perl на компьютер, имеющий соединение через Интернет, проще всего воспользоваться утилитой ppm, которая устанавливается вместе с интерпретатором Perl. Запустите эту утилиту в командном приглашении Microsoft Windows: I:\>ppm Далее введите команду поиска нужного Вам модуля: PPM> search HTML-Template Если модуль найден, установите его при помощи команды install: PPM> install HTML-Template Теперь модуль установлен и готов к использованию. Утилита CPAN для Linux Для установки дополнительных модулей Perl на компьютер с операционной системой Linux, подключенный к Интернету, воспользуйтесь утилитой cpan. Запустите эту утилиту с помощью интерпретатора perl, введя в системном приглашении следующую команду: # perl -MCPAN -e shell В ответ Вы получите сообщение о начале инициализации и конфигурирования модуля CPAN.pm, ответственного за получение модулей из архива CPAN: We have to reconfigure CPAN.pm due to
following uninitialized parameters: Далее Вам будет задан ряд вопросов относительно размещения каталогов для создания файлов, расположение утилит-архиваторов, настройки прокси-серверов и т.п. Практически на все вопросы можно давать ответы по умолчанию, просто наживая клавишу Enter. Когда конфигурирование будет закончено, Вы увидите приглашение утилиты cpan. Введите в нем команду поиска нужного Вам модуля: cpan> i /HTML-Template/ В качестве параметра команде поиска i передается шаблон имени модуля. После завершения поиска на экране появится список модулей, имя которых соответствует указанному шаблону: Distribution
S/SA/SAMTREGAR/HTML-Template-2.4.tar.gz Теперь для установки модуля введите команду install, передав ей в качестве параметра имя устанавливаемого модуля: cpan:>install HTML::Template Далее начнется процесс установки, сопровождающийся выдачей на экран большого количества сообщений. Вот финальная часть этих сообщений при установке модуля HTML::Template: . . . На этом установка модуля считается завершенной. Настройка конфигурации Apache Одно из преимуществ сервера Apache заключается в том, что он не допускает запуск никаких программ, если это не разрешено явным образом в конфигурационном файле httpd.conf. Для того чтобы файлы с расширением имени cgi распознавались сервером Apache как программы CGI, нужно вставить в файл httpd.conf команду следующего вида: AddHandler cgi-script .cgi Если сервер Apache работает в операционной системе Microsoft Windows, для разрешения работы программ Perl необходимо снять символ комментария со следующей команды, расположенной в конфигурационном файле httpd.conf: ScriptInterpreterSource registry При этом Apache будет распознавать программы CGI, написанные на языке Perl, по расширению имени файла pl. Заметим, что без выполнения описанной выше настройки файла httpd.conf все попытки запуска программ CGI будут отвергнуты сервером Apache. В ответ на каждую такую попытку в файл журнала ошибок будет записываться следующее сообщение: [Wed Oct 17 13:26:28 2001] [error] [client 154.100.100.31] couldn't spawn child process: e:/www.cgi-test.at-home/cgi/login.pl В данном случае оно говорит о невозможности запуска программы login.pl. Дополнительно в файле журнала доступа появится запись об отказе в доступе с кодом 500: 154.100.100.31 - - [17/Oct/2001:13:26:28 +0400] "GET /cgiprg/login.pl HTTP/1.1" 500 619 В процессе отладки программ CGI пользуйтесь журналами ошибок и доступа. Сообщения, сохраняемые в этих журналах, помогут Вам избавиться от ошибок в своих программах. Создание виртуального каталога программ CGI Итак, Вы установили интерпретатор Perl и познакомились с тем, как найти и установить для этого интерпретатора дополнительный модули. Теперь мы расскажем о том, как создать для Web-узла виртуальный каталог, в котором будут находиться программы CGI, написанные на языке Perl. Как мы уже говорили в главе 3, посвященной установке и настройке Web-сервера Apache, каталоги, предназначенные для программ CGI, нужно создавать и описывать в файле конфигурации httpd.conf специальным образом. В частности, необходимо создать псевдоним физического каталога программ CGI, называемый также виртуальным каталогом программ CGI. Записав файлы программ CGI в предназначенный для них каталог, необходимо соответствующим образом настроить доступ пользователей компьютера к этим файлам. Доступ нужно настроить так, чтобы никто, кроме администратора, не мог читать или изменять содержимое файлов. В то же время посетители Web-узла должны обладать правами на запуск программ CGI. Определение виртуального каталога программ CGI Как мы уже говорили в главе 3, посвященной установке и настройке Web-сервера Apache, каталоги с программами CGI настраиваются специальным образом. Обычно Web-приложения Apache, ссылаясь на файлы программ CGI, используют не физический путь к этим файлам, а виртуальный, построенный с использованием команды ScriptAlias. Данная команда задает псевдоним (алиас) для физического каталога. В дальнейшем Web-приложения ссылаются на этот псевдоним, а не на реальный каталог с программами CGI. Вот пример использования команды ScriptAlias в файле конфигурации Apache для операционной системы Microsoft Windows: ScriptAlias /cgiprg/ "e:/Admin123Trudogolik/cgi/" Эта команда определяет виртуальный каталог программ CGI с именем cgiprg для физического каталога e:/Admin123Trudogolik/cgi/. Что же касается Apache для Linux, то здесь команда ScriptAlias используется аналогичным образом: ScriptAlias /cgiprg/ "/var/web_projects/www_trudogolik/cgiprg/" В данном случае команда определяет виртуальный каталог программ CGI с именем cgiprg для физического каталога /var/web_projects/www_trudogolik/cgiprg. Приведем пример адресации каталога программ CGI с применением описанных выше псевдонимов. Если для Web-узла http://www.datarecovery.ru был определен псевдоним (виртуальный каталог) cgi-bin, отображаемый на физический каталог /var/www/cgi-bin/, то правильный адрес URL каталога программ CGI будет http://www.datarecovery.ru/cgi-bin. Права доступа к каталогу программ CGI Для каждого каталога программ CGI нужно определить права доступа с помощью команд <Directory> и </Directory>. В частности, для этих каталогов необходимо запретить интерпретацию файла управления доступом .htaccess и разрешить исполнение программ CGI. Ниже мы привели пример для сервера Apache, работающего под управлением ОС Microsoft Windows: <Directory
"e:/Admin123Trudogolik/cgi/"> Здесь интерпретация файла управления доступом .htaccess запрещается командой AllowOverride с аргументом None. Команды Order и Allow разрешают доступ к каталогу программ CGI всем посетителям независимо от адреса IP их рабочих станций. Определение прав доступа к каталогу программ CGI для сервера Apache, установленного в Linux, выглядит следующим образом: <Directory "/var/web_projects/www_trudogolik/cgiprg/"> Здесь дополнительно используется команда Options с аргументом ExecCGI, разрешающая запуск программ CGI из данного каталога. Данную команду можно применять и для сервера Apache, работающего в среде ОС Microsoft Windows. Права доступа к файлам программ CGI Записав файлы программ CGI в предназначенный для них каталог, необходимо определить для пользователей сервера права доступа к этим файлам. В операционной системе Linux для этого можно использовать команду chmod с параметром 755: chmod 755 my_cgi.pl Если Вы загружаете программы CGI на Web-сервер при помощи клиентов FTP, то эти же программы могут помочь Вам установить необходимые атрибуты доступа. Например, выделив нужный файл в программе FAR, нажмите клавишу F9 и выберите из меню Files строку File attributes. На экране появится окно Set attributes (рис. 5-11).
Рис. 5-11. Установка прав доступа к файлу в программе FAR При помощи клавиш перемещения курсора по горизонтали и клавиши пробела Вы можете устанавливать и сбрасывать отдельные флажки атрибутов доступа. Для файлов программ CGI установите их в положение, показанное на рис. 5-11. Если сервер Apache работает в операционной системе Microsoft Windows, то Вы можете усилить защиту программ CGI, запретив их изменение и чтение всем пользователям, кроме администратора. При этом не забудьте разрешить всем пользователям выполнение этих программ. В этом разделе мы приведем исходный текст несложной программы CGI, динамически формирующей документ HTML и возвращающей этот документ посетителю. Несмотря на предельную простоту этой программы, мы советуем Вам начать изучение технологии CGI именно с нее. При этом Вы дополнительно потренируетесь в создании и настройке каталогов виртуального Web-узла, предназначенных для хранения программ CGI, а также в настройке прав доступа посетителей к файлу программы CGI. Параметры виртуального Web-узла Для отладки этой и других учебных программ CGI, приведенных в нашей книге, мы будем использовать виртуальный Web-узел с доменным именем www.cgi-test.at-home. Заметим, что это доменное имя не может существовать в Интернете, так как не существует корневой зоны at-home. Для использования имени www.cgi-test.at-home мы должны настроить соответствующим образом локальный сервер DNS. В нашем случае в зоне cgi-test.at-home необходимо описать узел www с адресом IP, равным 154.100.100.31. Вы, разумеется, можете использовать другие доменные имена и адреса IP. Ниже мы привели фрагмент файла httpd.conf для операционной системы Microsoft Windows, в котором определен наш виртуальный Web-узел www.cgi-test.at-home: <VirtualHost 154.100.100.31:80> Обратите внимание, что для программ CGI мы создали физический каталог e:/www.cgi-test.at-home/cgi. В нем мы разрешили выполнение программ CGI, указав команду Options с аргументом +ExecCGI. Дополнительно с помощью команд Order, Allow и AllowOverride мы разрешили всем посетителям доступ к этому каталогу и запретили использование файла .htaccess для управления доступом в данном каталоге. Чтобы исключить возможность прямого доступа посетителей к физическому каталогу программ CGI, мы создали псевдоним cgiprg, использовав для этого команду ScriptAlias. Документ HTML со ссылкой на программу CGI Программы CGI можно запускать из командного приглашения операционной системы, однако для нас важнее научиться запускать их из документов HTML, расположенных в каталогах Web-сервера. Как Вы, наверное, знаете, программы CGI можно запускать при помощи форм и ссылок, созданных с применением тега <A>. В нашем первом примере мы воспользуемся именно этим, вторым способом. Для запуска программы CGI, расположенной в файле с названием login.pl, мы создали документ HTML со ссылкой Запустить! (рис. 5-12).
Рис. 5-12. Документ HTML со ссылкой для запуска программы CGI Если щелкнуть эту ссылку, в окне браузера появится динамически созданный документ HTML, показанный на рис. 5-13.
Рис. 5-13. Документ HTML, созданный динамически программой CGI Рассмотрим исходный текст документа HTML со ссылкой (листинг 5-1). Листинг 5-1 Вы найдете в файле chap05\cgi-1\www.cgi-test.at-home\root\index.html на прилагаемом к книге компакт-диске. <html> Как видите, в нем с помощью тега <A> определена ссылка на программу CGI следующего вида: <A href="/cgiprg/login.pl">Запустить!</A> Обратите внимание, что здесь мы ссылаемся не на физический каталог cgi, а на псевдоним cgiprg, определенный нами в файле httpd.conf. Имя файла программы CGI (login.pl) выбрано нами произвольно и в настоящий момент не несет никакой смысловой нагрузки. В дальнейшем мы наделим эту программу функцией аутентификации посетителей, и тогда использование данного имени станет оправданным. Теперь настало время изучить исходный текст нашей первой программы CGI, составленной на языке Perl. Вы найдете его в листинге 5-2. Листинг 5-2 Вы найдете в файле chap05\cgi-1\www.cgi-test.at-home\cgi\login.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w Первая строка исходного текста программ Perl всегда выглядит одинаково: #!/usr/bin/perl -w Она указывает путь к программному файлу интерпретатора Perl, а также параметры работы этого интерпретатора. В частности, параметр w включает режим выдачи предупреждений об ошибках. Оператор use с параметром CGI подключает модуль CGI, значительно облегчающий создание CGI-программ: use CGI; И хотя в нашей первой программе его возможности не используются, очень скоро этот модуль нам пригодится. Следующая строка программы записывает в стандартный поток вывода текстовую строку заголовка HTTP: print "Content-Type: text/html\n\n"; В этой сроке определяется тип документа, который будет отправлен браузеру. В нашем случае это текстовый документ HTML. Обратите внимание, что в конце строки заголовка мы пометили два символа конца строки \n. Это необходимо для отделения заголовка HTTP от текста документа HTML пустой строкой. Далее в стандартный поток вывода записывается текст документа HTML: print "<html><head><title>Динамический документ HTML</title></head><body>"; Как видите, он ничем не примечателен и состоит из заголовка и тела, в котором имеется один параграф текста. Для вывода этого небольшого документа можно было использовать и один оператор print. В этом и следующем разделе мы покажем примеры несложных программ CGI, демонстрирующих динамическое создание документов HTML, просмотр переменных окружения и обработку данных, введенных при помощи форм. Предыдущая программа CGI создавала новый документ HTML, не анализируя никаких передаваемых ей данных. Однако большинство программ CGI извлекает данные из форм, а также из так называемых переменных среды Web-сервера (Web-server environment variables). Переменные среды формируемых Web-сервером на основе заголовков HTTP, полученных от браузера. Они были перечислены в разделе «Переменные среды для программы CGI» главы 3. Это такие переменные, как AUTH_TYPE, GATEWAY_INTERFACE, HTTP_ACCEPT и другие. Когда программа CGI, написанная на языке Perl, получает управление, глобальный хеш с именем %ENV записываются все переменные среды. Вы можете извлекать отдельные значения переменных по имени, такому как HTTP_HOST, или выводить их в цикле, перебирая все элементы хеша. В нашей программе (листинг 5-3) мы используем оба способа. Листинг 5-3 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\http-header.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w Прежде всего, обратите внимание, что к динамически формируемому документу HTML мы добавили новый заголовок HTTP, указывающий примененную в документе кодировку символов: print "Content-Type:
text/html\n"; В данном случае применена кодировка символов кириллицы, принятая в ОС Microsoft Windows. Обратите внимание на пустую строку, отделяющую заголовок HTTP от текста документа. Далее наша программа формирует верхнюю часть заголовка и тела документа HTML, отображая в заголовке доменное имя Web-узла, полученное из переменой среды HTTP_HOST: print "<h1>Узел $ENV{'HTTP_HOST'}</h1>"; Здесь в фигурных скобках мы указали имя нужной нам переменой среды. Вслед за заголовком в документ HTML выводится таблица имен и значений переменных среды (рис. 5‑14). Рис. 5-14. Просмотр переменных окружения Ниже мы привели цикл формирования строк таблицы: my $env_var; Цикл проходит по всем ключам хеша %ENV, записывая в переменную $env_var поочередно имена всех переменных окружения. Далее значение каждой переменной окружения сохраняется в переменой $val: my $val=$ENV{$env_var}; Если значение переменной среды не пустое, оно используется при формировании строки таблицы. В том случае, если переменная окружения определена с пустым значением, мы записываем в таблицу значение в виде строки «[не определено]». Наша программа просто отображает значение переменных окружения, но никак их не использует. Вместе с тем анализируя переменные среды, программа CGI может получить немало информации о браузере посетителя, а также о Web-сервере, на котором она работает. Взглянув на рис. 5-14, можно определить, что адрес IP посетителя REMOTE_ADDR равен 154.100.100.31, что браузер посетителя способен отображать страницы, написанные на английском и русском языках (эта информация хранится в переменной среды HTTP_ACCEPT_LANGUAGE). Можно определить тип браузера (переменная HTTP_USER_AGENT), а также тип кодировки документов, воспринимаемой браузером (переменная HTTP_ACCEPT_ENCODING) . Что же касается информации о Web-сервере, то исходя из анализа значения переменной среды SERVER_SIGNATURE, можно сделать вывод о том, что в качестве программного обеспечения сервера используется Apache версии 1.3.20. Из переменной GATEWAY_INTERFACE можно узнать версию протокола CGI, с которой работает данный сервер. Программа CGI может узнать доменное имя Web-сервера, с которого она была запущена (переменная HTTP_REFERER), имя программы (переменная SCRIPT_NAME), физический путь к файлу программы CGI (переменная SCRIPT_FILENAME) и к каталогу документов HTML (переменная DOCUMENT_ROOT), а также другую информацию. Программа CGI может использовать данную информацию, например, для оптимизации своей работы и для получения статистической информации о посетителях. Заметим еще раз, что набор переменных среды зависит от типа и версии программного обеспечения Web-сервера, поэтому не следует ожидать, что Вы получите одинаковый набор переменных для разных Web-серверов и для разных операционных систем. В разделе «Подготовка форм HTML» предыдущей главы мы рассказывали Вам о том, как создавать формы. Тогда же мы привели пример формы, содержащей элементы управления различных типов (на рис. 5-15 эта форма показана в заполненном виде). Немного измененный исходный текст формы на языке HTML приведен в листинге 5-4.
Рис. 5-15. Форма с заполненными полями Теперь мы расскажем Вам о том, как «оживить» эту форму, обеспечив обработку полученных от нее данных в программе CGI. В результате обработки создается динамический документ HTML с таблицей, строки которой отражают содержимое полей формы (рис. 5-16). Рис. 5-16. Данные из полей формы Последние две строки таблицы появляются только в том случае, если для отправки данных формы была использована графическая кнопка Send it!, а не обычная кнопка Send. Листинг 5-4 Вы найдете в файле chap05\www.cgi-test.at-home\root\form.html на прилагаемом к книге компакт-диске. <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 3.2//EN"> Рассмотрим исходный текст программы form.pl, обрабатывающей данные нашей формы (листинг 5-5). Листинг 5-5 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\form.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w В отличие от предыдущей программы, программа form.pl пользуется модулем CGI. Для обработки формы мы загружаем не все функции этого модуля, а только стандартные: use CGI qw(:standard); Далее наша программа записывает в стандартный поток вывода заголовок HTTP создаваемого документа HTML: print "Content-Type:
text/html\n"; Для получения содержимого полей формы мы используем функцию param, определенную в модуле CGI. В качестве параметра этой функции нужно передать имя поля, определенного при помощи параметра NAME соответствующего тега формы. Извлечение содержимого текстовых полей формы В следующей строке мы извлекаем содержимое текстового поля с именем TEXT1 и вставляем его в строку таблицы, формируемой динамически: print "<tr><td width=150>text1</td><td>".param('TEXT1')."</td></tr>"; Соответствующее поле ввода определено в форме так: <input type="text" name="TEXT1" value="Текст" size="30"> Для успешного извлечения содержимого поля Вы должны передать функции param имя поля в точно таком же виде, как оно было определено в форме. В данном случае это имя TEXT1. Обработка текстового поля, предназначенного для ввода паролей, а также многострочного поля выполняется аналогично: print "<tr><td
width=150>pwd</td><td>".param('PWD')."</td></tr>"; Здесь мы передаем функции param имена соответствующих полей, получая от нее содержимое поля. Точно таким же образом мы извлекаем содержимое скрытого элемента управления: print "<tr><td width=150>Скрытый
элемент управления</td> Обработка флажков с независимой фиксацией Как мы уже говорили, состояние флажков с независимой фиксацией можно изменять индивидуально. В нашей форме определено три таких флажка с именами chk1, chk2 и chk3: <INPUT TYPE=CHECKBOX
NAME="chk1" VALUE="on" CHECKED>Первый<BR> Сразу после загрузки формы первый и третий флажок отображаются в отмеченном состоянии. Ниже мы привели фрагмент программы, извлекающий состояние флажков и формирующий соответствующую строку таблицы: print "<tr><td width=150>Отмеченные
флажки CHECKBOX</td><td>"; Программа проверяет, находится ли каждый флажок в отмеченном состоянии, записывая название отмеченного флажка в ячейку таблицы. Для проверки используется тот факт, что только отмеченные флажки формы посылают данные программе CGI. Если флажок не отмечен, функция param, вызванная для этого флажка, возвратит вызывающей программе пустую строку. Обработка флажков с зависимой фиксацией Что касается флажков с зависимой фиксацией, то из них может быть отмечен только один. Все связанные между собой флажки определяются с одним и тем же именем. В нашем случае это имя rad: <INPUT TYPE=RADIO
NAME="rad" VALUE="on1" CHECKED>Первый<BR> Для того чтобы программа CGI могла их различать, каждому флажку мы присвоили свое индивидуальное значение, воспользовавшись для этого параметром VALUE тега <INPUT>. Фрагмент программы, определяющий отмеченную кнопку, приведен ниже: print "<tr><td width=150>Отмеченный флажок RADIO</td><td>"; Здесь при помощи функции param программа извлекает значение параметра VALUE и в зависимости от этого значения записывает ту или иную строку в ячейку таблицы. Наш список содержит три строки, определенных при помощи тега <OPTION>: <SELECT NAME="sel" SIZE="1"> С каждой строкой при помощи оператора VALUE связывается то или иное значение, доступное программе CGI. Вот как мы извлекаем значение, присвоенное строке, которую выбрал посетитель: print "<tr><td width=150>Выбранная
строка списка</td> Как видите, здесь мы используем все ту же функцию param. Обработка данных от графической кнопки Если посетитель отправляет данные формы на Web-сервер при помощи графической кнопки, программа CGI может извлечь координаты курсора (в пикселах), отсчитываемые относительно верхнего левого угла графического изображения кнопки. В нашей форме графическая кнопка определена следующим образом: <INPUT TYPE=IMAGE NAME="graf" SRC="send.gif" BORDER=0> Когда посетитель щелкает такую кнопку, форма отправляет программе CGI два параметра. Имена этих кнопок образуются путем добавления к имени кнопки (заданному параметром NAME) суффиксов «.x» и «.y». Первый такой параметр задает координату X, а второй — координату Y курсора мыши в момент щелчка кнопки. В том случае, когда посетитель отправил данные формы на Web-сервер, щелкнув обычную кнопку типа SUBMIT, указанные выше параметры не передаются. Вот как наша программа получает и обрабатывает данные, полученные от графической кнопки: if(param('graf.x') ne
'') Вначале программа проверяет, что посетитель щелкнул графическую кнопку, а не обычную, анализируя содержимое переменной graf.x (можно было использовать и переменную graf.y). Если содержимое этой переменной не пустое, программа получает координаты курсора мыши, вызывая для этого функцию param. Что программа CGI может сделать с этими координатами? Можно придумать различные применения для графических кнопок. Например, если Ваше Web-приложение отображает в окне браузера картографическую информацию в виде графического изображения, можно масштабировать тот участок карты, который щелкнул посетитель. С помощью графических кнопок можно организовать графические ссылки, отправляющие посетителя на ту или иную страницу Web-узла в зависимости от того, в каком месте он щелкнул графическое изображение. Словом, тут все ограничивается только Вашей фантазией. В примерах, приведенных выше, мы использовали программы CGI только для обработки данных из полей форм. При этом адрес URL загрузочного файла программы указывался в параметре ACTION тега <FORM>. Однако есть и другая возможность вызова программ CGI: указать их адрес в параметре HREF тега ссылки <A>. В этом случае Вы можете передать программе CGI параметры, указав их после имени файла загрузочного модуля через разделительный символ «?». Программа CGI получит строку параметров методом GET и сможет извлечь ее из переменной среды с именем QUERY_STRING или, что проще, с помощью функции param, описанной в предыдущем разделе. Все эти методы позволяют добиться того, чтобы программа CGI загружала в окно браузера тот или иной документ в зависимости от параметров, с которыми она была вызвана. Пример документа HTML, в котором демонстрируется вызов программы CGI указанным выше способом, показан в листинге 5-6. Листинг 5-6 Вы найдете в файле chap05\www.cgi-test.at-home\root\aref.html на прилагаемом к книге компакт-диске. <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 3.2//EN"> В этом документе есть три ссылки на программу CGI с именем aref.exe, причем каждый раз ей передаются разные значения параметра page: <A HREF="/cgiprg/aref.pl?page=1">Издательство
"Русская редакция"</A><BR> Программа CGI принимает параметр и в зависимости от его значения отображает один из документов HTML. Например, при выборе первой строки в окне браузера отображается главная страница сервера Web издательства «Русская Редакция», а при выборе последней — главная страница Web-узла службы восстановления данных DataRecovery.Ru. Исходный текст программы AREF приведен в листинге 5-7. Листинг 5-7 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\aref.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w Программа получает значение параметра page при помощи функции param. Далее она сравнивает значение параметра со строками «1», «2» и «3». При совпадении программа возвращает браузеру адрес URL соответствующего документа HTML, формируя заголовок HTTP специального вида: Location: [Адрес URL]\n\n Когда браузер получает от сервера Web такой заголовок, он отображает документ или файл графического изображения, адрес URL которого указан в заголовке. В случае ошибки посетителю отправляется документ с именем error.html. Таким образом, программа CGI анализирует параметры, поступающие от браузера через ссылку или поля формы, а затем не только динамически формирует документ HTML для отображения в окне браузера, но и возвращает ссылки на уже существующие документы в виде их адресов URL. Эта возможность пригодится Вам, например, для организации ссылок на документы через списки, создаваемые тегом <SELECT>, находящимся в форме. Программа CGI определит, какая строка выбрана в списке в момент посылки заполненной формы серверу Web, и в зависимости от этого, либо возвратит ссылку на тот или иной существующий документ, либо сформирует новый документ динамически. Применение шаблонов HTML В предыдущих примерах программы CGI самостоятельно формировали заголовки HTTP и текст динамически создаваемого документа HTML при помощи функции записи в стандартный поток вывода print: print "<h1>Результаты обработки формы</h1>"; Несмотря на простоту данного способа, он обладает одним существенным недостатком — для работы над дизайном формируемой страницы Web-мастер должен редактировать исходный текст программы CGI. Этот метод пригоден, если создается относительно простой Web-узел, когда и программированием, и дизайном занимается один и тот же человек. Однако более или менее сложные Web-узлы обычно не создают в одиночку. Дизайн создается Web-дизайнерами, а программы CGI, базы данных и другие программные модули — Web-программистами. Технология создания сложных Web-узлов и перечень задач, встающих перед разработчиками, Вы найдете в нашей книге [1]. При этом возникает проблема — дизайнеры могут не владеть языками и технологиями программирования, а программисты не в состоянии самостоятельно разработать и реализовать хороший дизайн Web-узла. Механизм шаблонов, реализованный в модуле HTML::Templates, решает эту проблему для программ CGI, написанных на языке Perl. При этом дизайнер создает шаблон страницы в виде обычного документа HTML, пользуясь привычным для него инструментарием. Помимо обычных тегов HTML шаблон содержит специальные теги, позволяющие программе CGI динамически изменять содержимое шаблона при отправке посетителю. Существуют три вида шаблонов: шаблоны переменных, циклические и условные шаблоны. Расскажем о них подробнее. Шаблоны переменных Шаблоны переменных позволяют подставлять в заданное место формируемого документа содержимое произвольной переменной, определенной в программе Perl. Для этого в шаблоне определяется тег следующего вида: <TMPL_VAR NAME=[Имя переменной шаблона]> В качестве параметра NAME тега <TMPL_VAR> подставляется так называемое имя переменной шаблона, которая будет использована программой CGI для подстановки. Чтобы это было понятнее, сразу перейдем к практическому примеру. Пусть нам нужно написать программу CGI, которая создает динамическую страницу HTML с информацией об адресе IP и браузере посетителя. В листинге 5-8 показан исходный текст шаблона, подготовленного нами для такой страницы. Листинг 5-8 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\Template\templ_sample1.html на прилагаемом к книге компакт-диске. <HTML> Обратите внимание, что помимо обычных тегов HTML в этом шаблоне определено три тега <TMPL_VAR> с именами переменных шаблона REMOTE_ADDR, HTTP_USER_AGENT и HTTP_ACCEPT_LANGUAGE (эти имена выбраны нами произвольно, но так, чтобы отражать смысл передаваемой через них информации). Если просмотреть файл шаблона в браузере, то ячейки таблицы с тегами шаблона <TMPL_VAR> будут показаны пустыми (рис. 5-17). Именно в таком виде шаблон может создаваться и редактироваться Web-дизайнером, не знакомым с программированием вообще и с языком Perl в частности. Рис. 5-17. Просмотр шаблона страницы в браузере Заметим, что файл шаблона не предназначен для непосредственной загрузки в браузер посредством указания его адреса URL. Вместо этого отображение шаблона выполняет программа Perl, обращаясь для этого к функциям, определенным в модуле HTML::Template. Исходный текст программы CGI, предназначенной для работы с только что описанным шаблоном, приведен в листинге 5-9. Листинг 5-9 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\template1.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w Для того чтобы программа могла обращаться к модулю HTML::Template, его нужно подключить явным образом при помощи оператора use: use HTML::Template; Заметим, что модуль HTML::Template не устанавливается вместе с интерпретатором Perl. Его нужно загрузить из библиотеки CPAN и установить, как это было описано в разделе «Установка дополнительных модулей Perl» этой главы. Для работы с модулем HTML::Template необходимо использовать объектно-ориентированные возможности языка Perl. Прежде всего, необходимо создать объект шаблона: my $template = HTML::Template->new(filename => 'template/templ_sample1.html'); Здесь объект создается при помощи метода new, причем ссылка на созданный объект записывается в переменную $template. Методу new мы указываем относительный путь к файлу шаблона, который отсчитывается от каталога программ CGI. Можно, разумеется, указать и абсолютный путь, однако при этом файлы шаблона будут жестко привязаны к физическому расположению содержащего их каталога. Далее наша программа заполняет три переменных шаблона с именами REMOTE_ADDR, HTTP_USER_AGENT и HTTP_ACCEPT_LANGUAGE: $template->param(REMOTE_ADDR =>
$ENV{'REMOTE_ADDR'}); Для инициализации этих переменных мы использовали значения соответствующих переменных окружения, сформированных Web-сервером на основе данных, полученных от браузера посетителя. После того как программа определила значения всех переменных шаблона, можно записывать заголовок протокола HTTP и шаблон в стандартный поток вывода: print header
(-charset=>'windows-1251'); Обратите внимание, что для записи заголовка HTTP мы применили здесь функцию header, определенную в модуле CGI. При этом мы указали параметр charset, задающий кодировку символов документа HTML. Вместо этого можно было воспользоваться и старым методом формирования заголовка, использованным нами в предыдущих программах: print "Content-Type:
text/html\n"; На рис. 5-18 мы показали результат работы нашей программы. Теперь, как видите, все ячейки таблицы заполнены.
Рис. 5-18. Страница, сформированная с использованием шаблона При работе с модулем HTML::Template возможно возникновение ошибок, связанное с его неправильным использованием. Вы можете забыть установить этот модуль или выполнить установку неправильно, указать с ошибкой путь к файлу шаблона или имена переменных шаблона. Если программа CGI, обращающаяся к шаблону, не работает, просмотрите записи в журнале ошибок. Возможно, Вы что-то забыли или сделали неправильно. Для формирования периодически повторяющихся фрагментов документов HTML, таких, например, как строки таблицы, очень удобно использовать так называемые циклические шаблоны. Циклические шаблоны создаются при помощи тегов <TMPL_LOOP> и <TMPL_VAR>. В следующем примере мы покажем использование шаблонов HTML:Template для формирования таблицы значений переменных окружения. Ранее мы уже решали эту задачу, записывая текст документа HTML в стандартный поток вывода (см. раздел «Просмотр переменных окружения» этой главы). Для отображения таблицы, содержащей названия и значения переменных окружения мы подготовили шаблон, исходный текст которого приведен в листинге 5-10. Листинг 5-10 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\Template\templ_sample2.html на прилагаемом к книге компакт-диске. <HTML> Повторяющиеся строки таблицы мы описали с помощью тегов <TMPL_LOOP> и </TMPL_LOOP>: <TMPL_LOOP
NAME="THIS_LOOP"> Обратите внимание, что тег <TMPL_LOOP> снабжен именем, определенным при помощи параметра NAME. Таким образом, в одном документе HTML можно определять несколько циклических шаблонов, задавая для каждого из них свое имя. Что же касается ячеек таблицы, то в них мы записали теги шаблонов переменных с именами ENV_NAME и ENV_VALUE. На их место программа CGI будет подставлять, соответственно, имя переменной окружения и ее значение. Исходный текст программы, заполняющей наш циклический шаблон, представлен в листинге 5-11. Листинг 5-11 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\template2.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w После создания объекта модуля HTML::Template, наша программа определяет массив loop для хранения данных строк таблицы: @::loop = (); Далее программа в цикле записывает в этот массив хеши с именами переменных окружения и их значениями: my %row = (ENV_NAME => $env_var,
ENV_VALUE => $val); После этого заполненный массив используется для инициализации циклического шаблона: $template->param(THIS_LOOP => \@::loop); Заголовок HTTP и циклический шаблон отображаются в окне браузера посетителя точно таким же образом, что и в предыдущем примере: print header
(-charset=>'windows-1251'); В результате посетитель увидит страницу, показанную на рис. 5-14. Условные шаблоны позволяют управлять внешним видом страницы или отдельных ее фрагментов, просто устанавливая значения переменных шаблона. Для условных шаблонов применяются теги <TMPL_IF>, <TMPL_ELSE> и </TMPL_IF>, ограничивающие фрагменты шаблона, которые должны использоваться при выполнении тех или иных условий. В нашей книге мы ограничимся использованием только этих тегов. Документация, загруженная Вами вместе с дистрибутивом модуля HTML::Template, содержит детальное описание этих и некоторых других тегов, применяющихся при создании шаблонов. Для демонстрации возможностей условных шаблонов модифицируем предыдущий пример программы, отображающей значения переменных окружения Web-сервера. Новая программа будет отображать таблицу значений два раза. В первый раз мы используем простой дизайн таблицы, а во второй — немного улучшенный (рис. 5-19). Рис. 5-19. Выбор дизайна таблицы при помощи условного шаблона Исходный текст шаблона, примененного нами в этой программе, представлен в листинге 5-12. Листинг 5-12 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\Template\templ_sample3.html на прилагаемом к книге компакт-диске. <HTML> Обратите внимание, что в этот шаблон мы поместили два определения таблицы, отличающихся только дизайнерским оформлением. Первый, более привлекательный дизайн будет использован для формирования страницы в том случае, когда программа CGI определит значение переменной шаблона с именем SMART_LAYOUT: <TMPL_IF
NAME="SMART_LAYOUT"> В противном случае будет использован более простой способ оформления таблицы. Заметим, что указанным образом можно изменять оформление не только целых таблиц, но и любых отдельных фрагментов документа HTML — ячеек и строк таблицы, отдельных слов, символов, графических изображений и т.д. В одном шаблоне можно задействовать несколько тегов <TMPL_IF>, определив для них разные или одинаковые имена. В первом случае будет выполняться проверка нескольких условий. Что же касается определения значений переменных для условных шаблонов, то оно выполняется таким же образом, как и раньше. Исходный текст соответствующей программы приведен в листинге 5-13. Листинг 5-13 Вы найдете в файле chap05\www.cgi-test.at-home\cgi\template3.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w Обратите внимание, что после однократной выдачи заголовка HTTP наша программа два раза выводит данные шаблона: print header (-charset=>'windows-1251');
Перед вторым выводом программа устанавливает значение переменной шаблона SMART_LAYOUT равным единице. В результате во второй раз будет отображена таблица с улучшенным дизайном. Работа с Cookie в программах CGI В этом разделе мы расскажем Вам о таком важном элементе, как Cookie. Возможно, Вы слышали о нем и даже знаете, что с его помощью недобросовестные администраторы серверов Web получают несанкционированный доступ к файлам пользователей. Что такое Cookie? Скажем сразу, что с кулинарным искусством это связано мало, хотя переводится с английского языка как «печенье» или «булочка». Говоря кратко, Cookie представляет собой свойство документа HTML. Данные Cookie физически хранятся локально на компьютере пользователя, загрузившего этот документ, в виде специальных файлов. Средствами Cookie пользователь может настроить, или «приготовить», по собственному вкусу документ HTML, если для него предусмотрена такая настройка. Проще всего представить себе Cookie как набор строковых параметров, каждый из которых имеет имя и значение. Клиентский сценарий может создавать Cookie для документа HTML, определяя в нем произвольное количество параметров и задавая для них произвольные значения. Далее такой набор параметров становится принадлежностью данного конкретного документа HTML и его может быть проанализирован, изменен или удален сценарием. Как мы уже говорили, основное, для чего нужен Cookie, — так это для того, чтобы предоставить пользователю возможность настроить «под себя» интерфейс активных документов HTML. Эти параметры могут анализироваться или не анализироваться сервером Web, но в любом случае они хранятся у пользователя. И, разумеется, пропадут, если пользователь, скажем, отформатирует свой жесткий диск. После этого для документа HTML их придется задавать заново. Конечно, задачу индивидуальной настройки параметров страниц удается решить и другими способами. Это можно сделать, например, при помощи технологии PHP, активных серверных страниц ASP или расширений сервера Web — программ CGI и приложений ISAPI. Для этого на сервере Web надо установить базу данных, хранящую параметры для всех зарегистрированных в ней пользователей. В этом случае расширение сервера Web способно динамически создавать настраиваемые документы HTML, используя для определения внешнего вида страниц параметры, хранящиеся в базе данных. Возлагая задачу хранения параметров отдельных документов HTML на браузер посетителя, Вы сильно упрощаете задачу организации настройки диалогового интерфейса. А для этого как раз нужны Cookie. Еще одно практическое применение Cookie — хранение товара, выбранного посетителем Вашего виртуального электронного магазина. Покупатель отмечает разный товар на разных страницах сервера. При этом полный заказ вначале формируется и сохраняется в Cookie, а затем по явному запросу пользователя переправляется на сервер. Среди других применений Cookie можно отметить сетевые игры. В Cookie может хранится, например, текущее состояние игры или другие параметры. При разработке приложений Web помните, что приложения ни при каких условиях не должны хранить в Cookie такую информацию, как идентификаторы пользователей и пароли, а также номера кредитных карточек. Дело в том, что эта информация может оказаться доступной администраторам серверов Web и попасть в третьи руки. Обнаружив, что Ваше приложение пытается записывать в Cookie конфиденциальную информацию, предусмотрительные пользователи, скорее всего, откажутся от работы с ним. Далее мы рассмотрим основные операции с Cookie, например создание Cookie, получение и изменение значений параметров Cookie, а также удаление Cookie. Существуют два способа создания Cookie, первый из которых используется расширениями сервера Web, а второй — клиентскими сценариями. Мы рассмотрим только первый из них в приложении к программам CGI. Детальное описание второго способа и примеры приложений Вы найдете в [1]. Там же рассказано о приемах работы с Cookie в серверных сценариях ASP. Заголовок HTTP для создания Cookie Для того чтобы создать Cookie первым способом, программа CGI или расширение Web-сервера другого типа обычно добавляет в заголовок HTTP динамически создаваемого документа HTML поле с именем Set-Cookie. В нем определяются имена и значения параметров Cookie. Когда программа CGI вызывается из документа HTML, имеющего Cookie, параметры Cookie предаются этому расширению через поле Cookie заголовка HTTP и могут быть проанализированы. Заголовок HTTP, предназначенный для создания Cookie, выглядит следующим образом: Set-Cookie: Имя=Значение; expires=Дата_GMT; Описание отдельных полей заголовка Set-Cookie приведено в табл. 5-1. Таблица 5-1. Поля заголовка Set-Cookie
Все поля, кроме первых двух (Имя и Значение), не обязательны. Дата должна быть записана в формате День_недели, ДД-Мес-ГГ ЧЧ:ММ:СС GMT, где: · День_недели — английское трехбуквенное сокращение названия дня недели (например, Mon); · ДД — номер дня недели; · Мес — английское трехбуквенное сокращение названия месяца (например, Jun); · ГГ — две последние цифры года; · ЧЧ — часы; · ММ — минуты; · СС — секунды. Например, дату можно указать так: Mon, 07-Jun-93 14:45:00 GMT Сделаем небольшое замечание относительно полей domain и path, определяющих условие, при котором выполняется установка Cookie. Когда браузер загружает документ HTML с сервера Web и среди заголовков HTTP этого документа присутствует заголовок Set-Cookie, он проверяет возможность установки Cookie. В процессе проверки анализируется адрес URL, откуда был загружен этот документ, а также содержимое полей domain и path. Если эти поля не указаны, то по умолчанию считаются, что они соответствуют адресу URL, по которому находится загруженный документ HTML. В этом случае выполняется установка Cookie. Когда же указано поле domain, установка Cookie выполняется, только если документ загружен с сервера Web, принадлежащего данному домену. Средствами параметра path можно установить ограничение на адреса URL в рамках домена, для которых выполняется установка Cookie. При этом значение «/» соответствует всем адресам данного домена. Одновременно сервер Web способен создать несколько параметров Cookie, включив в заголовок документа HTML несколько заголовков Set-Cookie. Запись Cookie программой CGI Когда сценарий CGI создает страницу, он может записать Cookie в заголовке HTTP с помощью обычной функции print. Вот фрагмент программы CGI, записывающий Cookie подобным образом: print "Content-Type:
text/html\n"; Здесь записывается Cookie с именем $cookie_name и значением $cookie_value. После записи Cookie программа выводит шаблон, путь к которому находится в переменной $template_path. Пользуясь информацией из предыдущего раздела Вы можете формировать Cookie подобным образом, задавая различные поля, описанные в табл. 5-1. Модуль Perl с названием CGI предоставляет в распоряжение программиста другие средства записи Cookie. Вот, например, как можно записать сразу два Cookie: use CGI qw/:standard/; Заметим, что если Вы не указали дату автоматического удаления Cookie, то созданные подобным образом Cookie будут автоматически удалены при завершении работы браузера. Если задана дата, которая еще не наступила, данные Cookie записываются в локальный файл на компьютер посетителя и хранятся там до момента автоматического удаления Cookie. В том случае, когда указана уже наступившая дата, данные Cookie будут удалены немедленно. Практическое применение Cookie мы рассмотрим в главе 8 «Виртуальное кадровое агентство Трудоголик.Ру» при описании Web-узла администрирования виртуального кадрового агентства http://www.trudogolik.ru. Получение значения Cookie Итак, мы рассказали, как создавать Cookie в клиентских сценариях. Теперь попробуем решить другую задачу — определение значения параметров Cookie. Проще всего это сделать при помощи функции cookie, определенной в модуле Perl с названием CGI: my $user_id_cookie=cookie('trudogolik_ru_user_id'); Здесь мы получаем значение Cookie с именем trudogolik_ru_user_id и затем сохраняем его в переменной $user_id_cookie для дальнейшего использования. Изменение значения параметра Cookie Для изменения значения параметра Cookie с заданным именем Вы можете просто записать новое значение с использованием одной из двух технологий, описанных нами ранее в разделе «Запись Cookie программой CGI» этой главы. Самый простой способ удалить Cookie — установить для него такую дату автоматического удаления, которая уже прошла: print "Content-Type:
text/html\n"; Здесь мы задали уже прошедшую дату автоматического удаления: 1 января 1970 года. Разумеется, программа Perl может определить текущую дату, немного уменьшить ее и затем использовать полученный результат для формирования даты автоматического удаления. Модуль CGI позволяет указывать относительную дату автоматического удаления: use CGI qw/:standard/; Здесь мы указали дату автоматического удаления, которая прошла 5 дней назад. Ограничения на использование Cookie На использование Cookie накладываются определенные ограничения, перечисленные ниже: · всего разрешается создать не более 300 Cookie; · необходимо, чтобы размер каждого Cookie не превышал 4 кб; · для каждого домена может быть создано не более 20 Cookie Данные ограничения зависят от типа браузера и приведены только для ориентировки. Если указанные ограничения нарушаются, браузер может удалить самые старые Cookie или обрезать значения параметров Cookie. Заметим, что технологию Cookie нужно использовать только в тех случаях, когда она действительно необходима. Разработчик Web-приложения не может полагаться на то, что браузер посетителя принимает Cookie или что данные Cookie хранятся какое-то определенное время. Поэтому неправильное использование Cookie может привести к ненадежной работе Web-приложения. Там, где требуется высокая надежность работы и максимальная независимость работоспособности Web-приложения от типа браузера, установленного у посетителя, Cookie использовать не рекомендуется. Рассмотрите другие альтернативы хранения персональных данных посетителей, например, хранение этих данных в СУБД, установленной на сервере. Обмен данными с сервером электронной почты Большинство приложений Web тем или иным способом интегрируется с почтовыми серверами. Например, сервер Web Интернет-магазина может выполнять ночную рассылку сообщений ленты новостей по электронной почте или отправлять почтовые сообщения из форм, расположенных на его страницах. В этом разделе мы расскажем Вам об основных протоколах электронной почты и научим отправлять почтовые сообщения при помощи программ CGI, составленных на языке программирования Perl. Если Вы создаете ASP-приложения для операционной системы Microsoft Windows, мы рекомендуем Вам прочитать в [1] описание элемента управления ActiveX с названием MTASend. Этот элемент может быть использован для отправки электронной почты серверными сценариями ASP. Как Вы, наверное, знаете, электронная почта появилась в Интернете еще до возникновения серверов Web вместе с операционной системой UNIX. Работать с электронной почтой в локальных и глобальных компьютерных сетях, выполненных на базе UNIX, позволял протокол копирования UNIX-UNIX (UNIX to UNIX Copy, UUCP). При использовании этого протокола почта передавалась последовательно с одного узла на другой, в результате чего она иногда долго путешествовала по сети, прежде чем достигала адресата. Сегодня в Интернете протокол UUCP, хотя и применяется, но гораздо реже: его постепенно заменяют современные протоколы: · простой протокол передачи почты (Simple Mail Transfer Protocol, SMTP); · протокол почтового отделения (Post Office Protocol, POP); · протокол доступа к сообщениям Интернета (Internet Message Access Protocol, IMAP) Эти протоколы надежнее и быстрее, чем UUCP. Все они описаны в документах RFC. О том, что представляют собой эти документы, мы подробно рассказывали в главе 1. Если Вас заинтересовал какой-либо протокол, отыщите его описание в документе RFC, отыскав тот по номеру и загрузив его, например, c Web-сервера http://www.rfc-editor.org. Простой протокол передачи почты Simple Mail Transfer Protocol (SMTP) предназначен только для передачи почты. Обычно его используют в паре с протоколами POP3 и IMAP, обеспечивающими прием почтовых сообщений. Работа протокола SMTP основана на передаче текстовых строк. После того как почтовая программа установит соединение с почтовым сервером провайдера, между ней и сервером начинается обмен текстовыми строками. Чуть позже мы покажем примерный сценарий такого обмена. Например, почтовая программа установила соединение с почтовым сервером smtp.galsnet.ru. Это доменный адрес сервера SMTP компании провайдера Гласнет. Если Вы подключены к другому провайдеру, то и адрес сервера SMTP будет иным. Сразу после установки соединения с использованием порта 25 почтовый сервер посылает почтовой программе сообщение следующего вида: 220-hawk.glas.apc.org Smail-3.2.0.109
(#4 1999-Nov-10) ready at Sun, 26 Dec 1999 Для другого сервера внешний вид приглашения будет отличаться от приведенного выше. В ответ почтовая программа отправляет серверу SMTP команду
подключения HELO smtp.glasnet.ru Если подключение выполнено без ошибок, сервер должен ответить сообщением с кодом 250: 250 hawk.glas.apc.org Hello smtp.glasnet.ru (smtp.glasnet.ru from address [195.178.200.74]). Далее почтовая программа продолжит диалог с сервером. Теперь
она отправит серверу команду MAIL FROM: alexandre@frolov.pp.ru Здесь в качестве адреса отправителя используется наш электронный почтовый адрес alexandre@frolov.pp.ru, так как мы отправляли сообщение именно снего. В ответ почтовая программа получает следующее сообщение с кодом 250: 250 2.1.0 alexandre@frolov.pp.ru Sender Okay. Теперь она должна сообщить серверу адрес получателя. Например: RCPT TO: a_frolov@hotmail.com Здесь указан наш второй адрес электронной почты на сервере Hotmail. Об этом сервере мы Вам уже рассказывали в главе 5. В ответ сервер посылает почтовой программе подтверждение следующего вида: 250 2.1.0 'a_frolov@hotmail.com' Recipient Okay. Далее почтовая программа передает серверу команду, свидетельствующую о готовности к началу передачи данных (то есть тела сообщения): DATA В ответ она получает приглашение для ввода текста сообщения с кодом 354: 354 Enter mail, end with "." on a line by itself... Далее она передает серверу строки заголовка сообщения, начиная с Subject: SUBJECT:Test И затем — пустую строку и строки тела сообщения. Завершает ввод строка, состоящая из одной точки в первой позиции: This is test В нашем послании тело сообщения состоит только из одной строки (что вполне допустимо). Сообщение будет отправлено, а почтовая программа получит извещение об этом в следующем виде: 250 2.6.0 Mail accepted, queue ID m122Hir-001oz7n. Как видите, протокол SMTP действительно оправдывает свое название — он весьма прост: описание основ его работы занимает всего лишь около страницы книги (мы опустили некоторые несущественные детали, не меняющие сути дела). Обратите внимание, что текст сообщения передается в открытом виде, а для соединения с почтовым сервером не нужно указывать идентификатор пользователя и пароль. Из этого следует, что протокол SMTP не обеспечивает никакой, даже самой слабой защиты передаваемой информации. Ее легко перехватить или подделать. Чтобы хоть как-то контролировать процесс отправки почты, провайдеры требуют установки прямого соединения между компьютером, отправляющим почту, и почтовым сервером SMTP провайдера (строго говоря, они должны находиться в сети с одним адресом IP). При этом, дабы вычислить пользователя, который, например, занимается массовой рассылкой рекламной почты, провайдеру достаточно сопоставить параметры отправленного сообщения и статистические данные о работе своих клиентов. В табл. 5-2 мы перечислили основные команды протокола SMTP. Таблица 5-2. Команды SMTP
Более подробно протокол SMTP и все его команды описаны в документе RFC 821. Протокол почтового отделения Post Office Protocol версии 3 — POP3 — предназначен для получения почты с сервера и обычно применяется вместе с только что описанным протоколом SMTP. Для того чтобы подключится к серверу POP3 (имеющему, как и сервер SMTP, свой доменный адрес), почтовая программа должна сообщить ему идентификатор и пароль пользователя. Протокол POP3 обеспечивает некоторую защиту. Во всяком случае, никто не сможет забрать Ваши почтовые сообщения, не зная Вашего идентификатора и пароля. Когда почтовая программа загружает сообщение с сервера POP3, она может либо удалить оригинал сообщения, либо оставить его на постоянное или временное хранение. Строго говоря, протокол POP3, в отличие от своего предшественника POP2, способен не только принимать, но и передавать сообщения. Поэтому при его использовании протокол SMTP не требуется. Однако многие почтовые программы все же используют оба протокола — и SMTP, и POP3. Чтобы Вы получили некоторое представление о том, что представляет собой протокол POP3, расскажем, как с его помощью почтовые программы получают информацию о содержимом почтового ящика пользователя и загружают сообщения. В качестве примера мы рассмотрим сервер POP3 с вымышленным именем pop3.goods.ru (не пытайтесь обращаться к нему; если хотите потренироваться, воспользуйтесь сервером своего провайдера). После того как почтовая программа установит соединение с сервером POP3 с использованием порта 110, она получит от него сообщение следующего вида: +OK QPOP (version 2.53) at pop3.goods.ru starting. В ответ она посылает серверу команду подключения USER username Сервер отправляет почтовой программе сообщение о необходимости предоставления пароля пользователя с идентификатором username: +OK Password required for username. Почтовая программа пересылает его с помощью команды PASS ******* Далее сервер «докладывает» почтовой программе, сколько сообщений хранится в почтовом ящике пользователя и сколько они занимают места на диске сервера: +OK username has 6 messages (27973 octets). Эту же информацию можно получить посредством команды STAT Команда LIST Для каждого сообщения в списке указан его размер в количестве символов. Список завершается строкой, состоящей из одной точки. Если команде LIST 1 Чтобы извлечь полный текст сообщения с заданным номером,
почтовая программа должна отправить серверу POP3 команду RETR 4 Командой TOP 4 10 Вот что вернул сервер в ответ на эту команду: +OK 2735 octets Почтовая программа анализирует ответ сервера POP3, извлекает из него поля заголовка, текст сообщения и отображает все это в окне просмотра сообщения. В табл. 5-3 мы кратко описали некоторые команды протокола POP3. Полную информацию о протоколе POP3 и его командах Вы найдете в документе RFC 1939. Таблица 5-3. Команды POP3
Команды Пара протоколов SMTP и POP3 очень удобна для обмена почтой в пакетном режиме. При этом за относительно короткий промежуток времени, когда Ваш компьютер подключен к серверу провайдера, Вы отправляете сообщения по протоколу SMTP и получаете по протоколу POP3. Когда обмен почтой завершен, можно отключаться от Интернета и работать с полученными сообщениями в автономном режиме. Таким образом, Вы сэкономите деньги, так как передача и прием сообщений занимает немного времени (если, конечно, Вы не отправляете письма с файлами приложений, имеющими размеры в несколько мегабайт), а вот на их чтение его требуется гораздо больше. Тем не менее, в последнее время все популярнее становится такая услуга, как постоянное подключение к Интернету: Вы платите фиксированную сумму в месяц и получаете неограниченный доступ в глобальную сеть. При этом для работы с электронной почтой удобнее использовать современный протокол доступа к сообщениям Интернета Internet Message Access Protocol (IMAP). Он описан в документе RFC 2060 и используется совместно с протоколом SMTP. В отличие от протокола POP3, загружающего на Ваш компьютер все сообщения целиком или частично, протокол IMAP позволяет передавать только заголовки сообщений. Это отнимает намного меньше времени. Просмотрев заголовки, Вы решите, какие сообщения Вас заинтересовали и загрузите именно их. Остальные сообщения Вы имеете возможность стереть, не читая. Что же касается новых сообщений, то, как только Вы их создадите, они немедленно будут скопированы на почтовый сервер и затем переданы адресату. Среди возможностей четвертой версии этого протокола — IMAP4 нам хотелось бы отметить поиск сообщений, хранящихся на сервере, по ключевым словам. Заметим, что протокол POP3 тоже позволяет отказаться от загрузки некоторых сообщений, параметры которых задаются в специальном фильтре. Например, от сообщений, пришедших с каких-то конкретных адресов или содержащих в своем теле или в строке Тема (Subject) какие-то конкретные слова. Однако в этом режиме нельзя просмотреть заголовки отвергнутой почты, так как она сразу по поступлении удаляется с сервера. Режим постоянного подключения к Интернету или тарифный план без ограничения времени подключения позволяет, не торопясь, просматривать сообщения и загружать их с почтового сервера с помощью протокола IMAP. Но если Вы выбрали поминутный режим оплаты сеанса связи с Интернетом, лучше воспользоваться протоколами SMTP и POP3. Внутренняя структура электронного сообщения Любое сообщение, передаваемое по каналам электронной почты, состоит максимум из трех основных компонентов: заголовка, тела сообщения и присоединенных файлов, передаваемых вместе с сообщением. Заголовок содержит адресную и служебную информацию, тело сообщения — текст электронного письма, а присоединенные файлы — любые данные. Заголовок и тело сообщения неотъемлемая часть сообщения, а вот присоединенные файлы Вы вставляете в послание сами, если Вам это требуется. Фактически присоединенные файлы можно рассматривать как необязательную часть тела сообщения. Заголовок почтового сообщения состоит из нескольких полей. Некоторые из них Вы должны заполнить сами (это поля To, Cc, Bcc и Subject), чтобы отправить новое сообщение. Эти поля расположены в окне нового сообщения, которое Вы открываете в почтовой программе. Остальные почтовая программа заполнит автоматически. Вот заголовок письма, который мы сами отправили на наш же электронный адрес: From: "Alexandre Frolov"
<alexandre@frolov.pp.ru> Этот заголовок можно увидеть, например, в почтовой программе Microsoft Outlook Express. Для этого в окне просмотра сообщения из меню File нужно выбрать строку Properties. Далее на вкладке Detailes щелкните кнопку Message Source. На экране появится окно с полным текстом сообщения, включающим все заголовки. Вам не придется создавать такие заголовки вручную, так как эта работа выполняется почтовыми программами. Тем не менее в ряде случаев (например, для борьбы с отправителями надоедливых рекламных сообщений) знание формата заголовка и назначения его полей Вам весьма пригодится. Рассмотрим некоторые поля заголовка по отдельности. From. В этом поле, заполняющемся автоматически почтовой программой, указывается имя и электронный адрес отправителя сообщения. В данном случае сообщение было отправлено Александром Фроловым (Alexandre Frolov) с адреса alexandre@frolov.pp.ru. To. Здесь указывают электронный почтовый адрес получателя сообщения. Так как мы послали почту сами себе, то ввели здесь тот же адрес, что и в поле From. Обычно же содержимое этого поля не совпадает с содержимым поля From. Cc. Имя поля образовано как сокращение от словосочетания Carbon Copy, которое можно перевести как «копия». Это поле Вам понадобится, когда Вы захотите разослать одно сообщение сразу по нескольким адресам. Надо указать в этом поле список электронных адресов, и сообщение будет отправлено по ним всем. Bcc. Названия этого поля образовано от Blind Carbon Copy — «слепая», или «блокированная», копия. По своему назначению это поле аналогично полю Cc, однако между ними есть одно существенное отличие. Поле Bcc позволяет скрыть от получателей список рассылки: имена других адресатов сообщения останутся неизвестны Вашим корреспондентам. Subject. Здесь Вам надо кратко описать содержимое почтового сообщения. Когда адресат получит Ваше послание, по описанию в поле Subject он поймет, о чем речь в сообщении. Date. Это поле заполняется автоматически почтовой программой. Оно содержит дату создания сообщения. В конце строки даты указано значение смещения часового пояса (разница между местным временем и временем по Гринвичу), для Москвы оно равно +3 часам. MIME-Version. Электронные сообщения передаются в закодированном виде. В поле MIME-Version почтовая программа указывает номер версии стандарта многоцелевых расширений почты Интернета (Multipurpose Internet Mail Extension, MIME), использованной для кодирования данного сообщения. Content-Type. В соответствии со стандартом MIME сообщение может содержать данные различного типа — как текстовые, так и двоичные. Причем в заголовке сообщения обязательно находится строка описания типа данных для каждого конкретного сообщения. Тип данных описывается в поле заголовка Content-Type (данное поле автоматически заполняется почтовой программой), например: Content-Type: multipart/alternative; В данном случае тип X-Priority и X-MSMail-Priority. Здесь определяется так называемый приоритет почтового сообщения. Что это такое? Почтовые программы позволяют задавать для сообщения низкий, обычный или высокий приоритет. В списке полученных сообщений, отображаемом в окне почтовой программы, высокоприоритетные сообщения выделяются цветом или специальным символом таким образом, чтобы пользователь сразу обратил на них внимание (способ выделения разный в разных почтовых программах). Низкоприоритетные сообщения также выделяются, но по-другому. Присваивать своим сообщениям повышенный приоритет нужно только при необходимости. В противном случае обилие выделенных сообщений будет лишь раздражать Ваших корреспондентов. X-Mailer. Здесь почтовая программа записывает свое собственное название и версию. Анализируя содержимое данного поля, нетрудно узнать, какой почтовой программой пользуется Ваш корреспондент. Например, взглянув на показанный выше заголовок, можно установить, что для подготовки сообщения использовалась почтовая программа Microsoft Outlook Express версии 5.00.2314.1300 (цифры 2314.1300 означают номер модификации для версии 5.0). X-MimeOLE. Здесь указывается название и версию программной компоненты, выполняющей кодирование данных в стандарте MIME. Чтобы показать, как выглядит тело сообщения, мы подготовили с помощью почтовой программы Microsoft Outlook Express небольшое электронное письмо, состоящее из одной строки «Test message». Заголовок этого сообщения показан в предыдущем разделе. Ниже мы приводим тело сообщения полностью, таким, как его создает почтовая программа: This is a multi-part message in MIME
format. Как видите, собственно строка сообщения составляет лишь малую часть тела сообщения. Почтовая программа Microsoft Outlook создала два фрагмента для двух вариантов сообщения, один из которых текстовый, а другой подготовлен с применением языка разметки гипертекста HTML, применяемого для создания страниц серверов Web. Каждый фрагмент имеет свой заголовок, начинающийся со строки разделителя. Вы видите, что первый фрагмент имеет тип text/plain, а второй — text/html. Этот тип определяется содержимым поля Content-Type. Кроме типа данных, в заголовке фрагмента указано название набора символов сообщения charset и тип кодирования Content-Transfer-Encoding. В данном случае для текста использован набор символов koi8-r, а для кодирования этого текста при передаче в теле сообщения используется формат quoted-printable. О наборах символов и кодировке текста сообщения мы расскажем в следующем разделе этой главы. Когда Вы получите сообщение, то его текст будет извлечен почтовой программой из тела, перекодирован и отображен в окне этой программы без служебной информации. Вам не придется каждый раз вручную вычленять его из приведенного выше листинга, хотя при необходимости такую операцию можно выполнить (это требуется, например, для извлечения отдельных фрагментов сообщений, поврежденных в процессе передачи). Для чего почтовая программа поместила в тело сообщения два фрагмента? Первый из них предназначен для устаревших почтовых программ, которые не способны отображать сообщения в формате HTML. Такие программы проигнорируют фрагмент типа text/html. Что же касается новых программ, то они способны реализовать богатые возможности языка HTML, применяя их для шрифтового и стилевого оформления почтовых сообщений, а также для размещения в таких сообщениях графических изображений и активных объектов. Сообщения, подготовленные с применением языка разметки HTML, выглядят более привлекательно, чем обычный неформатированный текст. Наборы символов и кодировка сообщения Остановимся подробнее на названии набора символов, указанного в поле charset. Как Вы, наверное, знаете, серверы Интернета создаются на базе различных операционных систем, однако большинство почтовых серверов и серверов Web работают в среде Unix. На компьютерах пользователей Интернета, однако, может быть установлена не только операционная система Windows, но и Unix, IBM OS/2 и даже DOS. Так как в разных операционных системах применяются различные несовместимые между собой наборы символов, появляются, в частности, сложности с отображением кириллицы. Обычно почтовые сообщения с символами кириллицы передаются через Интернет с применением набора символов KOI8-R, принятого по умолчанию в операционной системе Unix, однако возможны и другие наборы. В табл. 5-4 мы перечислили названия стандартных наборов символов кириллицы для некоторых наиболее распространенных операционных систем. Таблица 5-4. Наборы символов кириллицы в разных операционных системах Помимо этого существует и другая проблема при передаче сообщений по каналам электронной почты. Она связана с тем, что некоторые почтовые серверы способны пропускать только 7-битные потоки данных, а для представления полного набора символов (т. е. букв, цифр, знаков пунктуации) нужно 8 бит. Чтобы решить эту проблему, применяется дополнительное кодирование текста передаваемых сообщений. На заре развития электронной почты для кодирования использовался метод «кодировка UNIX-UNIX» (UNIX to UNIX Encode, UUEncode): двоичные 8-битные данные представлялись 7-битным эквивалентом в виде символов латинского алфавита. Имейте в виду, что латинские символы кодируются числами в диапазоне от 0 до 127 и могут быть представлены только посредством 7 бит. Как мы уже говорили, сегодня кодирование почтовых сообщений выполняется в соответствии со стандартом многоцелевых расширений почты Интернета (Multipurpose Internet Mail Extension, MIME). При этом в заголовке фрагмента помимо названия набора символов сообщения charset указан и тип кодирования Content-Transfer-Encoding. А теперь мы перечислим различные типы кодирования (примеры использования некоторых из них показаны в следующем разделе): · binary — означает отсутствие кодирования. Символы сообщения передаются в исходном виде, даже если для их представления используется 8 бит. Передаваемые строки сообщения могут иметь большую длину; · 8-bit — аналогично предыдущему, но передаются строки небольшого размера; · 7-bit — аналогично предыдущему, но для представления символов передаваемого сообщения используется только 7 бит; · quoted-printable — применяется для кодирования текста, большинство символов которого могут быть представлены посредством 7 бит. Это латинские символы. Если же для представления символа необходимо 8 бит, то такой символ кодируется с использованием 7-битных символов; · base-64 — в результате кодирования данного типа выполняется преобразование групп из трех 8-битных символов в группы по четыре 6-битных символа. В результате такой кодировки размер сообщения увеличивается примерно на треть; · x-token — если указан этот тип кодирования, то отправляющая и принимающая программа сами договариваются между собой об использовании той или иной кодировки символов. Как мы уже говорили, в электронное письмо разрешается вставить присоединенные файлы. В зависимости от содержимого такого файла применяется тот или иной метод кодирования. Например, вот какие данные добавляются к телу сообщения в том случае, если в роли дополнительного выступает текстовый файл, содержащий только латинские символы: ------=_NextPart_000_0019_01BFE386.575BA590 Мы добавили к сообщению файл с именем Text Document.txt. Как видите, в заголовке фрагмента указан тип данных application/octet-stream, имя файла и 7-битная кодировка. Далее следует пустая строка и данные файла до строки разделителя. Если к сообщению присоединяется двоичный файл, он кодируется по-другому: ------=_NextPart_000_004A_01BF8F69.E9392E40 Ради экономии места мы пропустили часть листинга. Как видите, для двоичного файла с именем RK.COM применена кодировка base64. В результате 8-битовый поток данных удалось представить в виде 7-битовых символов ANSI. Кодировка ANSI Американский национальный институт стандартов American National Standards Institute (ANSI) разработал стандарт для представления символов. Согласно этому стандарту, каждому из 256 символов соответствует одно 8-битное значение (т. е. один символ кодируется одним байтом). При этом первые 128 значений (с кодами в пределах от 0 до 127) соответствуют латинским буквам и символам. Значения от 128 до 255 предназначены для представления специальных символов и букв национальных алфавитов. Используя 7-битную кодировку, можно представить только латинские буквы и символы. Вы можете познакомиться со стандартами ANSI на сервере Web http://www.ansi.org. Отправка данных из формы по электронной почте Рассмотрим программу CGI, составленную на Perl и используемую на нашем узле Web службы восстановления данных DataRecovery.Ru для отправки срочной заявки на выполнение аварийных работ. Соответствующая страница узла http://www.datarecovery.ru показана на рис. 5‑20.
Рис. 5-20. Форма для отправки срочного сообщения На этой странице расположена форма с двумя текстовыми полями и двумя списками. Для оформления заявки в текстовых полях необходимо указать номер контактного телефона и Ваше имя, а в списках выбрать тип файловой и операционной системы. Щелкнув кнопку Экстренный вызов, Вы отправите сообщение в службу восстановления данных. Ниже мы привели фрагмент исходного текста страницы экстренной помощи, одержащий только что описанную форму:
Как видите, атрибут ACTION тега FORM задает путь к программе обработки данных формы как http://www.datarecovery.ru/urgent_mail.pl. Файл urgent_mail.pl представляет собой программу CGI, составленную на языке программирования Perl (листинг 11-19). Поля формы с именами PHONE и NAME предназначены соответственно для ввода номера контактного телефона, а также имени контактного лица. Список FS позволяет выбрать тип файловой системы, а список OS — тип операционной системы. Исходный текст программы urgent_mail.pl Рассмотрим исходный текст программы urgent_mail.pl (листинг 11-19). Листинг 5-14 Вы найдете в файле chap5\urgentmail\urgentmail.pl на прилагаемом к книге компакт-диске. Начальный фрагмент программы характерен для всех программ CGI, составленных на языке Perl:
Как мы уже говорили, в первой строке мы указываем путь к
интерпретатору Perl. Если программа выполняется под
управлением операционной системы Microsoft Windows NT или Microsoft Windows 2000, указанный в этой строке путь /usr/bin/perl не используется. Параметр Вторая строка заставляет интерпретатор Perl выполнять строгую проверку использования необъявленных и неинициализированных переменных:
Далее мы подключаем к программе два дополнительных модуля CGI и Net (вторая строка направляет сообщения об ошибках программы в окно браузера, что облегчает отладку):
Модуль CGI необходим для
использования функций, выполняемых программами CGI.
Параметр В программе urgent_mail.pl определены две функции с именами Функция
Записав входной параметр в служебную переменную с именем Функция Для отправки почты используется функция с именем
Функции Переменные Первое, что делает функция
Здесь в переменной Если канал создать не удалось, функция возвращает значение 1
и завершает свою работу. В противном случае функция заполняет поля заголовка
сообщения и отправляет их на сервер при помощи метода Перед тем как вернуть управление, функция завершает процесс
передачи данных на почтовый сервер методом Обработка формы HTML Модуль CGI содержит чрезвычайно
удобные средства для обработки данных форм HTML,
поступающих от браузера. В своей программе мы использовали функцию Вот как мы извлекаем из формы номер телефона, а также имя контактного лица:
Как видите, для этого нам потребовалось написать в программе всего две строки. Чтобы не отправлять сообщение в тех случаях, когда посетитель забыл указать номер телефона или имя, мы выполняем простую проверку:
В номере телефона, хранящемся в переменной Если посетитель ошибся при заполнении формы, наша программа отправляет ему содержимое документа HTML с сообщением об ошибке. Этот документ хранится в файле с именем mail_incomplete.htm. Для этого вначале программа динамически формирует заголовок документа, указывая в нем кодировку символов Windows-1251:
Далее программа открывает файл mail_incomplete.htm и копирует его
содержимое в выходной поток, а затем закрывает файл. Если файла нет, программа
завершает свою работу аварийно посредством команды Теперь мы рассмотрим действия программы в том случае, если
контактная информация указана правильно. При этом программа отправляет
сообщение электронной почты в два адреса, дважды вызывая для этого функцию
В первый раз сообщение отправляется по адресу alexandre@frolov.pp.ru, а во второй — на адрес шлюза с системой передачи сообщений SMS на мобильный телефон или пэйджер (адрес datarecovery@sms_gate.ru указан только для примера, в своих программах Вы должны заменить его). Обратите внимание, что в качестве первого параметра мы
передаем функции Тема сообщения указана как «Urgent!» («Срочно!»). Текст сообщения комбинируется из содержимого полей формы, заполненной посетителем узла Web службы восстановления данных. Отправив сообщения, программа проверяет содержимое переменных
Если оба сообщения отправлены без ошибок, посетителю отправляется содержимое файла mail_ok.htm, а в противном случае — содержимое файла mail_error.htm. Итак, теперь Вы умеете создавать программы CGI, отправляющие сообщения электронной почты. Однако иногда возникает обратная задача — нужно «научить» Web-сервер принимать почту с использованием протокола POP3. Для чего Web-серверу принимать почту? С помощью программы, запускающейся периодически планировщиком процессов, Вы сможете создать почтового робота. Получая задания по электронной почте в виде ключевых слов или ключевых фраз, такой робот может выполнять резервное копирование данных, «чистку» баз данных от ненужных записей, добавление пользователей в какие-либо списки и удаление пользователей из списков, и другие аналогичные задачи. Пользуясь сведениями о работе с электронной почтой, приведенными в этой главе, Вы даже сможете создать свою почтовую систему с Web-интерфейсом, напоминающую по своим функциональным возможностям таким системам, как Microsoft Hotmail. Заметим, однако, что программы CGI, составленные с использованием языка Perl, не подойдут для обработки огромного количества запросов в единицу времени, характерных для известных бесплатных систем электронной почты. Однако корпоративную почтовую систему с Web-интерфейсом вполне можно создать при помощи программ CGI, написанных на языке Perl. Мы расскажем Вам о двух модулях Perl, предназначенных для получения электронной почты посредством протокола POP3. Это модули Net::POP3 и Mail::POP3Client. Оба этих модуля можно найти в архиве CPAN (http://www.cpan.org). Там, кстати, имеются модули и для создания почтовых серверов, однако их рассмотрение выходит за рамки нашей книги. Использование модуля Net::POP3 Модуль Net::POP3, имеющий объектно-ориентированный интерфейс, содержит все необходимые методы для подключения к серверу электронной почты, извлечения списка сообщений, хранящихся в почтовом ящике, а также самих сообщений и связанной с ними информацией. В листинге 5-15 мы привели исходный текст несложной программы CGI, проверяющей содержимое почтового ящика и отображающей в окне браузера обнаруженные в нем сообщения электронной почты. Листинг 5-15 Вы найдете в файле chap5\www.cgi-test.at-home\cgi\read_mail.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w Для того чтобы программа могла работать с модулем Net::POP3, его необходимо подключить при помощи оператора use: use Net::POP3; Дополнительно в нашей программе мы будем работать с модулем HTML::Entities: use HTML::Entities (); Этот модуль не имеет отношения к электронной почте, однако он поможет нам отформатировать текст почтовых сообщений для их отображения в браузере. Первое, что должна сделать наша программа, это создание объекта Net::POP3. Соответствующему конструктору необходимо передать доменное имя почтового сервера $ServerName, значение флага отладки Debug и максимального времени ожидания Timeout: my $ServerName =
"YourMailServer"; Если объект был создан без ошибок, программа может продолжить свою работу. В противном случае она отображает в окне браузера сообщение об ошибке. На следующем этапе программа устанавливает соединение с почтовым сервером, передавая методу login идентификатор пользователя $UserName и пароль пользователя $Password: my $UserName = "YourName"; Если идентификатор и пароль указаны правильно, метод login возвращает количество сообщений, хранящихся в почтовом ящике пользователя, или неопределенное значение undef, если при указании идентификатора или пароля были допущены ошибки. Далее наша программа вызывает метод list, получая хеш всех номеров сообщений и их размеров: my $Messages; Обработка всех элементов хеша $Messages выполняется в цикле: foreach $msg_id (keys(%$Messages)) Здесь для каждого сообщения, имеющего текущий номер $msg_id, мы получаем его содержимое (вызывая метод get), а также уникальный идентификатор сообщения UIDL (при помощи метода uidl). Метод get возвращает строки сообщения в виде массива. Ссылку на этот массив, а также значение UIDL текущего сообщения мы передаем функции PrintMessage. Данная функция записывает эти строки в выходной поток, создавая таким способом динамический документ HTML (рис. 5-21).
Рис. 5-21. Просмотр полученных сообщений (первый вариант) Перед тем как завершить свою работу, наша программа закрывает соединение с почтовым сервером, вызывая для этого метод quit: $pop3->quit(); Рассмотрим теперь исходный текст функции PrintMessage, предназначенной для вывода содержимого сообщений. Получив управление, функция PrintMessage сохраняет значения своих параметров в переменных $msguidl и $lines: my ($msguidl, $lines) = @_; В первую из этих переменных записывается идентификатор сообщения, а во вторую — массив строк сообщения. Обработка массива строк выполняется в цикле: my ($from, $line, $subject, $full_msg,
@lines); Полный текст тела сообщения мы накапливаем построчно в переменной $full_msg, копируя в конец этой переменной текущую строку $line. Перед копированием эта строка преобразуется методом HTML::Entities::encode таким образом, что вместо специальных симвов HTML (таких, как <>&”) преобразуются в символьные объекты (< > & и "). Далее, мы ищем в строках сообщения поля From и Subject, записывая их содержимое в переменные $from и $subject. Перед завершением своей работы функция записывает в выходной поток содержимое этих двух переменных, переменной $msguidl идентификатора сообщения, а также переменной $full_msg с полным текстом сообщения, включающим в себя все заголовки: print
"<P><hr><b>From:</b>
".HTML::Entities::encode($from)."<br>"; При этом вызывается метод HTML::Entities::encode. Этот метод выполняет преобразование полей From и Subject, необходимое для записи их содержимого в документ HTML. Заметим, что в модуле Net::POP3 предусмотрены и другие методы. Прежде всего, заслуживает упоминание метод delete, с помощью которого можно удалить из почтового ящика сообщение с заданным номером. Обычно такая операция выполняется после прочтения сообщения. Полное описание методов модуля Net::POP3 Вы можете найти в документации на модуль, поставляющейся вместе с интерпретатором Perl, а также на Web-узле http://www.cpan.org. Использование модуля Mail::POP3Client Аналогичными возможностями работы с серверами POP3 обладает модуль Mail::POP3Client (по сравнению с только что описанным модулем Net::POP3). Об использовании модуля Mail::POP3Client мы расскажем на примере программы CGI, исходный текст которой представлен в листинге 5-16. Листинг 5-16 Вы найдете в файле chap5\www.cgi-test.at-home\cgi\read_mail1.pl на прилагаемом к книге компакт-диске. #!/usr/bin/perl -w Прежде всего, нам необходимо подключить модуль Mail::POP3Client с помощью оператора use: use Mail::POP3Client; Далее при конструировании объекта модуля Mail::POP3Client мы подключаемся к почтовому серверу. При этом мы передаем конструктору идентификатор пользователя USER, пароль PASSWORD и доменное имя почтового сервера HOST: my $pop = new Mail::POP3Client( После этого мы вызываем метод Alive, проверяя, было ли успешным установление соединения с почтовым сервером. В случае возникновения ошибки программа отображает сообщение и завершает свою работу. Выборка сообщений выполняется в цикле: for(my $i = 1; $i <=
$pop->Count(); $i++) Для определения количества сообщений, имеющихся в почтовом ящике пользователя, применяется метод Count. Далее для каждого сообщения наша программа получает заголовки, вызывая метод Head: foreach $line ($pop->Head($i)) Строки заголовков анализируются в цикле. При этом из них извлекаются значения полей From и Subject, которые затем сохраняются в переменных $from и $subject, соответственно. Уникальный идентификатор сообщений мы получаем методом Uidl, передавая ему номер сообщения: my $MsgUidl = $pop->Uidl($i); Перед тем, как приступить к извлечению тела сообщения, программа записывает в стандартный поток вывода значения полей From и Subject, а также идентификатор сообщения:
print "<b>From:
</b>".HTML::Entities::encode($from), "<br>"; Тело сообщения мы извлекаем методом Body и записываем в выходной поток построчно: foreach ( $pop->Body($i)) При этом применяется перекодирование при помощи функции HTML::Entities::encode. Перед завершением своей работы программа закрывает соединение с почтовым сервером, вызывая метод Close: $pop->Close(); Внешний вид выходного документа HTML с содержимым сообщений показан на рис. 5‑22. Рис. 5-22. Просмотр полученных сообщений (второй вариант) Как видите, с помощью методов Head и Body нам удалось выделить тело сообщения и заголовки «в чистом виде». В этом отношении модуль Mail::POP3Client удобнее по сравнению с модулем Net::POP3. Помимо методов, использованных в нашей программе, модуль Mail::POP3Client экспортирует и другие модули. Например, при помощи метода Delete можно удалить сообщение с заданным номером, а при помощи метода ListArray — получить массив размеров сообщений. Более подробную информацию о модуле Mail::POP3Client ищите в документации или на Web-узле http://www.cpan.org. |