Еще причина ,отчасти перекликающаяся с первой, это то что когда говорят об интернет-программировании обычно излагают HTML со всеми тэгами, которые всем уже по ночам в кошмарах снятся ,ну а после чего начинают долго охать и ахать над прелестями нового аппаратно и платформо-независимого,переносимого,безопасного.....и.т.д. языка Java.Иногда в еще и могут тонким краешком затронуть JavaScript.Видя эту не побоюсь этого слова безнадежную ситуацию, я как доблестный CGI-программист решил хоть что-то поправить к лучшему.
Краткое лирическое отступление насчет CGI
Итак что такое CGI- скрипты и вообще подобные вещи. Начнем с того что ваш браузер (когда вы набрали URL) соединяется по протоколу HTTP с указаным сервером и просит у него нужный файл,примерно так:GET /~paaa/cgi-bin/guestbbok.cgi HTTP/1.0 -Вот это самое главное в запросе
Ну тут дальше идет посылаемая браузером информация о себе и о том что более подробно ему надо.(Например Accept: */*)
Ну и если запрошен простой файл например .html то если если такой файл есть, То сервер отошлет браузеру ответ:
HTTP/1.0 200 Okay
Content-Type: text/html
Далее после пустой строки(она нужна чтоб отделить заголовок от тела) идет информация из самого URL'а ...
Вот в принципе и весь WWW ....ходишь от ссылки к ссылке....
А что если Нужно внести в этот унылый процесс что-нибудь по настоящему интерактивное , динамическое,прекрасное и великолепное....? Чтож есть ответ и на этот вопрос. Просто что если в запрашиваемом URL указать спецыальную программу (CGI,программа Common Gateway Inteface - Общего Шлюзового Интерфейса) и то что эта прога выдаст то и отправить браузеру....Сервер запускает .cgi программу и она например обработав данные формы заносит вас куда-нибудь в свою базу данных,а вам сообщит что вы большой молодец :)
Ну надеюсь я вас заинтриговал......?
Итак ...приступим...
Краткие сведения о том что надо знать чтоб писать CGI скрипты: Ну вопервых надо знать что такое интернет и как он работает (а вы знаете? ;))) ) Ну и чуть-чуть умения прграмировать(это самое главное)
Давайте вместе писанем какой нибудь простенький скриптик а потом я вам расскажу где сдесь собака порылась....
Ну сначала в своем домашнем каталоге создайте директорию cgi-bin:
cd public_html
mkdir cgi-bin
chmod 0777 cgi-bin
Последняя строчка будет очень важна.
Возьмите редактор и наберите:
#!/usr/bin/perl
#first.cgi
print "Content-Type: text/html\n\n";
print "";
print "Hello you!!!
";
print "";
Сохраните его в директории cgi-bin под именем first.cgi .Ну как сохранили?
А теперь сделайте его исполняемым(ведь это программа):
chmod +x first.cgi
Ну вот,подходим к торжественному моменту.... наберите в строке браузера http://www.uic.nnov.ru/~твой_логин/cgi-bin/first.cgi
и посмотрите чо будет. Будет одно из двух ,либо скрипт заработает и вы увидите сгенерированую им страничку (поздравляю,в нашем полку прибыло!) либо Internal Server Error -тогда не расстраивайтесь,вы что-то сделали не так. Вам тогда пригодится пособие по ловле блох. Ну вопервых проверку синтаксиса можно осуществить следующим образом:
perl -с first.cgi
Perl вам сразу выдаст либо сообщения об ошибках(ну бывает,точку с запятой пропустили, скобочки или кавычки забыли закрыть...) это сразу по ходу дела поправимо.
Более грубая с логической точки зрения это пропустить вывод пустой строки, которая отделяет заголовок от тела:
print "Content-Type: text/html\n\n"; #Все Правильно
print "Content-Type: text/html\n"; #ОШИБКА!!!
Разберем скрипт:
Первая строка #!/usr/bin/perl Просто указывает где в системе расположен Perl. Вторая это просто коментарий -вы можете тыкать чо угодно после знака #
Затем идет print "Content-Type: text/html\n\n"; Это заголовок указывающий тип содержимого все что скрипт печатает в свой стандартный вывод STDOUT идет на обработку к серверу. Пустая строка отделяет заголовок от тела,которое в нашем случае представляет собой
Hello you!!!
Сервер обработает ответ скрипта и на базе него сформирует и пошлет браузеру ответ.(Сервер обычно не изменяет тела сообщения,он только дополняет заголовок нужными для протокола HTTP полями)
Ну вот азы уже освоены,все не так трудно и удручающе как могло показаться на первый раз
Вы теперь можете сами потренироваться в написании таких вот простеньких скриптов чтоб набить руку.
Переменные среды CGI
Предыдущий скрипт не содержал ничего особенно замечательного,так просто вываливал HTMLый текст который благополучно и отбражался на екране браузера.Но По настоящему мощь придает CGI возможность обработки параметров,которые переданы скрипту.например вы можете набрать
http://www.somehost.ru/somedir/cgi-bin/my_cgi.cgi?param=value
то есть вы хотите чтоб скрипт my_cgi.cgi обработал для вас параметер param со значением value (ну это например) или когда вы заполнили запрос в форме (в например yahoo или altavista).Ну это с точки зрения пользователя... А на сервере при запуске CGI-скрипта сервер формирует среду окружения в которой скрипт может найти всю доступную информацию о HTTP-соединении и о запросе.
Вот эти переменные:
REQUEST_METHOD
Это одно из самых главных поле используемое для определения метода запроса HTTP Протокол HTTP использует методы GET и POST для запроса к серверу.Они отличаются тем что при методе GET запрос является как-бы частью URL т.е. http://www..../myscript.cgi?request а при методе POST данные передаются в теле HTTP-запроса (при GET тело запроса пусто) и следовательно для CGI тоже есть различие при GET запрос идет в переменную QUERY_STRING а при POST подается на STDIN скрипта.QUERY_STRING
Пример:REQUEST_METHOD=GET
Это строка запроса при методе GET. Вам всем известно что запрос из формы кодируется браузером поскольку не все символы разрешены в URL некоторые имеют специальное назначение. Теперь о методе urlencode: неплохо бы чисто формально напомнить,что все пробелы заменяются в URL на знак '+', а все специальные и непечатные символы на последовательность %hh ,где hh-шестнадцатиричный код символа,разделитель полей формы знак '&',так что при обработке форм надо произвести декодирование.CONTENT_LENGTH
Пример:QUERY_STRING= name=quake+doomer&age=20&hobby=games
Длина в байтах тела запроса.При методе запроса POST необходимо считать со стандартного входа STDIN CONTENT_LENGTH байт,а потом производить их обработку.Обычно методом POST пользуются для передачи форм,содержащих потенциально большие области ввода текста TEXTAREA.При этом методе нет никаких ограничений,а при методе GET существуют ограничения на длину URL .CONTENT_TYPE
Пример:CONTENT_LENGTH=31
Тип тела запроса(для форм кодированых выше указаным образом он application/x-www-form-urlencoded)GATEWAY_INTERFACE
Версия протокола CGI.REMOTE_ADDR
Пример:GATEWAY_INTERFACE=CGI/1.1
IP-Адрес удаленого хоста,делающего данный запрос.REMOTE_HOST
Пример:REMOTE_ADDR=139.142.24.157
Если запрашивающий хост имеет доменное имя,то эта переменная содержит его, в противном случае -тот же самый IP-адресс что и REMOTE_ADDRSCRIPT_NAME
Пример:REMOTE_HOST=idsoftware.com
Имя скрипта,исполизованое в запросе.Для получения реального пути на сервере используйте SCRIPT_FILENAMESCRIPT_FILENAME
Пример:SCRIPT_NAME=/~paaa/guestbook.cgi
Имя файла скрипта на сервере.SERVER_NAME
Пример:SCRIPT_FILENAME=/home/p/paaa/public_html/cgi-bin/guestbook.cgi
Имя серера ,чаще всего доменное как www.microsoft.com ,но в редких случаях за неимением такового может быть IP-адресом как 157.151.74.254SERVER_PORT
Пример:SERVER_NAME=www.uic.nnov.ru
TCP-Порт сервера используюшийся для соединения .По умолчаниию HTTP-порт 80, хотя может быть в некоторых случаях другим.SERVER_PROTOCOL
Пример:SERVER_PORT=80
Версия протокола сервера.SERVER_SOFTWARE
Пример:SERVER_PROTOCOL=HTTP/1.1
Програмное обеспечение сервера.AUTH_TYPE, REMOTE_USER
Пример:Apache/1.0
Эти переменные определены в том случае,когда запрошеный ресурс требует аутентификации пользователя.Переменные заголовка HTTP-запроса.
За исключением тех строк из заголовка HTTP-запроса которые были включены в другие переменные,сервер приделывает строкам префикс HTTP_ и заменяет знаки '-' на '_':
HTTP_ACCEPT
Давая запрос на сервер браузер обычно расчитывает получить информацию определеного формата,и для этого он в заголовке запроса указывает поле Accept:,Отсюда скрипту поступает cписок тех MIME,которые браузер готов принять в качестве ответа от сервера.HTTP_USER_AGENT
Пример:HTTP_ACCEPT=text/html,text/plain,image/gif
Браузер обычно посылает на сервер и информацию о себе,чтоб базируясь на знании особеностей и недостатков конкретных браузеров CGI-скрипт мог выдать информацию с учетом этого. Например,разные браузеры могут поддерживать или не поддерживать какие-то HTMLые тэги.
Пример:HTTP_USER_AGENT=Mozila/2.01 Gold(Win95;I)
Ну,начнем применять на практике усвоеные уроки.
#!/usr/bin/perlТак как все ваши .cgi -файлы должны быть исполняемыми то чтоб облегчить себе жизнь заведите себе в директории cgi-bin командный файл mkcgi ,содержащий
#vars.cgi
sub urldecode{ #очень полезная функция декодирования
local($val)=@_; #запроса,будет почти в каждой вашей CGI-программе
$val=~s/\+/ /g;
$val=~s/%([0-9A-H]{2})/pack('C',hex($1))/ge;
return $val;
}
print "Content-Type: text/html\n\n";
print "CGI-Variables \n";
print "\n";
print "Enter here something:
\n";
print "Your request is:$ENV{'REQUEST_STRING'}
\n";
print "Decoded request is:urldecode($ENV{'REQUEST_STRING'})
\n";
print "
\n";
print "Variables:
\n";
print "REQUEST_METHOD=$ENV{'REQUEST_METHOD'}
\n";
print "QUERY_STRING=$ENV{'QUERY_STRING'}
\n";
print "CONTENT_LENGTH=$ENV{'CONTENT_LENGTH'}
\n";
print "CONTENT_TYPE=$ENV{'CONTENT_TYPE'}
\n";
print "GATEWAY_INTERFACE=$ENV{'GATEWAY_INTERFACE'}
\n";
print "REMOTE_ADDR=$ENV{'REMOTE_ADDR'}
\n";
print "REMOTE_HOST=$ENV{'REMOTE_HOST'}
\n";
print "SCRIPT_NAME=$ENV{'SCRIPT_NAME'}
\n";
print "SCRIPT_FILENAME=$ENV{'SCRIPT_FILENAME'}
\n";
print "SERVER_NAME=$ENV{'SERVER_NAME'}
\n";
print "SERVER_PORT=$ENV{'SERVER_PORT'}
\n";
print "SERVER_PROTOCOL=$ENV{'SERVER_PROTOCOL'}
\n";
print "SERVER_SOFTWARE=$ENV{'SERVER_SOFTWARE'}
\n";
print "HTTP_ACCEPT=$ENV{'HTTP_ACCEPT'}
\n";
print "HTTP_USER_AGENT=$ENV{'HTTP_USER_AGENT'}
\n";
print "
\n";
print "All enviroment:
\n";
foreach $env_var (keys %ENV){
print "$env_var=$ENV{$env_var}
\n";
}
print "\n";
chmod +x *.cgiи сделайте его в свою очередь исполняемым chmod +x mkcgi -он сильно упростит вам жизнь.
Ну а теперь запускайте скрипт......
Изучив информацию,выдаваемую данным скриптом вы сможете лучше ориентироваться в переменных окружения CGI.
Прекрасный язык Perl
Вы наверное обратили свое внимание что CGI скрипты пишутся обычно на языке Perl (Practical Extraction and Report Language)- очень удобном языке,впитавшем из других все лучшие черты.Может у вас возникнуть сомнение :Ну вот!Изучать новый язык программирования!? Спешу вас успокоить,изучение Perl не будет в тягость (я сужу по своему опыту!). Вы даже сами не заметите как выучите его.Если вы хоть когда-нибудь программировали скажем на C и использовали утилиту grep для поиска регулярных выражений в тексте,то вам будет еще легче.Мое изучение Perl началось с того что я скачал Perl под Windows и изучения той HTMLой документации которая к нему прилагалась хватило чтоб этот язык стал моим любимым....
Все в нем сделано для удобства программиста (в отличии например от Java;( )
Начнем с переменных,они в Perl бывают 3х типов скаларные,списковые(массивы) и хэши(ассоциативные массивы). Для указания компилятору(да и для немалого удобства программиста) перед именем скалярной переменной стоит знак '$' перед массивом '@',перед хешем '%'. т.е. например $scalar_var,@array_var,%hash_var Скалярные переменные могут быть как числовые так и строковые,но это не надо указывать Perl сам по контексту в зависимости от операций может привести одно к другому.
Например: "123"+"4" будет 127 (или "127") так как операция '+' действует над числами а вот если применить операцию конкатенации строк '.' то строковое "test" . 1 будет "test1"
Ну а вот операции над скалярными переменными:
| Операцыи | Описание | Пример |
| + - * / % | Арифметические | print 2*7+4/(8%3); print int(127/15); #целая часть |
| ** | Возведение в степень | print 2**16; |
| ++ -- | Инкремент-декремент | $i++; |
| & | ^ ~ << >> | Побитовые | $x=3;$y=4; print $x|$y; print $x&$y; |
| == != < > <= >= <=> | Числовые операции сравнения | if($x==9){print "Ok!";} |
| eq ne lt gt le ge cmp | стрковые операции сравнения | if($game eq 'doom'){print "You are doomer!\n";} |
| || && ! | Логические | if(($x==9)||($game eq 'doom')){print "hello you!\n";} |
| ?: | Условный оператор | $x=($game eq 'quake'?9:8); |
| , | Последовательное вычисление | $x=10,$y=20; |
| . | Конкатенация | $x='http://'.'www.uic.nnov.ru'; |
| x | Повторение | $x='1234'x5; #$x='12341234123412341234' |
| =~ | Сопоставление с образцом | if($url=~/http/){print "HTTP";} |
| !~ | То же но с отрицанием | if($url!~/http/){print "No HTTP";} |
| = += -= *= /= %= **= |= &= ^= ~= <<= >>= .= x= | Присваивание | $x+=$y; |
$x='qwerty';Списки: Спискочные переменные начинаются с символа '@' конструируются следующим образом
print 'my var is $x'; #выведет my var is $x
print "my var is $x"; #выведет my var is qwerty
@List1=(1,2,5,70);Также можно список использовать как lvalue:
@List2=(12,23,@List1); #12,23,1,2,5,70
@Rgb=($r,$g,$b);
@List=(1,2,3..8,15);Можно обращаться к нескольким,выбраным элементам массива(срезу массива):
($x,$y,$z)=@List; #$x=1,$y=2,$z=3
($x,$y,$z,@list2)=@List; #$x=1,$y=2,$z=3,@list2=(4,5,6,7,8,15);
($r,$g,$b)=@Rgb;
@list=(1..10);Обратится к скаларному значению -элементу массива можно $имя_массива[индекс], сдесь обратите внимание на знак '$'- мы ведь обращаемся к скаляру-элементу.
@list[2,3,5,9]=(100,200,300,400); #@list=(1,100,200,4,300,6,7,8,400,10)
@list[1,10]=@list[10,1];#меняет местами элементы
Теперь немного о хешах:
хеш это такой массив который состоит из пар ключ-значение, весь хеш обозначается %хеш ,к отдельным элементам доступ $хеш{скалярное выражение} конструируется хеш так:
$my_hash{1}="doom";
$my_hash{'quake'}="www.idsoftware.com";
$my_hash{1+2}=100;
Хеш может быть также сконструирован из массива с четным числом элементов где пары превращаются в ключ-значение %hash=(1,20,2,100);#аналогично $hash{1}=20;$hash{2}=100;
удаление из хеша -операция delete: delete $hash{1};
есть функции выдающие ключи и значения соответственно. %hash=(1,20,2,100,3,'doom');Операторы:
@k=keys %hash; #@k=(1,2,3);
@v=values %hash;#@v=(20,100,'doom');
Набор операторов в Perl Очень широк,многие из них прямые аналоги имеющихся в других языках,например if,for,while;но есть и значительные улучшения имеюшихся и конечно новые...
Тот же самый оператор if имеет две формы (как когда удобнее):
if(условие)оператор;В пару к оператору if имеется оператор unless : означающий if с отрицанием:
оператор if условие;
unless(($method eq 'GET')||($method eq 'POST')){print "Unsupported method";}
print "Ok" unless $x < $y;
Также в пару while существует untilсинтаксис оператора for полностью аналогичен C:
for($i=0;$i<10;$i++){
print $i;
}
новшеством(и приятным) является foreach позволяющий пройтись по всем элементам массива,присваивая по очереди его элементы какой-то переменной, его синтаксис такой:foreach $переменная (@массив){
блок операторов;
}
или
foreach (@массив){
операторы;
}
Последний пример особенно важен для упрощения вашего тяжкого труда програмиста и демонтстрирует интересную особенность Perl-переменную по умолчанию $_: в оргомном количестве операторов и функций при опускании аргумента она подразумевается по умолчанию. Она также по умолчанию сопоставляется с регулярным выражением: следующий примеркак видите затраты труда значительно сокращаются,благодаря этому маленькому трюку. Регулярные выражения.
@Data=;
foreach(@Data){
chomp;
print if /^From:/;
}
аналогичен такому:
@Data=;
foreach $_ (@Data){
chomp($_);
print $_ if $_ =~ /^From:/;
регулярное выражение записывается между двух слэшей /рег_выр/
if(/abc/){
print '$_ содержит abc\n';
}
это самый простой пример применения регулярного выражения а теперь посложнее вот тут в табличке (из того что я помню наизусть): | Символ | Значение | Пример применения |
| . | Соответствует любому символу | print if /ab.c/; |
| [мн-во симв] | Соответствует любому символу из данного мн-ва | /[abc]d/;#соответствует ad,bd,cd |
| [^мн-во] | Отрицание мн-ва символов | /[^xyz]/;# |
| (....) | Группировка элементов(и также запоминание в переменных $1 $2 $3 ...) | /(xyz)*/ /([abc].[^xy]qwerty)/ |
| (..|..|..) | Одна из альтернатив | |
| * | повторение образца 0 или более раз | /.*/;#соответствует всему |
| ? | Повторение 0 или 1 раз | /(http:\/\/)?.*\.cgi/ |
| + | Повторение 1 или более раз | |
| {n,m} | повторение от n до m раз | |
| {n} | повторение точно n раз | |
| {n,} | повторение n и более раз | |
| Спец символы: | ||
| \t \r \n ... | Управляющие символы:табуляции,возврат каретки,перевод строки..... | |
| \d | Соответствует цифре,Аналог [0-9] | |
| \D | Соответствует нецифровому симсволу,аналог[^0-9] | |
| \w | Соответствует букве | |
| \W | Соответствует небуквеному символу | |
| \s | Соответствует пробельным символам(пробелы,табуляции,новые строки..) | |
| \S | Соответствует непробельному символу | |
| \b | Соответствует границе слова | $test1="this is test"; $test2="wise"; if($test1=~/\bis\b/){print "1";}#соответствует if($test2=~/\bis\b/){print "2";}#нет |
| \B | Соответствует не границе слова | /\Bis\B/ соответсвует 'wise' но не 'is' |
print "Are you sure?:";
$answer=;
if($answer=~/Y/i){
#че-нибудь сделаем...
}
Полезные функции.
В Perl очень много различных функций ,как говорится на все случаи жизни,все о них я конечно не опишу,но обо многих. Начну с тех,которые больше относятся к операторам. Операция замены s/рег.выражение/строка/ игнорировать регистр - опция i глобальная(по всей строке) замена -опция g; Пример:
$x="This is test";Очень полезная опция у s/// e -она означает что вторая строка не строка а выражение, результат которого и будет подставлен. Например,у вас есть файл в котором все записи о возрасте через год надо менять
$x=~s/ /_/g;
print $x; #This_is_test
open OLD,"oldfile.txt" || die "Cannot open oldfile.txt $!\n";или более показательным примером послужит функция urldecode,которая будет встречатся в каждой вашей программе,обрабатывающей формы:
open NEW,">newfile.txt" || die "Cannot open newfile.txt $!\n";
foreach(){
s/(\d+)(\s+год)/($1+1).$2/gie;
s/(\d+)(\s+лет)/($1+1).$2/gie;
print NEW $_;
}
close NEW;
close OLD;
sub urldecode{
local($val)=@_;
$val=~s/\+/ /g;
$val=~s/%([0-9A-H]{2})/pack('C',hex($1))/ge;
return $val;
}
Также важным удобством в Perl являются операции для работы с файлами для выполнения схожих функций в других языках приходиться проделывать огромную массу работы. Аргументами могут быть как Файловые переменные,так и строки,представляющие имя файла. | Операция | Описание | Пример использоввания |
| -r | Доступен для чтения | unless(-r "myfile"){print "Cannot read myfile\n";} |
| -w | Доступен для записи | |
| -x | Для исполнения | |
| -o | Принадлежит пользователю | if(-o "index.htm"){chmod 0777,"index.htm";} |
| -R | Доступен для чтения реальным пользователем,а не только "эффективным". Имеет значения для set-uid -скриптов | if(-r FILE){unless(-R FILE){die "Its not allowed to read this\n";}} |
| -W | Доступен для записи реальным пользователем | |
| -X | Доступен для исполнения реальным пользователем | |
| -O | Принадлежит реальному пользователю | |
| -e | Файл или каталог Существует | unless(-e $htmlfile){ open HTML,">$htmlfile"; print HTMLFILE ""; close HTMLFILE; } |
| -z | Существует,но имеет нулевую длину | if(-z 'tmpfile'){unlink 'tmpfile';} |
| -s | Размер файла в байтах | system "rar m -m5 archive.rar $myfile" if -s $myfile > 1000; |
| -f | Файл существует и является простым файлом | |
| -d | Файл существует и является каталогом | if(-d 'public_html'){chdir 'public_html';} |
| -l | Символической ссылкой | |
| -p | Каналом FIFO | |
| -u | Имеет бит установки пользователя | |
| -g | Имеет бит установки группы | |
| -k | Установлен sticky-бит | |
| -t | Является терминальным устройством | |
| -M | Время с последнего изменения (в днях) | while(defiled($file=glob('*'))){ if(-M $file >= 7.0){ unlink($file);#удаляем слишком старые файлы } } |
| -A | Время последнего доступа(в днях) | if(-A "$ENV{'HOME'}/public_html/index.html" < -A "$ENV{'HOME'}/.last"){print "Кто-то ходил на твою домашнюю страничку пока тебя не было!!!\n";} |
| -C | Время последнего обновления файлового индекса(в днях) | |
функция open открывает файл
open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,"имя файла"; #открыть файл для чтенияЧто какается открытия файлов,то вам как програмистам все очевидно, но с коммандами тоже все здорово,что пояснит хороший пример(из практики):
open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,">имя файла"; #для записи
open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,">>имя файла";#для записи в конец
open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,"+<имя файла";#для чтения и записи
open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,"|комманда"; #направить информацию на вход программы
open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,"комманда|"; #считать информацию с выхода программы
open ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,"|комманда|"; #и то и другое вместе
open MAIL,"|mail paaa@uic.nnov.ru";#Пошлем информацию по почтекогда вы открыли файл вы можете считать из него строку в скалярную переменную Вот так:$str=
print MAIL "Hello\n";
print MAIL "...\n";
print MAIL "...\n";
close MAIL;
избавиться от символа новой строки на конце поможет функция chomp, ведь этот символ может помешаться например в имени файла или при выводе на экран
print "Введите имя файла:";Если также подставить списочную переменную,то получим список строк файла от текущей строки и до конца
$fname=;
chomp($fname);
open F,$fname || die "Cannot open $fname $!\n";
.....
print "Что искать:";бинарный файл можно читать и писать функциями sysread и syswrite:
$search=;
chomp($search);
@L=;
foreach(@L){
print if /$search/;
}
а можно и так:
print "Что искать:";
$search=;
chomp($search);
foreach(){
print if /$search/;
}
sysread ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,$скалярная_перемменая,сколько_байт
syswrite ФАЙЛОВАЯ_ПЕРЕМЕННАЯ,$скалярная_перемменая,сколько_байт
функции split и join: @Список=split /рег.выр/,$скаляр;
$скаляр=join строка,@Список;
#Разбить строку слов,разделенных пробелами в список вы можетеВстроеные функции Perl можно вызывать со скобками или без (как вам удобно), скобки программисты указывают или для красоты,или чаще,что устранить возможную неоднозначность в выраженнии:
@WordList=split / /,$String;
#После обработки снова обьединить
$String=join ' ',@WordList;
printf "x=%d",$x;Надеюсь что я вас позабавил примерами функций ;).
printf ("x=%d",$x);#аналогично
Примеры применения Perl для различных нужд...
Следующая программа переводит текстовый файл в формат HTML (вспомните сколько хлопот вам доставит отлов во всем файле '<', '>' и '&' чтоб заменить их на &tl; , > и & а как неплохо чтоб автоматически все http://www.... превратились в http://www....)
#!/usr/bin/perlБолее подробную информацию о Perl вы можете получить по адресам:
#txt2html
die "Usage: txt2html Infile OutFile\n" unless(@ARGV);
open IN,"$ARGV[0]" || die "Cannot open $ARGV[0] $! \n";
open OUT,">$ARGV[1]" || die "Cannot open $ARGV[1] $! \n";
while(){
s/&/&/g;
s/</g;
s/>/>/g;
s/\n/
\n/g;
s/(http:\/\/\S+)/$1<\/A>/g;
print OUT $_;
}
close IN;
close OUT;
http://www.perl.com
http://www.metronet.com/0/perlinfo/perl5/manual/perl.html
http://www.ActiveWare.com/
Заголовки запросов и ответов
Даже если вы и знаете кое-что о HTTP все равно не лишне будет вспомнить о том как это все работает тем более на эту информацию придется ориентироваться при написании CGI скриптов.
Этапы соедирения.
Первый этап это когда HTTP -клиент(браузер) соединяется с сервером.для этого он использует протокол TCP/IP соединение происходит к известному клиенту TCP-порту (80 -номер порта HTTP) (другие сервисы сидят на других портах ,например FTP и SMTP на 21 и 25)
Вторым этапом идет запрос клиента:клиент передает заголовок запроса и возможно(в зависимости от метода) тело сообщения запроса.В заголовке обязательно указывается метод ,URI,и версия HTTP,и может быть еще несколько необязательных полей
Третий этап -ответ сервера,который опять таки состоит из заголовка,в котором сервер указывает версию HTTP и код статуса, который может говорить о успешном или неуспешном результате и его причинах.Далее идет тело ответа.
Четвертым этапом происходит разрыв TCP/IP соединения.
HTTP -запрос.
Запрос состоит из Строки запроса(она обязательна) и остальных полей. Синтаксис строки :МЕТОД
где
Методы HTTP.
GET
Самый часто применяемый метод,в протоколе HTTP/0.9 был единственным методом,и применяется для извлечения информации по заданому URI Может быть условным если в заголовке указано поле If-Modified-Since:
HEAD
Почти идентичен GET но отличается тем что сервер не возвращает тело обьекта а только его заголовок (метаинформацию) программы могут применять его для проверки гиперссылок на правильность,доступность и изменения.
POST
передает данные для обработки их программой ,указаной в URIсдесь обязательно указывается поле Content-Length:
Сушествуют и другие ,реже применяемые методы,например PUT -для сохранения передавемых данных в указаном URI и DELETE для удаления ресурса.
Поля заголовка запроса.
После строки запроса идут поля заголовка запроса. Поля общего(general-header) заголовка (он общий как для запросов так и для ответов):
Date:
Указывает дату запроса,например:
Date: Sun, 20 Nov 1994 08:12:31 GMT
MIME-version:
Указывает версию MIME (по умолчанию 1.0)
MIME-version: 1.0
Pragma:
Содержит указания для таких промежуточных агентов как прокси и шлюзы,
Pragma: no-cache
Поля относящиеся к запросу(Request-Header):
Authorization:
Содержит информацию аутентификации
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
From:
Браузер может посылать адрес пользователя серверу
From: quake@doom.ru
If-Modified-Since:
используется при методе GET ресурс возвращается ,если он был изменен с указаного момента, может использоваться при кешировании.
If-Modified-Since:Mon 15 Jul 1997 00:15:24 GMT
Referer:
Содержит URL предшествующего ресурса.
Referer: http://www.uic.nnov.ru/~paaa/index.html
User-Agent:
Програмное обеспечение клиента.
User-Agent: Mozilla/3.0
Заголовок информации сообщения (Entity-Header) применяется как в запросах так и в ответах (при этом некоторые поля только в ответах):
Allow: (в ответе сервера)
Список методов,поддерживаемых ресурсом.
Allow: GET, HEAD
Content-Encoding:
идентифицирует метод кодировки,которым был закодирован ресурс
Content-Encoding: x-gzip
Content-Length:
Длина тела сообщения
Content-Length: 102
Content-Type:
Содержит тип ресурса(MIME),для текстовых еще и кодировку символов(необязательно)
Content-Type: text/html; charset=windows-1251
Expires: (в ответе сервера)
Дата окончания действия ресурса,применяется в кешировании для запрета кеширования устаревших ресурсов (в ответе)
Expires: Tue, 24 Sep 1998 23:00:15 GMT
Last-Modified: (в ответе сервера)
Время последнего обновления ресурса
Last-Modified: Tue, 23 sep 1998 13:48:40 GMT
Другие поля:
Поля Accept: указывают серверу выдавать только указаные форматы данных,которые клиент может распознать.
Accept: text/html
Accept: text/plain
Accept: image/gif
Примеры запросов:
Простейший запрос:Ответ HTTP-сервера.
GET /index.html HTTP/1.0
Посложнее:
GET /somedir/somedoc.html HTTP/1.0
User-Agent: Mozilla/2.0
Accept: text/html
Accept: text/plain
Accept: image/gif
Передача данных CGI- скрипту через метод GET
GET /~paaa/cgi-bin/test.cgi?name=Dmitry&organization=%D3%ED%E8%E2%E5%F0%F1%E8%F2%E5%F2+%CD%E8%E6%ED%E5%E3%EE+%CD%EE%E2%E3%EE%F0%EE%E4%E0&Name=&email=&comment= HTTP/1.0
User-Agent: Mozila/2.0
Accept: text/html
Accept: image/gif
Используя метод POST данные передаются в теле сообщения запроса:
GET /~paaa/cgi-bin/test.cgi HTTP/1.0
User-Agent: Mozila/2.0
Accept: text/html
Accept: image/gif
Content-Type: application/x-www-form-urlencoded
Content-Length: 131
name=Lesha
&organization=%D3%ED%E8%E2%E5%F0%F1%E8%F2%E5%F2+%CD%E8%E6%ED%E5%E3%EE+%CD%EE%E2%E3%EE%F0%EE%E4%E0&Name=
&email=
&comment=
Ответ идет от сервера.Состоит он из строки состояния и затем поля ответа Общий заголовок(General-Header) и заголовок тела сообщения (Entity-Header),которые уже описаны при обсуждении запроса. и еще идет заголовок ответа(Response-Header).
Строка состояния имеет следующий формат:
HTTP/version
где HTTP/version версия,Status-Code -3х значный код,и Status-Phrase текстовая фраза, поясняющая код ,пример: HTTP/1.0 200 Ok
,200 -код означающий успешную обработку запроса,что и поясняет "Ok" Заголовок ответа состоит из полей:
Location:
Содержит URI ресурса,может быть использован для переключения клиента в другое место, если например ресурс был перемещен в другое место или на другой сервер.
Location: http://www.uic.nnov.ru/newlocation/index.html
Server:
Информация о програмном обеспечении сервера
Server: Apache/1.1
WWW-Autenticate:
Параметры аутентификации.
WWW-Autenticate: Basic realm="doomsday"
Коды ответов HTTP.
| Код статуса | Значение |
| 200 | OK |
| 201 | Успешная команда POST |
| 202 | Запрос принят |
| 203 | Запрос GET или HEAD выполнен |
| 204 | Запрос выполнен но нет содержимого |
| 300 | Ресурс обнаружен в нескольких местах |
| 301 | Ресурс удален навсегда |
| 302 | Ресурс отсутствует временно |
| 304 | Ресурс был изменен |
| 400 | Плохой запрос от клиента |
| 401 | Неавторизованый запрос |
| 402 | Необходима оплата за ресурс |
| 403 | Доступ Запрещен |
| 404 | Ресурс не найден |
| 405 | Метод не применим для данного ресурса |
| 406 | Недопустимый тип ресурса |
| 410 | Ресурс Недоступен |
| 500 | Внутренняя ошибка сервера (это по вашу душу,юные CGI-программисты ;( ) |
| 501 | Метод не выполнен |
| 502 | Неисправный шлюз либо перегруз сервера |
| 503 | Сервер недоступен/тайм-аут шлюза |
| 504 | Вторичный шлюз/тай-аут сервера |
Несколько примеров:
HTTP/1.0 200 OkCGI-заголовок.
Date: Wed, 25 Sep 1998 23:00:00 GMT
Server: Apache/1.1
MIME-version: 1.0
Last-Modified: Mon 15 Nov 1996 15:20:12 GMT
Content-Type: text/html
Content-Length: 2000Hello
......
А вот такое сервер выдаст в неудачном случае:
HTTP/1.0 404 Not Found
В том случае когда запрашиваемый URI есть CGI-скрипт сервер базируясь на данных запроса создает среду переменных CGI и передает управление скрипту скрипт должен выдать CGI-заголовок,после которого и идет тело ответа,сгенерированое скриптом.
Заголовок (CGI-Header) состоит из полей:
Content-Type:
Должно обязательно присутствовать,если есть тело.
Content-Type: text/html
Location:
Содержит URL ресурса на который скрипт перенаправляет запрос.Как правило,если присутствует это поле больше ничего не указывается.
Location: http://www.idsoftware.com/index.html
Status:
Позволяет CGI скрипту вернуть статус обработки,если это поле не задано,то сервер подразумевает
Status: 404 Not found
На базе этой информации сервер и формирует окончательный заголовок,который и передается клиенту.
Примеры:
Обычно такое выдает скрипт: Content-Type: text/html ....... Но иногда такое(когда он служит для перенаправления): Location: http://www.mustdie.ru/ А вот пример возврата статуса: Content-Type: image/gif Status: 190 Its seems great like a playing doom! WOW! GIF89a........nph-скрипты.
Иногда возникает необходимость чтобы CGI -скрипт сам отвечал напрямую клиенту, минуя разбор заголовка.Это во-первых уменьшает нагрузку на сервер,и во вторых, что самое главное такой прямой ответ клиенту позволяет скрипту полностью контролировать транзакцию.Для этого существуют nph-скрипты(Not Parse Header) ,имя скрипта должно начинаться с префикса "nph-" ,Например "nph-animate.cgi" .Такие скрипты сами формируют HTTP-ответ клиенту,что полезно при анимации:
#!/usr/bin/perl #nph-animate.cgi $times = 20; #Заготовте несколько небольних gif-файлов для этой программы @files = qw(img0.gif img1.gif img2.gif img3.gif); select (STDOUT); $|=1; #autoflush mode on #Generate header print "HTTP/1.0 200 Okay\n"; print "Content-Type: multipart/x-mixed-replace;boundary=myboundary\n\n"; print "--myboundary\n"; for ($num=1;$num<=$times;$num++) { foreach $file (@files) { print "Content-Type: image/gif\n\n"; open(PIC,"$file"); print ; close(PIC); print "\n--myboundary\n"; sleep(3); } } print "\n--myboundary--\n"; Этот пример вам выдаст анимацию ,составленую из нескольких .gif -файлов.Если же вы получили вместо анимации сообщение об ошибках,то вам следует,может быть перейти к следующей главе, которая поведает вам о правах доступа- того,без чего Unix не был бы Unixом. Права Доступа
Я бы ни за что не написал этот раздел,если бы он не был так важен.Сидя в пределах своей домашней директории и занимаясь только тем,что качаете с Инета всякую херню,вы возможно и не задавались некоторыми вопросами....а зря.......... Ведь немного надо,чтоб попортить нервы начинающему CGI -програмисту.
Одна из таких вещей это права доступа......
Начнем с того ,что в системе Unix каждый пользователь имеет свой идентификатор- число,уникально идентифицирующее его в этой системе.(Мой логин paaa а ему соответсвует число 1818).Это число внутреннее для операционной системы,для пользования оно представлено как логин,который и соответствует пользователю.
Только не надо думать о пользователе,как о конкретном человеке сидящим за клавиатурой, пользователем может быть и какой-нибудь процесс.Важно отметить что пользователь-это определенная область прав доступа,которая ему соответствует.(Вы например не можете удалить файлы из каталога другого пользователя). Это и дает возможность стабильной работы всей системы.
Итак есть идентификатор пользователя.Также имеется идентификатор группы.
Группа служит для выделения пользователей по группам. Например у пользователей группы users (Обычные пользователи) не такие права как у группы wheels (административная группа).
Каждый процесс который вами запущен(Будь то Netscape,терминал,или текстовый редактор)получают ваши идентификаторы пользователя и группы. таким образом исполняются от вашего имени.
Теперь рассмотрим повнимательней файловую систему.В Unix с файлом связано много характеристик. Во-первых в системе нет "ничьих" файлов ,все файлы имеют владельца-пользователя и владельца-группу. Любой файл который вы создаете автоматически получает ваш идентификатор.По этому система очень легко отслеживает, чьи это файлы и каталоги.
Следующее новшество по сравнению с DOS это права доступа к файлу.Их может сменить только тот пользователь которому принадлежит файл,или супервизор.(Это в отличии от DOS где каждая дрянь типа вируса может снять атрибут readonly)
Права доступа задаются обычно числом в восьмеричном коде и разбиты на 3 части по 3 бита: Каждая часть задает права доступа для конкретной группы:
| 1я -права доступа для пользователя,которому принадлежит файл |
| 2я -для группы которой принадлежит файл |
| 3я -для всех остальных |
| Бит | Описание |
| 8 | Право на чтение для пользователя |
| 7 | Право на запись для пользователя |
| 6 | Право на исполнение для пользователя |
| 5 | Право на чтение для группы |
| 4 | Право на запись для группы |
| 3 | Право на исполнение для группы |
| 2 | Право на чтение для всех остальных |
| 1 | Право на запись для всех остальных |
| 0 | Право на исполнение для всех остальных |
chmod [u|g|o]{+|-}{r|w|x} file
chmod number file
,где u-user,g-group,o-other,r-read,w-write,x-execute;--удалить,+-установить
Примеры:
chmod +r file.txt #разрешает всем право на чтения файла
chmod u+w file.txt #устанавливает для владельца файла право на запись в него
chmod +x gbook.cgi #право на исполнение для всех,как для ползователя,группы,и для других
chmod 0777 cgi-bin #Разрешает самые широкие права доступа для cgi-bin
Приоткрытии файла программой,операционная система сравнивает идентификатор пользователя с идентификатором пользователя владельца файла, если они равны,то действуют права пользователя,если не равны то сравниваются идентификаторы группы,если и они не равны,то действуют права доступа для остальных остальных.В том случае если у процесса нет достаточных прав,система возвращает ошибку. Следует заметить ,что для супервизора root права доступа не проверяются.
Можно выполнить скрипт,только если есть права на его исполнение. Вот почему следует давать chmod +x *.cgi иначе ваши скрипты станут просто недоступными. Но и это еще не все.....
Ваш скрипт может обращатся к вашим файлам (например ведет базу данных гостевой книги). Все выглядит нормально,но только ничего не работает,файл в который вы намеревались писать,
не открывается,знакомая проблема ;(( ?.Так вот чтобы вы не мучались в догадках Ваш скрипт не может получить доступ к вашим файлам,потому что он выполняется не вами (не с вашим идентификатором), а от имени nobody (непривелигированый пользователь).Это мера предосторожности направлена на то, чтоб скрипты ,взбесившись из-за неправильно переданых параметров(или вообще от глюков) не могли ничего повредить ценного и важного на сервере.
Поэтому к тем файлам,к которым скрипт по смыслу должен обращатся нужно присвоить самые широкие права доступа 0777
Например в случае гостевой книги chmod 0777 guestbook.dat
Если также важно чтоб скрипты могли заводить новые файлы в cgi-bin то надо дать также права на это chmod 0777 cgi-bin
Если вы видите что ваш скрипт не может обратится к какому-то файлу,то это в 99% случаев из-за вашей забывчивости.!!!
На самый крайний случай воспользуйтесь setuid-скриптами (к этому делу ,если вы на это решились,отнеситесь ОЧЕНЬ серьезно,так как целые тома по безопасности в Unix посвящены именно setuid-скриптам). Хочу сразу предупредить ,сам я таких не писал,да и вам не особенно советую.Но для общего как говорится развития,имейте в виду следующую информацыю.
Кроме указания прав доступа,существуют специальные биты у файла.Это биты установки пользователя и группы. Когда процесс выполняется(простой процесс) то его реальный и эффективный идентификаторы пользователей совпадают,идентификаторы групп тоже. На самом деле значение имеют как раз эффективные значения пользователя и группы,они учавствуют в сравнении прав доступа. Нельзя ли их как-то изменить,когда уж совсем нужда заставит? Можно! .На этот вопрос дают ответ программы с установленым битом пользователя.Когда система запускает такую программу,она присваивает новому процессу не идентификатор того пользователя,что запустил ее, а идентификатор пользователя-владельца исполняемого файла.
Самый классический пример setuid-программ это программа passwd ,предназначеная для смены пароля пользователя. Такие данные как пароль и прочие характеристики пользователей хранятся в специальном файле,который имеет огромное значение при входе в систему. Так как это системный файл,то открыть к нему доступ на запись всем-значит подвергнуть ВСЮ систему риску,ведь любое неправильное изменение его повлечет катастрофические последствия(в конце концов бывает просто хулиганство). Поэтому доступ к этому файлу закрыт для всех пользователей.А что если надо сменить пароль? Запускаем программу passwd ,если глянуть на ее аттрибуты ,то видно что она принадлежит root -супервизору, и еще имеет установленый бит setuid. Так корректно обходится эта проблема.
Если вы все-же решили попытаться ,то знайте ,что сделать программу setuid можно
коммандой : chmod +s myprogramm
И как всгда Примерчик напоследок:
Эта программа выдает содержимое вашей директории public_html в том случае,если она доступна для чтения,и для каждого файла указывает ,можно ли его читать,писать и исполнять. Попробуйте ее сделать setuid и посмотрите как изменится результат.
#!/usr/bin/perl #listmydir.cgi print "Content-Type: text/html\n\n"; if(!(-r '..')){ print ".. is not allowed for reading ;)))))\n"; } else{ @list=glob('../*'); foreach(@list){ print "$_"; print " readable" if -r; print " writable" if -w; print " executable" if -x; print "
\n"; } } Генерация ответа
Большую часть того что нужно знать о генерации ответа,я сказал в разделе Заголовки запросов и ответов.Нет,не угадали! Я не буду сдесь говорить о всяком дизайне того что вы выдаете.Этому вы успели напрактиковатся на HTML -страничках.
Я поговорю о MIME (Multipurpose Internet Mail Extension).И о разных браузерах.
Стандарт MIME появился в электронной почте (e-mail) потому что остро стала проблемма пересылки по e-mail различных данных в различных форматах.Так как HTTP тоже работает с различными типами данных то поэтому тоже использует MIME для своих нужд. Типы MIME состоят из Типа и подтипа (например text/plain,где text-указывает на наличие текстового содержимого,а plain-уточняет его как простой текст) приведеный ниже список (он далеко не полн,типов MIME огромное количество) описывает некоторые часто встречающиеся типы.: text/html text/plain text/richtext image/gif image/jpeg image/tiff audio/basic audio/32kadpcm audio/ video/mpeg video/quicktime multipart/mixed multipart/alternate multipart/ application/octet-stream application/msword application/postscript message/digest
Информация о MIME больше возможно пригодится вам в том случае если вы собираетесь работать из ваших скриптов с электронной почтой,но и для WWW она не повредит. Онобенно знание Content-Type:
Content-Type:
Состоит из типа и подтипа типы могут быть как стандартные так и экспериментальные начинающиеся с префикса 'x-':
text
Текстовые данные.Первым подтипом который включен сюда это plain,что значит простой текст. сюда же включен самый ходовой формат html .У типа text как и у многих типов могут быть параметры,главным из них является charset он как раз и указывает на раскладку символов, которая применена в тексте, так что если вы хотите указать браузеру какую раскладку применять, то просто укажите charset:
Content-Type: text/plain; charset=us-ascii
Content-Type: text/html; charset=iso-8859-1
Content-Type: text/html; charset=koi8-r
multipart
Данные которые могут состоять из нескольких частей,различных типов данных.Поэтому параметром multipart служит boundary, позволяюший указать разделитель.Каждый фрагмент в многочастевом сообщении имеет свой Content-Type: (Он может быть также multipart,т.е. допускаются вложеные multipart,главное чтоб boundary были разными).В электронной почте применяется больше multipart/mixed (основной подтип) и multipart/alternative (Он отличается тем что показывается одна из альтернатив,например сообщение шлется в простом и HTMLом форматах,и почтовая программа показывает либо часть,которую она способна отобразить). В WWW -програмировании распостранен x-mixed-replace ,который означает что следующая часть должна заменить предыдущую после подгрузки, что применяется для анимации.
Теперь о разделителе,его надо выбирать так,чтоб он не встретился где-то в данных (т.е. что-то вроде "diUr344rnmvforgefvrg923rghyj2").Когда вы задали разделитель,например boundary="boundary" то когда закончилась одна часть,вы должны выдать строку --boundary,последняя часть --boundary--,причем эти разделители должны быть на отдельной строке,а не сливаться с текстом:
Пример:
MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="w23renff491nc4rth56u34-9449" --w23renff491nc4rth56u34-9449 Content-Type: text/plain; charset="koi8-r" Hello,World!! --w23renff491nc4rth56u34-9449 Content-Type: text/html; charset="us-ascii"messageHello,Word!!
Hello people! --w23renff491nc4rth56u34-9449--
Представляет инкапсулированое почтовое сообщение.Используется в e-mail ,а не в WWW.
image
Некоторое Графическое изображение.(чаще всего image/gif и image/jpeg)
audio
Аудиоданные.
video
Видеоданные.
application
бинарные данные какого-нибудь приложения.В том случае если данное приложение может быть запущено,Браузер запускает его.Например при поступлении данных application/msword Браузер спросит,нужно ли запустить Word для просмотра досумента.При отсутствии нужного приложения браузер спросит в каком файле сохранить данные.Подтип octet-stream как раз и означает поток байт информации,который и используется по умолчанию.(К сожалению не все так гладко,известен глюк в Netscape Navigator'е который вместо того чтоб сохранить application/octet-stream пытается его показать как text/plain что если это сгенерировано из CGI,ни к чему хорошему не приводит ;(()
Что касается application ,то Вы можете тут смело извращатся,используя x- типы данных,
Например application/x-fuck-to-netscape-navigator. ;)))))
Часто используемый параметр name позволяет указать имя файла.Например:
Content-Type: application/msword; name="readme.doc"
Что полезно при полученнии файлов через HTTP,причем этот параметр может применятся и для других типов таких image или audio ,Например:
Content-Type: image/gif; name="myfoto.gif"
Content-Transfer-Encoding:
Применяется больше в системе электронной почты и обозначает метод кодирования, которым были закодированы данные при передаче сообщения.Например:
7bit 8bit quoted-printable base64 binary x-типы
MIME-Version:
Указывает версию MIME .
Теперь поговорим о разных браузерах вы знаете что браузеры бывают разные,разных версий на разных платформах, поддерживают и не разные тэги и глюки у них тоже разные.....;((( .
Это могло попортить много нервов WEB-дизайнерам и конечно же нам ,CGI-програмистам. Профессионально написаный сайт от просто хорошего отличается тем что хорошо выглядит Не только на экране того браузера,которым пользуется сам его автор,а на других тоже.
Если вы используете JavaScript для своих страничек,то вы уже наверно использовали (или хотя бы вам в голову приходила мысль использовать)свойства navigator.AppName navigator.AppCodeName navigator.appVersion navigator.userAgent:
илиНу вот ,на этом можно закончить это краткое введение в HTMLые формы.
Итак,У нас на входе скрипта данные формы,закодированые методом urlencode Положеные в Переменную QUERY_STRING или подаваемые на STDIN.Мы должны вопервых их получить.
if($ENV{'REQUEST_METHOD'} eq 'GET'){#Анализируем метод,GET или POST $query=$ENV{'QUERY_STRING'}; } elsif($ENV{'REQUEST_METHOD'} eq 'POST'){ sysread STDIN,$query,$ENV{'CONTENT_LENGTH'}; } Вот,мы уже считали наш запрос в переменную $query.Теперь пришло самое время ее обработать. Мы знаем что поля разделены символом '&' значит используем его в качестве разделителя функции split: @formfields=split /&/,$query;Вот разделили,а теперь организуем цикл foreach по полученым полям @formfields
foreach(@formfields){ if(/^Name=(.*)/){$name=urldecode($1);} if(/^Age=(.*)/){$age=urldecode($1);} } Сдесь выражение в регулярном выражении в круглых скобках (.*) после знака '=',запоминается в скалярную переменную $1 ,которая затем и декодируется нашей старой и знакомой функцией urldecode (я предупреждал,что она будет почти в каждой вашей CGI-программе) sub urldecode{ #очень полезная функция декодирования local($val)=@_; #запроса,будет почти в каждой вашей CGI-программе $val=~s/\+/ /g; $val=~s/%([0-9A-H]{2})/pack('C',hex($1))/ge; return $val; } Так мы проходим по всем полям,которые нам переданы.Это стандартный подход,он годится в качестве шаблона.У вас может возникнуть вопрос,а что делать если вам переданы данные от списка у которого задана возможность выбора нескольких элементов и данные поступают в таком виде: Sel=opt1&Sel=opt2&Sel=opt9. Тут тоже нет никаких проблем,просто запихиваем эти поступающие значения в массив. foreach(@formfields){ ..... if(/^Sel=(.*)/){push @Sel,urldecode($1);} ..... } И потом спокойно оперируем с Полученым Массивом @Sel.На этом можно так сказать заканчивается шаблонная часть скрипта и начинается содержательная, которая зависит только от вашей фантазии.....
Вы можете сколько угодно анализировать полученые значения,обращатся при этом к различным файлам .Если вы к этому приложите фантазию,то кто знает что получится....
А Пока Ради примера я вам напишу скрипт,который ведет социологическое исследование насчет курения и отношения к нему.Может он слишком массивен для данного пособия, но зато он наглядно показывает как достаточно простыми средствами можно проводить социологические исследования.