# File: shared/Posting/Admin.pm #
# (was: ~Handle.pm) #
# #
-# Authors: Frank Schoenmann <fs@tower.de>, 2001-03-13 #
-# Andre Malo <nd@o3media.de>, 2001-03-29 #
+# Authors: Frank Schönmann <fs@tower.de> #
+# André Malo <nd@o3media.de> #
+# Christian Kruse <ckruse@wwwtech.de> #
# #
# Description: Allow administration of postings #
# #
# Todo: * Lock files before modification #
# * Change body in change_posting_body() #
-# * Recursively set invisibility flag in main forum xml by #
-# hide_posting() and recover_posting() #
# #
################################################################################
use strict;
use vars qw(
@EXPORT
- $VERSION
);
-use Lock qw(:READ);
+use Lock;
use Posting::_lib qw(
+ parse_xml_file
get_message_node
save_file
get_all_threads
#
# Version check
#
-$VERSION = do { my @r =(q$Revision$ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+# last modified:
+# $Date$ (GMT)
+# by $Author$
+#
+sub VERSION {(q$Revision$ =~ /([\d.]+)\s*$/)[0] or '0.0'}
################################################################################
#
# * Lock files before modification
#
sub add_user_vote ($$$) {
- my ($forum, $tpath, $info) = @_;
- my ($tid, $mid, $percent) = ($info->{'thread'},
- $info->{'posting'},
- $info->{'percent'});
-
- # Thread
- my $tfile = $tpath . '/t' . $tid . '.xml';
+ my ($forum, $tpath, $info) = @_;
+ my ($tid, $mid, $percent) = ($info->{'thread'},
+ $info->{'posting'},
+ $info->{'percent'});
- my $parser = new XML::DOM::Parser;
- my $xml = $parser->parsefile($tfile);
+ # Thread
+ my $tfile = $tpath . '/t' . $tid . '.xml';
+ my $xml = parse_xml_file($tfile);
- my $mnode = get_message_node($xml, $tid, $mid);
- my $votes = $mnode->getAttribute('votingUser') + 1;
- $mnode->setAttribute('votingUser', $votes);
+ my $mnode = get_message_node($xml, $tid, $mid);
+ my $votes = $mnode->getAttribute('votingUser') + 1;
+ $mnode->setAttribute('votingUser', $votes);
- return save_file($tfile, \$xml->toString);
+ return save_file($tfile, \$xml->toString);
}
### level_vote () ##############################################################
# * Lock files before modification
#
sub level_vote {
- my ($forum, $tpath, $info´) = @_;
- my ($tid, $mid, $level, $value) = (
- $info->{'thread'},
- $info->{'posting'},
- $info->{'level'},
- $info->{'value'}
- );
-
- # Thread
- my $tfile = $tpath . '/t' . $tid . '.xml';
-
- my $parser = new XML::DOM::Parser;
- my $xml = $parser->parsefile($tfile);
-
- my $mnode = get_message_node($xml, $tid, $mid);
-
- unless (defined $value) {
- removeAttribute($level);
- }
- else {
- $mnode->setAttribute($level, $value);
- }
-
- return save_file($tfile, \$xml->toString);
+ my ($forum, $tpath, $info) = @_;
+ my ($tid, $mid, $level, $value) = ($info->{'thread'},
+ $info->{'posting'},
+ $info->{'level'},
+ $info->{'value'});
+
+ # Thread
+ my $tfile = $tpath . '/t' . $tid . '.xml';
+ my $xml = parse_xml_file($tfile);
+ my $mnode = get_message_node($xml, $tid, $mid);
+
+ unless (defined $value) {
+ removeAttribute($level);
+ }
+ else {
+ $mnode->setAttribute($level, $value);
+ }
+
+ return save_file($tfile, \$xml->toString);
}
### hide_posting () ############################################################
#
# Params: $forum Path and filename of forum
# $tpath Path to thread files
-# \%info Hash reference: 'thread', 'posting', 'indexFile'
+# \%info Hash reference: 'thread', 'posting'
# Return: -none-
#
-# Todo:
-# * set flags recursively in forum xml
-# * lock files before modification
-#
-sub hide_posting ($$$) {
- my ($forum, $tpath, $info) = @_;
- my ($tid, $mid, $indexFile) = ($info->{'thread'},
- $info->{'posting'},
- $info->{'indexFile'});
-
- # Thread
- my $tfile = $tpath . '/t' . $tid . '.xml';
- change_posting_visibility($tfile, 't'.$tid, 'm'.$mid, 1);
-
- # Forum
- my ($f, $lthread, $lmsg, $dtd, $zlev) = get_all_threads($forum, 0, 0); # filter deleted, descending
-
- for (@{$f->{$tid}})
- {
- if ($_->{'mid'} == $mid)
- {
- $_->{'deleted'} = 1;
- }
+sub hide_posting($$$) {
+ my ($forum, $tpath, $info) = @_;
+ my ($tid, $mid) = ($info->{'thread'},
+ $info->{'posting'});
+
+ # Thread
+ my $tfile = $tpath . '/t' . $tid . '.xml';
+
+ # lock files
+ my $main = new Lock $forum;
+ my $tlock = new Lock $tfile;
+
+ return unless $tlock->lock(LH_EXCL); # lock failed
+ unless ($main->lock(LH_EXCL)) { # lock failed
+ $tlock->unlock;
+ return;
+ }
+
+ #
+ # Change invisibility in the thread file.
+ #
+ unless (change_posting_visibility($tfile, 't'.$tid, 'm'.$mid, 1)) { # saving failed
+ $tlock->unlock;
+ $main->unlock;
+ return;
+ }
+
+ # get all Forum threads
+ my ($f, $lthread, $lmsg,$dtd) = get_all_threads($forum, 1);
+ unless ($f) {
+ $tlock->unlock;
+ $main->unlock;
+ }
+
+ #
+ # Change invisibility in the main forum index.
+ #
+ for my $i (0 .. $#{$f->{$tid}}) {
+ if ($f->{$tid}->[$i]->{'mid'} == $mid) {
+ $f->{$tid}->[$_]->{'deleted'} = 1 for ($i .. $i+$f->{$tid}->[$i]->{'answers'});
+ last;
}
+ }
- my %cfxs = (
- 'dtd' => $dtd,
- 'lastMessage' => $lmsg,
- 'lastThread' => $lthread
- );
- my $xmlstring = create_forum_xml_string($f, \%cfxs);
- save_file($forum, $$xmlstring);
+ my $success = save_file($forum,
+ create_forum_xml_string($f,
+ {
+ 'dtd' => $dtd,
+ 'lastMessage' => $lmsg,
+ 'lastThread' => $lthread
+ })
+ );
+
+ $tlock->unlock;
+ $main->unlock;
+
+ return $success;
}
### recover_posting() ##########################################################
#
# Params: $forum Path and filename of forum
# $tpath Path to thread files
-# \%info Hash reference: 'thread', 'posting', 'indexFile'
-# Return: -none-
-#
-# Todo:
-# * set flags recursive in forum xml
-# * lock files before modification
+# \%info Hash reference: 'thread', 'posting'
+# Return: success or unsuccess
#
sub recover_posting ($$$) {
- my ($forum, $tpath, $info) = @_;
- my ($tid, $mid, $indexFile) = ($info->{'thread'},
- $info->{'posting'},
- $info->{'indexFile'});
-
- # Thread
- my $tfile = $tpath . '/t' . $tid . '.xml';
- change_posting_visibility($tfile, 't'.$tid, 'm'.$mid, 0);
-
- # Forum
- my ($f, $lthread, $lmsg, $dtd, $zlev) = get_all_threads($forum, 1, 0); # do not filter deleted, descending
-
- for (@{$f->{$tid}})
- {
- if ($_->{'mid'} == $mid)
- {
- $_->{'deleted'} = 0;
- }
+ my ($forum, $tpath, $info) = @_;
+ my ($tid, $mid) = ($info->{'thread'},
+ $info->{'posting'});
+
+ # Thread
+ my $tfile = $tpath . '/t' . $tid . '.xml';
+
+ # lock files
+ my $main = new Lock $forum;
+ my $tlock = new Lock $tfile;
+
+ return unless $tlock->lock(LH_EXCL); # lock failed
+ unless ($main->lock(LH_EXCL)) { # lock failed
+ $tlock->unlock;
+ return;
+ }
+
+ #
+ # Change invisibility in the thread file.
+ #
+ unless (change_posting_visibility($tfile, 't'.$tid, 'm'.$mid, 0)) { # saving failed
+ $main->unlock;
+ $tlock->unlock;
+ return;
+ }
+
+ # get all Forum threads
+ my ($f, $lthread, $lmsg,$dtd) = get_all_threads($forum,1);
+
+ unless ($f) {
+ $main->unlock;
+ $tlock->unlock;
+
+ return;
+ }
+
+ #
+ # Change invisibility in the main forum index.
+ #
+ for my $i (0 .. $#{$f->{$tid}}) {
+ if ($f->{$tid}->[$i]->{'mid'} == $mid) {
+ $f->{$tid}->[$_]->{'deleted'} = 0 for ($i .. $i+$f->{$tid}->[$i]->{'answers'});
+ last;
}
+ }
+
+ my $success = save_file($forum,
+ create_forum_xml_string($f,
+ {
+ 'dtd' => $dtd,
+ 'lastMessage' => $lmsg,
+ 'lastThread' => $lthread
+ })
+ );
+
+ $tlock->unlock;
+ $main->unlock;
- my %cfxs = (
- 'dtd' => $dtd,
- 'lastMessage' => $lmsg,
- 'lastThread' => $lthread
- );
- my $xmlstring = create_forum_xml_string($f, \%cfxs);
- save_file($forum, $$xmlstring);
+ return $success;
}
### change_posting_visibility () ###############################################
# $invisible 1 - invisible, 0 - visible
# Return: Status code
#
-sub change_posting_visibility ($$$$)
-{
- my ($fname, $tid, $mid, $invisible) = @_;
+sub change_posting_visibility($$$$) {
+ my ($fname, $tid, $mid, $invisible) = @_;
- my $parser = new XML::DOM::Parser;
- my $xml = $parser->parsefile($fname);
+ my $xml = parse_xml_file($fname);
+ return unless $xml; # parser failed
- # Set flag in given msg
- my $mnode = get_message_node($xml, $tid, $mid);
- $mnode->setAttribute('invisible', $invisible);
+ # Set flag in given msg
+ my $mnode = get_message_node($xml, $tid, $mid);
+ $mnode->setAttribute('invisible', $invisible);
- # Set flag in sub nodes
- for ($mnode->getElementsByTagName('Message')) {
- $_->setAttribute('invisible', $invisible);
- }
+ # Set flag in sub nodes
+ $_->setAttribute('invisible', $invisible) foreach $mnode->getElementsByTagName('Message');
- return save_file($fname, \$xml->toString);
+ return save_file($fname, \$xml->toString);
}
### modify_posting () ##########################################################
# (data = \%hashref: 'subject', 'category', 'body')
# Return: -none-
#
+# Todo:
+# * Lock files!
+# * save return values
+#
sub modify_posting($$$) {
- my ($forum, $tpath, $info) = @_;
- my ($tid, $mid, $indexFile, $data) = (
- $info->{'thread'},
- $info->{'posting'},
- $info->{'indexFile'},
- $info->{'data'}
- );
-
- my ($subject, $category, $body) = (
- $data->{'subject'},
- $data->{'category'},
- $data->{'body'}
- );
-
- my %msgdata;
-
- # These values may be changed by change_posting_value()
- $subject && $msgdata{'Subject'} = $subject;
- $category && $msgdata{'Category'} = $category;
-
- # Thread
- my $tfile = $tpath . '/t' . $tid . '.xml';
- change_posting_value($tfile, 't'.$tid, 'm'.$mid, \$msgdata);
- $body && change_posting_body($tfile, 't'.$tid, 'm'.$mid, $body);
-
- # Forum (does not contain msg bodies)
- if ($subject or $category) {
- my ($f, $lthread, $lmsg, $dtd, $zlev) = get_all_threads($forum, 1, 0);
-
- for (@{$f->{$tid}}) {
- if ($_->{'mid'} == $mid) {
- $subject && $_->{'subject'} = $subject;
- $category && $_->{'cat'} = $category;
- }
- }
-
- my %cfxs = (
- 'dtd' => $dtd,
- 'lastMessage' => $lmsg,
- 'lastThread' => $lthread
- );
- my $xmlstring = create_forum_xml_string($f, \%cfxs);
- save_file($forum, $$xmlstring);
+ my ($forum, $tpath, $info) = @_;
+ my ($tid, $mid, $indexFile, $data) = (
+ $info->{'thread'},
+ $info->{'posting'},
+ $info->{'indexFile'},
+ $info->{'data'}
+ );
+
+ my ($subject, $category, $body) = (
+ $data->{'subject'},
+ $data->{'category'},
+ $data->{'body'}
+ );
+
+ my %msgdata;
+
+ # These values may be changed by change_posting_value()
+ $msgdata{'Subject'} = $subject if $subject;
+ $msgdata{'Category'} = $category if $category;
+
+ # Thread
+ my $tfile = $tpath . '/t' . $tid . '.xml';
+ change_posting_value($tfile, 't'.$tid, 'm'.$mid, \%msgdata);
+ change_posting_body($tfile, 't'.$tid, 'm'.$mid, $body) if $body;
+
+ # Forum (does not contain msg bodies)
+ if ($subject or $category) {
+ my ($f, $lthread, $lmsg, $dtd, $zlev) = get_all_threads($forum, 1, 0);
+
+ for (@{$f->{$tid}}) {
+ if ($_->{'mid'} == $mid) {
+ $_->{'subject'} = $subject if $subject;
+ $_->{'cat'} = $category if $category;
+ }
+ }
+
+ save_file($forum, create_forum_xml_string($f,{dtd=>$dtd,lastMessage=>$lmsg,lastThread$lthread}));
+ }
+
}
### change_posting_value () ####################################################
# Return: Status code
#
sub change_posting_value($$$$) {
- my ($fname, $tid, $mid, $values) = @_;
+ my ($fname, $tid, $mid, $values) = @_;
- my $parser = new XML::DOM::Parser;
- my $xml = $parser->parsefile($fname);
+ my $xml = parse_xml_file($fname);
+ my $mnode = get_message_node($xml, $tid, $mid);
- my $mnode = get_message_node($xml, $tid, $mid);
+ for (keys %$values) {
+ # Find first direct child node with name $_
+ my $nodes = $mnode->getElementsByTagName($_, 0);
+ my $node = $nodes->item(0);
+ $node->setValue($values->{$_});
+ }
- for (keys %$values)
- {
- # Find first direct child node with name $_
- my $nodes = $mnode->getElementsByTagName($_, 0);
- my $node = $nodes->item(0);
- $node->setValue($values->{$_});
- }
-
- return save_file($fname, \$xml->toString);
+ return save_file($fname, \$xml->toString);
}
### change_posting_body () #####################################################
# * Change body
#
sub change_posting_body ($$$$) {
- my ($fname, $tid, $mid, $body) = @_;
-
- my $parser = new XML::DOM::Parser;
- my $xml = $parser->parsefile($fname);
+ my ($fname, $tid, $mid, $body) = @_;
- my $mbnody = get_message_body($xml, $mid);
+ my $xml = parse_xml_file($fname);
+ my $mbnody = get_message_body($xml, $mid);
# todo: change body
- return save_file($fname, \$xml->toString);
+ return save_file($fname, \$xml->toString);
}