Форумы в Интернете можно встретить сплошь и рядом.Ни один уважающий себя сайт не
обходится без них. Форум дает возможность узнать мнение посетителей о сайте и о
том,что они думают об авторе и о его творениях :). Форум,пример которого я здесь
приведу не очень сложный,но он обеспечивает все необходимые функции.Для лучшего
понимания имеет смысл разбить его на несколько частей,объяснить каждую в
отдельности,а затем объединить все вместе.
Данный форум состоит из
следующих частей:
* Главная страница-вывод списка топиков.
*
Создание нового топика и запись в файл.
* Создание ответа на топик и запись
в файл.
Начнем не с главной страницы,потому что она обобщает всю
информацию,а с середины-добавления нового топика.
Добавление нового
топика.
Сначала в директории cgi-bin веб-сервера создадим каталог
html,куда будут записываться все сообщения. Сразу оговорюсь,что все сообщения
пишутся в html-файл:сначала топик и сообщение,затем к нему дописываются ответы.
По ходу дела все будет понятно.
Сгенерируем форму для добавления новой темы
и сообщения.
#!/usr/local/bin/perl #Webforum.cgi version 1.01
$request=$ENV{′REQUEST_METHOD′}; $content=$ENV{′CONTENT_LENGTH′};
$cgi="url/cgi-bin"; $url="url/cgi-bin/html";
$dir="/usr/local/apache/cgi-bin/html";
print
"Content-type:text/htmlnn"; print <<HTML;
<html><head><style>a:link {text-decoration:none;
}</style></head><body> <h4 align=center><font
color="0000ff">New topic</font></h4> <p
align=right><a href="$cgi/webforum.cgi"><font face="ferdana"
size=3> <b>Home</b></font></a>
<p><form action="$cgi/webforum.cgi" name="newtop" method="GET">
<table width=60% align=center bgcolor="e6e8fa">
<tr><td> <tr><td><b>Your
nick:</b><td><input type="text" name="nick" size=20>
<tr><td><b>Topic name:</b><td><input
type="text" name="theme" size=20> <tr><td><input
type="hidden" name="action" value="ok"> <tr><td colspan=2>
<b>Message:</b><p> <textarea cols=40 rows=15
name="post" wrap="virtual"></textarea> <tr><td
colspan=2><input type="submit" value="Submit"></table> HTML
|
Если данные введены в форму получаем их и
декодируем.
@pairs = split(/&/, $query); foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair); $name =~ tr/+/ /; $name =~
s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $name =~ s///g; $name
=~ s/<([^>]|n)*>//g; $value =~ tr/+/ /; $value =~
s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ s///g;
$value =~ s/</</g; $value =~ s/>/>/g; $value =~ s/cM/
/g; $value =~ s/|/ /g; $value =~ tr/ / /s; $value =~
s/<([^>]|n)*>//g; $value =~ s/"/"/g;
$value=~s/(http://+S)/<A href="$1">$1</A>/g; $input{$name} =
$value; }
$nick=$input {′nick′}; $theme=$input {′theme′};
$message=$input {′post′};
#Create new topic.
#Открываем
каталог и читаем его содержимое. Файлы в каталог записываются в виде
#001.html,002.html и т.д.То есть,каждый вновь записываемый файл,увеличивается
#на единицу.Это делается следующим образом.
opendir (DIR,"$dir");
while (@mes=readdir (DIR)) { foreach $mes(@mes) { $count=@mes;
$count++; $page="00".($count-2); }
# ($count-2)-это для
того,чтобы не считать подкаталоги типа "." и "..". # Проверяем,не являются ли
поля формы пустыми. Если нет-открываем файл на запись # и пишем информацию.
if ($nick ne "" && $theme ne "" && $message ne "") {
open (FILE,">$dir/$page.html"); print FILE
"<html><head><style> a:link {text-decoration:none; }
</style><title>$theme</title>n"; print FILE "<meta
name="author" content="$nick"></head>n"; print FILE "<body
bgcolor="f6f8fa">n"; print FILE "<p align=right><a
href="$cgi/webforum.cgi?action=reply&file=$page.html">n"; print FILE
"<font face="ferdana" size=3><b>Post
reply</b></font></a>n"; print FILE " <a
href="$cgi/webforum.cgi"><font face="ferdana" size=3><b>
Home</b></font></a><p>n"; print FILE "<table
width=90% cellpadding=0 cellspacing=0 border=1>n"; print FILE
"<tr><td align=center width=150 bgcolor="D5E6E1">< font
face="Arial" size=2 color="808080">Author</font>n"; print FILE
"<td bgcolor="D5E6E1"><font face="serif" size=2
color="0000ff">Topic:</font>n"; print FILE "<font face="serif"
size=2 color="ff0000">$theme</font></td></tr>n"; print
FILE "<tr><td rowspan=2 bgcolor="D5E6E1" align=center> <font
face="serif" size=3 color="ff0000">$nick</font></td>n"; print
FILE "<td bgcolor="e6e8fa" height=30> <font face="serif" size=1
color="000080">Posted:",scalar
localtime,"</font></td></tr>n"; print FILE
"<tr><td bgcolor="f7f7f7"><font face="serif" size=2
color="000080">
$message</font></td></tr></table>n"; close
(FILE); } else {
#Если одно из полей формы осталось
пустым-выдаем ошибку.Это делается для того,чтобы # не создавать пустые файлы,не
содержащие информации.Perl′у все равно,что писать :)
print
"Content-type:text/htmlnn"; print <<HTML; <p> <p>
vp> <body bgcolor="e6e8fa"> <h4
align=center>Sorry,you didn′t enter your nick or message! </h4>
<p><center><b>Please,go back and try again</b>
<p><a href="$cgi/webforum.cgi?action=newtop"><font
face="ferdana" size=3> <b>Back</b></font></a>
</center> HTML exit; } } closedir (DIR); }
# Если все прошло нормально,выносим пользователю благодарность.Новый
топик создан.
print "Content-type:text/htmlnn"; print
<<HTML; <p> <p> <p> <body
bgcolor="e6e8fa"> <h4 align=center>Thank you,<font
color="0000ff">$nick!</font></h4>
<p><center><b>Your message is added.</b>
<p><a href="$cgi/webforum.cgi"><font face="ferdana"
size=3> <b>View
topics</b></font></a></center> HTML
</BODY> </HTML> HTML
|
Добавление ответа на топик.
Добавление ответа почти ничем не отличается от добавления
топика,единственное отличие- нужно передать адрес страницы,чтобы скрипт
знал,куда писать ответ.А он содержится в файле топика.Если посмотреть чуть
выше,можно увидеть ссылку <a
href="$cgi/webforum.cgi?action=reply&file=$page.html">Post
reply</a> В ней и передается адрес страницы.
Генерируем форму:
# Сначала читаем файл в массив.Это делается для того,чтобы поместить
его во фрейм ниже формы # на тот случай,если кто-то захочет вставить цитату из
предыдущих сообщений.
$page=$input {′file′};
open
(FILE,"$dir/$page"); @data=<FILE>; close (FILE);
print
"Content-type:text/htmlnn"; print <<HTML;
<html><head><style>a:link {text-decoration:none;
}</style></head><body> <h4 align=center><font
color="0000ff">Post reply</font></h4> <p
align=right><a href="$cgi/webforum.cgi"> <font face="ferdana"
size=3><b>Home</b></font></a> <p><form
action="$cgi/webforum.cgi" name="reply" method="GET"> <table width=60%
align=center bgcolor="e6e8fa"> <tr><td>
<br><b>Your nick:</b><td>vinput type="text" name="nick"
size=20> <tr><td><input type="hidden" name="type"
value="reply"> <tr><td><input type="hidden" name="action"
value="ok"> <tr><td><input type="hidden" name="file"
value="$page"> <tr><td colspan=2>
<b>Message:</b><p> <textarea cols=40 rows=15
name="post"></textarea> <tr><td colspan=2><input
type="submit" value="Submit"></table>
<p><center><iframe src="$dir/$page" width=90%
height=300></iframe></center> HTML
#Reply to topic.
# Снова проверяем,чтобы поля формы не были пустыми. Если все в
порядке,открываем файл, # содержащий топик на добавление и дописываем ответ.
if ($nick ne "" && $message ne "" ) { open
(FILE,">>$dir/$page"); print FILE "<table width=90% cellpadding=0
cellspacing=0 border=1>n"; print FILE "<tr><td rowspan=2
bgcolor="f7f7f7" align=center width=150> <font face="serif" size=3
color="0000ff">$nick</font></td>n"; print FILE "<td
bgcolor="e6e8fa" height=30><font face="serif" size=1 color="000080">
Posted:",scalar localtime,"</font></td></tr>n"; print
FILE "<tr><td bgcolor="f7f7f7"><font face="serif" size=2>
$message</td></tr></table>n"; close (FILE); close
(FILE); } else {
# Если одно из полей осталось пустым-выдаем ошибку.
print "Content-type:text/htmlnn"; print <<HTML;
<p> <p> <p> <body bgcolor="e6e8fa">
<h4 align=center>Sorry,you didn′t enter your nick or message!
</h4> <p><center><b>Please,go back and try
again</b> <p><a
href="$cgi/webforum.cgi?action=reply&file=$page.html"> <font
face="ferdana" size=3><b>Back</b></font></a>
</center> HTML exit; }
# Снова выносим
благодарность посетителю.Ответ добавлен.
print
"Content-type:text/htmlnn"; print <<HTML; <p> <p>
<p> <body bgcolor="e6e8fa"> <h4 align=center>Thank
you,<font color="0000ff">$nick!</font></h4>
<p><center><b>Your message is added.</b>
<p><a href="$cgi/webforum.cgi"><font face="ferdana"
size=3> <b>View
topics</b></font></a></center> HTML
</BODY> </HTML> HTML
|
Главная страница.
Ну вот
мы,наконец,добрались и до главной страницы.Она выводит список топиков,дату
последнего ответа на каждый топик,количество ответов,имя создателя топика.Она
заслуживает отдельного описания.
Данные на экран выводятся в виде
html-таблицы.
print "Content-type:text/htmlnn"; print <<HTML;
<html><head><title>Webforum ver1.01</title>
<style>a: {text-decoration:none; } </style></head>
<body bgcolor="e6e8fa"> <p> <p><h4
align=center><font color="0000ff">Webforum</font></h4>
<p align=right><a href="$cgi/webforum.cgi?action=newtop">
<font face="ferdana" size=3><b>New
topic</b></font></a> <p><table width=700
cellpadding=0 cellspacing=0 border=1> <tr bgcolor="D5E6E1"><td
align=center width=300 height=50> <font face="arial" size=2
color="0000ff">Topic name</font></td> <td align=center
width=150 height=50><font face="arial" size=2 color="0000ff"> Topic
starter</font></td> <td align=center width=50 height=50>
<font face="arial" size=2
color="0000ff">Replies</font></td> <td align=center
width=200 height=50> <font face="arial" size=2 color="0000ff">Last
post</font></td></tr> HTML
# С этим,думаю,все
понятно.А теперь более подробно о том, как получить всю эту информацию. #
Открываем каталог и читаем сообщения в массив.
opendir (DIR,"$dir");
while (@mes=readdir(DIR)) { foreach $mes (@mes) {
# Каждый файл
в каталоге открываем и читаем в массив.
if (!-d "$dir/$mes" &&
"$mes" ne "." && "$mes" ne "..") {
$mtime=localtime((stat("$dir/$mes"))[9]);
open (FILE,"$dir/$mes");
@lines=<FILE>; close (FILE);
# Теперь в каждом файле с
помощью регулярных выражений ищем тему топика,имя автора топика # и количество
ответов.
foreach $line (@lines) { if ($line=~
/<title>(.*?)</title>/is) { $title=$1; } if ($line=~
/content="(.*?)"/is) { $name=$1; }
# Количество ответов помещаем
в массив reply,отнимая единицу,так как первое сообщение-это # сообщение автора
топика.
if ($line=~ /^<table(s*)(.*?)>$/i) { $reply=$1;
push (@reply,$reply); $char=@reply-1; } }
# Печатаем
данные в таблицу,после каждой итерации очищая массив reply,чтобы ответы на #
каждый топик не складывались после каждой итерации.
print
<<HTML; <tr bgcolor="f7f7f7"><td height=30><a
href="$url/$mes"> <font face="serif"
size=2>$title</font></a></td> <td align=center
height=30><font face="serif" size=2>$name</font></td>
<td height=30 align=center>$char</td> <td height=30
align=center><font face="serif"
size=2>$mtime</font></td></tr> HTML splice
(@reply); } } }
print "</table>n"; closedir (DIR);
|
Ну вот,вроде бы и все.
Конечно,я не реализовал все возможности.Можно добавить регистрацию
пользователя,возможность редактирования сообщений и т.д.В дальнейшем я планирую
доработать этот форум и сделать его более продвинутым. В данный момент моей
целью было объяснить,как это работает