]> git.p6c8.net - selfforum.git/blobdiff - selfforum-cgi/shared/Posting/Write.pm
now, if main file is master locked, fo_view.pl won't show any single message
[selfforum.git] / selfforum-cgi / shared / Posting / Write.pm
index d2444df8d180a920299f0f626b4c37e9c1981880..62fa11cb75aef9857a02719e061ee175a6445f94 100644 (file)
-# 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);
+################################################################################
+#                                                                              #
+# File:        shared/Posting/Write.pm                                         #
+#                                                                              #
+# Authors:     AndrĂ© Malo <nd@o3media.de>                                      #
+#                                                                              #
+# Description: Save a posting                                                  #
+#                                                                              #
+################################################################################
 
-# ====================================================
-# Funktionsexport
-# ====================================================
-
-require Exporter;
-@ISA    = qw(Exporter);
-@EXPORT = qw(write_posting);
+use strict;
+use vars qw(
+  %error
+  @EXPORT
+);
 
 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 Lock;
+use Posting::_lib qw(
+  get_message_node
+  get_message_header
+  create_forum_xml_string
+  create_new_thread
+  create_message
+  save_file
+  parse_xml_file
+  KEEP_DELETED
+);
 
 use XML::DOM;
 
-################################
-# sub write_posting
+%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'
+);
+
+################################################################################
 #
-# Neues Posting speichern
-################################
+# Version check
+#
+# last modified:
+#    $Date$ (GMT)
+# by $Author$
+#
+sub VERSION {(q$Revision$ =~ /([\d.]+)\s*$/)[0] or '0.0'}
 
-sub write_posting ($) {
+################################################################################
+#
+# Export
+#
+use base qw(Exporter);
+@EXPORT = qw(
+  write_new_thread
+  write_reply_posting
+);
+
+### sub write_new_thread ($) ###################################################
+#
+# save a posting and update the forum main file
+#
+# Params: $param - hashreference
+#                  (see doc for details)
+#
+# Return: (0 or error, thread-xml, new mid)
+#
+sub write_new_thread ($) {
   my $param = shift;
-  my ($thread,$tid);
+  my $thread;
   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);}
+  my $tid   = 't'.($param -> {lastThread} + 1);
+
+  # define the params needed for a new thread
+  #
+  my $pars = {
+    msg      => $mid,
+    ip       => $param -> {ip},
+    name     => defined $param -> {author}   ? $param -> {author}   : '',
+    email    => defined $param -> {email}    ? $param -> {email}    : '',
+    home     => defined $param -> {homepage} ? $param -> {homepage} : '',
+    image    => defined $param -> {image}    ? $param -> {image}    : '',
+    category => defined $param -> {category} ? $param -> {category} : '',
+    subject  => defined $param -> {subject}  ? $param -> {subject}  : '',
+    body     => encoded_body(
+      \($param -> {body}),
+      { quoteChars => $param -> {quoteChars},
+        messages   => $param -> {messages},
+        base_uri   => $param -> {base_uri}
+      }
+    ),
+    time     => $param -> {time},
+    dtd      => $param -> {dtd},
+    thread   => $tid
+  };
+
+  # create new thread and save it to disk
+  #
+  $thread = create_new_thread ($pars);
+  save_file ($param -> {messagePath}.$tid.'.xml',\($thread -> toString)) or return $error{threadWrite};
+
+  # update forum main file
+  #
+  $param
+    -> {parsedThreads}
+    -> {$param -> {lastThread} + 1} = [
+        { mid     => $param -> {lastMessage} + 1,
+          unid    => $param -> {uniqueID},
+          name    => plain($pars -> {name}),
+          cat     => plain($pars -> {category}),
+          subject => plain($pars -> {subject}),
+          time    => plain($pars -> {time}),
+          level   => 0,
+        }
+       ];
+
+  my $forum = create_forum_xml_string (
+    $param -> {parsedThreads},
+    { dtd         => $pars -> {dtd},
+      lastMessage => $mid,
+      lastThread  => $tid
+    }
+  );
+
+  save_file ($param -> {forumFile}, $forum) or return $error{forumWrite};
+  new Lock ($param -> {messagePath}.$tid.'.xml') -> release;
+  return (0, $thread, $mid, $tid);
 }
 
-# ====================================================
-# 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);
+### sub write_reply_posting ($) ################################################
+#
+# save a reply and update the forum main file
+#
+# Params: $param - hashreference
+#                  (see doc for details)
+#
+# Return: (0 or error, thread-xml, new mid)
+#
+sub write_reply_posting ($) {
+  my $param = shift;
+  my $thread;
+  my $mid   = 'm'.($param -> {lastMessage} + 1);
+  my $tid   = 't'.($param -> {thread});
 
-  # 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} )}));
+  my $tfile = new Lock ($param -> {messagePath}.$tid.'.xml');
 
-  # die ganzen Nodes verknuepfen
-      $thread -> appendChild ($message);
-    $forum -> appendChild ($thread);
+  unless ($tfile->lock(LH_EXCL)) {
+    return $error{threadFile};
+  }
 
-      $content -> appendChild ($mcontent);
-    $forum -> appendChild ($content);
+  else {
+    my $xml = parse_xml_file ($tfile->filename);
+
+    unless ($xml) {
+      $tfile -> unlock;
+      return $error{threadFile};
+    }
+
+    my $mnode = get_message_node ($xml, $tid, 'm'.$param -> {parentMessage});
+
+    unless (defined $mnode) {
+      $tfile -> unlock;
+      return $error{noParent};
+    }
+
+    my $pars = {
+      msg      => $mid,
+      ip       => $param -> {ip},
+      name     => defined $param -> {author}   ? $param -> {author}   :'',
+      email    => defined $param -> {email}    ? $param -> {email}    :'',
+      home     => defined $param -> {homepage} ? $param -> {homepage} :'',
+      image    => defined $param -> {image}    ? $param -> {image}    :'',
+      category => defined $param -> {category} ? $param -> {category} :'',
+      subject  => defined $param -> {subject}  ? $param -> {subject}  :'',
+      time     => $param -> {time},
+    };
+
+    my $message = create_message ($xml, $pars);
+
+    $mnode -> appendChild ($message);
+
+    my $mcontent = $xml -> createElement ('MessageContent');
+    $mcontent -> setAttribute ('mid' => $mid);
+    $mcontent -> appendChild (
+      $xml -> createCDATASection (
+        ${encoded_body(
+          \($param -> {body}),
+          { quoteChars => $param -> {quoteChars},
+            messages   => $param -> {messages},
+            base_uri   => $param -> {base_uri}
+          }
+        )}
+      )
+    );
+
+    my $content = $xml -> getElementsByTagName ('ContentList', 1) -> item (0);
+       $content -> appendChild ($mcontent);
+
+    # save thread file
+    #
+    unless (save_file ($tfile->filename, \($xml -> toString))) {
+      $tfile -> unlock;
+      return $error{threadWrite};
+    }
+
+    $tfile -> unlock;
+
+    $thread = $xml;
+
+    # add message to thread tree
+    # ATTENTION: don't use the tree for visual output after this operation
+    #
+    my $i=1;
+    for (@{$param -> {parsedThreads} -> {$param -> {thread}}}) {
+      if ($_ -> {mid} == $param -> {parentMessage}) {
+        splice @{
+          $param -> {parsedThreads} -> {$param -> {thread}}},$i, 0,
+          { mid     => $param -> {lastMessage} + 1,
+            unid    => plain ($param -> {uniqueID}),
+            name    => plain ($pars -> {name}),
+            cat     => plain ($pars -> {category}),
+            subject => plain ($pars -> {subject}),
+            level   => $_ -> {level} + 1,
+            time    => plain ($pars -> {time})
+          };
+        last;
+      }
+      $i++;
+    }
+
+    # create & save forum main file
+    #
+    my $forum = create_forum_xml_string (
+      $param -> {parsedThreads},
+      { dtd         => $param -> {dtd},
+        lastMessage => $mid,
+        lastThread  => 't'.$param -> {lastThread}
+      }
+    );
 
-  $xml -> appendChild ($forum);
+    save_file ($param -> {forumFile}, $forum) or return $error{forumWrite};
+  }
 
-  # und fertiges Dokument zurueckgeben
-  $xml;
+  return (0, $thread, $mid, $tid);
 }
 
-# ====================================================
-# Modulinitialisierung
-# ====================================================
-
-# making require happy
+# keep 'require' happy
+#
 1;
 
-# ====================================================
-# end of Posting::Write
-# ====================================================
\ No newline at end of file
+#
+#
+### end of Posting::Write ######################################################
\ No newline at end of file

patrick-canterino.de