X-Git-Url: https://git.p6c8.net/selfforum.git/blobdiff_plain/ba659b53059e637777865e646f0f2a6fb7f2988e..48fce6394d3bb5d6829f453a88f874d4c1f2ff13:/selfforum-cgi/shared/Posting/_lib.pm diff --git a/selfforum-cgi/shared/Posting/_lib.pm b/selfforum-cgi/shared/Posting/_lib.pm index fea4097..0f3f015 100644 --- a/selfforum-cgi/shared/Posting/_lib.pm +++ b/selfforum-cgi/shared/Posting/_lib.pm @@ -1,47 +1,53 @@ -# Posting/_lib.pm +package Posting::_lib; -# ==================================================== -# Autor: n.d.p. / 2001-01-07 -# lm : n.d.p. / 2001-01-08 -# ==================================================== -# Funktion: -# * Schnittstellen fuer den Zugriff auf Messages -# * Zeitdarstellung -# ==================================================== +################################################################################ +# # +# File: shared/Posting/_lib.pm # +# # +# Authors: André Malo , 2001-03-03 # +# Frank Schoenmann , 2001-03-13 # +# # +# Description: Message access interface, time format routines # +# # +################################################################################ use strict; -package Posting::_lib; - -use vars qw(@ISA @EXPORT_OK); - use Encode::Plain; $Encode::Plain::utf8 = 1; use XML::DOM; # ==================================================== -# Funktionsexport +# Export # ==================================================== -require Exporter; -@ISA = qw(Exporter); -@EXPORT_OK = qw(get_message_header get_message_body get_message_node parse_single_thread - hr_time short_hr_time long_hr_time - get_all_threads - create_forum_xml_string - save_file); +use constant SORT_ASCENT => 0; # (young postings first) +use constant SORT_DESCENT => 1; +use constant KEEP_DELETED => 1; +use constant KILL_DELETED => 0; + +use base qw(Exporter); +@Posting::_lib::EXPORT_OK = qw( + get_message_header get_message_body get_message_node get_body_node parse_single_thread parse_xml_file + hr_time short_hr_time long_hr_time + get_all_threads create_forum_xml_string + save_file + SORT_ASCENT SORT_DESCENT KEEP_DELETED KILL_DELETED +); # ==================================================== -# Zugriff uebers DOM +# Access via XML::DOM # ==================================================== -########################### -# sub get_message_header +### get_message_header () ###################################################### # -# Messageheader auslesen -########################### - -sub get_message_header ($) { +# Read message header, return as a hash +# +# Params: $node XML message node +# Return: Hash reference (name, category, subject, email, home, image, time) +# +sub get_message_header ($) +{ my $node = shift; my %conf; @@ -55,54 +61,109 @@ sub get_message_header ($) { my $subject = $header -> getElementsByTagName ('Subject', 0) -> item (0); my $date = $header -> getElementsByTagName ('Date', 0) -> item (0); - %conf = (name => ($name -> hasChildNodes)?$name -> getFirstChild -> getData:undef, - category => ($cat -> hasChildNodes)?$cat -> getFirstChild -> getData:undef, - subject => ($subject -> hasChildNodes)?$subject -> getFirstChild -> getData:undef, - email => (defined ($email) and $email -> hasChildNodes)?$email -> getFirstChild -> getData:undef, - home => (defined ($home) and $home -> hasChildNodes)?$home -> getFirstChild -> getData:undef, - image => (defined ($image) and $image -> hasChildNodes)?$image -> getFirstChild -> getData:undef, - time => $date -> getAttribute ('longSec')); + %conf = ( + name => ($name -> hasChildNodes)?$name -> getFirstChild -> getData:undef, + category => ($cat -> hasChildNodes)?$cat -> getFirstChild -> getData:undef, + subject => ($subject -> hasChildNodes)?$subject -> getFirstChild -> getData:undef, + email => (defined ($email) and $email -> hasChildNodes)?$email -> getFirstChild -> getData:undef, + home => (defined ($home) and $home -> hasChildNodes)?$home -> getFirstChild -> getData:undef, + image => (defined ($image) and $image -> hasChildNodes)?$image -> getFirstChild -> getData:undef, + time => $date -> getAttribute ('longSec') + ); + \%conf; } -########################### -# sub get_message_header +### get_body_node () ######################################################## # -# Messagebody auslesen -########################### +# Search a specific message body in a XML tree +# +# Params: $xml XML::DOM::Document Object (Document Node) +# $mid Message ID +# Return: MessageContent XML node (or -none-) +# +sub get_body_node ($$) +{ + my ($xml, $mid) = @_; + + for ($xml->getElementsByTagName ('ContentList', 1)->item (0)->getElementsByTagName ('MessageContent', 0)) + { + return $_ if ($_ -> getAttribute ('mid') eq $mid); + } + + return; +} -sub get_message_body ($$) { - my ($xml,$mid) = @_; +### get_message_body () ######################################################## +# +# Read message body +# +# Params: $xml XML::DOM::Document Object (Document Node) +# $mid Message ID +# Return: Scalar reference +# +sub get_message_body ($$) +{ + my $cnode = get_body_node ($_[0], $_[1]); my $body; - foreach ($xml -> getElementsByTagName ('ContentList', 1) -> item (0) -> getElementsByTagName ('MessageContent', 0)) { - if ($_ -> getAttribute ('mid') eq $mid) { - $body = ($_ -> hasChildNodes)?$_ -> getFirstChild -> getData:''; - last;}} + $body = ($cnode -> hasChildNodes)?$cnode -> getFirstChild -> getData:'' if $cnode; \$body; } -########################### -# sub get_message_header +### get_message_node () ######################################################## # -# Messagenode bestimmen -########################### - -sub get_message_node ($$$) { - my ($xml,$tid,$mid) = @_; - my ($mnode,$tnode); - - for ( $xml -> getElementsByTagName ('Thread')) { - if ($_ -> getAttribute ('id') eq $tid) { +# Search a specific message in a XML tree +# +# Params: $xml XML::DOM::Document Object (Document Node) +# $tid Thread ID +# $mid Message ID +# Return: Message XML node, Thread XML node (or -none-) +# +sub get_message_node ($$$) +{ + my ($xml, $tid, $mid) = @_; + my ($mnode, $tnode); + + for ($xml->getElementsByTagName ('Thread')) + { + if ($_->getAttribute ('id') eq $tid) + { $tnode = $_; - for ($tnode -> getElementsByTagName ('Message')) { - if ($_ -> getAttribute ('id') eq $mid) { + for ($tnode -> getElementsByTagName ('Message')) + { + if ($_ -> getAttribute ('id') eq $mid) + { $mnode = $_; - last;}} - last;}} + last; + } + } + last; + } + } + + wantarray ? ($mnode, $tnode) : $mnode; +} + +### sub parse_xml_file ($) ##################################################### +# +# load the specified XML-File and create the DOM tree +# this sub is only to avoid errors and to centralize the parse process +# +# Params: $file filename +# Return: XML::DOM::Document Object (Document Node) or false +# +sub parse_xml_file ($) { + my $file = shift; + my $xml = eval { + local $SIG{__DIE__}; + new XML::DOM::Parser (KeepCDATA => 1) -> parsefile ($file); + }; + + return if ($@); - wantarray?($mnode, $tnode):$mnode; + $xml; } ########################### @@ -123,7 +184,8 @@ sub parse_single_thread ($$;$) { ip => $_ -> getAttribute ('ip'), kids => [$_ -> getElementsByTagName ('Message', 0)], answers => $_ -> getElementsByTagName ('Message') -> getLength, - deleted => ($_ -> getAttribute ('flag') eq 'deleted')?1:0, + deleted => $_ -> getAttribute ('invisible'), + archive => $_ -> getAttribute ('archive'), name => plain($header -> {name}), cat => plain($header -> {category} or ''), subject => plain($header -> {subject}), @@ -161,17 +223,19 @@ sub create_message_xml ($$$) { my $message = $xml -> createElement ('Message'); $message -> setAttribute ('id', 'm'.$msg -> {mid}); - $message -> setAttribute ('flag', 'deleted') if ($msg -> {deleted}); + $message -> setAttribute ('invisible', '1') if ($msg -> {deleted}); + $message -> setAttribute ('archive', '1') if ($msg -> {archive}); # Header erzeugen - my $header = $xml -> createElement ('Header'); + my $header = $xml -> createElement ('Header'); # alles inside of 'Header' my $author = $xml -> createElement ('Author'); - my $name = $xml -> createElement ('Name'); - $name -> addText (toUTF8($msg -> {name})); - my $email = $xml -> createElement ('Email'); + my $name = $xml -> createElement ('Name'); + $name -> addText (toUTF8($msg -> {name})); + + my $email = $xml -> createElement ('Email'); my $category = $xml -> createElement ('Category'); $category -> addText (toUTF8($msg -> {cat})); @@ -182,8 +246,8 @@ sub create_message_xml ($$$) { my $date = $xml -> createElement ('Date'); $date -> setAttribute ('longSec', $msg -> {time}); - $author -> appendChild ($name); - $author -> appendChild ($email); + $author -> appendChild ($name); + $author -> appendChild ($email); $header -> appendChild ($author); $header -> appendChild ($category); $header -> appendChild ($subject); @@ -192,7 +256,9 @@ sub create_message_xml ($$$) { if ($msg -> {kids}) { for (@{$msg -> {kids}}) { - $message -> appendChild (&create_message_xml ($xml, $msges, $_));}} + $message -> appendChild (&create_message_xml ($xml, $msges, $_)); + } + } $message; } @@ -233,62 +299,80 @@ sub sort_thread ($$) { \@smsg; } -########################### -# sub delete_messages +### delete_messages () ######################################################### # -# geoeschte Nachrichten -# herausfiltern -########################### - -sub delete_messages ($) { +# Filter out deleted messages +# +# Params: $smsg Reference of array of references of hashs +# Return: -none- +# +sub delete_messages ($) +{ my $smsg = shift; my ($z, $oldlevel, @path) = (0,0,0); - for (@$smsg) { - if ($_ -> {deleted}) { - my $n = $_ -> {answers}+1; - for (@path) {$smsg -> [$_] -> {answers} -= $n;} - splice @$smsg,$z,$n;} - - else { - if ($_ -> {level} > $oldlevel) { + for (@$smsg) + { + if ($_ -> {'deleted'}) + { + my $n = $_ -> {'answers'} + 1; + $smsg -> [$_] -> {'answers'} -= $n for (@path); + splice @$smsg,$z,$n; + } + else + { + if ($_ -> {'level'} > $oldlevel) + { push @path,$z; - $oldlevel = $_ -> {level};} - - elsif ($_ -> {level} < $oldlevel) { - splice @path,$_ -> {level}-$oldlevel; - $oldlevel = $_ -> {level};} - - else { $path[-1] = $z; } - - $z++;}} + $oldlevel = $_ -> {'level'}; + } + elsif ($_ -> {'level'} < $oldlevel) + { + splice @path,$_ -> {'level'} - $oldlevel; + $oldlevel = $_ -> {'level'}; + } + else + { + $path[-1] = $z; + } + + $z++; + } + } return; } -########################### -# sub get_all_threads +### get_all_threads () ######################################################### # -# Hauptdatei laden und -# parsen -########################### - -sub get_all_threads ($$;$) { +# Read and Parse the main file (without any XML-module, they are too slow) +# +# Params: $file /path/to/filename of the main file +# $deleted hold deleted (invisible) messages in result (1) oder not (0) +# $sorted direction of message sort: descending (0) (default) or ascending (1) +# Return: scalar context: hash reference +# list context: list (\%threads, $last_thread, $last_message, $dtd, \@unids) +# +sub get_all_threads ($$;$) +{ my ($file, $deleted, $sorted) = @_; - my ($last_thread, $last_message, @unids, %threads); - local *FILE; + my ($last_thread, $last_message, $dtd, @unids, %threads); + local (*FILE, $/); open FILE, $file or return undef; my $xml = join '', ; close(FILE) or return undef; - if (wantarray) { + if (wantarray) + { + ($dtd) = $xml =~ //; ($last_thread) = map {/(\d+)/} $xml =~ /]*>/; - ($last_message) = map {/(\d+)/} $xml =~ /]*>/;} + ($last_message) = map {/(\d+)/} $xml =~ /]*>/; + } my $reg_msg = qr~(?: - |]*>\s* + |]*>\s*
[^<]*(?:<(?!Name>)[^<]*)* ([^<]+)[^<]*(?:<(?!Category>)[^<]*)* ([^<]*)\s* @@ -296,89 +380,95 @@ sub get_all_threads ($$;$) { ]*>\s*
\s*(?:(<)/Message>|(?=(<)Message\s*)))~sx; - while ($xml =~ /([^<]*(?:<(?!\/Thread>)[^<]*)*)<\/Thread>/g) { - + while ($xml =~ /([^<]*(?:<(?!\/Thread>)[^<]*)*)<\/Thread>/g) + { my ($tid, $thread) = ($1, $2); my ($level, $cmno, @msg, @stack) = (0); - while ($thread =~ m;$reg_msg;g) { - - if (defined($9)) { + while ($thread =~ m;$reg_msg;g) + { + if (defined($10)) + { push @stack,$cmno if (defined $cmno); - push @msg, {}; - - if (defined $cmno) { + push @msg, {mid => $1, + unid => $2, + deleted => $3, + archive => $4, + name => $5, + cat => $6, + subject => $7, + time => $8, + level => $level++, + unids => [], + kids => [], + answers => 0}; + + if (defined $cmno) + { push @{$msg[$cmno] -> {kids}} => $#msg; - push @{$msg[$cmno] -> {unids}} => $2;} - else { - push @unids => $2;} + push @{$msg[$cmno] -> {unids}} => $2; + } + else + { + push @unids => $2; + } - for (@stack) {$msg[$_] -> {answers}++} + $msg[$_] -> {answers}++ for (@stack); $cmno=$#msg; - ($msg[-1] -> {mid}, - $msg[-1] -> {unid}, - $msg[-1] -> {name}, - $msg[-1] -> {cat}, - $msg[-1] -> {subject}, - $msg[-1] -> {time}) = ($1, $2, $4, $5, $6, $7); - - $msg[-1] -> {deleted} = ($3 eq 'deleted')?1:undef; - - $msg[-1] -> {name} =~ s/&/&/g; - $msg[-1] -> {cat} =~ s/&/&/g; + $msg[-1] -> {name} =~ s/&/&/g; + $msg[-1] -> {cat} =~ s/&/&/g; $msg[-1] -> {subject} =~ s/&/&/g; - $msg[-1] -> {unids} = []; - $msg[-1] -> {kids} = []; - $msg[-1] -> {answers} = 0; - $msg[-1] -> {level} = $level++;} - - elsif (defined ($8)) { - push @msg, {}; - - if (defined $cmno) { + } + elsif (defined ($9)) + { + push @msg, {mid => $1, + unid => $2, + deleted => $3, + archive => $4, + name => $5, + cat => $6, + subject => $7, + time => $8, + level => $level, + unids => [], + kids => [], + answers => 0}; + + if (defined $cmno) + { push @{$msg[$cmno] -> {kids}} => $#msg; push @{$msg[$cmno] -> {unids}} => $2; - $msg[$cmno] -> {answers}++;} - else { - push @unids => $2;} - - for (@stack) {$msg[$_] -> {answers}++} + $msg[$cmno] -> {answers}++; + } + else + { + push @unids => $2; + } - ($msg[-1] -> {mid}, - $msg[-1] -> {unid}, - $msg[-1] -> {name}, - $msg[-1] -> {cat}, - $msg[-1] -> {subject}, - $msg[-1] -> {time}) = ($1, $2, $4, $5, $6, $7); + $msg[$_] -> {answers}++ for (@stack); - $msg[-1] -> {deleted} = ($3 eq 'deleted')?1:undef; - - $msg[-1] -> {name} =~ s/&/&/g; - $msg[-1] -> {cat} =~ s/&/&/g; + $msg[-1] -> {name} =~ s/&/&/g; + $msg[-1] -> {cat} =~ s/&/&/g; $msg[-1] -> {subject} =~ s/&/&/g; + } + else + { + $cmno = pop @stack; $level--; + } + } - $msg[-1] -> {level} = $level; - $msg[-1] -> {unids} = []; - $msg[-1] -> {kids} = []; - $msg[-1] -> {answers} = 0;} - - else { - $cmno = pop @stack; $level--;}} - - # ============ - # Sortieren und bei Bedarf - # geloeschte Messages entfernen - - my $smsg = sort_thread (\@msg, $sorted); - delete_messages ($smsg) unless ($deleted); + my $smsg = sort_thread (\@msg, $sorted); # sort messages + delete_messages ($smsg) unless ($deleted); # remove invisible messages $threads{$tid} = $smsg if (@$smsg); } - wantarray?(\%threads, $last_thread, $last_message, \@unids): \%threads; + wantarray + ? (\%threads, $last_thread, $last_message, $dtd, \@unids) + : \%threads; } ########################### @@ -404,7 +494,8 @@ sub create_forum_xml_string ($$) { $level = $msg -> {level}; $xml .= ' {deleted})?' flag="deleted"':'') + .(($msg -> {deleted})?' invisible="1"':'') + .(($msg -> {archive})?' archive="1"':'') .'>' .'
' .'' @@ -432,21 +523,26 @@ sub create_forum_xml_string ($$) { \$xml; } -########################### -# sub save_file +### save_file () ############################################################### # -# Datei speichern -########################### - -sub save_file ($$) { - my ($filename,$content) = @_; +# Save a file +# +# Params: $filename Filename +# $content File content as scalar reference +# Return: Status (1 - ok, 0 - error) +# +sub save_file ($$) +{ + my ($filename, $content) = @_; local *FILE; - open FILE,">$filename.temp" or return; + open FILE, ">$filename.temp" or return; - unless (print FILE $$content) { + unless (print FILE $$content) + { close FILE; - return;}; + return; + } close FILE or return; @@ -473,8 +569,8 @@ sub save_file ($$) { ########################### sub hr_time ($) { - my @month = qw(Januar Februar M\303\244rz April Mail Juni Juli August September Oktober November Dezember); - # ^^^^^^^^ - UTF8 # + my @month = (qw(Januar Februar), "M\303\244rz", qw(April Mail Juni Juli August September Oktober November Dezember)); + # ^^^^^^^^ - UTF8 # my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]); @@ -488,8 +584,8 @@ sub short_hr_time ($) { } sub long_hr_time ($) { - my @month = qw(Januar Februar M\303\244rz April Mail Juni Juli August September Oktober November Dezember); - # ^^^^^^^^ - UTF8 # + my @month = (qw(Januar Februar), "M\303\244rz", qw(April Mail Juni Juli August September Oktober November Dezember)); + # ^^^^^^^^ - UTF8 # my @wday = qw(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag); my ($sek, $min, $hour, $day, $mon, $year, $wday) = localtime ($_[0]); @@ -502,8 +598,4 @@ sub long_hr_time ($) { # ==================================================== # making require happy -1; - -# ==================================================== -# end of Posting::_lib -# ==================================================== \ No newline at end of file +1; \ No newline at end of file