Rewritten banana spool structure for faster build and access
[banana.git] / banana / message.inc.php
index c83d17b..efe8f7a 100644 (file)
@@ -22,7 +22,7 @@ final class BananaMessage extends BananaMimePart
             if (isset($this->headers['in-reply-to']) && isset($this->headers['references'])) {
                 unset($this->headers['in-reply-to']);
             }
-            Banana::$show_hdr = array_intersect(Banana::$show_hdr, array_keys($this->headers));
+            Banana::$msgshow_headers = array_intersect(Banana::$msgshow_headers, array_keys($this->headers));
             Banana::$message =& $this;
         }
     }
@@ -36,7 +36,7 @@ final class BananaMessage extends BananaMimePart
     {
         $msg = new BananaMessage();
         $msg->msg_headers = $headers;
-        $msg->makeTextPart($body, 'text/plain', '8bits', 'UTF-8', 'fixed');
+        $msg->makeTextPart($body, 'text/plain', '8bits', 'UTF-8', 'flowed');
         if (!is_null($file)) {
             $msg->addAttachment($file);
         }
@@ -49,15 +49,15 @@ final class BananaMessage extends BananaMimePart
           case 'from':          return _b_('De');
           case 'subject':       return _b_('Sujet');
           case 'newsgroups':    return _b_('Forums');
-          case 'followup-to':   return _b_('Suivi à');
-          case 'to':            return _b_('À');
-          case 'cc':            return _b_('Copie à');
-          case 'bcc':           return _b_('Copie cachée à');
-          case 'reply-to':      return _b_('Répondre à');
+          case 'followup-to':   return _b_('Suivi à');
+          case 'to':            return _b_('À');
+          case 'cc':            return _b_('Copie à');
+          case 'bcc':           return _b_('Copie cachée à');
+          case 'reply-to':      return _b_('Répondre à');
           case 'date':          return _b_('Date');
           case 'organization':  return _b_('Organisation');
           case 'in-reply-to':
-          case 'references':    return _b_('Références');
+          case 'references':    return _b_('Références');
           case 'x-face':        return _b_('Image');
         }
         return $hdr;
@@ -87,7 +87,7 @@ final class BananaMessage extends BananaMimePart
             return substr($res,0, -2);
 
           case "from":
-            return BananaMessage::formatFrom($text);
+            return BananaMessage::formatFrom($text, $this->headers['subject']);
 
           case "references": case "in-reply-to":
             $rsl     = "";
@@ -107,12 +107,9 @@ final class BananaMessage extends BananaMimePart
             return $rsl;
 
           case "subject":
-            $link = null;
             $text = stripslashes($text);
-            if (function_exists('hook_getSubject')) {
-                $link = hook_getSubject($text);
-            }
-            return banana_catchFormats($text) . $link;
+            $text = banana_htmlentities($text);
+            return banana_catchFormats($text);
 
           default:
             return $text;
@@ -122,7 +119,7 @@ final class BananaMessage extends BananaMimePart
     public function getSender()
     {
         $from = $this->headers['from'];
-        $name = trim(preg_replace('/<[^ ]*>/', '', $from));
+        $name = trim(strip_tags($from));
         if (empty($name)) {
             return $from;
         }
@@ -137,6 +134,8 @@ final class BananaMessage extends BananaMimePart
         }
         if ($hdr == 'date') {
             return strtotime($this->headers['date']);
+        } else if ($hdr == 'references' || $hdr == 'reply-to') {
+            return str_replace('><', '> <', $this->headers[$hdr]);
         } else {
             return $this->headers[$hdr];
         }
@@ -144,40 +143,65 @@ final class BananaMessage extends BananaMimePart
 
     public function getHeaders()
     {
-        $this->msg_headers = array_merge($this->msg_headers, Banana::$custom_hdr, Banana::$profile['custom_hdr']);
+        $this->msg_headers = array_merge($this->msg_headers, Banana::$msgedit_headers, Banana::$profile['headers']);
         $headers = array_map(array($this, 'encodeHeader'), $this->msg_headers);
         return array_merge($headers, parent::getHeaders());
     }
 
-    static public function formatFrom($text)
+    static public function formatFrom($text, $subject = '')
     {
 #     From: mark@cbosgd.ATT.COM
 #     From: <mark@cbosgd.ATT.COM>
 #     From: mark@cbosgd.ATT.COM (Mark Horton)
 #     From: Mark Horton <mark@cbosgd.ATT.COM>
         $mailto = '<a href="mailto:';
-    
+
         $result = banana_htmlentities($text);
-        if (preg_match("/^([^ ]+@[^ ]+)$/", $text, $regs)) {
-            $result = $mailto . $regs[1] . '">' . banana_htmlentities($regs[1]) . '</a>';
+        if ($subject) {
+           $subject = '?subject=' . banana_htmlentities(_b_('Re: ') . $subject, ENT_QUOTES);
         }
-        if (preg_match("/^<(.+@.+)>$/", $text, $regs)) {
-            $result = $mailto . $regs[1] . '">' . banana_htmlentities($regs[1]) . '</a>';
+        if (preg_match("/^<?([^< ]+@[^> ]+)>?$/", $text, $regs)) {
+            $result = $mailto . $regs[1] . $subject . '">' . banana_htmlentities($regs[1]) . '</a>';
         }
         if (preg_match("/^([^ ]+@[^ ]+) \((.*)\)$/", $text, $regs)) {
-            $result = $mailto . $regs[1] . '">' . banana_htmlentities($regs[2]) . '</a>';
-        }   
+            $result = $mailto . $regs[1] . $subject . '">' . banana_htmlentities($regs[2]) . '</a>';
+        }
         if (preg_match("/^\"?([^<>\"]+)\"? +<(.+@.+)>$/", $text, $regs)) {
             $nom = preg_replace("/^'(.*)'$/", '\1', $regs[1]);
             $nom = stripslashes($nom);
-            $result = $mailto . $regs[2] . '">' . banana_htmlentities($nom) . '</a>';
+            $result = $mailto . $regs[2] . $subject . '">' . banana_htmlentities($nom) . '</a>';
         }
         return preg_replace("/\\\(\(|\))/","\\1",$result);
     }
 
+    public function getAuthorName()
+    {
+        $text = $this->getHeaderValue('From');
+        $name = null;
+        if (preg_match("/^([^ ]+@[^ ]+) \((.*)\)$/", $text, $regs)) {
+            $name = $regs[2];
+        }
+        if (preg_match("/^\"?([^<>\"]+)\"? +<(.+@.+)>$/", $text, $regs)) {
+            $name = preg_replace("/^'(.*)'$/", '\1', $regs[1]);
+            $name = stripslashes($name);
+        }
+        if ($name) {
+            return preg_replace("/\\\(\(|\))/","\\1", $name);
+        }
+
+        if (function_exists('hook_getAuthorName') && $name = hook_getAuthorName($this)) {
+            return $name;
+        }
+
+        if (preg_match("/([^< ]+)@([^> ]+)/", $text, $regs)) {
+            return $regs[1];
+        }
+        return 'Anonymous';
+    }
+
     static public function formatDate($text)
     {
-        return utf8_encode(strftime("%A %d %B %Y, %H:%M (fuseau serveur)", strtotime($text)));
+        return strftime("%A %d %B %Y, %H:%M (fuseau serveur)", strtotime($text));
     }
 
     public function translateHeaders()
@@ -204,25 +228,28 @@ final class BananaMessage extends BananaMimePart
         return BananaMessage::formatReferences($this->headers);
     }
 
-    static public function formatReferences(array &$refs)
+    static public function &formatReferences(array &$refs)
     {
-        if (isset($refs['references'])) {
-            $text = str_replace('><', '> <', $refs['references']);
-            return preg_split('/\s/', strtr($text, Banana::$spool->ids));
-        } elseif (isset($refs['in-reply-to'])) {
-            return array(Banana::$spool->ids[$refs['in-reply-to']]);
-        } else {
-            return array();
+        $references = array();
+        $msgs = Banana::$spool->getReferences($refs);
+        foreach ($msgs as &$msg) {
+            $references[] = $msg->id;
         }
+        return $references;
     }
 
     public function hasXFace()
     {
-        return Banana::$formatxface && isset($this->headers['x-face']);
+        return Banana::$msgshow_xface && 
+               ((function_exists('hook_hasxface') && hook_hasXFace($this->headers))
+               || isset($this->headers['x-face']));
     }
 
     public function getXFace()
     {
+        if (function_exists('hook_getxface') && hook_getXFace($this->headers)) {
+            return;
+        }
         header('Content-Type: image/gif');
         $xface = $this->headers['x-face'];
         passthru('echo ' . escapeshellarg($xface)
@@ -231,11 +258,11 @@ final class BananaMessage extends BananaMimePart
         exit;
     }
 
-    public function getFormattedBody($type = null)
+    public function getFormattedBody(&$reqtype = null)
     {
-        $types = Banana::$body_mime;
-        if (!is_null($type)) {
-            array_unshift($types, $type);
+        $types = Banana::$msgshow_mimeparts;
+        if (!is_null($reqtype)) {
+            array_unshift($types, $reqtype);
         }
         foreach ($types as $type) {
             @list($type, $subtype) = explode('/', $type);
@@ -243,25 +270,26 @@ final class BananaMessage extends BananaMimePart
             if (empty($parts)) {
                 continue;
             }
-            foreach ($parts as &$part) {
-                list($type, $subtype) = $part->getType();
-                switch ($subtype) {
-                  case 'html': return banana_formatHtml($part);
-                  case 'enriched': case 'richtext': return banana_formatRichText($part);
-                  default: return banana_formatPlainText($part);
-                }
-            }
+            $reqtype = implode('/', $parts[0]->getType());
+            return $parts[0]->toHtml();
         }
         return null;
     }
 
     public function quote()
     {
-        $part = $this->toPlainText();
-        if (is_null($part)) {
-            return banana_quoteHtml($this->toHtml());
+        foreach (Banana::$msgedit_mimeparts as $type) {
+            @list($type, $subtype) = explode('/', $type);
+            $parts = $this->getParts($type, $subtype);
+            if (empty($parts)) {
+                continue;
+            }
+            if ($parts[0] === $this) {
+                return parent::quote();
+            }
+            return $parts[0]->quote();
         }
-        return banana_quotePlainText($part);
+        return null;
     }
 
     public function canCancel()
@@ -272,14 +300,35 @@ final class BananaMessage extends BananaMimePart
         if (function_exists('hook_checkcancel')) {
             return hook_checkcancel($this->headers);
         }
-        return Banana::$profile['name'] == $this->headers['from'];
+        return Banana::$profile['headers']['From'] == $this->headers['from'];
     }
 
     public function canSend()
     {
         return Banana::$protocole->canSend();
     }
+
+    public function getSignature()
+    {
+        $email = $this->getHeaderValue('from');
+        if (preg_match('/<?([^ <]+@[^ >]+)>?/', $email, $matches)) {
+            $email = $matches[1];
+        }
+        $signature = BananaMimePart::getSignature();
+        if (empty($signature)) {
+            return $signature;
+        } else {
+            foreach ($signature['identity'] as $ident) {
+                if (strpos($ident, "<$email>") !== false) {
+                    return $signature;
+                }
+            }
+            $signature['certified'] = false;
+            $signature['certification_error'] = 'mauvaise identité';
+        }
+        return $signature;
+    }
 }
 
-// vim:set et sw=4 sts=4 ts=4:
+// vim:set et sw=4 sts=4 ts=4 enc=utf-8:
 ?>