Форумы в Интернете можно встретить сплошь и рядом.Ни один уважающий себя сайт не обходится без них. Форум дает возможность узнать мнение посетителей о сайте и о том,что они думают об авторе и о его творениях :). Форум,пример которого я здесь приведу не очень сложный,но он обеспечивает все необходимые функции.Для лучшего понимания имеет смысл разбить его на несколько частей,объяснить каждую в отдельности,а затем объединить все вместе.
Данный форум состоит из следующих частей: * Главная страница-вывод списка топиков. * Создание нового топика и запись в файл. * Создание ответа на топик и запись в файл. Начнем не с главной страницы,потому что она обобщает всю информацию,а с середины-добавления нового топика. Добавление нового топика. Сначала в директории 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> Home</font></a> <p><form action="$cgi/webforum.cgi" name="newtop" method="GET"> <table width=60% align=center bgcolor="e6e8fa"> <tr><td> <tr><td>Your nick:<td><input type="text" name="nick" size=20> <tr><td>Topic name:<td><input type="text" name="theme" size=20> <tr><td><input type="hidden" name="action" value="ok"> <tr><td colspan=2> Message:<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>Post reply</font></a>n"; print FILE " <a href="$cgi/webforum.cgi"><font face="ferdana" size=3> Home</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>Please,go back and try again <p><a href="$cgi/webforum.cgi?action=newtop"><font face="ferdana" size=3> Back</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>Your message is added. <p><a href="$cgi/webforum.cgi"><font face="ferdana" size=3> View topics</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>Home</font></a> <p><form action="$cgi/webforum.cgi" name="reply" method="GET"> <table width=60% align=center bgcolor="e6e8fa"> <tr><td> Your nick:<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> Message:<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>Please,go back and try again <p><a href="$cgi/webforum.cgi?action=reply&file=$page.html"> <font face="ferdana" size=3>Back</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>Your message is added. <p><a href="$cgi/webforum.cgi"><font face="ferdana" size=3> View topics</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>New topic</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); |
Ну вот,вроде бы и все. Конечно,я не реализовал все возможности.Можно добавить регистрацию пользователя,возможность редактирования сообщений и т.д.В дальнейшем я планирую доработать этот форум и сделать его более продвинутым. В данный момент моей целью было объяснить,как это работает. Автор: Ковязин Дмитрий, P-Lib(p-lib.narod.ru) |