# #
# File: shared/Posting/_lib.pm #
# #
-# Authors: André Malo <nd@o3media.de>, 2001-06-11 #
-# Frank Schoenmann <fs@tower.de>, 2001-06-04 #
+# Authors: André Malo <nd@o3media.de> #
+# Frank Schönmann <fs@tower.de> #
# #
# Description: Message access interface, time format routines #
# #
################################################################################
use strict;
+use vars qw(
+ @EXPORT_OK
+);
use Encode::Plain; $Encode::Plain::utf8 = 1;
-use Time::German;
+use Time::German qw(localtime);
use XML::DOM;
-# ====================================================
-# Export
-# ====================================================
+################################################################################
+#
+# Version check
+#
+# last modified:
+# $Date$ (GMT)
+# by $Author$
+#
+sub VERSION {(q$Revision$ =~ /([\d.]+)\s*$/)[0] or '0.0'}
-use constant SORT_ASCENT => 0; # (young postings first)
+################################################################################
+#
+# Export
+#
+use constant SORT_ASCENT => 0; # (latest postings first)
use constant SORT_DESCENT => 1;
use constant KEEP_DELETED => 1;
use constant KILL_DELETED => 0;
+use constant FORUM_DTD => 'http://selfforum.sourceforge.net/dtd/forum.dtd';
+
use base qw(Exporter);
-@Posting::_lib::EXPORT_OK = qw(
+@EXPORT_OK = qw(
get_message_header
get_message_body
get_message_node
KILL_DELETED
);
-# ====================================================
+################################################################################
+#
# Access via XML::DOM
-# ====================================================
+#
### sub create_message ($$) ####################################################
#
# create a XML::DOM::Document object of a thread containing one posting
#
# Params: hash reference
-# (dtd, thread, msg, body, ip, name, email, home,
+# (thread, msg, body, ip, name, email, home,
# image, category, subject, time)
#
# Return: XML::DOM::Document object
# set doctype
#
- my $dtd = $xml -> createDocumentType ('Forum' => $par -> {dtd});
+ my $dtd = $xml -> createDocumentType ('Forum' => FORUM_DTD);
$xml -> setDoctype ($dtd);
# create root element 'Forum'
$xml;
}
-###########################
-# sub parse_single_thread
+### parse_single_thread () #####################################################
+#
+# parse a thread file
+#
+# Params: $tnode - Thread element node
+# $deleted - keep deleted (boolean)
+# $sorted - sorting order
+#
+# Return: arrayref
#
-# einzelne Threaddatei
-# parsen
-###########################
-
sub parse_single_thread ($$;$) {
my ($tnode, $deleted, $sorted) = @_;
my ($header, @msg, %mno);
for ($tnode -> getElementsByTagName ('Message')) {
$header = get_message_header ($_);
- push @msg,{mid => ($_ -> getAttribute ('id') =~ /(\d+)/)[0],
- ip => $_ -> getAttribute ('ip'),
- kids => [$_ -> getElementsByTagName ('Message', 0)],
- answers => $_ -> getElementsByTagName ('Message') -> getLength,
- deleted => $_ -> getAttribute ('invisible'),
- archive => $_ -> getAttribute ('archive'),
- name => plain($header -> {name}),
- cat => plain($header -> {category} or ''),
- subject => plain($header -> {subject}),
- time => plain($header -> {time})};
- $mno{$_} = $#msg;}
-
- # Eintraege ergaenzen und korrigieren
+ push @msg => {
+ mid => ($_ -> getAttribute ('id') =~ /(\d+)/)[0],
+ ip => $_ -> getAttribute ('ip'),
+ kids => [$_ -> getElementsByTagName ('Message', 0)],
+ answers => $_ -> getElementsByTagName ('Message') -> getLength,
+ deleted => $_ -> getAttribute ('invisible'),
+ archive => $_ -> getAttribute ('archive'),
+ name => plain($header -> {name}),
+ cat => plain($header -> {category} or ''),
+ subject => plain($header -> {subject}),
+ time => plain($header -> {time})
+ };
+ $mno{$_} = $#msg;
+ }
+
my $level;
$msg[0] -> {level} = 0;
for (@msg) {
$level = $_ -> {level} + 1;
- @{$_ -> {kids}} = map {$msg[$mno{$_}] -> {level} = $level; $mno{$_}} @{$_ -> {kids}};}
-
- # ============
- # Sortieren und bei Bedarf
- # geloeschte Messages entfernen
+ @{$_ -> {kids}} = map {$msg[$mno{$_}] -> {level} = $level; $mno{$_}} @{$_ -> {kids}};
+ }
+ # sort and process deleted files
+ #
my $smsg = sort_thread (\@msg, $sorted);
delete_messages ($smsg) unless ($deleted);
$smsg;
}
-###########################
-# sub create_message_xml
+################################################################################
#
-# Message-XML-String
-# erzeugen
-###########################
-
-sub create_message_xml ($$$) {
- my ($xml, $msges, $num) = @_;
-
- my $msg = $msges -> [$num];
-
- my $message = $xml -> createElement ('Message');
- $message -> setAttribute ('id', 'm'.$msg -> {mid});
- $message -> setAttribute ('invisible', '1') if ($msg -> {deleted});
- $message -> setAttribute ('archive', '1') if ($msg -> {archive});
-
- # Header erzeugen
- 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 $category = $xml -> createElement ('Category');
- $category -> addText (toUTF8($msg -> {cat}));
-
- my $subject = $xml -> createElement ('Subject');
- $subject -> addText (toUTF8($msg -> {subject}));
-
- my $date = $xml -> createElement ('Date');
- $date -> setAttribute ('longSec', $msg -> {time});
-
- $author -> appendChild ($name);
- $author -> appendChild ($email);
- $header -> appendChild ($author);
- $header -> appendChild ($category);
- $header -> appendChild ($subject);
- $header -> appendChild ($date);
- $message -> appendChild ($header);
-
- if ($msg -> {kids}) {
- for (@{$msg -> {kids}}) {
- $message -> appendChild (&create_message_xml ($xml, $msges, $_));
- }
- }
-
- $message;
-}
-
-# ====================================================
-# XML-Parsen von Hand
-# ====================================================
-
-###########################
-# sub sort_thread
+# Access via regexps and native perl ;)
#
-# Messages eines
-# Threads sortieren
-###########################
+### sort_thread () #############################################################
+#
+# sort the message array
+#
+# Params: $msg - arrayref
+# $sorted - sorting order
+#
+# Return: sorted arrayref
+#
sub sort_thread ($$) {
my ($msg, $sorted) = @_;
my ($z, %mhash) = (0);
- if ($sorted) { # aelteste zuerst
+ if ($sorted) { # oldest first
for (@$msg) {
@$msg[@{$_ -> {kids}}] = sort {$a -> {mid} <=> $b -> {mid}} @$msg[@{$_ -> {kids}}] if (@{$_ -> {kids}} > 1);
$mhash{$_ -> {mid}} = [@$msg[@{$_ -> {kids}}]];}}
- else { # juengste zuerst
+ else { # latest first
for (@$msg) {
@$msg[@{$_ -> {kids}}] = sort {$b -> {mid} <=> $a -> {mid}} @$msg[@{$_ -> {kids}}] if (@{$_ -> {kids}} > 1);
$mhash{$_ -> {mid}} = [@$msg[@{$_ -> {kids}}]];}}
- # Kinder wieder richtig einsortieren
+ # sort the children
+ #
my @smsg = ($msg -> [0]);
for (@smsg) {
++$z;
splice @smsg,$z,0,@{$mhash{$_ -> {mid}}} if ($_ -> {answers});
- delete $_ -> {kids};}
+ delete $_ -> {kids};
+ }
+ # return
\@smsg;
}
close(FILE) or return;
if (wantarray) {
- ($dtd) = $xml =~ /<!DOCTYPE\s+\S+\s+SYSTEM\s+"([^"]+)">/;
+ $dtd = FORUM_DTD;
($last_thread) = map {/(\d+)/} $xml =~ /<Forum.+?lastThread="([^"]+)"[^>]*>/;
($last_message) = map {/(\d+)/} $xml =~ /<Forum.+?lastMessage="([^"]+)"[^>]*>/;
}
my $reg_msg = qr~(?:</Message>
- |<Message\s+id="m(\d+)"\s+unid="([^"]*)"(?:\s+invisible="([^"]*)")?(?:\s+archive="([^"]*)")?[^>]*>\s*
+ |<Message\s+id="m(\d+)"(?:\s+unid="([^"]*)")?(?:\s+invisible="([^"]*)")?(?:\s+archive="([^"]*)")?[^>]*>\s*
<Header>[^<]*(?:<(?!Name>)[^<]*)*
<Name>([^<]+)</Name>[^<]*(?:<(?!Category>)[^<]*)*
<Category>([^<]*)</Category>\s*
push @stack,$cmno if (defined $cmno);
push @msg, {
mid => $1,
- unid => $2,
+ unid => (defined $2) ? $2 : '',
deleted => $3 || 0,
archive => $4 || 0,
name => $5,
if (defined $cmno)
{
push @{$msg[$cmno] -> {kids}} => $#msg;
- push @{$msg[$cmno] -> {unids}} => $2;
+ push @{$msg[$cmno] -> {unids}} => (defined $2) ? $2 : '#';
}
else
{
- push @unids => $2;
+ push @unids => (defined $2) ? $2 : '';
}
$msg[$_] -> {answers}++ for (@stack);
{
push @msg, {
mid => $1,
- unid => $2,
+ unid => (defined $2) ? $2 : '',
deleted => $3 || 0,
archive => $4 || 0,
name => $5,
if (defined $cmno)
{
push @{$msg[$cmno] -> {kids}} => $#msg;
- push @{$msg[$cmno] -> {unids}} => $2;
+ push @{$msg[$cmno] -> {unids}} => (defined $2) ? $2 : '';
$msg[$cmno] -> {answers}++;
}
else
{
- push @unids => $2;
+ push @unids => (defined $2) ? $2 : '';
}
$msg[$_] -> {answers}++ for (@stack);
my ($level, $thread, $msg);
my $xml =
- '<?xml version="1.0" encoding="UTF-8"?>'."\n"
- . '<!DOCTYPE Forum SYSTEM "'.$param -> {dtd}.'">'."\n"
- . '<Forum lastMessage="'.$param -> {lastMessage}.'" lastThread="'.$param -> {lastThread}.'">';
+ '<?xml version="1.0"?>'."\n"
+ . '<!DOCTYPE Forum SYSTEM "'.FORUM_DTD.'">'."\n"
+ . '<Forum lastMessage="m'.($param->{lastMessage} =~ /(\d+)/)[0].'" lastThread="t'.($param->{lastThread} =~ /(\d+)/)[0].'">';
for $thread (sort {$b <=> $a} keys %$threads) {
$xml .= '<Thread id="t'.$thread.'">';
$level = $msg -> {level};
$xml .=
'<Message id="m'.$msg -> {mid}.'"'
- . ' unid="'.$msg -> {unid}.'"'
+ . (($msg -> {unid}) ?' unid="'.$msg -> {unid}.'"':'')
. (($msg -> {deleted})?' invisible="1"':'')
. (($msg -> {archive})?' archive="1"':'')
. '>'
}
sub hr_time ($) {
- my (undef, $min, $hour, $day, $mon, $year) = germantime (shift);
+ my (undef, $min, $hour, $day, $mon, $year) = localtime (shift);
sprintf ('%02d. %s %04d, %02d:%02d Uhr', $day, month($mon+1), $year+1900, $hour, $min);
}
sub short_hr_time ($) {
- my (undef, $min, $hour, $day, $mon, $year) = germantime (shift);
+ my (undef, $min, $hour, $day, $mon, $year) = localtime (shift);
sprintf ('%02d. %02d. %04d, %02d:%02d Uhr', $day, $mon+1, $year+1900, $hour, $min);
}
sub long_hr_time ($) {
my @wday = qw(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag);
- my ($sek, $min, $hour, $day, $mon, $year, $wday) = germantime (shift);
+ my ($sek, $min, $hour, $day, $mon, $year, $wday) = localtime (shift);
sprintf ('%s, %02d. %s %04d, %02d:%02d:%02d Uhr', $wday[$wday], $day, month($mon+1), $year+1900, $hour, $min, $sek);
}
sub very_short_hr_time($) {
- my (undef, $min, $hour, $day, $mon, $year) = germantime (shift);
+ my (undef, $min, $hour, $day, $mon, $year) = localtime (shift);
sprintf ('%02d. %02d. %04d', $day, $mon+1, $year+1900);
}
#
#
-### end of Posting::_lib #######################################################
+### end of Posting::_lib #######################################################
\ No newline at end of file