Создание CGI-программ
Когда пользователь заполняет html-форму и нажимает кнопку submit, данные отправляются
веб-серверу. Веб-сервер, будь это Apache, IIS или какой-либо другой, запускает программу,
указанную в качестве значения атрибута action. В нашем случае это test.cgi.
Веб-сервер запускает test.cgi и передает ей параметры в виде
текстовой строки, следующего
содержания: name1=value1&name2=value2&....nameN=valueN, т.е. имя_параметра=значение.
Эта строка передается на стандартный поток
ввода (STDIN) или в качестве значения переменной окружения QUERY_STRING. Соответственно,
считать данную
строку в программе можно одним из двух способов:
unsigned int len;
len = atoi( getenv("CONTENT_LENGTH") );
query = (char*)malloc(len+1);
fread(query, 1, len, stdin);
query[len] = 0;
или
query=(char*)malloc(strlen(getenv("QUERY_STRING")));
strcpy(query,getenv("QUERY_STRING"));
|
В первом случае параметры передаются методом POST, а во втором методом GET.
В первом случае мы читаем
строку из STDIN. Длину строки мы узнаем из значения параметра окружения
CONTENT_LENGTH. Во втором она хранится в переменной окружения QUERY_STRING.
Значение переменной окружения можно получить, вызвав функцию getenv.
Метод, с помощью которого передается строка с параметрами CGI-программе, можно
определить следующим образом: strcmp(getenv("REQUEST_METHOD"),"POST").
Далее придется разбирать строку и получать необходимые значения параметров.
Для того чтобы не делать это каждый раз,
мы написали небольшую, но очень удобную библиотечку ITCGI для написания CGI-скриптов.
Эта библиотека позволяет вам полностью абстрагироваться от метода, которым
передаются параметры, от кодировки, от разбора строки. Вы просто вызываете
функцию GetParamByName, в которую передаете имя интересующего вас параметра
и адрес строки, куда сохранить значение. Библиотека также предоставляет вам ряд
функций для написания эффективных и защищенных от взлома CGI-скриптов.
В простейшем случае, когда ваша программа не нуждается в параметрах, вам и не
потребуется ни самому разбирать и раскодировать строку, ни использовать для
этого нашу библиотеку. Самой простой CGI-программой будет:
#include<stdio.h>
int main()
{
// выдаем обязательный заголовок
// это часть CGI-протокола
printf("Content-type: text/html\n\n");
printf("<html>");
printf("<body>");
printf("Hello, World!");
printf("</body>");
printf("</html>");
return 0;
}
|
Заголовок является обязательной частью. Он передается веб-серверу и определяет,
что следует за ним. В большинстве случаев у вас будет именно такой заголовок.
Он говорит веб-серверу, что дальше идет HTML-код. С другими типами заголовков
мы познакомимся чуть позже. В заголовке может быть несколько
строк. Конец заголовка обозначается двумя переходами на новую строку - \n\n.
Откомпилируйте эту программу, а исполняемый файл
положите в каталог /cgi-bin вашего веб-сайта. Переименуйте его в test.cgi.
К этому скрипту можно
обратится непосредственно через обозреватель, написав в командной строке URL,
например у меня это выглядит так http://itsoft.ru/cgi-bin/test.cgi
В результате, в вашем обозревателе вы увидите строку: "Hello, World!".
Далее мы рассмотрим CGI-программу такого же типа. Она не принимает никаких
параметров, но зато выдает более полезную информацию - список и значения всех
переменных окружения. Такой скрипт вам пригодится, когда вы будете
отлаживать свои CGI-программы на различных веб-серверах. Дело в том,
что переменные окружения различаются на различных веб-серверах. Так, например,
для веб-сервера Apache, путь к каталогу веб-сайта хранится в переменной окружения
DOCUMENT_ROOT. Для веб-сервера Microsoft Internet Information Server
это значение хранится в переменной PATH_TRANSLATED.
В операционной системе UNIX скрипт для вывода всех переменных выглядит
следующим образом.
#!/bin/sh
echo "content-type: text/plain\n\n"
echo
env
|
Обратите внимание на CGI-заголовок. Он отличается от того, который у нас был в предыдущем
примере. plain означает, что скрипт выдаст не HTML-код, а чистый текст. Броузер
будет воспринимать его, как обычный текст и выводить в точности как есть.
Здесь не надо заменять спецсимволы типа < на их эквиваленты <.
Скопируйте этот скрипт в директорию /cgi-bin с именем env. Установите атрибут
755 (rwxr-xr-x).
Вот результат выполнения такого скрипта на моем unix-сервере:
GATEWAY_INTERFACE=CGI/1.1
REMOTE_USER=itsoft
REMOTE_ADDR=192.168.34.134
QUERY_STRING=
REMOTE_PORT=1781
HTTP_USER_AGENT=Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)
DOCUMENT_ROOT=/usr/local/www/itsoft
AUTH_TYPE=Basic
SERVER_SIGNATURE=<ADDRESS>Apache/1.3.12
Server at itsoft.ru Port 80</ADDRESS>
HTTP_ACCEPT=image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
SCRIPT_FILENAME=/usr/local/www/itsoft/cgi-bin/web/env
HTTP_HOST=itsoft.ru
REQUEST_URI=/cgi-bin/web/env
SERVER_SOFTWARE=Apache/1.3.12 (Unix) PHP/3.0.17
HTTP_CONNECTION=Keep-Alive
HTTP_COOKIE=/cgi-bin/authenticate.cgi_LAST=956345778
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:
/usr/local/bin:/usr/X11R6/bin
HTTP_ACCEPT_LANGUAGE=ru
SERVER_PROTOCOL=HTTP/1.1
HTTP_ACCEPT_ENCODING=gzip, deflate
REQUEST_METHOD=GET
SERVER_ADMIN=igor@itsoft.ru
SERVER_ADDR=194.226.32.34
SERVER_PORT=80
SCRIPT_NAME=/cgi-bin/web/env
SERVER_NAME=itsoft.ru
|
Программа на языке Си для Windows и веб-сервера Internet Information Server
будет выглядеть следующим образом:
#include <stdio.h>
#include <stdlib.h>
void main()
{
char *text;
char str[1024];
int length;
FILE *in;
sprintf(str,"command.com /c set>%s\\temp\\env.dmp",getenv("PATH_TRANSLATED"));
system(str);
sprintf(str,"%s\\temp\\env.dmp",getenv("PATH_TRANSLATED"));
in = fopen(str, "rb");
if( !in )
{
printf("Content-type: text/plain\n\nCan't open file %s.", str);
return;
}
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
text = (char*)malloc(length+1);
fread(text, 1, length, in);
text[length] = 0;
fclose(in);
printf("Content-type: text/plain\n\n%s", text);
free(text);
}
|
Сначала выполняется команда command.com /c set>c:\www\mysite\temp\env.dmp.
Результатом выполнения такой команды и будет список всех переменных
окружения, который затем сохраняется в файл. Далее мы читаем этот файл
и выдаем его содержимое веб-серверу. Вы можете заметить, что
в данном случае, как и в прошлом примере, мы печатаем не html-код, а чистый текст
и поэтому у нас заголовок: Content-type: text/plain. Не забудьте также, что
этот cgi-скрипт будет работать только под Internet Information Server.
Для веб-сервера Apache следует заменить getenv("PATH_TRANSLATED") на
getenv("DOCUMENT_ROOT").
Ниже приведен результат действия этого скрипта на WindowsNT, вы можете видеть, какое
количество параметров доступно через переменные окружения. Такой cgi-скрипт
пригодится вам при настройке ваших скриптов на чужом сервере, где переменные
окружения могут отличаться от ваших локальных.
COMSPEC=C:\WINNT\SYSTEM32\COMMAND.COM
COMPUTERNAME=JUPITER
CONTENT_LENGTH=0
GATEWAY_INTERFACE=CGI/1.1
HTTP_ACCEPT=image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/vnd.ms-powerpoint, application/vnd.ms-excel, applic
HTTP_ACCEPT_LANGUAGE=ru
HTTP_CONNECTION=Keep-Alive
HTTP_HOST=www.oxygensoftware.com
HTTP_USER_AGENT=Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
HTTP_ACCEPT_ENCODING=gzip, deflate
HTTPS=off
INCLUDE=C:\Program Files\Mts\Include
INSTANCE_ID=1410
LIB=C:\Program Files\Mts\Lib
LOCAL_ADDR=168.144.29.178
NUMBER_OF_PROCESSORS=2
OS2LIBPATH=C:\WINNT\system32\os2\dll;
OS=Windows_NT
PATH=C:\WINNT\system32;C:\WINNT;C:\Program Files\Mts
PATH_TRANSLATED=e:\InetPub\Clients\oxygensoftware.com
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.JS;.VBE;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 5 Stepping 1, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=0501
PROMPT=$P$G
REMOTE_ADDR=194.226.32.34
REMOTE_HOST=194.226.32.34
REQUEST_METHOD=GET
SCRIPT_NAME=/cgi-bin/env.exe
SERVER_NAME=www.oxygensoftware.com
SERVER_PORT=80
SERVER_PORT_SECURE=0
SERVER_PROTOCOL=HTTP/1.1
SERVER_SOFTWARE=Microsoft-IIS/4.0
SYSTEMDRIVE=C:
SYSTEMROOT=C:\WINNT
TEMP=C:\temp
TMP=C:\temp
USERPROFILE=C:\WINNT\Profiles\Default User
Далее, прежде чем перейти к рассмотрению cgi-скриптов, которые принимают и
обрабатываю параметры формы, мы напишем простенькую программу, которая
выдает строку параметров html-формы. О том, как считываются параметры
формы, читайте выше, здесь я привожу исходный код программы и ее результат
для html-формы, описанной в четвертой главе.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char* query=NULL;
if( !strcmp(getenv("REQUEST_METHOD"),"POST") )
{
unsigned int len;
len = atoi( getenv("CONTENT_LENGTH") );
query = (char*)malloc(len+1);
fread(query, 1, len, stdin);
query[len] = 0;
}
else if( !strcmp(getenv("REQUEST_METHOD"),"GET") )
{
query=(char*)malloc(strlen(getenv("QUERY_STRING")));
strcpy(query,getenv("QUERY_STRING"));
}
else
printf("unknown REQUEST_METHOD\n");
printf("Content-type: text/plain\n\n%s", query);
free(query);
}
|
Скомпилируйте этот код. Он платформенно независимый, поэтому можете
скомпилировать как под Unix, так и под Windows.
Из четвертой главы возьмите HTML-форму, можете взять и любую другую.
В поле action пропишите путь к данной программе на вашем веб-сервере.
Результат после нажатия на кнопку "Опубликовать":
text=zero&text=zero&list=0&list2=0&textarea=%C7%E4%E5%F1%FC+%F2%E5%EA%F1%F2+%EF%EE+%F3%EC%EE%EB%F7%E0%ED%E8%FE
Это строка, которая содержит список всех параметров
Далее, вы можете воспользоваться нашей библиотекой ITCGI или же самим разбирать
эту строку параметров. О библиотеке и ее практическом использовании читайте
в следующей параграфе.
|