Use Banana to preview the mails for ML moderation
authorx2003bruneau <x2003bruneau@839d8a87-29fc-0310-9880-83ba4fa771e5>
Sun, 14 Jan 2007 18:28:31 +0000 (18:28 +0000)
committerx2003bruneau <x2003bruneau@839d8a87-29fc-0310-9880-83ba4fa771e5>
Sun, 14 Jan 2007 18:28:31 +0000 (18:28 +0000)
git-svn-id: svn+ssh://murphy/home/svn/platal/trunk@1333 839d8a87-29fc-0310-9880-83ba4fa771e5

include/banana/forum.inc.php [new file with mode: 0644]
include/banana/hooks.inc.php [new file with mode: 0644]
include/banana/moderate.inc.php [new file with mode: 0644]
modules/banana.php
templates/lists/moderate_mail.tpl

diff --git a/include/banana/forum.inc.php b/include/banana/forum.inc.php
new file mode 100644 (file)
index 0000000..ca845dd
--- /dev/null
@@ -0,0 +1,155 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2007 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+require_once 'banana/banana.inc.php';
+require_once 'banana/hooks.inc.php';
+
+function hook_checkcancel($_headers)
+{
+    return ($_headers['x-org-id'] == S::v('forlife') or S::has_perms());
+}
+
+function hook_makeLink($params)
+{
+    global $globals;
+    $base = $globals->baseurl . '/banana';
+    if (isset($params['page'])) {
+        return $base . '/' . $params['page'];
+    }
+    if (@$params['action'] == 'subscribe') {
+        return $base . '/subscription';
+    }
+
+    if (!isset($params['group'])) {
+        return $base;
+    }
+    $base .= '/' . $params['group'];
+
+    return $base . hook_platalMessageLink($params);
+}
+
+class PlatalForums extends Banana
+{
+    function __construct($params = null)
+    {
+        global $globals;
+        Banana::$msgedit_canattach = false;
+        array_push(Banana::$msgparse_headers, 'x-org-id', 'x-org-mail');
+        Banana::$nntp_host = 'news://web_'.S::v('forlife')
+                           . ":{$globals->banana->password}@{$globals->banana->server}:{$globals->banana->port}/";
+        parent::__construct($params);
+    }
+
+    public function run()
+    {
+        global $platal, $globals;
+
+        // Update last unread time
+        $time = null;
+        if (!is_null($this->params) && isset($this->params['updateall'])) {
+            $time = intval($this->params['updateall']);
+            $_SESSION['banana_last']     = $time;
+        }
+
+        // Get user profile from SQL
+        $req = XDB::query("SELECT  nom, mail, sig,
+                                   FIND_IN_SET('threads',flags), FIND_IN_SET('automaj',flags)
+                             FROM  {$globals->banana->table_prefix}profils
+                            WHERE  uid={?}", S::i('uid'));
+        if (!(list($nom,$mail,$sig,$disp,$maj) = $req->fetchOneRow())) {
+            $nom  = S::v('prenom')." ".S::v('nom');
+            $mail = S::v('forlife')."@polytechnique.org";
+            $sig  = $nom." (".S::v('promo').")";
+            $disp = 0;
+            $maj  = 1;
+        }
+        if ($maj) {
+            $time = time();
+        }
+
+        // Build user profile
+        $req = XDB::query("      
+                 SELECT  nom     
+                   FROM  {$globals->banana->table_prefix}abos
+              LEFT JOIN  {$globals->banana->table_prefix}list ON list.fid=abos.fid
+                  WHERE  uid={?}", S::i('uid'));
+        Banana::$profile['headers']['From']         = utf8_encode("$nom <$mail>");
+        Banana::$profile['headers']['Organization'] = 'Utilisateur de Polytechnique.org';
+        Banana::$profile['signature']               = utf8_encode($sig);
+        Banana::$profile['display']                 = $disp;
+        Banana::$profile['autoup']                  = $maj;
+        Banana::$profile['lastnews']                = S::v('banana_last');
+        Banana::$profile['subscribe']               = $req->fetchColumn();
+
+        // Update the "unread limit" 
+        if (!is_null($time)) {
+            XDB::execute("UPDATE  auth_user_quick
+                             SET  banana_last = FROM_UNIXTIME({?})
+                           WHERE  user_id={?}",
+                         $time, S::i('uid'));
+        }
+
+        // Register custom Banana links and tabs
+        if (!Banana::$profile['autoup']) {
+            Banana::$page->registerAction('<a href=\'javascript:dynpostkv("'
+                                . $platal->path . '", "updateall", ' . time() . ')\'>'
+                                . 'Marquer tous les messages comme lus'
+                                . '</a>', array('forums', 'thread', 'message'));
+        }   
+        Banana::$page->registerPage('profile', utf8_encode('Préférences'), null);
+        
+
+        // Run Banana
+        return parent::run();
+    }
+
+    protected function action_saveSubs($groups)
+    {
+        global $globals;
+        $uid = S::v('uid');
+
+        Banana::$profile['subscribe'] = array();
+        XDB::execute("DELETE FROM {$globals->banana->table_prefix}abos WHERE uid={?}", $uid);
+        if (!count($groups)) {
+            return true;
+        }
+
+        $req  = XDB::iterRow("SELECT fid,nom FROM {$globals->banana->table_prefix}list");
+        $fids = array();
+        while (list($fid,$fnom) = $req->next()) {
+            $fids[$fnom] = $fid;
+        }
+
+        $diff = array_diff($groups, array_keys($fids));
+        foreach ($diff as $g) {
+            XDB::execute("INSERT INTO {$globals->banana->table_prefix}list (nom) VALUES ({?})", $g);
+            $fids[$g] = XDB::insertId();
+        }
+
+        foreach ($groups as $g) {
+            XDB::execute("INSERT INTO {$globals->banana->table_prefix}abos (fid,uid) VALUES ({?},{?})",
+                         $fids[$g], $uid);
+            Banana::$profile['subscribe'][] = $g;
+        }
+    }
+}
+
+?>
diff --git a/include/banana/hooks.inc.php b/include/banana/hooks.inc.php
new file mode 100644 (file)
index 0000000..6cc035c
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2007 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+require_once 'banana/banana.inc.php';
+
+function hook_formatDisplayHeader($_header, $_text, $in_spool = false)
+{
+    switch ($_header) {
+      case 'from': case 'to': case 'cc': case 'reply-to':
+        $addresses = preg_split("/ *, */", $_text);
+        $text = '';
+        foreach ($addresses as $address) {
+            $address = BananaMessage::formatFrom(trim($address));
+            if ($_header == 'from') {
+                if ($id = Banana::$message->getHeaderValue('x-org-id')) {
+                    return $address . ' <a href="profile/' . $id . '" class="popup2" title="' . $id . '">'
+                        . '<img src="images/icons/user_suit.gif" title="fiche" alt="" /></a>';
+                } elseif ($id = Banana::$message->getHeaderValue('x-org-mail')) {
+                    list($id, $domain) = explode('@', $id);
+                    return $address . ' <a href="profile/' . $id . '" class="popup2" title="' . $id . '">'
+                        . '<img src="images/icons/user_suit.gif" title="fiche" alt="" /></a>';
+                } else {
+                    return $address;
+                }    
+            }
+            if (!empty($text)) {
+                $text .= ', ';
+            }
+            $text .= $address;
+        }
+        return $text;
+
+      case 'subject':
+        $link = null;
+        $text = stripslashes($_text);
+        if (preg_match('/^(.+?)\s*\[=> (.*?)\]\s*$/u', $text, $matches)) {
+            $text = $matches[1];
+            $group = $matches[2];
+            if (Banana::$group == $group) {
+                $link = ' [=>&nbsp;' . $group . ']';
+            } else {
+                $link = ' [=>&nbsp;' . Banana::$page->makeLink(array('group' => $group, 'text' => $group)) . ']';
+            }
+        }
+        $text = banana_catchFormats(banana_htmlentities($text));
+        if ($in_spool) {
+            return array($text, $link);
+        }
+        return $text . $link;
+    }
+    return null;
+}
+
+function hook_platalMessageLink($params)
+{
+    $base = '';
+    if (isset($params['first'])) {
+        return $base . '/from/' . $params['first'];
+    }
+    if (isset($params['artid'])) {
+        if (@$params['part'] == 'xface') {
+            $base .= '/xface';
+        } elseif (@$params['action'] == 'new') {
+            $base .= '/reply';
+        } elseif (@$params['action'] == 'cancel') {
+            $base .= '/cancel';
+        } else {
+            $base .= '/read';
+        }
+        if (isset($params['part']) && $params['part'] != 'xface') {
+            return $base . '/' . $params['artid'] . '?part=' . urlencode($params['part']);
+        } else {
+            return $base . '/' . $params['artid'];
+        }
+    }
+
+    if (@$params['action'] == 'new') {
+        return $base . '/new';
+    }
+    return $base;
+}
+
+function hook_makeImg($img, $alt, $height, $width)
+{
+    $url = 'images/banana/' . $img;
+
+    if (!is_null($width)) {
+        $width = ' width="' . $width . '"';
+    }
+    if (!is_null($height)) {
+        $height = ' height="' . $height . '"';
+    }
+
+    return '<img src="' . $url . '"' . $height . $width . ' alt="' . $alt . '" />';
+}
+
+?>
diff --git a/include/banana/moderate.inc.php b/include/banana/moderate.inc.php
new file mode 100644 (file)
index 0000000..0faf662
--- /dev/null
@@ -0,0 +1,239 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2007 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+require_once 'banana/banana.inc.php';
+require_once 'banana/hooks.inc.php';
+
+function hook_checkcancel($_headers)
+{
+    return ($_headers['x-org-id'] == S::v('forlife') or S::has_perms());
+}
+
+function hook_makeLink($params)
+{
+    global $platal, $globals;
+    $base = $globals->baseurl . '/' . $platal->ns . '/lists/moderate/' . ModerationBanana::$listname . '?';
+    $get = '';
+    foreach ($params as $key=>$value) {
+        if ($key == 'artid') {
+            $key = 'mid';
+        }
+        if ($key == 'group') {
+            continue;
+        }
+        if ($key == 'action') {
+            continue;
+        }
+        if (!empty($get)) {
+            $get .= '&';
+        }
+        $get .= $key . '=' . $value;
+    }
+    return $base . $get;
+}
+
+class ModerationBanana extends Banana
+{
+    static public $listname;
+    static public $domain;
+    static public $client;
+
+    function __construct($params = null, &$client)
+    {
+        global $globals;
+        ModerationBanana::$client = $client;
+        ModerationBanana::$listname = $params['listname'];
+        ModerationBanana::$domain = isset($params['domain']) ? $params['domain'] : $globals->mail->domain;
+        $params['group'] = ModerationBanana::$listname . '@' . ModerationBanana::$domain;
+        Banana::$spool_boxlist = false;
+        Banana::$msgshow_withthread = false;
+        Banana::$withtabs      = false;
+        array_push(Banana::$msgparse_headers, 'x-org-id', 'x-org-mail');
+        parent::__construct($params, 'MLInterface', 'ModerationPage');
+    }
+}
+
+require_once('banana/page.inc.php');
+
+class ModerationPage extends BananaPage
+{
+    protected function prepare()
+    {
+        $this->killPage('subscribe');
+        $this->killPage('forums');
+        $this->assign('noactions', true);
+        return parent::prepare();
+    }
+
+    public function trig($msg)
+    {
+        global $page;
+        if ($page) {
+            $page->trig(utf8_decode($msg));
+        }
+        return true;
+    }
+}
+
+require_once('banana/protocoleinterface.inc.php');
+require_once('banana/message.inc.php');
+
+class BananaMLInterface implements BananaProtocoleInterface
+{
+    private $infos; //(list, addr, host, desc, info, diff, ins, priv, sub, own, nbsub)
+    private $helds; //(id, sender, size, subj, date)
+
+    public function __construct()
+    {
+        $this->infos = ModerationBanana::$client->get_members(ModerationBanana::$listname); 
+        $this->infos = $this->infos[0];
+        
+        $mods = ModerationBanana::$client->get_pending_ops(ModerationBanana::$listname);
+        $this->helds = $mods[1];
+    }
+    
+    public function isValid()
+    {
+        return !is_null(ModerationBanana::$client);
+    }
+    
+    public function lastErrNo()
+    {
+        return 0;
+    }
+    
+    public function lastError()
+    {
+        return null;
+    }
+
+    public function getDescription()
+    {
+        return $this->infos['desc'];
+    }
+
+    public function getBoxList($mode = Banana::BOXES_ALL, $since = 0, $withstats = false)
+    {
+        return array(Banana::$group => Array(
+                        'desc' => $this->infos['desc'],
+                        'msgnum' => count($this->helds),
+                        'unread' => count($this->helds)));
+    }
+
+    public function &getMessage($id)
+    {
+        $message = null;
+        $msg = ModerationBanana::$client->get_pending_mail(ModerationBanana::$listname, $id, 1);
+        if ($msg) {
+            $message = new BananaMessage($msg);
+        }
+        return $message;
+    }
+
+    public function getMessageSource($id)
+    {
+        return ModerationBanana::$client->get_pending_mail(ModerationBanana::$listname, $id, 1);
+    }
+
+    public function getIndexes()
+    {
+        $ids = array();
+        foreach ($this->helds as &$desc) {
+            $ids[] = intval($desc['id']);
+        }
+        sort($ids);
+        return array(count($ids), min($ids), max($ids));
+    }
+
+    public function &getMessageHeaders($firstid, $lastid, array $msg_headers = array())
+    {
+        $conv = array('from' => 'sender', 'subject' => 'subj', 'date' => 'stamp', 'message-id' => 'id');
+        $headers = array();
+        foreach ($msg_headers as $hdr) {
+            $hdr = strtolower($hdr);
+            $mlhdr = isset($conv[$hdr]) ? $conv[$hdr] : $hdr;
+            foreach ($this->helds as &$desc) {
+                $id = intval($desc['id']);
+                if (!isset($headers[$id])) {
+                    $headers[$id] = array();
+                }
+                if ($mlhdr == 'id') {
+                    $headers[$id][$hdr] = $desc['stamp'] . '$' . $desc['id'] . '@' . Banana::$group;
+                } else {
+                    $headers[$id][$hdr] = isset($desc[$mlhdr]) ? banana_html_entity_decode($desc[$mlhdr]) : null;
+                }
+            }
+        }
+        return $headers;
+    }
+
+    public function updateSpool(array &$messages) { }
+
+    public function getNewIndexes($since)
+    {
+        $ids = array();
+        foreach ($this->helds as &$desc) {
+            if ($desc['stamp'] > $since) {
+                $ids[] = intval($desc['id']);
+            }
+        }
+        sort($ids);
+        return $ids;
+    }
+
+    public function canSend()
+    {
+        return false;
+    }
+
+    public function canCancel()
+    {
+        return false;
+    }
+
+    public function requestedHeaders()
+    {
+        return array();
+    }
+
+    public function send(BananaMessage &$message)
+    {
+        return true;
+    }
+
+    public function cancel(BananaMessage &$message)
+    {
+        return true;
+    }
+
+    public function name()
+    {
+        return 'MLModeration';
+    }
+
+    public function filename()
+    {
+        return ModerationBanana::$domain . '_' . ModerationBanana::$listname;
+    }
+}
+
+// vim:set et sw=4 sts=4 ts=4:
+?>
index b7cbfbd..9a1ebca 100644 (file)
@@ -149,9 +149,9 @@ class BananaModule extends PLModule
         $page->addCssLink('banana.css');
         $page->assign('xorg_title','Polytechnique.org - Forums & PA');
 
-        require_once dirname(__FILE__).'/banana/banana.inc.php';
+        require_once 'banana/forum.inc.php';
 
-        $banana = new PlatalBanana($params);
+        $banana = new PlatalForums($params);
         $res = $banana->run();
         $page->assign_by_ref('banana', $banana);
         $page->assign('banana_res', $res);
index 4cded5d..5604eb3 100644 (file)
 {include file="lists/header_listes.tpl"}
 
 <h1>
-  Propriétés du mail en attente
-</h1>
-
-<table class='tinybicol' cellpadding='0' cellspacing='0'>
-  <tr>
-    <td class='titre'>émetteur</td>
-    <td>{mailto address=$mail.sender}</td>
-  </tr>
-  <tr>
-    <td class='titre'>sujet</td>
-    <td>{$mail.subj|hdc}</td>
-  </tr>
-  <tr>
-    <td class='titre'>taille</td>
-    <td>{$mail.size} octets</td>
-  </tr>
-  <tr>
-    <td class='titre'>date</td>
-    <td>{$mail.stamp|date_format:"%X le %x"}</td>
-  </tr>
-</table>
-
-<h1>
   Contenu du mail en attente
 </h1>
 
-{if $mail.parts_plain|@count}
-<table class='bicol' cellpadding='0' cellspacing='0'>
-  {foreach from=$mail.parts_plain item=part key=i}
-  <tr><th>Partie n°{$i}</th></tr>
-  <tr class='{cycle values="impair,pair"}'>
-    <td><tt>{$part|qpd|nl2br}</tt></td>
-  </tr>
-  {/foreach}
-</table>
-<br />
-{/if}
-
-{if $mail.parts_html|@count}
-<table class='bicol' cellpadding='0' cellspacing='0'>
-  {foreach from=$mail.parts_html item=part key=i}
-  <tr><th>Partie n°{$i} (Le texte original est formaté en HTML)</th></tr>
-  <tr class='{cycle values="impair,pair"}'>
-    <td><tt>{$part|qpd|clean_html|nl2br}</tt></td>
-  </tr>
-  {/foreach}
-</table>
-<br />
-{/if}
+{$mail|smarty:nodefaults}
 
 <form method='post' action='{$platal->pl_self(1)}'>
   <table class='tinybicol' cellpadding='0' cellspacing='0'>