Remove dead code.
[banana.git] / banana / spool.inc.php
index 1dfe3a3..015dd5d 100644 (file)
@@ -8,24 +8,28 @@
 ********************************************************************************/
 
 require_once dirname(__FILE__) . '/banana.inc.php';
+require_once dirname(__FILE__) . '/tree.inc.php';
 
-define('BANANA_SPOOL_VERSION', '0.5');
+define('BANANA_SPOOL_VERSION', '0.5.14');
 
 /** Class spoolhead
  *  class used in thread overviews
  */
 class BananaSpoolHead
 {
+    public $id;
+    public $msgid;
+
     /** date (timestamp) */
     public $date;
     /** subject */
     public $subject;
     /** author */
     public $from;
+    public $name;
+    public $color;
     /** reference of parent */
     public $parent = null;
-    /** paren is direct */
-    public $parent_direct;
     /** array of children */
     public $children = Array();
     /** true if post is read */
@@ -34,6 +38,8 @@ class BananaSpoolHead
     public $desc;
     /**  same as desc, but counts only unread posts */
     public $descunread;
+    /** last time the number of children has been updated */
+    public $time = 0;
 
     /** storage data */
     public $storage = array();
@@ -46,14 +52,31 @@ class BananaSpoolHead
      * @param $_read BOOLEAN true if read
      * @param $_descunread INTEGER descunread value (0 for a new post)
      */
-    public function __construct(array &$message)
+    public function __construct($id, array &$message)
     {
+        $this->id         = $id;
+        $this->msgid      = @$message['message-id'];
         $this->date       = $message['date'];
-        $this->subject    = $message['subject'];
+        $this->subject    = @$message['subject'];
         $this->from       = $message['from'];
+        $this->color      = sprintf('#%06x', abs(crc32($this->from) % 0xffffff));
         $this->desc       = 1;
         $this->isread     = true;
         $this->descunread = 0;
+        if (preg_match("/^([^ ]+@[^ ]+) \((.*)\)$/", $this->from, $regs)) {
+            $this->name = $regs[2];
+        }
+        if (preg_match("/^\"?([^<>\"]+)\"? +<(.+@.+)>$/", $this->from, $regs)) {
+            $this->name = preg_replace("/^'(.*)'$/", '\1', $regs[1]);
+            $this->name = stripslashes($this->name);
+        }
+        if ($this->name) {
+            $this->name =  preg_replace("/\\\(\(|\))/","\\1", $this->name);
+        } else if (preg_match("/([^< ]+)@([^> ]+)/", $this->from, $regs)) {
+            $this->name = $regs[1];
+        } else {
+            $this->name = 'Anonymous';
+        }
     }
 }
 
@@ -66,11 +89,12 @@ class BananaSpool
     /**  group name */
     public $group;
     /**  spool */
-    public $overview;
+    public $overview = array();
     /**  array msgid => msgnum */
-    public $ids;
+    public $ids      = array();
     /** thread starts */
-    public $roots;
+    public $roots    = array();
+
     /** protocole specific data */
     public $storage = array();
 
@@ -94,7 +118,7 @@ class BananaSpool
             $spool =& Banana::$spool;
         } else {
             $spool =& BananaSpool::readFromFile($group);
-        }        
+        }
         if (is_null($spool)) {
             $spool = new BananaSpool($group);
         }
@@ -107,19 +131,27 @@ class BananaSpool
         return $spool;
     }
 
-    private static function spoolFilename($group)
+    public static function getPath($file = null)
     {
-        $file = Banana::$spool_root . '/' . Banana::$protocole->name() . '/';
-        if (!is_dir($file)) {
-            mkdir($file);
+        $path = Banana::$spool_root . '/' . Banana::$protocole->name() . '/' . Banana::$protocole->filename();
+        if (!is_dir($path)) {
+            if (file_exists($path)) {
+                @unlink($path);
+            }
+            mkdir($path, 0777, true);
         }
-        return $file . Banana::$protocole->filename();
+        return $path . '/' . $file;
+    }
+
+    private static function spoolFilename()
+    {
+        return BananaSpool::getPath('spool');
     }
 
     private static function &readFromFile($group)
     {
         $spool = null;
-        $file = BananaSpool::spoolFilename($group);
+        $file = BananaSpool::spoolFilename();
         if (!file_exists($file)) {
             return $spool;
         }
@@ -132,26 +164,26 @@ class BananaSpool
         return $spool;
     }
 
-    private function compare($a, $b)
+    private function compare(&$a, &$b)
     {
-        return ($this->overview[$b]->date >= $this->overview[$a]->date);
+        return ($b->date - $a->date);
     }
 
     private function saveToFile()
     {
-        $file = BananaSpool::spoolFilename($this->group);
+        $file = BananaSpool::spoolFilename();
 
         $this->roots = Array();
-        foreach($this->overview as $id=>&$msg) {
+        foreach($this->overview as &$msg) {
             if (is_null($msg->parent)) {
-                $this->roots[] = $id;
+                $this->roots[] =& $msg;
             }
         }
         usort($this->roots, array($this, 'compare'));
 
         if ($this->mode == Banana::SPOOL_ALL) {
             file_put_contents($file, serialize($this));
-        }    
+        }
     }
 
     private function build()
@@ -173,16 +205,16 @@ class BananaSpool
         }
         $clean  = $this->clean($first, $last, $msgnum);
         $update = $this->update($first, $last, $msgnum);
-        
+
         if ($clean || $update) {
             $this->saveToFile();
         }
     }
-    
+
     private function clean(&$first, &$last, $msgnum)
     {
         $do_save = false;
-        if (is_array($this->overview)) {
+        if (!empty($this->overview)) {
             $mids = array_keys($this->overview);
             foreach ($mids as $id) {
                 if (($first <= $last && ($id < $first || $id > $last))
@@ -200,46 +232,45 @@ class BananaSpool
 
     private function update(&$first, &$last, $msgnum)
     {
-        if ($first > $last || !$msgnum) {       
+        if ($first > $last || !$msgnum) {
             return false;
         }
 
         $messages =& Banana::$protocole->getMessageHeaders($first, $last,
             array('Date', 'Subject', 'From', 'Message-ID', 'References', 'In-Reply-To'));
 
-        if (!is_array($this->ids)) {
-            $this->ids = array();
-        }
-        foreach ($messages as $id=>&$message) {
-            $this->ids[$message['message-id']] = $id;
-        }
-
-        if (!is_array($this->overview)) {
-            $this->overview = array();
-        }
+        // Build all the new Spool Heads
+        $time = time();
         foreach ($messages as $id=>&$message) {
             if (!isset($this->overview[$id])) {
-                $this->overview[$id] = new BananaSpoolHead($message);
+                $this->overview[$id] = new BananaSpoolHead($id, $message);
+                $head =& $this->overview[$id];
+                $this->ids[$head->msgid] =& $head;
+                $head->time = $time;
             }
-            $msg    =& $this->overview[$id];
-            $msgrefs = BananaMessage::formatReferences($message);
-            $parents = preg_grep('/^\d+$/', $msgrefs);
-            $msg->parent = array_pop($parents);
-            $msg->parent_direct = preg_match('/^\d+$/', array_pop($msgrefs));
-
-            if (!is_null($p = $msg->parent)) {
-                if (empty($this->overview[$p])) {
-                    $this->overview[$p] = new BananaSpoolHead($messages[$p]);
-                }
-                $this->overview[$p]->children[] = $id;
+        }
 
-                while (!is_null($p)) {
-                    $this->overview[$p]->desc += $msg->desc;
-                    if ($p != $this->overview[$p]->parent) {
-                        $p = $this->overview[$p]->parent;
+        // Build tree
+        $null = null;
+        foreach ($messages as $id=>&$message) {
+            $msg         =& $this->overview[$id];
+            $parents     =& $this->getReferences($message);
+            while (!empty($parents) && ($msg->parent === $msg || is_null($msg->parent))) {
+                @$msg->parent =& array_pop($parents);
+            }
+
+            if (!is_null($msg->parent)) {
+                $parent =& $msg->parent;
+                $parent->children[] =& $msg;
+                while (!is_null($parent)) {
+                    $parent->desc += $msg->desc;
+                    $parent->time  = $time;
+                    $prev =& $parent;
+                    if ($parent !== $parent->parent) {
+                        $parent =& $parent->parent;
                     } else {
-                        $p = null;
-                    }    
+                        $parent =& $null;
+                    }
                 }
             }
         }
@@ -259,21 +290,18 @@ class BananaSpool
             return;
         }
 
-        if (!is_array($this->ids)) {
-            $this->ids = array();
-        }
         $newpostsids = array_intersect($newpostsids, array_keys($this->ids));
         foreach ($newpostsids as $mid) {
-            $id = $this->ids[$mid];
-            if ($this->overview[$id]->isread) {
-                $this->overview[$id]->isread = false;
-                $this->unreadnb++;
-                while (isset($id)) {
-                    $this->overview[$id]->descunread++;
-                    $id = $this->overview[$id]->parent;
+            $overview =& $this->ids[$mid];
+            if ($overview->isread) {
+                $overview->isread = false;
+                while (!is_null($overview)) {
+                    $overview->descunread++;
+                    $overview =& $overview->parent;
                 }
             }
         }
+        $this->unreadnb += count($newpostsids);
     }
 
     public function setMode($mode)
@@ -281,27 +309,56 @@ class BananaSpool
         $this->mode = $mode;
         switch ($mode) {
           case Banana::SPOOL_UNREAD:
-            foreach ($this->roots as $k=>$i) {
-                if ($this->overview[$i]->descunread == 0) {
-                    $this->killdesc($i);
-                    unset($this->roots[$k]);
+            $num = max(array_keys($this->overview));
+            if ($this->overview[$num]->isread) {
+                break;
+            }
+            foreach ($this->roots as &$root) {
+                if ($root->descunread == 0) {
+                    $this->killdesc($root->id);
                 }
             }
             break;
         }
     }
 
+    /** Fetch list of references
+     */
+    public function &getReferences(array &$refs)
+    {
+        $references = array();
+        if (isset($refs['references'])) {
+            $text = preg_split('/\s/', str_replace('><', '> <', $refs['references']));
+            foreach ($text as $id=>&$value) {
+                if (isset($this->ids[$value])) {
+                    $references[] =& $this->ids[$value];
+                }
+            }
+        } elseif (isset($refs['in-reply-to']) && isset($this->ids[$refs['in-reply-to']])) {
+            $references[] =& $this->ids[$refs['in-reply-to']];
+        }
+        return $references;
+    }
+
+    /** Get the tree associated to a given id
+     */
+    public function &getTree($id)
+    {
+        return BananaTree::build($id)->show();
+    }
+
     /** Mark the given id as read
      * @param id MSGNUM of post
      */
     public function markAsRead($id)
     {
-        if (!$this->overview[$id]->isread) {
-            $this->overview[$id]->isread = true;
+        $overview =& $this->overview[$id];
+        if (!$overview->isread) {
+            $overview->isread = true;
             $this->unreadnb--;
-            while (isset($id)) {
-                $this->overview[$id]->descunread--;
-                $id = $this->overview[$id]->parent;
+            while (!is_null($overview)) {
+                $overview->descunread--;
+                $overview =& $overview->parent;
             }
         }
     }
@@ -313,20 +370,20 @@ class BananaSpool
         if (!$this->unreadnb) {
             return;
         }
-        if (is_null($array) && is_array($this->roots)) {
+        if (is_null($array) && !empty($this->roots)) {
             $array =& $this->roots;
         } elseif (is_null($array)) {
             return;
         }
-        foreach ($array as $id) {
-            if (!$this->overview[$id]->isread) {
-                $this->markAsRead($id);
+        foreach ($array as &$msg) {
+            if (!$msg->isread) {
+                $this->markAsRead($msg->id);
                 if (!$this->unreadnb) {
                     return;
                 }
             }
-            if ($this->overview[$id]->descunread) {
-                $this->markAllAsRead($this->overview[$id]->children);
+            if ($msg->descunread) {
+                $this->markAllAsRead($msg->children);
             }
         }
     }
@@ -336,15 +393,22 @@ class BananaSpool
      */
     private function killdesc($_id)
     {
-        if (sizeof($this->overview[$_id]->children)) {
-            foreach ($this->overview[$_id]->children as $c) {
-                $this->killdesc($c);
+        $overview =& $this->overview[$_id];
+        $children =& $overview->children;
+        if (sizeof($children)) {
+            foreach ($children as &$c) {
+                $this->killdesc($c->id);
             }
         }
         unset($this->overview[$_id]);
-        if (($msgid = array_search($_id, $this->ids)) !== false) {
-            unset($this->ids[$msgid]);
+        foreach ($this->roots as $k=>&$root) {
+            if ($root === $overview) {
+                unset($this->roots[$k]);
+                break;
+            }
         }
+        unset($this->ids[$overview->msgid]);
+        $overview = null;
     }
 
     /** delete a post from overview
@@ -352,50 +416,60 @@ class BananaSpool
      */
     public function delid($_id, $write = true)
     {
-        if (isset($this->overview[$_id])) {
-            $overview =& $this->overview[$_id];
-            if (!$overview->isread) {
-                $this->markAsRead($_id);
-            }
-            if ($overview->parent) {
-                $p      =  $overview->parent;
-                $parent =& $this->overview[$p];
-                $parent->children = array_diff($parent->children, array($_id));
-                if (sizeof($overview->children)) {
-                    $parent->children = array_merge($parent->children, $overview->children);
-                    foreach ($overview->children as $c) {
-                        $this->overview[$c]->parent        = $p;
-                        $this->overview[$c]->parent_direct = false;
-                    }
-                }
-                while (isset($p)) {
-                    $this->overview[$p]->desc--;
-                    $p = $this->overview[$p]->parent;
-                }
-            } elseif ($overview->children) {
-                foreach ($overview->children as $c) {
-                    $this->overview[$c]->parent = null;
+        if (!isset($this->overview[$_id])) {
+            return;
+        }
+
+        $overview =& $this->overview[$_id];
+        // Be sure it is not counted as unread
+        if (!$overview->isread) {
+            $this->markAsRead($_id);
+        }
+
+        $parent =& $overview->parent;
+
+        // Remove from the message tree
+        if (!is_null($parent)) {
+            foreach ($parent->children as $key=>&$child) {
+                if ($child === $overview) {
+                    unset($parent->children[$key]);
+                    break;
                 }
             }
-            unset($overview);
-            unset($this->overview[$_id]);
-            $msgid = array_search($_id, $this->ids);
-            if ($msgid !== false) {
-                unset($this->ids[$msgid]);
+            if (sizeof($overview->children)) {
+                $parent->children = array_merge($parent->children, $overview->children);
+                foreach ($overview->children as &$child) {
+                    $child->parent =& $parent;
+                }
             }
-            $msgid = array_search($_id, $this->roots);
-            if ($msgid !== false) {
-                unset($this->roots[$msgid]);
+            $time = time();
+            while (!is_null($parent)) {
+                $parent->desc--;
+                $parent->time = $time;
+                $parent =& $parent->parent;
             }
-            
-            if ($write) {
-                $this->saveToFile();
+        }
+
+        // Remove all refenrences and assign null to the object
+        unset($this->ids[$overview->msgid]);
+        unset($this->overview[$_id]);
+        BananaTree::kill($_id);
+        foreach ($this->roots as $k=>&$root) {
+            if ($root === $overview) {
+                unset($this->roots[$k]);
+                break;
             }
         }
+        $overview = null;
+
+        if ($write) {
+            $this->saveToFile();
+        }
     }
 
-    private function formatDate($stamp)
+    public function formatDate(BananaSpoolHead &$head)
     {
+        $stamp  = $head->date;
         $today  = intval(time() / (24*3600));
         $dday   = intval($stamp / (24*3600));
 
@@ -405,175 +479,64 @@ class BananaSpool
             $format = _b_('hier')." %H:%M";
         } elseif ($today < 7 + $dday) {
             $format = '%a %H:%M';
-        } else {
+        } elseif ($today < 90 + $dday) {
             $format = '%a %e %b';
+        } else {
+            $format = '%a %e %b %Y';
         }
         return strftime($format, $stamp);
     }
 
-    /** displays children tree of a post
-     * @param $_id INTEGER MSGNUM of post
-     * @param $_index INTEGER linear number of post in the tree
-     * @param $_first INTEGER linear number of first post displayed
-     * @param $_last INTEGER linear number of last post displayed
-     * @param $_ref STRING MSGNUM of current post 
-     * @param $_pfx_node STRING prefix used for current node
-     * @param $_pfx_end STRING prefix used for children of current node
-     * @param $_head BOOLEAN true if first post in thread
-     *
-     * If you want to analyse subject, you can define the function hook_formatDisplayHeader
-     */
-    private function _to_html($_id, $_index, $_first=0, $_last=0, $_ref="", $_pfx_node="", $_pfx_end="", $_head=true, $_pfx_id="")
-    {
-        static $spfx_f, $spfx_n, $spfx_Tnd, $spfx_Lnd, $spfx_snd, $spfx_T, $spfx_L, $spfx_s, $spfx_e, $spfx_I;
-        if (!isset($spfx_f)) {
-            $spfx_f   = Banana::$page->makeImg(Array('img' => 'k1',       'alt' => 'o', 'height' => 21,  'width' => 9)); 
-            $spfx_n   = Banana::$page->makeImg(Array('img' => 'k2',       'alt' => '*', 'height' => 21,  'width' => 9));
-            $spfx_Tnd = Banana::$page->makeImg(Array('img' => 'T-direct', 'alt' => '+', 'height' => 21, 'width' => 12));
-            $spfx_Lnd = Banana::$page->makeImg(Array('img' => 'L-direct', 'alt' => '`', 'height' => 21, 'width' => 12));
-            $spfx_snd = Banana::$page->makeImg(Array('img' => 's-direct', 'alt' => '-', 'height' => 21, 'width' => 5));
-            $spfx_T   = Banana::$page->makeImg(Array('img' => 'T',        'alt' => '+', 'height' => 21, 'width' => 12));
-            $spfx_L   = Banana::$page->makeImg(Array('img' => 'L',        'alt' => '`', 'height' => 21, 'width' => 12));
-            $spfx_s   = Banana::$page->makeImg(Array('img' => 's',        'alt' => '-', 'height' => 21, 'width' => 5));
-            $spfx_e   = Banana::$page->makeImg(Array('img' => 'e',   'alt' => '&nbsp;', 'height' => 21, 'width' => 12));
-            $spfx_I   = Banana::$page->makeImg(Array('img' => 'I',        'alt' => '|', 'height' => 21, 'width' => 12));
+    public function formatSubject(BananaSpoolHead &$head)
+    {
+        $subject = $popup = $head->subject;
+        $popup = $subject;
+        if (function_exists('hook_formatDisplayHeader')) {
+            list($subject, $link) = hook_formatDisplayHeader('subject', $subject, true);
+        } else {
+            $subject = banana_catchFormats(banana_entities(stripslashes($subject)));
+            $link = null;
         }
-
-        $overview =& $this->overview[$_id];
-        if ($_index + $overview->desc < $_first || $_index > $_last) {
-            return '';
+        if (empty($subject)) {
+            $subject = _b_('(pas de sujet)');
         }
-
-        $res = '';
-        if ($_index >= $_first) {
-            $hc = empty($overview->children);
-
-            $res .= '<tr id="'.$_pfx_id.$_id.'" class="' . ($_index%2 ? 'pair' : 'impair') . ($overview->isread ? '' : ' new') . "\">\n";
-            $res .= '<td class="date">' . $this->formatDate($overview->date) . " </td>\n";
-            $res .= '<td class="subj' . ($_index == $_ref ? ' cur' : '') . '"><div class="tree">'
-                . $_pfx_node .($hc ? ($_head ? $spfx_f : ($overview->parent_direct ? $spfx_s : $spfx_snd)) : $spfx_n)
-                . '</div>';
-            $subject = $overview->subject;
-            if (function_exists('hook_formatDisplayHeader')) {
-                list($subject, $link) = hook_formatDisplayHeader('subject', $subject, true);
-            } else {
-                $subject = banana_catchFormats(banana_htmlentities(stripslashes($subject)));
-                $link = null;
-            }
-            if (empty($subject)) {
-                $subject = _b_('(pas de sujet)');
-            }
-            if ($_index != $_ref) {
-                $subject = Banana::$page->makeLink(Array('group' => $this->group, 'artid' => $_id,
-                                                    'text'  => $subject, 'popup' => $subject));
-            }
-            $res .= '&nbsp;' . $subject . $link;
-            $res .= "</td>\n<td class='from'>" . BananaMessage::formatFrom($overview->from) . "</td>\n</tr>";
-
-            if ($hc) {
-                return $res;
-            }
-        } 
-
-        $_index ++;
-        $children = $overview->children;
-        while ($child = array_shift($children)) {
-            $overview =& $this->overview[$child];
-            if ($_index > $_last) {
-                return $res;
-            }
-            if ($_index + $overview->desc >= $_first) {
-                if (sizeof($children)) {
-                    $res .= $this->_to_html($child, $_index, $_first, $_last, $_ref,
-                            $_pfx_end . ($overview->parent_direct ? $spfx_T : $spfx_Tnd),
-                            $_pfx_end . $spfx_I, false,$_id.'_');
-                } else {
-                    $res .= $this->_to_html($child, $_index, $_first, $_last, $_ref,
-                            $_pfx_end . ($overview->parent_direct ? $spfx_L : $spfx_Lnd),
-                            $_pfx_end . $spfx_e, false,$_id.'_');
-                }
-            }
-            $_index += $overview->desc;
+        if ($head->id != Banana::$artid) {
+            $subject = Banana::$page->makeLink(Array('group' => $this->group, 'artid' => $head->id,
+                                                     'text'  => $subject, 'popup' => $popup));
         }
-
-        return $res;
+        return $subject . $link;
     }
 
-    /** Displays overview
-     * @param $_first INTEGER MSGNUM of first post
-     * @param $_last INTEGER MSGNUM of last post
-     * @param $_ref STRING MSGNUM of current/selectionned post
-     */
-    public function toHtml($first = 0, $overview = false)
+    public function formatFrom(BananaSpoolHead &$head)
     {
-        $res = Banana::$page->makeJs('jquery');
-        $res .= Banana::$page->makeJs('spool_toggle');
+        return BananaMessage::formatFrom($head->from);
+    }
 
-        if (!$overview) {
-            $_first = $first;
-            $_last  = $first + Banana::$spool_tmax - 1;
-            $_ref   = null;
+    public function start()
+    {
+        if (Banana::$first) {
+            return Banana::$first;
         } else {
-            $_ref   = $this->getNdx($first);
-            $_last  = $_ref + Banana::$spool_tafter;
-            $_first = $_ref - Banana::$spool_tbefore;
-            if ($_first < 0) {
-                $_last -= $_first;
-            }
-        }
-        $index = 1;
-        foreach ($this->roots as $id) {
-            $res   .= $this->_to_html($id, $index, $_first, $_last, $_ref);
-            $index += $this->overview[$id]->desc ;
-            if ($index > $_last) {
-                break;
-            }
+            $first = array_search(Banana::$artid, $this->roots);
+            return max(0, $first - Banana::$spool_tbefore);
         }
-        return $res;
     }
 
-    /** computes linear post index
-     * @param $_id INTEGER MSGNUM of post
-     * @return INTEGER linear index of post
-     */
-    public function getNdX($_id)
+    public function context()
     {
-        $ndx    = 1;
-        $id_cur = $_id;
-        while (true) {
-            $id_parent = $this->overview[$id_cur]->parent;
-            if (is_null($id_parent)) break;
-            $pos       = array_search($id_cur, $this->overview[$id_parent]->children);
-        
-            for ($i = 0; $i < $pos ; $i++) {
-                $ndx += $this->overview[$this->overview[$id_parent]->children[$i]]->desc;
-            }
-            $ndx++; //noeud père
-
-            $id_cur = $id_parent;
-        }
-
-        foreach ($this->roots as $i) {
-            if ($i==$id_cur) {
-                break;
-            }
-            $ndx += $this->overview[$i]->desc;
-        }
-        return $ndx;
+        return Banana::$first ? Banana::$spool_tmax : Banana::$spool_tcontext;
     }
 
     /** Return root message of the given thread
      * @param id INTEGER id of a message
      */
-    public function root($id)
+    public function &root($id)
     {
-        $id_cur = $id;
-        while (true) {
-            $id_parent = $this->overview[$id_cur]->parent;
-            if (is_null($id_parent)) break;
-            $id_cur = $id_parent;
+        $parent =& $this->overview[$id];
+        while (!is_null($parent->parent)) {
+            $parent =& $parent->parent;
         }
-        return $id_cur;
+        return $parent;
     }
 
     /** Return the last post id with the given subject
@@ -607,13 +570,13 @@ class BananaSpool
      */
     public function prevThread($id)
     {
-        $root = $this->root($id);
+        $root =& $this->root($id);
         $last = null;
-        foreach ($this->roots as $i) {
-            if ($i == $root) {
+        foreach ($this->roots as &$i) {
+            if ($i === $root) {
                 return $last;
             }
-            $last = $i;
+            $last = $i->id;
         }
         return $last;
     }
@@ -623,13 +586,13 @@ class BananaSpool
      */
     public function nextThread($id)
     {
-        $root = $this->root($id);
+        $root =& $this->root($id);
         $ok   = false;
-        foreach ($this->roots as $i) {
+        foreach ($this->roots as &$i) {
             if ($ok) {
-                return $i;
+                return $i->id;
             }
-            if ($i == $root) {
+            if ($i === $root) {
                 $ok = true;
             }
         }
@@ -641,16 +604,16 @@ class BananaSpool
      */
     public function prevPost($id)
     {
-        $parent = $this->overview[$id]->parent;
+        $parent =& $this->overview[$id]->parent;
         if (is_null($parent)) {
             return null;
         }
-        $last = $parent;
-        foreach ($this->overview[$parent]->children as $child) {
-            if ($child == $id) {
+        $last = $parent->id;
+        foreach ($parent->children as &$child) {
+            if ($child->id == $id) {
                 return $last;
             }
-            $last = $child;
+            $last = $child->id;
         }
         return null;
     }
@@ -660,26 +623,27 @@ class BananaSpool
      */
     public function nextPost($id)
     {
-        if (count($this->overview[$id]->children) != 0) {
-            return $this->overview[$id]->children[0];
+        $cur =& $this->overview[$id];
+        if (count($cur->children) != 0) {
+            return $cur->children[0]->id;
         }
-        
-        $cur    = $id;
+
+        $parent =& $cur;
         while (true) {
-            $parent = $this->overview[$cur]->parent;
+            $parent =& $cur->parent;
             if (is_null($parent)) {
                 return null;
             }
             $ok = false;
-            foreach ($this->overview[$parent]->children as $child) {
+            foreach ($parent->children as &$child) {
                 if ($ok) {
-                    return $child;
+                    return $child->id;
                 }
-                if ($child == $cur) {
+                if ($child === $cur) {
                     $ok = true;
                 }
             }
-            $cur = $parent;
+            $cur =& $parent;
         }
         return null;
     }
@@ -687,16 +651,16 @@ class BananaSpool
     /** Look for an unread message in the thread rooted by the message
      * @param id INTEGER message number
      */
-    private function _nextUnread($id)
+    private function _nextUnread(BananaSpoolHead &$cur)
     {
-        if (!$this->overview[$id]->isread) {
-            return $id;
+        if (!$cur->isread) {
+            return $cur->id;
         }
-        foreach ($this->overview[$id]->children as $child) {
+        foreach ($cur->children as &$child) {
             $unread = $this->_nextUnread($child);
             if (!is_null($unread)) {
                 return $unread;
-            }    
+            }
         }
         return null;
     }
@@ -712,7 +676,7 @@ class BananaSpool
 
         if (!is_null($id)) {
             // Look in message children
-            foreach ($this->overview[$id]->children as $child) {
+            foreach ($this->overview[$id]->children as &$child) {
                 $next = $this->_nextUnread($child);
                 if (!is_null($next)) {
                     return $next;
@@ -721,31 +685,39 @@ class BananaSpool
         }
 
         // Look in current thread
-        $cur = $id;
+        if (is_null($id)) {
+            $cur = null;
+        } else {
+            $cur =& $this->overview[$id];
+        }
         do {
-            $parent = is_null($cur) ? null : $this->overview[$cur]->parent;
-            $ok     = is_null($cur) ? true : false;
+            if (is_null($cur)) {
+                $parent =& $cur;
+                $ok     = true;
+            } else {
+                $parent =& $cur->parent;
+                $ok     =  false;
+            }
             if (!is_null($parent)) {
-                $array = &$this->overview[$parent]->children;
+                $array =& $parent->children;
             } else {
-                $array = &$this->roots;
+                $array =$this->roots;
             }
-            foreach ($array as $child) {
+            foreach ($array as &$child) {
                 if ($ok) {
                     $next = $this->_nextUnread($child);
                     if (!is_null($next)) {
                         return $next;
                     }
                 }
-                if ($child == $cur) {
+                if ($child === $cur) {
                     $ok = true;
                 }
             }
-            $cur = $parent;
+            $cur =& $parent;
         } while(!is_null($cur));
         return null;
-    }    
+    }
 }
-
 // vim:set et sw=4 sts=4 ts=4 enc=utf-8:
 ?>