Обработка заполняемых форм HTML,
или как организовать "Книгу отзывов и предложений"
Форма на Web-странице

Важнейшим условием "долголетия" любого Web-сервера является постоянная "обратная связь" со своими читателями, то есть непрекращающаяся работа над откликами, сбор и обработка статистики посещаемости, и, наконец, проведение прямого анкетирования посетителей. Примером такого анкетирования может служить система сбора и хранения читательских отзывов. Проще ее всего реализовать с помощью заполняемых форм (form), входящих в состав языка разметки Web-страниц HTML. Допустим, среди посетителей Web-сервере нашей фирмы необходимо организовать сбор отзывов и "визитных карточек". Форма, соответствующая этой задаче, может выглядеть следующим образом:

e-mail:
наименование организации:
фио для контакта:
должность:
телефон/факс: код города номер
почтовый адрес:

ваш отзыв, замечания, предложения:

<html>
...
<form method="post" action="/cgi-bin/reply.pl">
e-mail: <input type=text name="e-mail" size=50><br>
наименование организации: <input type=text name="organization" size=50><br>
фио для контакта: <input type=text name="person-name" size=50><br>
должность: <input type=text name="person-position" size=50><br>
телефон/факс: код города <input type=text name="phonecode" size=7>
номер <input type=text name="phone" size=20><br>
почтовый адрес: <input type=text name="postaddr" size=50><p>
ваш отзыв, замечания, предложения:<br>
<textarea name="comments" rows=5 cols=35></textarea><p>
<input type="submit" value="после заполнения, нажмите эту кнопку">
</form>
...
</html>

На что здесь следует обратить внимание? Тэг form имеет два важных для нас атрибута - method и action. Первый из них описывает некоторые особенности передачи данных на сервер и будет рассмотрен нами позднее. Второй указывает, какой именно программе будет поручено обрабатывать переданные на сервер сведения. В данном примере это будет программа reply.pl.

(Следует иметь в виду, что путь, указанный в атрибуте action, чаще всего вовсе не соответствует реальному каталогу на Web-сервере, где нам следует разместить программу reply.pl. Например, в нашем примере это может быть каталог /usr/www/cgi-bin, а не просто /cgi-bin, как было заявлено в action)

В случае же, если Вы, к примеру, являетесь держателем бесплатной домашней страницы на таком сервере, как www.oocities.org или www.chat.ru, то скорее всего Вам не предоставят возможности самим разрабатывать и устанавливать программы, автоматически осуществляющие обработку заполняемых форм. В таком случае Вам не остается ничего другого, как по электронной почте принимать информацию, полученную через заполняемые формы, и обрабатывать ее затем вручную. При этом в action следует писать уже не имя программы, а команду пересылки по электронной почте, например:

<form method="post" action=mailto:yourname@yoursite.ru enctype="text/plain"> После этого, все данные, внесенные посетителем в нашу форму, будут присылаться в почтовый ящик yourname@yoursite.ru.

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

И наконец, заполнив поля представленной формы, посетитель должен каким-то образом инициировать передачу своих сведений на наш сервер. Сделать это он сможет с помощью клавиши, описанной тэгом <input type="submit" ...>. И после этого дальнейшая обработка информации будет осуществляться на сервере с помощью CGI-интерфейса.

К сожалению, в некоторых случаях Вам возможно все же придется вручную проверять правильность заполнения читателями форм и отбраковывать те из них, в которых окажутся не заполненными или неправильно заполненными отдельные поля. Например, бессмысленно держать в качестве визитной карточки сведения, в которых посетитель забыл указать свои инициалы (поле person-name). Желательно было бы проводить такую проверку сразу после заполнения формы, еще на компьютере самого читателя. Для этой цели Вам понадобится написать специальную программу на JavaScript и поместить ее на ту же web-страницу, где находится форма.

CGI-интерфейс

CGI-интерфейс (Common Gateway Interface) представляет собой некий набор общепринятых правил, по которым строится взаимодействие между Интернет и приложениями внутри самого Web-сервера. Рассмотрим, как работает этот интерфейс, применительно к нашей задаче сбора сведений, переданных из заполняемой формы. Как уже было сказано, обработку этих сведений выполняет программа reply.pl . Каким именно образом данные передаются программе, зависит от значения атрибута method. Согласно спецификации CGI, если в форме был указан метод GET, то данные будут переданы программе через переменную окружения QUERY_STRING. Если же был ипользован метод POST, то они будут переданы уже непосредственно на стандартный вход программы как некая строка текста. При этом в переменной окружения CONTENT_LENGTH будет зафиксирована длина этой строки. Выполнив обработку предоставленных данных, программа должна выдать на стандартное устройство вывода некую информацию, которая будет передана обратно в браузер читателя и представлена как новая Web-страница, автоматически сгенерированная как отклик на передачу заполненной формы.

Как из всего сказанного следует, что обработку заполняемых форм в принципе может выполнять программа, написаная на любом языке. Это может быть даже командный файл для оболочки sch. Однако в настоящее время для Web-серверов на базе OS Unix программы CGI-интерфейса чаще всего пишутся на языке Perl (TM O'Reilly & Associates, Inc.), как наиболее приспособленным для обработки текстовой информации. С одной стороны, этот язык является интерпретатором, то есть программа для него представляет собой ни что иное, как просто некий текстовый файл с набором команд, который всегда можно просмотреть и откорректировать в любом текстовом редакторе. С другой стороны, сама программа интерпретатора Perl (последняя версия 5.004) доступна для всех желающих в исходном кодах на языке Си (по адресу http://language.perl.com) и имеет реализации практически для всех существующих ныне платформ.

Хотя для программ на языке Perl разработано множество вспомогательных библиотек, специально предназначенных для создания CGI-интерфейса, в качестве примера мы рассмотрим работу лишь с простейшей библиотекой cgi-lib, разработанной Стевеном Бренна (Steven Brenner, http://cgi-lib.stanford.edu/cgi-lib).

Итак, рассмотрим текст программы reply.pl

#!/usr/local/bin/perl
# Первая строка в программе играет важную роль. Во-первых, она объявляет, что
# в данном файле содержится не просто текст, а некая программа (#!)
# Во-вторых, указывает с помощью какого интерпретатора его обрабатывать. 
# В данном примере это будет утилита perl из каталога /usr/local/bin

# Файл, куда будет храниться полученная информация
$log_file="/usr/www/log.txt";  
# Страница, которая будет передана на браузер после обработки формы
$reg_ok="/usr/www/docs/reg_ok.htm";

local($FILE,@message);

# Каталог, где размещаются служебные библиотеки Perl
push (@INC,"/usr/local/lib/perl5");
# Загрузка библиотеки cgi-bin
push(@INC,"/usr/www/cgi-bin");
require 'cgi-lib';

# Обязательные предварительные процедуры 
&ReadParse;
print &PrintHeader;

  @message=(); 
  push(@message,"********************\n");

# Хэш-таблица %in содержит названия всех полей в форме - 
# "e-mail", "person-name", "person-position" и т.д. - ($key),
# а также присанные туда читателем сведения - $in{$key}
# Зафиксировать всю эту информацию
  foreach $key (keys %in) {
    push(@message,"    ",$key," = ",$in{$key},"\n");
  }

# Зафиксировать также имя и IP-адрес компьютера, откуда поступила информация
  push(@message,"    HostName = $ENV{'REMOTE_HOST'}\n");
  push(@message,"    HostAddr = $ENV{'REMOTE_ADDR'}\n");

# Зафиксировать время поступления информации
  local($min,$hour,$mday,$mon,$year);
  (undef,$min,$hour,$mday,$mon,$year,undef,undef,undef)=localtime();
  $mon+=1;
  push(@message,"    Time = $hour:$min $mday/$mon/$year\n");
  push(@message,"*********************\n");

# Сохранить всю полученную информацию в файле, чье имя указано в переменной log_file
  open(FILE,">>$log_file") || die;
  print FILE @message;
  close(FILE);

# ...а также переслать в почтовый ящик менеджера по внешним связям
  open(FILE,'| mail yourname@yoursite.ru') || die;
  print FILE @message;
  print FILE "\n.\n";
  close(FILE);

# Обработка полученных данных завершена, загрузить в браузер читателя Web-страницу,
# указанную в переменной reg_ok
  open(FILE, $reg_ok) || die;
  print <FILE>;
  close(FILE);
Система сбора и регистрации читательских отзывов готова. Если после изучения Вашего сайта какой-либо читатель захочет оставить свой отзыв или "визитную карточку", то для этого ему нужно будет заполнить специально разработанный для этой цели бланк (форму). После автоматической обработки этого бланка на Вашем Web-сервере в файле /usr/www/log.txt появится запись примерно следующего вида:
********************
phonecode: 095
person-name: Усманов Радик Дамирович
organization: НИЦ ПЭУ
e-mail: radik@vpk.ru
comments: Проверка 
person-position: системотехник
phone: 112-25-04
********************
Кроме того, эта же информация будет передана по электронной почте Вашему менеджеру по внешним связям.

Сделаем еще несколько замечаний по поводу нашей программы.

  1. К сожалению, в программах на языке Perl (по крайней мере, в реализации для FreeBSD UNIX) явным образом использовать буквы русского алфавита невозможно. Если Вам все же необходимо, к примеру, поместить в переменную какое-либо слово или фразу на русском языке, то для этого в них придется каждую букву аккуратно заменить на соответствующий восьмеричный код. Например, строку

  2. $text1="*** Получен отзыв ***";
    следует заменить на
    $text1="*** \317\356\353\363\367\345\355 \356\362\347\373\342 ***";
    (Поэтому перед размещением на сервере приводенной ниже программы из нее следует изъять все комментарии на русском языке.)
  3. В некоторых случаях могут возникать проблемы, связанные с тем, что в почтовых сообщениях, циркулирующих в Интернет, и в Windows95 используются разные кодировки для русского алфавита. В связи с этим, возможно, Вам придется встраивать в программу обработки форм специальную функцию, предназначенную для перевода из одной кодировки в другую.
  4. Помимо сведений, представленных самим посетителем, мы включили в отчет еще и некоторые специальные данные, полученные сервером в процессе общения с компьютером читателя. Данные эти хранятся также в переменных окружения, некоторые из которых мы и приводим в качестве справки (для Web-сервера NSCA на платформе FreeBSD): REMOTE_ADDR - IP адрес компьютера, откуда была получена информация
    REMOTE_HOST - имя этого компьютера
    HTTP_USER_AGENT - информация о браузере, которым пользуется данный посетитель
P.S. Впоследствии была написана другая программа обработки формы, которая возвращает читателю форму обратно, если он не заполнил в ней все требуемые поля.
back