]>
git.p6c8.net - selfforum.git/blob - selfforum-cgi/shared/Posting/_lib.pm
587ed9aa4e484660fea0b42fc315c40624e60b24
3 # ====================================================
4 # Autor: n.d.p. / 2001-01-07
5 # lm : n.d.p. / 2001-02-25
6 # ====================================================
8 # * Schnittstellen fuer den Zugriff auf Messages
10 # ====================================================
14 package Posting
::_lib
;
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
30 create_forum_xml_string
33 # ====================================================
35 # ====================================================
37 ###########################
38 # sub get_message_header
40 # Messageheader auslesen
41 ###########################
43 sub get_message_header
($) {
47 my $header = $node -> getElementsByTagName
('Header', 0) -> item
(0);
48 my $author = $header -> getElementsByTagName
('Author', 0) -> item
(0);
49 my $name = $author -> getElementsByTagName
('Name', 0) -> item
(0);
50 my $email = $author -> getElementsByTagName
('Email', 0) -> item
(0);
51 my $home = $author -> getElementsByTagName
('HomepageUrl', 0) -> item
(0);
52 my $image = $author -> getElementsByTagName
('ImageUrl', 0) -> item
(0);
53 my $cat = $header -> getElementsByTagName
('Category', 0) -> item
(0);
54 my $subject = $header -> getElementsByTagName
('Subject', 0) -> item
(0);
55 my $date = $header -> getElementsByTagName
('Date', 0) -> item
(0);
57 %conf = (name
=> ($name -> hasChildNodes
)?
$name -> getFirstChild
-> getData
:undef,
58 category
=> ($cat -> hasChildNodes
)?
$cat -> getFirstChild
-> getData
:undef,
59 subject
=> ($subject -> hasChildNodes
)?
$subject -> getFirstChild
-> getData
:undef,
60 email
=> (defined ($email) and $email -> hasChildNodes
)?
$email -> getFirstChild
-> getData
:undef,
61 home
=> (defined ($home) and $home -> hasChildNodes
)?
$home -> getFirstChild
-> getData
:undef,
62 image
=> (defined ($image) and $image -> hasChildNodes
)?
$image -> getFirstChild
-> getData
:undef,
63 time => $date -> getAttribute
('longSec'));
67 ###########################
68 # sub get_message_header
70 # Messagebody auslesen
71 ###########################
73 sub get_message_body
($$) {
77 foreach ($xml -> getElementsByTagName
('ContentList', 1) -> item
(0) -> getElementsByTagName
('MessageContent', 0)) {
78 if ($_ -> getAttribute
('mid') eq $mid) {
79 $body = ($_ -> hasChildNodes
)?
$_ -> getFirstChild
-> getData
:'';
85 ###########################
86 # sub get_message_header
88 # Messagenode bestimmen
89 ###########################
91 sub get_message_node
($$$) {
92 my ($xml,$tid,$mid) = @_;
95 for ( $xml -> getElementsByTagName
('Thread')) {
96 if ($_ -> getAttribute
('id') eq $tid) {
98 for ($tnode -> getElementsByTagName
('Message')) {
99 if ($_ -> getAttribute
('id') eq $mid) {
104 wantarray?
($mnode, $tnode):$mnode;
107 ###########################
108 # sub parse_single_thread
110 # einzelne Threaddatei
112 ###########################
114 sub parse_single_thread
($$;$) {
115 my ($tnode, $deleted, $sorted) = @_;
116 my ($header, @msg, %mno);
118 for ($tnode -> getElementsByTagName
('Message')) {
119 $header = get_message_header
($_);
121 push @msg,{mid
=> ($_ -> getAttribute
('id') =~ /(\d+)/)[0],
122 ip
=> $_ -> getAttribute
('ip'),
123 kids
=> [$_ -> getElementsByTagName
('Message', 0)],
124 answers
=> $_ -> getElementsByTagName
('Message') -> getLength
,
125 deleted
=> ($_ -> getAttribute
('flag') eq 'deleted')?
1:0,
126 name
=> plain
($header -> {name
}),
127 cat
=> plain
($header -> {category
} or ''),
128 subject
=> plain
($header -> {subject
}),
129 time => plain
($header -> {time})};
132 # Eintraege ergaenzen und korrigieren
134 $msg[0] -> {level
} = 0;
136 $level = $_ -> {level
} + 1;
137 @
{$_ -> {kids
}} = map {$msg[$mno{$_}] -> {level
} = $level; $mno{$_}} @
{$_ -> {kids
}};}
140 # Sortieren und bei Bedarf
141 # geloeschte Messages entfernen
143 my $smsg = sort_thread
(\
@msg, $sorted);
144 delete_messages
($smsg) unless ($deleted);
149 ###########################
150 # sub create_message_xml
154 ###########################
156 sub create_message_xml
($$$) {
157 my ($xml, $msges, $num) = @_;
159 my $msg = $msges -> [$num];
161 my $message = $xml -> createElement
('Message');
162 $message -> setAttribute
('id', 'm'.$msg -> {mid
});
163 $message -> setAttribute
('flag', 'deleted') if ($msg -> {deleted
});
166 my $header = $xml -> createElement
('Header');
168 # alles inside of 'Header'
169 my $author = $xml -> createElement
('Author');
170 my $name = $xml -> createElement
('Name');
171 $name -> addText
(toUTF8
($msg -> {name
}));
173 my $email = $xml -> createElement
('Email');
175 my $category = $xml -> createElement
('Category');
176 $category -> addText
(toUTF8
($msg -> {cat
}));
178 my $subject = $xml -> createElement
('Subject');
179 $subject -> addText
(toUTF8
($msg -> {subject
}));
181 my $date = $xml -> createElement
('Date');
182 $date -> setAttribute
('longSec', $msg -> {time});
184 $author -> appendChild
($name);
185 $author -> appendChild
($email);
186 $header -> appendChild
($author);
187 $header -> appendChild
($category);
188 $header -> appendChild
($subject);
189 $header -> appendChild
($date);
190 $message -> appendChild
($header);
192 if ($msg -> {kids
}) {
193 for (@
{$msg -> {kids
}}) {
194 $message -> appendChild
(&create_message_xml
($xml, $msges, $_));}}
199 # ====================================================
200 # XML-Parsen von Hand
201 # ====================================================
203 ###########################
208 ###########################
210 sub sort_thread
($$) {
211 my ($msg, $sorted) = @_;
213 my ($z, %mhash) = (0);
215 if ($sorted) { # aelteste zuerst
217 @
$msg[@
{$_ -> {kids
}}] = sort {$a -> {mid
} <=> $b -> {mid
}} @
$msg[@
{$_ -> {kids
}}] if (@
{$_ -> {kids
}} > 1);
218 $mhash{$_ -> {mid
}} = [@
$msg[@
{$_ -> {kids
}}]];}}
220 else { # juengste zuerst
222 @
$msg[@
{$_ -> {kids
}}] = sort {$b -> {mid
} <=> $a -> {mid
}} @
$msg[@
{$_ -> {kids
}}] if (@
{$_ -> {kids
}} > 1);
223 $mhash{$_ -> {mid
}} = [@
$msg[@
{$_ -> {kids
}}]];}}
225 # Kinder wieder richtig einsortieren
226 my @smsg = ($msg -> [0]);
229 splice @smsg,$z,0,@
{$mhash{$_ -> {mid
}}} if ($_ -> {answers
});
230 delete $_ -> {kids
};}
235 ###########################
236 # sub delete_messages
238 # geoeschte Nachrichten
240 ###########################
242 sub delete_messages
($) {
245 my ($z, $oldlevel, @path) = (0,0,0);
248 if ($_ -> {deleted
}) {
249 my $n = $_ -> {answers
}+1;
250 for (@path) {$smsg -> [$_] -> {answers
} -= $n;}
251 splice @
$smsg,$z,$n;}
254 if ($_ -> {level
} > $oldlevel) {
256 $oldlevel = $_ -> {level
};}
258 elsif ($_ -> {level
} < $oldlevel) {
259 splice @path,$_ -> {level
}-$oldlevel;
260 $oldlevel = $_ -> {level
};}
262 else { $path[-1] = $z; }
269 ###########################
270 # sub get_all_threads
272 # Hauptdatei laden und
274 ###########################
276 sub get_all_threads
($$;$) {
277 my ($file, $deleted, $sorted) = @_;
278 my ($last_thread, $last_message, @unids, %threads);
281 open FILE
, $file or return undef;
282 my $xml = join '', <FILE
>;
283 close(FILE
) or return undef;
286 ($last_thread) = map {/(\d+)/} $xml =~ /<Forum.+?lastThread="([^"]+)"[^>]*>/;
287 ($last_message) = map {/(\d+)/} $xml =~ /<Forum.+?lastMessage="([^"]+)"[^>]*>/;}
289 my $reg_msg = qr
~(?
:</Message
>
290 |<Message\s
+id
="m(\d+)"\s
+unid
="([^"]*)"(?:\s+flag="([^"]*)")?
[^>]*>\s
*
291 <Header
>[^<]*(?
:<(?
!Name
>)[^<]*)*
292 <Name
>([^<]+)</Name
>[^<]*(?
:<(?
!Category
>)[^<]*)*
293 <Category
>([^<]*)</Category
>\s
*
294 <Subject
>([^<]+)</Subject
>\s
*
295 <Date\s
+longSec
="(\d+)"[^>]*>\s
*
296 </Header>\s*(?:(<)/Message
>|(?
=(<)Message\s
*)))~sx
;
298 while ($xml =~ /<Thread id="t(\d+)">([^<]*(?:<(?!\/Thread
>)[^<]*)*)<\
/Thread>/g) {
300 my ($tid, $thread) = ($1, $2);
301 my ($level, $cmno, @msg, @stack) = (0);
303 while ($thread =~ m
;$reg_msg;g
) {
306 push @stack,$cmno if (defined $cmno);
310 push @
{$msg[$cmno] -> {kids
}} => $#msg;
311 push @
{$msg[$cmno] -> {unids
}} => $2;}
315 for (@stack) {$msg[$_] -> {answers
}++}
323 $msg[-1] -> {subject
},
324 $msg[-1] -> {time}) = ($1, $2, $4, $5, $6, $7);
326 $msg[-1] -> {deleted
} = ($3 eq 'deleted')?
1:undef;
328 $msg[-1] -> {name
} =~ s/&/&/g;
329 $msg[-1] -> {cat
} =~ s/&/&/g;
330 $msg[-1] -> {subject
} =~ s/&/&/g;
332 $msg[-1] -> {unids
} = [];
333 $msg[-1] -> {kids
} = [];
334 $msg[-1] -> {answers
} = 0;
335 $msg[-1] -> {level
} = $level++;}
337 elsif (defined ($8)) {
341 push @
{$msg[$cmno] -> {kids
}} => $#msg;
342 push @
{$msg[$cmno] -> {unids
}} => $2;
343 $msg[$cmno] -> {answers
}++;}
347 for (@stack) {$msg[$_] -> {answers
}++}
353 $msg[-1] -> {subject
},
354 $msg[-1] -> {time}) = ($1, $2, $4, $5, $6, $7);
356 $msg[-1] -> {deleted
} = ($3 eq 'deleted')?
1:undef;
358 $msg[-1] -> {name
} =~ s/&/&/g;
359 $msg[-1] -> {cat
} =~ s/&/&/g;
360 $msg[-1] -> {subject
} =~ s/&/&/g;
362 $msg[-1] -> {level
} = $level;
363 $msg[-1] -> {unids
} = [];
364 $msg[-1] -> {kids
} = [];
365 $msg[-1] -> {answers
} = 0;}
368 $cmno = pop @stack; $level--;}}
371 # Sortieren und bei Bedarf
372 # geloeschte Messages entfernen
374 my $smsg = sort_thread
(\
@msg, $sorted);
375 delete_messages
($smsg) unless ($deleted);
377 $threads{$tid} = $smsg if (@
$smsg);
380 wantarray?
(\
%threads, $last_thread, $last_message, \
@unids): \
%threads;
383 ###########################
384 # sub create_forum_xml_string
386 # Forumshauptdatei erzeugen
387 ###########################
389 sub create_forum_xml_string
($$) {
390 my ($threads, $param) = @_;
391 my ($level, $thread, $msg);
393 my $xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n"
394 .'<!DOCTYPE Forum SYSTEM "'.$param -> {dtd
}.'">'."\n"
395 .'<Forum lastMessage="'.$param -> {lastMessage
}.'" lastThread="'.$param -> {lastThread
}.'">';
397 foreach $thread (sort {$b <=> $a} keys %$threads) {
398 $xml .= '<Thread id="t'.$thread.'">';
401 foreach $msg (@
{$threads -> {$thread}}) {
402 $xml .= '</Message>' x
($level - $msg -> {level
} + 1) if ($msg -> {level
} <= $level);
403 $level = $msg -> {level
};
404 $xml .= '<Message id="m'.$msg -> {mid
}.'"'
405 .' unid="'.$msg -> {unid
}.'"'
406 .(($msg -> {deleted
})?
' flag="deleted"':'')
411 .plain
($msg -> {name
})
416 .((length $msg -> {cat
})?plain
($msg -> {cat
}):'')
419 .plain
($msg -> {subject
})
426 $xml .= '</Message>' x
($level + 1);
427 $xml .= '</Thread>';}
434 ###########################
438 ###########################
441 my ($filename,$content) = @_;
444 open FILE
,">$filename.temp" or return;
446 unless (print FILE
$$content) {
450 close FILE
or return;
452 rename "$filename.temp", $filename or return;
457 # ====================================================
459 # ====================================================
461 ###########################
463 # 02. Januar 2001, 12:02 Uhr
466 # 02. 01. 2001, 12:02 Uhr
469 # Dienstag, 02. Januar 2001, 12:02:01 Uhr
471 # formatierte Zeitangabe
472 ###########################
475 my @month = qw(Januar Februar M\303\244rz April Mail Juni Juli August September Oktober November Dezember);
478 my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
480 sprintf ('%02d. %s %04d, %02d:%02d Uhr', $day, $month[$mon], $year+1900, $hour, $min);
483 sub short_hr_time ($) {
484 my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
486 sprintf ('%02d. %02d. %04d, %02d:%02d Uhr', $day, $mon+1, $year+1900, $hour, $min);
489 sub long_hr_time ($) {
490 my @month = qw(Januar Februar M\303\244rz April Mail Juni Juli August September Oktober November Dezember);
493 my @wday = qw(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag);
494 my ($sek, $min, $hour, $day, $mon, $year, $wday) = localtime ($_[0]);
496 sprintf ('%s, %02d. %s %04d, %02d:%02d:%02d Uhr', $wday[$wday], $day, $month[$mon], $year+1900, $hour, $min, $sek);
499 # ====================================================
500 # Modulinitialisierung
501 # ====================================================
503 # making require happy
506 # ====================================================
507 # end of Posting::_lib
508 # ====================================================
patrick-canterino.de