Привет кул-хацкер! Да,
вижу, ты неплохо раскачал свою страничку в
инете. Поставил себе счётчик, ksnews. В общем,
все как надо. Но тебе наверняка хотелось
поговорить, познакомиться с твоими
посетителями. Можно было бы засунуть чат на
твою хоум пагу, но мы для начала разместим
Forum, где можно будет оставлять сообщения,
отзывы, да всё, что хочешь! Итак, сначала
создадим Html файл, например forum.html. Эта
страничка будет стартовой. Кстати, писать
мы будем на Perl. Вообще я считаю, что Perl –
лучший язык для создания Интернет
приложений. Из forum.html мы будем вызывать
скрипт, отображающий все сообщения. Вот сам
файл:

<HTML>
<HEAD>
<TITLE>Forum</TITLE>
</HEAD>
<BODY BGCOLOR="#ffffff" TEXT="#400080"></BODY>
<CENTER>
<H1>FORUM</H2>
</CENTER>
<FONT size="3" COLOR="black">
Добро пожаловать на Forum v1.0<HR>
<UL>

Теперь вызываем скрипт —
forum.cgi, который будет выводить все сообщения.
Помести его, например, в папку cgi-bin

<!—#exec cgi="/cgi-bin/forum.cgi"—>
</UL>
<BR><HR>

Ну, а дальше форма для
нового сообщения

<B>Добавь своё
сообщение:</B><BR>
<FONT COLOR="red">ВНИМАНИЕ! Запрещается
использовать Html теги, а также символы ‘+’ и
‘|’.</FONT>
<FORM ACTION="/cgi-bin/dobavit.cgi" METHOD="GET">
<B>Имя<SUP>*</SUP>:</B><BR>
<INPUT TYPE="TEXT" NAME="name" SIZE="58"><BR>
<B>E-mail:</B><BR>
<INPUT TYPE="TEXT" NAME="mail" SIZE="58"><BR>
<B>Subject<SUP>*</SUP>:</B><BR>
<INPUT TYPE="TEXT" NAME="subject" SIZE="58"
maxlength="80"><BR>
<B>Сообщение:</B><BR>
<TEXTAREA TYPE="TEXT" NAME="main" ROWS="6" COLS="50"></TEXTAREA><BR>
<INPUT TYPE=SUBMIT VALUE="Post ">
<INPUT TYPE="RESET" VALUE="Clear">
</FORM><HR>
Forum coded by ‘Здесь твоё имя’<SUP>&copy</SUP>2001.
<A HREF="mailto:здесь твой e-mail">e-mail</A>
</FONT>
</HTML>

В теге Body ты можешь
изменить цвет текста, ссылок и фона (для
этого нужно присвоить значения
соответствующим параметрам, например для
красного фона нужно BGCOLOR="#ffffff"
заменить на BGCOLOR="#ff0000" или BGCOLOR="red")
Как ты заметил, мы запрещаем вводить хтмл
теги и символы ‘+’ и ‘|’. Это обусловлено
специфическим форматом нашей базы данных (
forum.dat — далее ‘б.д.’), впрочем скоро ты сам в
этом убедишься. Теперь перейдём к скрипту
forum.cgi. Это самый главный скрипт, потому что
без него никто не увидит сообщений. Мои
комментарии будут следовать после символа
‘#’. Вот его код:

#!/perl/bin/perl #Это путь к Perl.
Очень важно указать его правильно!
srand; #Повышаем фактор случайности при
генерации случайных чисел
print "Content-type: text/html\n\n"; #Будет выводиться
Html файл
open(FORUM,"forum.dat"); #Открываем базу данных.
Кстати она должна
#находится в той же директории, что и скрипт
$line=0;
while (<FORUM>) { #Читаем по одной строке из б.д.
и записываем её в $_
$line++;
$_=~ s/\|(.*)\|(.*)\|(.*)\|(\d*)$//;

Ну а эта строка одна из
самых главных. В нашей б.д. данные будут
записываться в формате сабджект | само
сообщение | ник | e-mail | время. 

Теперь понятно, почему не
допускаются символы ‘|’, иначе у нас бы всё
перепуталось. Поэтому мы применяем поиск
по шаблону для извлечения этих параметров.
Знак ‘.’ означает любой символ, а знак ‘*’
означает повторение 0 или более раз. Круглые
скобки сохраняют, стоящее в них выражение в
переменной $1, $2, $3 и т.д. ‘\d’ означает одну
цифру. Это и есть время, которое мы будем
хранить в виде длиннющего числа ( по
Гринвичу ) и потом преобразовывать его в
понятный для нас формат. Перед ‘|’ мы
ставим косую черту, потому что есть такой
метасимвол, и тем самым мы говорим Perl, что
хотим использовать обыкновенный символ. В
итоге в $_ останется только сабжект.

$message=$1; #Записываем
значения в переменных $1, $2, $3, $4, в другие
#т.к. они обнулятся при следующем поиске.
$nickname=$2;
$email=$3;
$time=localtime($4); #Преобразовывать время в
понятный для нас формат
$_=~s/(^\+*)//;

Если строка в начале б.д.
содержит ‘+’, то она является ответом,
причем, чем больше плюсов, тем больше
отступов нужно сделать ( т.е. это будет ответ
на ответ и т.д. ) Поэтому мы сохраняем строку
с плюсами в $1 (если строка пустая она все
равно сохраняется).

$col=$1;
if (length($col)==0) { #Проверяем есть ли в начале
плюсы
if ($flag) {$flag—} else {print "<BR>"}
print "<li type=disc>";
} else {
print "<UL>" x length($col); #Отступаем столько
раз, сколько плюсов в строке
if (length($col)==1) {print "<li type=circle>"} else {print
"<li type=square>"}
$flag=2;
}
$ln=$line;
for ($i=1;$i<10;$i++) {
$k=int rand(9);
$ln=$k.$ln;
}

Дальше мы передадим
скрипту answer ключ code со значением номера
строки, но чтобы никто не догадался, мы
просто добавим в начало 9 случайных чисел (для
повышения фактора случайности мы в начале
скрипта вызвали функцию srand). Итак “зашифрованный”
номер строки находится в $ln.

print "<A HREF=\"/cgi-bin/answer.cgi?code=$ln\">$_</A>";
if ($message) {print "<BR>"} else {print "&nbsp;(пустое)<BR>"}
print <<"EOF";
<FONT size="3">
$nickname</FONT>
&nbsp;&nbsp;<FONT size="2"><I>$time</I></FONT></li><BR>
EOF
if ($flag==2) {print "</UL>" x length($col);
$flag—;}
;
}

В самом конце мы выводим
на экран ссылку, указывающую на скрипт
answer.cgi, и пишем ‘пустое’, если сообщения нет
(только один сабджект). Строкой ниже пишем
ник чела и дату. Теперь разберём скрипт
dobavit.cgi, который будет вызываться при
нажатии на кнопку ‘Post’ в forum.html. Форма
передаст скрипту параметры в формате ключ=значение.
Он должен добавить в б.д. сообщение. В нём
ничего сложного не будет, короче вот он:

#!/perl/bin/perl #С этим ты уже
знаком
use CGI qw(param); #Подключаем модуль Cgi.pm
#Он нам поможет извлекать значения из
ключей
print "Content-type: text/html\n\n";
$name=param("name"); #Извлекаем значения ключей,
передаваемых формой
$email=param("mail");
$subject=param("subject");
$mess=param("main");
proverka(); #Вызываем функцию proverka
open(FORUM,">>forum.dat"); #Открываем б.д. в
режиме дополнения
print FORUM "$subject |"."$mess|".$name."|".$email."|".time."\n";
#Записываем извлечённые значения в уже
известном нам формате в файл
print <<"EOF"; #Выводим сообщение об
успешном завершении операции.
<HTML>
<TITLE>Регистрация прошла успешно</TITLE>
<FONT Size="4">
Ваши данные были занесены в базу данных.<BR>
Нажмите <A HREF="/forum.html">сюда</A>,
чтобы вернуться на главную страницу.
</FONT>
</HTML>
EOF;

sub runaway { #Это функция
экстренного выхода с сообщением об ошибке
print "<H4>Вы не заполнили необходимые
поля, либо заполнили их неправильно!</H4>";
print "<A HREF=\"/forum.html\">обратно</A>";
exit;
}

sub proverka { #А вот и функция
proverka, которую мы вызывали выше
#Будет проверять имя, сабджект и т.д. на
наличие ‘+’, ‘|’ и тегов
$name=~s/\|//; #Удалить все символы ‘|’ из имени
$name=~s/<[^>]*>//gs; #Удалить все Html теги из
имени
$name=~s/^\s+//; #Удалить все символы ‘+’, стоящие
в начале имени,
$name=~s/\s+$//; #Удалить все пробелы в конце имени
if (not $name) {runaway()} #Если $name — пустая строка, то
экстренный выход
$email=~s/<[^>]*>//gs; #Удалить все Html теги из e-mail
$email=~s/\|//; #Удалить все символы ‘|’ из e-mail
$subject=~s/<[^>]*>//gs; #Удалить все Html теги из
сабджекта
$subject=~s/^\s+//; #Удалить все символы ‘+’,
стоящие в начале сабджекта,
$subject=~s/\s+$//; #Удалить все пробелы в конце
сабджекта
$mess=~s/^\s+//; #Удалить все пробелы в начале
сообщения
$mess=~s/\s+$//; #Удалить все пробелы в конце
сообщения
if (not $subject) {runaway()} #Если $subject-пустая строка, то
экстренный выход
$mess=~s/^\+*//; $mess=~s/\|//g; $mess=~s/<[^>]*>//gs;
#Провести все проверки (на символы ‘+’ , ’|’
и Html теги) с сообщением
}

Небольшое пояснение к
функции proverka:

В ней мы применяем поиск
по шаблону. Тут встречается метасимвол ‘\s’.
Я лучше сразу дам тебе описание всех
метасимволов:

\w — алфавитно-цифровой или
‘_’ символ
\W — не алфавитно-цифровой или ‘_’ символ
\s — один пробел
\S — один не пробел
\d — одна цифра
\D — одна не цифра
Обратите внимание что все это "один"
символ. Для обозначения последовательности
применяйте модификаторы. Так:
\w+ — слово
\d+ — целое число
[+-]?\d+ — целое со знаком
[+-]?\d+\.?\d* — число с точкой
Кроме того существуют мнимые метасимволы.
Обозначающие не существующие символы в
месте смены значения. Такие как:
\b — граница слова
\B — не граница слова
\A — начало строки
\Z — конец строки
\G — конец действия m//g

Я надеюсь, ты понял, что
при открытии forum.html скрипт forum.cgi выведет все
сообщения в виде ссылок на скрипт answer.cgi (вот
завернул!). Я уже говорил, что ему (answer.cgi)
передаётся ключ code со значением номера
строки с сообщением. Это сделано, чтобы,
если юзер захочет ответить на какую-нибудь
фразу, то ему нужно будет только на неё
нажать. По сути, этот скрипт выводит форму с
такими же полями, как и на forum.html. Ну ладно,
ближе к делу. Вот сам скрипт:

#!/perl/bin/perl
use CGI qw(param);
print "Content-type: text/html\n\n";
$number=param("code"); #Считываем значение ключа
code
substr($number,0,9)=""; #Убираем маскировку 🙂
open(FORUM,"forum.dat"); #Открываем б.д.
$line=0;
while (<FORUM>) {
$line++; #Считаем страницы
if ($line==$number) { #Если номера совпали
$_=~ s/\|(.*)\|(.*)\|(.*)\|(\d*)$//; #Опять извлекаем
элементы
$message=$1; #Сообщение
$nickname=$2; #Ник
$email=$3; #e-mail
$time=localtime($4); #Время
$sub=$_; #Записываем сабджект в отдельную
переменную
$sub=~s/(^\+*)//; #Убираем плюсы с начала строки
$value="Re: ".$sub; #Создаём значение по
умолчанию
}}

if (not $message) {$message=$sub} #Если
сообщение пустое, то вместо него
#используем сабджект
print <<"EOF"; #Выводим на экран форму
<HTML>
<TITLE>$sub</TITLE>
<BODY TEXT="black">
<CENTER>
<H1>$sub</H1>
</CENTER>
<HR><BR>
<FONT SIZE="4" COLOR="black">Posted by
<A HREF="mailto:$email">$nickname</A>
on&nbsp;<FONT SIZE="3"><I>$time</I></FONT><BR><BR>
$message</FONT><BR><BR>
<HR>
<H2>Написать ответ</H2>
<FONT COLOR="red">ВНИМАНИЕ! Запрещается
использовать Html теги, а также символы ‘+’ и
‘|’.</FONT>
<FORM ACTION="/cgi-bin/write.cgi" METHOD="GET">
<INPUT TYPE=HIDDEN NAME="code" VALUE=$number><BR>
<B>Имя<SUP>*</SUP>:</B><BR>
<INPUT TYPE="TEXT" NAME="name" SIZE="58"><BR>
<B>E-mail:</B><BR>
<INPUT TYPE="TEXT" NAME="mail" SIZE="58"><BR>
<B>Subject<SUP>*</SUP>:</B><BR>
<INPUT TYPE="TEXT" NAME="subject" SIZE="58"
MAXLENGTH="80" VALUE="$value"><BR>
<B>Сообщение</B><BR>
<TEXTAREA TYPE="TEXT" NAME="main" ROWS="6" COLS="50">
</TEXTAREA><BR>
<INPUT TYPE=SUBMIT VALUE="Post ">
<INPUT TYPE="RESET" VALUE="Clear">
</FORM><BR><HR>
<A HREF="/forum.html">Или дави сюда, чтобы
вернуться</A>
EOF
;

В форме сложного ничего
нет, но тут появился HIDDEN. Это такое же поле,
как остальные, только его не видит
пользователь, и оно в тайне передаёт
следующему скрипту ключ code, т.е. номер
страницы. А передаёт оно этот ключ скрипту
write.cgi, который записывает полученные данные
в б.д. Вот его содержимое:

#!/perl/bin/perl
use CGI qw(param);
print "Content-type: text/html\n\n";
$line=param("code"); #Получаем значения
$name=param("name");
$email=param("mail");
$subject=param("subject");
$mess=param("main");
proverka(); #Вызываем функцию проверки
open(FORUM,"forum.dat"); #Открываем б.д.
open(DATA,">murof.dat"); #Создаём временный
файл
$ln=0;
while (<FORUM>) {
$ln++;
if ($ln==$line) { #Находим нужную строку
$_=~/(^\+*)/; #Извлекаем начальные плюсы
$col=length($1);
$col++;
$col="+" x $col; #Создаём строку из плюсов,
которых теперь на 1 больше
print DATA $_; #Записываем прочитанную из б.д.
строку
print DATA $col.$subject." |".$mess."|".$name."|".$email."|".time."\n";
#Записываем новую
} else {print DATA $_} #если строка не та, то просто
записываем прочитанную
}
close(FORUM); #Всё закрываем
close(DATA);
rename("murof.dat","forum.dat"); #Переименовываем
временный файл в б.д.
print <<"EOF"; #Выводим сообщение об
успешном завершении операции
<HTML>
<TITLE>Регистрация прошла успешно</TITLE>
<FONT Size="4">
Ваши данные были занесены в базу данных.<BR>
Нажмите <A HREF="/forum.html">сюда</A>,
чтобы вернуться на главную страницу.
</FONT>
</HTML>
EOF;

#Здесь нужно вставить
описание функции RunAway и Proverka из dobavit.cgi

Ну, вот и всё! Форум готов.
Теперь ты смело можешь его залить на сайт и
гордиться. И мой тебе совет: если ты плохо
варишь в Perl, то перечитай эту статью и
разбери каждую строку, и я уверен, что ты
скоро сам напишешь форум ещё лучше, чем этот!
Если будут вопросы, то пишите на fork@e-mail.ru

Удачи, Fork!

Оставить мнение

Check Also

Скрытая сила пробела. Эксплуатируем критическую уязвимость в Apache Tomcat

В этой статье мы поговорим о баге в Apache Tomcat, популярнейшем веб-сервере для сайтов на…