<% ASP на блюдечке %>. Часть 10

Форум своими силами (продолжение)

Рубен Садоян, rouben@iname.com

Введение

Что же такое форум

Из чего состоит типичная форум-система

Постановка задачи

Что нам понадобится

Создание и подготовка базы данных

Просмотр списка сообщений в режиме администрирования (файл Admin-List.asp)

Редактор сообщения (файл Edit-Del.asp)

Отправка сообщения (файл Post.asp)

Заключение

Введение

В предыдущей статье серии «<% ASP на блюдечке %>» мы рассмотрели процесс создания такого важного компонента современного Интернета, как форум и конференция. Как и было обещано, предметом настоящей статьи станут инструменты контроля и администрирования форум-системы, то есть все то, что лежало в рассмотренной нами главной страничке под ссылкой: «Для администрирования системы жми сюда»  (см. рис. 1). Попросту говоря, в данной статье рассматривается процесс создания Web-основанной системы управления форумом. И хотя в общем случае решить эту задачу возможно и с привлечением других средств (например, написанием программы на C++), тем не менее именно Web-интерфейс в данном случае остается наиболее удобным решением. Однако не будем забегать вперед, а для лучшего представления задачи повторим основы создания форума.

В начало В начало

Что же такое форум

Для начала давайте вспомним концепцию простейшей форум-системы с точки зрения потенциального клиента, что позволит нам в дальнейшем очертить задачу построения форума и для программиста. В данном случае нам прежде всего необходимо обратить внимание на вопросы управления форумами и задуматься над возможностями  автоматизации этих процессов. Предположим, мы уже знаем, что такое форум, более того, можем сами создавать форум-систему (нам это известно из предыдущей статьи). Давайте еще раз попытаемся упорядочить свои собственные представления о форуме. Обратим особое внимание прежде всего на функции администрирования форум-систем.

Итак, во-первых, как нам известно, форум — это некая область экрана (окна браузера), где различные его участники (будем называть их пользователями форум-системы или просто пользователями) могут излагать свои мысли на заданную тему, придавая им форму текстовых сообщений. Просматривая сообщения, каждый пользователь волен написать сообщение в ответ на чье-либо уже написанное сообщение, которое, в свою очередь, тоже может являться ответом на сообщение и т.д.

Обобщая, можно сказать, что форум представляет собой двухмерный поток текстовых сообщений. Под вторым измерением следует понимать сообщения-ответы, ответы на ответы и т.д.

Не правда ли, для нас с вами концепция форума стала гораздо понятнее и доступнее? Теперь можно переходить к рассмотрению и некоторых отличительных особенностей форумов. Конечно, это не догма, и не все форумы обладают такими особенностями, однако все они (эти особенности), как правило, присутствуют в современных форум-системах.

В начало В начало

Из чего состоит типичная форум-система

Во-первых, это система идентификации пользователей, призванная регистрировать имя (псевдоним, nickname), пароль, электронный адрес и т.д. пользователя для обеспечения его уникальности в форум-системе.

Во-вторых, это, как правило, система управления форумом, позволяющая осуществлять контроль за потоком текстовых сообщений. В современных системах данная функция возложена на так называемых модераторов или форум-менеджеров.

Что же следует понимать под форум-управлением?

Вкратце список функций управления форумами можно представить следующим образом:

  1. Контроль тематики — модератор следит за соблюдением определенной тематики сообщений и удаляет (предупреждает конкретного пользователя о нарушении им заданной тематики) лишние сообщения. Согласитесь, что ненужные сообщения отвлекают от предмета обсуждения (хотя это не мешает существованию форумов с весьма неопределенной тематической ориентацией).
  2. Контроль ненормативной лексики — почти то же самое, что и контроль тематики, но «фильтруются» бранные слова и выражения.
  3. «Поддержка» форума — предумышленная посылка модератором множества сообщений от имени разных пользователей на интригующие читателей форума темы (хотя иногда такое и случается, однако не следует воспринимать форум как место, где можно всегда пообщаться лишь с модератором или с системным администратором).
  4. Организация общего управления форумом — порождение или удаление форумов заданной тематики, контроль, назначение и управление работой модераторов. Выполняется администратором форума.

Список можно и продолжить, но, на наш взгляд, именно без вышеперечисленного не обходится ни одна форум-система.

Во-вторых, как следует из вышеприведенного списка, это система безопасности, обеспечивающая модераторов и администраторов форума доступ к функциям, недоступным для других пользователей.

В-третьих, это система поиска сообщений и (или) их авторов как по тематике, так и по содержимому сообщения.

Конечно, существуют варианты с выбором картинки-смайлика и цвета текстового сообщения, но сути задачи это не меняет.

Совокупность вышеуказанных трех компонентов и является, по существу, самым обычным и зачастую самым распространенным Интернет-форумом.

Как вероятно читатель уже догадался, в разрабатываемой нами системе мы будем отличать контроль и поддержку форумов от организации общего управления ими в первую очередь по ролям. Контроль и поддержка (первые три функции управления) будут относиться к обязанностям модератора каждого конкретного форума, а общее управление (назначение модераторов, создание, редактирование и удаление форумов) — к обязанностям администратора форум-системы. Отсюда следствие: у форум-системы может быть много модераторов, но лишь один администратор.

В начало В начало

Постановка задачи

Теперь, когда мы уяснили, что представляет собой форум-система с точки зрения пользователя, можно переходить и к постановке и формализации программной задачи.

Итак, необходимо разработать:

  1. Базу данных с таблицами сообщений, форумов, пользователей, модераторов и администраторов.
  2. Модули идентификации пользователей.
  3. Поисковый модуль, осуществляющий поиск сообщений.
  4. Систему контроля за потоком текстовых сообщений, позволяющую администратору создавать, редактировать и удалять форумы, а также назначать модераторов с присвоением им соответствующих паролей и имен, а модераторам — удалять или редактировать требуемые сообщения в заданном (своем) форуме.

В предыдущей статье серии мы разработали первые три пункта поставленной нами задачи, а теперь настала пора разобраться и с четвертым (последним) пунктом.

В начало В начало

Что нам понадобится

Предполагается, что читатель знаком с основами ASP- и SQL-программирования (первых частей настоящей статьи для этого будет вполне достаточно). Кроме того, нам потребуется Microsoft Access 97 или 2000, какой-нибудь HTML или текстовый редактор (рекомендую использовать Macromedia Dreamweaver UltraDev 4.0) и немного терпения.

В начало В начало

Создание и подготовка базы данных

Создадим три таблицы: таблицу пользователей (ForumUsers), таблицу форумов (ForumsTable) и таблицу текстовых сообщений (MessagesTable). Представим себе их взаимосвязь следующим образом: Файл Images\DB.gif

Таблица ForumUsers будет служить для хранения имен и паролей администраторов системы, и ее редактирование не будет доступно непосредственно с помощью Web-интерфейса.

Таблица ForumsTable будет хранить информацию о доступных форумах, их именах и паролях доступа их модераторов и может редактироваться непосредственно с помощью Web-интерфейса в режиме администрирования.

Таблица MessagesTable будет содержать весь поток всех сообщений участников всех форумов и, разумеется, тоже будет пополняться с помощью Web-интерфейса в обычном режиме и редактироваться с помощью Web-интерфейса в режиме администрирования.

Теперь, когда база данных готова, можно приступать к созданию и самой системы администрирования форума.

Универсальный набор функций (файл common-admin.asp)

Прежде чем приступить к разработке самой системы управления форумом, вынесем все типовые функции, которые нам понадобятся многократно, в один файл, который по мере необходимости будем впоследствии «включать» в разрабатываемые странички. Давайте разберемся, что же нам понадобится?

Во-первых, это заголовок и «концевик» HTML-файлов наших ASP-страниц (их придется создавать достаточно часто); во-вторых, это функции соединения и закрытия соединения с базой данных; в-третьих, функция, упорядочивающая дочерние сообщения (сообщения ответы на сообщения), функция посылки уведомления пользователям по электронной почте, функция выбора последнего введенного значения, функция изменения цвета для раскраски строк таблиц и функция контроля уровня доступа:

<%  
 option explicit  
 response.buffer=true  
 response.write "<meta charset='visual'>"  
   
 dim line  
 line = "<img src='images/line.gif' width=600 height=1><br><br>"  
   
 Sub Header()  
   Response.Write "<head><meta http-equiv='Content-Type' content='text/html; charset=windows-1251'>"  
   Response.Write "<TITLE>ASP Форум (Администрирование)</TITLE>"  
   Response.Write "</HEAD><body>"  
   Response.Write "<table border=0 cellpadding=0 cellspacing=0>"  
 End Sub  
   
 Sub admin()  
  Response.Write "<br><br><A HREF='administration/main.asp'>-----------</a>"  
 End Sub  
   
 Response.Buffer = true  
   
 dim dsn,conn,rs,sql  
 dsn = "DBQ=" & Server.Mappath("../Data/Forum.mdb") & ";Driver={Microsoft Access Driver (*.mdb)};"  
   
 Sub Connect()  
   set conn = server.createobject("adodb.connection")  
   set rs = server.createobject("adodb.recordset")  
   conn.open dsn  
End Sub  
   
 Sub Close()  
   rs.close  
   set rs = nothing  
   conn.close  
   set conn = nothing  
 End Sub  
   
 Sub Footer()  
   Response.Write "<tr><td><br>"  
   Response.Write "<img src='images/line.gif' width=600 height=1><br><br>"  
   Response.Write "</body></html>"  
End Sub  
   
 Sub displayMessages(layer,id)  
  dim sql_order,rs_order,image,str,MessageSpacing,mesid,spaceing,tid  
  set rs_order=server.createObject("adodb.recordset")  
  sql_order = "SELECT * FROM MessagesTable WHERE thread_parent = " & id & "and thread_parent <> 0"  
  rs_order.open sql_order,conn  
   
  Do Until rs_order.eof  
    mesid = rs_order("id")  
    name = rs_order("name")  
    email = rs_order("email")  
    subject = rs_order("subject")  
    mesdate = rs_order("mesdate")  
    fid = rs_order("forumID")  
    tid = rs_order("thread_id")  
    image="<img src='../images/arr1.gif' border=0>"  
    str=""  
    spaceing=""  
   
    For MessageSpacing = 1 To layer  
      spaceing = spaceing & "&nbsp;&nbsp;&nbsp;"  
    Next  
   
    str = "<tr><td>"  
    str = str & spaceing & image & "<a href='../show.asp?id=" & mesid &_  
            "&fid="&fid&"&tid="&tid&"'>" & subject & "</a>" & "...." & mesdate   
    str = str & "...." &  name & "&nbsp;<a href='edit-del.asp?action=edit&id=" & mesID &_  
            "&fid="&fid&"&tid="&tid&"'>(Редактировать </a>" &_  
            "<a href='edit-del.asp?action=del&id=" & mesid &_  
            "&fid="&fid&"&tid="&tid&"'> | Удалить) </a>"  
   
    str = str & "</tr></td>"  
    str = str & "</b>"  
   
    Response.Write str   
   
    Call displayMessages(layer+1,mesid)  
   
    rs_order.MoveNext  
  Loop  
   
  rs_order.close  
  set rs_order = nothing  
End Sub              
   
 Sub sendAllFamily(tid,maxid,fid)  
  dim body,email,link,rs_send  
  set rs_send=server.createObject("adodb.recordset")  
  sql="select email,id,thread_id from MessagesTable"  
  sql=sql & " where (thread_id="& tid & " or id="& tid & ") and id<>" & maxid &""  
  sql=sql & "and forumid="&fid&" and isChecked=1"  
  rs_send.open sql,conn  
   
  Do While Not rs_send.eof  
   link="http://localhost/show.asp?fid=" & fid & "&id=" & maxid & "&tid=" & tid  
   email=rs_send("email")  
   response.write email  
    Body = "Поступило новое сообщение на форум"  
    Body = Body & "Адрес поступившего сообщения: "  
    Body = Body &  link  
   
   Dim objCDO  
   Set objCDO = Server.CreateObject("CDONTS.NewMail")  
   objCDO.To = email  
   objCDO.From = "rouben@iname.com"  
   objCDO.Subject = "Уведомление о поступлении сообщения!"  
   objCDO.Body = body  
   objCDO.Send  
     
   rs_send.MoveNext  
  Loop  
   
  rs_send.close  
  set rs_send = nothing  
 End Sub  
   
 Sub maxRec()  
  set rs_maxid=server.createobject("adodb.recordset")  
  sql_maxid = "select max(id) as maxid from MessagesTable"   
  Set rs_maxid = Conn.Execute(sql_maxid)   
  maxid = rs_maxid("maxid")'new id  
  rs_maxid.close  
  set rs_maxid=nothing  
 End Sub  
   
 Function changeColor()  
  If flag = 0 Then  
   flag = 1  
   color = "LightBlue"  
  Else  
   flag = 0  
   color = "White"  
  End if  
 End Function  
   
 Sub secure_general()  
  If session("status") <> "admin" Then  
    Response.Redirect "error.htm"  
 End If  
End Sub  
%>

Остановимся на извлечении идентификатора последнего введенного значения и на функции посылки уведомлений о поступлении нового сообщения по электронной почте. Первая функция попросту извлекает максимальное значение идентификатора сообщения. А так как идентификаторы (identity) таблиц баз данных уникальны и постоянно инкрементируются, то фактически эта функция возвращает идентификатор последнего сообщения. В случае если это действие выполняется непосредственно после добавления в таблицу, а в данном случае это именно так, то извлекаемое значение совпадает с идентификатором последнего введенного значения, то есть последнего сообщения.

По сути, функция посылки уведомительных сообщений о поступлении новых сообщений в цикле по результатам запроса сообщений, авторы которых пожелали получать уведомление по электронной почте, посылает сообщения, используя серверный объект CDONTS. Выборка этих сообщений из таблицы сообщений выглядит следующим образом:

   sql = "select email,id,thread_id from MessagesTable"  
   sql = sql & " where (thread_id="& tid & " or id="& tid & ") and id<>" & maxid &""  
   sql = sql & "and forumid="&fid&" and isChecked=1"   

где флажок isChecked и отражает предпочтение пользователя о посылке уведомления по электронной почте.

Почти все функции и процедуры нам знакомы, за исключением, пожалуй, двух последних. Функция changeColor() позволяет изменять атрибут цвета в зависимости от состояния флажка flag и применяется для раскраски строк таблиц. Процедура secure_general() используется для обеспечения безопасности форум-системы и служит для перенаправления пользователей на страницу с текстом о невозможности доступа к режиму администрирования в случае, если значение сессионной переменной session("status") не равно константе "admin".

Главная страничка — выбор режима администрирования (файл index.asp)

Теперь необходимо создать страничку, в которой пользователь сможет выбрать себе роль администратора или модератора. Для этого необходимы две формы с запросом имени и пароля, контролирующие корректность ввода последних и допускающие вход в систему управления с соответствующими функциями и правами:

<!--#include file="common-admin.asp"-->  
   
<%  
 dim useraction,username,password,forumid  
 useraction=request("action")  
   
 Select Case userAction  
   
   Case "login"  
     username = Trim (request.form("username"))  
     password = Trim (request.form("password"))  
                  
     Call Connect()  
     sql="select username,password from ForumUsers where username='"&username&_  
            "' and password='"&password&"'"  
     rs.open sql,conn  
   
     If rs.eof AND rs.bof Then  
      Response.Write "<b>Проверьте правильность ввода имени и (или) пароля</b><br><br>"  
     Else  
      Session("status") = "admin"  
      Response.Redirect "main.asp"  
     End If  
   
     Call Close()  
                  
   Case "f_login"  
     username=trim(request.form("username"))  
     password=trim(request.form("password"))  
                  
     Call Connect()  
     sql="select forumid,username,password from ForumsTable where username='"&username&"' and password='"&password&"'"  
     rs.open sql,conn  
   
     If rs.eof AND rs.bof Then  
      response.write "<b>Проверьте правильность ввода имени и (или) пароля</b><br><br>"  
     Else  
      forumid = rs("forumid")  
      Session ("status") = forumid  
      Response.Redirect "admin-list.asp?fid="&forumid  
     End If  
                  
     Call Close()  
   
 End Select  
%>  
   
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>ASP - Форум своими силами (Администрирование)</title>  
</head>  
   
<body>  
<table border=1 bgcolor = "#FFCC99">  
   
<form action="index.asp?action=login" method="post">  
   
<tr>  
<td colspan=2 align = center>Администратор форума</td>  
</tr>  
   
<tr align=right><td>Имя:</td>  
<td><input type="text" name="username" size=15 maxlength=10></td>  
</tr>  
   
<tr align=right>  
<td>Пароль:</td>  
<td><input type="password" name="password" size=15 maxlength=10></td>  
</tr>  
   
<tr>  
<td colspan=2 align=center><input type="submit" name="submit" value="Вход"></td>  
</tr>  
   
</form>  
</table>  
   
<br><br>  
   
<table border=1 bgcolor = "#FFCC99">  
   
<form action="index.asp?action=f_login" method="post">  
   
<tr>  
<td colspan=2 align=center>Модератор форума</tr></td>  
<tr align=right>  
<td>Имя:</td>  
<td><input type="text" name="username" size=15 maxlength=10></td>  
</tr>  
   
<tr align=right>  
<td>Пароль:</td>  
<td><input type="password" name="password" size=15 maxlength=10></td>  
</tr>  
   
<tr>  
<td colspan=2 align=center><input type="submit" name="submit" value="Вход">  
</td>  
</tr>  
   
</form>  
</table>  
   
<br><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a>  
   
</body>  
</html>  

Форум-редактор в режиме администрирования (файл main.asp)

Теперь нам будет необходима страничка просмотра всех форумов, а также прикрепленных к ним модераторов, их учетных записей и паролей, причем с возможностью как создания и редактирования форумов, так и их удаления:

<!--#include file="common-admin.asp"-->  
   
<%  
 Call secure_general()  
   
 dim useraction  
 dim username, password, topic, secure  
 dim id, flag, color  
   
 userAction = request("action")  
   
 Select Case userAction  
  Case "add"  
    username = request.form("username")  
    password = request.form("password")  
    topic    = request.form("topic")  
    secure = 0  
   
    Call Connect()  
    sql="select forumname,username,password from ForumsTable where forumname='" & topic &_  
           "' or password='"&password&"'"  
    rs.open sql,conn  
   
    If rs.eof AND rs.bof Then  
     conn.execute("insert into ForumsTable (forumname, username, password, isSecure) " &_  
                           "values('"&topic&"','"&username&"','"&password&"','"&secure&"')")  
   Else  
     response.write "<script>alert('Повтор названия форума или пароля недопустим!')</script>"  
   End If  
   
   Call Close()  
 End Select  
   
 Call Connect()  
 sql="select * from ForumsTable order by forumid"  
 rs.open sql,conn  
%>       
   
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>ASP - Форум своими силами – Форум-редактор</title>  
<script>  
   
function IsDel()  
{   
 if (confirm("Вы уверены, что хотите удалить этот форум?")) {   
  return true;   
 }  
 else {   
  return false;   
 }   
}   
</script>  
   
</head>  
   
<body>  
<table border=1 cellspacing=2>  
 <tr>  
  <td><b>Название форума</b></td>  
  <td><b>Имя</b></td>  
  <td><b>Пароль</b></td>  
  <td><b>Редактировать</b></td>  
  <td><b>Удалить</b></td>  
 </tr>  
   
<%  
 Do while not rs.eof  
  changeColor()  
  id = rs("forumid")  
  Response.Write "<tr bgcolor="& color &"><td>"  
  Response.Write rs("forumname") & "</td><td>"  
  Response.Write rs("username") & "</td><td>"  
  Response.Write rs("password") & "</td><td>"  
  Response.Write "<a href='editdel.asp?id="&id&"&action=edit'>Редактировать</td><td><a href='editdel.asp?id="&id&"&action=del'onclick='return IsDel()'>Удалить</td></tr>"  
  rs.MoveNext  
 Loop  
   
 Call Close()  
 Response.Write "</table><br></table>"  
%>  
   
<table border=2 width=380>  
<tr>  
<td colspan=2>Добавление нового форума.  
  <br> Введите название форума, а также имя и пароль его модератора  
</td>  
</tr>  
   
<form action="main.asp?action=add" method="post">  
   
<tr align=left>  
<td>Имя:</td>  
<td><input type="text" name="username" size="35" maxlength="10"></td>  
</tr>  
   
<tr align=left>  
<td>Пароль:</td>  
<td><input type="password" name="password" size="35" maxlength="10"></td>  
</tr>  
   
<tr align=left>  
<td>Название:</td>  
<td><input type="text" name="topic" size="35" maxlength="50"></td>  
</tr>  
              
<tr align=left>  
<td colspan=2 align=center>  
  <input type="submit" name="submit" value="Добавить форум">&nbsp;  
  <input type="Reset" value="Сброс">  
</td>  
</tr>  

</form>  
</table>  
   
<p><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a></p>  

</body>  
</html>  

Как видите, все просто, и результатом формирования странички, по сути, будет таблица с форумами, в каждой строке которой будут отображены сведения об одном из форумов и будут присутствовать ссылки на функции редактирования атрибутов форума и его удаления из форум-системы. Далее будет следовать форма добавления новых форумов в форум-систему (см. рис. 2).

Особое внимание следует обратить на то, каким образом идентифицируются модераторы в нашей форум-системе. Дело в том, что для соблюдения однозначности мы будем запрещать повторение паролей модераторов, и кроме того, необходимо также обеспечить уникальность и в названиях форумов. Следующий код как раз и призван для этого:

Редактирование атрибутов форума (файл EditDel.asp)

Эта страничка загружается в том случае, если перейти по ссылке редактирования форума в режиме администрирования, и позволяет редактировать название форума, имя его модератора, а также пароль подступа к привилегированному режиму, в котором модератор сможет редактировать сообщения других пользователей (участников) обсуждения, а также удалять нежелательные сообщения из их потока:

<!--#include file="common-admin.asp"-->  
   
<%  
 Call secure_general()  
   
 Response.CacheControl = "no-cache"   
 Response.AddHeader "Pragma", "no-cache"   
 Response.Expires = -1   
   
 dim useraction  
 dim id, sql_c, sOne, sZero, secure  
 dim username,password,forumname  
 id=request("id")  
   
 userAction = request("action")  
   
 call connect()  
   
 Select Case userAction  
   
  Case "update"  
   id = request.form("id")  
   username = request.form("username")  
   password = request.form("password")  
   forumname = request.form("topic")  
                  
   secure = 0  
   sql_c="select forumname, username, password, issecure from ForumsTable where" &_  
              " ( forumname='"&forumname&"' or password='"& password & "' ) and forumid<>"&id&""  
   
   set rs = conn.execute(sql_c)  
   
   If rs.eof AND rs.bof Then  
    sql = "update ForumsTable SET "&_   
        forumname='" & forumname & "', username='" & username & "', password='" & password &_  
       "', isSecure="  & secure & " where forumid="&id  
    conn.execute(sql)  
    response.redirect "main.asp"  
   Else  
     response.write "<script>alert('Введите другое имя /пароль');location.href='main.asp';</script>"  
   End If  
   
   conn.close  
   set conn = nothing  
                   
  Case "del"  
   sql = "delete from ForumsTable where forumid="&id  
   conn.execute(sql)  
   conn.close  
   set conn = nothing  
   response.redirect "main.asp"  
   
 Case "edit"  
   sql = "select * from ForumsTable where forumid="&id  
   set rs = conn.execute(sql)  
   username=rs("username")  
   password=rs("password")  
   forumname=rs("forumname")  
   secure = rs("issecure")  
   
   if secure="0" then  
     sOne=""  
     sZero="checked"  
   Else  
    sOne="checked"  
    sZero=""  
   End If  
   
 End Select             
   
 conn.close  
 set conn = nothing  
%>  
                  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>ASP Форум (Редактирование атрибутов форума)</title>  
</head>  
   
<body>  
<a>Редактирование атрибутов форума</a><br><br>  
   
<table border=2 width=400 align=left>  
<tr align = left>  
<td colspan = 2>Введите название форума и имя модератора, а также пароль</td>  
</tr>  
   
<form action="editdel.asp?action=update" method="post">  
<input type=hidden name=id value='<%=id%>'>  
   
<tr align=left>  
<td>Имя:</td>  
<td><input type="text" name="username" size="25" value='<%=password%>' maxlength="10"></td>  
</tr>  
   
<tr align=left>  
<td>Пароль:</td>  
<td><input type="text" name="password" size="25" value='<%=password%>' maxlength="10"></td>  
</tr>  
   
<tr align=left>  
<td>Название форума:</td>  
<td><input type="text" name="topic" size="25" maxlength="50" value='<%=forumname%>'></td>  
</tr>  
   
<tr align=left>  
<td colspan=2 align=center><input type="submit" name="submit" value="Обновление данных">&nbsp;<input type="Reset" value="Сброс"></td>  
</tr>  
   
</form>  
</table>  
<br><br><br><br><br><br><br><br><br><br><br><br>  
<p><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a></p>  
</body>  
</html>  
В начало В начало

Просмотр списка сообщений в режиме администрирования (файл Admin-List.asp)

Нам потребуется страничка просмотра списка сообщений, извлекающая сообщения выбранного пользователем форума из таблицы всех сообщений и

организующая показ сообщений иерархически, то есть сдвигая сообщения-ответы вправо, сообщения-ответы на ответы еще правее и т.д.

<!--#include file="common-admin.asp"-->  
   
<%  
 dim fid,tp,tid  
 dim rs_fn  
 dim ParentID,name,email,subject,mes,mesdate,image  
 dim forumname  
   
 Function getForumName(id)  
  set rs_fn=server.createObject("adodb.recordset")  
  sql="select forumid,forumname from ForumsTable where forumid="&id  
  rs_fn.open sql,conn  
  forumname = rs_fn("forumname")  
  response.write "<tr><td><b>" & forumname & "<br><br></b></TR></TD>"  
  rs_fn.close  
  set rs_fn=nothing  
 End Function  
   
'Извлечем идентификатор текущего форума  
 fid = request("fid")  
   
 If CInt (session("status")) <> CInt(fid) OR session("status") = "" Then  
  Response.Redirect "error.htm"  
 End If  
   
 image = "<img src='../images/arr.gif' border=0>"  
   
 Call Header()  
%>  
<script>  
   
function IsDel()  
{   
 if (confirm("Вы уверены, что хотите удалить это сообщение?")) {   
  return true;   
 }  
 else {   
  return false;   
 }   
}   
</script>  
   
<%   
 sql="select id, thread_id, name, email, subject, mesdate, forumID, thread_parent from MessagesTable "&_  
        "WHERE (forumid = " & fid & ") and thread_parent=0 order by id desc"  
   
 call connect()  
 rs.open sql,conn  
   
 If rs.eof and rs.bof then ' Если сообщений нет  
   Response.Write "<tr><td>Сообщений нет</tr></td>"  
 Else                      ' Показ всех сообщений  
  Response.Write getForumName(fid)  
   
  Do While Not rs.eof  
    tid = rs("thread_id")  
    ParentID=rs("id")  
    name=rs("name")  
    email=rs("email")  
    subject=rs("subject")  
    mesdate=rs("mesdate")  
   
    Response.write "<tr><td>"  
    Response.write image & "<a href='../show.asp?id=" & parentID & _  
             "&fid="&fid&"&tid="&tid&"'>" & subject & "</a>" & "...." & mesdate & "...." &  name & "</a>"  
   
    Response.write "&nbsp;<a href='edit-del.asp?action=edit&id=" & parentID & _  
                             "&fid="&fid&"&tid="&tid&"'>(Редактировать </a>" & _  
                             "<a href='edit-del.asp?action=del&id=" & parentID & _  
                             "&fid="&fid&"&tid="&tid&"' onclick='return IsDel()'> | Удалить) </a></tr></td>"  
              
    'Покажем дочерние сообщения  
    Call displayMessages(1,ParentID)  
   
    rs.MoveNext  
  Loop  
   
 End If  
   
 Call Close()  
   
 Response.Write "<tr><td><br>"  
 Response.Write "<br><br><a href='post.asp?fid=" & fid & "'>Послать сообщение как модератор форума</a>"  
 Response.Write "</table><br>"  
%>  
   
<p><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a></p>  
</body>  
</html>  

Согласитесь, все довольно просто. Результатом формирования странички списка является набор ссылок на странички просмотра отдельных сообщений (на страничку show.asp, которой в качестве параметра передается строка с идентификатором сообщения), и уровня вложенности: show.asp?id=" & parentID & "&fid="& fid &"&tid=" & tid", то есть точно таким же образом, как мы это описывали в предыдущей части статьи.

Самое главное в этой страничке заключается в выводе дочерних сообщений. Осуществляется это посредством вызова функции displayMessages.

Данная функция осуществляет вывод всех дочерних сообщений, причем в качестве параметров этой функции передаются уровень, с которого необходимо начать вывод дочерний сообщений, а также идентификатор сообщения-родителя.

В начало В начало

Редактор сообщения (файл Edit-Del.asp)

Теперь нам (а точнее, нашим модераторам) будет нужен довольно простой редактор сообщений, позволяющий редактировать заголовок сообщения, атрибуты его автора, а также сам текст сообщения:

<%  
 option explicit  
 dim fid  
 dim useraction  
 dim dsn,sql,conn,rs  
 dim name,subject,email,id,mesBody  
 id = request("id")  
 fid = request("fid")  
   
 If CInt(session("status")) <> cint(fid) OR session("status") = "" Then  
  Response.Redirect "error.htm"  
 End If  
   
 userAction = request("action")  
   
 dsn = "DBQ=" & Server.Mappath("../Data/Forum.mdb") & ";Driver={Microsoft Access Driver (*.mdb)};"  
 'dsn = "Forum"  
   
 set conn = server.createObject("adodb.connection")  
 conn.open dsn  
   
 Select Case userAction  
   
  Case "update"  
                id=request.form("id")  
                name=request.form("name")  
                subject=request.form("subject")  
                email=request.form("email")  
              mesBody = request.form("mesBody")  
                mesbody = Replace(mesbody, vbCrLf, "<br>")  
                sql = "update MessagesTable SET mesBody = '"&mesBody &_  
                        "', subject='" & subject&"', name = '" & name &_  
                        "', email = '" & email & "' where id="&id  
                conn.execute(sql)  
                conn.close  
                set conn = nothing  
                response.redirect "admin-list.asp?fid=" & fid  
   
  Case "del"  
                id = request.querystring("id")  
                sql = "delete from MessagesTable where id="&id  
                conn.execute(sql)  
                conn.close  
                set conn = nothing  
                response.redirect "admin-list.asp?fid=" & fid  
   
  Case "edit"  
             sql = "select * from MessagesTable where id="&id  
             set rs = conn.execute(sql)  
             name=rs("name")  
             subject=rs("subject")  
             email=rs("email")  
             mesBody=rs("mesBody")  
             mesbody = Replace(mesbody, "<br>",vbCrLf)  
   
 conn.close  
 set conn = nothing  
%>  
                  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>ASP Форум (Редактирование сообщения)</title>  
</head>  
   
<body>  
<table border=1 width=400>  
<tr>  
<td colspan=2><b>Редактирование сообщения</b><br></td>  
</tr>  
   
<form action="edit-del.asp?action=update" method="post">  
 <input type=hidden name=id value=<%=id%>>  
 <input type=hidden name=fid value=<%=fid%>  
   
 <tr>  
 <td>Имя:</td>  
 <td><input type="text" name="name" size=20 maxlength=20 value='<%= name %>'>  
 </td>  
 </tr>  
   
 <tr>  
 <td>Tema:</td>  
 <td><input type="text" name="subject" size=20 maxlength=20 value='<%= subject %>'>  
 </td>  
 </tr>  
   
 <tr>  
 <td>E-mail:</td>  
 <td><input type="text" name="email" size=20 maxlength=20 value='<%= email %>'>  
 </td>  
 </tr>  
   
 <tr>  
 <td>Сообщение:</td>  
 <td><textarea cols=25 rows=8 name='mesBody' maxlength='20' size=23 wrap="virtual" ><%=mesBody%></textarea>  
 </td>  
 </tr>  
   
 <tr>  
 <td colspan=2 align="center">  
 <input type="submit" value="Update">  
 </td>  
 </tr>  
   
 </form>  
 </table>  
</body>  
</html>  
   
<% End Select %>  
В начало В начало

Отправка сообщения (файл Post.asp)

На этом этапе нам надлежит сформировать формы посылки сообщения от имени модератора. Единственным отличием от обычной формы посылки сообщения здесь является то, что вместо имени пользователя в соответствующее поле формы отправки по умолчанию будет загружено значение «Модератор». Далее, как и в обычном случае, нам потребуется реализовать проверку корректности  заполнения формы, обработку введенных значений и механизм добавления новых сообщений в соответствующую таблицу базы данных.

Извлечем идентификатор текущего форума, сообщения и его уровня вложенности, а затем опросим действия пользователя. Данные, введенные пользователем в качестве тела сообщения, а также его заголовка (темы) и имени пользователя, обработаем с использованием серверного метода Server.HtmlEncode: mesbody = Server.HtmlEncode(mesbody),  после чего можем добавлять новую запись в таблицу:

<!--#include file="common-admin.asp"-->  
   
<SCRIPT LANGUAGE=VBScript RUNAT=Server>  
 <!--Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" -->  
</SCRIPT>  
   
<%  
 dim useraction,fid,action,id,tid,mailme  
 dim mesbody,name,subject  
 dim sql_maxid,rs_maxid,maxid  
   
 fid = request("fid")  
 id = request("id")  
 tid = request("tid")  
   
 If CInt(session("status")) <> CInt(fid) OR session("status")="" Then  
  Response.Redirect "error.htm"  
 End If  
   
 If id="" Then  
  action="post.asp?action=save"  
 Else  
  action="post.asp?action=replay"  
 End If  
   
 userAction = request("action")  
   
 Select Case userAction  
    Case "save"  
        call connect()  
            sql="select * from MessagesTable"  
            RS.Open sql, Conn, 3, adLockOptimistic  
            mesbody=request.form("message")  
            name=request.form("name")  
            name = "**" & name & "**"  
            subject=request.form("subject")  
            mailme=request.form("mailme")  
              
            rs.addnew  
            rs("name")=name  
            rs("subject")=subject  
            rs("email")=request.form("email")  
            rs("mesdate")=now()  
            rs("mesbody")=mesbody  
            rs("thread_parent")=0  
            rs("thread_id")=0  
            rs("forumID")=request.form("fid")  
            rs("isChecked")=mailme  
            rs.update  
            call close()  
            response.redirect "../list.asp?fid="&fid  
              
 End Select  
   
 dim requireFldSign  
 requireFldSign = "<font color='red'>*</font>"  
 response.write "<HTML><HEAD><link rel='stylesheet' href='style.css'>"  
%>  
   
<script language="javascript">  
function submitit()  
{  
 var name = document.myform.name.value;  
 var subject = document.myform.subject.value;  
 var email = document.myform.email.value;  
   
 if (name == "") {  
  alert("Введите Ваше имя.")  
  document.myform.name.focus()  
  return false  
 }  
          
 if (subject == "") {  
  alert("Введите тему")  
  document.myform.subject.focus()  
  return false  
 }  
          
 if (email!="") {  
  if (email.indexOf('@', 0) == -1 || email.indexOf('.', 0) == -1) {   
   alert("Некорректный формат электронного адреса");  
   document.myform.email.focus()  
   return false  
  }  
 }  
          
}  
</script>  
   
<%  
 response.write "<meta http-equiv='Content-Type' content='text/html; charset=windows-1251'>"  
 response.write "<TITLE></TITLE></HEAD><body>"  
 response.write "<b>Послать сообщение как модератор форума</b><br><br>"  
 response.write "<table border=0 width=600 cellpadding=0 cellspacing=0>"  
 response.write "<tr><td width=100></tr></td>"  
 response.write "<form name='myform' action='" &action & "' method='post' onsubmit='return submitit()'>"  
 response.write "<input type=hidden name='fid' value='"&fid&"'>"  
 response.write "<input type=hidden name='id' value='"&id&"'>"  
 response.write "<input type=hidden name='tid' value='"&tid&"'>"  
 response.write "<tr><td width=100>"  
 response.write requireFldSign & "Имя:</td><td><input type='text' name='name' maxlength='20' size=23 value='Модератор'></tr></td>"  
 response.write "<tr><td>"  
 response.write "E-mail:</td><td><input type='text' name='email' maxlength='28' size=23></tr></td>"  
 response.write "<tr><td>"  
 response.write requireFldSign & "Тема:</td><td><input type='text' name='subject' maxlength='25' size=23></tr></td>"  
 response.write "<tr><td valign=top>"  
 response.write "Сообщение:</td><td><textarea cols=25 rows=8 name='message' maxlength='20' size=23 wrap='virtual'></textarea></tr></td>"  
 response.write "<tr><td colspan=2><br>"  
 response.write "<input type='checkbox' name='mailme' value='1'>"  
 response.write "Отправить электронное уведомление об ответах</tr></td>"  
 response.write "<tr><td colspan=2><br>"  
 response.write "<input type='submit' name='submit' value='Отправить сообщение'>&nbsp;&nbsp;"  
 response.write "<input type='reset' name='reset' value='Сброс'>"  
 response.write "</form>"  
 response.write "</tr></td></table></body></html>"  
 response.write "<table border=0 width=600 cellpadding=0 cellspacing=0><tr><td>"  
   
 Call Footer()  
 Response.Write "</tr></td></table>"  
%>  

По своей сути эта страничка очень похожа на аналогичную страничку посылки сообщения, рассмотренную нами выше.

В начало В начало

Заключение

Наконец, нам осталось разместить все исходники наших страниц в папке с именем Administration, и тогда наша форум-система будет окончательно готова к использованию.

 

Полный архив исходных текстов ASP-страниц к настоящей и предыдущей частям статьи лежит здесь.

КомпьютерПресс 6'2001