Создание 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; } |
Далее мы рассмотрим CGI-программу такого же типа. Она не принимает никаких параметров, но зато выдает более полезную информацию - список и значения всех переменных окружения. Такой скрипт вам пригодится, когда вы будете отлаживать свои CGI-программы на различных веб-серверах. Дело в том, что переменные окружения различаются на различных веб-серверах. Так, например, для веб-сервера Apache, путь к каталогу веб-сайта хранится в переменной окружения DOCUMENT_ROOT. Для веб-сервера Microsoft Internet Information Server это значение хранится в переменной PATH_TRANSLATED. В операционной системе UNIX скрипт для вывода всех переменных выглядит следующим образом.
#!/bin/sh echo "content-type: text/plain\n\n" echo env |
Броузер будет воспринимать его, как обычный текст и выводить в точности как есть. Здесь не надо заменять спецсимволы типа < на их эквиваленты <. Скопируйте этот скрипт в директорию /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=gif, x-xbitmap, jpeg, 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 |
#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=gif, x-xbitmap, jpeg, 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); } |
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 или же самим разбирать эту строку параметров. О библиотеке и ее практическом использовании читайте в следующей параграфе.
|