=?utf-8?q?Ajout=20de=20:
authorx2003bruneau <x2003bruneau@9869982d-c50d-0410-be91-f2a2ec7c7c7b>
Mon, 27 Feb 2006 12:39:29 +0000 (12:39 +0000)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Fri, 4 Jan 2008 23:34:30 +0000 (00:34 +0100)
=20*=20support=20succint=20des=20messages=20multipart=20(pas=20pour=20l'instant=20de=20distinction=20entre=20les=20types=20de=20multipart)
=20*=20support=20des=20pi=C3=83=C5=A1ces=20jointes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

git-svn-id: svn+ssh://murphy/home/svn/banana/trunk@3 9869982d-c50d-0410-be91-f2a2ec7c7c7b

banana/banana.inc.php.in
banana/post.inc.php
examples/pj.php [new file with mode: 0644]

index bb8475d..6d756bf 100644 (file)
@@ -12,7 +12,7 @@ class Banana
     var $maxspool  = 3000;
 
     var $hdecode   = array('from','name','organization','subject');
-    var $parse_hdr = array('content-transfer-encoding', 'content-type', 'date', 'followup-to', 'from',
+    var $parse_hdr = array('content-disposition', 'content-transfer-encoding', 'content-type', 'date', 'followup-to', 'from',
             'message-id', 'newsgroups', 'organization', 'references', 'subject', 'x-face');
     var $show_hdr  = array('from', 'subject', 'newsgroups', 'followup', 'date', 'organization', 'references', 'x-face');
 
@@ -103,6 +103,15 @@ class Banana
                         return $banana->action_newFup($group, $artid);
                 }
             }
+
+            if (isset($_GET['pj'])) {
+                $action = false;
+                if (isset($_GET['action']) && $_GET['action'] == 'view') {
+                    $action = true;
+                }
+                return $banana->action_getAttachment($group, $artid, $_GET['pj'], $action);
+            }
+            
             return $res . $banana->action_showArticle($group, $artid);
         }
     }
@@ -184,6 +193,26 @@ class Banana
         return $res.$cuts;
     }
 
+    function action_getAttachment($group, $id, $pjid, $action)
+    {
+        $this->_newSpool($group, $this->profile['display'], $this->profile['lastnews']);
+        $this->_newPost($id);
+        if (!$this->post) {
+            if ($this->nntp->lasterrorcode == "423") {
+                $this->spool->delid($id);
+            }
+            $this->nntp->quit();
+            return displayshortcuts().'<p class="error">'._b_('Impossible d\'accéder au message.   Le message a peut-être été annulé').'</p>';
+        }
+
+        $this->nntp->quit();
+        if ($this->post->get_attachment($pjid, $action)) {
+            return "";
+        } else {
+            return displayshortcuts().'<p calss="error">'._b_('Impossible d\'accéder à la pièce jointe.').'</p>';
+        }
+    }
+
     function action_cancelArticle($group, $id)
     {
         $this->_newSpool($group, $this->profile['display'], $this->profile['lastnews']);
index f9ca5cc..364c122 100644 (file)
@@ -17,6 +17,8 @@ class BananaPost
     var $headers;
     /** body */
     var $body;
+    /** attachment */
+    var $pj;
     /** poster name */
     var $name;
 
@@ -27,6 +29,7 @@ class BananaPost
     {
         global $banana;
         $this->id = $_id;
+        $this->pj = array();
         $this->_header();
 
         if ($body = $banana->nntp->body($_id)) {
@@ -43,6 +46,11 @@ class BananaPost
             }
         }
 
+        if (preg_match("@multipart/([^;]+);@", $this->headers['content-type'], $mpart_type)) {
+            preg_match("/boundary=\"?([^ \"]+)\"?/", $this->headers['content-type'], $mpart_boundary);
+            $this->split_multipart($mpart_type[1], $mpart_boundary[1]);
+        }
+        
         if (preg_match('!charset=([^;]*)\s*(;|$)!', $this->headers['content-type'], $matches)) {
             $this->body = iconv($matches[1], 'utf-8', $this->body);
         } else {
@@ -50,6 +58,111 @@ class BananaPost
         }
     }
 
+    /** split multipart messages
+     * @param $type STRING multipart type description
+     * @param $boundary STRING multipart boundary identification string
+     */
+    function split_multipart($type, $boundary)
+    {
+        global $banana;
+        
+        $parts = preg_split("/\n--$boundary(--|\n)/", $this->body);
+        foreach ($parts as $part) {
+            $part = $this->get_part($part);
+            $local_header = $part['headers'];
+            $local_body = $part['body'];
+            if (isset($local_header['content-disposition']) && preg_match("/attachment/", $local_header['content-disposition'])) {
+                $this->add_attachment($part);
+            } else if (isset($local_header['content-type']) && preg_match("@text/@", $local_header['content-type'])) {
+                $this->body = $local_body;
+                foreach ($banana->parse_hdr as $hdr) {
+                    if (isset($local_header[$hdr])) {
+                        $this->headers[$hdr] = $local_header[$hdr];
+                    }
+                }
+            }
+        }
+    }
+
+    /** extract new headers from the part
+     * @param $part STRING part of a multipart message
+     */
+    function get_part($part) {
+        global $banana;
+
+        $lines = split("\n", $part);
+        while (count($lines)) {
+            $line = array_shift($lines);
+            if ($line != "") {
+                list($hdr, $val) = split(":[ \t\r]*", $line, 2);
+                $hdr = strtolower($hdr);
+                if (in_array($hdr, $banana->parse_hdr)) {
+                    $local_headers[$hdr] = $val;
+                }
+            } else {
+                break;
+            }
+        }
+        #        echo join("\n", $lines)."<br/>------------------------------------<br/>";
+        return Array('headers' => $local_headers, 'body' => join("\n", $lines)); 
+    }
+
+    function add_attachment($part) {
+        $local_header = $part['headers'];
+        $local_body = $part['body'];
+
+        if (!isset($local_header['content-transfer-encoding'])) {
+            return;
+        }
+
+        if (isset($local_header['content-disposition'])) {
+            if (preg_match("/attachment/", $local_header['content-disposition'])) {
+                preg_match("/filename=\"?([^\"]+)\"?/", $local_header['content-disposition'], $filename);
+                $filename = $filename[1];
+            }
+        }
+        if (!isset($filename)) {
+            $filename = "attachment".count($pj);
+        }
+
+        if (isset($local_header['content-type'])) {
+            if (preg_match("/^\\s*([^ ;]+);/", $local_header['content-type'], $mimetype)) {
+                $mimetype = $mimetype[1];
+            }
+        }
+        if (!isset($mimetype)) {
+            return;
+        }
+
+        array_push($this->pj, Array('MIME' => $mimetype,
+                                    'filename' => $filename,
+                                    'encoding' => strtolower($local_header['content-transfer-encoding']),
+                                    'data' => $local_body));
+    }
+
+    /** decode an attachment
+     * @param pjid INT id of the attachment to decode
+     * @param action BOOL action to execute : true=view, false=download
+     */
+    function get_attachment($pjid, $action = false) {
+        if ($pjid >= count($this->pj)) {
+            return false;
+        } else {
+            $file = $this->pj[$pjid];
+            header('Content-Type: '.$file['MIME']);
+            if (!$action) {
+                header('Content-Disposition: attachment; filename="'.$file['filename'].'"');
+            }
+            if ($file['encoding'] == 'base64') {
+                echo base64_decode($file['data']);
+            } else {
+                header('Content-Transfer-Encoding: '.$file['encoding']);
+                echo $file['data'];
+            }
+            return true;
+        }
+    }
+
     function _header()
     {
         global $banana;
@@ -112,6 +225,22 @@ class BananaPost
 
         $res .= '<tr><th colspan="2">'._b_('Corps').'</th></tr>';
         $res .= '<tr><td colspan="2"><pre>'.formatbody($this->body).'</pre></td></tr>';
+
+        if (count($this->pj) > 0) {
+            $res .= '<tr><th colspan="2">'._b_('Pièces jointes').'</th></tr>';
+            $res .= '<tr><td colspan="2">';
+            $i = 0;
+            foreach ($this->pj as $file) {
+                $res .= $file['filename'].' ('.$file['MIME'].') : ';
+                $res .= '<a href="pj.php?group='.$banana->state['group'].'&artid='.$this->id.'&pj='.$i.'">télécharger</a>';
+                if (preg_match("@(image|text)/@", $file['MIME'])) {
+                    $res .= ' . <a href="pj.php?group='.$banana->state['group'].'&artid='.$this->id.'&pj='.$i.'&action=view">aperçu</a>';
+                }
+                $res .=  '<br/>';
+                $i++;
+            }
+            $res .= '</td></tr>';
+        }
         
         $res .= '<tr><th colspan="2">'._b_('apercu').'</th></tr>';
         $ndx  = $banana->spool->getndx($this->id);
diff --git a/examples/pj.php b/examples/pj.php
new file mode 100644 (file)
index 0000000..65cef9e
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+/********************************************************************************
+* pj.php : for getting attachments
+* -----------
+*
+* This file is part of the banana distribution
+* Copyright: See COPYING files that comes with this distribution
+********************************************************************************/
+
+require_once("banana/banana.inc.php");
+$res = Banana::run();
+
+?>
+