Создание серверных приложений на языке PERL
Блокировка файла функция Flock
Блокировка файла, функция Flockflock(FileVar, operation);
Сразу сделаю небольшую оговорочку, эта функция работает ТОЛЬКО под Unix-подобными операционными системами (Unix, Linux, FreeBSD, SunOS и др.) и Windows NT, W2k, XP...
Необходимость блокировки файлов возникает очень часто когда ваша Perl программа использует данные непосредственно из файлов. Это может быть гостевая книга, форум, чат, счетчик и т. д.
Сначала кажется, что никаких проблем не будет если просто написать код, открывающий файл при необходимости и закрывающий его, после завершения операции чтения/записи:
open(file, "file.txt"); while($string=
В качестве параметра operation допускаются следующие значения:
| "LOCK_SH" или "1" | Блокировка для чтения |
| "LOCK_EX" или "2" | Блокировка для записи |
| "4" | "двухстороннее" блокирование |
| "LOCK_UN" или "8" | Разблокирование |
open(file, "file.txt"); flock(file, LOCK_SH); while($string=
Код записи данных в файл, с блокировкой:
open (FH, ">>data.tmp"); flock(FH, 2); $str="new line"; print FH $str; flock(FH, 8); close(FH); Есть одна особенность при использовании блокировки файлов: если к файлу может обратиться хотя бы один процесс, в котором не ставится блокировка, то вся система блокирования становится бесполезной. Другими словами, надо использовать блокировку не только при создании/обновлении/записи в нужный файл, но и в других скриптах, работающих с этими файлом.
* * * *
Напишем скрипт, который записывает в файл переданную ему строчку, и удаляет строку с переданным номером:
#!/usr/bin/perl # programm 13 print "Content-type: text/html\n\n";
&parse_form;
print
| Добавить запись | ||
| Удалить запись номер: |
"; } } elsif ($FORM{'action'} eq "del") { # выполняем этот блок когда хотим удалить строку open(file,"file.txt"); @array=; close file; open(file,">file.txt"); $size=@array; for($i=0;$i; close file; foreach $i(@array){ $u++; print "$u. $i
"; } } else { # вып. этот код когда хотим просмотреть все записи open(file,"file.txt"); @array=; close file; foreach $i(@array){ $u++; print "$u. $i
"; } } Возможно, Вам будет трудно поначалу разобраться с работой этой программы. Попробуйте мысленно "запустить" её, представив что Вы - это Perl. Последовательно интерпретируйте код, возможно записывая часть результатов на бумагу. Мысленно подставляйте значения в форму и снова "запускайте" её, тогда Вы быстро поймете работу программы. Важно обладать таким навыком, это впредь поможет Вам находить ошибки в своих и чужих скриптах.
* * * *
Дополнительный материал: [работа с файлами] [работа с файлами 2] [работа с файлами 3]
Bottom
[Содержание] [Вступление] [необходимое для начала изучения] [урок 1] [урок 2] [урок 3] [урок 4] [урок 5] [урок 6] [урок 7] [урок 8] [урок 9] [урок 10] [урок 11] [урок 12] [урок 13] [урок 14] [урок 15] [урок 16] [урок 17] [урок 18] [урок 19] [урок 20] [урок 21] [урок 22] [урок 23] [урок 24] [урок 25] [урок 26] [урок 27] [урок 28] [правила хорошего тона] [приложение A] [приложение Б] [приложение В] [заключение] [благодарности]Дополнительные поля HTTP заголовка
Дополнительные поля HTTP заголовкаДалее я расскажу только о 3-х, самых основных полях HTTP заголовка.
Поле Status: передает браузеру код завершения обработки запроса. В случае успешной обработки передается код "200", в случае ошибки на сервере -"500" и т.д.
Поле Location: передает браузеру альтернативный URL. После приема заголовка с таким полем, браузер обычно переходит по означенной в поле ссылке.
Код ниже генерирует заголовок, являющимся скриптом-редиректом:
print "Content-Type: text/html\n"; print "Status: 302 Moved\n"; print "Location: http://goout.ru\n\n"; код 302 означает, что ресурс временно недоступен.
Еще немного об операторе Print
Еще немного об операторе PrintИногда есть необходимость вывести целый блок однотипной информации. В таком случае использование оператора Print в классическом стиле не совсем удобно. Яркий пример тому программа номер 11: чтобы вывести форму, потребовалось написать оператор Print целых 5 раз, да еще нужно было следить, чтобы перед каждой кавычкой стоял бэк-слэш. Чтобы не возникало подобных неудобств прибегают к методу here-doc. Суть этого метода такова: Прямо в текст программы вставляется фрагмент, предназначенный для вывода, за которым следует выражение-огранечитель. Помимо того, что мы избавляемся от необходимости лишний раз писать оператор print, этот метод хорош и тем, что внутри блока сохраняется форматирование и интерполируются все метасимволы.
Необходимые требования, предъявляемые ограничителям:
1. ограничитель должен быть изолирован, т.е. стоять на следующей строке ПОСЛЕ выводимого блока, и после ограничителя не должно быть никаких символов кроме перевода строки (не путать с метасимвлолм "\n");
2. ограничитель не должен являться зарезервированным литералом (это пока Вам не грозит).
Вот программа 11 с применением метода here-doc:
#!/usr/bin/perl #programm 12 print "Content-Type: text/html\n\n"; &parse_form; print <<OKAY; \n"; if ($FORM{'match'} == 1){ print "A + B = ",$FORM{'a'}+$FORM{'b'},"
"; print "A - B = ",$FORM{'a'}-$FORM{'b'},"
"; print "A * B = ",$FORM{'a'}*$FORM{'b'},"
"; print "AB = ",$FORM{'a'}**$FORM{'b'};}
* * * *
Напишите программу, которая запрашивает кол-во текстовых полей и выводит их одно под другим. Напротив каждого поля должна располагаться "галочка". По нажатию на "submit", форма передается скрпту, который выводит значение только тех полей, напортив которых "галочка" была отмечена. Ограничите максимальное количество полей значением 10, а минимальное - тремя. Используйте метод Post при передаче формы.
MIME
MIMEMIME (Multipurpose Internet Mail Extensions) - Многоцелевые расширения почты интернета, были разработаны как стандарт идентификации различных типов файлов для отправки их по почте, но в последствии их функции были расширены и на другие сервисы Интернета. Для типа MIME, который прописывается в реестре Windows и используется различными программами, в частности, указывается расширение файла и программа, с помощью которой данный тип файлов будет обрабатываться.
| Типы MIME | Тип файла |
| Архив RAR | application/x-tar |
| Архив ZIP | application/x-zip-compressed |
| Исполняемый файл (.exe) | application/octet-stream |
| Аудио- или видеозапись ASF | video/x-ms-asf |
| Аудио- или видеозапись WMV | video/x-ms-wmv |
| Аудиозапись AIFF | audio/aiff |
| Аудиозапись AU | audio/basic |
| Аудиозапись MIDI | audio/mid |
| Аудиозапись MP3 | audio/mpeg |
| Аудиозапись WAV | audio/wav |
| Аудиозапись WMA | audio/x-ms-wma |
| Аудиозапись AVI | video/avi |
| Аудиозапись AVI (.avi) | video/x-msvideo |
| Видеозапись Indeo (IVF) | video/x-ivf |
| Видеозапись MPEG (.mpeg .mpg .mpe) | video/mpeg |
| Видеозапись QuickTime (.qt .mov) | video/quicktime |
| Визитная карточка, используемая почтовыми программами для хранения данных об адресате | text/x-vcard |
| Графический файл ART | image/x-jg |
| Графический файл BMP | image/bmp |
| Графический файл GIF | image/gif |
| Графический файл JPEG | image/jpeg |
| Графический файл Macromedia Flash | application/futuresplash |
| Графический файл TIFF | image/tiff |
| Документ Adobe Acrobat | application/pdf |
| Документ HTML | text/html |
| Документ Microsoft Excel | application/x-msexcel |
| Документ Microsoft Word | application/msword |
| Документ RTF | application/msword |
| Документ RTX | text/richtext |
| Документ XML | text/xml |
| Приложение | application/x-msdownload |
| Приложение HTML (HTA) | application/hta |
| Таблица стилей HTML | text/css |
| Текстовой документ | text/plain |
Область многострочного редактирования
Область многострочного редактированияЕё еще называют областью потенциально большого объема текста. Синтаксис её таков:
У этого тега есть дополнительные параметры и атрибуты:
| name | имя области |
| rows | кол-во строк области в символах |
| cols | ширина области в символах |
| А роза упала на лапу Азора |
Оператор do
Оператор dodo {operator} while (EXPR) do {operator} until (EXPR)
Оператор while/until проверяет условие в начале каждого цикла, до входа в него. Если результат проверки условия — "ложь", цикл не будет выполнен вообще.
Иногда возникает необходимость проверять условие не в начале, а в конце цикла. Для этого в Perl есть оператор do {} while, который очень похож на обычный оператор while, за исключением того, что он проверяет выражение только после однократного выполнения цикла.
* * * *
Приведенная ниже программа демонстрирует работу оператора While.
#!/usr/bin/perl #programm 7 print "Content-Type: text/html\n\n";
$i=1; while($i<9){ print "$i X 7 = ".$i*7; print "
"; }continue{$i++}
* * * *
Модернизируйте программу, которая выводит таблицу Пифагора (Всё равно какую) так, чтобы вместо оператора For в ней использовались операторы While и Until.
Дополнительная информация: [Управляющие структуры ] [Управляющие структуры 2 ]
Оператор Foreach
Оператор Foreachforeach VAR (LIST) {operator}
Переменной VAR присваивается поочередно каждый элемент списка LIST и выполняется блок. Если VAR опущено, то элементы присваиваются встроенной переменной $_. Если в теле блока изменять значение VAR то это вызовет изменение и элементов списка т.к. VAR фактически указывает на текущий элемент списка. Вместо слова foreach можно писать просто for - это слова синонимы.
оператор ..
Элемент списка может включать операцию конструктора списка. Это два скалярных значения, разделенных двумя точками. Данная операция создает список значений, начиная с левого скалярного значения и кончая правым скалярным значением, с шагом 1.
Если правый скаляр меньше левого, то список будет пустым, так как в обратном направлении отсчет вести нельзя. Если последнее значение не соответствует целому числу шагов, то список заканчивается там, где приращение на единицу привело бы к появлению числа, не принадлежащего заданному диапазону. Ниже приведенная программа демонстрирует работу операторов foreach и "..":
#!/usr/bin/perl print "Content-Type: text/html\n\n"; @array=(1..10); foreach $a(@array){ print ($a,"
"); }
* * * *
Оператор GOTO
Оператор GOTOgoto метка;
Можно теоретически показать, что рассмотренных операторов вполне достаточно для написания программ любой сложности. В этом отношении наличие в языке оператора перехода кажется излишнем. Более того технология структурного программирования основана на принципе "программирование без GOTO": считается, что использование оператора перехода затрудняет понимание программы, делает её запутанней и сложной в отладке.
Тем не менее, в некоторых случаях использование оператора перехода может упростить программу.
В Perl метки обозначаются ЗАГЛАВНЫМИ латинскими буквами и отделяются от следующего за ним оператора двоеточием (:).
Оператор Grep
Оператор Grepgrep {блок} список;
grep (выражение, список);
Выполнят блок или выражение для каждого элемента списка. Переменная $_ содержит текущий элемент. Возвращает список элементов, с которыми выражение дало результат true. В скалярном контексте возвращает количество результатов true. Как видите, grep очень похож на foreach:
@tmp=(1,2,3); grep{print $_} @tmp;
Оператор Last
Оператор Lastlast - подобен оператору break в языке С. Немедленно прерывает цикл. Блок continue пропускается
Оператор m//
Оператор m//m/PATERN/gimosx;
/PATERN/gimosx;
Поиск в строке по паттерну (шаблону). В скалярном контексте возвращает логическое значение true (1) или false (''). Если строка не указана с помощью операторов '=~' или '!~', поиск ведется в строке $_ . Опции:
| g | - Глобальный поиск. Поиск всех вхождений. |
| i | - Сравнение не зависит от регистра (верхний или нижний) |
| m | - Строка многострочная. |
| o | - однопроходная компиляция |
| s | - однострочная строка |
| x | - используются расширенные регулярные выражения. |
PATTERN может содержать переменные, которые будут интерполироваться (перекомпилироваться) каждый раз в момент вычисления. Переменные $) и $| не интерполируются. Если вы хотите, что бы такой шаблон интерполировался один раз - добавьте /o. Это необходимо делать в циклах поиска для увеличения быстродействия, однако, если вы измените значение переменной, Perl этого даже не заметит.
Если PATERN - нулевая строка, то используется последнее регулярное выражение.
В скалярном контексте возвращается список элементы которого - результаты выполнения выражений в скобках паттерна ($1, $2, $3...). Обратите внимание что первый элемент $1.
Оператор Map
Оператор Mapmap {блок} список;
map выражение, список;
Выполняет блок или выражение для каждого элемента списка. Возвращает список результатов.
@tmp=(1,2,3); $v = map $i.=$_, @tmp; print $i,"
"; print $v;
* * * *
Оператор Next
Оператор Nextnext - подобен continue в С. Переходит к началу текущего цикла (блок continue вычисляется) т.е. повторяет итерацию.
Оператор q//
Оператор q//q/строка/;
'строка';
Не интерполируемая строка литералов. Если в качестве разделителя используется одинарная кавычка, ключевое слово "q" можно опускать.
Сами того не зная, Вы используете этот оператор почти с самого первого урока.
print q^Windows 3.11^; # результат: Windows 3.11 print q?Windows 98?; # результат: Windows 98 print 'Windows 2000'; # результат: Windows 2000
Оператор qq//
Оператор qq//qq/строка/;
"строка";
Интерполируемая строка. Если в качестве разделителя используется двойная кавычка, ключевое слово "qq" можно опускать.
$var311 = "3.11"; # определяем переменные $var98 = "98"; print qq#Windows $var311#; # результат: Windows 3.11 print qq+Windows $var98+; # релультат: Windows 98 print "Windows 2000"; # результат: Windows 2000
Оператор qw//
Оператор qw//qw/строка/;
Возвращает список, элементы которого содержат слова из строки. Т.е. пробелы рассматриваются как символы-разделители.
Следующий код подчеркнет все слова фразы, длиной 7 букв:
@array = qw(Пока толстый сохнет, худой - сдохнет); foreach $i(@array){ if (length($i) == 7){print "$i "} else {print "$i "} }
Оператор qx//
Оператор qx//qx/строка/;
`строка`;
Сначала строка интерполируется, а потом выполняется как системная команда.
print ""; print `dir`; print ""; Этот код выведет очень много ценной информации ;-) . Не забудьте переключить кодировку браузера в "DOS".
Оператор Redo
Оператор Redoredo - начать новый цикл не вычисляя EXPR и не выполняя continue блок.
* * * *
Пример применения оператора next:
#!/usr/bin/perl print "Content-Type: text/html\n\n";
M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 next M1 if $i < 3; # Переходим в начало если $i < 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i } # получаем 1 2 4 6
Пример применения оператора last:
#!/usr/bin/perl print "Content-Type: text/html\n\n";
M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 last M1 if $i > 3; # Выход из цикла если $i > 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i } # результат: 2 4
Пример применения оператора redo:
#!/usr/bin/perl print "Content-Type: text/html\n\n";
M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 redo M1 if $i == 3; # Далее пропустить для $i = 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i } # получим 2 5 7
* * * *
Напишите программу, выводящую все простые числа из диапазона (-28..53) включительно. Есть ли вообще простые числа в этом диапазоне?
Для справки: простое число, это такое число, которое дилится без остатка только на себя и еденицу.
Напишите программу, вычисляющую произведение двух соседних числа ряда из диапазона (-28..53), и если это число делется без остатка на 7, выводит результат на экран и увеличивает переменную цикла на 2.
Оператор S///
Оператор S///s/шаблон/подстрока/egimosx;
Поиск по шаблону и в случае успеха замена подстрокой. Возвращает количество произведенных подстановок, иначе false (0). Если строка в которой ведется поиск не указана (операторы =~ или != ), то используется переменная $_ . Если в качестве разделителя '/' использовать одинарную кавычку ('), то интерполяции не будет, иначе можно применять переменные в шаблоне или подстроке. Опции:
| e | - Рассматривать правую часть как выражение. |
| g | - Глобальный поиск. |
| i | - Без различия регистра букв |
| m | - многострочная переменная |
| o | - компилировать шаблон один раз |
| s | - однострочная переменная |
| x | - расширенное регулярное выражение |
$var = "12345"; # исходная строка $var =~ s/1/0/; # Заменить '1' на '0'. Результат 02345 $var =~ s(5)(.); # Заменить '5' на '.' Результат 0234. Здесь в качестве разделителя применены скобки, поэтому подстрока взята в две скобки.
$var =~ s/\d*/каламбур/; #Заменить все цифры. Результат 'каламбур.' $var =~ s/а/о/g; # Заменить все 'а' на 'о'. Результат 'коломбур.' $var = "12 34"; # Новое значение $var =~ s/(\d\d) (\d\d)/$2 $1/; # Поменять местами числа. Результат '34 12'.
Оператор Split
Оператор Splitsplit (/шаблон/, выражение, предел);
split (/шаблон/, выражение);
split (/шаблон/);
split;
Разделяет строку, указанную выражением, на массив элементов и возвращает его. В скалярном контексте возвращает количество полученных элементов массива, а сам массив помещает в @_ (в списковом контексте поместить результат в @_ можно если применить ?шаблон?) Если выражение отсутствует, то обрабатывается содержимое переменной $_. Если шаблон отсутствует, то разделителем является пробел. Все, что подходит по шаблону, считается разделителем. Если указан предел, то это максимальное число разделений. Отрицательное значение предела воспринимается как неограниченно большой предел. Если пустая строка походит под шаблон разделителя, то исходное значение разделяется посимвольно. Предел удобно использовать для частичного разделения строки.
($a, $b, $остаток) = split(/ /, "Один Два Три Четыре",3); # $a = 'Один', $b = 'Два' и $остаток = 'Три Четыре' Если шаблон содержит круглые скобки, то символы-разделители, указанные в них, вставляются в результирующий список как обычные элементы, причем вставляется символ, который совпал с разделителем
@a = split(/([,.])/, "Один,Два.Три"); # @a = ("Один", "," ,"Два", ".", "Три") И еще один примерчик:
@a = split(//,"червь"); # @a = ('ч','е','р','в','ь')
* * * *
Попробуйте создать так называемую "плоскую базу": напишите скрипт, который записывает в файл строчки такого вида: "переданная_строка1 & переданная_строка2 & переданная_строка3", при каждом обращении к скрипту. И выводящий на экран самую длинную строку из первых значений и саму короткую из вторых. Эти строки должны сопровождаться значениями из 3-их строк.
Операторы tr/// и y///
Операторы tr/// и y///tr/таблица1/таблица2/cds;
y/таблица1/таблица2/cds;
Замена всех символов из "таблица1" на соответствующий символ из "таблица2". Результат - количество замен или стирании. Без оператора =~ или != операция выполняется со строкой $_. Для совместимости с программой sed вместо tr можно писать 'y'.
Опции:
| c | - дополнение "таблица1" |
| d | - стереть найденные, но не замененные символы. |
| s | - "сжать" повторяющиеся замененные символы. |
$s = "hello"; # Исходная строка $s =~ tr/a-z/A-Z/; # Заменить малые буквы на большие. Результат # 'HELLO' $s = 'Hel....lo'; $s =~ tr/a-zA-z/_/c; # Заменить все не буквы на '_' # Результат 'Hel____lo' $s =~ tr/_/ /s; # Заменить '_' на ' ' и сжать. # Результат 'Hel lo' $s =~ tr/a-zA-Z /a-zA-Z/d; # Удалить все не буквы. Результат 'Hel
* * * *
Попробуйте написать функцию, которая запрашивает выражение и число. Функция должна возвращать номера слов в выражении, длина которых превышает переданное число.
Дополнительная информация: [регулярные выражения]
Открытие и закрытие дескриптора файла
Открытие и закрытие дескриптора файлаopen (FileVar, FileName);
close (FileVar);
Функция Open открывает указанный файл и ассоциирует с ним файловую переменную (дескриптор файла). В зависимости от спецсимвола, стоящего перед именем файла, файл можно открыть с разным способом доступа к нему.
| open (FV,"FN"); | Файл открыт для чтения. Запись в него запрещена. |
| open (FV,">FN"); | Файл открыт для записи. Когда файл открыт таким способом, его содержимое автоматически стирается (а если файл не существует - создается) и в файл можно добавлять данные. |
| open (FV,">>FN"); | Файл открыт для записи в конец. При таком способе открытия файла, тело файла не изменяется и разрешено добавлять строки в его конец. |
open (FV,"+| Файл открыт для чтения и записи. |
|
| open (FV,"|FN"); | Направить информацию на вход программы. |
| open (FV,"FN|"); | Считать информацию с выхода программы. |
| open (FV,"|FN|"); | И то и другое. |
Из файла можно считать данные в виде массива и построчно. При считывании файла построчно, какой-то переменной, при первом считывании, присваивается первая строка файла и указатель перемещается на следующую строку. Такое присваивание возвращает True. При втором считывании присваивается вторая строка, при третьем - третья и т.д. до конца файла. Когда указатель дойдет до последней строки, счетчик сбрасывается, указатель перемещается на первую строчку файла, а возвращаемое выражение становится равным False
При считывании файла в массив, каждая строка файла помещается в отдельную ячейку массива. Плюсы и минусы этих методов очевидны: При считывании файла построчно, экономится память сервера, но работать с файлом становится неудобно, да и этот метод не очень производителен. Другое дело - работа с массивом: это быстро, это удобно, но есть очевидный минус - сильная загрузка памяти сервера. Но несмотря на это, данный метод пользуется огромной популярностью при написании небольших скриптов.
Чтобы считать файл/строку в какую-то переменную, этой переменной присваивают дескриптор файла, заключенный в треугольные скобки:
@array =
Переключатель
ПереключательПереключатель должен иметь имя и значение. Имя задается в параметре "Name", значение в "value" (в отличие от кнопок, где value - надпись на кнопке). В том случае, если переключатель выбран, передается его имя и значение. Если не выбран - ничего не передается. Если необходимо чтобы переключатель был по умолчанию отмечен, он должен иметь атрибут "checked".
Почтовые рассылки
Почтовые рассылкичтобы средствами Perl можно было отсылать почту, необходимо чтобы на сервере была установленна программа "sendmail". Версию под Windows пожно скачать из раздела "Download".
что делаем. Открываем функцией Open программу, и ей на вход подаем нашу почтовую форму:
open (MAIL,"|/usr/lib/sendmail -t"); print MAIL "To: to\@e.mail\n"; print MAIL "From: from\@e.mail\n"; print MAIL "Subject: Subject\n\n"; print MAIL "Body\n"; close MAIL; Как и HTTP запрос, Email запрос состоит из заголовка и тела. Разберем подробнее заголовок:
To: - Email адрес получателя письма;
From: - Email адрес отправителя;
Subject: - тема.
Как и в HTTP запросе, тело от заголока отделяется пустой строкой.
А Вот форма более продвинутого содержания:
print В общем, почти то же самое, только информации передается побольше и добавлено поле Cc - адресат скрытой копии.
Еще один интересный код, дает возможность передавать вложенные файлы:
$to = '"Your Name" '; $recip = 'yourname@yourdomain.com'; $from = '"Your Name" '; $subject = "This is the subject"; $mainbody = "This is the main body\n"; $attachment = "This is an attachment\n"; $message = MakeMessage($to, $from, $subject, $mainbody, $attachment); open (MAIL, "|sendmail -t"); print MAIL $message; close (MAIL); sub MakeMessage { # make a composite message containing a main body and one attachment my ($to, $from, $subject, $mainbody, $attachment) = @_; my $message =
Поле для ввода пароля
Поле для ввода пароляДля этих полей справедливы вышеизложенные утверждения. Создается это поле тегом со значением "pa" пара" параметра "type".
Получение данных методом GET
Получение данных методом GETСуть метода GET заключается в передаче некоторого объема информации вместе с URL скрипта. Для отделения URL от передаваемой информации используют знак "?" (вопросительный знак). Неплохо бы чисто формально напомнить, что все пробелы заменяются в URL на знак '+', а все специальные и непечатные символы на последовательность %hh ,где hh-шестнадцатиричный код символа. Методом GET можно одновременно передавать несколько значений. Как это делается я расскажу вам позже, а пока будем довольствоваться одним передаваемым значением.
* * * *
Напишем программу, которая выводит квадрат числа, если передаем ей число, или строку, если передаем текстовую строку. Передавать данные следует примерно так: "http://.../cgi-bin/script.pl?256"
#!/usr/bin/perl
print "Content-Type: text/html\n\n";
if ($ENV{'QUERY_STRING'}**2 == 0){print $ENV{'QUERY_STRING'}}
else{print $ENV{'QUERY_STRING'}**2}
И еще одна программка, выводящая некоторые сведения о Вашем сервере:
#!/usr/bin/perl #programm 9 print "Content-Type: text/html\n\n";
@array=($ENV{'SERVER_SOFTWARE'},$ENV{'SERVER_NAME'}); @array=(@array,$ENV{'SCRIPT_FILENAME'},$ENV{'HTTP_USER_AGENT'}); print "
| $_ |
* * * *
Попробуйте написать программу, выводящую таблицу Пифагора с максимальным значением по оси X и Y, передаваемым методом GET.
Сделайте так, чтобы ячейки закрашивались в шахматном порядке, а оси имели черный цвет.
Напишите программу, которая выводит символьную строку, переданную скрипту только в том случае, если IP удаленной машины не соответствует 127.0.0.1 .
Правила хорошего тона при разработке CGI программ
Правила хорошего тона при разработке CGI программДля начала я расскажу Вам о существовании функции USE.
Прежде чем приступить к занятиям ...
Прежде чем приступить к занятиям...Прежде чем Вы перейдете к первому уроку, Вы должны немного знать о том как вообще работает Web-сервер и как будут работать Ваши CGI-скрипты (а именно так мы будем называть программы написанные на Perl) на нем. Также Вам потребуется определенное программное обеспечение.
И так, давайте определимся с терминологией.
сервер -компьютер, некоторые ресурсы которого доступны другим компьютерам.
WEB-сервер -компьютер означенный специальным П/О, по средствам которого он способен отдавать HTML документы и результаты работы серверных сценариев другим компьютерам.
В нашем случае серверные сценарии мы будем писать на языке Perl.
Существует такой протокол как HTTP, по средствам которого Web-сервер может получать запросы от браузера и отвечать ему. Когда Вы пытаетесь открыть какую-то страницу, браузер посылает на сервер HTTP запрос, в котором содержится информация о том, что хочет от сервера браузер, данные какого формата он может принять и др. Взамен сервер отсылает браузеру HTTP ответ, состоящий из HTTP заголовка и тела. В HTTP заголовке содержаться сведения о формате передаваемых данных, в теле непосредственно данные (к примеру html файл). По мере изучения курса Вы будете всё больше и больше узнавать о передаваемых данных в заголовках HTTP.
Если сервер получил запрос файла с серверным сценарием, он передаст его соответствующему обработчику, а результат передаст браузеру в теле HTTP.
Значит, чтобы Вы могли запускать perl-скрипты у себя дома (а без этого у Вас просто не получится изучать Perl), Вам потребуется интерпретатор Perl и программа-сервер, которая сможет с ним работать.
Так уж завелось, что большая честь Интернет серверов оснащена программами Apache и работают на платформе Unix, а большая часть пользователей работают на платформе Windows и вообще не имеют программ-серверов. Главная наша задача - максимально приблизиться к условиям настоящих Интернет серверов, от этого зависит качество обучения и в конечном счете качество Ваших Perl-скриптов.
Можно было бы, конечно, установить себе Unix, и работать на "настоящем" web-сервере, но делать это едва ли кто захочет. По этому ограничимся ОС Windows NT. Пойдет всё: NT4/2000/XP. Но если у Вас нет возможности ставить себе такую "роскошь", пойдет и Windows98, только некоторые функции Perl вы не сможете использовать.
Программу-сервер, как Вы уже догадались, я рекомендую Apache. Скачать его можно из раздела "Download-perl". Настройка Apache весьма сложна и требует немало времени и терпения, но результат того стоит! В том же разделе лежит другой HTTP сервер, называющейся SHTTPS (Small HTTP Server). Его главное отличие от Apache - простота настройки. В принципе, сразу после инсталляции он уже готов к работе, нужно только прописать путь к Perl, чтобы он мог выполнять Perl-скрипты.
Дистрибутив Perl я рекомендую качать полный (8 Мб), иначе очень навороченные скрипты (по большей части форумы), которые вы скорее всего будете отлаживать у себя на машине, не смогут работать. Но для изучения Perl пойдет и минимальный дистрибутив (600 Кб).
И так, если у Вас сервер Apache с полным дистрибутивом Perl установлены на Windows 2000, Вы в полной мере сможете ощутить ВСЮ мощ CGI-программинга!
Напротив, если вы установите SHTTPS с минимальным дистрибутивом Perl под Windows 95, Этого едва ли хватит для первоначального знакомства с Perl.
Если Вы уже установили сервер и Perl, можете приступать к первому уроку. Если еще нет, раздел "Help" поможет Вам установить и настроить сервера.
Желаю удачи!
Дополнительная информация: [подробнее об HTTP протоколе]
A Форматы MIME Работа
Приложение A.Форматы MIME. Работа с почтой.
Дополнительные поля HTTP заголовка; работа с Cookie
Простые поля для ввода
Простые поля для вводаПростое поле для ввода создается тегом , но в отличае от кнопок, значение атрибута "type" должно быть "text". У простого поле для ввода есть дополнительные параметры и атрибуты:
| name | идентификатор данного поля |
| size | длина поля в символах |
| title | текст всплывающей подсказки |
| value | значение поля по умолчанию |
| maxlength | максимально возможное количество вводимых символов |
| disabled | этот атрибут не дает изменить значение по умолчанию |
Как это работает: при отправке формы, значение каждого поля будет являться значением параметра, а имя поля - именем параметра. Именно поэтому необходимо каждому полю присваивать какое-нибудь имя.
Прототипы
ПрототипыДля краткого описания типа передаваемых подпрограмме параметров можно применять прототипы. Если формат передаваемых данных не будет удовлетворять шаблону прототипа, это вызовет ошибку программы. В Perl существуют следующие прототипы:
| sub mylink($$) | mylink $old, $new |
| sub myvec($$$) | myvec $var, $offset, 1 |
| sub myindex($$;$) | myindex &getstring, "substr" |
| sub myreverse(@) | myreverse $a, $b, $c |
| sub myjoin($@) | myjoin ":",$a,$b,$c |
| sub mypop(\@) | mypop @array |
| sub mysplice(\@$$@) | mysplice @array, @array, 0, @pushme |
| sub mykeys(\%) | mykeys %{$hashref} |
| sub myopen(*;$) | myopen HANDLE, $name |
| sub mypipe(**) | mypipe READHANDLE, WRITEHANDLE |
| sub mygrep(&@) | mygrep { /foo/ } $a, $b, $c |
| sub myrand($) | myrand 42 |
| sub mytime() | mytime |
require "файл";
Пример кода, где подпрограмма загружается из внешнего файла:
# Файл sub.pl sub summ($$){ return ($_[0]+$_[1]) } # Файл со скриптом require "sub.pl"; print summ(5,2);
* * * *
Напишем функцию, которая возвращает фактореал переданного ей числа.
sub fact{ # объявляем функцию fact my($sum,$i); # объявляем локальные переменные $sum=1; for ($i=1;$i<=$_[0];$i++){ $sum*=$i; } return $sum # возвращаем значение переменной $sum }
Примеры вызова такой функции:
print fact(4);
print fact(4,22.8,5);
Результатом выполнения этого кода будет 24 Чтобы избежать вызова функции с ошибочными значениями, используем прототип $, означающий, что функции мы передаем только один парамер:
sub fact($){
my($sum,$i); $sum=1; for ($i=1;$i
Перепишем программу 13 с учетом полученных знаний:
#!/usr/bin/perl # programm 17 print "Content-type: text/html\n\n";
&parse_form;
sub wiev(){ open(file,"file.txt"); @array=; close file; foreach $i(@array){ $u++; print "$u. $i
"; }}
print
| Добавить запись | ||
| Удалить запись номер: |
* * * *
Путь к файлу
Путь к файлуЕсли опустить путь к файлу, а указать только его имя, будет считаться, что указанный файл лежит в той же директории, что и файл скрипта. Допускается указывать как абсолютный, так и относительный путь. К примеру, имеем такое дерево файлов и каталогов:
D:/USR/LOCAL/APACHE |----> CGI-BIN | |----> MYDIR | | |----> file0.txt | | | |----> script.pl | |----> file1.txt | |----> HTDOCS |----> file2.txt Тогда абсолютные пути к файлам будем иметь такими:
D:/USR/LOCAL/APACHE/CGI-BIN/MYDIR/file0.txt D:/USR/LOCAL/APACHE/CGI-BIN/file1.txt D:/USR/LOCAL/APACHE/CGI-BIN/script.pl D:/USR/LOCAL/APACHE/HTDOCS/file3.txt А относительно файла script.pl, пути будут такими:
MYDIR/file0.txt file1.txt ../HTDOCS/file2.txt При написании CGI программ принято использовать относительные пути, т.к. владельцы WEB-серверов часто скрывают абсолютное расположение своих директорий.
Работа с Cookie
Работа с Cookie(отрывок из статьи "Что такое Cookies и с чем их едят")
Что такое cookie?
Cookie является решением одной из наследственных проблем HTTP спецификации. Эта проблема заключается в непостоянстве соединения между клиентом и сервером, как при FTP или Telnet сессии, т.е. для каждого документа (или файла) при передаче по HTTP протоколу посылается отдельный запрос. Включение cookie в HTTP протокол дало частичное решение этой проблемы.
Cookie это небольшая порция информации, которую сервер передает клиенту. Клиент (броузер) будет хранить эту информацию и передавать ее серверу с каждым запросом как часть HTTP заголовка. Некоторые cookie хранятся только в течение одной сессии, они удаляются после закрытия броузера. Другие, установленные на некоторый период времени, записываются в файл. Обычно этот файл называется 'cookie.txt'.
Что можно делать с помощью cookie?
Сами по себе cookies не могут делать ничего, это только лишь некоторая информация. Однако, сервер может на содержащуюся в cookies информацию. Например, в случае авторизованного доступа к чему либо через WWW, в cookies сохраняется login и password в течение сессии, что позволяет не вводить их при запросе каждого запаролированного документа. Другой пример: cookies могут использоваться для построения персонализированных страниц. Чаще всего встречается такое - на некотором сервере Вас просят ввести свое имя, и каждый раз, когда Вы заходите на первую страницу этого сервера, Вам пишут что-то типа "Hello, your_name!". На использовании cookies также часто строят функцию оформления заказа в онлайновых магазинах, в частности, в Амазоне, такая своеобразная виртуальная корзина покупателя, как в обычном реальном супермаркете.
У Cookies есть 2 основных параметра: содержание и время жизни, по истечении которого Cookies не передаются серверу. Чтобы с помощью CGI установить Cookies, нужно добавить в HTTP заголовок строку такого вида:
Set-Cookie: key=value; expires=date;
[key=value] - тело;
[date] -время жизни.
Время жизни представляет собой критическую дату, после которой Cookies считается не действительным. Она указывается весьма своеобразным способом:
Set-Cookie: Name=CowBoy; expires=Fri, 31-Dec-02 23:59:59 GMT;
Это значит, что Cookies будут жить только до 31 декабря 2002 года.
Один документ может содержать несколько Cookies. Код ниже формирует HTTP заголовок с установкой Cookies:
print "Content-Type: text/html\n"; print "Status: 200 Ok\n"; print "Set-Cookie: name=Robert; expires=Sat, 26-Aug-03 15:45:30 GMT;\n"; print "Set-Cookie: nick=Pauls; expires=Sat, 26-Aug-03 15:45:30 GMT;\n\n";
Чтобы автоматизировать процесс выставления Cookies, написана процедура set_cookie. Она принимает 3 параметра: время жизни в часах, ключ, значение.
sub set_cookie($$$){ my($year,$date,@day,$ret,$time); $time=time+($_[0]*3600); $year=(localtime($time))[5]; $date=localtime($time); @day=split(/ /,$date); $year =~ s/\d*(\d\d)/$1/; $ret="Set-Cookie: $_[1]=$_[2]; expires="; $ret.="$day[0], $day[2]-$day[1]-$year $day[3] GMT;"; return $ret }
Посмотрите как просто с помощью неё устанавливать Cookies:
print set_cookie(10,"name","Robert"),"\n"; print set_cookie(10,"nick","Pauls"),"\n\n";
sub set_cookie($$$){ my($year,$date,@day,$ret,$time); $time=time+($_[0]*3600); $year=(localtime($time))[5]; $date=localtime($time); $date =~ s/ +/ /g; @day=split(/ /,$date); $year =~ s/\d*(\d\d)/$1/; $ret="Set-Cookie: $_[1]=$_[2]; expires="; $ret.="$day[0], $day[2]-$day[1]-$year $day[3] GMT;"; return $ret }
Чтение ранее записанных значений Cookies производится из переменной окружения $ENV{'HTTP_COOKIE'}. Для удобства получения данных написана процедура get_cookie.
sub get_cookie{ my (@coo_pairs,$pair,$name,$value); @coo_pairs = split(/; /, $ENV{'HTTP_COOKIE'}); foreach $pair (@coo_pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $COOKIE{$name} = $value;} }
Она создает хеш %COOKIE, в котором данные представлены в виде ключ-значения.
В Cookies можно хранить только символы латинского алфавита, символы нижнего подчеркивания, цифры и знаки % (процент). Обычно такого набора символов хватает для хранения служебной информации.
Чтобы в Cookies можно было хранить все символы таблицы ASCII, доработаем функции передачи следующим образом: будем передавать не сам символ, а его номер в таблице. Для разделения символов будем использовать символ "%". Анологичным образом поступим с функцией приема Cookies, только она будет дешифрировать наши последовательности.
Скрипт ниже создает и считывает значения из Cookies. Все функции модифицированны:
#!/usr/bin/perl
print "Content-Type: text/html\n"; print &set_cookie(1,"name","Robert"),"\n"; print &set_cookie(1,"nick","Pauls"),"\n\n"; my ($COOKIE);
sub set_cookie($$$){ my($year,$date,@day,$ret,$time,$word); $time=time+($_[0]*3600); $year=(localtime($time))[5]; $date=localtime($time); $date =~ s/ +/ /g; @day=split(/ /,$date); $year =~ s/\d*(\d\d)/$1/;
$word=$_[2]; $word =~ s/(.)/"%".ord($1)/eg;
$ret="Set-Cookie: $_[1]=$word; expires="; $ret.="$day[0], $day[2]-$day[1]-$year $day[3] GMT;"; return $ret }
sub get_cookie{ my (@coo_pairs,$pair,$name,$value); @coo_pairs = split(/; /, $ENV{'HTTP_COOKIE'}); foreach $pair (@coo_pairs) { ($name, $value) = split(/=/, $pair); $value =~ s/%(\d+)/chr($1)/eg; $COOKIE{$name} = $value;} } get_cookie;
print $COOKIE{'name'},"
"; print $COOKIE{'nick'};
Радиокнопка
Радио-кнопкаВ отличие от checkbox, может быть несколько радио кнопок с одинаковым параметром name ,но с разными value, из них передается только та, что выбрана. Одна из них может быть изначально выбрана по умолчанию.
Скрытое поле
Скрытое полеСкрытое поле не отображаемое на экране. Но оно имеет имя и значение и следовательно передается в форму. Служит для того (и очень часто программисты его применяют) чтоб передавать скрипту какую нибудь информацию.Например,если ваш скрипт обрабатывает несколько форм разных типов, то в скрытом поле каждой формы можно указать с какой формой конкретно вы имеете дело. Так как это ваша внутренняя кухня то нечего пользователю мозолить глаза этой информацией.
Создание серверных приложений
Создание серверных приложений на языке PERLУскоренный учебный курс
Содержание
| [урок 1] | Создание и запуск Perl-скриптов, оператор Print. |
| [урок 2] | Типы данных в Perl, переменные, одинарные и двойные кавычки. |
| [урок 3] | Операции с числами и строками, логические выражения. |
| [урок 4] | Составной и условный операторы. |
| [урок 5] | Операторы повторения с заданным количеством итераций. |
| [урок 6] | Операторы повторения с неизвестным заранее количеством итераций. |
| [урок 7] | Метки, оператор перехода, операторы управления циклами. |
| [урок 8] | Список. Массив. Работа с массивом. |
| [урок 9] | Метасимволы. |
| [урок 10] | Встроенные переменные, получение данных методом GET. |
| [урок 11] | HTML формы, функция ParseForm, метод POST. |
| [урок 12] | Оператор Print, хеши. |
| [урок 13] | Функции работы с файлами. |
| [урок 14] | Функции для работы с файлами (продолжение). |
| [урок 15] | Функции для работы с файлами (продолжение). |
| [урок 16] | коротко о SSI. |
| [урок 17] | Подпрограммы, прототипы. |
| [урок 18] | Работа с числами. |
| [урок 19] | Функции для работы со строками. |
| [урок 20] | Операторы для работы со строками (продолжение). |
| [урок 21] | Регулярные выражения. |
| [урок 22] | Операторы поиска и замены. |
| [урок 23] | Еще немного о циклах. |
| [урок 24] | Функции для работы с массивами. |
| [урок 25] | Функции для работы с хешами. |
| [урок 26] | Дата и время. |
| [урок 27] | Функции для работы с директориями. |
| [урок 28] | Прочие функции. |
| [приложение A] | Форматы MIME. Работа с почтой. Дополнительные поля HTTP заголовка; работа с Cookie. |
| [приложение Б] | Возможные ответы на задания для самостоятельного выполнения. |
| [приложение В] | Примеры скриптов, выполненных на языке Perl |
Создание серверных приложений на языке PERL
Ускоренный учебный курс
Off-line plus версия
Автор: Cleric ICN
Дата последнего изменения: 04.12.02 18:21
Это учебное пособие написано для того чтобы помочь Вам самостоятельно изучить язык Perl и представляет собой своего рода выжимку из многих электронных и бумажных изданий подобного рода. Пройдя его Вы изучите все необходимые для разработки собственных приложений операторы и функции, узнаете об их специфических особенностях. В рамках этого курса мы будем рассматривать Perl только как язык написания CGI-сценариев.
Чтобы ускоренное изучение Perl не вызывало у Вас никаких затруднений, Вы должны обладать определенным набором знаний в области создания HTML документов. Вы должны хорошо знать HTML тэги, работать с таблицами и каскадными таблицами стилей (CSS). Помимо этого вы должны иметь хотя бы начальные знания в области языков программирования высокого уровня (Pascal, Basic, Delphi, C, JavaScript и т.д.). А если Вы уже знаете PHP, то получите ни с чем не сравнимое удовольствие от изучения Perl по ускоренному курсу.
И так, с чем же Вы будете иметь дело?! Весь курс разбит на 28 уроков, пройдя которые Вы изучите 114 операторов и встроенных функций.
В свою очередь каждый урок разбит на 3 части:
1-я часть - теоретическая. В ней будет даваться теоретический материал по теме урока.
2-я часть - практическая. В ней будет дан пример CGI-приложения выполненного с применением знаний, полученных в этом и предыдущих уроках.
3-я часть - задания для самостоятельного выполнения. В конце каждого урока я буду давать Вам несколько "домашних заданий" для закрепления полученных знаний.
Психологами установлено, что учеба проходит гораздо быстрее, эффективнее и интереснее, если есть какая-то видимая конечная цель (стимул), к которой нужно стремиться. Полное изучение Pelrl не может быть в данном случает стимулом, т.к. знания не вещественны. Стимулом этого курса будет создание скрипта гостевой книги.
В период изучения Perl у вас могут возникать вопросы по некоторым темам, это характерно для любого человека. Важно быстро получить качественный ответ. Сделать это не всегда просто, ведь Вы часто не имеете возможность задать свой вопрос знающему человеку. Чтобы попробовать самостоятельно разобраться со своим вопросом, в разделе "Help" выложены 2 полных справочника по "чистому" Perl и "Учебное пособие по CGI-программированию от Леши", которое будет являться памяткой для Вас. И помните, Вы ВСЕГДА можете обратится со своими вопросами к автору курса по E-mail.
Если у Вас Всё готово, можете переходить к организационному разделу.
Создание серверных приложений на языке PERL
Ускоренный учебный курс
Список
СписокЗадает список, позволяющий выбрать одну (или несколько) опций из списка. Его значение всегда передается, т.к. всегда хотя бы одно выбрано.
Список создается тегом