]>
git.p6c8.net - selfforum.git/blob - selfforum-cgi/shared/Posting/_lib.pm
3 ################################################################################
5 # File: shared/Posting/_lib.pm #
7 # Authors: André Malo <nd@o3media.de>, 2001-02-25 #
8 # Frank Schoenmann <fs@tower.de>, 2001-03-02 #
10 # Description: Message access interface, time format routines #
12 ################################################################################
16 use vars
qw(@EXPORT_OK);
17 use base qw(Exporter);
19 use Encode
::Plain
; $Encode::Plain
::utf8
= 1;
23 # ====================================================
25 # ====================================================
27 @EXPORT_OK = qw(get_message_header get_message_body get_message_node parse_single_thread
28 hr_time short_hr_time long_hr_time
29 get_all_threads create_forum_xml_string
32 # ====================================================
34 # ====================================================
36 ### get_message_header () ######################################################
38 # Read message header, return as a hash
40 # Params: $node XML message node
41 # Return: Hash reference (name, category, subject, email, home, image, time)
43 sub get_message_header
($)
48 my $header = $node -> getElementsByTagName
('Header', 0) -> item
(0);
49 my $author = $header -> getElementsByTagName
('Author', 0) -> item
(0);
50 my $name = $author -> getElementsByTagName
('Name', 0) -> item
(0);
51 my $email = $author -> getElementsByTagName
('Email', 0) -> item
(0);
52 my $home = $author -> getElementsByTagName
('HomepageUrl', 0) -> item
(0);
53 my $image = $author -> getElementsByTagName
('ImageUrl', 0) -> item
(0);
54 my $cat = $header -> getElementsByTagName
('Category', 0) -> item
(0);
55 my $subject = $header -> getElementsByTagName
('Subject', 0) -> item
(0);
56 my $date = $header -> getElementsByTagName
('Date', 0) -> item
(0);
59 name
=> ($name -> hasChildNodes
)?
$name -> getFirstChild
-> getData
:undef,
60 category
=> ($cat -> hasChildNodes
)?
$cat -> getFirstChild
-> getData
:undef,
61 subject
=> ($subject -> hasChildNodes
)?
$subject -> getFirstChild
-> getData
:undef,
62 email
=> (defined ($email) and $email -> hasChildNodes
)?
$email -> getFirstChild
-> getData
:undef,
63 home
=> (defined ($home) and $home -> hasChildNodes
)?
$home -> getFirstChild
-> getData
:undef,
64 image
=> (defined ($image) and $image -> hasChildNodes
)?
$image -> getFirstChild
- >getData
:undef,
65 time => $date -> getAttribute
('longSec')
71 ### get_message_body () ########################################################
75 # Params: $xml XML tree
77 # Return: Scalar reference
79 sub get_message_body
($$)
84 foreach ($xml->getElementsByTagName ('ContentList', 1)->item (0)->getElementsByTagName ('MessageContent', 0))
86 if ($_ -> getAttribute
('mid') eq $mid)
88 $body = ($_ -> hasChildNodes
)?
$_ -> getFirstChild
-> getData
:'';
96 ### get_message_node () ########################################################
98 # Search a specific message in a XML tree
100 # Params: $xml XML tree
103 # Return: Message XML node, Thread XML node
105 sub get_message_node
($$$)
107 my ($xml, $tid, $mid) = @_;
110 for ($xml->getElementsByTagName ('Thread'))
112 if ($_->getAttribute ('id') eq $tid)
115 for ($tnode -> getElementsByTagName
('Message'))
117 if ($_ -> getAttribute
('id') eq $mid)
127 wantarray ?
($mnode, $tnode) : $mnode;
130 ###########################
131 # sub parse_single_thread
133 # einzelne Threaddatei
135 ###########################
137 sub parse_single_thread
($$;$) {
138 my ($tnode, $deleted, $sorted) = @_;
139 my ($header, @msg, %mno);
141 for ($tnode -> getElementsByTagName
('Message')) {
142 $header = get_message_header
($_);
144 push @msg,{mid
=> ($_ -> getAttribute
('id') =~ /(\d+)/)[0],
145 ip
=> $_ -> getAttribute
('ip'),
146 kids
=> [$_ -> getElementsByTagName
('Message', 0)],
147 answers
=> $_ -> getElementsByTagName
('Message') -> getLength
,
148 deleted
=> $_ -> getAttribute
('invisible'),
149 archive
=> $_ -> getAttribute
('archive'),
150 name
=> plain
($header -> {name
}),
151 cat
=> plain
($header -> {category
} or ''),
152 subject
=> plain
($header -> {subject
}),
153 time => plain
($header -> {time})};
156 # Eintraege ergaenzen und korrigieren
158 $msg[0] -> {level
} = 0;
160 $level = $_ -> {level
} + 1;
161 @
{$_ -> {kids
}} = map {$msg[$mno{$_}] -> {level
} = $level; $mno{$_}} @
{$_ -> {kids
}};}
164 # Sortieren und bei Bedarf
165 # geloeschte Messages entfernen
167 my $smsg = sort_thread
(\
@msg, $sorted);
168 delete_messages
($smsg) unless ($deleted);
173 ###########################
174 # sub create_message_xml
178 ###########################
180 sub create_message_xml
($$$) {
181 my ($xml, $msges, $num) = @_;
183 my $msg = $msges -> [$num];
185 my $message = $xml -> createElement
('Message');
186 $message -> setAttribute
('id', 'm'.$msg -> {mid
});
187 $message -> setAttribute
('invisible', '1') if ($msg -> {deleted
});
188 $message -> setAttribute
('archive', '1') if ($msg -> {archive
});
191 my $header = $xml -> createElement
('Header');
193 # alles inside of 'Header'
194 my $author = $xml -> createElement
('Author');
196 my $name = $xml -> createElement
('Name');
197 $name -> addText
(toUTF8
($msg -> {name
}));
199 my $email = $xml -> createElement
('Email');
201 my $category = $xml -> createElement
('Category');
202 $category -> addText
(toUTF8
($msg -> {cat
}));
204 my $subject = $xml -> createElement
('Subject');
205 $subject -> addText
(toUTF8
($msg -> {subject
}));
207 my $date = $xml -> createElement
('Date');
208 $date -> setAttribute
('longSec', $msg -> {time});
210 $author -> appendChild
($name);
211 $author -> appendChild
($email);
212 $header -> appendChild
($author);
213 $header -> appendChild
($category);
214 $header -> appendChild
($subject);
215 $header -> appendChild
($date);
216 $message -> appendChild
($header);
218 if ($msg -> {kids
}) {
219 for (@
{$msg -> {kids
}}) {
220 $message -> appendChild
(&create_message_xml
($xml, $msges, $_));
227 # ====================================================
228 # XML-Parsen von Hand
229 # ====================================================
231 ###########################
236 ###########################
238 sub sort_thread
($$) {
239 my ($msg, $sorted) = @_;
241 my ($z, %mhash) = (0);
243 if ($sorted) { # aelteste zuerst
245 @
$msg[@
{$_ -> {kids
}}] = sort {$a -> {mid
} <=> $b -> {mid
}} @
$msg[@
{$_ -> {kids
}}] if (@
{$_ -> {kids
}} > 1);
246 $mhash{$_ -> {mid
}} = [@
$msg[@
{$_ -> {kids
}}]];}}
248 else { # juengste zuerst
250 @
$msg[@
{$_ -> {kids
}}] = sort {$b -> {mid
} <=> $a -> {mid
}} @
$msg[@
{$_ -> {kids
}}] if (@
{$_ -> {kids
}} > 1);
251 $mhash{$_ -> {mid
}} = [@
$msg[@
{$_ -> {kids
}}]];}}
253 # Kinder wieder richtig einsortieren
254 my @smsg = ($msg -> [0]);
257 splice @smsg,$z,0,@
{$mhash{$_ -> {mid
}}} if ($_ -> {answers
});
258 delete $_ -> {kids
};}
263 ### delete_message () ##########################################################
265 # Filter out deleted messages
267 # Params: $smsg Reference of array of references of hashs
270 sub delete_messages
($)
274 my ($z, $oldlevel, @path) = (0,0,0);
278 if ($_ -> {'deleted'})
280 my $n = $_ -> {'answers'} + 1;
283 $smsg -> [$_] -> {'answers'} -= $n;
289 if ($_ -> {'level'} > $oldlevel)
292 $oldlevel = $_ -> {'level'};
294 elsif ($_ -> {'level'} < $oldlevel)
296 splice @path,$_ -> {'level'} - $oldlevel;
297 $oldlevel = $_ -> {'level'};
311 ###########################
312 # sub get_all_threads
314 # Hauptdatei laden und
316 ###########################
318 sub get_all_threads
($$;$)
320 my ($file, $deleted, $sorted) = @_;
321 my ($last_thread, $last_message, @unids, %threads);
324 open FILE
, $file or return undef;
325 my $xml = join '', <FILE
>;
326 close(FILE
) or return undef;
329 ($last_thread) = map {/(\d+)/} $xml =~ /<Forum.+?lastThread="([^"]+)"[^>]*>/;
330 ($last_message) = map {/(\d+)/} $xml =~ /<Forum.+?lastMessage="([^"]+)"[^>]*>/;}
332 my $reg_msg = qr
~(?
:</Message
>
333 |<Message\s
+id
="m(\d+)"\s
+unid
="([^"]*)"(?:\s+invisible="([^"]*)")?
(?
:\s
+archive
="([^"]*)")?[^>]*>\s*
334 <Header>[^<]*(?:<(?!Name>)[^<]*)*
335 <Name>([^<]+)</Name>[^<]*(?:<(?!Category>)[^<]*)*
336 <Category>([^<]*)</Category>\s*
337 <Subject>([^<]+)</Subject>\s*
338 <Date\s+longSec="(\d
+)"[^>]*>\s*
339 </Header>\s*(?:(<)/Message>|(?=(<)Message\s*)))~sx;
341 while ($xml =~ /<Thread id="t
(\d
+)">([^<]*(?:<(?!\/Thread>)[^<]*)*)<\/Thread>/g) {
343 my ($tid, $thread) = ($1, $2);
344 my ($level, $cmno, @msg, @stack) = (0);
346 while ($thread =~ m;$reg_msg;g) {
349 push @stack,$cmno if (defined $cmno);
353 push @{$msg[$cmno] -> {kids}} => $#msg;
354 push @{$msg[$cmno] -> {unids}} => $2;}
358 for (@stack) {$msg[$_] -> {answers}++}
366 $msg[-1] -> {subject},
367 $msg[-1] -> {time}) = ($1, $2, $5, $6, $7, $8);
369 $msg[-1] -> {deleted} = $3;
370 $msg[-1] -> {archive} = $4;
372 $msg[-1] -> {name} =~ s/&/&/g;
373 $msg[-1] -> {cat} =~ s/&/&/g;
374 $msg[-1] -> {subject} =~ s/&/&/g;
376 $msg[-1] -> {unids} = [];
377 $msg[-1] -> {kids} = [];
378 $msg[-1] -> {answers} = 0;
379 $msg[-1] -> {level} = $level++;}
381 elsif (defined ($9)) {
385 push @{$msg[$cmno] -> {kids}} => $#msg;
386 push @{$msg[$cmno] -> {unids}} => $2;
387 $msg[$cmno] -> {answers}++;}
391 for (@stack) {$msg[$_] -> {answers}++}
397 $msg[-1] -> {subject},
398 $msg[-1] -> {time}) = ($1, $2, $5, $6, $7, $8);
400 $msg[-1] -> {deleted} = $3;
401 $msg[-1] -> {archive} = $4;
403 $msg[-1] -> {name} =~ s/&/&/g;
404 $msg[-1] -> {cat} =~ s/&/&/g;
405 $msg[-1] -> {subject} =~ s/&/&/g;
407 $msg[-1] -> {level} = $level;
408 $msg[-1] -> {unids} = [];
409 $msg[-1] -> {kids} = [];
410 $msg[-1] -> {answers} = 0;}
413 $cmno = pop @stack; $level--;}}
416 # Sortieren und bei Bedarf
417 # geloeschte Messages entfernen
419 my $smsg = sort_thread (\@msg, $sorted);
420 delete_messages ($smsg) unless ($deleted);
422 $threads{$tid} = $smsg if (@$smsg);
425 wantarray ? (\%threads, $last_thread, $last_message, \@unids) : \%threads;
428 ###########################
429 # sub create_forum_xml_string
431 # Forumshauptdatei erzeugen
432 ###########################
434 sub create_forum_xml_string ($$) {
435 my ($threads, $param) = @_;
436 my ($level, $thread, $msg);
438 my $xml = '<?xml version="1.0" encoding="UTF
-8"?>'."\n"
439 .'<!DOCTYPE Forum SYSTEM "'.$param -> {dtd}.'">'."\n"
440 .'<Forum lastMessage="'.$param -> {lastMessage}.'" lastThread="'.$param -> {lastThread}.'">';
442 foreach $thread (sort {$b <=> $a} keys %$threads) {
443 $xml .= '<Thread id="t
'.$thread.'">';
446 foreach $msg (@{$threads -> {$thread}}) {
447 $xml .= '</Message>' x ($level - $msg -> {level} + 1) if ($msg -> {level} <= $level);
448 $level = $msg -> {level};
449 $xml .= '<Message id="m
'.$msg -> {mid}.'"'
450 .' unid="'.$msg -> {unid}.'"'
451 .(($msg -> {deleted})?' invisible="1"':'')
452 .(($msg -> {archive})?' archive="1"':'')
457 .plain($msg -> {name})
462 .((length $msg -> {cat})?plain($msg -> {cat}):'')
465 .plain($msg -> {subject})
472 $xml .= '</Message>' x ($level + 1);
473 $xml .= '</Thread>';}
480 ### save_file () ###############################################################
484 # Params: $filename Filename
485 # $content File content as scalar reference
486 # Return: Status (1 - ok, 0 - error)
490 my ($filename, $content) = @_;
493 open FILE, ">$filename.temp
" or return;
495 unless (print FILE $$content)
501 close FILE or return;
503 rename "$filename.temp
", $filename or return;
508 # ====================================================
510 # ====================================================
512 ###########################
514 # 02. Januar 2001, 12:02 Uhr
517 # 02. 01. 2001, 12:02 Uhr
520 # Dienstag, 02. Januar 2001, 12:02:01 Uhr
522 # formatierte Zeitangabe
523 ###########################
526 my @month = (qw(Januar Februar), "M\303\244rz", qw(April Mail Juni Juli August September Oktober November Dezember));
529 my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
531 sprintf ('%02d. %s %04d, %02d:%02d Uhr', $day, $month[$mon], $year+1900, $hour, $min);
534 sub short_hr_time
($) {
535 my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
537 sprintf ('%02d. %02d. %04d, %02d:%02d Uhr', $day, $mon+1, $year+1900, $hour, $min);
540 sub long_hr_time
($) {
541 my @month = (qw(Januar Februar), "M\303\244rz", qw(April Mail Juni Juli August September Oktober November Dezember));
544 my @wday = qw(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag);
545 my ($sek, $min, $hour, $day, $mon, $year, $wday) = localtime ($_[0]);
547 sprintf ('%s, %02d. %s %04d, %02d:%02d:%02d Uhr', $wday[$wday], $day, $month[$mon], $year+1900, $hour, $min, $sek);
550 # ====================================================
551 # Modulinitialisierung
552 # ====================================================
554 # making require happy
patrick-canterino.de