simplifications
authorx2000habouzit <x2000habouzit>
Sun, 2 Jan 2005 13:52:51 +0000 (13:52 +0000)
committerx2000habouzit <x2000habouzit>
Sun, 2 Jan 2005 13:52:51 +0000 (13:52 +0000)
css/style.css
include/misc.inc.php
include/spool.inc.php
install.d/format.inc.php

index 373865d..19caebe 100644 (file)
@@ -134,3 +134,5 @@ table.overview td.subject,td.group,td.from,td.description {
   text-align: left;
 }
 
+table.overview .new { font-weight: bold; }
+
index 9731d16..1db84aa 100644 (file)
@@ -1,21 +1,51 @@
 <?php
 /********************************************************************************
-* include/wrapper.inc.php : text wrapper 
+* include/misc.inc.php : Misc functions
 * -------------------------
 *
 * This file is part of the banana distribution
 * Copyright: See COPYING files that comes with this distribution
 ********************************************************************************/
 
-function wrap($_text, $_prefix="", $_length=72)
+function _headerdecode($charset, $c, $str) {
+    $s = ($c == 'Q') ? quoted_printable_decode($str) : base64_decode($str);
+    $s = iconv($charset, 'iso-8859-15', $s);
+    return str_replace('_', ' ', $s);
+}
+function headerDecode($value) {
+    $val = preg_replace('/(=\?[^?]*\?[BQ]\?[^?]*\?=) (=\?[^?]*\?[BQ]\?[^?]*\?=)/', '\1\2', $value);
+    return preg_replace('/=\?([^?]*)\?([BQ])\?([^?]*)\?=/e', '_headerdecode("\1", "\2", "\3")', $val);
+}
+
+function formatFrom($text) {
+#     From: mark@cbosgd.ATT.COM
+#     From: mark@cbosgd.ATT.COM (Mark Horton)
+#     From: Mark Horton <mark@cbosgd.ATT.COM>
+    $mailto = '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;';
+
+    $result = htmlentities($text);
+    if (preg_match("/^([^ ]+)@([^ ]+)$/",$text,$regs)) {
+        $result="$mailto{$regs[1]}&#64;{$regs[2]}\">".htmlentities($regs[1]."&#64;".$regs[2])."</a>";
+    }
+    if (preg_match("/^([^ ]+)@([^ ]+) \((.*)\)$/",$text,$regs)) {
+        $result="$mailto{$regs[1]}&#64;{$regs[2]}\">".htmlentities($regs[3])."</a>";
+    }
+    if (preg_match("/^\"?([^<>\"]+)\"? +<(.+)@(.+)>$/",$text,$regs)) {
+        $result="$mailto{$regs[2]}&#64;{$regs[3]}\">".htmlentities($regs[1])."</a>";
+    }
+    return preg_replace("/\\\(\(|\))/","\\1",$result);
+}
+
+function wrap($text, $_prefix="", $_length=72)
 {
-    $parts = preg_split("/\n-- ?\n/", $_text);
+    $parts = preg_split("/\n-- ?\n/", $text);
     if (count($parts)  >1) {
         $sign = "\n-- \n" . array_pop($parts);
         $text = join("\n-- \n", $parts);
     } else {
         $sign = '';
-        $text = $_text;
+        $text = $text;
     }
     
     $cmd = "echo ".escapeshellarg($text)." | perl -MText::Autoformat -e 'autoformat {left=>1, right=>$_length, all=>1 };'";
@@ -24,15 +54,21 @@ function wrap($_text, $_prefix="", $_length=72)
     return $_prefix.join("\n$_prefix", $result).($_prefix ? '' : $sign);
 }
 
-function _headerdecode($charset, $c, $str) {
-    $s = ($c == 'Q') ? quoted_printable_decode($str) : base64_decode($str);
-    $s = iconv($charset, 'iso-8859-15', $s);
-    return str_replace('_', ' ', $s);
-}
-function headerDecode($value) {
-    $val = preg_replace('/(=\?[^?]*\?[BQ]\?[^?]*\?=) (=\?[^?]*\?[BQ]\?[^?]*\?=)/', '\1\2', $value);
-    return preg_replace('/=\?([^?]*)\?([BQ])\?([^?]*)\?=/e', '_headerdecode("\1", "\2", "\3")', $val);
+function formatbody($_text) {
+    global $news;
+    $res  = "\n\n" . htmlentities(wrap($_text, "", $news['wrap']))."\n\n";
+    $res  = preg_replace("/(&lt;|&gt;|&quot;)/", " \\1 ", $res);
+    $res  = preg_replace('/(["\[])?((https?|ftp|news):\/\/[a-z@0-9.~%$£µ&i#\-+=_\/\?]*)(["\]])?/i', "\\1<a href=\"\\2\">\\2</a>\\4", $res);
+    $res  = preg_replace("/ (&lt;|&gt;|&quot;) /", "\\1", $res);
+   
+    $parts = preg_split("/\n-- ?\n/", $res);
+
+    if (count($parts) > 1) {
+        $sign = "</pre><hr style='width: 100%; margin: 1em 0em; ' /><pre>" . array_pop($parts);
+        return join("\n-- \n", $parts).$sign;
+    } else {
+        return $res;
+    }
 }
 
 ?>
index 942f36e..a4831c4 100644 (file)
@@ -16,11 +16,9 @@ if(!function_exists('_file_put_contents')) {
         }
         fputs($fp, $data);
         fclose($fp);
-
     }
 }
 
-
 /** Class spoolhead
  *  class used in thread overviews
  */
@@ -89,108 +87,122 @@ class spool
      * @param $_display INTEGER 1 => all posts, 2 => only threads with new posts
      * @param $_since INTEGER time stamp (used for read/unread)
      */
-
     function spool(&$_nntp, $_group, $_display=0, $_since="")
     {
         global $news;
+        $this->group = $_group;
+        $groupinfo   = $_nntp->group($_group);
+        if (!$groupinfo) { return ($this = null); }
 
-        $do_save    = false;
-
-        $spool_path = dirname(dirname(__FILE__)).'/spool';
-        $spoolfile  = "$spool_path/spool-$_group.dat";
 
-        $groupinfo  = $_nntp->group($_group);
-        $first      = max($groupinfo[2]-$news['maxspool'], $groupinfo[1]);
-        $last       = $groupinfo[2];
-
-        if (!$groupinfo) {
-            $this = null;
-            return false;
-        }
-        if (file_exists($spoolfile)) {
-            $this   = unserialize(file_get_contents($spoolfile));
-        }
+        $this->_readFromFile();
 
+        $do_save = false;
+        $first   = max($groupinfo[2]-$news['maxspool'], $groupinfo[1]);
+        $last    = $groupinfo[2];
         if ($this->version == BANANA_SPOOL_VERSION) {
-            $keys   = array_values($this->ids);
-            rsort($keys);
-            // remove expired messages
             for ($id = min(array_keys($this->overview)); $id<$first; $id++) { 
                 $this->delid($id, false);
                 $do_save = true;
             }
-            $start  = max(array_keys($this->overview))+1;
+            $first = max(array_keys($this->overview))+1;
         } else {
             unset($this->overview, $this->ids);
-            $this->group   = $_group;
             $this->version = BANANA_SPOOL_VERSION;
-            $start         = $first;
         }
 
-        if (($start<$last) && $groupinfo[0]) {
-            $do_save  = true;
+        if ($first<$last && $groupinfo[0]) {
+            $do_save = true;
+            $this->_updateSpool($_nntp, "$first-$last");
+        }
 
-            $dates    = array_map("strtotime",    $_nntp->xhdr("Date",    "$start-$last"));
-            $subjects = array_map("headerdecode", $_nntp->xhdr("Subject", "$start-$last"));
-            $froms    = array_map("headerdecode", $_nntp->xhdr("From",    "$start-$last"));
-            $msgids   = $_nntp->xhdr("Message-ID", "$start-$last");
-            $refs     = $_nntp->xhdr("References", "$start-$last");
+        if ($do_save) { $this->_saveToFile(); }
 
-            if (isset($this->ids)) {
-                $this->ids = array_merge($this->ids, array_flip($msgids));
-            } else {
-                $this->ids = array_flip($msgids);
+        $this->_updateUnread($_nntp, $_since, $_display);
+    }
+
+    function _readFromFile()
+    {
+        $file = dirname(dirname(__FILE__))."/spool/spool-{$this->group}.dat";
+        if (file_exists($file)) {
+            $this = unserialize(file_get_contents($file));
+        }
+    }
+
+    function _saveToFile()
+    {
+        $file = dirname(dirname(__FILE__))."/spool/spool-{$this->group}.dat";
+        uasort($this->overview, "spoolcompare");
+
+        $this->roots = Array();
+        foreach($this->overview as $id=>$msg) {
+            if (is_null($msg->parent)) {
+                $this->roots[] = $id;
+            }
+        }
+        
+        file_put_contents($file, serialize($this));
+    }
+
+    function _updateSpool(&$_nntp, $arg)
+    {
+        $dates    = array_map(strtotime,    $_nntp->xhdr("Date",    $arg));
+        $subjects = array_map(headerdecode, $_nntp->xhdr("Subject", $arg));
+        $froms    = array_map(headerdecode, $_nntp->xhdr("From",    $arg));
+        $msgids   = $_nntp->xhdr("Message-ID", $arg);
+        $refs     = $_nntp->xhdr("References", $arg);
+
+        if (is_array($this->ids)) {
+            $this->ids = array_merge($this->ids, array_flip($msgids));
+        } else {
+            $this->ids = array_flip($msgids);
+        }
+
+        foreach ($msgids as $id=>$msgid) {
+            $msg                = new spoolhead($dates[$id], $subjects[$id], $froms[$id]);
+            $refs[$id]          = str_replace('><', '> <', $refs[$id]);
+            $msgrefs            = preg_split("/[ \t]/", strtr($refs[$id], $this->ids));
+            $parents            = preg_grep('/^\d+$/', $msgrefs);
+            $msg->parent        = array_pop($parents);
+            $msg->parent_direct = preg_match('/^\d+$/', array_pop($msgrefs));
+
+            if (isset($this->overview[$id])) {
+                $msg->desc     = $this->overview[$id]->desc;
+                $msg->children = $this->overview[$id]->children;
             }
+            $this->overview[$id] = $msg;
 
-            foreach ($msgids as $id=>$msgid) {
-                $msg                = new spoolhead($dates[$id], $subjects[$id], $froms[$id]);
-                $refs[$id]          = str_replace("><", "> <", $refs[$id]);
-                $msgrefs            = preg_split("/( |\t)/", strtr($refs[$id], $this->ids));
-                $parents            = preg_grep("/^\d+$/", $msgrefs);
-                $msg->parent        = array_pop($parents);
-                $msg->parent_direct = preg_match("/^\d+$/", array_pop($msgrefs));
-                
-                if (isset($this->overview[$id])) {
-                    $msg->desc     = $this->overview[$id]->desc;
-                    $msg->children = $this->overview[$id]->children;
+            if ($p = $msg->parent) {
+                if (empty($this->overview[$p])) {
+                    $this->overview[$p] = new spoolhead($dates[$p], $subjects[$p], $froms[$p], 1);
                 }
-                $this->overview[$id] = $msg;
-           
-                if ($p = $msg->parent) {
-                    if (empty($this->overview[$p])) {
-                        $this->overview[$p] = new spoolhead($dates[$p], $subjects[$p], $froms[$p], 1);
-                    }
-                    $this->overview[$msg->parent]->children[] = $id;
+                $this->overview[$p]->children[] = $id;
 
-                    while ($p) {
-                        $this->overview[$p]->desc += $msg->desc;
-                        $p = $this->overview[$p]->parent;
-                    }
-                    
+                while ($p) {
+                    $this->overview[$p]->desc += $msg->desc;
+                    $p = $this->overview[$p]->parent;
                 }
             }
         }
+    }
 
-        if ($do_save) { $this->save($spoolfile); }
-
-        if ($_since) {
-            $newpostsids = $_nntp->newnews($_since, $_group);
-            if (sizeof($newpostsids)) {
-                $newpostsids = array_intersect($newpostsids, array_keys($this->ids));
-                if ($newpostsids && !is_null($newpostsids)) {
-                    foreach ($newpostsids as $mid) {
-                        $this->overview[$this->ids[$mid]]->isread     = false;
-                        $this->overview[$this->ids[$mid]]->descunread = 1;
-                        $parentmid = $this->ids[$mid];
-                        while (isset($parentmid)) {
-                            $this->overview[$parentmid]->descunread ++;
-                            $parentmid = $this->overview[$parentmid]->parent;
-                        }
-                    }
+    function _updateUnread(&$nntp, $since, $mode) {
+        if (empty($since)) { return; }
+
+        if (is_array($newpostsids = $nntp->newnews($since, $this->group))) {
+            $newpostsids = array_intersect($newpostsids, array_keys($this->ids));
+            foreach ($newpostsids as $mid) {
+                $this->overview[$this->ids[$mid]]->isread     = false;
+                $this->overview[$this->ids[$mid]]->descunread = 1;
+                $parentmid = $this->ids[$mid];
+                while (isset($parentmid)) {
+                    $this->overview[$parentmid]->descunread ++;
+                    $parentmid = $this->overview[$parentmid]->parent;
                 }
             }
-            if (sizeof($newpostsids)>0) {
-                switch ($_display) {
+
+            if (count($newpostsids)) {
+                switch ($mode) {
                     case 1:
                         foreach ($this->roots as $k=>$i) {
                             if ($this->overview[$i]->descunread==0) {
@@ -202,22 +214,6 @@ class spool
                 }
             }
         }
-        
-        return true;
-    }
-
-    function save($file)
-    {
-        uasort($this->overview, "spoolcompare");
-
-        $this->roots = Array();
-        foreach($this->overview as $id=>$msg) {
-            if (is_null($msg->parent)) {
-                $this->roots[] = $id;
-            }
-        }
-        
-        file_put_contents($file, serialize($this));
     }
 
     /** kill post and childrens
@@ -232,8 +228,7 @@ class spool
             }
         }
         unset($this->overview[$_id]);
-        $msgid = array_search($_id, $this->ids);
-        if ($msgid) {
+        if (($msgid = array_search($_id, $this->ids)) !== false) {
             unset($this->ids[$msgid]);
         }
     }
@@ -272,9 +267,7 @@ class spool
                 unset($this->ids[$msgid]);
             }
             
-            if ($write) {
-                $this->save(dirname(dirname(__FILE__)).'/spool');
-            }
+            if ($write) { $this->_saveToFile(); }
         }
     }
 
@@ -310,43 +303,38 @@ class spool
             $us = ($_index == $_ref);
             $hc = empty($this->overview[$_id]->children);
 
-            echo '<tr class="'.($_index%2?$css["pair"]:$css["impair"])."\">\n";
-            echo "<td class=\"{$css['date']}\">"
-                .formatSpoolHeader("date", $this->overview[$_id]->date, $_id,
-                        $this->group, $us, $this->overview[$_id]->isread)
-                ." </td>\n";
-            echo "<td class=\"{$css['subject']}\"><div class=\"{$css['tree']}\">$_pfx_node"
-                .($hc?($_head?$spfx_f:($this->overview[$_id]->parent_direct?$spfx_s:$spfx_snd)):$spfx_n)
-                ."</div>"
-                .formatSpoolHeader("subject", $this->overview[$_id]->subject, $_id,
-                        $this->group, $us, $this->overview[$_id]->isread)
-                ." </td>\n";
-            echo "<td class=\"{$css['author']}\">"
-                .formatSpoolHeader("from", $this->overview[$_id]->from, $_id,
-                        $this->group, $us, $this->overview[$_id]->isread)
-                ." </td>\n</tr>";
-            if ($hc) {
-                return true;
+            echo '<tr class="'.($_index%2?$css["pair"]:$css["impair"]).($this->overview[$_id]->isread?'':' new')."\">\n";
+            echo "<td class=\"{$css['date']}\">".locale_header_date($this->overview[$_id]->date)." </td>\n";
+            echo "<td class=\"{$css['subject']}\">"
+                ."<div class=\"{$css['tree']}\">$_pfx_node".($hc?($_head?$spfx_f:($this->overview[$_id]->parent_direct?$spfx_s:$spfx_snd)):$spfx_n)
+                ."</div>";
+            if ($_index == $_ref) {
+                echo '<span class="isref">'.htmlentities($this->overview[$_id]->subject).'</span>';
+            } else {
+                echo "<a href='article.php?group={$this->group}&amp;id=$_id'>".htmlentities($this->overview[$_id]->subject).'</a>';
             }
+            echo "</td>\n<td class=\"{$css['author']}\">".formatFrom($this->overview[$_id]->from)."</td>\n</tr>";
+
+            if ($hc) { return; }
         } 
 
-        $index = $_index+1;
+        $_index ++;
 
         $children = $this->overview[$_id]->children;
         while ($child = array_shift($children)) {
-            if ($index > $_last) { return; }
-            if ($index+$this->overview[$child]->desc >= $_first) {
+            if ($_index > $_last) { return; }
+            if ($_index+$this->overview[$child]->desc >= $_first) {
                 if (sizeof($children)) {
-                    $this->disp_desc($child, $index, $_first, $_last, $_ref, $_pfx_end.
-                            ($this->overview[$child]->parent_direct?$spfx_T:$spfx_Tnd),
+                    $this->disp_desc($child, $_index, $_first, $_last, $_ref,
+                            $_pfx_end.($this->overview[$child]->parent_direct?$spfx_T:$spfx_Tnd),
                             $_pfx_end.$spfx_I, false);
                 } else {
-                    $this->disp_desc($child, $index, $_first, $_last, $_ref, $_pfx_end.
-                            ($this->overview[$child]->parent_direct?$spfx_L:$spfx_Lnd),
+                    $this->disp_desc($child, $_index, $_first, $_last, $_ref,
+                            $_pfx_end.($this->overview[$child]->parent_direct?$spfx_L:$spfx_Lnd),
                             $_pfx_end.$spfx_e, false);
                 }
             }
-            $index += $this->overview[$child]->desc;
+            $_index += $this->overview[$child]->desc;
         }
     }
 
@@ -363,9 +351,7 @@ class spool
             foreach ($this->roots as $id) {
                 $this->disp_desc($id, $index, $_first, $_last, $_ref);
                 $index += $this->overview[$id]->desc ;
-                if ($index > $_last) {
-                    break;
-                }
+                if ($index > $_last) { break; }
             }
         } else {
             echo "<tr class=\"{$css['pair']}\">\n";
index f0b9f0e..00449b3 100644 (file)
@@ -7,55 +7,6 @@
 * Copyright: See COPYING files that comes with this distribution
 ********************************************************************************/
 
-/** produces HTML output for overview
- * @param $_header STRING name of the header
- * @param $_text STRING value of the header
- * @param $_id INTEGER MSGNUM of message
- * @param $_group TEXT name of newsgroup
- * @param $_isref BOOLEAN emphasizes message in overview tree ?
- * @param $_isread BOOLEAN displays message as read ?
- * @return STRING HTML output
- * @see disp_desc
- */
-
-function formatSpoolHeader($_header,$_text,$_id,$_group,$_isref,$_isread=true) {
-  global $locale;
-  switch ($_header) {
-    case "date": 
-      return locale_header_date($_text);
-    case "from":
-#     From: mark@cbosgd.ATT.COM
-#     From: mark@cbosgd.ATT.COM (Mark Horton)
-#     From: Mark Horton <mark@cbosgd.ATT.COM>
-      $result = htmlentities($_text);
-      if (preg_match("/^([^ ]+)@([^ ]+)$/",$_text,$regs))
-        $result="<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;".
-          "{$regs[1]}&#64;{$regs[2]}\">".htmlentities($regs[1].
-          "&#64;".$regs[2])."</a>";
-      if (preg_match("/^([^ ]+)@([^ ]+) \((.*)\)$/",$_text,$regs))
-        $result="<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;".
-          "{$regs[1]}&#64;{$regs[2]}\">".htmlentities($regs[3])."</a>";
-      if (preg_match("/^\"?([^<>\"]+)\"? +<(.+)@(.+)>$/",$_text,$regs))
-        $result="<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;".
-          "{$regs[2]}&#64;{$regs[3]}\">".htmlentities($regs[1])."</a>";
-      return preg_replace("/\\\(\(|\))/","\\1",$result);
-    case "subject":
-      if ($_isref) {
-        return '<span class="isref">'.htmlentities($_text).'</span>';
-      } else {
-        if ($_isread) {
-          return "<a href=\"article.php?group=$_group&amp;id=$_id\">"
-          .htmlentities($_text)."</a>";
-        }else {
-          return "<a href=\"article.php?group=$_group&amp;id=$_id\"><b>"
-          .htmlentities($_text)."</b></a>";
-        }
-      }
-    default:
-      return htmlentities($_text);
-  }
-}
-
 /** produces HTML ouput for header section in post.php
  * @param $_header STRING name of the header
  * @param $_text STRING value of the header
@@ -64,128 +15,95 @@ function formatSpoolHeader($_header,$_text,$_id,$_group,$_isref,$_isread=true) {
  */
 
 function formatDisplayHeader($_header,$_text,$_spool) {
-  global $locale;
-  switch ($_header) {
-    case "date": 
-      return locale_date($_text);
-    case "followup":
-    case "newsgroups":
-      $res = "";
-      $groups = preg_split("/(\t| )*,(\t| )*/",$_text);
-      foreach ($groups as $g) {
-        $res.='<a href="thread.php?group='.$g.'">'.$g.'</a>, ';
-      }
-      return substr($res,0, -2);
-    case "from":
-#     From: mark@cbosgd.ATT.COM
-#     From: mark@cbosgd.ATT.COM (Mark Horton)
-#     From: Mark Horton <mark@cbosgd.ATT.COM>
-#     From: Anonymous <anonymous>
-      $result = htmlentities($_text);
-      if (preg_match("/^([^ ]+)@([^ ]+)$/",$_text,$regs))
-        $result="<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;"
-          ."{$regs[1]}&#64;{$regs[2]}\">".htmlentities($regs[1])
-          ."&#64;{$regs[2]}</a>";
-      if (preg_match("/^([^ ]+)@([^ ]+) \((.*)\)$/",$_text,$regs))
-        $result="<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;"
-          ."{$regs[1]}&#64;{$regs[2]}\">".htmlentities($regs[3])
-          ."</a>";
-      if (preg_match("/^\"?([^<>\"]+)\"? +<(.+)@(.+)>$/",$_text,$regs))
-        $result="<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;"
-          ."{$regs[2]}&#64;{$regs[3]}\">".htmlentities($regs[1])
-          ."</a>";
-      return preg_replace("/\\\(\(|\))/","\\1",$result);
-    case "references":
-      $rsl = "";
-      $ndx = 1;
-      $text=str_replace("><","> <",$_text);
-      $text=preg_split("/( |\t)/",strtr($text,$_spool->ids));
-      $parents=preg_grep("/^\d+$/",$text);
-      $p=array_pop($parents);
-      while ($p) {
-        $rsl .= "<a href=\"article.php?group={$_spool->group}"
-          ."&amp;id=$p\">$ndx</a> ";
-        $_spool->overview[$p]->desc++;
-        $p = $_spool->overview[$p]->parent;
-        $ndx++;
-      }
-      return $rsl;
-    case "xface":
-      return '<img src="xface.php?face='.base64_encode($_text)
-      .'"  alt="x-face" />';
-    default:
-      return htmlentities($_text);
-  }
-}
+    global $locale;
+    switch ($_header) {
+        case "date": 
+            return locale_date($_text);
+        
+        case "followup":
+            case "newsgroups":
+            $res = "";
+            $groups = preg_split("/(\t| )*,(\t| )*/",$_text);
+            foreach ($groups as $g) {
+                $res.='<a href="thread.php?group='.$g.'">'.$g.'</a>, ';
+            }
+            return substr($res,0, -2);
 
-/** produces HTML output for message body
- * @param $_text STRING message body
- * @return STRING HTML output
- */
-function formatbody($_text) {
-  global $news;
-  $res ="\n\n";
-  $res .= htmlentities(wrap($_text,"",$news['wrap']))."\n";
-  $res = preg_replace("/(&lt;|&gt;|&quot;)/"," \\1 ",$res);
-  $res = preg_replace('/(["\[])?((https?|ftp|news):\/\/[a-z@0-9.~%$£µ&i#\-+=_\/\?]*)(["\]])?/i',
-    "\\1<a href=\"\\2\">\\2</a>\\4", $res);
-  $res = preg_replace("/ (&lt;|&gt;|&quot;) /","\\1",$res);
-  return $res."\n";
+        case "from":
+            return formatFrom($_text);
+        
+        case "references":
+            $rsl = "";
+            $ndx = 1;
+            $text=str_replace("><","> <",$_text);
+            $text=preg_split("/( |\t)/",strtr($text,$_spool->ids));
+            $parents=preg_grep("/^\d+$/",$text);
+            $p=array_pop($parents);
+            while ($p) {
+                $rsl .= "<a href=\"article.php?group={$_spool->group}"
+                    ."&amp;id=$p\">$ndx</a> ";
+                $_spool->overview[$p]->desc++;
+                $p = $_spool->overview[$p]->parent;
+                $ndx++;
+            }
+            return $rsl;
+
+        case "xface":
+            return '<img src="xface.php?face='.base64_encode($_text)
+            .'"  alt="x-face" />';
+        
+        default:
+            return htmlentities($_text);
+    }
 }
 
 /** contextual links 
  * @return STRING HTML output
  */
 function displayshortcuts() {
-  global $news,$locale,$first,$spool,$group,$post,$id;
-  $sname = $_SERVER['SCRIPT_NAME'];
-  $array = explode('/',$sname);
-  $sname = array_pop($array);
+    global $news,$locale,$first,$spool,$group,$post,$id;
+    $sname = basename($_SERVER['SCRIPT_NAME']);
 
-  echo '<div class="shortcuts">';
-  echo '[<a href="disconnect.php">'.$locale['format']['disconnection']
-    .'</a>] ';
-  
-  switch ($sname) {
-    case 'thread.php' :
-      echo '[<a href="index.php">'.$locale['format']['grouplist']
+    echo '<div class="shortcuts">';
+    echo '[<a href="disconnect.php">'.$locale['format']['disconnection']
         .'</a>] ';
-      echo "[<a href=\"post.php?group=$group\">"
-        .$locale['format']['newpost']."</a>] ";
-      if (sizeof($spool->overview)>$news['max']) {
-        for ($ndx=1; $ndx<=sizeof($spool->overview); $ndx += $news['max']) {
-          if ($first==$ndx) {
-            echo "[$ndx-".min($ndx+$news['max']-1,sizeof($spool->overview))."] ";
-          } else {
-            echo "[<a href=\"".$_SERVER['PHP_SELF']."?group=$group&amp;first="
-           ."$ndx\">$ndx-".min($ndx+$news['max']-1,sizeof($spool->overview))
-            ."</a>] ";
-          }
-        }
-      }
-      break;
-    case 'article.php' :
-      echo '[<a href="index.php">'.$locale['format']['grouplist']
-        .'</a>] ';
-      echo "[<a href=\"thread.php?group=$group\">"
-        .$locale['format']['group_b'].$group
-        .$locale['format']['group_a']."</a>] ";
-      echo "[<a href=\"post.php?group=$group&amp;id=$id&amp;type=followup\">"
-        .$locale['format']['followup']."</a>] ";
-      if (checkcancel($post->headers)) {
-        echo "[<a href=\"article.php?group=$group&amp;id=$id&amp;type=cancel\">"
-        .$locale['format']['cancel']."</a>] ";
-      }
-      break;
-    case 'post.php' :
-      echo '[<a href="index.php">'.$locale['format']['grouplist']
-        .'</a>] ';
-      echo "[<a href=\"thread.php?group=$group\">"
-        .$locale['format']['group_b'].$group
-        .$locale['format']['group_a']."</a>] ";
-      break;
-  }
-  echo '</div>';
+
+    switch ($sname) {
+        case 'thread.php' :
+            echo '[<a href="index.php">'.$locale['format']['grouplist'].'</a>] ';
+            echo "[<a href=\"post.php?group=$group\">".$locale['format']['newpost']."</a>] ";
+            if (sizeof($spool->overview)>$news['max']) {
+                for ($ndx=1; $ndx<=sizeof($spool->overview); $ndx += $news['max']) {
+                    if ($first==$ndx) {
+                        echo "[$ndx-".min($ndx+$news['max']-1,sizeof($spool->overview))."] ";
+                    } else {
+                        echo "[<a href=\"".$_SERVER['PHP_SELF']."?group=$group&amp;first="
+                            ."$ndx\">$ndx-".min($ndx+$news['max']-1,sizeof($spool->overview))
+                            ."</a>] ";
+                    }
+                }
+            }
+            break;
+        case 'article.php' :
+            echo '[<a href="index.php">'.$locale['format']['grouplist'].'</a>] ';
+            echo "[<a href=\"thread.php?group=$group\">"
+                .$locale['format']['group_b'].$group
+                .$locale['format']['group_a']."</a>] ";
+            echo "[<a href=\"post.php?group=$group&amp;id=$id&amp;type=followup\">"
+                .$locale['format']['followup']."</a>] ";
+            if (checkcancel($post->headers)) {
+                echo "[<a href=\"article.php?group=$group&amp;id=$id&amp;type=cancel\">"
+                    .$locale['format']['cancel']."</a>] ";
+            }
+            break;
+        case 'post.php' :
+            echo '[<a href="index.php">'.$locale['format']['grouplist'].'</a>] ';
+            echo "[<a href=\"thread.php?group=$group\">"
+                .$locale['format']['group_b'].$group
+                .$locale['format']['group_a']."</a>] ";
+            break;
+    }
+    echo '</div>';
 }
 
 ?>