+#
+# Обработка операций, которые вызываются одинаково,
+# но выполняются по-разному для разных типов объектов
+#
+# Параметры $cgi,$forum, тип => ссылка на функцию ...
+# где тип - message, topic или forum. Определяет обрабатываемый объект
+# и вызывает соответствующую фунцкию. Ожидает что функция завершится
+#вызовом exit.
+sub dispatch_objtype {
+ my $cgi=shift;
+ my $forum = shift;
+ my %actions=@_;
+ if (-f $path_translated) {
+ if ($cgi->param("id")) {
+ $actions{"message"}->($cgi,$forum,$path_translated,$cgi->param("id"))
+ if exists($actions{'message'});
+ } else {
+ $actions{topic}->($cgi,$forum,$path_translated)
+ if exists($actions{'topic'});
+ }
+ } elsif (-d $path_translated && -f $path_translated ."/". $forum->{indexfile}) {
+ $actions{'forum'}->($cgi,$forum,$path_translated)
+ if exists($actions{'forum'});
+
+ }
+ return undef;
+}
+#Удаление
+sub delete_item {
+ my ($formname,$cgi,$forum) = @_;
+ #
+ # Сначала разберемся, что мы собственно удаляем
+ #
+ if ($cgi->param("user")) {
+ delete_user($cgi,$forum,$cgi->param("user"));
+ }
+ dispatch_objtype($cgi,$forum,topic=>\&delete_topic,
+ message=>\&delete_comment,
+ forum=>\&delete_forum);
+ show_error($forum,"Невозможно удалить неопознанный объект");
+}
+# Показ формы редактирования
+sub show_editable {
+ my ($formname,$cgi,$forum) = @_;
+ dispatch_objtype($cgi,$forum,"message"=>\&show_messageedit,
+ topic=>\&show_topicedit,
+ forum=>\&show_forumedit);
+ show_error($forum,"Невозможно редактировать неопознанный объект");
+}
+# Применение результатов редактирования
+sub edit_item {
+ my ($formname,$cgi,$forum) = @_;
+ dispatch_objtype($cgi,$forum,"message"=>\&messageedit,
+ topic=>\&topicedit,
+ forum=>\&forumedit);
+ show_error($forum,"Невозможно редактировать неопознанный объект");
+}
+sub move_item {
+ my ($formname,$cgi,$forum) = @_;
+ dispatch_objtype($cgi,$forum,"message"=>\&move_message,
+ topic=>\&move_topic,
+ forum=>\&move_forum);
+ show_error($forum,"Невозможно переместить неопознанный объект");
+}
+sub show_move_dest {
+ my ($formname,$cgi,$forum) = @_;
+ dispatch_objtype($cgi,$forum,"message"=>\&show_move_message,
+ topic=>\&show_move_topic,
+ forum=>\&show_move_forum);
+ show_error($forum,"Невозможно переместить неопознанный объект");
+}
+#
+# Удаление пользователя
+#
+sub delete_user {
+ my ($cgi,$forum,$user) = @_;
+ if ($forum->{authenticated}{user} ne $user &&
+ getrights($cgi,$forum) ne "admin") {
+ show_error($forum,"У вас недостаточно прав для удаления
+ пользователя $user");
+ }
+ my %base;
+ dbmopen %base,datafile($forum,"passwd"),0644;
+ delete $base{$user};
+ dbmclose %base;
+ forum_redirect($cgi,$forum,$forum->{forumtop});
+}
+# Проверка прав на изменение реплики
+sub moderator_or_author {
+ my ($cgi,$forum,$msg)=@_;
+ return 1 if getrights($cgi,$forum) eq "moderator"
+ || getrights($cgi,$forum) eq "admin";
+ my $author= $msg->look_down(_tag=>"input",name=>"author");
+ if ($author) {
+ return $author->attr("value") eq $forum->{authenticated}{user};
+ } elsif ($author = $msg->look_down(class=>"author",_tag=>"a")) {
+ return $author->as_text eq $forum->{authenticated}{user};
+ } else {
+ return undef;
+ }
+}
+#
+# Удаление реплики
+#
+sub delete_comment {
+ my ($cgi,$forum,$topic,$id) = @_;
+ my ($tree,$lockfd) = gettree($topic);
+ my ($msg) = $tree->look_down(id => $id);
+ show_error($forum,"В данной теме нет реплики с id=$id") if (!$msg);
+ show_error($forum,"У вас нет прав на удаление этого сообщения")
+ unless moderator_or_author($cgi,$forum,$msg);
+ delete_from_list($tree,"messagelist","message",$msg);
+ savetree($topic,$tree,$lockfd);
+ $tree->delete;
+ ($tree,$lockfd) = gettree($forum->{forumroot}."/recent.html");
+ ($msg) = $tree->look_down(id => $id);
+ if ($msg) {
+ delete_from_list($tree,"messagelist","message",$msg);
+ savetree($forum->{forumroot}."/recent.html",$tree,$lockfd);
+ } else {
+ discardtree($tree,$lockfd);
+ }
+ # Если у реплики были картинки, то их тоже надо грохнуть
+ for my $pic (<$id."_*.*">) {
+ unlink $pic;
+ }
+ forum_redirect($cgi,$forum,$cgi->path_info);
+}
+#
+# Удаление темы
+#
+sub delete_topic {
+ my ($cgi,$forum,$topic) = @_;
+ # Если модератор, то в тему и не заглядываем
+ my ($dir,$id) = ($1,$2) if $topic=~/^(.*)\/([^\/]+).html$/;
+ show_error($forum,"Неверное имя темы $topic") unless ($dir && $id);
+ if (getrights($cgi,$forum) ne "moderator" &&
+ getrights($cgi,$forum) ne "admin") {
+ # Проверяем авторство темы и наличие в ней сообщений
+ my ($tree,$lockfd) = gettree($topic);
+ my $info = $tree->look_down(class=>"topic");
+ my $author = $tree->look_down(class=>"author");
+ if ($author->as_text() ne $forum->{authenticated}{user}) {
+ show_error($forum,"У вас нет права удалять эту тему");
+ }
+ $info = $tree->look_down(class=>"messagelist");
+ if ($info->attr("style") !~ /display: none;/) {
+ show_error($forum,"Невозможно удалить тему, содержащую сообщения");
+ }
+ discardtree($tree,$lockfd);
+ } # FIXME при удалении непустой темы модератором почистить recent.html
+ my ($tree,$lockfd) = gettree($dir . "/".$forum->{indexfile});
+ delete_from_list($tree,"topiclist","topic",$id);
+ savetree($tree,$dir ."/".$forum->{indexfile});
+ unlink $topic;
+ my $redirect_url = $cgi->path_info;
+ $redirect_url =~ s/\/[^\/]*$//;
+ forum_redirect($cgi,$forum,$redirect_url);
+}
+#
+# Удаление форума
+#
+sub delete_forum {
+ my ($cgi,$forum,$dir) = @_;
+ if (getrights($cgi,$forum) ne "moderator" && getrights($cgi,$forum)
+ ne "admin") {
+ show_error($forum,"У вас нет права удалять форумы");
+ }
+ opendir DIR,$dir;
+ my $count = 0;
+ while ( my $entry=readdir DIR) {
+ next if $entry eq $forum->{indexfile};
+ next if $entry eq "perms.txt";
+ next if $entry =~ /^logo.[^.]+/;
+ show_error($forum,"Нельзя удалять корень форума" )
+ if $entry eq ".forum";
+ $count ++;
+ }
+ closedir DIR;
+ show_error($forum,"Нельзя удалять непустой форум") if $count;
+ # Находим родительский форум
+ my $upper = $dir;
+ $upper=~s/([\/]+)$/$forum->{indexfile}/;
+ my $id = $1 if $dir =~ /\/([\/]+)$/;
+ # Удаляем форум из списка.
+ my ($tree,$lockfd) = gettree($upper);
+ delete_from_list($tree,"forumlist","forum",$id);
+ savetree($upper,$tree,$lockfd);
+ # Удаляем из файловой системы
+ opendir DIR,$dir;
+ for my $entry ( readdir DIR) {
+ unlink "$dir/$entry";
+ }
+ rmdir $dir;
+ my $redirect_url = $cgi->path_info;
+ $redirect_url =~s/\/$//;
+ $redirect_url =~ s/\/[^\/]*$//;
+ forum_redirect($cgi,$forum,$redirect_url);
+}
+# Показ сообщения для редактирования
+sub show_messageedit {
+ my ($cgi,$forum,$path,$id)=@_;
+ my ($tree,$lockfd) = gettree($path);
+ my $dirname = $path;
+ $dirname =~ s/\/[^\/]+$//;
+ my ($msg) = $tree->look_down(id => $id);
+ show_error($forum,"В данной теме нет реплики с id=$id") if (!$msg);
+ show_error($forum,"У вас нет прав на редактированиее этого сообщения")
+ unless moderator_or_author($cgi,$forum,$msg);
+ # Выбираем данные сообщения
+ my ($text) = $msg->look_down(class=>"mtext")->content_list;
+ my ($subject) = $msg->look_down(class=>"subject");
+ $cgi->param("text"=>$text->as_HTML('<>&"'));
+ $cgi->param("text_format"=>"html");
+ $cgi->param("subject"=> $subject->as_text);
+ discardtree($tree,$lockfd);
+ # Подготавливаем шаблон
+ my $form = prepare_template("edit_message",$cgi,$forum);
+ # Подставляем информацию о картинках.
+ opendir D,$dirname;
+ while ( my $filename=readdir D) {
+ next unless $filename =~/^${id}_/;
+ my $pic = "$dirname/$filename";
+ my $picitem = newlistelement($form,"picture","picturelist");
+ my ($w,$h) = imgsize($pic);
+ substinfo($picitem,[_tag=>"img", class=>"msgpicture"],
+ src=>dir2url($cgi,$pic),width=>$w,height=>$h);
+ substinfo($picitem,[_tag=>"input",name=>"delpicture"],
+ value=>$filename);
+ substinfo($picitem,[class=>"filename"],_content =>$filename);
+ }
+ closedir D;
+ send_to_user($form,"edit_message",$cgi,$forum);
+}
+# Показ темы для редактирования
+sub show_topicedit {
+ my ($cgi,$forum,$path)=@_;
+}
+# Показ форума для редактирования
+sub show_forumedit {
+ my ($cgi,$forum,$path) = @_;
+}