]>
git.p6c8.net - selfforum.git/blob - selfforum-cgi/shared/Posting/_lib.pm
fea40970dd9d72fe25d4161f6598a3b5ec9d455a
3 # ====================================================
4 # Autor: n.d.p. / 2001-01-07
5 # lm : n.d.p. / 2001-01-08
6 # ====================================================
8 # * Schnittstellen fuer den Zugriff auf Messages
10 # ====================================================
14 package Posting
::_lib
;
16 use vars
qw(@ISA @EXPORT_OK);
18 use Encode::Plain; $Encode::Plain::utf8 = 1;
22 # ====================================================
24 # ====================================================
28 @EXPORT_OK = qw(get_message_header get_message_body get_message_node parse_single_thread
29 hr_time short_hr_time long_hr_time
31 create_forum_xml_string
34 # ====================================================
36 # ====================================================
38 ###########################
39 # sub get_message_header
41 # Messageheader auslesen
42 ###########################
44 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);
58 %conf = (name
=> ($name -> hasChildNodes
)?
$name -> getFirstChild
-> getData
:undef,
59 category
=> ($cat -> hasChildNodes
)?
$cat -> getFirstChild
-> getData
:undef,
60 subject
=> ($subject -> hasChildNodes
)?
$subject -> getFirstChild
-> getData
:undef,
61 email
=> (defined ($email) and $email -> hasChildNodes
)?
$email -> getFirstChild
-> getData
:undef,
62 home
=> (defined ($home) and $home -> hasChildNodes
)?
$home -> getFirstChild
-> getData
:undef,
63 image
=> (defined ($image) and $image -> hasChildNodes
)?
$image -> getFirstChild
-> getData
:undef,
64 time => $date -> getAttribute
('longSec'));
68 ###########################
69 # sub get_message_header
71 # Messagebody auslesen
72 ###########################
74 sub get_message_body
($$) {
78 foreach ($xml -> getElementsByTagName
('ContentList', 1) -> item
(0) -> getElementsByTagName
('MessageContent', 0)) {
79 if ($_ -> getAttribute
('mid') eq $mid) {
80 $body = ($_ -> hasChildNodes
)?
$_ -> getFirstChild
-> getData
:'';
86 ###########################
87 # sub get_message_header
89 # Messagenode bestimmen
90 ###########################
92 sub get_message_node
($$$) {
93 my ($xml,$tid,$mid) = @_;
96 for ( $xml -> getElementsByTagName
('Thread')) {
97 if ($_ -> getAttribute
('id') eq $tid) {
99 for ($tnode -> getElementsByTagName
('Message')) {
100 if ($_ -> getAttribute
('id') eq $mid) {
105 wantarray?
($mnode, $tnode):$mnode;
108 ###########################
109 # sub parse_single_thread
111 # einzelne Threaddatei
113 ###########################
115 sub parse_single_thread
($$;$) {
116 my ($tnode, $deleted, $sorted) = @_;
117 my ($header, @msg, %mno);
119 for ($tnode -> getElementsByTagName
('Message')) {
120 $header = get_message_header
($_);
122 push @msg,{mid
=> ($_ -> getAttribute
('id') =~ /(\d+)/)[0],
123 ip
=> $_ -> getAttribute
('ip'),
124 kids
=> [$_ -> getElementsByTagName
('Message', 0)],
125 answers
=> $_ -> getElementsByTagName
('Message') -> getLength
,
126 deleted
=> ($_ -> getAttribute
('flag') eq 'deleted')?
1:0,
127 name
=> plain
($header -> {name
}),
128 cat
=> plain
($header -> {category
} or ''),
129 subject
=> plain
($header -> {subject
}),
130 time => plain
($header -> {time})};
133 # Eintraege ergaenzen und korrigieren
135 $msg[0] -> {level
} = 0;
137 $level = $_ -> {level
} + 1;
138 @
{$_ -> {kids
}} = map {$msg[$mno{$_}] -> {level
} = $level; $mno{$_}} @
{$_ -> {kids
}};}
141 # Sortieren und bei Bedarf
142 # geloeschte Messages entfernen
144 my $smsg = sort_thread
(\
@msg, $sorted);
145 delete_messages
($smsg) unless ($deleted);
150 ###########################
151 # sub create_message_xml
155 ###########################
157 sub create_message_xml
($$$) {
158 my ($xml, $msges, $num) = @_;
160 my $msg = $msges -> [$num];
162 my $message = $xml -> createElement
('Message');
163 $message -> setAttribute
('id', 'm'.$msg -> {mid
});
164 $message -> setAttribute
('flag', 'deleted') if ($msg -> {deleted
});
167 my $header = $xml -> createElement
('Header');
169 # alles inside of 'Header'
170 my $author = $xml -> createElement
('Author');
171 my $name = $xml -> createElement
('Name');
172 $name -> addText
(toUTF8
($msg -> {name
}));
174 my $email = $xml -> createElement
('Email');
176 my $category = $xml -> createElement
('Category');
177 $category -> addText
(toUTF8
($msg -> {cat
}));
179 my $subject = $xml -> createElement
('Subject');
180 $subject -> addText
(toUTF8
($msg -> {subject
}));
182 my $date = $xml -> createElement
('Date');
183 $date -> setAttribute
('longSec', $msg -> {time});
185 $author -> appendChild
($name);
186 $author -> appendChild
($email);
187 $header -> appendChild
($author);
188 $header -> appendChild
($category);
189 $header -> appendChild
($subject);
190 $header -> appendChild
($date);
191 $message -> appendChild
($header);
193 if ($msg -> {kids
}) {
194 for (@
{$msg -> {kids
}}) {
195 $message -> appendChild
(&create_message_xml
($xml, $msges, $_));}}
200 # ====================================================
201 # XML-Parsen von Hand
202 # ====================================================
204 ###########################
209 ###########################
211 sub sort_thread
($$) {
212 my ($msg, $sorted) = @_;
214 my ($z, %mhash) = (0);
216 if ($sorted) { # aelteste zuerst
218 @
$msg[@
{$_ -> {kids
}}] = sort {$a -> {mid
} <=> $b -> {mid
}} @
$msg[@
{$_ -> {kids
}}] if (@
{$_ -> {kids
}} > 1);
219 $mhash{$_ -> {mid
}} = [@
$msg[@
{$_ -> {kids
}}]];}}
221 else { # juengste zuerst
223 @
$msg[@
{$_ -> {kids
}}] = sort {$b -> {mid
} <=> $a -> {mid
}} @
$msg[@
{$_ -> {kids
}}] if (@
{$_ -> {kids
}} > 1);
224 $mhash{$_ -> {mid
}} = [@
$msg[@
{$_ -> {kids
}}]];}}
226 # Kinder wieder richtig einsortieren
227 my @smsg = ($msg -> [0]);
230 splice @smsg,$z,0,@
{$mhash{$_ -> {mid
}}} if ($_ -> {answers
});
231 delete $_ -> {kids
};}
236 ###########################
237 # sub delete_messages
239 # geoeschte Nachrichten
241 ###########################
243 sub delete_messages
($) {
246 my ($z, $oldlevel, @path) = (0,0,0);
249 if ($_ -> {deleted
}) {
250 my $n = $_ -> {answers
}+1;
251 for (@path) {$smsg -> [$_] -> {answers
} -= $n;}
252 splice @
$smsg,$z,$n;}
255 if ($_ -> {level
} > $oldlevel) {
257 $oldlevel = $_ -> {level
};}
259 elsif ($_ -> {level
} < $oldlevel) {
260 splice @path,$_ -> {level
}-$oldlevel;
261 $oldlevel = $_ -> {level
};}
263 else { $path[-1] = $z; }
270 ###########################
271 # sub get_all_threads
273 # Hauptdatei laden und
275 ###########################
277 sub get_all_threads
($$;$) {
278 my ($file, $deleted, $sorted) = @_;
279 my ($last_thread, $last_message, @unids, %threads);
282 open FILE
, $file or return undef;
283 my $xml = join '', <FILE
>;
284 close(FILE
) or return undef;
287 ($last_thread) = map {/(\d+)/} $xml =~ /<Forum.+?lastThread="([^"]+)"[^>]*>/;
288 ($last_message) = map {/(\d+)/} $xml =~ /<Forum.+?lastMessage="([^"]+)"[^>]*>/;}
290 my $reg_msg = qr
~(?
:</Message
>
291 |<Message\s
+id
="m(\d+)"\s
+unid
="([^"]*)"(?:\s+flag="([^"]*)")?
[^>]*>\s
*
292 <Header
>[^<]*(?
:<(?
!Name
>)[^<]*)*
293 <Name
>([^<]+)</Name
>[^<]*(?
:<(?
!Category
>)[^<]*)*
294 <Category
>([^<]*)</Category
>\s
*
295 <Subject
>([^<]+)</Subject
>\s
*
296 <Date\s
+longSec
="(\d+)"[^>]*>\s
*
297 </Header>\s*(?:(<)/Message
>|(?
=(<)Message\s
*)))~sx
;
299 while ($xml =~ /<Thread id="t(\d+)">([^<]*(?:<(?!\/Thread
>)[^<]*)*)<\
/Thread>/g) {
301 my ($tid, $thread) = ($1, $2);
302 my ($level, $cmno, @msg, @stack) = (0);
304 while ($thread =~ m
;$reg_msg;g
) {
307 push @stack,$cmno if (defined $cmno);
311 push @
{$msg[$cmno] -> {kids
}} => $#msg;
312 push @
{$msg[$cmno] -> {unids
}} => $2;}
316 for (@stack) {$msg[$_] -> {answers
}++}
324 $msg[-1] -> {subject
},
325 $msg[-1] -> {time}) = ($1, $2, $4, $5, $6, $7);
327 $msg[-1] -> {deleted
} = ($3 eq 'deleted')?
1:undef;
329 $msg[-1] -> {name
} =~ s/&/&/g;
330 $msg[-1] -> {cat
} =~ s/&/&/g;
331 $msg[-1] -> {subject
} =~ s/&/&/g;
333 $msg[-1] -> {unids
} = [];
334 $msg[-1] -> {kids
} = [];
335 $msg[-1] -> {answers
} = 0;
336 $msg[-1] -> {level
} = $level++;}
338 elsif (defined ($8)) {
342 push @
{$msg[$cmno] -> {kids
}} => $#msg;
343 push @
{$msg[$cmno] -> {unids
}} => $2;
344 $msg[$cmno] -> {answers
}++;}
348 for (@stack) {$msg[$_] -> {answers
}++}
354 $msg[-1] -> {subject
},
355 $msg[-1] -> {time}) = ($1, $2, $4, $5, $6, $7);
357 $msg[-1] -> {deleted
} = ($3 eq 'deleted')?
1:undef;
359 $msg[-1] -> {name
} =~ s/&/&/g;
360 $msg[-1] -> {cat
} =~ s/&/&/g;
361 $msg[-1] -> {subject
} =~ s/&/&/g;
363 $msg[-1] -> {level
} = $level;
364 $msg[-1] -> {unids
} = [];
365 $msg[-1] -> {kids
} = [];
366 $msg[-1] -> {answers
} = 0;}
369 $cmno = pop @stack; $level--;}}
372 # Sortieren und bei Bedarf
373 # geloeschte Messages entfernen
375 my $smsg = sort_thread
(\
@msg, $sorted);
376 delete_messages
($smsg) unless ($deleted);
378 $threads{$tid} = $smsg if (@
$smsg);
381 wantarray?
(\
%threads, $last_thread, $last_message, \
@unids): \
%threads;
384 ###########################
385 # sub create_forum_xml_string
387 # Forumshauptdatei erzeugen
388 ###########################
390 sub create_forum_xml_string
($$) {
391 my ($threads, $param) = @_;
392 my ($level, $thread, $msg);
394 my $xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n"
395 .'<!DOCTYPE Forum SYSTEM "'.$param -> {dtd
}.'">'."\n"
396 .'<Forum lastMessage="'.$param -> {lastMessage
}.'" lastThread="'.$param -> {lastThread
}.'">';
398 foreach $thread (sort {$b <=> $a} keys %$threads) {
399 $xml .= '<Thread id="t'.$thread.'">';
402 foreach $msg (@
{$threads -> {$thread}}) {
403 $xml .= '</Message>' x
($level - $msg -> {level
} + 1) if ($msg -> {level
} <= $level);
404 $level = $msg -> {level
};
405 $xml .= '<Message id="m'.$msg -> {mid
}.'"'
406 .' unid="'.$msg -> {unid
}.'"'
407 .(($msg -> {deleted
})?
' flag="deleted"':'')
412 .plain
($msg -> {name
})
417 .((length $msg -> {cat
})?plain
($msg -> {cat
}):'')
420 .plain
($msg -> {subject
})
427 $xml .= '</Message>' x
($level + 1);
428 $xml .= '</Thread>';}
435 ###########################
439 ###########################
442 my ($filename,$content) = @_;
445 open FILE
,">$filename.temp" or return;
447 unless (print FILE
$$content) {
451 close FILE
or return;
453 rename "$filename.temp", $filename or return;
458 # ====================================================
460 # ====================================================
462 ###########################
464 # 02. Januar 2001, 12:02 Uhr
467 # 02. 01. 2001, 12:02 Uhr
470 # Dienstag, 02. Januar 2001, 12:02:01 Uhr
472 # formatierte Zeitangabe
473 ###########################
476 my @month = qw(Januar Februar M\303\244rz April Mail Juni Juli August September Oktober November Dezember);
479 my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
481 sprintf ('%02d. %s %04d, %02d:%02d Uhr', $day, $month[$mon], $year+1900, $hour, $min);
484 sub short_hr_time ($) {
485 my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
487 sprintf ('%02d. %02d. %04d, %02d:%02d Uhr', $day, $mon+1, $year+1900, $hour, $min);
490 sub long_hr_time ($) {
491 my @month = qw(Januar Februar M\303\244rz April Mail Juni Juli August September Oktober November Dezember);
494 my @wday = qw(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag);
495 my ($sek, $min, $hour, $day, $mon, $year, $wday) = localtime ($_[0]);
497 sprintf ('%s, %02d. %s %04d, %02d:%02d:%02d Uhr', $wday[$wday], $day, $month[$mon], $year+1900, $hour, $min, $sek);
500 # ====================================================
501 # Modulinitialisierung
502 # ====================================================
504 # making require happy
507 # ====================================================
508 # end of Posting::_lib
509 # ====================================================
patrick-canterino.de