]> git.p6c8.net - selfforum.git/commitdiff
Initial release
authorfox_two <>
Wed, 21 Feb 2001 10:38:08 +0000 (10:38 +0000)
committerfox_two <>
Wed, 21 Feb 2001 10:38:08 +0000 (10:38 +0000)
48 files changed:
selfforum-cgi/shared/Conf.pm [new file with mode: 0644]
selfforum-cgi/shared/Conf/Admin.pm [new file with mode: 0644]
selfforum-cgi/shared/Encode/Plain.pm [new file with mode: 0644]
selfforum-cgi/shared/Encode/Posting.pm [new file with mode: 0644]
selfforum-cgi/shared/Id.pm [new file with mode: 0644]
selfforum-cgi/shared/Lock.pm [new file with mode: 0644]
selfforum-cgi/shared/Mail.pm [new file with mode: 0644]
selfforum-cgi/shared/Posting/Write.pm [new file with mode: 0644]
selfforum-cgi/shared/Posting/_lib.pm [new file with mode: 0644]
selfforum-cgi/shared/Template.pm [new file with mode: 0644]
selfforum-cgi/shared/Template/Forum.pm [new file with mode: 0644]
selfforum-cgi/shared/Template/Posting.pm [new file with mode: 0644]
selfforum-cgi/shared/Template/_conf.pm [new file with mode: 0644]
selfforum-cgi/shared/Template/_query.pm [new file with mode: 0644]
selfforum-cgi/shared/Template/_thread.pm [new file with mode: 0644]
selfforum-cgi/shared/common.xml [new file with mode: 0644]
selfforum-cgi/user/config/answer.tmp.xml [new file with mode: 0644]
selfforum-cgi/user/config/common.xml [new file with mode: 0644]
selfforum-cgi/user/config/fo_admin_default.dtd [new file with mode: 0644]
selfforum-cgi/user/config/fo_admin_default.xml [new file with mode: 0644]
selfforum-cgi/user/config/fo_admin_default.xml.lock [new file with mode: 0644]
selfforum-cgi/user/config/fo_admin_default.xml.lock.ref [new file with mode: 0644]
selfforum-cgi/user/config/fo_admin_default.xml.lock.ref.lock [new file with mode: 0644]
selfforum-cgi/user/config/fo_admin_default.xml.master.lock [new file with mode: 0644]
selfforum-cgi/user/config/fo_posting.xml [new file with mode: 0644]
selfforum-cgi/user/config/fo_view.xml [new file with mode: 0644]
selfforum-cgi/user/config/forum.tmp.xml [new file with mode: 0644]
selfforum-cgi/user/config/posting.tmp.xml [new file with mode: 0644]
selfforum-cgi/user/fo_posting.pl [new file with mode: 0644]
selfforum-cgi/user/fo_view.pl [new file with mode: 0644]
selfforum-data/.htaccess [new file with mode: 0644]
selfforum-data/images/01.gif [new file with mode: 0644]
selfforum-data/images/02.gif [new file with mode: 0644]
selfforum-data/images/03.gif [new file with mode: 0644]
selfforum-data/images/04.gif [new file with mode: 0644]
selfforum-data/images/05.gif [new file with mode: 0644]
selfforum-data/images/06.gif [new file with mode: 0644]
selfforum-data/images/07.gif [new file with mode: 0644]
selfforum-data/images/08.gif [new file with mode: 0644]
selfforum-data/images/09.gif [new file with mode: 0644]
selfforum-data/images/10.gif [new file with mode: 0644]
selfforum-data/index.shtml [new file with mode: 0644]
selfforum-data/messages/forum.dtd [new file with mode: 0644]
selfforum-data/messages/selfforum.xml.lock [new file with mode: 0644]
selfforum-data/messages/selfforum.xml.lock.ref [new file with mode: 0644]
selfforum-data/messages/selfforum.xml.lock.ref.lock [new file with mode: 0644]
selfforum-data/messages/selfforum.xml.master.lock [new file with mode: 0644]
selfforum-data/neu.shtml [new file with mode: 0644]

diff --git a/selfforum-cgi/shared/Conf.pm b/selfforum-cgi/shared/Conf.pm
new file mode 100644 (file)
index 0000000..1fa97b2
--- /dev/null
@@ -0,0 +1,163 @@
+# Conf.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-05
+# lm   : n.d.p. / 2001-02-02
+# ====================================================
+# Funktion:
+#      Einlesen der Scriptkonfiguration
+# ====================================================
+
+use strict;
+
+package Conf;
+
+use vars qw(@ISA @EXPORT);
+
+use XML::DOM;
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(read_script_conf);
+
+################################
+# sub read_script_conf
+#
+# Scriptkonf. lesen
+################################
+
+sub read_script_conf ($$$) {
+  my ($Bin, $Shared, $Script) = @_;
+
+  $Script =~ s/^(.*)\..*$/$1/;             # Vornamen extrahieren
+  my $common  = "$Shared/common.xml";      # gemeinsame Konf-datei
+  my $group   = "$Bin/config/common.xml";  # gemeinsame (Gruppen-)Konf-datei
+  my $special = "$Bin/config/$Script.xml"; # spezielle Konf-datei
+  my %conf=();                             # conf-Hash
+
+  &parse_script_conf ($common , \%conf, $Script);   # und los...
+  &parse_script_conf ($group,   \%conf, $Script);
+  &parse_script_conf ($special, \%conf, $Script);
+
+  # Rueckgabe
+  \%conf;
+}
+
+# ====================================================
+# Private Funktionen
+# ====================================================
+
+sub parse_script_conf ($$$) {
+  my ($filename, $conf, $Script) = @_;
+
+  if (-f $filename) {
+    # XML parsen
+    my $xml = new XML::DOM::Parser -> parsefile ($filename);
+    my $config = $xml -> getElementsByTagName ('Config',0) -> item (0);
+
+    foreach ($config -> getElementsByTagName ('Constant', 0)) {&add_data ($_, $conf)}
+    foreach ($config -> getElementsByTagName ('Property', 0)) {&add_prop ($_, $conf)}
+    foreach ($config -> getElementsByTagName ('Limit', 0))    {&add_limit ($_, $conf, $Script)}}
+
+  return;
+}
+
+sub add_data ($$) {
+  my ($node, $conf) = @_;
+  my $name = $node -> getAttribute ('name');
+
+  die "element '".$node -> getNodeName."' requires attribute 'name' - aborted" unless (length ($name) and defined ($name));
+  die "double defined name '$name' - aborted" if ( exists ( $conf -> {$name} ) );
+
+  # Wert eintragen
+  $conf -> {$name} = ($node -> hasChildNodes)?$node -> getFirstChild -> getData:undef;
+
+  return;
+}
+
+sub add_prop ($$) {
+  my ($node, $conf) = @_;
+
+  my $name = $node -> getAttribute ('name');
+
+  die "element 'Property' requires attribute 'name' - aborted" unless (length ($name));
+
+  my @props  = $node -> getElementsByTagName ('Property', 0);
+  my @vars = $node -> getElementsByTagName ('Variable', 0);
+  my @lists  = $node -> getElementsByTagName ('List', 0);
+
+  # Properties
+  if (@props) {
+    for (@props) {
+      my $hash = (defined $conf -> {$name})?$conf -> {$name}:{};
+
+      die "name '$name' is defined for 'Property' and 'Variable' - aborted" unless (ref $hash eq 'HASH');
+
+      &add_prop ($_, $hash);
+      $conf -> {$name} = $hash;}}
+
+  # Array
+  if (@lists) {
+    for (@lists) {
+      my $lname = $_ -> getAttribute ('name');
+
+      die "element 'List' requires attribute 'name' - aborted" unless (length ($lname) and defined ($lname));
+      die "double defined name '$lname' - aborted" if ( exists ( $conf -> {$name} -> {$lname} ) );
+
+      $conf -> {$name} -> {$lname} = [map {($_ -> hasChildNodes)?$_ -> getFirstChild -> getData:undef} $_ -> getElementsByTagName ('ListItem', 0)];}}
+
+  # Hash
+  if (@vars) {
+    for (@vars) {
+      my $vname = $_ -> getAttribute ('name');
+
+      die "element 'Variable' requires attribute 'name' - aborted" unless (length ($vname) and defined ($vname));
+      die "double defined name '$vname' - aborted" if ( exists ( $conf -> {$name} -> {$vname} ) );
+
+      $conf -> {$name} -> {$vname} = ($_ -> hasChildNodes)?$_ -> getFirstChild -> getData:undef;}}
+
+  return;
+}
+
+sub add_limit ($$$) {
+  my ($node, $conf, $Script) = @_;
+
+  my %apps = map {($_ -> getFirstChild -> getData => 1)}
+                   $node -> getElementsByTagName ('Application',0) -> item (0)
+                   -> getElementsByTagName ('Script',0);
+
+  if ($apps {$Script}) {
+    foreach ($node -> getElementsByTagName ('Constant', 0)) {&add_data ($_, $conf)}
+    foreach ($node -> getElementsByTagName ('Property', 0)) {&add_prop ($_, $conf)}}
+
+  return;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Conf
+# ====================================================
+
+package Conf::Test;sub show{print"Content-type: text/plain\n\n";&hash($_[
+0],'')}sub hash{my($ref,$string)=@_;foreach(sort keys%$ref){my$val=$ref->
+{$_};unless(ref($val)){print$string,$_,' = ',$val,"\n";next;}else{if(ref(
+$val)eq 'HASH'){&hash($val,"$string$_ -> ");}else{if(ref($val)eq'ARRAY'){
+&array($val,"$string$_ -> ");}}}}}sub array {my($ref,$string)=@_;my $i=0;
+foreach (@$ref){unless(ref($_)){print$string,"[$i] = ", $_,"\n";}else{if(
+ref($_)eq 'HASH'){&hash($_,"$string\[$i] -> ")}else{if(ref($_)eq'ARRAY'){
+&array($_,"$string\[$i] -> ");}}}$i++;}}# n.d.p./2001-01-05/lm:2001-01-19
+# FUNCTION: printing the configuration, USAGE: &Conf::Test::show ($conf);
+
+# ====================================================
+# 'real' end of Conf .-))
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Conf/Admin.pm b/selfforum-cgi/shared/Conf/Admin.pm
new file mode 100644 (file)
index 0000000..cf4fa13
--- /dev/null
@@ -0,0 +1,150 @@
+# Admin.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-05
+# lm   : n.d.p. / 2001-02-02
+# ====================================================
+# Funktion:
+#      Einlesen der Admindefaultkonfiguration
+# ====================================================
+
+use strict;
+
+package Conf::Admin;
+
+use vars qw(@ISA @EXPORT);
+
+use Lock qw(:READ);
+
+use XML::DOM;
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(read_admin_conf);
+
+################################
+# sub read_admin_conf
+#
+# Default-Admin-Konf. lesen
+################################
+
+sub read_admin_conf ($) {
+  my $filename=shift;
+  my %conf;
+
+  if (-f $filename) {                                                    # gibts die Datei ueberhaupt?
+    if (lock_file ($filename)) {                                         # sperren...
+      my $xml = new XML::DOM::Parser -> parsefile ($filename);           # ...einlesen und parsen...
+      violent_unlock_file ($filename) unless (unlock_file ($filename));  # ...freigeben
+
+      # =================================
+      # jetzt Daten in den Hash schreiben
+
+      my $forum = $xml -> getElementsByTagName ('Forum',0) -> item (0);
+
+      # View
+      my $forum_view      = $forum       -> getElementsByTagName ('ForumView', 0) -> item (0);
+        my $thread_view   = $forum_view  -> getElementsByTagName ('ThreadView', 0) -> item (0);
+          my $show_thread = $thread_view -> getElementsByTagName ('ShowThread', 0) -> item (0);
+            my $show_how  = $show_thread -> getElementsByTagName ('*', 0) -> item (0);
+            my $how_name  = $show_how -> getTagName;
+        my $message_view  = $forum_view  -> getElementsByTagName ('MessageView', 0) -> item (0);
+        my $flags         = $forum_view  -> getElementsByTagName ('Flags', 0) -> item (0);
+        my $quoting       = $forum_view  -> getElementsByTagName ('Quoting', 0) -> item (0);
+          my $char        = $quoting     -> getElementsByTagName ('Chars', 0) -> item (0);
+
+      $conf {View} = {threadOpen    => $thread_view -> getAttribute ('threadOpen'),
+                      countMessages => $thread_view -> getAttribute ('countMessages'),
+                      sortThreads   => $thread_view -> getAttribute ('sortThreads'),
+                      sortMessages  => $thread_view -> getAttribute ('sortMessages'),
+                      showThread    => (($how_name eq 'showAll')?undef:
+                                       (($how_name eq 'showNone')?1:
+                                       ($show_how -> getFirstChild -> getData))),
+                      showPreview   => $message_view -> getAttribute ('previewON'),
+                      showNA        => $flags -> getAttribute ('showNA'),
+                      showHQ        => $flags -> getAttribute ('showHQ'),
+                      quoting       => $quoting -> getAttribute ('quotingON'),
+                      quoteChars    => $char?$char -> getFirstChild -> getData:undef};
+
+      # Severance
+      $conf {Severance} = &get_severance ($forum -> getElementsByTagName ('Severance', 0) -> item (0));
+
+      # Messaging
+      my $messaging      = $forum     -> getElementsByTagName ('Messaging', 0) -> item (0);
+        my $call_by_user = $messaging -> getElementsByTagName ('CallByUser', 0) -> item (0);
+
+      $conf {Messaging} = {userAnswer => $messaging -> getAttribute ('callUserAnswer'),
+                           thread     => $messaging -> getAttribute ('callAdminThread'),
+                           na         => $messaging -> getAttribute ('callAdminNA'),
+                           hq         => $messaging -> getAttribute ('callAdminHQ'),
+                           voting     => $messaging -> getAttribute ('callAdminVoting'),
+                           archiving  => $messaging -> getAttribute ('callAdminArchiving'),
+                           byUser     => $messaging -> getAttribute ('callUserAnswer'),
+                           callByName => [map {$_ -> getFirstChild -> getData} $call_by_user -> getElementsByTagName ('Name', 0)],
+                           callByMail => [map {$_ -> getFirstChild -> getData} $call_by_user -> getElementsByTagName ('Email', 0)],
+                           callByIP   => [map {$_ -> getFirstChild -> getData} $call_by_user -> getElementsByTagName ('IpAddress', 0)]};
+
+      # Instant
+      my $instant    = $forum   -> getElementsByTagName ('InstantJob', 0) -> item (0);
+        my $job      = $instant -> getElementsByTagName ('*',0) -> item (0);
+        my $job_name = $job -> getTagName;
+        $job_name = $job -> getAttribute ('reason') if ($job_name ne 'Severance');
+
+      $conf {Instant} = {execute     => $instant -> getAttribute ('executeJob'),
+                         description => $job_name,
+                         url         => (($job_name ne 'Severance')?$job -> getElementsByTagName ('FileUrl', 0) -> item (0) -> getFirstChild -> getData:undef),
+                         Severance   => (($job_name eq 'Severance')?&get_severance ($job):undef)};
+
+      # User
+      my $user = $forum -> getElementsByTagName ('UserManagement', 0) -> item (0);
+
+      $conf {User} = {deleteAfterDays => $user -> getElementsByTagName ('DeleteUser', 0) -> item (0)
+                                               -> getElementsByTagName ('AfterDays', 0) -> item (0)
+                                               -> getFirstChild -> getData};
+    }
+
+    else {
+      violent_unlock_file ($filename);}}
+
+  # Rueckgabe
+  \%conf;
+}
+
+# ====================================================
+# Private Funktionen
+# ====================================================
+
+sub get_severance ($) {
+  my $severance = shift;
+
+  my $after_byte    = $severance -> getElementsByTagName ('AfterByte', 0) -> item (0);
+  my $after_message = $severance -> getElementsByTagName ('AfterMessage', 0) -> item (0);
+  my $after_thread  = $severance -> getElementsByTagName ('AfterThread', 0) -> item (0);
+  my $last_posting  = $severance -> getElementsByTagName ('AfterLastPosting', 0) -> item (0);
+
+  my %conf =( exArchiving  => $severance -> getAttribute ('executeArchiving'),
+              archiving    => $severance -> getElementsByTagName ('Archiving', 0) -> item (0)
+                                -> getElementsByTagName ('*', 0) -> item (0) -> getTagName,
+              severance    => $severance -> getAttribute ('executeSeverance'),
+              afterByte    => ($after_byte?$after_byte -> getFirstChild -> getData:undef),
+              afterThread  => ($after_thread?$after_thread -> getFirstChild -> getData:undef),
+              afterMessage => ($after_message?$after_message -> getFirstChild -> getData:undef),
+              lastPosting  => ($last_posting?$last_posting -> getFirstChild -> getData:undef));
+
+  \%conf;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Conf::Admin
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Encode/Plain.pm b/selfforum-cgi/shared/Encode/Plain.pm
new file mode 100644 (file)
index 0000000..cf7ef06
--- /dev/null
@@ -0,0 +1,402 @@
+# Encode/Plain.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-07
+# lm   : n.d.p. / 2001-02-06
+# ====================================================
+# Funktion:
+#      Codierung von non-ASCII-Zeichen fuer
+#      HTML
+# ====================================================
+
+use strict;
+
+package Encode::Plain;
+
+require 5.6.0;
+
+use vars qw(@ISA @EXPORT %sonder %unimap $utf8);
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(plain multiline toUTF8);
+
+################################
+# sub plain
+#
+# einfache Sonderzeichen ->
+# Entity-Codierung
+################################
+
+sub plain ($;$) {
+  my ($old,$ref)=@_;
+  my $exreg;
+
+  return \'' unless (defined $old);
+
+  my $new=(ref ($old))?$$old:$old;;
+  $ref=($ref or {});
+
+  # Ausnahmen
+  my $except=exists($ref->{-except});
+  if ($except) {
+
+    # Referenz, also Liste uebergeben -> umwandeln in Regex
+    if (ref ($ref -> {-except})) {
+      $exreg = join ('|',map {quotemeta $_} @{$ref -> {-except}});}
+
+    # keine Referenz, also Regex angegeben
+    else {
+      $exreg = $ref -> {-except};
+      $exreg =~ s/\//\\\//g;}}      # LTS :-)
+
+  if (lc($ref->{-amp}) eq 'soft') {
+
+    if ($except) {
+      $new=~s/($exreg)|(?:\&(?!(?:#[Xx][\da-fA-F]+|#\d+|[a-zA-Z]+);))/(length($1))?$1:'&amp;'/eg;}
+
+    else {
+      $new=~s/\&(?!(?:#[Xx][\da-fA-F]+|#\d+|[a-zA-Z]+);)/&amp;/g;}}
+
+  elsif (lc($ref->{-amp}) ne 'no') {
+
+    if ($except) {
+      $new=~s/($exreg)|\&/(length($1))?$1:'&amp;'/eg;}
+
+    else {
+      $new=~s/\&/&amp;/g;}}
+
+    #  Weitere Zeichen
+  if ($except) {
+    $new =~ s/($exreg)|</(length($1))?$1:'&lt;'/eg;     # HTML ausschalten
+    $new =~ s/($exreg)|>/(length($1))?$1:'&gt;'/eg;
+    $new =~ s/($exreg)|\|/(length($1))?$1:'&#124;'/eg;  # nich wahr
+    $new =~ s/($exreg)|"/(length($1))?$1:'&quot;'/eg;   # Diese Zeile wird den Bannerklickern
+                                                        # zu schaffen machen, sowas aber auch...
+
+    # Der grosse Hash
+    if ($utf8 or $ref -> {-utf8}) {
+      my $x;
+      $new =~ s/($exreg)|([\300-\337][\200-\277]|[\340-\357][\200-\277][\200-\277])/
+                length($1)?$1:(exists($unimap{$x = unpack('U',$2)})?$unimap{$x}:"&#$x;")/eg;}
+
+    $new =~ s/($exreg)|([\177-\377])/(length($1))?$1:$sonder{$2}/eg;}
+
+  else {
+    $new =~ s/</&lt;/g;
+    $new =~ s/>/&gt;/g;
+    $new =~ s/\|/&#124;/g;
+    $new =~ s/"/&quot;/g;
+
+    # Der grosse Hash
+    if ($utf8 or $ref -> {-utf8}) {
+      my $x;
+      $new =~ s/([\300-\337][\200-\277]|[\340-\357][\200-\277][\200-\277])/
+                exists($unimap{$x = unpack('U',$1)})?$unimap{$x}:"&#$x;"/eg;}
+
+    $new =~ s/([\177-\377])/$sonder{$1}/g;}
+
+  # Zeichen <= 31
+  $new=~s/([\001-\010\013\014\016-\037])/'&#'.ord($1).';'/eg;
+  $new=~s/\000/ /g;
+
+  # Rueckgabe
+  ref($old)?\$new:$new;
+}
+
+################################
+# sub multiline
+#
+# Whitespacecodierung
+# fuer Leerzeilen
+################################
+
+sub multiline {
+  my $old=shift;
+  my $string=(ref ($old))?$$old:$old;
+
+  # Zeilenumbrueche normalisieren
+  $string=~s/\015\012|\015|\012/\n/g;
+
+  # Zeilenumbrueche in <br> umwandeln
+  $string=~s/\n/<br>/g;
+
+  # mehr als ein aufeinanderfolgendes
+  # Leerzeichen in feste Leerzeichen umwandeln
+  $string=~s/(\s\s+)/('&nbsp;' x (length($1)-1)) . ' '/eg;
+
+  # Leerzeichen nach einem <br> in feste
+  # Spaces umwandeln
+  $string=~s/(?:^|(<br>))\s/$1&nbsp;/g;
+
+  # Rueckgabe
+  \$string;
+}
+
+sub toUTF8 ($) {
+  my $ref = shift;
+  my $string = ref($ref)?$$ref:$ref;
+  no warnings 'utf8';
+
+  $string =~ tr/\x80-\xff//CU;
+
+  ref($ref)?\$string:$string;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+BEGIN {
+  # Latin 1 + geraten
+  %sonder=("\177" => '&#127;',    # Delete-Zeichen
+           "\200" => '&#8364;',   # Euro-Zeichen
+           "\201" => '&uuml;',    # ue - DOS-Zeichensatz
+           "\202" => '&#8218;',   # einfaches Anfuehrungszeichen unten
+           "\203" => '&#402;',    # forte
+           "\204" => '&#8222;',   # doppelte Anfuehrungszeichen unten
+           "\205" => '&#8230;',   # drei punkte
+           "\206" => '&#8224;',   # dagger
+           "\207" => '&#8225;',   # Dagger
+           "\210" => '&#710;',    # circ
+           "\211" => '&#8240;',   # Promille
+           "\212" => '&#352;',    # so ein S mit Haken drueber :-)
+           "\213" => '&#8249;',   # lsaquo
+           "\214" => '&#338;',    # OE (so verhakelt - daenisch?) wer weiss das schon
+           "\215" => '&igrave;',  # Codepage 850;
+           "\216" => '&#381;',    # Z mit Haken drueber (Latin Extended B)
+           "\217" => '&Aring;',   # Codepage 850 (Win)
+           "\220" => '&uuml;',    # ue - Mac-Zeichensatz
+           "\221" => "'",         # einfache Anfuehrungszeichen oben
+           "\222" => "'",         # dito
+           "\223" => '&#8220;',   # doppelte Anfuehrungszeichen oben
+           "\224" => '&#8220;',   # dito
+           "\225" => '&#8226;',   # Bullet
+           "\226" => '-',         # Bindestrich
+           "\227" => '-',         # dito
+           "\230" => '&#732;',    # tilde...?
+           "\231" => '&#8482;',   # Trade-Mark
+           "\232" => '&#353;',    # kleines s mit Haken drueber
+           "\233" => '&#8250;',   # rsaquo;
+           "\234" => '&#339;',    # oe verhakelt
+           "\235" => '&#216;',    # Codepage 850 (Win)
+           "\236" => '&#215;',    # Codepage 850 (Win)
+           "\237" => '&#376;',    # Y mit Punkten drueber
+           "\240" => '&nbsp;',    # nbsp;
+           "\241" => '&#161;',    # umgedrehtes !
+           "\242" => '&#162;',    # cent-Zeichen
+           "\243" => '&pound;',   # (engl.)Pfund-Zeichen
+           "\244" => '&#164;',    # Waehrungszeichen
+           "\245" => '&yen;',     # Yen halt :-)
+           "\246" => '&#166;',    # eigentlich soll es wohl ein | sein .-)
+           "\247" => '&sect;',    # Paragraph
+           "\250" => '&#168;',    # zwei Punkte oben
+           "\251" => '&copy;',    # (C)
+           "\252" => '&#170;',    # hochgestelltes unterstrichenes a
+           "\253" => '&laquo;',   # left-pointing double angle quotation mark (besser koennte ichs auch nicht beschreiben...)
+           "\254" => '&#172;',    # Negationszeichen
+           "\255" => '-',         # Bindestrich
+           "\256" => '&reg;',     # (R)
+           "\257" => '&szlig;',   # sz, was auch immer fuern Zeichensatz (DOS?)
+           "\260" => '&#176;',    # Grad-Zeichen
+           "\261" => '&#177;',    # Plusminus
+           "\262" => '&#178;',    # hoch 2
+           "\263" => '&#179;',    # hoch 3
+           "\264" => '&#8218;',   # einf. anfuehrungszeichen unten
+           "\265" => '&#181;',    # my-Zeichen (griech)
+           "\266" => '&#182;',    # Absatzzeichen
+           "\267" => '&#183;',    # Mal-Zeichen
+           "\270" => '&cedil;',
+           "\271" => '&sup1;',    # hoch 1
+           "\272" => '&#186;',    # masculine ordinal indicator (spanish)
+           "\273" => '&raquo;',   # right-pointing double angle quotation mark
+           "\274" => '&#188;',    # 1/4
+           "\275" => '&#189;',    # 1/2
+           "\276" => '&#190;',    # 3/4
+           "\277" => '&#191;',    # umgedrehtes ?
+           "\300" => '&Agrave;',
+           "\301" => '&Aacute;',
+           "\302" => '&Acirc;',
+           "\303" => '&Atilde;',
+           "\304" => '&Auml;',
+           "\305" => '&Aring;',
+           "\306" => '&AElig;',
+           "\307" => '&Ccedil;',
+           "\310" => '&Egrave;',
+           "\311" => '&Eacute;',
+           "\312" => '&Ecirc;',
+           "\313" => '&Euml;',
+           "\314" => '&Igrave;',
+           "\315" => '&Iacute;',
+           "\316" => '&Icirc;',
+           "\317" => '&Iuml;',
+           "\320" => '&ETH;',     # keine Ahnung, was das wohl sein soll, auf jeden Fall was islaendisches...
+           "\321" => '&Ntilde;',
+           "\322" => '&Ograve;',
+           "\323" => '&Oacute;',
+           "\324" => '&Ocirc;',
+           "\325" => '&Otilde;',
+           "\326" => '&Ouml;',
+           "\327" => '&#215;',    # eigentlich &times; funzt afaik aber nicht aufm Mac (ob das hier funktioniert, weiss ich nicht)
+           "\330" => '&Oslash;',
+           "\331" => '&Ugrave;',
+           "\332" => '&Uacute;',
+           "\333" => '&Ucirc;',
+           "\334" => '&Uuml;',
+           "\335" => '&Yacute;',
+           "\336" => '&THORN;',
+           "\337" => '&szlig;',
+           "\340" => '&agrave;',
+           "\341" => '&aacute;',
+           "\342" => '&acirc;',
+           "\343" => '&atilde;',
+           "\344" => '&auml;',
+           "\345" => '&aring;',
+           "\346" => '&aelig;',
+           "\347" => '&ccedil;',
+           "\350" => '&egrave;',
+           "\351" => '&eacute;',
+           "\352" => '&ecirc;',
+           "\353" => '&euml;',
+           "\354" => '&igrave;',
+           "\355" => '&iacute;',
+           "\356" => '&icirc;',
+           "\357" => '&iuml;',
+           "\360" => '&eth;',
+           "\361" => '&ntilde;',
+           "\362" => '&ograve;',
+           "\363" => '&oacute;',
+           "\364" => '&ocirc;',
+           "\365" => '&otilde;',
+           "\366" => '&ouml;',
+           "\367" => '&divide;',
+           "\370" => '&oslash;',
+           "\371" => '&ugrave;',
+           "\372" => '&uacute;',
+           "\373" => '&ucirc;',
+           "\374" => '&uuml;',
+           "\375" => '&yacute;',
+           "\376" => '&thorn;',
+           "\377" => '&yuml;');
+
+  # Unicode-Mapping
+  %unimap=(128 => '&#8364;',
+           129 => '&uuml;',
+           130 => '&#8218;',
+           131 => '&#402;',
+           132 => '&#8222;',
+           133 => '&#8230;',
+           134 => '&#8224;',
+           135 => '&#8225;',
+           136 => '&#710;',
+           137 => '&#8240;',
+           138 => '&#352;',
+           139 => '&#8249;',
+           140 => '&#338;',
+           141 => '&igrave;',
+           142 => '&#381;',
+           143 => '&Aring;',
+           144 => '&uuml;',
+           145 => "'",
+           146 => "'",
+           147 => '&#8220;',
+           148 => '&#8220;',
+           149 => '&#8226;',
+           150 => '-',
+           151 => '-',
+           152 => '&#732;',
+           153 => '&#8482;',
+           154 => '&#353;',
+           155 => '&#8250;',
+           156 => '&#339;',
+           157 => '&#216;',
+           158 => '&#215;',
+           159 => '&#376;',
+           160 => '&nbsp;',
+           163 => '&pound;',
+           165 => '&yen;',
+           167 => '&sect;',
+           169 => '&copy;',
+           171 => '&laquo;',
+           173 => '-',
+           174 => '&reg;',
+           175 => '&szlig;',
+           180 => '&#8218;',
+           184 => '&cedil;',
+           185 => '&sup1;',
+           187 => '&raquo;',
+           192 => '&Agrave;',
+           193 => '&Aacute;',
+           194 => '&Acirc;',
+           195 => '&Atilde;',
+           196 => '&Auml;',
+           197 => '&Aring;',
+           198 => '&AElig;',
+           199 => '&Ccedil;',
+           200 => '&Egrave;',
+           201 => '&Eacute;',
+           202 => '&Ecirc;',
+           203 => '&Euml;',
+           204 => '&Igrave;',
+           205 => '&Iacute;',
+           206 => '&Icirc;',
+           207 => '&Iuml;',
+           208 => '&ETH;',
+           209 => '&Ntilde;',
+           210 => '&Ograve;',
+           211 => '&Oacute;',
+           212 => '&Ocirc;',
+           213 => '&Otilde;',
+           214 => '&Ouml;',
+           216 => '&Oslash;',
+           217 => '&Ugrave;',
+           218 => '&Uacute;',
+           219 => '&Ucirc;',
+           220 => '&Uuml;',
+           221 => '&Yacute;',
+           222 => '&THORN;',
+           223 => '&szlig;',
+           224 => '&agrave;',
+           225 => '&aacute;',
+           226 => '&acirc;',
+           227 => '&atilde;',
+           228 => '&auml;',
+           229 => '&aring;',
+           230 => '&aelig;',
+           231 => '&ccedil;',
+           232 => '&egrave;',
+           233 => '&eacute;',
+           234 => '&ecirc;',
+           235 => '&euml;',
+           236 => '&igrave;',
+           237 => '&iacute;',
+           238 => '&icirc;',
+           239 => '&iuml;',
+           240 => '&eth;',
+           241 => '&ntilde;',
+           242 => '&ograve;',
+           243 => '&oacute;',
+           244 => '&ocirc;',
+           245 => '&otilde;',
+           246 => '&ouml;',
+           247 => '&divide;',
+           248 => '&oslash;',
+           249 => '&ugrave;',
+           250 => '&uacute;',
+           251 => '&ucirc;',
+           252 => '&uuml;',
+           253 => '&yacute;',
+           254 => '&thorn;',
+           255 => '&yuml;');
+}
+
+# making require happy
+1;
+
+# ====================================================
+# end of Encode::Plain
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Encode/Posting.pm b/selfforum-cgi/shared/Encode/Posting.pm
new file mode 100644 (file)
index 0000000..b12420f
--- /dev/null
@@ -0,0 +1,231 @@
+# Posting.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-07
+# lm   : n.d.p. / 2001-01-08
+# ====================================================
+# Funktion:
+#      Spezielle Codierung eines Postingtextes
+# ====================================================
+
+use strict;
+
+package Encode::Posting;
+
+use vars qw(@ISA @EXPORT);
+use Encode::Plain; $Encode::Plain::utf8 = 1;
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(encoded_body answer_field message_field);
+
+################################
+# sub encoded_body
+#
+# Nachrichtentext in gueltiges
+# HTML konvertieren
+################################
+
+sub encoded_body ($;$) {
+  my $posting = ${+shift};
+  my $params = shift;
+
+  $posting =~ s/[ \t]$//gm;        # Whitespaces am Zeilenende entfernen
+  $posting =~s /\s+$//;            # Whitespaces am Stringende entfernen
+  $posting = ${plain (\$posting)}; # Sonderzeichen maskieren
+
+  # Quotingzeichen normalisieren (\177)
+  my $quote = plain($params -> {quoteChars});
+  my $qquote = quotemeta $quote;
+  my $len = length ($quote);
+  $posting =~ s!^((?:$qquote)+)(.*)$!"\177" x (length($1)/$len) .$2!gem if (length ($qquote));
+
+  # Multine
+  $posting = ${multiline (\$posting)};
+
+  # normaler Link
+  $posting =~ s{\[link:\s*
+               ((?:ftp://                        # hier beginnt $1
+               |   https?://
+               |   about:
+               |   view-source:
+               |   gopher://
+               |   mailto:
+               |   news:
+               |   nntp://
+               |   telnet://
+               |   wais://
+               |   prospero://
+               |   \.\.?/                        # relativ auf dem server
+               |   /                             # absolut auf dem server
+               |   (?:[a-zA-Z.\d]+)?\??          # im forum
+               )   [^\s<'()\[\]]+                # auf jeden Fall kein \s und kein ] etc.
+               )                                 # hier ist $1 zuende
+               \s*(?:\]|(\s|\(|\)|<br>))         # der Begrenzer (\s, ] oder Zeilenende)
+              }
+              {<a href="$1">$1</a>$2}gix;        # und der Link
+
+  # javascript-links extra
+  my $klammer1='\((?:[^)])*\)';
+  my $klammer2="\\((?:$klammer1|(?:[^)])*)\\)";
+  my $klammer3="\\((?:$klammer2|(?:[^)])*)\\)";
+  my $klammer4="\\((?:$klammer3|(?:[^)])*)\\)";
+
+  $posting =~ s{\[link:\s*
+               (javascript:                      # hier beginnt $1
+               (?:
+                 $klammer4                       # Klammern bis Verschachtelungstiefe 4 (sollte reichen?)
+               | '[^\'\\]*(?:\\.[^\'\\]*)*'      # mit ' quotierter String, J.F. sei gedankt
+                                                 # im String sind Escapes zugelassen (also auch \')
+                                                 # damit werden (korrekt gesetzte) Javascript-Links moeglich
+               | [^\s<()'\]]+)+                  # auf jeden Fall kein \s und kein ] (ausser im String)
+               )                                 # hier ist $1 zuende
+               \s*(?:\s|\]|(\(|\)|<br>))         # der Begrenzer (\s, ] oder Zeilenende)
+              }
+              {<a href="$1">$1</a>$2}gix;        # und der Link
+
+  # images
+  $posting =~ s{\[image:\s*
+               ((?:https?://
+               |   \.\.?/                        # relativ auf dem server
+               |   /                             # absolut auf dem server
+               |   (?:[a-zA-Z.\d]+)?\??          # im forum
+               )   [^\s<'()\[\]]+                # auf jeden Fall kein \s und kein ] etc.
+               )                                 # hier ist $1 zuende
+               \s*(?:\]|(\s|\(|\)|<br>))         # der Begrenzer (\s, ] oder Zeilenende)
+              }
+              {<img src="$1" border=0 alt="">$2}gix; # und das Bild
+
+  # iframe
+  $posting =~ s{\[iframe:\s*
+               ((?:ftp://
+               |   https?://
+               |   about:
+               |   view-source:
+               |   gopher://
+               |   mailto:
+               |   news:
+               |   nntp://
+               |   telnet://
+               |   wais://
+               |   prospero://
+               |   \.\.?/                        # relativ auf dem server
+               |   /                             # absolut auf dem server
+               |   [a-zA-Z\d]+(?:\.html?|/)      # im forum (koennen eh nur threads oder verweise
+                                                 # auf tiefere verzeichnisse sein)
+               )[^\s<'()\]]+                     # auf jeden Fall kein \s und kein ] etc. (s.o.)
+               )                                 # hier ist $1 zuende
+               \s*(?:\]|(\s|\(|\)|<br>))         # der Begrenzer (\s, ] oder Zeilenende)
+              }
+              {<iframe src="$1" width="90%" height="90%"><a href="$1">$1</a></iframe>$2}gix;
+
+  # [msg...]
+  $params -> {messages} = {} unless (defined $params -> {messages});
+  my %msg = %{$params -> {messages}};
+  foreach (keys %msg) {
+    $posting =~ s/\[msg:\s*$_(?:\s*\]|\s)/'<img src="'.$msg{$_} -> {src}.'" width='.$msg{$_}->{width}.' height='.$msg{$_}->{height}.' border=0 alt="'.plain($msg{$_}->{alt}).'">'/gei;}
+
+  # Rueckgabe
+  \$posting;
+}
+
+################################
+# sub answer_field
+#
+# Antwort HTML einer Message
+# erzeugen
+################################
+
+sub answer_field ($$) {
+  my $posting = shift;
+  my $params = shift;
+  $params = {} unless (defined $params);
+
+  # ================
+  # Antwortfeld
+  # ================
+  my $area = $$posting;
+
+  my $qchar = $params -> {quoteChars};
+
+  $area =~ s/(?:^|(<br>))(?!<br>)/$1\177/g if ($params -> {quoteArea}); # Antwortfeld quoten?!
+  $area =~ s/\177/$qchar/g; # normalisierte Quotes jedenfalls in Chars umsetzen
+
+  # HTML-Zeug zurueckuebersetzen
+
+  $params -> {messages} = {} unless (defined $params -> {messages}); # um Fehlermeldungen auszuschliessen...
+  my %msg = map {($params -> {messages} -> {$_} -> {src} => $_)} keys %{$params -> {messages}};
+
+  $area =~ s{<iframe\s+src="([^"]*)"[^>]+>.*?</iframe>|<img\s+src="([^"]*)"\s+width[^>]+>|<img src="([^"]*)"[^>]*>|<a href="([^"]*)">.*?</a>}
+            {if    (defined $1) {"[iframe: $1]"}
+             elsif (defined $2) {"[msg: $msg{$2}]"}
+             elsif (defined $3) {"[image: $3]"}
+             elsif (defined $4) {"[link: $4]"}}eg;
+  $area =~ s/<br>/\n/g;
+  $area =~ s/&(?:#160|nbsp);/ /g;
+
+  # Rueckgabe
+  \$area;
+}
+
+################################
+# sub message_field
+#
+# HTML eines Postingtextes
+# erzeugen
+################################
+
+sub message_field ($$) {
+  my $posting = ${+shift};
+  my $params = shift;
+  $params = {} unless (defined $params);
+
+  # ================
+  # Postingtext
+  # ================
+  my $qchar = $params -> {quoteChars};
+
+  if ($params -> {quoting}) {    # Quotes bekommen eine extra Klasse?
+    # ueberfluessige Abstaende entfernen,
+    # sie werden eh wieder auseinandergezogen...
+    $posting =~ s/(\177(?:[^<]|<(?!br>))*<br>)<br>(?=\177)/$1/g;
+    $posting =~ s/(\177(?:[^<]|<(?!br>))*<br>)<br>(?!\177)/$1/g;
+
+    my ($last_level, $level, $line, $q, @new)=(-1,0);
+
+    foreach $line (split (/<br>/,$posting)) { # Zeilenweise gucken,
+      ($q) = ($line =~ /^(\177+)/g);          # wieviele
+      $level = length ($q);                   # Quotingchars am Anfang stehen
+      if ($level != $last_level) {            # wenn sich was verandert...
+                                              # ... dann TU ETWAS!
+
+        if    ($last_level <= 0 and $level > 0) {$last_level = $level; $line='<br>'.$params -> {startCite} . $line}
+        elsif ($level > 0) {$last_level = $level; $line=$params -> {endCite} . '<br>' . $params -> {startCite} . $line}
+        elsif ($level == 0 and $last_level > 0) {$last_level = -1; $line = $params -> {endCite} . '<br>' . $line}}
+
+      push @new,$line}
+
+    $new[0] =~ s/^<br>//;
+    $posting = (join '<br>',@new) . (($last_level > 0)?$params -> {endCite}:'');}
+
+  $posting =~ s/\177/$qchar/g; # normalisierte Quotes in Chars umsetzen
+
+  # Rueckgabe
+  \$posting;
+}
+
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Encode::Posting
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Id.pm b/selfforum-cgi/shared/Id.pm
new file mode 100644 (file)
index 0000000..33c0c83
--- /dev/null
@@ -0,0 +1,73 @@
+# Id.pm
+
+##############################################
+#                                            #
+# Autor: n.d.p. / nd@o3media.de              #
+#                                            #
+# Letze Aenderung: n.d.p. / 2001-01-28       #
+#                                            #
+# ========================================== #
+#                                            #
+# Funktion:                                  #
+#                                            #
+# Bereitsstellen einer einmaligen ID         #
+#                                            #
+##############################################
+
+use strict;
+
+package Id;
+require 5.000;
+
+#####################
+# Funktionsexport
+#####################
+
+require Exporter;
+@Id::ISA = qw(Exporter);
+@Id::EXPORT = qw(unique_id);
+
+use vars qw(@table);
+
+##########################################
+# EXPORT                                 #
+#                                        #
+# sub &unique_id                         #
+#                                        #
+# Funktion:                              #
+#      Rueckgabe der ID                  #
+##########################################
+
+sub unique_id {
+  my $id;
+
+  my $ip=$ENV{'REMOTE_ADDR'};
+  my $time=time();
+  my $port=$ENV{'REMOTE_PORT'};
+  my $rand=int(rand(time()));
+  $ip =  hex(join ('',map {sprintf ('%02X',$_)} split (/\./,$ip)));
+
+  join '',map {to_base64 ($_)} (substr ($time,-9), $port, $ip, $rand, $$);
+}
+
+sub to_base64 ($) {
+  my $x = shift;
+  my $y = $table[$x % 64];
+
+  while ($x = int ($x/64)) {$y = $table[$x % 64] . $y}
+
+  # Rueckgabe
+  $y;
+}
+
+BEGIN {
+  srand(time()^$$);
+  @table = ('a'..'z','-','0'..'9','A'..'Z','_');
+}
+
+# making 'require' happy
+1;
+
+#####################
+# end of Id
+#####################
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Lock.pm b/selfforum-cgi/shared/Lock.pm
new file mode 100644 (file)
index 0000000..1d2c929
--- /dev/null
@@ -0,0 +1,608 @@
+# Lock.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-04
+# lm   : n.d.p. / 2000-01-05
+# ====================================================
+# Funktion:
+#      Sperren einer Datei
+# ====================================================
+
+use strict;
+
+package Lock;
+
+use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS $Timeout $violentTimeout $masterTimeout $iAmMaster);
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA         = qw(Exporter);
+
+@EXPORT_OK   = qw(lock_file unlock_file write_lock_file write_unlock_file
+                  violent_unlock_file set_master_lock release_file);
+
+%EXPORT_TAGS = (READ  => [qw(lock_file unlock_file violent_unlock_file)],
+                WRITE => [qw(write_lock_file write_unlock_file violent_unlock_file)],
+                ALL   => [qw(lock_file unlock_file write_lock_file write_unlock_file
+                             violent_unlock_file set_master_lock release_file)]);
+
+# ====================================================
+# Windows section (no symlinks)
+# ====================================================
+
+################################
+# sub w_lock_file
+#
+# Schreibsperre setzen
+################################
+
+sub w_lock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+  my $i;
+
+  if (-f &masterlockfile($filename)) {
+
+    for ($i=0 ; $i<=$timeout ; $i++) {
+      # Referenzzaehler um eins erhoehen
+      &set_ref($filename,1,$timeout) and return 1;
+      sleep (1);}}
+
+  else {
+    # Mastersperre
+    return undef;}
+
+  0; # Mist
+}
+
+################################
+# sub w_unlock_file
+#
+# Schreibsperre aufheben
+################################
+
+sub w_unlock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+
+  if (-f &masterlockfile($filename)) {
+    # Referenzzaehler um eins erniedrigen
+    &set_ref($filename,-1,$timeout) and return 1;}
+
+  0; # Mist
+}
+
+################################
+# sub w_write_lock_file
+#
+# Lese- und Schreibsperre
+# setzen
+################################
+
+sub w_write_lock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+
+  if (-f &masterlockfile($filename) or $iAmMaster) {
+    # bevorstehenden Schreibzugriff anmelden
+    &simple_lock ($filename,$timeout) or return 0;
+
+    my $i;
+    for ($i=0 ; $i<=$timeout ; $i++) {
+      # Referenzdatei sperren
+      &simple_lock (&reffile($filename),$timeout) or (return &simple_unlock($filename,$timeout) and 0);
+
+      # Referenzzaehler = 0 ? => okay
+      return 1 if (&get_ref ($filename) == 0);
+
+      # Referenzdatei wieder freigeben
+      &simple_unlock (&reffile($filename),$timeout) or (return &simple_unlock($filename,$timeout) and 0);
+      sleep(1);}
+
+    &simple_unlock ($filename);}
+
+  else {
+    # Mastersperre gesetzt
+    return undef;}
+
+  0; # Mist
+}
+
+################################
+# sub w_write_unlock_file
+#
+# Lese- und Schreibsperre
+# aufheben
+################################
+
+sub w_write_unlock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+
+  if (-f &masterlockfile($filename) or $iAmMaster) {
+    &simple_unlock (&reffile($filename),$timeout) or return 0; # Referenzdatei freigeben
+    &simple_unlock ($filename,$timeout) or return 0;}          # Lesesperre aufheben
+
+  1; # jawoll!
+}
+
+################################
+# sub w_violent_unlock_file
+#
+# Sperre brutal aufheben
+################################
+
+sub w_violent_unlock_file ($) {
+  my $filename=shift;
+
+  if (-f &masterlockfile($filename)) {
+
+    # Zeit der letzten Modifikation feststellen
+    # und abbrechen, wenn meine Zeit noch nicht gekommen ist
+    my $reffile;
+    if (-f ($reffile = $filename) or -f ($reffile = &lockfile($filename))) {
+      my $time = (stat $reffile)[9];
+      return if ((time - $time) < $violentTimeout);}
+
+    write_lock_file ($filename,1);       # letzter Versuch, exklusiven Zugriff zu bekommen
+    unlink (&reffile($filename));        # Referenzzaehler auf null
+    simple_unlock (&reffile($filename)); # Referenzdatei freigeben
+    simple_unlock ($filename);}          # Datei freigeben (Lesesperre aufheben)
+}
+
+################################
+# sub w_set_master_lock
+#
+# Mastersperre setzen
+################################
+
+sub w_set_master_lock ($;$) {
+  my $filename=shift;
+  my $timeout=(shift @_ or $masterTimeout);
+
+  # exklusiven Zugriff erlangen...oder abbrechen
+  return 0 unless (&write_lock_file ($filename,$timeout));
+
+  # Mastersperre setzen und Erfolg melden
+  unlink &masterlockfile($filename) and return 1;
+
+  0; # Mist
+}
+
+################################
+# sub w_release_file
+#
+# Alle Sperren inkl. Master-
+# sperre aufheben
+################################
+
+sub w_release_file ($) {
+  my $filename=shift;
+
+  unlink (&reffile($filename));                              # Referenzzaehler auf null
+  return 0 if (-f &reffile($filename));                      # wirklich?
+  return 0 unless (simple_unlock (&reffile($filename)));     # Referenzzaehler freigeben
+  return 0 unless (&simple_unlock ($filename));              # Datei selbst freigeben (Lesesperre)
+  return 0 unless (&simple_unlock (&masterfile($filename))); # Mastersperre aufheben
+
+  1; # jup
+}
+
+# ====================================================
+# *n*x section (symlinks possible)
+# ====================================================
+
+################################
+# sub x_lock_file
+#
+# Schreibsperre setzen
+################################
+
+sub x_lock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+  my $i;
+
+  unless (-l &masterlockfile($filename)) {
+
+    for ($i=0 ; $i<=$timeout ; $i++) {
+      # Referenzzaehler um eins erhoehen
+      &set_ref($filename,1,$timeout) and return 1;
+      sleep (1);}}
+
+  else {
+    # Mastersperre
+    return undef;}
+
+  0; # Mist
+}
+
+################################
+# sub x_unlock_file
+#
+# Schreibsperre aufheben
+################################
+
+sub x_unlock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+
+  unless (-l &masterlockfile($filename)) {
+    # Referenzzaehler um eins erniedrigen
+    &set_ref($filename,-1,$timeout) and return 1;}
+
+  0; # Mist
+}
+
+################################
+# sub x_write_lock_file
+#
+# Lese- und Schreibsperre
+# setzen
+################################
+
+sub x_write_lock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+
+  unless (-l &masterlockfile($filename) and not $iAmMaster) {
+    # bevorstehenden Schreibzugriff anmelden
+    &simple_lock ($filename,$timeout) or return 0;
+
+    my $i;
+    for ($i=0 ; $i<=$timeout ; $i++) {
+      # Referenzdatei sperren
+      &simple_lock (&reffile($filename),$timeout) or (return &simple_unlock($filename,$timeout) and 0);
+
+      # Referenzzaehler = 0 ? => okay
+      return 1 if (&get_ref ($filename) == 0);
+
+      # Referenzdatei wieder freigeben
+      &simple_unlock (&reffile($filename),$timeout) or (return &simple_unlock($filename,$timeout) and 0);
+      sleep(1);}
+
+    &simple_unlock ($filename);}
+
+  else {
+    # Mastersperre gesetzt
+    return undef;}
+
+  0; # Mist
+}
+
+################################
+# sub x_write_unlock_file
+#
+# Lese- und Schreibsperre
+# aufheben
+################################
+
+sub x_write_unlock_file ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+
+  unless (-l &masterlockfile($filename) and not $iAmMaster) {
+    &simple_unlock (&reffile($filename),$timeout) or return 0; # Referenzdatei freigeben
+    &simple_unlock ($filename,$timeout) or return 0;}          # Lesesperre aufheben
+
+  1; # jawoll!
+}
+
+################################
+# sub x_violent_unlock_file
+#
+# Sperre brutal aufheben
+################################
+
+sub x_violent_unlock_file ($) {
+  my $filename=shift;
+
+  unless (-l &masterlockfile($filename)) {
+
+    # Zeit der letzten Modifikation feststellen
+    # und abbrechen, wenn meine Zeit noch nicht gekommen ist
+    my ($reffile,$time);
+
+    if (-f ($reffile = $filename)) {
+      $time = (stat $reffile)[9];}
+
+    elsif (-l ($reffile = &lockfile($filename))) {
+      $time = (lstat $reffile)[9];}
+
+    if ($reffile) {
+      return if ((time - $time) < $violentTimeout);}
+
+    write_lock_file ($filename,1);       # letzter Versuch, exklusiven Zugriff zu bekommen
+    unlink (&reffile($filename));        # Referenzzaehler auf null
+    simple_unlock (&reffile($filename)); # Referenzdatei freigeben
+    simple_unlock ($filename);}          # Datei freigeben (Lesesperre aufheben)
+}
+
+################################
+# sub x_set_master_lock
+#
+# Mastersperre setzen
+################################
+
+sub x_set_master_lock ($;$) {
+  my $filename=shift;
+  my $timeout=(shift @_ or $masterTimeout);
+
+  # exklusiven Zugriff erlangen...oder abbrechen
+  return 0 unless (&write_lock_file ($filename,$timeout));
+
+  # Mastersperre setzen und Erfolg melden
+  symlink $filename, &masterlockfile($filename) and return 1;
+
+  0; # Mist
+}
+
+################################
+# sub x_release_file
+#
+# Alle Sperren inkl. Master-
+# sperre aufheben
+################################
+
+sub x_release_file ($) {
+  my $filename=shift;
+
+  unlink (&reffile($filename));                              # Referenzzaehler auf null
+  return 0 if (-f &reffile($filename));                      # wirklich?
+  return 0 unless (simple_unlock (&reffile($filename)));     # Referenzzaehler freigeben
+  return 0 unless (&simple_unlock ($filename));              # Datei selbst freigeben (Lesesperre)
+  return 0 unless (&simple_unlock (&masterfile($filename))); # Mastersperre aufheben
+
+  1; # jup
+}
+
+# ====================================================
+# private subs
+# ====================================================
+
+################################
+# Dateinamen
+################################
+
+sub reffile ($) {
+  "$_[0].lock.ref";
+}
+sub lockfile ($) {
+  "$_[0].lock";
+}
+sub masterlockfile ($) {
+  &lockfile(&masterfile($_[0]));
+}
+sub masterfile ($) {
+  "$_[0].master";
+}
+
+################################
+# einfaches Sperren/Entsperren
+# Windows
+#
+# (Lockdatei loeschen)
+################################
+
+sub w_simple_lock ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+  my $lockfile=&lockfile($filename);
+
+  my $i;
+  for ($i=$timeout; $i>=0; $i--) {
+    unlink("$lockfile") and return 1;
+    sleep(1);}
+
+  0; # Mist
+}
+
+sub w_simple_unlock ($) {
+  my $filename=shift;
+  my $lockfile=&lockfile($filename);
+  my $flag=1;
+  local *LF;
+
+  open(LF, ">$lockfile") or $flag=0;
+  close(LF) or $flag=0;
+
+  # Rueckgabe
+  $flag;
+}
+
+################################
+# einfaches Sperren/Entsperren
+# *n*x
+#
+# (symlink setzen)
+################################
+
+sub x_simple_lock ($;$) {
+  my $filename=shift;
+  my ($timeout)=(shift (@_) or $Timeout);
+  my $lockfile=&lockfile($filename);
+
+  my $i;
+  for ($i=$timeout; $i>=0; $i--) {
+    symlink $filename,$lockfile and return 1;
+    sleep(1);}
+
+  0; # Mist
+}
+
+sub x_simple_unlock ($) {
+  my $filename=shift;
+
+  unlink (&lockfile($filename)) and return 1;
+
+  0; # hmmm...
+}
+
+################################
+# sub w_set_ref
+# Windows
+#
+# Referenzzaehler um $_[1]
+# erhoehen
+# (kann auch negativ sein...)
+################################
+
+sub w_set_ref ($$$) {
+  my ($filename,$z)=@_;
+  my $timeout=(shift @_ or $Timeout);
+  my $old;
+  my $reffile=&reffile($filename);
+  local *REF;
+
+
+  # runterzaehlen - ja, neue Leseversuche - nein
+  if ($z > 0) {
+    return 0 unless(-e &lockfile($filename));}
+
+  # Referenzdatei locken
+  return 0 unless(&simple_lock ($reffile,$timeout));
+
+  # Referenzdatei auslesen
+  unless (open REF,"<$reffile") {
+    $old=0;}
+  else {
+    $old=<REF>;
+    chomp $old;
+    close REF or return 0;}
+
+  # Neuen Referenzwert schreiben
+  $old+=$z;
+  $old=0 if ($old < 0);
+  open REF,">$reffile" or return 0;
+  print REF $old;
+  close REF or return 0;
+
+  # wieder entsperren
+  return 0 unless(&simple_unlock($reffile));
+
+  1;
+}
+
+################################
+# sub x_set_ref
+# *n*x
+#
+# Referenzzaehler um $_[1]
+# erhoehen
+# (kann auch negativ sein...)
+################################
+
+sub x_set_ref ($$$) {
+  my ($filename,$z)=@_;
+  my $timeout=(shift @_ or $Timeout);
+  my $old;
+  my $reffile=&reffile($filename);
+  local *REF;
+
+
+  # runterzaehlen - ja, neue Leseversuche - nein
+  if ($z > 0) {
+    return 0 if(-l &lockfile($filename));}
+
+  # Referenzdatei locken
+  return 0 unless(&simple_lock ($reffile,$timeout));
+
+  # Referenzdatei auslesen
+  unless (open REF,"<$reffile") {
+    $old=0;}
+  else {
+    $old=<REF>;
+    chomp $old;
+    close REF or return 0;}
+
+  # Neuen Referenzwert schreiben
+  $old += $z;
+  $old = 0 if ($old < 0);
+  open REF,">$reffile" or return 0;
+  print REF $old;
+  close REF or return 0;
+
+  # wieder entsperren
+  return 0 unless(&simple_unlock($reffile));
+
+  1;
+}
+
+################################
+# sub get_ref
+#
+# Referenzzaehler auslesen
+#
+# Das Locking muss an
+# anderer Stelle ausgefuehrt
+# werden!
+################################
+
+sub get_ref ($$) {
+  my $filename=shift;
+  my $reffile=&reffile($filename);
+  my $old;
+  local *REF;
+
+  unless (open REF,"<$reffile") {
+    $old=0;}
+  else {
+    $old=<REF>;
+    chomp $old;
+    close REF or return 0;}
+
+  # Rueckgabe
+  $old;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+BEGIN {
+  # Globale Variablen (Zeiten in Sekunden)
+  $Timeout        =  10; # normaler Timeout
+  $violentTimeout = 600; # zum gewaltsamen Entsperren (10 Minuten)
+  $masterTimeout  =  20; # fuer die Mastersperre
+
+  $iAmMaster = 0;        # erstmal bin ich kein Master :-)
+
+  # wirkliche Funktionen ihren Bezeichnern zuweisen
+  # (perldoc -f symlink)
+
+  if ( eval {local $SIG{__DIE__}; symlink('',''); 1 } ) {
+    *lock_file           = \&x_lock_file;
+    *unlock_file         = \&x_unlock_file;
+    *write_lock_file     = \&x_write_lock_file;
+    *write_unlock_file   = \&x_write_unlock_file;
+    *violent_unlock_file = \&x_violent_unlock_file;
+    *set_master_lock     = \&x_set_master_lock;
+    *release_file        = \&x_release_file;
+
+    *simple_lock         = \&x_simple_lock;
+    *simple_unlock       = \&x_simple_unlock;
+    *set_ref             = \&x_set_ref;}
+
+  else {
+    *lock_file           = \&w_lock_file;
+    *unlock_file         = \&w_unlock_file;
+    *write_lock_file     = \&w_write_lock_file;
+    *write_unlock_file   = \&w_write_unlock_file;
+    *violent_unlock_file = \&w_violent_unlock_file;
+    *set_master_lock     = \&w_set_master_lock;
+    *release_file        = \&w_release_file;
+
+    *simple_lock         = \&w_simple_lock;
+    *simple_unlock       = \&w_simple_unlock;
+    *set_ref             = \&w_set_ref;}
+}
+
+# making require happy
+1;
+
+# ====================================================
+# end of Lock
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Mail.pm b/selfforum-cgi/shared/Mail.pm
new file mode 100644 (file)
index 0000000..e46a81c
--- /dev/null
@@ -0,0 +1,294 @@
+# Mail.pm
+
+##############################################
+#                                            #
+# Autor: n.d.p. nd@o3media.de                #
+#                                            #
+# Letze Aenderung: n.d.p. / 2001-01-03       #
+#                                            #
+# ========================================== #
+#                                            #
+# Funktion:                                  #
+#      ganz simples Formatieren und Senden   #
+#      einer Mail im text/plain, qp-Format   #
+#                                            #
+##############################################
+
+use strict;
+
+package Mail;
+
+use vars qw($mailbox $mailprog @ISA @EXPORT);
+
+# ===================
+# Funktionsexport
+# ===================
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(is_mail_address send_mail);
+
+########################################
+# EXPORT
+# sub is_mail_address
+#
+# Funktion:
+#      Ueberpruefen der Syntax einer
+#      Email-Adresse
+#
+# Rueckgabe
+#      true/false
+########################################
+
+sub is_mail_address ($) {
+  return ($_[0] =~ /$mailbox/);
+}
+
+########################################
+# EXPORT
+# sub send_mail
+#
+# Funktion:
+#      Senden der Nachricht
+#      ueber open-print-close
+#      $Mail::mailprog enthaelt
+#      den vollstaendigen string fuer
+#      open, dass heisst, es kann
+#      auch ein Dateiname sein.
+#
+# Rueckgabe:
+#      true/false
+########################################
+
+sub send_mail {
+  my $param=shift;
+  local *MAIL;
+
+  open MAIL,$mailprog or return 0;
+    print MAIL &as_string ($param);
+  close MAIL and return 1;
+
+  # Hier muss irgendwas schiefgelaufen sein
+  0;
+}
+
+##########################################
+# PRIVAT
+# sub as_string
+#
+# Funktion:
+#      Bereitstellung der gesamten Mail
+#      als String.
+#
+# Rueckgabe:
+#      String
+##########################################
+
+sub as_string {
+  my $param=shift;
+
+  my $header=&header_as_string ($param);
+  my $body=&body_as_string ($param);
+
+  # Rueckgabe
+  "$header\n$body\n";
+}
+
+##########################################
+# PRIVAT
+# sub body_as_string
+#
+# Funktion:
+#      Bereitstellung des Bodys
+#      als (qp-codierten) String.
+#
+# Rueckgabe:
+#      String
+##########################################
+
+sub body_as_string {
+  my $param=shift;
+
+  &encode_qp($param->{body});
+}
+
+##########################################
+# PRIVAT
+# sub header_as_string
+#
+# Funktion:
+#      Bereitstellung des Headers
+#      als String.
+#
+# Rueckgabe:
+#      String
+##########################################
+
+sub header_as_string {
+  my $param=shift;
+
+  my $string="Content-Disposition: inline\n";
+     $string.="MIME-Version: 1.0\n";
+     $string.="Content-Transfer-Encoding: quoted-printable\n";
+     $string.="Content-Type: text/plain\n";
+     $string.="Date: ".&rfc822_date(time)."\n";
+     $string.="From: ".$param->{'from'}."\n";
+     $string.=&get_list('To',$param->{'to'});
+     $string.=&get_list('Cc',$param->{'cc'});
+     $string.=&get_list('Bcc',$param->{'bcc'});
+     $string.="Subject: ".encode_qp($param->{'subject'})."\n";
+
+  # Rueckgabe
+  $string;
+}
+
+#######################################
+# PRIVAT
+# sub encode_qp
+#
+# C&P aus dem Modul MIME::QuotedPrint
+# Thanx for that
+#######################################
+
+sub encode_qp ($)
+{
+    my $res = shift;
+    $res =~ s/([^ \t\n!-<>-~])/sprintf("=%02X", ord($1))/eg;  # rule #2,#3
+    $res =~ s/([ \t]+)$/
+      join('', map { sprintf("=%02X", ord($_)) }
+                   split('', $1)
+      )/egm;                        # rule #3 (encode whitespace at eol)
+
+    # rule #5 (lines must be shorter than 76 chars, but we are not allowed
+    # to break =XX escapes.  This makes things complicated :-( )
+    my $brokenlines = "";
+    $brokenlines .= "$1=\n"
+        while $res =~ s/(.*?^[^\n]{73} (?:
+                 [^=\n]{2} (?! [^=\n]{0,1} $) # 75 not followed by .?\n
+                |[^=\n]    (?! [^=\n]{0,2} $) # 74 not followed by .?.?\n
+                |          (?! [^=\n]{0,3} $) # 73 not followed by .?.?.?\n
+            ))//xsm;
+
+    "$brokenlines$res";
+}
+
+##############################################
+# PRIVAT
+# sub get_list
+#
+# Funktion:
+#      Aufbereitung einer Liste oder eines
+#      Strings fuer den Header (To, Cc, Bcc)
+#
+# Rueckgabe:
+#      Ergebnis oder nichts
+##############################################
+
+sub get_list ($$) {
+  my ($start,$list)=splice @_;
+  my $string="";
+
+  return "" unless (length($list));
+  if (ref($list)) {
+    return "" unless (@$list);
+    foreach (@$list) {
+      $string.="$start: $_\n";}}
+  else {
+    $string="$start: $list\n";}
+
+  # Rueckgabe
+  $string;
+}
+
+##############################################
+# PRIVAT
+# sub rfc822_date
+#
+# Funktion:
+#      Bereitstellung eines RFC-konformen
+#      Datumstrings
+#
+# Rueckgabe:
+#      Datumstring
+##############################################
+
+sub rfc822_date ($) {
+  my ($sek, $min, $std, $mtag, $mon, $jahr, $wtag) = gmtime (+shift);
+
+  sprintf ('%s, %02d %s %04d %02d:%02d:%02d GMT',
+             (qw(Sun Mon Tue Wed Thu Fri Sat))[$wtag],
+             $mtag,
+             (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec))[$mon],
+             $jahr+1900, $std, $min, $sek);
+}
+
+##############################################
+# Modulinitialisierung
+# BEGIN
+#
+# Funktion:
+#      Bereitstellung des Regexps und des
+#      Mailprogs
+##############################################
+
+BEGIN {
+    # Standard-Mailprogramm
+
+    # Dieser String wird so, wie er ist, an die open-Anweisung geschickt,
+    # -t  = tainted(?),der Header (=alles bis zur ersten Leerzeile)
+    #       wird nach To:, Cc: und evtl. Bcc: abgesucht.
+    # -oi = damit wird verhindert, dass sendmail, ein Zeile, wo nur ein
+    #       Punkt drinsteht, als Mailende erkennt( waere Standard ).
+    # ===================================================================
+
+    $mailprog = '|/usr/lib/sendmail -t -oi';
+
+    # Thanx to J. Friedl for this regex:
+
+    my ($address,$route_addr,$phrase,$addr_spec,$X,$phrase_char,$quoted_str,$comment,$word,$phrase_ctrl,$NonASCII,
+        $CloseBR,$OpenBR,$esc,$route,$domain,$local_part,$Period,$sub_domain,$domain_lit,$domain_ref,$quoted_pair,
+        $dtext,$atom,$qtext,$atom_char,$ctrl,$space,$tab,$CloseParen,$ctext,$Cnested,$OpenParen,$CRlist);
+
+    $esc        = '\\\\';
+    $Period      = '\.';
+    $space      = '\040';
+    $tab         = '\t';
+    $OpenBR     = '\[';
+    $CloseBR     = '\]';
+    $OpenParen  = '\(';
+    $CloseParen  = '\)';
+    $NonASCII   = '\x80-\xff';
+    $ctrl        = '\000-\037';
+    $CRlist     = '\n\015';
+    $qtext = qq/[^$esc$NonASCII$CRlist\"]/;
+    $dtext = qq/[^$esc$NonASCII$CRlist$OpenBR$CloseBR]/;
+    $quoted_pair = qq< $esc [^$NonASCII] >;
+    $ctext   = qq< [^$esc$NonASCII$CRlist()] >;
+    $Cnested = qq< $OpenParen $ctext* (?: $quoted_pair $ctext* )* $CloseParen >;
+    $comment = qq< $OpenParen $ctext* (?: (?: $quoted_pair | $Cnested ) $ctext* )* $CloseParen >;
+    $X = qq< [$space$tab]* (?: $comment [$space$tab]* )* >;
+    $atom_char   = qq/[^($space)<>\@,;:\".$esc$OpenBR$CloseBR$ctrl$NonASCII]/;
+    $atom = qq< $atom_char+ (?!$atom_char) >;
+    $quoted_str = qq< \" $qtext * (?: $quoted_pair $qtext * )* \" >;
+    $word = qq< (?: $atom | $quoted_str ) >;
+    $domain_ref  = $atom;
+    $domain_lit  = qq< $OpenBR (?: $dtext | $quoted_pair )* $CloseBR >;
+    $sub_domain  = qq< (?: $domain_ref | $domain_lit ) $X >;
+    $domain = qq< $sub_domain (?: $Period $X $sub_domain )* >;
+    $route = qq< \@ $X $domain (?: , $X \@ $X $domain )* : $X >;
+    $local_part = qq< $word $X (?: $Period $X $word $X )* >;
+    $addr_spec  = qq< $local_part \@ $X $domain >;
+    $route_addr = qq[ < $X (?: $route )? $addr_spec > ];
+    $phrase_ctrl = '\000-\010\012-\037';
+    $phrase_char = qq/[^()<>\@,;:\".$esc$OpenBR$CloseBR$NonASCII$phrase_ctrl]/;
+    $phrase = qq< $word $phrase_char * (?: (?: $comment | $quoted_str ) $phrase_char * )* >;
+    $mailbox = qq< $X (?: $addr_spec | $phrase  $route_addr ) >;
+    $mailbox = qr ~^$mailbox$~x;
+}
+
+# making 'require' happy
+1;
+
+#####################
+# end of Mail
+#####################
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Posting/Write.pm b/selfforum-cgi/shared/Posting/Write.pm
new file mode 100644 (file)
index 0000000..d2444df
--- /dev/null
@@ -0,0 +1,280 @@
+# Posting/Write.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-29
+# lm   : n.d.p. / 2001-01-29
+# ====================================================
+# Funktion:
+#      Speicherung eines Postings
+# ====================================================
+
+use strict;
+
+package Posting::Write;
+
+use vars qw(@ISA @EXPORT);
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(write_posting);
+
+use Encode::Plain; $Encode::Plain::utf8 = 1;
+use Encode::Posting;
+use Lock qw(:WRITE release_file);
+use Posting::_lib qw(get_message_node get_message_header create_forum_xml_string save_file);
+
+use XML::DOM;
+
+################################
+# sub write_posting
+#
+# Neues Posting speichern
+################################
+
+sub write_posting ($) {
+  my $param = shift;
+  my ($thread,$tid);
+  my $mid   = 'm'.($param -> {lastMessage} + 1);
+
+  my $pars = {quoteChars => $param -> {quoteChars},
+              messages   => $param -> {messages}};
+
+  my %error = (threadWrite => '1 could not write thread file',
+               forumWrite  => '2 could not write forum file',
+               threadFile  => '3 could not load thread file',
+               noParent    => '4 could not find parent message');
+
+  # neue Nachricht
+  unless ($param -> {parentMessage}) {
+    $tid   = 't'.($param -> {lastThread} + 1);
+    $thread = create_new_thread ({msg      => $mid,
+                                  ip       => $param -> {ip},
+                                  name     => $param -> {author},
+                                  email    => $param -> {email},
+                                  home     => $param -> {homepage},
+                                  image    => $param -> {image},
+                                  category => $param -> {category},
+                                  subject  => $param -> {subject},
+                                  time     => $param -> {time},
+                                  dtd      => $param -> {dtd},
+                                  thread   => $tid,
+                                  body     => $param -> {body},
+                                  pars     => $pars});
+
+    save_file ($param -> {messagePath}.$tid.'.xml',\($thread -> toString)) or return $error{threadWrite};
+
+    # Thread eintragen
+    $param -> {parsedThreads}
+           -> {$param -> {lastThread} + 1} = [{mid     => $param -> {lastMessage} + 1,
+                                               unid    => $param -> {uniqueID},
+                                               name    => plain($param -> {author}),
+                                               cat     => plain(length($param -> {category})?$param->{category}:''),
+                                               subject => plain($param -> {subject}),
+                                               time    => plain($param -> {time})}];
+
+    my $forum = create_forum_xml_string ($param -> {parsedThreads},
+                                        {dtd         => $param -> {dtd},
+                                         lastMessage => $mid,
+                                         lastThread  => $tid});
+
+    save_file ($param -> {forumFile}, $forum) or return $error{forumWrite};
+    release_file ($param -> {messagePath}.$tid.'.xml');
+    return (0, $thread, $mid);}
+
+  # Reply
+  else {
+    $tid   = 't'.($param -> {thread});
+    my $tfile = $param -> {messagePath}.$tid.'.xml';
+    my $xml;
+
+    unless (write_lock_file ($tfile)) {
+      violent_unlock_file ($tfile);
+      return $error{threadFile};}
+
+    else {
+      $xml = eval {local $SIG{__DIE__}; new XML::DOM::Parser (KeepCDATA => 1) -> parsefile ($tfile);};
+
+      if ($@) {
+        violent_unlock_file ($tfile) unless (write_unlock_file ($tfile));
+        return $error{threadFile};}
+
+      my $mnode = get_message_node ($xml, $tid, 'm'.$param -> {parentMessage});
+
+      unless (defined $mnode) {
+        violent_unlock_file ($tfile) unless (write_unlock_file ($tfile));
+        return $error{noParent};}
+
+      my $pheader = get_message_header ($mnode);
+
+      my $message = create_message ($xml,
+                                   {msg      => $mid,
+                                    ip       => $param -> {ip},
+                                    name     => $param -> {author},
+                                    email    => $param -> {email},
+                                    home     => $param -> {homepage},
+                                    image    => $param -> {image},
+                                    category => length($param -> {category})?$param -> {category}:$pheader -> {category},
+                                    subject  => length($param -> {subject})?$param -> {subject}:$pheader -> {subject},
+                                    time     => $param -> {time},
+                                    pars     => $pars});
+
+      $mnode -> appendChild ($message);
+
+      my $mcontent = $xml -> createElement ('MessageContent');
+         $mcontent -> setAttribute ('mid', $mid);
+         $mcontent -> appendChild ($xml -> createCDATASection (${encoded_body(\($param -> {body}), $pars)}));
+
+      my $content = $xml -> getElementsByTagName ('ContentList', 1) -> item (0);
+         $content -> appendChild ($mcontent);
+
+      unless (save_file ($tfile, \($xml -> toString))) {
+        violent_unlock_file ($tfile) unless (write_unlock_file ($tfile));
+        return $error{threadWrite};}
+
+      violent_unlock_file ($tfile) unless (write_unlock_file ($tfile));
+
+      $thread = $xml;
+
+      # Message eintragen
+      # ACHTUNG! danach kann der Threadbaum nicht mehr fuer die visuelle
+      # Ausgabe genutzt werden, da die answers nicht angepasst werden
+      # (und somit nicht mehr stimmen...)
+
+      my $i=1;
+      my $cat  = length($param -> {category})?$param -> {category}:$pheader -> {category};
+      my $subj = length($param -> {subject})?$param -> {subject}:$pheader -> {subject};
+
+      for (@{$param -> {parsedThreads} -> {$param -> {thread}}}) {
+        if ($_ -> {mid} == $param -> {parentMessage}) {
+          splice @{$param -> {parsedThreads} -> {$param -> {thread}}},$i,0,
+            {mid     => $param -> {lastMessage} + 1,
+             unid    => $param -> {uniqueID},
+             name    => plain ($param -> {author}),
+             cat     => plain(length($cat)?$cat:''),
+             subject => plain(length($subj)?$subj:''),
+             level   => $_ -> {level} + 1,
+             time    => plain ($param -> {time})};
+          last;}
+        $i++;}
+
+      my $forum = create_forum_xml_string ($param -> {parsedThreads},
+                                          {dtd         => $param -> {dtd},
+                                           lastMessage => $mid,
+                                           lastThread  => 't'.$param -> {lastThread}});
+
+      save_file ($param -> {forumFile}, $forum) or return $error{forumWrite};}
+
+  return (0, $thread, $mid);}
+}
+
+# ====================================================
+# Private Funktionen
+# ====================================================
+
+sub create_message ($$) {
+  my ($xml,$par) = @_;
+
+  my $message = $xml -> createElement ('Message');
+  $message -> setAttribute ('id', $par -> {msg});
+  $message -> setAttribute ('ip', $par -> {ip});
+
+  # Header erzeugen
+  my $header = $xml -> createElement ('Header');
+
+  # alles inside of 'Header'
+  my $author   = $xml -> createElement ('Author');
+    my $name  = $xml -> createElement ('Name');
+    $name -> addText ($par -> {name});
+    $author -> appendChild ($name);
+
+    my $email = $xml -> createElement ('Email');
+    $email -> addText ($par -> {email});
+    $author -> appendChild ($email);
+
+    if (length ($par -> {home})) {
+      my $home  = $xml -> createElement ('HomepageUrl');
+      $home -> addText ($par -> {home});
+      $author -> appendChild ($home);}
+
+    if (length ($par -> {image})) {
+      my $image = $xml -> createElement ('ImageUrl');
+      $image -> addText ($par -> {image});
+      $author -> appendChild ($image);}
+
+  my $category = $xml -> createElement ('Category');
+  $category -> addText ($par -> {category});
+
+  my $subject  = $xml -> createElement ('Subject');
+  $subject -> addText ($par -> {subject});
+
+  my $date     = $xml -> createElement ('Date');
+  $date -> setAttribute ('longSec', $par -> {time});
+
+    $header -> appendChild ($author);
+    $header -> appendChild ($category);
+    $header -> appendChild ($subject);
+    $header -> appendChild ($date);
+  $message -> appendChild ($header);
+
+  $message;
+}
+
+sub create_new_thread ($) {
+  my $par = shift;
+
+  # neues Dokument
+  my $xml = new XML::DOM::Document;
+
+  # XML-declaration
+  my $decl = new XML::DOM::XMLDecl;
+  $decl -> setVersion  ('1.0');
+  $decl -> setEncoding ('UTF-8');
+  $xml -> setXMLDecl ($decl);
+
+  # Doctype
+  my $dtd = $xml -> createDocumentType ('Forum', $par -> {dtd}, undef, undef);
+  $xml -> setDoctype ($dtd);
+
+  # Root erzeugen
+  my $forum = $xml -> createElement ('Forum');
+
+  # Thread erzeugen
+  my $thread = $xml -> createElement ('Thread');
+  $thread -> setAttribute ('id', $par -> {thread});
+
+  # Message erzeugen
+  my $message = create_message ($xml,$par);
+
+  # Contentlist
+  my $content  = $xml -> createElement ('ContentList');
+  my $mcontent = $xml -> createElement ('MessageContent');
+  $mcontent -> setAttribute ('mid', $par -> {msg});
+  $mcontent -> appendChild ($xml -> createCDATASection (${encoded_body(\($par -> {body}), $par -> {pars} )}));
+
+  # die ganzen Nodes verknuepfen
+      $thread -> appendChild ($message);
+    $forum -> appendChild ($thread);
+
+      $content -> appendChild ($mcontent);
+    $forum -> appendChild ($content);
+
+  $xml -> appendChild ($forum);
+
+  # und fertiges Dokument zurueckgeben
+  $xml;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Posting::Write
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Posting/_lib.pm b/selfforum-cgi/shared/Posting/_lib.pm
new file mode 100644 (file)
index 0000000..fea4097
--- /dev/null
@@ -0,0 +1,509 @@
+# Posting/_lib.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-07
+# lm   : n.d.p. / 2001-01-08
+# ====================================================
+# Funktion:
+#    * Schnittstellen fuer den Zugriff auf Messages
+#    * Zeitdarstellung
+# ====================================================
+
+use strict;
+
+package Posting::_lib;
+
+use vars qw(@ISA @EXPORT_OK);
+
+use Encode::Plain; $Encode::Plain::utf8 = 1;
+
+use XML::DOM;
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+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);
+
+# ====================================================
+# Zugriff uebers DOM
+# ====================================================
+
+###########################
+# sub get_message_header
+#
+# Messageheader auslesen
+###########################
+
+sub get_message_header ($) {
+  my $node = shift;
+  my %conf;
+
+  my $header    = $node   -> getElementsByTagName ('Header', 0) -> item (0);
+    my $author  = $header -> getElementsByTagName ('Author', 0) -> item (0);
+      my $name  = $author -> getElementsByTagName ('Name', 0) -> item (0);
+      my $email = $author -> getElementsByTagName ('Email', 0) -> item (0);
+      my $home  = $author -> getElementsByTagName ('HomepageUrl', 0) -> item (0);
+      my $image = $author -> getElementsByTagName ('ImageUrl', 0) -> item (0);
+    my $cat     = $header -> getElementsByTagName ('Category', 0) -> item (0);
+    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;
+}
+
+###########################
+# sub get_message_header
+#
+# Messagebody auslesen
+###########################
+
+sub get_message_body ($$) {
+  my ($xml,$mid) = @_;
+  my $body;
+
+  foreach ($xml -> getElementsByTagName ('ContentList', 1) -> item (0) -> getElementsByTagName ('MessageContent', 0)) {
+    if ($_ -> getAttribute ('mid') eq $mid) {
+      $body = ($_ -> hasChildNodes)?$_ -> getFirstChild -> getData:'';
+      last;}}
+
+  \$body;
+}
+
+###########################
+# sub get_message_header
+#
+# Messagenode bestimmen
+###########################
+
+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) {
+          $mnode = $_;
+          last;}}
+      last;}}
+
+  wantarray?($mnode, $tnode):$mnode;
+}
+
+###########################
+# sub parse_single_thread
+#
+# 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 ('flag') eq 'deleted')?1:0,
+               name    => plain($header -> {name}),
+               cat     => plain($header -> {category} or ''),
+               subject => plain($header -> {subject}),
+               time    => plain($header -> {time})};
+    $mno{$_} = $#msg;}
+
+  # Eintraege ergaenzen und korrigieren
+  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
+
+  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 ('flag', 'deleted') if ($msg -> {deleted});
+
+  # 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
+#
+# Messages eines
+# Threads sortieren
+###########################
+
+sub sort_thread ($$) {
+  my ($msg, $sorted) = @_;
+
+  my ($z, %mhash) = (0);
+
+  if ($sorted) {  # aelteste zuerst
+    for (@$msg) {
+      @$msg[@{$_ -> {kids}}] = sort {$a -> {mid} <=> $b -> {mid}} @$msg[@{$_ -> {kids}}] if (@{$_ -> {kids}} > 1);
+      $mhash{$_ -> {mid}} = [@$msg[@{$_ -> {kids}}]];}}
+
+  else {          # juengste zuerst
+    for (@$msg) {
+      @$msg[@{$_ -> {kids}}] = sort {$b -> {mid} <=> $a -> {mid}} @$msg[@{$_ -> {kids}}] if (@{$_ -> {kids}} > 1);
+      $mhash{$_ -> {mid}} = [@$msg[@{$_ -> {kids}}]];}}
+
+  # Kinder wieder richtig einsortieren
+  my @smsg = ($msg -> [0]);
+  for (@smsg) {
+    ++$z;
+    splice @smsg,$z,0,@{$mhash{$_ -> {mid}}} if ($_ -> {answers});
+    delete $_ -> {kids};}
+
+  \@smsg;
+}
+
+###########################
+# sub delete_messages
+#
+# geoeschte Nachrichten
+# herausfiltern
+###########################
+
+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) {
+        push @path,$z;
+        $oldlevel = $_ -> {level};}
+
+      elsif ($_ -> {level} < $oldlevel) {
+        splice @path,$_ -> {level}-$oldlevel;
+        $oldlevel = $_ -> {level};}
+
+      else { $path[-1] = $z; }
+
+      $z++;}}
+
+  return;
+}
+
+###########################
+# sub get_all_threads
+#
+# Hauptdatei laden und
+# parsen
+###########################
+
+sub get_all_threads ($$;$) {
+  my ($file, $deleted, $sorted) = @_;
+  my ($last_thread, $last_message, @unids, %threads);
+  local *FILE;
+
+  open FILE, $file or return undef;
+  my $xml = join '', <FILE>;
+  close(FILE) or return undef;
+
+  if (wantarray) {
+    ($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+flag="([^"]*)")?[^>]*>\s*
+                      <Header>[^<]*(?:<(?!Name>)[^<]*)*
+                        <Name>([^<]+)</Name>[^<]*(?:<(?!Category>)[^<]*)*
+                        <Category>([^<]*)</Category>\s*
+                        <Subject>([^<]+)</Subject>\s*
+                        <Date\s+longSec="(\d+)"[^>]*>\s*
+                      </Header>\s*(?:(<)/Message>|(?=(<)Message\s*)))~sx;
+
+  while ($xml =~ /<Thread id="t(\d+)">([^<]*(?:<(?!\/Thread>)[^<]*)*)<\/Thread>/g) {
+
+    my ($tid, $thread) = ($1, $2);
+    my ($level, $cmno, @msg, @stack) = (0);
+
+    while ($thread =~ m;$reg_msg;g) {
+
+      if (defined($9)) {
+        push @stack,$cmno if (defined $cmno);
+        push @msg, {};
+
+        if (defined $cmno) {
+          push @{$msg[$cmno] -> {kids}}  => $#msg;
+          push @{$msg[$cmno] -> {unids}} => $2;}
+        else {
+          push @unids => $2;}
+
+        for (@stack) {$msg[$_] -> {answers}++}
+
+        $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/&amp;/&/g;
+        $msg[-1] -> {cat} =~ s/&amp;/&/g;
+        $msg[-1] -> {subject} =~ s/&amp;/&/g;
+
+        $msg[-1] -> {unids} = [];
+        $msg[-1] -> {kids} = [];
+        $msg[-1] -> {answers} = 0;
+        $msg[-1] -> {level} = $level++;}
+
+      elsif (defined ($8)) {
+        push @msg, {};
+
+        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[-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/&amp;/&/g;
+        $msg[-1] -> {cat} =~ s/&amp;/&/g;
+        $msg[-1] -> {subject} =~ s/&amp;/&/g;
+
+        $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);
+
+    $threads{$tid} = $smsg if (@$smsg);
+  }
+
+  wantarray?(\%threads, $last_thread, $last_message, \@unids): \%threads;
+}
+
+###########################
+# sub create_forum_xml_string
+#
+# Forumshauptdatei erzeugen
+###########################
+
+sub create_forum_xml_string ($$) {
+  my ($threads, $param) = @_;
+  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}.'">';
+
+  foreach $thread (sort {$b <=> $a} keys %$threads) {
+    $xml .= '<Thread id="t'.$thread.'">';
+    $level = -1;
+
+    foreach $msg (@{$threads -> {$thread}}) {
+      $xml .= '</Message>' x ($level - $msg -> {level} + 1) if ($msg -> {level} <= $level);
+      $level = $msg -> {level};
+      $xml .= '<Message id="m'.$msg -> {mid}.'"'
+                  .' unid="'.$msg -> {unid}.'"'
+                  .(($msg -> {deleted})?' flag="deleted"':'')
+                  .'>'
+             .'<Header>'
+             .'<Author>'
+             .'<Name>'
+                  .plain($msg -> {name})
+                  .'</Name>'
+             .'<Email></Email>'
+             .'</Author>'
+             .'<Category>'
+                  .((length $msg -> {cat})?plain($msg -> {cat}):'')
+                  .'</Category>'
+             .'<Subject>'
+                  .plain($msg -> {subject})
+                  .'</Subject>'
+             .'<Date longSec="'
+                  .$msg -> {time}
+                  .'"/>'
+             .'</Header>';}
+
+    $xml .= '</Message>' x ($level + 1);
+    $xml .= '</Thread>';}
+
+  $xml.='</Forum>';
+
+  \$xml;
+}
+
+###########################
+# sub save_file
+#
+# Datei speichern
+###########################
+
+sub save_file ($$) {
+  my ($filename,$content) = @_;
+  local *FILE;
+
+  open FILE,">$filename.temp" or return;
+
+  unless (print FILE $$content) {
+    close FILE;
+    return;};
+
+  close FILE or return;
+
+  rename "$filename.temp", $filename or return;
+
+  1;
+}
+
+# ====================================================
+# Zeitdarstellung
+# ====================================================
+
+###########################
+# sub hr_time
+#     02. Januar 2001, 12:02 Uhr
+#
+# sub short_hr_time
+#     02. 01. 2001, 12:02 Uhr
+#
+# sub long_hr_time
+#     Dienstag, 02. Januar 2001, 12:02:01 Uhr
+#
+# formatierte Zeitangabe
+###########################
+
+sub hr_time ($) {
+  my @month = qw(Januar Februar M\303\244rz April Mail Juni Juli August September Oktober November Dezember);
+                               # ^^^^^^^^ - UTF8 #
+
+  my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
+
+  sprintf ('%02d. %s %04d, %02d:%02d Uhr', $day, $month[$mon], $year+1900, $hour, $min);
+}
+
+sub short_hr_time ($) {
+  my (undef, $min, $hour, $day, $mon, $year) = localtime ($_[0]);
+
+  sprintf ('%02d. %02d. %04d, %02d:%02d Uhr', $day, $mon+1, $year+1900, $hour, $min);
+}
+
+sub long_hr_time ($) {
+  my @month = qw(Januar Februar M\303\244rz 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]);
+
+  sprintf ('%s, %02d. %s %04d, %02d:%02d:%02d Uhr', $wday[$wday], $day, $month[$mon], $year+1900, $hour, $min, $sek);
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Posting::_lib
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Template.pm b/selfforum-cgi/shared/Template.pm
new file mode 100644 (file)
index 0000000..74626d9
--- /dev/null
@@ -0,0 +1,228 @@
+# Template.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-06
+# lm   : n.d.p. / 2001-01-25
+# ====================================================
+# Funktion:
+#      Ausfuellen von Templates
+# ====================================================
+
+use strict;
+
+package Template;
+
+use XML::DOM;
+
+# ====================================================
+# Methoden
+# ====================================================
+
+################################
+# sub new
+#
+# Konstruktor
+################################
+
+sub new {
+  my $instance=shift;
+  my $class=(ref($instance) or $instance);
+
+  my $self = {};
+  $self = bless $self,$class;
+
+  $self -> file (+shift);
+
+  # Rueckgabe
+  $self;
+}
+
+################################
+# sub file
+#
+# Datei zuweisen und parsen
+################################
+
+sub file {
+  my $self = shift;
+  my $old = $self -> {file};
+  my $new = shift;
+
+  $self -> {file} = $new if (defined $new);
+  $self -> parse_file;
+
+  $old;
+}
+
+################################
+# sub insert
+#
+# Bezeichner in Metazeichen
+# eingeschlossen zurueckgeben
+################################
+
+sub insert {
+  my $self=shift;
+  die "no template file specified" unless (defined $self -> {file});
+
+  my $name=shift;
+
+  # Rueckgabe
+  $self -> {metaon} . $name . $self -> {metaoff};
+}
+
+################################
+# sub list
+#
+# komplette Liste einsetzen
+################################
+
+sub list {
+  my $self=shift;
+  my $name=shift;
+
+  die "no template file specified" unless (defined $self->{file});
+
+  my $list = join '', map { ${ $self -> scrap ($name, $_) } } @{ +shift };
+
+  # Rueckgabe
+  \$list;
+}
+
+################################
+# sub scrap
+#
+# Schnipsel ausfuellen
+################################
+
+sub scrap {
+  my $self=shift;
+  my $name=shift;
+
+  die "no template file specified" unless (defined $self->{file});
+
+  my %params;
+
+  # Parameter holen
+  # Als Values werden nur die Referenzen gespeichert
+  %params = map { my $ref = $_; map { ($_ => ( (ref ($ref -> {$_} ) )?$ref -> {$_}: \($ref -> {$_} ) ) ) } keys %$ref } splice @_;
+
+  # und einsetzen
+  my $scrap=$self->{parsed}->{$name};
+  my $qmon=quotemeta $self->{metaon};
+  my $qmoff=quotemeta $self->{metaoff};
+
+  # und zwar solange, bis nichts mehr da ist
+  while ($scrap =~ s<$qmon\s*([_a-zA-Z]\S*)\s*$qmoff>[
+    my $x='';
+    if ( exists ( $params{$1} ) ) { $x = ${$params{$1}} }
+    elsif (exists ( $self -> {parsed} -> {$1} ) ) { $x = $self -> {parsed} -> {$1}}
+    $x;]geo ){};
+
+  $self -> parse_if (\$scrap,\%params);
+
+  # Rueckgabe
+  \$scrap;
+}
+
+# ====================================================
+# Private Funktionen/Methoden
+# ====================================================
+
+################################
+# sub parse_file
+#
+# Template einlesen & parsen
+################################
+
+sub parse_file {
+  my $self = shift;
+
+  if (-f $self -> {file}) {
+    my $filename = $self -> {file};
+    my $xml = new XML::DOM::Parser -> parsefile ($filename);
+    my $template = $xml -> getElementsByTagName ('Template', 0) -> item (0);
+
+    # Metas bestimmen
+    $self -> {metaon}  = $template -> getAttribute ('metaon');
+    $self -> {metaoff} = $template -> getAttribute ('metaoff');
+
+    die "missing meta defintion(s) in template file '$filename'." unless ($self -> {metaon} and $self -> {metaoff});
+
+    $self -> {parsed} = {};
+    foreach ($template -> getElementsByTagName ('Scrap', 0)) {
+      my $name = $_ -> getAttribute ('id');
+
+      die "Element 'Scrap' requires attribute 'id' in template file '$filename'." unless (length ($name));
+      die "double defined id '$name' in template file '$filename'." if (exists ($self -> {parsed} -> {$name}));
+      die "use '/^[_a-zA-Z]\\S*\$/' for 'Scrap'-ids in template file '$filename' (wrong: '$name')." unless ($name =~ /^[_a-zA-Z]\S*$/);
+
+      $self -> {parsed} -> {$name} = $_ -> getFirstChild -> getData;
+      $self -> {parsed} -> {$name} =~ s/^\s+|\s+$//g;}
+
+    return 1; # alles klar
+  }
+
+  0;
+}
+
+################################
+# sub parse_if
+#
+# %IF - Anweisungen parsen
+################################
+
+sub parse_if {
+  my $self = shift;
+  my ($scrap,$params) = @_;
+
+  my $qmon  = quotemeta $self -> {metaon};
+  my $qmoff = quotemeta $self -> {metaoff};
+
+  # der folgende Regex ist ein bisschen fies ...
+  # ... aber er funktioniert :-)
+  #
+  # pfff - rekursive Strukturen iterativ parsen ist nicht wirklich witzig
+  while ($$scrap=~s[ ($qmon\s*%(?:IF|ELSE)\s+.+?\s*$qmoff.*?) # Wenn IF oder ELSE von
+                     (?=$qmon\s*%IF\s+.+?\s*$qmoff)           # IF gefolgt werden, soll
+                                                              # dieses Stueck uebersprungen
+                                                              # werden und erstmal mit der
+                                                              # naechsten Ebene weitergemacht
+                                                              # werden.
+
+                    |(                                        # hier beginnt $2
+                      $qmon\s*%IF\s+(.+?)\s*$qmoff            # IF
+                      (.*?)                                   # $4
+                      (?:
+                        $qmon\s*%ENDIF\s*$qmoff               # gefolgt von ENDIF
+                       |                                      # oder
+                        $qmon\s*%ELSE\s*$qmoff                # von ELSE... ($4 ELSE $5) $5 $6
+                        (.*?)
+                        $qmon\s*%ENDIF\s*$qmoff               # und ENDIF
+                      )
+                     )
+                   ]
+                   [my $ret;
+                    if ($2) {
+                      my ($t4,$t5,$t6) = ($4,$5,$6);
+                      my $flag=0;
+                      foreach (split /\s+/,$3) {
+                        if (exists($params->{$_}) and length(${$params->{$_}})) {$ret = $t4; $flag=1;last;}}
+                      $ret = $t5 unless ($flag);}
+                    else {$ret=$1;}
+                    $ret;
+                   ]gosex) {};
+
+  return;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Template
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Template/Forum.pm b/selfforum-cgi/shared/Template/Forum.pm
new file mode 100644 (file)
index 0000000..ab853ae
--- /dev/null
@@ -0,0 +1,96 @@
+# Template/Forum.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-12
+# lm   : n.d.p. / 2001-01-12
+# ====================================================
+# Funktion:
+#      Erzeugung der HTML-Ausgabe der
+#      Forumshauptdatei
+# ====================================================
+
+use strict;
+
+package Template::Forum;
+
+use vars qw(@ISA @EXPORT);
+
+use Lock qw(:READ);
+use Encode::Plain; $Encode::Plain::utf8 = 1;
+use Posting::_lib qw(get_all_threads long_hr_time);
+use Template;
+use Template::_conf;
+use Template::_thread;
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(print_forum_as_HTML);
+
+################################
+# sub print_forum_as_HTML
+#
+# HTML erstellen
+################################
+
+sub print_forum_as_HTML ($$$) {
+  my ($mainfile, $tempfile, $param) = @_;
+  my $assign = $param -> {assign};
+
+  my $template = new Template $tempfile;
+
+  my ($threads, $stat);
+
+  unless ($stat = lock_file ($mainfile)) {
+    if ($stat == 0) {
+      violent_unlock_file ($mainfile);
+      # ueberlastet
+    }
+
+    else {
+     # Mastersperre...
+    }}
+
+  else {
+    my $view = get_view_params ({adminDefault => $param -> {adminDefault}
+                               });
+
+    $threads = get_all_threads ($mainfile, $param -> {showDeleted}, $view -> {sortedMsg});
+    violent_unlock_file ($mainfile) unless (unlock_file ($mainfile));
+
+    print ${$template -> scrap ($assign -> {mainDocStart},
+                               {$assign -> {loadingTime} => plain (long_hr_time (time)) } )},"\n<dl>";
+
+    my $tpar = {template => $param -> {tree},
+                cgi      => $param -> {cgi},
+                start    => -1};
+
+    my @threads;
+
+    unless ($view -> {sortedThreads}) {
+      @threads = sort {$b <=> $a} keys %$threads;}
+    else {
+      @threads = sort {$a <=> $b} keys %$threads;}
+
+    for (@threads) {
+      $tpar -> {thread} = "$_";
+      print ${html_thread ($threads -> {$_}, $template, $tpar)},"\n",'<dd>&nbsp;</dd>',"\n";}
+
+    print "</dl>\n",${$template -> scrap ($assign -> {mainDocEnd})};}
+
+  return;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Template::Forum
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Template/Posting.pm b/selfforum-cgi/shared/Template/Posting.pm
new file mode 100644 (file)
index 0000000..d10d105
--- /dev/null
@@ -0,0 +1,147 @@
+# Template/Posting.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-14
+# lm   : n.d.p. / 2001-01-14
+# ====================================================
+# Funktion:
+#      HTML-Darstellung eines Postings
+# ====================================================
+
+use strict;
+
+package Template::Posting;
+
+use vars qw(@ISA @EXPORT);
+
+use Encode::Posting;
+use Encode::Plain; $Encode::Plain::utf8 = 1;
+use Id;
+use Lock qw(:WRITE);
+use Posting::_lib qw(get_message_node get_message_header get_message_body parse_single_thread hr_time);
+use Template;
+use Template::_query;
+use Template::_thread;
+
+use XML::DOM;
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(print_posting_as_HTML message_as_HTML);
+
+################################
+# sub print_posting_as_HTML
+#
+# HTML erzeugen
+################################
+
+sub print_posting_as_HTML ($$$) {
+  my ($threadpath, $tempfile, $param) = @_;
+
+  my $template = new Template $tempfile;
+
+  # Datei sperren... (eigentlich)
+  my $xml=new XML::DOM::Parser -> parsefile ($threadpath.'t'.$param -> {thread}.'.xml');
+
+  my ($mnode, $tnode) = get_message_node ($xml, 't'.$param -> {thread}, 'm'.$param -> {posting});
+  my $pnode = $mnode -> getParentNode;
+  my $header = get_message_header ($mnode);
+  my $msg = parse_single_thread ($tnode, 0, 0);
+  my $pheader = ($pnode -> getNodeName eq 'Message')?get_message_header ($pnode):{};
+
+  my $assign = $param -> {assign};
+  my $formdata = $param -> {form} -> {data};
+  my $formact = $param -> {form} -> {action};
+
+  my $body = get_message_body ($xml, 'm'.$param -> {posting});
+
+  my $text = message_field ($body,
+                           {quoteChars => '&raquo;&raquo; ',
+                            quoting    => 1,
+                            startCite  => ${$template -> scrap ($assign -> {startCite})},
+                            endCite    => ${$template -> scrap ($assign -> {endCite})}
+                           });
+
+  my $area = answer_field ($body,
+                          {quoteArea  => 1,
+                           quoteChars => '&raquo;&raquo; ',
+                           messages   => $param -> {messages}
+                          });
+
+  my $pars = {};
+
+  for (qw(posterBody uniqueID followUp quoteChar userID posterName posterEmail posterURL posterImage)) {
+    $pars -> {$formdata -> {$_} -> {assign} -> {name}} = plain($formdata -> {$_} -> {name});}
+
+  my $cgi = $param -> {cgi};
+
+  my $tpar = {thread   => $param -> {thread},
+              template => $param -> {tree},
+              start    => $param -> {posting},
+              cgi      => $cgi};
+
+  my $plink = %$pheader?(query_string ({$cgi -> {thread} => $param -> {thread}, $cgi -> {posting} => ($pnode -> getAttribute ('id') =~ /(\d+)/)[0]})):'';
+
+  print ${$template -> scrap ($assign->{mainDoc},
+                             {$assign->{name}                            => plain($header->{name}),
+                              $assign->{email}                           => plain($header->{email}),
+                              $assign->{home}                            => plain($header->{home}),
+                              $assign->{image}                           => plain($header->{image}),
+                              $assign->{time}                            => plain(hr_time($header->{time})),
+                              $assign->{message}                         => $text,
+                              $assign->{messageTitle}                    => plain($header->{subject}),
+                              $assign->{parentTitle}                     => plain($pheader->{subject}),
+                              $assign->{messageCat}                      => plain($header->{category}),
+                              $assign->{parentCat}                       => plain($pheader->{category}),
+                              $assign->{parentName}                      => plain($pheader->{name}),
+                              $assign->{parentLink}                      => $plink,
+                              $assign->{parentTime}                      => plain(hr_time($pheader->{time})),
+                              $param->{tree}->{main}                     => html_thread ($msg, $template, $tpar),
+                              $formact->{post}->{assign}                 => $formact->{post}->{url},
+                              $formact->{vote}->{assign}                 => $formact->{vote}->{url},
+                              $formdata->{posterBody}->{assign}->{value} => $area,
+                              $formdata->{uniqueID}  ->{assign}->{value} => plain(unique_id),
+                              $formdata->{followUp}  ->{assign}->{value} => plain($param -> {thread}.';'.$param -> {posting}),
+                              $formdata->{quoteChar} ->{assign}->{value} => "&#255;".plain('»» '),
+                              $formdata->{userID}    ->{assign}->{value} => '',
+                              }, $pars)};
+
+}
+
+################################
+# sub message_as_HTML
+#
+# HTML erzeugen
+################################
+
+sub message_as_HTML ($$$) {
+  my ($xml, $template, $param) = @_;
+
+  my $assign = $param -> {assign};
+  my $body = get_message_body ($xml, $param -> {posting});
+
+  my $text = message_field ($body,
+                           {quoteChars => '&raquo;&raquo; ',
+                            quoting    => 1,
+                            startCite  => ${$template -> scrap ($assign -> {startCite})},
+                            endCite    => ${$template -> scrap ($assign -> {endCite})}
+                           });
+
+  # Rueckgabe
+  $text;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Template::Posting
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Template/_conf.pm b/selfforum-cgi/shared/Template/_conf.pm
new file mode 100644 (file)
index 0000000..b94d01d
--- /dev/null
@@ -0,0 +1,54 @@
+# Template/_conf.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-02-20
+# lm   : n.d.p. / 2001-02-20
+# ====================================================
+# Funktion:
+#      Bereitstellung der Ausgabeparameter
+#      durch Kombination von User und Adminkonf.
+# ====================================================
+
+use strict;
+
+package Template::_conf;
+
+use vars qw(@ISA @EXPORT);
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(get_view_params);
+
+################################
+# sub get_view_params
+#
+# Ausgabeparameter bestimmen
+################################
+
+sub get_view_params ($) {
+  my $param = shift;
+  my $default = $param -> {adminDefault};
+  my %hash;
+
+  %hash = (quoteChars    => $default -> {View} -> {quoteChars},
+           sortedMsg     =>  $default -> {View} -> {sortMessages},
+           sortedThreads => $default -> {View} -> {sortThreads}
+          );
+
+  \%hash;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Template::_conf
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Template/_query.pm b/selfforum-cgi/shared/Template/_query.pm
new file mode 100644 (file)
index 0000000..606f4f3
--- /dev/null
@@ -0,0 +1,71 @@
+# Template/_query.pm
+
+# ====================================================
+# Autor: n.d.p. / 2000-12-30
+# lm   : n.d.p. / 2001-02-04
+# ====================================================
+# Funktion:
+#      Erzeugen eines Querystrings
+# ====================================================
+
+use strict;
+
+package Template::_query;
+
+use vars qw(@ISA @EXPORT);
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(query_string);
+
+################################
+# sub query_string
+#
+# Querystring erzeugen
+################################
+
+sub query_string ($) {
+  my $parlist=shift;
+
+  my $string = '?'.join ('&amp;',
+                         map {(ref)?map{&url_encode ($_).'='.&url_encode ($parlist -> {$_})} @{$parlist -> {$_}}:
+                                    &url_encode ($_).'='.&url_encode ($parlist -> {$_})}
+                           keys %$parlist);
+
+  # return
+  $string;
+}
+
+# ====================================================
+# Private Funktionen
+# ====================================================
+
+################################
+# sub url_encode
+#
+# URL-Codierung
+# (mehr oder weniger aus
+#  CGI.pm geklaut...)
+################################
+
+sub url_encode ($) {
+  my $string = shift;
+  $string=~s/([^a-zA-Z\d_.-])/uc sprintf('%%%02x',ord($1))/eg;
+
+  $string;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Template::_query
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Template/_thread.pm b/selfforum-cgi/shared/Template/_thread.pm
new file mode 100644 (file)
index 0000000..8c3cbbb
--- /dev/null
@@ -0,0 +1,136 @@
+# Template/_thread.pm
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-11
+# lm   : n.d.p. / 2001-01-11
+# ====================================================
+# Funktion:
+#      HTML-Darstellung eines Threads
+# ====================================================
+
+use strict;
+
+package Template::_thread;
+
+use vars qw(@ISA @EXPORT);
+
+use Encode::Plain; $Encode::Plain::utf8 = 1;
+use Posting::_lib qw(short_hr_time);
+use Template;
+use Template::_query;
+
+# ====================================================
+# Funktionsexport
+# ====================================================
+
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(html_thread);
+
+################################
+# sub html_thread
+#
+# Thread erzeugen
+################################
+
+sub html_thread ($$$) {
+  my ($msg, $template, $par) = @_;
+
+  return \'' unless @$msg;
+
+  my $temp = $par -> {template};
+  my $i = $par -> {cgi} -> {user};
+  my $t = $par -> {cgi} -> {thread};
+  my $p = $par -> {cgi} -> {posting};
+  my $c = $par -> {cgi} -> {command};
+  my $tid = $par -> {thread};
+  my $html='';
+  my $startlevel=0;
+  my $oldlevel=0;
+  my @indexes;
+
+  # ganzer Thread
+  if ($par -> {start} == -1) {
+    $_ = $msg -> [0];
+    @indexes = (1..$_ -> {answers});
+
+    if ($_ -> {answers}) {
+      $html = '<dd><dl><dt>'
+              .${$template -> scrap ($temp -> {(length $_ -> {cat})?'start':'startNC'},
+                                    {$temp -> {name}    => $_ -> {name},
+                                     $temp -> {subject} => $_ -> {subject},
+                                     $temp -> {cat}     => $_ -> {cat},
+                                     $temp -> {time}    => plain(short_hr_time ($_ -> {time})),
+                                     $temp -> {link}    => query_string({$t => $tid, $p => $_ -> {mid}})},
+                                     $par -> {addParam})}
+              .'</dt>';}
+
+    else {
+      $html = '<dd>'
+              .${$template -> scrap ($temp -> {(length $_ -> {cat})?'start':'startNC'},
+                                    {$temp -> {name}    => $_ -> {name},
+                                     $temp -> {subject} => $_ -> {subject},
+                                     $temp -> {cat}     => $_ -> {cat},
+                                     $temp -> {time}    => plain(short_hr_time ($_ -> {time})),
+                                     $temp -> {link}    => query_string({$t => $tid, $p => $_ -> {mid}})},
+                                     $par -> {addParam})}
+              .'</dd>';
+
+      return \$html;}}
+
+  # Teilthread
+  else {
+    my $start=-1;
+    for (@$msg) {$start++; last if ($_ -> {mid} == $par -> {start});}
+    my $end   = $start + $msg -> [$start] -> {answers};
+    $start++;
+    @indexes = ($start..$end);
+    $oldlevel = $startlevel = $msg -> [$par -> {start}] -> {level};}
+
+  # HTML erzeugen
+  for (@$msg[@indexes]) {
+
+    if ($_ -> {level} < $oldlevel) {
+      $html.='</dl></dd>' x ($oldlevel - $_ -> {level});}
+
+    $oldlevel = $_ -> {level};
+
+    if ($_ -> {answers}) {
+      $html.='<dd><dl><dt>'
+             .${$template -> scrap ($temp -> {(length $_ -> {cat})?'line':'lineNC'},
+                                   {$temp -> {name}    => $_ -> {name},
+                                   $temp -> {subject} => $_ -> {subject},
+                                   $temp -> {cat}     => $_ -> {cat},
+                                   $temp -> {time}    => plain(short_hr_time ($_ -> {time})),
+                                   $temp -> {link}    => query_string({$t => $tid, $p => $_ -> {mid}})},
+                                   $par -> {addParam})}
+             .'</dt>';
+    }
+    else {
+      $html.='<dd>'
+             .${$template -> scrap ($temp -> {(length $_ -> {cat})?'line':'lineNC'},
+                                   {$temp -> {name}    => $_ -> {name},
+                                   $temp -> {subject} => $_ -> {subject},
+                                   $temp -> {cat}     => $_ -> {cat},
+                                   $temp -> {time}    => plain(short_hr_time ($_ -> {time})),
+                                   $temp -> {link}    => query_string({$t => $tid, $p => $_ -> {mid}})},
+                                   $par -> {addParam})}
+             .'</dd>';
+    }
+  }
+
+  $html.='</dl></dd>' x ($oldlevel - $startlevel);
+
+  \$html;
+}
+
+# ====================================================
+# Modulinitialisierung
+# ====================================================
+
+# making require happy
+1;
+
+# ====================================================
+# end of Template::_thread
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/shared/common.xml b/selfforum-cgi/shared/common.xml
new file mode 100644 (file)
index 0000000..b534444
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+
+<Config>
+  <Constant name="wwwRoot">C:/Server/teamone</Constant>
+  <Constant name="cgiRoot">C:/Server/teamone/cgi-local</Constant>
+  <Constant name="serverName">teamone</Constant>
+</Config>
+
+<!-- Ende -->
diff --git a/selfforum-cgi/user/config/answer.tmp.xml b/selfforum-cgi/user/config/answer.tmp.xml
new file mode 100644 (file)
index 0000000..8da9959
--- /dev/null
@@ -0,0 +1,236 @@
+<?xml version="1.0"?>
+
+<Template metaon="{&amp;&amp;" metaoff="&amp;&amp;}">
+
+  <Scrap id="DOC_OPENING"><![CDATA[
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<!--   <meta http-equiv="expires" content="0">
+       <meta name="robots" content="noindex">
+ -->
+       <title>{&& %IF _ERR_MESS &&}SELFHTML Forum: Fehler{&& %ELSE &&}SELFHTML Forum: Neue Nachricht verfassen{&& %ENDIF &&}</title>
+
+       <link rel="stylesheet" type="text/css" href="{&& _CSS_FILE &&}">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000" link="#AA5522" vlink="#772200" alink="#000000">
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="top">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&} {&& IMG_X2 &&} {&& LINK_SELFFORUM &&}</td></tr>
+</table>
+
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc" width=110>{&& IMG_XWEB &&}</td>
+       <td bgcolor="#EEEEEE" class="doc" valign="bottom" width="100%"><h2>SELFHTML Forum<br>{&& %IF _ERR_MESS &&}Fehler{&& %ELSE &&}Neue Nachricht verfassen{&& %ENDIF &&}</h2></td></tr>
+<tr><td bgcolor="#EEEEEE" class="doc" valign="top" align="center">{&& IMG_X5 &&}</td>
+       <td bgcolor="#FFFFFF" valign="top">
+               <p>{&& IMG_XGDOWN &&}&nbsp;<a href="#a1"><b>{&& %IF _ERR_MESS &&}Fehler{&& %ELSE &&}Neue Nachricht verfassen{&& %ENDIF &&}</b></a><br></p>{&& %IF _ERR_MESS &&}{&& %ELSE &&}
+               <p><a name="zu_diesem_Forum" class="an">Dies ist ein Forum</a> als Erg&auml;nzung zu {&& IMG_X1 &&}&nbsp;{&& LINK_SELFHTML &&}. Von allen hier Teilnehmenden werden HTML-Grundkenntnisse erwartet. Es wird auch erwartet, da&szlig; bei Problemen erst einmal in SELFHTML oder anderen Hilfen nach einer L&ouml;sung gesucht wird. Ferner sollten folgende Ressourcen bekannt sein:<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_FAQ &&}<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_AUSLESE &&}<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_ARCHIV &&}<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_SUCHE &&}</p>
+                  <br>&nbsp;</td></tr>{&& %ENDIF &&}
+<tr><td colspan=2 bgcolor="#EEEEEE" class="doc">
+               <a href="#bottom">{&& IMG_XGDOWN &&}</a>&nbsp;</td></tr>
+</table>
+
+{&& %IF _ERR_MESS &&}<h2 class="Sh2"><a class="an" name="a1">Fehler</a></h2>
+<p>{&& _ERR_MESS &&}</p>{&& %ELSE &&}<h2 class="Sh2"><a class="an" name="a1">Neue Nachricht verfassen</a></h2>
+<p>Mit einer neuen Nachricht wird auch ein neues Thema (neuer Nachrichten-Thread) gestartet. Das ist sinnvoll, um eine Frage zu stellen oder eine neue Diskussion zu entfachen.</p>{&& %ENDIF &&}
+{&& POST_FORM &&}
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc">
+               <a href="#top">{&& IMG_XGOUP &&}</a></td></tr>
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="bottom">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&} {&& IMG_X2 &&} {&& LINK_SELFFORUM &&}</td></tr>
+</table>
+<p>&copy; 2000 {&& IMG_XGMAIL &&}&nbsp;<a href="mailto:{&& MAIL_SELF &&}">{&& MAIL_SELF &&}</a></p>
+</body>
+</html>
+  ]]></Scrap>
+
+  <Scrap id="DOC_FATAL"><![CDATA[
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+       <meta name="robots" content="noindex">
+
+       <title>SELFHTML Forum: Fehler</title>
+
+       <link rel="stylesheet" type="text/css" href="{&& _CSS_FILE &&}">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000" link="#AA5522" vlink="#772200" alink="#000000">
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="top">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&} {&& IMG_X2 &&} {&& LINK_SELFFORUM &&}</td></tr>
+</table>
+
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc" width=110>{&& IMG_XWEB &&}</td>
+       <td bgcolor="#EEEEEE" class="doc" valign="bottom" width="100%"><h2>SELFHTML Forum<br>Fehler</h2></td></tr>
+<tr><td bgcolor="#EEEEEE" class="doc" valign="top" align="center">{&& IMG_X5 &&}</td>
+<td bgcolor="#FFFFFF" valign="top">
+       <p>{&& IMG_XGDOWN &&}&nbsp;<a href="#a1"><b>Fehler</b></a><br></p></td></tr>
+<tr><td colspan=2 bgcolor="#EEEEEE" class="doc">
+               <a href="#bottom">{&& IMG_XGDOWN &&}</a>&nbsp;</td></tr>
+</table>
+
+<h2 class="Sh2"><a class="an" name="a1">Fehler</a></h2>
+<p>{&& _ERR_MESS &&}</p>
+
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc"><a href="#top">{&& IMG_XGOUP &&}</a></td></tr>
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="bottom">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&} {&& IMG_X2 &&} {&& LINK_SELFFORUM &&}</td></tr>
+</table>
+
+<p><a class="an" name="bottom">&copy; 2000</a> {&& IMG_XGMAIL &&}&nbsp;<a href="mailto:{&& MAIL_SELF &&}">{&& MAIL_SELF &&}</a></p>
+</body>
+</html>
+  ]]></Scrap>
+
+  <Scrap id="DOC_THANKYOU"><![CDATA[
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+       <meta name="robots" content="noindex">
+
+       <title>SELFHTML Forum: {&& %IF _CATEGORY &&}({&& _CATEGORY &&}) {&& %ENDIF &&}{&& _TITLE &&}</title>
+
+       <link rel="stylesheet" type="text/css" href="{&& _CSS_FILE &&}">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000" link="#AA5522" vlink="#772200" alink="#000000">
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="top">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&} {&& IMG_X2 &&} {&& LINK_SELFFORUM &&}</td></tr>
+</table>
+
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc" width=110>{&& IMG_XWEB &&}</td>
+       <td bgcolor="#EEEEEE" class="doc" valign="bottom" width="100%"><h2>Danke</h2></td></tr>
+<tr><td bgcolor="#EEEEEE" class="doc" valign="top" align="center">{&& IMG_X5 &&}</td>
+<td bgcolor="#FFFFFF" valign="top">
+       <p>{&& IMG_XGDOWN &&}&nbsp;<a href="#a1"><b>Diese Nachricht ist nun im Forum lesbar</b></a><br></p></td></tr>
+<tr><td colspan=2 bgcolor="#EEEEEE" class="doc">
+               <a href="#bottom">{&& IMG_XGDOWN &&}</a>&nbsp;</td></tr>
+</table>
+
+<h2 class="Sh2"><a class="an" name="a1">Diese Nachricht ist nun im Forum lesbar</a></h2>
+<p>von: <b>{&& _NAME &&}</b>{&& %IF _MAIL &&}, {&& IMG_XGMAIL &&}&nbsp;<a href="mailto:{&& _MAIL &&}"><b>{&& _MAIL &&}</b></a>{&& %ENDIF &&}, {&& _TIME &&}{&& %IF _HOME &&}<br>
+   <a href="{&& _HOME &&}"><b>{&& _HOME &&}</b></a>{&& %ENDIF &&}</p>
+<h3>{&& %IF _CATEGORY &&}({&& _CATEGORY &&}) {&& %ENDIF &&}{&& _TITLE &&}</h3>
+<p><tt>{&& _BODY &&}</tt></p><br>&#160;{&& %IF _IMAGE &&}
+<p><img src="{&& _IMAGE &&}" border=0 alt=""></p>{&& %ENDIF &&}
+
+<table cellpadding=4 cellspacing=0 border=0 width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc"><a href="#top">{&& IMG_XGOUP &&}</a></td></tr>
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="bottom">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&} {&& IMG_X2 &&} {&& LINK_SELFFORUM &&}</td></tr>
+</table>
+
+<p><a class="an" name="bottom">&copy; 2000</a> {&& IMG_XGMAIL &&}&nbsp;<a href="mailto:{&& MAIL_SELF &&}">{&& MAIL_SELF &&}</a></p>
+</body>
+</html>
+  ]]></Scrap>
+
+<!--
+       ***** Fehlermeldungen *****
+       (fatal)
+-->
+
+<Scrap id="_MANIPULATED"><![CDATA[ Die &Uuml;bergabedaten sind fehlerhaft oder wurden manipuliert. Zumindest sind sie unbrauchbar, deshalb sehen Sie diese Fehlermeldung. ]]></Scrap>
+<Scrap id="_OCCUPIED"><![CDATA[ Es wird gerade ein anderes Posting bearbeitet. Bitte einfach nochmal abschicken (vorher evtl. ein paar Minuten warten). ]]></Scrap>
+<Scrap id="_UNKNOWN"><![CDATA[ Es ist ein nicht identifizierbarer Fehler aufgetreten. Wir bitten um Entschuldigung und Ihr Verst&auml;ndnis. Wir werden den Fehler so bald wie m&ouml;glich beheben. ]]></Scrap>
+<Scrap id="_ENCODING"><![CDATA[ Die &Uuml;bergabedaten konnten nicht ausgewertet werden, da eine unbekannte Zeichencodierung verwendet wurde. Dieses System unterst&uuml;tzt derzeit nur den Latin-1-Zeichensatz (ISO-8859-1) und (experimentell) UTF-8. ]]></Scrap>
+<Scrap id="_NAME_TOO_LONG"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte den Namen! Er ist zu lang{&& %IF _NUM &&} (maximal {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_NAME_TOO_SHORT"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte den Namen! Er ist zu kurz{&& %IF _NUM &&} (mindestens {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_MAIL_TOO_LONG"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte die Mailadresse! Sie ist zu lang{&& %IF _NUM &&} (maximal {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_MAIL_TOO_SHORT"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte die Mailadresse! Sie ist zu kurz{&& %IF _NUM &&} (mindestens {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_MAIL_WRONG"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte die Mailadresse! Sie scheint nicht korrekt zu sein. ]]></Scrap>
+<Scrap id="_CAT_WRONG"><![CDATA[ W&auml;hlen Sie bitte einen Themenbereich aus dem Auswahlfeld! ]]></Scrap>
+<Scrap id="_SUB_TOO_LONG"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte das Thema! Es ist zu lang{&& %IF _NUM &&} (maximal {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_SUB_TOO_SHORT"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte das Thema! Es ist zu kurz{&& %IF _NUM &&} (mindestens {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_BODY_TOO_LONG"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte Ihre Mitteilung! Sie ist zu lang{&& %IF _NUM &&} (maximal {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_BODY_TOO_SHORT"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte Ihre Mitteilung! Haben Sie so wenig zu sagen? ]]></Scrap>
+<Scrap id="_URL_TOO_LONG"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte den Homepage-URL! Er ist zu lang{&& %IF _NUM &&} (maximal {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_IMG_TOO_LONG"><![CDATA[ &Uuml;berpr&uuml;fen Sie bitte den Bild-URL! Er ist zu lang{&& %IF _NUM &&} (maximal {&& _NUM &&} Zeichen){&& %ENDIF &&}. ]]></Scrap>
+<Scrap id="_NOREPLY"><![CDATA[ Die Nachricht, auf die Sie antworten m&ouml;chten, wurde nicht gefunden. ]]></Scrap>
+<Scrap id="_DUPE"><![CDATA[ Sie haben (vermutlich versehentlich) versucht, das Posting mehr als einmal abzusetzen. Ihr Beitrag wurde bereits aufgenommen. ]]></Scrap>
+<!--
+       ***** Schnipsel *****
+       aus Grundelementen zusammengesetzt
+-->
+
+  <Scrap id="POST_FORM"><![CDATA[
+<form method="post" action="{&& _FORM_ACTION &&}">{&& %IF _FORM_FUP_VALUE &&}
+<input type="hidden" name="{&& _FORM_FUP_NAME &&}" value="{&& _FORM_FUP_VALUE &&}">{&& %ENDIF &&}{&& %IF _FORM_UID_VALUE &&}
+<input type="hidden" name="{&& _FORM_UID_NAME &&}" value="{&& _FORM_UID_VALUE &&}">{&& %ENDIF &&}
+<input type="hidden" name="{&& _FORM_UNID_NAME &&}" value="{&& _FORM_UNID_VALUE &&}">
+<input type="hidden" name="{&& _FORM_QCHAR_NAME &&}" value="{&& _FORM_QCHAR_VALUE &&}">
+<table bgcolor="#EEEEEE" cellpadding="2" cellspacing="0" border="0">
+<tr><td align="right" valign="middle"><br><b>Name:</b></td>
+       <td valign="top"><br><input type="text" name="{&& _FORM_NAME_NAME &&}" value="{&& _FORM_NAME_VALUE &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt;"></td></tr>
+<tr><td align="right" valign="middle"><b>E-Mail:</b></td>
+       <td valign="top"><input type="text" name="{&& _FORM_MAIL_NAME &&}" value="{&& _FORM_MAIL_VALUE &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt"></td></tr>
+<tr><td align="right" valign="middle"><b>Themenbereich:</b></td>
+       <td valign="top"><select size=1 name="{&& _FORM_CAT_NAME &&}" style="width:260px; font-family:Arial,Sans-serif; font-size:10pt">
+               <option value="">Bitte ausw&auml;hlen!</option>{&& _CATLIST &&}</select></td></tr>
+<tr><td align="right" valign="middle"><b>Thema:</b></td>
+       <td valign="top"><input type="text" name="subject" value="{&& _FORM_SUBJECT_VALUE &&}" size=40 style="width:410px; font-family:Arial,Sans-serif; font-size:10pt"></td></tr>
+<tr><td valign="top" colspan=2>
+               <b>Nachrichtentext:</b><br>
+               <tt><textarea cols="76" rows="25" name="{&& _FORM_BODY_NAME &&}" style="width:580px; height:380px; font-family:Courier New,Courier; font-size:10pt; color:#0000C0">{&& _FORM_BODY_VALUE &&}{&& %IF _FORM_SIGN_VALUE &&}
+--
+{&& _FORM_SIGN_VALUE &&}{&& %ENDIF &&}</textarea></tt></td></tr>
+<tr><td align="right" valign="middle"><b>URL (optional):</b></td>
+       <td valign="top"><input type="text" name="{&& _FORM_URL_NAME &&}" value="{&& %IF _FORM_URL_VALUE &&}{&& _FORM_URL_VALUE &&}{&& %ELSE &&}http://{&& %ENDIF &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt"></td></tr>
+<tr><td align="right" valign="middle"><b>URL Grafik (optional):</b></td>
+       <td valign="top"><input type=text name="{&& _FORM_IMG_NAME &&}" value="{&& %IF _FORM_IMG_VALUE &&}{&& _FORM_IMG_VALUE &&}{&& %ELSE &&}http://{&& %ENDIF &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt"></td></tr>
+<tr><td valign="top" nowrap colspan="2"><input type="submit" value="Nachricht absenden"> <input type="reset" value="Eingaben verwerfen"></td></tr>
+</table>
+</form><br>
+<p>Bitte nur <b>einmal</b> auf <i>Nachricht absenden</i> klicken, dann abwarten!</p>
+  ]]></Scrap>
+
+<Scrap id="OPTION"><![CDATA[ <option{&& %IF _SELECTED &&} selected{&& %ENDIF &&}>{&& _OPTVAL &&}</option> ]]></Scrap>
+
+<!--
+       ***** ATOMICS *****
+       Grundelemente
+-->
+
+<Scrap id="CITE_START"><![CDATA[ <span style="color:#800000;"> ]]></Scrap>
+<Scrap id="CITE_END"><![CDATA[ </span><br> ]]></Scrap>
+
+<!--
+       Links/URLs
+-->
+
+<Scrap id="MAIL_SELF"><![CDATA[ selfhtml@teamone.de ]]></Scrap>
+
+<Scrap id="LINK_SELFAKTUELL"><![CDATA[ <a href="/selfaktuell/"><b>SELFHTML&nbsp;aktuell</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFLIVE"><![CDATA[ <a href="/selfaktuell/live/"><b>SELFHTML&nbsp;live!</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFFORUM"><![CDATA[ <a href="/selfaktuell/forum/"><b>SELFHTML&nbsp;Forum</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFHTML"><![CDATA[ <a href="/selfhtml/"><b>SELFHTML</b></a> ]]></Scrap>
+<Scrap id="LINK_FAQ"><![CDATA[ <a href="/selfaktuell/forum/forumsfaq.htm"><b>Forums-FAQ</b></a> ]]></Scrap>
+<Scrap id="LINK_AUSLESE"><![CDATA[ <a href="/selfaktuell/forum/forumsauslese.htm"><b>Forums-Auslese</b></a> ]]></Scrap>
+<Scrap id="LINK_ARCHIV"><![CDATA[ <a href="/selfaktuell/forum/forumsarchiv.htm"><b>Forumsarchiv</b></a> ]]></Scrap>
+<Scrap id="LINK_SUCHE"><![CDATA[ <a href="/cgi-local/sfasuch.pl"><b>Forumsarchiv-Suche</b></a> ]]></Scrap>
+
+<Scrap id="_CSS_FILE"><![CDATA[ /selfaktuell/src/wselfhtm.css ]]></Scrap>
+
+<!--
+       Bilder
+-->
+
+<Scrap id="IMG_XGMAIL"><![CDATA[ <img src="/selfaktuell/src/xgmail.gif" width="15" height="10" border="0" alt="E-Mail"> ]]></Scrap>
+<Scrap id="IMG_XGOUP"><![CDATA[ <img src="/selfaktuell/src/xgoup.gif" width="14" height="10" border="0" alt="nach oben"> ]]></Scrap>
+<Scrap id="IMG_XGDOWN"><![CDATA[ <img src="/selfaktuell/src/xgdown.gif" width="14" height="10" border="0" alt="nach unten"> ]]></Scrap>
+<Scrap id="IMG_X1"><![CDATA[ <img src="/selfaktuell/src/x1.gif" width="15" height="13" border="0" alt="Ordner"> ]]></Scrap>
+<Scrap id="IMG_X2"><![CDATA[ <img src="/selfaktuell/src/x2.gif" width="16" height="13" border="0" alt="Teil von"> ]]></Scrap>
+<Scrap id="IMG_X3"><![CDATA[ <img src="/selfaktuell/src/x3.gif" width="15" height="10" border="0" alt="Seite"> ]]></Scrap>
+<Scrap id="IMG_X5"><![CDATA[ <img src="/selfaktuell/src/x5.gif" width="30" height="20" vspace="6" border="0" alt="Informationsseite"> ]]></Scrap>
+<Scrap id="IMG_XWEB"><![CDATA[ <img src="/selfaktuell/src/xweb.gif" width="106" height="109" border="0" alt="SELFHTML"> ]]></Scrap>
+
+</Template>
diff --git a/selfforum-cgi/user/config/common.xml b/selfforum-cgi/user/config/common.xml
new file mode 100644 (file)
index 0000000..f0496b0
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+
+<Config>
+  <Property name="files">
+    <Variable name="messagePath">/selfaktuell/forum/messages/</Variable>
+    <Variable name="forum">/selfaktuell/forum/messages/selfforum.xml</Variable>
+    <Variable name="adminDefault">config/fo_admin_default.xml</Variable>
+  </Property>
+
+  <Property name="template">
+
+    <Property name="messages">
+      <Property name="selbermachen">
+        <Variable name="src">/selfaktuell/forum/images/01.gif</Variable>
+        <Variable name="width">419</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">F&#252;r dein Problem gibt es nur eine L&#246;sung: SELFmade von Selbermachen.</Variable></Property>
+
+      <Property name="archiv">
+        <Variable name="src">/selfaktuell/forum/images/02.gif</Variable>
+        <Variable name="width">302</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">Die Antwort auf deine Frage findest du im Archiv.</Variable></Property>
+
+      <Property name="formulierung">
+        <Variable name="src">/selfaktuell/forum/images/03.gif</Variable>
+        <Variable name="width">248</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">Was willst du jetzt eigentlich wissen?</Variable></Property>
+
+      <Property name="selfhtml">
+        <Variable name="src">/selfaktuell/forum/images/04.gif</Variable>
+        <Variable name="width">428</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">Schau mal in SELFHTML nach, um eine Antwort auf deine Frage zu finden!</Variable></Property>
+
+      <Property name="ende">
+        <Variable name="src">/selfaktuell/forum/images/05.gif</Variable>
+        <Variable name="width">158</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">Jetzt reicht's aber!</Variable></Property>
+
+      <Property name="reihenfolge">
+        <Variable name="src">/selfaktuell/forum/images/06.gif</Variable>
+        <Variable name="width">462</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">Erstmal selber probieren, dann bei Problemen: SELFHTML, danach: dieses Forum.</Variable></Property>
+
+      <Property name="fehlamplatz">
+        <Variable name="src">/selfaktuell/forum/images/07.gif</Variable>
+        <Variable name="width">275</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">Stopp! So etwas hat hier nichts zu suchen.</Variable></Property>
+
+      <Property name="links">
+        <Variable name="src">/selfaktuell/forum/images/08.gif</Variable>
+        <Variable name="width">213</Variable>
+        <Variable name="height">100</Variable>
+        <Variable name="alt">Schau mal unter folgenden Links nach:</Variable></Property>
+
+      <Property name="panik">
+        <Variable name="src">/selfaktuell/forum/images/10.gif</Variable>
+        <Variable name="width">224</Variable>
+        <Variable name="height">119</Variable>
+        <Variable name="alt">??!%${</Variable></Property>
+
+    </Property>
+  </Property>
+
+</Config>
+
+<!-- Ende -->
\ No newline at end of file
diff --git a/selfforum-cgi/user/config/fo_admin_default.dtd b/selfforum-cgi/user/config/fo_admin_default.dtd
new file mode 100644 (file)
index 0000000..b066b07
--- /dev/null
@@ -0,0 +1,296 @@
+<!--
+Document Type Declaration fuer das Administrieren des SELFHTML-Forums
+Autor: Thomas J. Sebestyen        thomasj.sebestyen@meta-text.net
+
+Version 1.00        27.12.2000
+
+Last modified: 30.12.2000
+-->
+
+<!ENTITY % boolean "(0 | 1)">
+<!-- Parameterentity fuer ja (1) oder nein (0) Fragen -->
+
+
+
+
+
+<!ELEMENT                Forum    (ForumView, Serverance, Messaging, InstantJob, UserManagement)   >
+<!-- *****************************************************************************************************
+      'Forum' ist das rootelement und beinhaltet alle anderen Elemente
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT      ForumView   (ThreadView, MessageView, Flags, Quoting)   >
+<!-- *****************************************************************************************************
+      'ForumView' beinhaltet die Elemente, die das Ausssehen des Forums bestimmen
+***************************************************************************************************** -->
+
+
+
+
+
+<!ELEMENT      Serverance  ((AfterByte | AfterThread | AfterMessage | AfterHours | AfterLastPosting)+, Archiving) >
+<!-- *****************************************************************************************************
+      'Serverance' enthaelt die Elemente, die das automatischens Abtrennen und die Archivierung des Forums
+       bestimmen;  fuer das Abtrennen duerfen mehrere Optionen gelichzeitig angegeben werden.
+***************************************************************************************************** -->
+<!ATTLIST      Serverance
+               executeArchiving  %boolean;   "1"
+               executeServerance (sequential | asymmetrical | instant)   #REQUIRED
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'executeArchiving' bestimmt ob eine Archivierung durchgefuehrt
+         wird (1, default Einstellung) oder nicht (0).
+      Das Attribut 'executeServerance' bestimmt das Abtrennverhalten f&uuml;r das Forum:
+         sequential =
+         asymmetrical =
+         instant = ist nur fuer die manuelle durchfuehrung einer Abtrennung im Forum
+***************************************************************************************************** -->
+
+
+<!ELEMENT      Archiving   (General | UserVotings ) >
+<!-- *****************************************************************************************************
+      'Archiving' enthaelt die Elemente, die die Archivierungsart des Forums bestimmen.
+***************************************************************************************************** -->
+
+<!ELEMENT   General  EMPTY >
+<!-- *****************************************************************************************************
+      'General' bestimmt, dass alles archiviert wird.
+***************************************************************************************************** -->
+
+<!ELEMENT   UserVotings EMPTY >
+<!-- *****************************************************************************************************
+      'UserVotings' bestimmt, dass nur die ausgewaehlten Nachrichten archiviert werden.
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT      AfterByte         (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'AfterByte' bestimmt ab wieviel Byte Groesse der Hauptdatei das Forum archiviert wird.
+***************************************************************************************************** -->
+
+<!ELEMENT      AfterThread       (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'AfterThread' bestimmt die Anzahl der Threads in der Hauptdatei nach der das Forum archiviert wird.
+***************************************************************************************************** -->
+
+<!ELEMENT      AfterMessage      (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'AfterMessages' bestimmt die Anzahl der Nachrichten in der Hauptdatei nach der das Forum archiviert wird.
+***************************************************************************************************** -->
+
+<!ELEMENT      AfterHours        (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'AfterHours' bestimmt die Anzahl der Stunden der aeltesten Postings in der Hauptdatei
+         nach der das Forum archiviert wird.
+***************************************************************************************************** -->
+
+<!ELEMENT      AfterLastPosting  (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'AfterLastPosting' bestimmt, dass bei der Archivierung alle Threads beruecksichtigt werden, deren
+         juengste Message laenger als die hier eingestelte Zeit in der Forumshauptdatei verweilt.
+***************************************************************************************************** -->
+
+
+
+
+
+<!ELEMENT      Messaging   (CallByUser)   >
+<!-- *****************************************************************************************************
+      'Messaging' beinhaltet die Optionen fuer die Benachrichtinungsschema im Forum
+***************************************************************************************************** -->
+<!ATTLIST      Messaging
+               callUserAnswer    %boolean;   "0"
+               callAdminThread   %boolean;   "0"
+               callAdminNA       %boolean;   "1"
+               callAdminHQ       %boolean;   "0"
+               callAdminVoting   %boolean;   "0"
+               callAdminArchving %boolean;   "1"
+               callByUser        %boolean;   "0"
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'callUserAnswer' bestimmt ob der User bei einer Antwort auf seine Frage
+         per Mail benachrichtigt wird (1) oder nicht (0, default Einstellung).
+      Das Attribut 'callAdminThread' bestimmt ob die Forumsleitung beim Eroeffen eines neuen
+         Threades per Mail benachrichtigt wird (1) oder nicht (0, default Einstellung).
+      Das Attribut 'callAdminNA' bestimmt ob die Forumsleitung beim Setzen des Flags NA
+         per Mail benachrichtigt wird (1, default Einstellung) oder nicht (0).
+      Das Attribut 'callAdminHQ' bestimmt ob die Forumsleitung beim Setzen des Flags HQ
+         per Mail benachrichtigt wird (1) oder nicht (0, default Einstellung).
+      Das Attribut 'callAdminVoting' bestimmt ob die Forumsleitung bei Uservoting fur eine Nachricht
+         per Mail benachrichtigt wird (1) oder nicht (0, default Einstellung).
+      Das Attribut 'callAdminArchiving' bestimmt ob die Forumsleitung bei automatischer Archivierung
+         per Mail benachrichtigt wird (1, default Einstellung) oder nicht (0).
+      Das Attribut 'callByUser' bestimmt ob die Forumsleitung bei Messages von in der 'CallByUser'
+         Liste gefuehrten User, per Mail benachrichtigt wird (1) oder nicht (0, default Einstellung).
+***************************************************************************************************** -->
+
+<!ELEMENT      CallByUser  (Name | Email | IpAddress)*   >
+<!-- *****************************************************************************************************
+      'CallAdminUser' beinhaltet die Liste der User-Elemente bei deren Auftauchen
+       in Messages die Forumsleitung per Mail benachrichtig wird.
+***************************************************************************************************** -->
+
+<!ELEMENT                Name                        (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'Name' enthaelt den Namen eines Messageautors
+***************************************************************************************************** -->
+
+<!ELEMENT                Email                        (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'Email' enthaelt die E-Mail-Adresse eines Messageautors
+***************************************************************************************************** -->
+
+<!ELEMENT                IpAddress   (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'IpAddress        ' enthaelt die IP-Adresse eines Messageautors
+***************************************************************************************************** -->
+
+
+
+
+<!ELEMENT      InstantJob  (Serverance | ForumClose) >
+<!-- *****************************************************************************************************
+      'InstantJob' beinhaltet die zu ausfuehrende Sofortmassnahmen fuer das Forum
+***************************************************************************************************** -->
+<!--  'Serverance' ermoeglicht es nach dem bereist bestimmten Kriterien eine manuelle Archivierung und
+        ein manuelles Abtrennen des Forums durchzufuehren -->
+<!ATTLIST      InstantJob
+               executeJob  %boolean;   "0"
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'executeJob' bestimmt ob eine der Sofortmassnahmen durchgefuehrt
+         wird (1) oder nicht (0, default Einstellung).
+***************************************************************************************************** -->
+
+
+<!ELEMENT      ForumClose  (FileUrl)  >
+<!-- *****************************************************************************************************
+      'ForumClose' enthaelt die Optionen die das Schliessen und Wiedereroeffnen das Forums regeln.
+***************************************************************************************************** -->
+<!ATTLIST      ForumClose
+               reason   (maintenance | annoyance) #REQUIRED
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'reason' gibt den Grund der Schliessung an.
+         maintenance = Wartung, annoyance = Aergernis
+***************************************************************************************************** -->
+
+<!ELEMENT      FileUrl  (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'FileUrl' enthaelt den Pfad zu einer Datei die waehrend der Schliessung angezeigt wird.
+***************************************************************************************************** -->
+
+
+
+
+<!ELEMENT      ThreadView  (ShowThread) >
+<!-- *****************************************************************************************************
+      'ThreadView' beinhaltet die Optionen, die das Ausssehen der Threades bestimmen
+***************************************************************************************************** -->
+<!ATTLIST      ThreadView
+               threadOpen     %boolean;   "0"
+               countMessages  %boolean;   "1"
+               sortThreads    %boolean;   "0"
+               sortMessages   %boolean;   "0"
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'threadsOpen' bestimmt ob der Threadbaum
+         aufgeklappt(1) oder nicht (0, default Einstellung).
+      Das Attribut 'countMessages' bestimmt ob die Zahl der Nachrichten im Thread
+         ausgegeben werden soll (1, default Einstellung) oder nicht (0).
+      Das Attribut 'sortThreads' bestimmt ob die Threads in der Forumshauptdatei aufsteigend praesentiert
+         werden sollen, also aelteste zuerst (1) oder juengste zuerst (0, default Einstellung).
+      Das Attribut 'sortMessages' bestimmt ob die Nachrichten in der Forumshauptdatei aufsteigend praesentiert
+         werden sollen, also aelteste zuerst (1) oder juengste zuerst (0, default Einstellung).
+***************************************************************************************************** -->
+
+<!ELEMENT      ShowThread  (ShowAll | ShowNone | ShowNumber)>
+<!-- *****************************************************************************************************
+      'ShowThread' bestimmt ob in jeden Message der komplette Thread angezeigt werden
+         soll, oder nicht, oder nur eine betimmnte Anzahl von Nahrichten angezeigt werden soll.
+***************************************************************************************************** -->
+
+<!ELEMENT      ShowAll   EMPTY >
+<!-- *****************************************************************************************************
+      'ShowAll' bestimmt, dass in jeden Message der komplette Thread (alle anderen Messages
+       angezeigt) werden soll.
+***************************************************************************************************** -->
+
+<!ELEMENT      ShowNone   EMPTY >
+<!-- *****************************************************************************************************
+      'ShowNone' bestimmt, dass in den Messages der Thread nicht (keine andere Mesages)
+       angezeigt werden soll.
+***************************************************************************************************** -->
+
+<!ELEMENT      ShowNumber  (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'ShowNumber' gibt die Anzahl der Messages an der vom Thread in einem Message angezeigt werden soll.
+***************************************************************************************************** -->
+
+
+
+
+<!ELEMENT      MessageView EMPTY >
+<!-- *****************************************************************************************************
+      'MessageView' beinhaltet die Optionen, die beim Posten einer Message ausgefuhrt werden
+***************************************************************************************************** -->
+<!ATTLIST      MessageView
+               previewON   %boolean; "1"
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'previewON' bestimmt ob vor dem Speichern einer neue Message zunaechst in einer
+         Vorschau angezeigt werden soll (1, default Einstellung) oder nicht (0).
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT      Flags EMPTY  >
+<!-- *****************************************************************************************************
+      'Flags' beinhaltet die Optionen, die die Grafiken vor einer Nachricht bestimmen
+***************************************************************************************************** -->
+<!ATTLIST      Flags
+               showNA   %boolean; "0"
+               showHQ   %boolean; "1"
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'showNA' bestimmt ob die NA-Grafik angezeigt werden soll (1)
+         oder nicht (0, default Einstellung).
+      Das Attribut 'showHQ' bestimmt ob die HQ-Grafik angezeigt werden soll (1, default Einstellung)
+         oder nicht (0).
+***************************************************************************************************** -->
+
+<!ELEMENT      Quoting  (Chars?) >
+<!-- *****************************************************************************************************
+      'Quoting' beinhaltet die Optionen, die das Kennzeihen von Zitaten in Nachrichten bestimmen.
+***************************************************************************************************** -->
+<!ATTLIST      Quoting
+               quotingON   %boolean; "1"
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'quotingON' bestimmt ob Zitate in den Nachrichten gekennzeichnet werden
+      sollten (1, default Einstellung) oder nicht (0).
+***************************************************************************************************** -->
+
+<!ELEMENT      Chars (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'Chars'  enthaelt das/die Zeichen mit den(en) Zitate in den Nachrichten gekennzeichnet werden
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT      UserManagement (DeleteUser)>
+<!-- *****************************************************************************************************
+      'UserManagement'  enthaelt Optionen die die Benutzerverwaltung betreffen
+***************************************************************************************************** -->
+
+<!ELEMENT      DeleteUser     (AfterDays) >
+<!-- *****************************************************************************************************
+      'DeleteUser' enthaelt Optionen die das Loeschen von Userprofiles bestimmen.
+***************************************************************************************************** -->
+<!ELEMENT      AfterDays     (#PCDATA)   >
+<!-- *****************************************************************************************************
+      'AfterDays' bestimmt die Anzahl der Tage nach dem ein nicht benutzer Userprofile geloescht wird.
+***************************************************************************************************** -->
diff --git a/selfforum-cgi/user/config/fo_admin_default.xml b/selfforum-cgi/user/config/fo_admin_default.xml
new file mode 100644 (file)
index 0000000..bbdfa57
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!DOCTYPE Forum SYSTEM "fo_admin_default.dtd">
+<Forum>
+  <ForumView>
+         <ThreadView threadOpen="0" countMessages="1" sortThreads="0" sortMessages="0">
+                <ShowThread>
+                  <ShowNumber>10</ShowNumber>
+                </ShowThread>
+         </ThreadView>
+         <MessageView previewON="1" />
+         <Flags showNA="0" showHQ="1" />
+         <Quoting quotingON="1">
+                <Chars>&#187;&#187; </Chars>
+         </Quoting>
+  </ForumView>
+  <Severance executeArchiving="1" executeSeverance="sequential">
+         <AfterByte>400</AfterByte>
+         <AfterMessage>100</AfterMessage>
+         <AfterThread>70</AfterThread>
+         <Archiving><UserVotings/>
+         </Archiving>
+  </Severance>
+  <Messaging callUserAnswer="0" callAdminThread="0" callAdminNA="1" callAdminHQ="0" callAdminVoting="0" callAdminArchiving="1" callByUser="0">
+         <CallByUser>
+                <Email>a9105535@unet.univie.ac.at</Email>
+                <Email>selfhtml@teamone.de</Email>
+                <Name>Wowbagger</Name>
+                <IpAddress>123.456.789</IpAddress>
+         </CallByUser>
+  </Messaging>
+  <InstantJob executeJob="0">
+         <Severance executeArchiving="0" executeSeverance="instant">
+                <AfterByte>300</AfterByte>
+                <Archiving>
+                           <General />
+                </Archiving>
+         </Severance>
+  </InstantJob>
+  <UserManagement>
+          <DeleteUser>
+                <AfterDays>45</AfterDays>
+        </DeleteUser>
+  </UserManagement>
+</Forum>
\ No newline at end of file
diff --git a/selfforum-cgi/user/config/fo_admin_default.xml.lock b/selfforum-cgi/user/config/fo_admin_default.xml.lock
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/selfforum-cgi/user/config/fo_admin_default.xml.lock.ref b/selfforum-cgi/user/config/fo_admin_default.xml.lock.ref
new file mode 100644 (file)
index 0000000..c227083
--- /dev/null
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/selfforum-cgi/user/config/fo_admin_default.xml.lock.ref.lock b/selfforum-cgi/user/config/fo_admin_default.xml.lock.ref.lock
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/selfforum-cgi/user/config/fo_admin_default.xml.master.lock b/selfforum-cgi/user/config/fo_admin_default.xml.master.lock
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/selfforum-cgi/user/config/fo_posting.xml b/selfforum-cgi/user/config/fo_posting.xml
new file mode 100644 (file)
index 0000000..0616273
--- /dev/null
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<Config>
+  <Property name="show">
+    <Property name="Posting">
+      <Variable name="templateFile">config/answer.tmp.xml</Variable>
+
+      <Property name="assign">
+        <Variable name="docNew">DOC_OPENING</Variable>
+        <Variable name="docThx">DOC_THANKYOU</Variable>
+
+        <Variable name="docError">DOC_OPENING</Variable>
+        <Variable name="docFatal">DOC_FATAL</Variable>
+        <Variable name="errorMessage">_ERR_MESS</Variable>
+        <Variable name="charNum">_NUM</Variable>
+        <Variable name="wrongPar">_MANIPULATED</Variable>
+        <Variable name="wrongCode">_ENCODING</Variable>
+        <Variable name="occupied">_OCCUPIED</Variable>
+        <Variable name="noReply">_NOREPLY</Variable>
+        <Variable name="dupe">_DUPE</Variable>
+        <Variable name="unknownError">_UNKNOWN</Variable>
+
+        <Variable name="cssFile">_CSS_FILE</Variable>
+
+        <Variable name="option">OPTION</Variable>
+        <Variable name="optval">_OPTVAL</Variable>
+        <Variable name="optsel">_SELECTED</Variable>
+
+        <Variable name="message">_MESSAGE</Variable>
+
+        <Variable name="startCite">CITE_START</Variable>
+        <Variable name="endCite">CITE_END</Variable>
+      </Property>
+
+      <Property name="thanx">
+        <Variable name="author">_NAME</Variable>
+        <Variable name="email">_MAIL</Variable>
+        <Variable name="time">_TIME</Variable>
+        <Variable name="body">_BODY</Variable>
+        <Variable name="category">_CATEGORY</Variable>
+        <Variable name="subject">_TITLE</Variable>
+        <Variable name="home">_HOME</Variable>
+        <Variable name="image">_IMAGE</Variable>
+      </Property>
+
+      <Property name="form">
+        <Property name="action">
+          <Property name="post">
+            <Variable name="url">/cgi-local/user/fo_posting.pl</Variable>
+            <Variable name="assign">_FORM_ACTION</Variable>
+          </Property>
+        </Property>
+
+        <Property name="must">
+          <List name="new">
+            <ListItem>uniqueID</ListItem>
+            <ListItem>quoteChar</ListItem>
+            <ListItem>posterName</ListItem>
+            <ListItem>posterEmail</ListItem>
+            <ListItem>posterCategory</ListItem>
+            <ListItem>posterSubject</ListItem>
+            <ListItem>posterBody</ListItem>
+          </List>
+
+          <List name="reply">
+            <ListItem>followUp</ListItem>
+            <ListItem>uniqueID</ListItem>
+            <ListItem>quoteChar</ListItem>
+            <ListItem>posterName</ListItem>
+            <ListItem>posterEmail</ListItem>
+            <ListItem>posterBody</ListItem>
+          </List>
+        </Property>
+
+        <Property name="data">
+          <Property name="followUp">
+            <Property name="assign">
+              <Variable name="name">_FORM_FUP_NAME</Variable>
+              <Variable name="value">_FORM_FUP_VALUE</Variable>
+              <Variable name="tooLong">_MANIPULATED</Variable>
+            </Property>
+
+            <Variable name="name">fup</Variable>
+            <Variable name="maxlength">20</Variable>
+            <Variable name="errorType">fatal</Variable>
+          </Property>
+
+          <Property name="userID">
+            <Property name="assign">
+              <Variable name="name">_FORM_UID_NAME</Variable>
+              <Variable name="value">_FORM_UID_VALUE</Variable>
+              <Variable name="tooLong">_MANIPULATED</Variable>
+            </Property>
+
+            <Variable name="name">userid</Variable>
+            <Variable name="maxlength">40</Variable>
+            <Variable name="errorType">fatal</Variable>
+          </Property>
+
+          <Property name="uniqueID">
+            <Property name="assign">
+              <Variable name="name">_FORM_UNID_NAME</Variable>
+              <Variable name="value">_FORM_UNID_VALUE</Variable>
+              <Variable name="tooLong">_MANIPULATED</Variable>
+            </Property>
+
+            <Variable name="name">unid</Variable>
+            <Variable name="maxlength">40</Variable>
+            <Variable name="errorType">fatal</Variable>
+          </Property>
+
+          <Property name="quoteChar">
+            <Property name="assign">
+              <Variable name="name">_FORM_QCHAR_NAME</Variable>
+              <Variable name="value">_FORM_QCHAR_VALUE</Variable>
+              <Variable name="tooLong">_MANIPULATED</Variable>
+            </Property>
+
+            <Variable name="name">qchar</Variable>
+            <Variable name="maxlength">20</Variable>
+            <Variable name="errorType">fatal</Variable>
+          </Property>
+
+          <Property name="posterName">
+            <Property name="assign">
+              <Variable name="name">_FORM_NAME_NAME</Variable>
+              <Variable name="value">_FORM_NAME_VALUE</Variable>
+              <Variable name="tooLong">_NAME_TOO_LONG</Variable>
+              <Variable name="tooShort">_NAME_TOO_SHORT</Variable>
+            </Property>
+
+            <Variable name="name">name</Variable>
+            <Variable name="maxlength">60</Variable>
+            <Variable name="minlength">2</Variable>
+            <Variable name="errorType">repeat</Variable>
+          </Property>
+
+          <Property name="posterEmail">
+            <Property name="assign">
+              <Variable name="name">_FORM_MAIL_NAME</Variable>
+              <Variable name="value">_FORM_MAIL_VALUE</Variable>
+              <Variable name="tooLong">_MAIL_TOO_LONG</Variable>
+              <Variable name="tooShort">_MAIL_TOO_SHORT</Variable>
+              <Variable name="wrong">_MAIL_WRONG</Variable>
+            </Property>
+
+            <Variable name="name">email</Variable>
+            <Variable name="maxlength">60</Variable>
+            <Variable name="minlength">7</Variable>
+            <Variable name="type">email</Variable>
+            <Variable name="errorType">repeat</Variable>
+          </Property>
+
+          <Property name="posterCategory">
+            <Property name="assign">
+              <Variable name="name">_FORM_CAT_NAME</Variable>
+              <Variable name="value">_CATLIST</Variable>
+              <Variable name="tooLong">_CAT_WRONG</Variable>
+              <Variable name="tooShort">_CAT_WRONG</Variable>
+              <Variable name="notSelected">_CAT_WRONG</Variable>
+            </Property>
+
+            <Variable name="name">category</Variable>
+            <Variable name="maxlength">18</Variable>
+            <Variable name="minlength">3</Variable>
+            <Variable name="errorType">repeat</Variable>
+            <List name="values">
+              <ListItem>ASP</ListItem>
+              <ListItem>BROWSER</ListItem>
+              <ListItem>CGI</ListItem>
+              <ListItem>CSS</ListItem>
+              <ListItem>DATENBANK</ListItem>
+              <ListItem>DESIGN</ListItem>
+              <ListItem>DHTML</ListItem>
+              <ListItem>E_MAIL</ListItem>
+              <ListItem>FTP</ListItem>
+              <ListItem>GRAFIK</ListItem>
+              <ListItem>HTML</ListItem>
+              <ListItem>HTTP</ListItem>
+              <ListItem>INTERNET-ANBINDUNG</ListItem>
+              <ListItem>JAVA</ListItem>
+              <ListItem>JAVASCRIPT</ListItem>
+              <ListItem>MEINUNG</ListItem>
+              <ListItem>MENSCHELEI</ListItem>
+              <ListItem>PERL</ListItem>
+              <ListItem>PHP</ListItem>
+              <ListItem>PROGRAMMIERTECHNIK</ListItem>
+              <ListItem>PROJEKTVERWALTUNG</ListItem>
+              <ListItem>PROVIDER</ListItem>
+              <ListItem>RECHT</ListItem>
+              <ListItem>SERVER</ListItem>
+              <ListItem>SOFTWARE</ListItem>
+              <ListItem>VBSCRIPT</ListItem>
+              <ListItem>XML</ListItem>
+              <ListItem>XML-DERIVAT</ListItem>
+              <ListItem>XSL</ListItem>
+              <ListItem>ZUR INFO</ListItem>
+              <ListItem>ZU DIESEM FORUM</ListItem>
+            </List>
+          </Property>
+
+          <Property name="posterSubject">
+            <Property name="assign">
+              <Variable name="name">_FORM_SUBJECT_NAME</Variable>
+              <Variable name="value">_FORM_SUBJECT_VALUE</Variable>
+              <Variable name="tooLong">_SUB_TOO_LONG</Variable>
+              <Variable name="tooShort">_SUB_TOO_SHORT</Variable>
+            </Property>
+            <Variable name="name">subject</Variable>
+            <Variable name="maxlength">64</Variable>
+            <Variable name="minlength">4</Variable>
+            <Variable name="errorType">repeat</Variable>
+          </Property>
+
+          <Property name="posterBody">
+            <Property name="assign">
+              <Variable name="name">_FORM_BODY_NAME</Variable>
+              <Variable name="value">_FORM_BODY_VALUE</Variable>
+              <Variable name="tooLong">_BODY_TOO_LONG</Variable>
+              <Variable name="tooShort">_BODY_TOO_SHORT</Variable>
+            </Property>
+            <Variable name="name">body</Variable>
+            <Variable name="maxlength">12288</Variable>
+            <Variable name="minlength">10</Variable>
+            <Variable name="errorType">repeat</Variable>
+          </Property>
+
+          <Property name="posterSignature">
+            <Variable name="assignValue">_FORM_SIGN_VALUE</Variable>
+          </Property>
+
+          <Property name="posterURL">
+            <Property name="assign">
+              <Variable name="name">_FORM_URL_NAME</Variable>
+              <Variable name="value">_FORM_URL_VALUE</Variable>
+              <Variable name="tooLong">_URL_TOO_LONG</Variable>
+            </Property>
+            <Variable name="name">url</Variable>
+            <Variable name="maxlength">1024</Variable>
+            <Variable name="errorType">repeat</Variable>
+          </Property>
+
+          <Property name="posterImage">
+            <Property name="assign">
+              <Variable name="name">_FORM_IMG_NAME</Variable>
+              <Variable name="value">_FORM_IMG_VALUE</Variable>
+              <Variable name="tooLong">_IMG_TOO_LONG</Variable>
+            </Property>
+            <Variable name="name">image</Variable>
+            <Variable name="maxlength">1024</Variable>
+            <Variable name="errorType">repeat</Variable>
+          </Property>
+
+        </Property>
+      </Property>
+    </Property>
+  </Property>
+</Config>
+
+<!-- Ende -->
\ No newline at end of file
diff --git a/selfforum-cgi/user/config/fo_view.xml b/selfforum-cgi/user/config/fo_view.xml
new file mode 100644 (file)
index 0000000..c5995c7
--- /dev/null
@@ -0,0 +1,182 @@
+<?xml version="1.0"?>
+
+<Config>
+
+  <Property name="show">
+    <Property name="assign">
+
+      <Property name="cgi">
+        <Variable name="user">i</Variable>
+        <Variable name="thread">t</Variable>
+        <Variable name="posting">m</Variable>
+        <Variable name="command">c</Variable>
+      </Property>
+
+      <Property name="thread">
+        <Variable name="main">_THREAD</Variable>
+        <Variable name="start">TREE_START</Variable>
+        <Variable name="line">TREE_LINE</Variable>
+        <Variable name="closed">TREE_CLOSED</Variable>
+        <Variable name="startNC">TREE_START_NC</Variable>
+        <Variable name="lineNC">TREE_LINE_NC</Variable>
+        <Variable name="closedNC">TREE_CLOSED_NC</Variable>
+        <Variable name="link">_LINK</Variable>
+        <Variable name="name">_NAME</Variable>
+        <Variable name="command">_COMMAND</Variable>
+        <Variable name="subject">_TITLE</Variable>
+        <Variable name="cat">_CATEGORY</Variable>
+        <Variable name="time">_TIME</Variable>
+      </Property>
+    </Property>
+
+    <Property name="Forum">
+
+      <Variable name="templateFile">config/forum.tmp.xml</Variable>
+
+      <Property name="assign">
+        <Variable name="mainDocStart">DOC_FORUM_START</Variable>
+        <Variable name="mainDocEnd">DOC_FORUM_END</Variable>
+        <Variable name="loadingTime">_LOAD_TIME</Variable>
+        <Variable name="cssFile">_CSS_FILE</Variable>
+      </Property>
+
+    </Property>
+
+    <Property name="Posting">
+      <Variable name="templateFile">config/posting.tmp.xml</Variable>
+
+      <Property name="assign">
+        <Variable name="mainDoc">DOC_POSTING</Variable>
+        <Variable name="cssFile">_CSS_FILE</Variable>
+        <Variable name="message">_MESSAGE</Variable>
+        <Variable name="name">_BEF_NAME</Variable>
+        <Variable name="email">_BEF_MAIL</Variable>
+        <Variable name="time">_BEF_TIME</Variable>
+        <Variable name="home">_BEF_HOME</Variable>
+        <Variable name="image">_BEF_IMAGE</Variable>
+        <Variable name="messageTitle">_BEF_TITLE</Variable>
+        <Variable name="parentCat">_REF_CATEGORY</Variable>
+        <Variable name="messageCat">_BEF_CATEGORY</Variable>
+        <Variable name="parentTitle">_REF_TITLE</Variable>
+        <Variable name="parentName">_REF_NAME</Variable>
+        <Variable name="parentTime">_REF_TIME</Variable>
+        <Variable name="parentLink">_REF_LINK</Variable>
+        <Variable name="startCite">CITE_START</Variable>
+        <Variable name="endCite">CITE_END</Variable>
+      </Property>
+
+      <Property name="form">
+        <Property name="action">
+          <Property name="post">
+            <Variable name="url">/cgi-local/user/fo_posting.pl</Variable>
+            <Variable name="assign">_FORM_ACTION</Variable>
+          </Property>
+
+          <Property name="vote">
+            <Variable name="url">/cgi-local/user/fo_voting.pl</Variable>
+            <Variable name="assign">_VOTE_ACTION</Variable>
+          </Property>
+        </Property>
+
+        <Property name="data">
+          <Property name="followUp">
+            <Property name="assign">
+              <Variable name="name">_FORM_FUP_NAME</Variable>
+              <Variable name="value">_FORM_FUP_VALUE</Variable>
+            </Property>
+
+            <Variable name="name">fup</Variable>
+            <Variable name="maxlength">20</Variable>
+          </Property>
+
+          <Property name="userID">
+            <Property name="assign">
+              <Variable name="name">_FORM_UID_NAME</Variable>
+              <Variable name="value">_FORM_UID_VALUE</Variable>
+            </Property>
+
+            <Variable name="name">userid</Variable>
+            <Variable name="maxlength">25</Variable>
+          </Property>
+
+          <Property name="uniqueID">
+            <Property name="assign">
+              <Variable name="name">_FORM_UNID_NAME</Variable>
+              <Variable name="value">_FORM_UNID_VALUE</Variable>
+            </Property>
+
+            <Variable name="name">unid</Variable>
+            <Variable name="maxlength">25</Variable>
+          </Property>
+
+          <Property name="quoteChar">
+            <Property name="assign">
+              <Variable name="name">_FORM_QCHAR_NAME</Variable>
+              <Variable name="value">_FORM_QCHAR_VALUE</Variable>
+            </Property>
+
+            <Variable name="name">qchar</Variable>
+            <Variable name="maxlength">5</Variable>
+          </Property>
+
+          <Property name="posterName">
+            <Property name="assign">
+              <Variable name="name">_FORM_NAME_NAME</Variable>
+              <Variable name="value">_FORM_NAME_VALUE</Variable>
+            </Property>
+
+            <Variable name="name">name</Variable>
+            <Variable name="maxlength">60</Variable>
+            <Variable name="minlength">2</Variable>
+          </Property>
+
+          <Property name="posterEmail">
+            <Property name="assign">
+              <Variable name="name">_FORM_MAIL_NAME</Variable>
+              <Variable name="value">_FORM_MAIL_VALUE</Variable>
+            </Property>
+
+            <Variable name="name">email</Variable>
+            <Variable name="maxlength">60</Variable>
+            <Variable name="minlength">7</Variable>
+          </Property>
+
+          <Property name="posterBody">
+            <Property name="assign">
+              <Variable name="name">_FORM_BODY_NAME</Variable>
+              <Variable name="value">_FORM_BODY_VALUE</Variable>
+            </Property>
+            <Variable name="name">body</Variable>
+            <Variable name="maxlength">12288</Variable>
+            <Variable name="minlength">10</Variable>
+          </Property>
+
+          <Property name="posterSignature">
+            <Variable name="assignValue">_FORM_SIGN_VALUE</Variable>
+          </Property>
+
+          <Property name="posterURL">
+            <Property name="assign">
+              <Variable name="name">_FORM_URL_NAME</Variable>
+              <Variable name="value">_FORM_URL_VALUE</Variable>
+            </Property>
+            <Variable name="name">url</Variable>
+            <Variable name="maxlength">1024</Variable>
+          </Property>
+
+          <Property name="posterImage">
+            <Property name="assign">
+              <Variable name="name">_FORM_IMG_NAME</Variable>
+              <Variable name="value">_FORM_IMG_VALUE</Variable>
+            </Property>
+            <Variable name="name">image</Variable>
+            <Variable name="maxlength">1024</Variable>
+          </Property>
+
+        </Property>
+      </Property>
+    </Property>
+  </Property>
+</Config>
+
+<!-- Ende -->
\ No newline at end of file
diff --git a/selfforum-cgi/user/config/forum.tmp.xml b/selfforum-cgi/user/config/forum.tmp.xml
new file mode 100644 (file)
index 0000000..89c7e56
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version="1.0"?>
+<Template metaon="{&amp;&amp;" metaoff="&amp;&amp;}">
+
+  <Scrap id="DOC_FORUM_START"><![CDATA[
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+       <meta name="description" content="SELFHTML Forum">
+       <meta name="keywords" content="SELFHTML, Forum">
+       <meta http-equiv="expires" content="0">
+       <meta http-equiv="cache-control" content="no-cache">
+       <meta name="robots" content="noindex">
+
+       <title>SELFHTML Forum</title>
+
+       <link rel="stylesheet" type="text/css" href="{&& _CSS_FILE &&}">
+
+       <script type="text/javascript"><!--
+       function Chat () { F1 = open("{&& URL_CHAT &&}","Fenster1","width=600,height=450"); }
+       function News () { F1 = open("{&& URL_NEWS &&}","Fenster2","width=520,height=400,scrollbars=yes,resizable=yes,status=yes"); }
+       function NewMessage () { alert("Der Verweis zum Erstellen einer neuen Nachricht\nbefindet sich am Ende dieser Seite.\n\nScrollen Sie langsam nach unten,\nlesen Sie die vorhandenen Nachrichten und\nsuchen Sie zuerst in SELFHTML,\nin der Forums-Auslese, in den Feature-Artikeln,\nim Archiv und im Link-Verzeichnis,\nbevor Sie einen neuen Thread beginnen."); }
+       //--></script>
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000" link="#AA5522" vlink="#772200" alink="#000000">
+<table cellpadding="4" cellspacing="0" border="0" width="100%">
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="top">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&}</td></tr>
+</table>
+<table cellpadding="4" cellspacing="0" border="0" width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc" width="110">{&& IMG_XWEB &&}</td>
+       <td bgcolor="#EEEEEE" class="doc" valign="bottom" width="100%"><h2>SELFHTML Forum</h2></td></tr>
+<tr><td bgcolor="#EEEEEE" class="doc" valign="top" align="center">
+               <table border="0" cellpadding="5" cellspacing="5" width="100%">
+               <tr><td bgcolor="#FFEEDD" align="center"><br>&nbsp;
+                               <a href="javascript:News()">{&& IMG_XVIEW &&}<br><b>SELFHTML<br>Newsticker</b></a><br>&nbsp;<br>
+                               <a href="javascript:Chat()">{&& IMG_SMILE &&}<br><b>Chat</b></a><br>&nbsp;<br>{&& LINK_UNRECHT &&}<br>&nbsp;</td></tr>
+               </table><br></td>
+       <td bgcolor="#FFFFFF" valign="top">
+               <p>{&& IMG_XGDOWN &&}&nbsp;<a href="#a1"><b>Aktuelle Nachrichten</b></a><br>
+                  {&& IMG_XGMESSAGE &&}&nbsp;<a href="javascript:NewMessage()"><b>Neue Nachricht</b></a><br></p>
+               <p><a name="zu_diesem_Forum" class="an">Dies ist ein Forum</a> als Erg&auml;nzung zu {&& IMG_X1 &&}&nbsp;{&& LINK_SELFHTML &&}. Von allen hier Teilnehmenden werden HTML-Grundkenntnisse erwartet. Es wird auch erwartet, da&szlig; bei Problemen erst einmal in SELFHTML oder anderen Hilfen nach einer L&ouml;sung gesucht wird. Ferner sollten folgende Ressourcen bekannt sein:<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_FAQ &&}<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_AUSLESE &&}<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_ARCHIV &&}<br>
+                  {&& IMG_X3 &&}&nbsp;{&& LINK_SUCHE &&}</p>
+               <p>Und im <a href="javascript:Chat()">{&& IMG_SMILE &&}&nbsp;<b>Chat</b></a> treffen sich fast den ganzen Tag &uuml;ber Gleichgesinnte und tauschen Infos und Hilfe aus!</p>{&& %IF _LOAD_TIME &&}
+               <p>Ladezeitpunkt: {&& _LOAD_TIME &&}</p>{&& %ENDIF &&}</td></tr>
+<tr><td colspan="2" bgcolor="#EEEEEE" class="doc"><a href="#bottom">{&& IMG_XGDOWN &&}</a>&#160;</td></tr>
+</table>
+<h2 class="Sh2"><a class="an" name="a1">Aktuelle Nachrichten</a></h2>
+<p><b>Mitmachen:</b> Um auf eine aktuelle Nachricht zu antworten, einfach diese &ouml;ffnen und lesen. Alle Nachrichten enthalten ein Formular zum Antworten.<br>
+   <b>Tip:</b> Nachrichten in neuem Fenster &ouml;ffnen (rechte Maustaste). Dann bleibt diese Indexdatei im Hintergrund ge&ouml;ffnet.</p>
+  ]]></Scrap>
+
+  <Scrap id="DOC_FORUM_END"><![CDATA[
+<h3>Alte Nachrichten</h3>
+<p>Alte Nachrichten finden Sie im {&& IMG_X1 &&}&nbsp;{&& LINK_ARCHIV2 &&}.</p>
+<h3>Neue Nachricht</h3>
+<p>{&& IMG_X3NEU &&}&nbsp;{&& LINK_NEU &&}</p>
+<p>Damit wird ein neuer Thread im Forum er&ouml;ffnet.</p>
+<table cellpadding="4" cellspacing="0" border="0" width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc"><a href="#top">{&& IMG_XGOUP &&}</a></td></tr>
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="bottom">{&& IMG_X2 &&}</a> {&& LINK_SELFAKTUELL &&} {&& IMG_X2 &&} {&& LINK_SELFLIVE &&}</td></tr>
+</table>
+<p>&copy; 2000 {&& IMG_XGMAIL &&}&nbsp;<a href="mailto:{&& MAIL_SELF &&}">{&& MAIL_SELF &&}</a></p>
+</body>
+</html>
+  ]]></Scrap>
+
+  <Scrap id="TREE_CLOSED"><![CDATA[
+<a href="{&& _COMMAND &&}">{&& IMG_XCLOSED &&}</a> (<b>{&& _CATEGORY &&}</b>) <a href="{&& _LINK &&}"><b>{&& _TITLE &&}</b></a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_CLOSED_NC"><![CDATA[
+<a href="{&& _COMMAND &&}">{&& IMG_XCLOSED &&}</a> <a href="{&& _LINK &&}"><b>{&& _TITLE &&}</b></a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_START"><![CDATA[
+{&& IMG_X3 &&} (<b>{&& _CATEGORY &&}</b>) <a href="{&& _LINK &&}"><b>{&& _TITLE &&}</b></a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_START_NC"><![CDATA[
+{&& IMG_X3 &&} <a href="{&& _LINK &&}"><b>{&& _TITLE &&}</b></a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_LINE"><![CDATA[
+{&& IMG_X3 &&} ({&& _CATEGORY &&}) <a href="{&& _LINK &&}">{&& _TITLE &&}</a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_LINE_NC"><![CDATA[
+{&& IMG_X3 &&} <a href="{&& _LINK &&}">{&& _TITLE &&}</a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+<!--
+       ***** ATOMICS *****
+       Grundelemente
+-->
+
+<!--
+       Links/URLs
+-->
+
+<Scrap id="_CSS_FILE"><![CDATA[ /selfaktuell/src/wselfhtm.css ]]></Scrap>
+
+<Scrap id="LINK_SELFHTML"><![CDATA[ <a href="/selfhtml/"><b>SELFHTML</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFAKTUELL"><![CDATA[ <a href="/selfaktuell/"><b>SELFHTML&nbsp;aktuell</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFLIVE"><![CDATA[ <a href="/selfaktuell/live/"><b>SELFHTML&nbsp;live!</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFFORUM"><![CDATA[ <a href="/selfaktuell/forum/"><b>SELFHTML&nbsp;Forum</b></a> ]]></Scrap>
+<Scrap id="LINK_UNRECHT"><![CDATA[ <a href="/selfaktuell/talk/rechtundlinks.htm"><b>Recht + Links</b></a> ]]></Scrap>
+<Scrap id="LINK_FAQ"><![CDATA[ <a href="forumsfaq.htm"><b>Forums-FAQ</b></a> ]]></Scrap>
+<Scrap id="LINK_AUSLESE"><![CDATA[ <a href="forumsauslese.htm"><b>Forums-Auslese</b></a> ]]></Scrap>
+<Scrap id="LINK_ARCHIV"><![CDATA[ <a href="forumsarchiv.htm"><b>Forumsarchiv</b></a> ]]></Scrap>
+<Scrap id="LINK_ARCHIV2"><![CDATA[ <a href="/selfhtml/sfarchiv/"><b>Forumsarchiv</b></a> ]]></Scrap>
+<Scrap id="LINK_SUCHE"><![CDATA[ <a href="/cgi-local/sfasuch.pl"><b>Forumsarchiv-Suche</b></a> ]]></Scrap>
+<Scrap id="LINK_NEU"><![CDATA[ <a href="neu.shtml" target="_blank"><b>Neue Nachricht verfassen</b></a> ]]></Scrap>
+
+<Scrap id="MAIL_SELF"><![CDATA[ selfhtml@teamone.de ]]></Scrap>
+
+<Scrap id="URL_NEWS"><![CDATA[ /selfaktuell/news.htm ]]></Scrap>
+<Scrap id="URL_CHAT"><![CDATA[ selfaktuell/live/chat.htm ]]></Scrap>
+
+<!--
+       Bilder
+-->
+
+<Scrap id="IMG_XGMAIL"><![CDATA[ <img src="/selfaktuell/src/xgmail.gif" width="15" height="10" border="0" alt="E-Mail"> ]]></Scrap>
+<Scrap id="IMG_XGOUP"><![CDATA[ <img src="/selfaktuell/src/xgoup.gif" width="14" height="10" border="0" alt="nach oben"> ]]></Scrap>
+<Scrap id="IMG_XGDOWN"><![CDATA[ <img src="/selfaktuell/src/xgdown.gif" width="14" height="10" border="0" alt="nach unten"> ]]></Scrap>
+<Scrap id="IMG_X1"><![CDATA[ <img src="/selfaktuell/src/x1.gif" width="15" height="13" border="0" alt="Ordner"> ]]></Scrap>
+<Scrap id="IMG_X2"><![CDATA[ <img src="/selfaktuell/src/x2.gif" width="16" height="13" border="0" alt="Teil von"> ]]></Scrap>
+<Scrap id="IMG_X3"><![CDATA[ <img src="../src/x3.gif" width="15" height="10" border="0" alt="Seite"> ]]></Scrap>
+<Scrap id="IMG_X3NEU"><![CDATA[ <img src="/selfaktuell/src/x3.gif" width="15" height="10" border="0" alt="neue Seite im eigenen Fenster"> ]]></Scrap>
+<Scrap id="IMG_X5"><![CDATA[ <img src="/selfaktuell/src/x5.gif" width="30" height="20" vspace="6" border="0" alt="Informationsseite"> ]]></Scrap>
+<Scrap id="IMG_XWEB"><![CDATA[ <img src="/selfaktuell/src/xweb.gif" width="106" height="109" border="0" alt="SELFHTML"> ]]></Scrap>
+<Scrap id="IMG_XVIEW"><![CDATA[ <img src="/selfaktuell/src/xview.gif" width="30" height="20" border="0" alt="News"> ]]></Scrap>
+<Scrap id="IMG_SMILE"><![CDATA[ <img src="/selfaktuell/src/smile2.gif" width="15" height="15" alt="Smile" border=0> ]]></Scrap>
+<Scrap id="IMG_XGMESSAGE"><![CDATA[ <img src="/selfaktuell/src/xmessage.gif" width="14" height="10" border="0" alt="weiter unten"> ]]></Scrap>
+<Scrap id="IMG_XCLOSED"><![CDATA[ <img src="/selfaktuell/src/x1.gif" width="15" height="13" border="0" alt="Thread aufklappen" title="Thread aufklappen"> ]]></Scrap>
+<Scrap id="IMG_XOPEN"><![CDATA[ <img src="/selfaktuell/src/x2.gif" width="16" height="13" border="0" alt="Thread zuklappen" title="Thread zuklappen"> ]]></Scrap>
+
+</Template>
diff --git a/selfforum-cgi/user/config/posting.tmp.xml b/selfforum-cgi/user/config/posting.tmp.xml
new file mode 100644 (file)
index 0000000..f37c575
--- /dev/null
@@ -0,0 +1,130 @@
+<?xml version="1.0"?>
+
+<Template metaon="{&amp;&amp;" metaoff="&amp;&amp;}">
+
+  <Scrap id="DOC_POSTING"><![CDATA[
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+       <meta http-equiv="expires" content="0">
+       <meta name="robots" content="noindex">
+
+       <title>SELFHTML Forum: {&& %IF _BEF_CATEGORY &&}({&& _BEF_CATEGORY &&}) {&& %ENDIF &&}{&& _BEF_TITLE &&}</title>
+
+       <link rel="stylesheet" type="text/css" href="{&& _CSS_FILE &&}">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000" link="#AA5522" vlink="#772200" alink="#000000">
+<table cellpadding="4" cellspacing="0" border="0" width="100%"><tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="top">{&& IMG_X2 &&}</a>&nbsp;{&& LINK_SELFAKTUELL &&}&nbsp;{&& IMG_X2 &&}&nbsp;{&& LINK_SELFLIVE &&}&nbsp;{&& IMG_X2 &&}&nbsp;{&& LINK_SELFFORUM &&}</td></tr></table><table cellpadding="4" cellspacing="0" border="0" width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc" width="110">{&& IMG_XWEB &&}</td>
+       <td bgcolor="#EEEEEE" class="doc" valign="bottom" width="100%"><h2>{&& _BEF_NAME &&}:<br>{&& %IF _BEF_CATEGORY &&}({&& _BEF_CATEGORY &&})&nbsp;{&& %ENDIF &&}{&& _BEF_TITLE &&}</h2></td></tr>
+<tr><td bgcolor="#EEEEEE" class="doc" valign="top" align="center">{&& IMG_X5 &&}</td>
+       <td bgcolor="#FFFFFF" valign="top">
+               <p>{&& IMG_XGDOWN &&}&nbsp;<a href="#a1"><b>Nachricht lesen</b></a><br>
+                  {&& IMG_XGDOWN &&}&nbsp;<a href="#a2"><b>Antworten</b></a></p></td></tr>
+<tr><td colspan="2" bgcolor="#EEEEEE" class="doc"><a href="#bottom">{&& IMG_XGDOWN &&}</a>&#160;</td></tr>
+</table>
+<h2 class="Sh2"><a class="an" name="a1">Nachricht lesen</a></h2>
+<p>{&& %IF _REF_LINK _REF_TITLE _REF_NAME &&}Urspr&uuml;ngliche Nachricht zum Thema: {&& IMG_X3 &&}&nbsp;{&& %IF _REF_CATEGORY &&}<b>({&& _REF_CATEGORY &&})</b>&nbsp;{&& %ENDIF &&}<a href="{&& _REF_LINK &&}"><b>{&& _REF_TITLE &&}</b></a> von <b>{&& _REF_NAME &&}</b>, {&& _REF_TIME &&}<br>
+   {&& %ENDIF &&}Die folgende Nachricht zum Thema stammt von: <b>{&& _BEF_NAME &&}</b>{&& %IF _BEF_MAIL &&}, {&& IMG_XGMAIL &&} <a href="mailto:{&& _BEF_MAIL &&}"><b>{&& _BEF_MAIL &&}</b></a>{&& %ENDIF &&}, {&& _BEF_TIME &&}{&& %IF _BEF_HOME &&}<br>
+   <a href="{&& _BEF_HOME &&}"><b>{&& _BEF_HOME &&}</b></a>{&& %ENDIF &&}</p>
+<p><tt>{&& _MESSAGE &&}</tt></p><br>&#160;{&& %IF _BEF_IMAGE &&}
+<p><img src="{&& _BEF_IMAGE &&}" border=0 alt=""></p>{&& %ENDIF &&}
+
+{&& UPNDOWN &&}
+
+<h2 class="Sh2"><a class="an" name="a2">Antworten</a></h2>{&& %IF _THREAD &&}
+<dl>{&& _THREAD &&}</dl>{&& %ENDIF &&}
+<h3>Eigene Antwort schreiben</h3>
+<p>Die Nachricht, auf die Sie antworten, ist im Feld des Nachrichtentextes noch mal komplett zitiert. Entfernen Sie bei langen Nachrichten bitte alle Passagen aus dem Zitat bis auf jene, auf die Sie selbst Bezug nehmen wollen.</p>
+<form method="post" action="{&& _FORM_ACTION &&}">
+<input type="hidden" name="{&& _FORM_FUP_NAME &&}" value="{&& _FORM_FUP_VALUE &&}">{&& %IF _FORM_UID_VALUE &&}
+<input type="hidden" name="{&& _FORM_UID_NAME &&}" value="{&& _FORM_UID_VALUE &&}">{&& %ENDIF &&}
+<input type="hidden" name="{&& _FORM_UNID_NAME &&}" value="{&& _FORM_UNID_VALUE &&}">
+<input type="hidden" name="{&& _FORM_QCHAR_NAME &&}" value="{&& _FORM_QCHAR_VALUE &&}">
+<table bgcolor="#EEEEEE" cellpadding="2" cellspacing="0" border="0">
+<tr><td align="right" valign="middle"><br><b>Name:</b></td>
+       <td valign="top"><br><input type="text" name="{&& _FORM_NAME_NAME &&}" value="{&& _FORM_NAME_VALUE &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt;"></td></tr>
+<tr><td align="right" valign="middle"><b>E-Mail:</b></td>
+       <td valign="top"><input type="text" name="{&& _FORM_MAIL_NAME &&}" value="{&& _FORM_MAIL_VALUE &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt"></td></tr>
+<tr><td valign="top" colspan=2>
+               <b>Nachrichtentext:</b><br>
+               <tt><textarea cols="76" rows="25" name="{&& _FORM_BODY_NAME &&}" style="width:580px; height:380px; font-family:Courier New,Courier; font-size:10pt; color:#0000C0">{&& _FORM_BODY_VALUE &&}{&& %IF _FORM_SIGN_VALUE &&}
+               --
+               {&& _FORM_SIGN_VALUE &&}{&& %ENDIF &&}</textarea></tt></td></tr>
+<tr><td align="right" valign="middle"><b>URL (optional):</b></td>
+       <td valign="top"><input type="text" name="{&& _FORM_URL_NAME &&}" value="{&& %IF _FORM_URL_VALUE &&}{&& _FORM_URL_VALUE &&}{&& %ELSE &&}http://{&& %ENDIF &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt"></td></tr>
+<tr><td align="right" valign="middle"><b>URL Grafik (optional):</b></td>
+       <td valign="top"><input type=text name="{&& _FORM_IMG_NAME &&}" value="{&& %IF _FORM_IMG_VALUE &&}{&& _FORM_IMG_VALUE &&}{&& %ELSE &&}http://{&& %ENDIF &&}" size="40" style="width:410px; font-family:Arial,Sans-serif; font-size:10pt"></td></tr>
+<tr><td valign="top" nowrap colspan="2"><input type="submit" value="Nachricht absenden"> <input type="reset" value="Eingaben verwerfen"></td></tr>
+</table>
+</form><br>
+<p>Bitte nur <b>einmal</b> auf <i>Nachricht absenden</i> klicken, dann abwarten!</p>
+<table cellpadding="4" cellspacing="0" border="0" width="100%">
+<tr><td bgcolor="#EEEEEE" class="doc"><a href="#top">{&& IMG_XGOUP &&}</a></td></tr>
+<tr><td bgcolor="#FFEEDD" class="nav"><a class="an" name="bottom">{&& IMG_X2 &&}</a>&nbsp;{&& LINK_SELFAKTUELL &&}&nbsp;{&& IMG_X2 &&}&nbsp;{&& LINK_SELFLIVE &&} {&& IMG_X2 &&}&nbsp;{&& LINK_SELFFORUM &&}</td></tr>
+</table>
+<p>&copy; 2000 {&& IMG_XGMAIL &&}&nbsp;<a href="mailto:{&& MAIL_SELF &&}">{&& MAIL_SELF &&}</a></p>
+</body>
+</html>
+  ]]></Scrap>
+
+
+<!--
+       ***** Schnipsel *****
+       aus Grundelementen zusammengesetzt
+-->
+  <Scrap id="TREE_START"><![CDATA[
+{&& IMG_X3 &&} (<b>{&& _CATEGORY &&}</b>) <a href="{&& _LINK &&}"><b>{&& _TITLE &&}</b></a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_START_NC"><![CDATA[
+{&& IMG_X3 &&} <a href="{&& _LINK &&}"><b>{&& _TITLE &&}</b></a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_LINE"><![CDATA[
+{&& IMG_X3 &&} ({&& _CATEGORY &&}) <a href="{&& _LINK &&}">{&& _TITLE &&}</a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="TREE_LINE_NC"><![CDATA[
+{&& IMG_X3 &&} <a href="{&& _LINK &&}">{&& _TITLE &&}</a> von <b>{&& _NAME &&}</b>, {&& _TIME &&}
+  ]]></Scrap>
+
+  <Scrap id="UPNDOWN"><![CDATA[
+<table bgcolor="#EEEEEE" class="doc" width="100%"><tr><td><a href="#top">{&& IMG_XGOUP &&}</a><a href="#bottom">{&& IMG_XGDOWN &&}</a>&#160;</td></tr></table>
+  ]]></Scrap>
+
+<!--
+       ***** ATOMICS *****
+       Grundelemente
+-->
+
+<Scrap id="CITE_START"><![CDATA[ <span style="color:#800000;"> ]]></Scrap>
+<Scrap id="CITE_END"><![CDATA[ </span> ]]></Scrap>
+
+<!--
+       Links/URLs
+-->
+
+<Scrap id="MAIL_SELF"><![CDATA[ selfhtml@teamone.de ]]></Scrap>
+
+<Scrap id="LINK_SELFAKTUELL"><![CDATA[ <a href="../"><b>SELFHTML&nbsp;aktuell</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFLIVE"><![CDATA[ <a href="../live/"><b>SELFHTML&nbsp;live!</b></a> ]]></Scrap>
+<Scrap id="LINK_SELFFORUM"><![CDATA[ <a href="./"><b>SELFHTML&nbsp;Forum</b></a> ]]></Scrap>
+
+<Scrap id="_CSS_FILE"><![CDATA[ ../src/wselfhtm.css ]]></Scrap>
+
+<!--
+       Bilder
+-->
+
+<Scrap id="IMG_XGMAIL"><![CDATA[ <img src="../src/xgmail.gif" width="15" height="10" border="0" alt="E-Mail"> ]]></Scrap>
+<Scrap id="IMG_XGOUP"><![CDATA[ <img src="../src/xgoup.gif" width="14" height="10" border="0" alt="nach oben"> ]]></Scrap>
+<Scrap id="IMG_XGDOWN"><![CDATA[ <img src="../src/xgdown.gif" width="14" height="10" border="0" alt="nach unten"> ]]></Scrap>
+<Scrap id="IMG_X2"><![CDATA[ <img src="../src/x2.gif" width="16" height="13" border="0" alt="Teil von"> ]]></Scrap>
+<Scrap id="IMG_X3"><![CDATA[ <img src="../src/x3.gif" width="15" height="10" border="0" alt="Seite"> ]]></Scrap>
+<Scrap id="IMG_X5"><![CDATA[ <img src="../src/x5.gif" width="30" height="20" vspace="6" border="0" alt="Informationsseite"> ]]></Scrap>
+<Scrap id="IMG_XWEB"><![CDATA[ <img src="../src/xweb.gif" width="106" height="109" border="0" alt="SELFHTML"> ]]></Scrap>
+
+</Template>
diff --git a/selfforum-cgi/user/fo_posting.pl b/selfforum-cgi/user/fo_posting.pl
new file mode 100644 (file)
index 0000000..fc8b182
--- /dev/null
@@ -0,0 +1,523 @@
+#!/usr/bin/perl
+
+# ====================================================
+# Autor: n.d.p. / 2001-01-23
+# lm   : n.d.p. / 2001-01-25
+# ====================================================
+# Funktion:
+#      Entgegennahme von Postings und
+#      Darstellung der "Neue Nachricht"-Seite
+# ====================================================
+
+use strict;
+use vars qw($Bin $Shared $Script %subhash $httpurl $flocked);
+
+BEGIN {
+  ($Bin)    = ($0 =~ /^(.*)\/.*$/)? $1 : '.';
+  $Shared   = "$Bin/../shared";
+  ($Script) = ($0 =~ /^.*\/(.*)$/)? $1 : $0;}
+
+use CGI::Carp qw(fatalsToBrowser);
+
+use lib "$Shared";
+use Conf;
+use Encode::Plain; $Encode::Plain::utf8 = 1;
+use Encode::Posting;
+use Id;
+use Lock qw(:ALL);
+use Mail;
+use Posting::_lib qw(get_all_threads get_message_node get_message_header hr_time);
+use Posting::Write;
+use Template;
+use Template::Posting;
+
+use CGI qw(param header);
+
+use XML::DOM;
+
+print header (-type => 'text/html');
+
+our $conf = read_script_conf ($Bin, $Shared, $Script);
+
+our $show_posting = $conf -> {show} -> {Posting};
+our $assign   = $show_posting -> {assign};
+our $formmust = $show_posting -> {form} -> {must};
+our $formdata = $show_posting -> {form} -> {data};
+our $formact  = $show_posting -> {form} -> {action};
+our $template = new Template "$Bin/".$show_posting -> {templateFile};
+our $pars = {};
+our ($failed, %dparam, $threads, $last_thread, $last_message, $ftid, $fmid, $flocked);
+
+sub forum_filename () {$conf -> {wwwRoot} . $conf -> {files} -> {forum};}
+sub message_path () {$conf -> {wwwRoot} . $conf -> {files} -> {messagePath};}
+
+################################
+
+# Formfelder ausfuellen (Namen)
+for (qw(posterBody uniqueID followUp quoteChar userID posterName posterEmail posterCategory posterSubject posterURL posterImage)) {
+  $pars -> {$formdata -> {$_} -> {assign} -> {name}} = plain($formdata -> {$_} -> {name});}
+
+my $checked = &check_param;
+
+unless (exists ($subhash {$checked})) {
+  &print_fatal ($assign -> {unknownError});}
+
+else {
+  unless ($checked eq 'newThread') {
+    $checked = &check_reply_dupe() || $checked;}
+
+  unless (exists ($subhash {$checked})) {
+    &print_fatal ($assign -> {unknownError});}
+  else {
+    &{$subhash {$checked}};}
+
+  if ($flocked) {
+    violent_unlock_file (forum_filename) unless (write_unlock_file (forum_filename));}}
+
+# ====================================================
+# end of main / Funktionen
+# ====================================================
+
+################################
+# sub check_reply_dupe
+#
+# Reply moeglich?
+# Doppelposting?
+################################
+
+sub check_reply_dupe () {
+  my $stat;
+
+  unless ($stat = write_lock_file (forum_filename)) {
+    if ($stat == 0) {
+      # ueberlastet oder so
+      violent_unlock_file (forum_filename);
+      return 'Occupied';}
+
+    else {
+      return 'masterLock';}}
+
+  else {
+    my ($i, %msg, %unids);
+
+    $flocked = 1;
+
+    ($threads, $last_thread, $last_message, my $unids) = get_all_threads (forum_filename, 1, 0);
+    ($ftid,$fmid) = split /;/,$dparam{$formdata -> {followUp} -> {name}},2;
+
+    # Thread existiert nicht
+    if (exists($dparam{$formdata -> {followUp} -> {name}})) {
+      return 'noReply' unless (exists($threads -> {$ftid}));
+
+      # nur nicht geloeschte Messages beachten
+      for ($i=0; $i < @{$threads -> {$ftid}}; $i++) {
+        if ($threads -> {$ftid} -> [$i] -> {deleted}) {
+          $+=$threads -> {$ftid} -> [$i] -> {answers};}
+
+        else {
+          $msg{$threads -> {$ftid} -> [$i] -> {mid}}=$i;}}
+
+      # Message existiert nicht
+      if (exists($dparam{$formdata -> {followUp} -> {name}})) {
+        return 'noReply' unless (exists($msg{$fmid}));}
+
+      %unids = map {$_ => 1} @{$threads -> {$ftid} -> [$msg{$fmid}] -> {unids}};}
+
+    else {
+      %unids = map {$_ => 1} @$unids;}
+
+    # jetzt endlich
+    return 'Dupe' if (exists ($unids{$dparam{$formdata -> {uniqueID} -> {name}}}));}
+
+  return;
+}
+
+################################
+# sub got_new
+#
+# Eroeffnungsposting speichern
+################################
+
+sub got_new () {
+
+  my $time = time;
+  my $pars = {author        => $dparam {$formdata -> {posterName} -> {name}},
+              email         => $dparam {$formdata -> {posterEmail} -> {name}},
+              category      => $dparam {$formdata -> {posterCategory} -> {name}},
+              subject       => $dparam {$formdata -> {posterSubject} -> {name}},
+              body          => $dparam {$formdata -> {posterBody} -> {name}},
+              homepage      => $dparam {$formdata -> {posterURL} -> {name}},
+              image         => $dparam {$formdata -> {posterImage} -> {name}},
+              time          => $time,
+              uniqueID      => $dparam {$formdata -> {uniqueID} -> {name}},
+              ip            => $ENV{REMOTE_ADDR},
+              forumFile     => forum_filename,
+              messagePath   => message_path,
+              lastThread    => $last_thread,
+              lastMessage   => $last_message,
+              parsedThreads => $threads,
+              dtd           => 'forum.dtd',
+              quoteChars    => toUTF8('»» '),
+              messages      => $conf -> {template} -> {messages}};
+
+  my ($stat, $xml, $mid) = write_posting ($pars);
+  violent_unlock_file (forum_filename) unless (write_unlock_file (forum_filename));
+  $flocked = undef;
+
+  if ($stat) {
+    print "Och noe...: $stat";}
+
+  else {
+    my $thx = $show_posting -> {thanx};
+
+    print ${$template -> scrap ($assign -> {docThx},
+                               {$thx -> {author}   => plain ($dparam {$formdata -> {posterName} -> {name}}),
+                                $thx -> {email}    => plain ($dparam {$formdata -> {posterEmail} -> {name}}),
+                                $thx -> {time}     => plain (hr_time($time)),
+                                $thx -> {body}     => message_as_HTML ($xml, $template,
+                                                                      {posting => $mid,
+                                                                       assign  => $assign}),
+                                $thx -> {category} => plain ($dparam {$formdata -> {posterCategory} -> {name}}),
+                                $thx -> {home}     => plain ($dparam {$formdata -> {posterURL} -> {name}}),
+                                $thx -> {image}    => plain ($dparam {$formdata -> {posterImage} -> {name}}),
+                                $thx -> {subject}  => plain ($dparam {$formdata -> {posterSubject} -> {name}})})};}
+  return;
+}
+
+################################
+# sub got_reply
+#
+# Antwortposting speichern
+################################
+
+sub got_reply () {
+  my $stat;
+
+  my $time = time;
+  my $pars = {author        => $dparam {$formdata -> {posterName} -> {name}},
+              email         => $dparam {$formdata -> {posterEmail} -> {name}},
+              category      => $dparam {$formdata -> {posterCategory} -> {name}},
+              subject       => $dparam {$formdata -> {posterSubject} -> {name}},
+              body          => $dparam {$formdata -> {posterBody} -> {name}},
+              homepage      => $dparam {$formdata -> {posterURL} -> {name}},
+              image         => $dparam {$formdata -> {posterImage} -> {name}},
+              time          => $time,
+              uniqueID      => $dparam {$formdata -> {uniqueID} -> {name}},
+              ip            => $ENV{REMOTE_ADDR},
+              parentMessage => $fmid,
+              thread        => $ftid,
+              forumFile     => forum_filename,
+              messagePath   => message_path,
+              lastThread    => $last_thread,
+              lastMessage   => $last_message,
+              parsedThreads => $threads,
+              dtd           => 'forum.dtd',
+              quoteChars    => toUTF8('»» '),
+              messages      => $conf -> {template} -> {messages}};
+
+  ($stat, my $xml, my $mid) = write_posting ($pars);
+  violent_unlock_file (forum_filename) unless (write_unlock_file (forum_filename));
+  $flocked = undef;
+
+  if ($stat) {
+    print "Och noe...: $stat";}
+
+  else {
+    my $thx = $show_posting -> {thanx};
+
+    print ${$template -> scrap ($assign -> {docThx},
+                               {$thx -> {author}   => plain ($dparam {$formdata -> {posterName} -> {name}}),
+                                $thx -> {email}    => plain ($dparam {$formdata -> {posterEmail} -> {name}}),
+                                $thx -> {time}     => plain (hr_time($time)),
+                                $thx -> {body}     => message_as_HTML ($xml, $template,
+                                                                      {posting => $mid,
+                                                                       assign  => $assign}),
+                                $thx -> {category} => plain ($dparam {$formdata -> {posterCategory} -> {name}}),
+                                $thx -> {home}     => plain ($dparam {$formdata -> {posterURL} -> {name}}),
+                                $thx -> {image}    => plain ($dparam {$formdata -> {posterImage} -> {name}}),
+                                $thx -> {subject}  => plain ($dparam {$formdata -> {posterSubject} -> {name}})})};}
+}
+
+################################
+# sub new_thread
+#
+# HTML fuer Eroeffnungsposting
+################################
+
+sub new_thread () {
+  my $list = [map {{$assign -> {optval} => plain($_)}} @{$formdata -> {posterCategory} -> {values}}];
+
+  # spaeter kommen noch userspezifische Daten dazu...
+  print ${$template -> scrap ($assign -> {docNew},
+                             {$formdata->{uniqueID}      ->{assign}->{value} => plain(unique_id),
+                              $formdata->{quoteChar}     ->{assign}->{value} => '&#255;'.plain(toUTF8('»» ')),
+                              $formact->{post}->{assign}                     => $formact->{post}->{url},
+                              $formdata->{posterCategory}->{assign}->{value} => $template->list ($assign -> {option}, $list)
+                             },$pars)};
+}
+
+################################
+# diverse subs
+#
+# Fehlermeldungen
+################################
+
+sub no_reply ()         {&print_fatal ($assign -> {noReply});}
+sub dupe_posting ()     {&print_fatal ($assign -> {dupe});}
+sub missing_key ()      {&print_fatal ($assign -> {wrongPar});}
+sub unexpected_key ()   {&print_fatal ($assign -> {wrongPar});}
+sub unknown_encoding () {&print_fatal ($assign -> {wrongCode});}
+sub too_short () {
+  if ($formdata -> {$failed} -> {errorType} eq 'repeat') {
+    &print_error ($formdata -> {$failed} -> {assign} -> {tooShort},
+                  $formdata -> {$failed} -> {minlength});}
+
+  else {
+    &print_fatal ($formdata -> {$failed} -> {assign} -> {tooShort});}
+}
+
+sub too_long () {
+  if ($formdata -> {$failed} -> {errorType} eq 'repeat') {
+    &print_error ($formdata -> {$failed} -> {assign} -> {tooLong},
+                  $formdata -> {$failed} -> {maxlength});}
+
+  else {
+    &print_fatal ($formdata -> {$failed} -> {assign} -> {tooLong});}
+}
+
+sub wrong_mail () {print_error ($formdata -> {$failed} -> {assign} -> {wrong});}
+sub occupied () {print_error ($assign -> {occupied});}
+
+################################
+# sub print_fatal
+#
+# fatale Fehlerausgabe
+################################
+
+sub print_fatal ($) {
+  print ${$template -> scrap ($assign -> {docFatal},
+                             {$assign -> {errorMessage} => $template -> insert ($_[0])
+                             },$pars)};
+}
+
+################################
+# sub print_error
+#
+# Fehlerausgabe, Moeglichkeit
+# zur Korrektur
+################################
+
+sub print_error ($;$) {
+  &fillin;
+  print ${$template -> scrap ($assign -> {docError},
+                             {$assign -> {errorMessage} => $template -> insert ($_[0]),
+                              $assign -> {charNum}      => $_[1]
+                             },$pars)};
+}
+
+################################
+# sub fetch_subject
+#
+# Subject und Category besorgen
+# (wenn noch nicht vorhanden)
+################################
+
+sub fetch_subject () {
+  unless (exists ($dparam{$formdata -> {posterCategory} -> {name}}) and
+          exists ($dparam{$formdata -> {posterSubject} -> {name}})) {
+
+    my $filename = message_path.'t'.$ftid.'.xml';
+
+    if (lock_file ($filename)) {
+      my $xml = new XML::DOM::Parser -> parsefile ($filename);
+      violent_unlock_file($filename) unless unlock_file ($filename);
+
+      my $mnode = get_message_node ($xml, "t$ftid", "m$fmid");
+      my $header = get_message_header ($mnode);
+
+      $dparam{$formdata -> {posterCategory} -> {name}} = $header -> {category};
+      $dparam{$formdata -> {posterSubject} -> {name}} = $header -> {subject};}}
+}
+
+################################
+# sub fillin
+#
+# Fuellen von $pars
+# (bereits vorhandene Formdaten)
+################################
+
+sub fillin () {
+  fetch_subject;
+
+  my $list = [map {{$assign -> {optval} => plain($_),
+                    (($_ eq $dparam{$formdata -> {posterCategory} -> {name}})?($assign -> {optsel} => 1):())}}
+                @{$formdata -> {posterCategory} -> {values}}];
+
+  $pars -> {$formdata->{posterCategory}->{assign}->{value}} = $template->list ($assign -> {option}, $list);
+  $pars -> {$formact ->{post}->{assign}}                    = $formact->{post}->{url};
+  $pars -> {$formdata->{quoteChar}->{assign}->{value}}      = '&#255;'.plain($dparam {$formdata -> {quoteChar} -> {name}} or '');
+
+  # Formfelder ausfuellen (Werte)
+  for (qw(uniqueID userID followUp posterName posterEmail posterSubject posterBody posterURL posterImage)) {
+    $pars -> {$formdata->{$_}->{assign}->{value}} = plain($dparam {$formdata -> {$_} -> {name}});}
+}
+
+################################
+# sub decode_param
+#
+# CGI-Parameter decodieren
+# (rudimentaerer UTF8-support)
+################################
+
+sub decode_param () {
+  my $code = param ($formdata -> {quoteChar} -> {name});
+  my @array;
+
+  # UTF-8 ([hoechst-]wahrscheinlich)
+  if ($code =~ /^\303\277/) {
+
+    foreach (param) {
+      @array=param ($_);
+
+      if (@array == 1) {
+        $dparam{$_} = $array[0];}
+
+      else {
+        $dparam{$_} = \@array;}}}
+
+  # Latin 1 (hoffentlich - eigentlich ist es gar keine Codierung...)
+  elsif ($code =~ /^\377/) {
+    foreach (param) {
+      @array=param ($_);
+
+      if (@array == 1) {
+        $dparam{$_} = toUTF8($array[0]);}
+
+      else {
+        $dparam{$_} = [map {toUTF8($_)} @array];}}}
+
+  # unbekannte Codierung
+  else {
+    return;}
+
+  # ersten beiden Zeichen der Quotechars loeschen (Indikator [&#255; (als UTF8)])
+  $dparam {$formdata -> {quoteChar} -> {name}} = ($dparam {$formdata -> {quoteChar} -> {name}} =~ /..(.*)/)[0];
+
+  delete $dparam {$formdata -> {posterURL} -> {name}}
+    unless ($dparam {$formdata -> {posterURL} -> {name}} =~ /$httpurl/);
+
+  delete $dparam {$formdata -> {posterImage} -> {name}}
+    unless ($dparam {$formdata -> {posterImage} -> {name}} =~ /$httpurl/);
+
+  # Codierung erkannt, alles klar
+  1;
+}
+
+################################
+# sub check_param
+#
+# CGI-Parameter pruefen
+################################
+
+sub check_param () {
+  my %gotKeys    = map {($_ => 1)} param;
+  my $numGotKeys = keys %gotKeys;
+
+  # Threaderoeffnung, Ersteingabe (leere Seite)
+  return 'newThread' if ($numGotKeys == 0 or
+                         (($numGotKeys == 1) and ($gotKeys {$formdata -> {userID} -> {name}})));
+
+  # =======================================================
+  # ab hier steht fest, wir haben ein ausgefuelltes
+  # Formular bekommen
+  #
+  # 1. Umrechnungshash bauen (CGI-Key => Identifier)
+  # 2. alle must-keys vorhanden?
+  # 3. zuviele Parameter uebermittelt?
+  # 4. entsprechen die Daten den Anforderungen?
+  #    (alle, nicht nur die must-Daten)
+
+  # 1
+  # ===
+  my %name = map {($formdata -> {$_} -> {name} => $_)} keys %$formdata;
+
+  # 2
+  # ===
+  $failed=1;
+  foreach (@{$formmust -> {$gotKeys {$formdata -> {followUp} -> {name}}?'reply':'new'}}) {
+    return 'missingKey' unless ($gotKeys {$formdata -> {$_} -> {name}});}
+
+  # 3
+  # ===
+  foreach (param) {
+    $failed = $name {$_};
+    return 'unexpectedKey' unless (exists ($name {$_}));}
+
+  # 4
+  # ===
+  return 'unknownEncoding' unless (decode_param);
+
+  foreach (keys %dparam) {
+    $failed = $name {$_};
+
+    return 'tooLong'   if (length($dparam{$_}) > $formdata -> {$name {$_}} -> {maxlength});
+    return 'tooShort'  if (@{[$dparam{$_} =~ /(\S)/g]} < $formdata -> {$name {$_}} -> {minlength});
+    return 'wrongMail' if ($formdata -> {$name{$_}} -> {type} eq 'email' and length ($dparam{$_}) and not is_mail_address ($dparam{$_}));
+  }
+
+  $failed=0;
+  return $gotKeys {$formdata -> {followUp} -> {name}}?'gotReply':'gotNew';
+}
+
+# ====================================================
+# Initialisierung
+# ====================================================
+
+BEGIN {
+  %subhash = (newThread       => \&new_thread,
+              missingKey      => \&missing_key,
+              unexpectedKey   => \&unexpected_key,
+              unknownEncoding => \&unknown_encoding,
+              tooShort        => \&too_short,
+              tooLong         => \&too_long,
+              wrongMail       => \&wrong_mail,
+              Occupied        => \&occupied,
+              Dupe            => \&dupe_posting,
+              noReply         => \&no_reply,
+              gotReply        => \&got_reply,
+              gotNew          => \&got_new
+              );
+
+  # Die RFC-gerechte URL-Erkennung ist aus dem Forum
+  # (thx2Cheatah - wo auch immer er sie (in der Form) her hat :-)
+  my $lowalpha       =  '(?:[a-z])';
+  my $hialpha        =  '(?:[A-Z])';
+  my $alpha          =  "(?:$lowalpha|$hialpha)";
+  my $digit          =  '(?:\d)';
+  my $safe           =  '(?:[$_.+-])';
+  my $hex            =  '(?:[\dA-Fa-f])';
+  my $escape         =  "(?:%$hex$hex)";
+  my $digits         =  '(?:\d+)';
+  my $alphadigit     =  "(?:$alpha|\\d)";
+
+  # URL schemeparts for ip based protocols:
+  my $port           =  "(?:$digits)";
+  my $hostnumber     =  "(?:$digits\\.$digits\\.$digits\\.$digits)";
+  my $toplabel       =  "(?:(?:$alpha(?:$alphadigit|-)*$alphadigit)|$alpha)";
+  my $domainlabel    =  "(?:(?:$alphadigit(?:$alphadigit|-)*$alphadigit)|$alphadigit)";
+  my $hostname       =  "(?:(?:$domainlabel\\.)*$toplabel)";
+  my $host           =  "(?:(?:$hostname)|(?:$hostnumber))";
+  my $hostport       =  "(?:(?:$host)(?::$port)?)";
+
+  my $httpuchar      =  "(?:(?:$alpha|$digit|$safe|(?:[!*\',]))|$escape)";
+  my $hsegment       =  "(?:(?:$httpuchar|[;:\@&=~])*)";
+  my $search         =  "(?:(?:$httpuchar|[;:\@&=~])*)";
+  my $hpath          =  "(?:$hsegment(?:/$hsegment)*)";
+
+  # das alles ergibt eine gueltige URL :-)
+  $httpurl           =  "^(?:https?://$hostport(?:/$hpath(?:\\?$search)?)?)\$";
+}
+
+# ====================================================
+# end of fo_posting.pl
+# ====================================================
\ No newline at end of file
diff --git a/selfforum-cgi/user/fo_view.pl b/selfforum-cgi/user/fo_view.pl
new file mode 100644 (file)
index 0000000..5d7d529
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+
+use strict;
+
+use vars qw($Bin $Shared $Script $t0);
+
+BEGIN {
+  ($Bin)    = ($0 =~ /^(.*)\/.*$/)? $1 : '.';
+  $Shared   = "$Bin/../shared";
+  ($Script) = ($0 =~ /^.*\/(.*)$/)? $1 : $0;}
+
+use lib "$Shared";
+#use CGI::Carp qw(fatalsToBrowser);
+
+use Conf;
+use Conf::Admin;
+use Template::Forum;
+use Template::Posting;
+
+use CGI qw(param header);
+
+print header(-type => 'text/html');
+
+my $conf = read_script_conf ($Bin, $Shared, $Script);
+
+$conf -> {wwwRoot} = 'i:/i_selfhtml/htdocs' unless ($ENV{GATEWAY_INTERFACE} =~ /CGI/);
+
+my $show = $conf -> {show};
+my $show_forum = $show -> {Forum};
+my $show_posting = $show -> {Posting};
+my $cgi = $show -> {assign} -> {cgi};
+my $tree = $show -> {assign} -> {thread};
+my $adminDefault = read_admin_conf ("$Bin/".$conf -> {files} -> {adminDefault});
+
+my $forum_file = $conf -> {wwwRoot}.$conf -> {files} -> {forum};
+my $message_path = $conf -> {wwwRoot}.$conf -> {files} -> {messagePath};
+
+#use Lock qw(:ALL);release_file(forum_file);die;
+
+my ($tid, $mid) = (param ($cgi -> {thread}), param ($cgi -> {posting}));
+
+if (defined ($tid) and defined ($mid)) {
+  print_posting_as_HTML ($message_path,
+                         "$Bin/".$show_posting -> {templateFile},
+                        {assign   => $show_posting -> {assign},
+                         thread   => $tid,
+                         posting  => $mid,
+                         messages => $show_posting -> {messages},
+                         form     => $show_posting -> {form},
+                         cgi      => $cgi,
+                         tree     => $tree
+                        });}
+
+else {
+  print_forum_as_HTML ($forum_file,
+                       "$Bin/".$show_forum -> {templateFile},
+                      {assign       => $show_forum -> {assign},
+                       adminDefault => $adminDefault,
+                       cgi          => $cgi,
+                       tree         => $tree
+                      });}
+
+# eos
\ No newline at end of file
diff --git a/selfforum-data/.htaccess b/selfforum-data/.htaccess
new file mode 100644 (file)
index 0000000..374a763
--- /dev/null
@@ -0,0 +1,4 @@
+DirectoryIndex index.shtml
+Options +Includes
+AddHandler server-parsed shtml
\ No newline at end of file
diff --git a/selfforum-data/images/01.gif b/selfforum-data/images/01.gif
new file mode 100644 (file)
index 0000000..1050b8f
Binary files /dev/null and b/selfforum-data/images/01.gif differ
diff --git a/selfforum-data/images/02.gif b/selfforum-data/images/02.gif
new file mode 100644 (file)
index 0000000..e7a39cf
Binary files /dev/null and b/selfforum-data/images/02.gif differ
diff --git a/selfforum-data/images/03.gif b/selfforum-data/images/03.gif
new file mode 100644 (file)
index 0000000..431cdaf
Binary files /dev/null and b/selfforum-data/images/03.gif differ
diff --git a/selfforum-data/images/04.gif b/selfforum-data/images/04.gif
new file mode 100644 (file)
index 0000000..eb6aa5b
Binary files /dev/null and b/selfforum-data/images/04.gif differ
diff --git a/selfforum-data/images/05.gif b/selfforum-data/images/05.gif
new file mode 100644 (file)
index 0000000..14c1157
Binary files /dev/null and b/selfforum-data/images/05.gif differ
diff --git a/selfforum-data/images/06.gif b/selfforum-data/images/06.gif
new file mode 100644 (file)
index 0000000..505b2ac
Binary files /dev/null and b/selfforum-data/images/06.gif differ
diff --git a/selfforum-data/images/07.gif b/selfforum-data/images/07.gif
new file mode 100644 (file)
index 0000000..d33e968
Binary files /dev/null and b/selfforum-data/images/07.gif differ
diff --git a/selfforum-data/images/08.gif b/selfforum-data/images/08.gif
new file mode 100644 (file)
index 0000000..95dcc0f
Binary files /dev/null and b/selfforum-data/images/08.gif differ
diff --git a/selfforum-data/images/09.gif b/selfforum-data/images/09.gif
new file mode 100644 (file)
index 0000000..36a798f
Binary files /dev/null and b/selfforum-data/images/09.gif differ
diff --git a/selfforum-data/images/10.gif b/selfforum-data/images/10.gif
new file mode 100644 (file)
index 0000000..67e5911
Binary files /dev/null and b/selfforum-data/images/10.gif differ
diff --git a/selfforum-data/index.shtml b/selfforum-data/index.shtml
new file mode 100644 (file)
index 0000000..2a7f9ef
--- /dev/null
@@ -0,0 +1 @@
+<!--#include virtual="/cgi-local/user/fo_view.pl?$QUERY_STRING"-->
diff --git a/selfforum-data/messages/forum.dtd b/selfforum-data/messages/forum.dtd
new file mode 100644 (file)
index 0000000..46cb440
--- /dev/null
@@ -0,0 +1,199 @@
+<!--
+Document Type Declaration fuer das SELFHTML-Forum
+Autor: Thomas J. Sebestyen     thomasj.sebestyen@meta-text.net
+
+Version 1.00   17.07.2000
+Version 1.01   29.07.2000
+Version 2.00   30.09.2000
+       AEnderung der DTD:
+       - Vereinfachung der Syntax: Wegfall von Attributen bei 'Thread' und 'Message'.
+       - Einfuehren von den Elementen 'Header' 'Email' 'Homepage' 'Imageurl' 'Category' 'Subject'.
+       - AEndern von 'Datum' auf 'Date' und Erweiterung der Attribute.
+   
+   Aenderung 27.2.2000 Thomas J.S.
+   - Hinzufuegen von den Attributen:visitings, votingUser, votingAteam und votingAdmin beim "Message"
+     lastThread und lastMessage beim "Forum"
+   - Reduzierung der Attribute beim "Date" auf 'longSec'
+   - Wegfall vom "Flag"
+   - Eifuehren von %boolean als ja/nein Wertangabe
+   
+-->
+
+<!ENTITY % boolean "(0 | 1)">
+<!-- Parameterentity fuer ja (1) oder nein (0) Fragen -->
+
+
+<!ELEMENT              Forum                   ((Thread, ContentList) | (Thread)*)>
+<!-- *****************************************************************************************************
+               Das Element 'Forum' wurde definert.
+      'Forum' ist das rootelement und beinhaltet alle anderen Elemente
+***************************************************************************************************** -->
+<!ATTLIST      Forum
+   lastThread     IDREF    #REQUIRED
+   lastMessage    IDREF    #REQUIRED
+>
+<!-- *****************************************************************************************************
+      Das Attribut 'lastThread' hat den Typ IDREF, es bezieht sich auf die ID des
+      jeweils letzten Threads im Forum
+      Das Attribut 'lastMessage' hat den Typ IDREF, es bezieht sich auf die ID der
+      jeweils letzten Messages im Forum
+***************************************************************************************************** -->
+
+
+
+
+
+<!ELEMENT              Thread                  (Message)>
+<!-- *****************************************************************************************************
+               Das Element 'Thread' wurde definert.
+      'Thread' stellt ein Nachrichtnbaum dar.
+***************************************************************************************************** -->
+<!ATTLIST      Thread
+       id              ID              #REQUIRED
+>
+<!-- *****************************************************************************************************
+               Das Attribut 'id' hat den Typ ID  und muss zwingend vorhanden sein.
+***************************************************************************************************** -->
+
+
+
+
+
+<!ELEMENT              ContentList             (MessageContent)+>
+<!-- *****************************************************************************************************
+               Das Element 'ContentList' wurde definert.
+      'ContentList' enthaelt alle Nachrichteninhalte.
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              MessageContent  (#PCDATA)>
+<!-- *****************************************************************************************************
+               Das Element 'MessageContent' wurde definert.
+      'MessageContent' beinhaltet den Nachrichtentext eines Messages
+***************************************************************************************************** -->
+<!ATTLIST MessageContent
+       mid             IDREF           #REQUIRED
+>
+<!-- *****************************************************************************************************
+               Das Attribut 'mid' hat den Typ IDREF, es bezieht sich auf die ID der entsprechnden Messages.
+***************************************************************************************************** -->
+
+
+
+
+<!ELEMENT              Message                 (Header, Message*)>
+<!-- *****************************************************************************************************
+               Das Element 'Message' wurde definert.
+      'Message' stellt eine Nachricht im Thread dar und darf andere 'Messages' enthalten
+       um so Teilbaeume im Thread zu bilden.
+***************************************************************************************************** -->
+<!ATTLIST Message
+       id              ID              #REQUIRED
+       visitings   NMTOKEN     #IMPLIED
+   votingUser  NMTOKEN     #IMPLIED
+   votingAteam %boolean;   #IMPLIED
+   votingAdmin %boolean;   #IMPLIED      
+>
+<!-- *****************************************************************************************************
+               Das Attribut 'id' hat den Typ ID  und muss zwingend vorhanden sein.
+      Das Attribut 'visitings' zaehlt die Anzahl der Aufrufe einer Messages.
+      Das Attribut 'votingUser' zaehlt wie oft User die Nachricht fuer das Archiv vorgeschlagen haben.
+      Das Attribut 'votingAteam'  ja/nein Entscheidung eines Mitgliedes des Auslese-Teams fuer die
+      Archivierung einer Nachricht. 0 = auf keinem Fall archivieren, 1 = auf jedem Fall archivieren.
+      Das Attribut 'votingAdmin'  ja/nein Entscheidung eines Mitgliedes des SELFHTML-Redaktionsteams
+      fuer die Archivierung einer Nachricht. 
+      0 = auf keinem Fall archivieren, 1 = auf jedem Fall archivieren.      
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              Header                  (Author, Category, Subject, Date)>
+<!-- *****************************************************************************************************
+               Das Element 'Header' wurde definert.
+      'Header' beinhaltet die fuer die Nachricht relevanten Informationen in Form von Elementen
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              Author                  (Name, Email, HomepageUrl?, ImageUrl?)>
+<!-- *****************************************************************************************************
+               Das Element 'Author' wurde definert.
+      'Autor' enthaelt alle benoetingten und optionalen Daten zum Nachrichtenautor.
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              Category                (#PCDATA)>
+<!-- *****************************************************************************************************
+               Das Element 'Category' wurde definert.
+      'Category' enthaelt ein, aus einer Liste waehlbares Forumsthema.
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              Subject                 (#PCDATA)>
+<!-- *****************************************************************************************************
+               Das Element 'Subject' wurde definert.
+      'Subject' beinhaltet den vom User definierten Titel der Nachricht.
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              Date                     EMPTY>
+<!-- *****************************************************************************************************
+               Das Element 'Datum' wurde definert.
+               'Date' enthaelt die Zeit, zu der die Nachricht gepostet wurde.
+***************************************************************************************************** -->
+<!ATTLIST Date
+       longSec NMTOKEN         #REQUIRED
+>
+<!--
+       year            NMTOKEN         #REQUIRED
+       mon             NMTOKEN         #REQUIRED
+       day             NMTOKEN         #REQUIRED
+       hour            NMTOKEN         #REQUIRED
+       min             NMTOKEN         #REQUIRED
+       sec             NMTOKEN         #REQUIRED
+       isoDate NMTOKEN         #REQUIRED
+-->   
+<!-- *****************************************************************************************************
+               Die Liste der Attribute fuer das Element 'Date' wurde definert.
+               Alle Attribute haben den Typ NMTOKEN und jedes der Attribute muss zwingend vorhanden sein.
+               NMTOKEN = Es duerfen Werte in den Attributen mit Zahlen beginnen;
+               und Buchstaben, Zahlen, den ( . ), den Unterstrich ( _ ) und Bindestrich ( - ) enthalten.
+               'isoDate' ist fuer Datumformat: YYYY-MM-DD gedacht.
+               'longSec' steht fuer Datum/Zeit in Sekunden seit 1970.
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              Name                    (#PCDATA)>
+<!-- *****************************************************************************************************
+               Das Element 'Name' wurde definert.
+      'Name' enthaelt den Namen des Messageautors
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              Email                   (#PCDATA)>
+<!-- *****************************************************************************************************
+               Das Element 'Email' wurde definert.
+      'Email' enthaelt die E-Mail-Adresse des Messageautors
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              HomepageUrl                     (#PCDATA)>
+<!-- *****************************************************************************************************
+               Das Element 'HomepageURL' wurde definert.
+      'HomepageUrl' enthaelt die Internetadresse der Website des Messageautors.
+***************************************************************************************************** -->
+
+
+
+<!ELEMENT              ImageUrl                (#PCDATA)>
+<!-- *****************************************************************************************************
+               Das Element 'ImageURL' wurde definert.
+      'ImageUrl' enthaelt die Internetadresse eines beliebigen Bildes (Banners) des Messageautors.
+***************************************************************************************************** -->
diff --git a/selfforum-data/messages/selfforum.xml.lock b/selfforum-data/messages/selfforum.xml.lock
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/selfforum-data/messages/selfforum.xml.lock.ref b/selfforum-data/messages/selfforum.xml.lock.ref
new file mode 100644 (file)
index 0000000..c227083
--- /dev/null
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/selfforum-data/messages/selfforum.xml.lock.ref.lock b/selfforum-data/messages/selfforum.xml.lock.ref.lock
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/selfforum-data/messages/selfforum.xml.master.lock b/selfforum-data/messages/selfforum.xml.master.lock
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/selfforum-data/neu.shtml b/selfforum-data/neu.shtml
new file mode 100644 (file)
index 0000000..4623889
--- /dev/null
@@ -0,0 +1 @@
+<!--#include virtual="/cgi-local/user/fo_posting.pl"-->

patrick-canterino.de