source: sandbox/2.5.0-expresso1/expressoMail1_2/inc/class.attachment.inc.php @ 5359

Revision 5359, 20.8 KB checked in by cristiano, 12 years ago (diff)

Ticket #2440 - Melhorias no carregamento de mensagens de e-mail do usuário

  • Property svn:executable set to *
Line 
1<?php
2/**
3* Classe que manipula e gerencia toda a parte de anexos.
4*
5* @package    ExpressoMail
6* @license    http://www.gnu.org/copyleft/gpl.html GPL
7* @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
8* @author     Cristiano Correa
9*/
10
11class attachment
12{
13    /*
14     * Globals variables
15     */
16    var $mbox;
17    var $imap_port;
18    var $has_cid;
19    var $imap_options;
20    var $imap_sentfolder;
21    var $msgNumber;
22    var $folder;
23    var $structure;
24    var $decodeConf;
25    //------------------------------------------//
26
27    /**
28     * Constructor
29         * @license   http://www.gnu.org/copyleft/gpl.html GPL
30         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
31     * @param string $folder Imap folder name
32     * @param integer $msgNumber Imap menssagem number
33     */
34    function attachment()
35    {
36        /*
37         * Requires
38         */
39            require_once dirname(__FILE__).'/../../library/mime/mimePart.php';
40            require_once dirname(__FILE__).'/../../library/mime/mimeDecode.php';
41        //----------------------------------------------------------//
42
43        $this->decodeConf['include_bodies'] = true;
44        $this->decodeConf['decode_bodies']  = true;
45        $this->decodeConf['decode_headers'] = true;
46       
47        if( array_key_exists('nested_messages_are_shown', $_SESSION['phpgw_info']['user']['preferences']['expressoMail']) && ($_SESSION['phpgw_info']['user']['preferences']['expressoMail']['nested_messages_are_shown'] == '1'))
48            $this->decodeConf['rfc_822bodies']  = true;
49    }
50    //----------------------------------------------------------------------------//
51
52
53
54    /**
55     * Open mail from Imap and parse structure
56     * @license   http://www.gnu.org/copyleft/gpl.html GPL
57         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
58         * @return string  menssagem
59     */
60    public function setStructureFromMail($folder,$msgNumber)
61    {
62        $this->folder       = mb_convert_encoding($folder, 'UTF7-IMAP',mb_detect_encoding($folder.'x', 'UTF-8, ISO-8859-1'));
63        $this->msgNumber    = $msgNumber;
64        $this->username     = $_SESSION['phpgw_info']['expressomail']['user']['userid'];
65        $this->password     = $_SESSION['phpgw_info']['expressomail']['user']['passwd'];
66        $this->imap_server  = $_SESSION['phpgw_info']['expressomail']['email_server']['imapServer'];
67        $this->imap_port    = $_SESSION['phpgw_info']['expressomail']['email_server']['imapPort'];
68        $this->imap_delimiter = $_SESSION['phpgw_info']['expressomail']['email_server']['imapDelimiter'];
69        $this->imap_sentfolder = $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSentFolder']   ? $_SESSION['phpgw_info']['expressomail']['email_server']['imapDefaultSentFolder']   : str_replace("*","", $this->functions->getLang("Sent"));
70        $this->has_cid = false;
71
72        if ($_SESSION['phpgw_info']['expressomail']['email_server']['imapTLSEncryption'] == 'yes')
73            $this->imap_options = '/tls/novalidate-cert';
74        else
75            $this->imap_options = '/notls/novalidate-cert';
76
77        $this->mbox = @imap_open("{".$this->imap_server.":".$this->imap_port.$this->imap_options."}".$this->folder , $this->username, $this->password) or die('Error');
78
79        $rawMessageData = $this->_getRaw();
80        $decoder = new Mail_mimeDecode($rawMessageData);
81        $this->structure = $decoder->decode($this->decodeConf);
82
83                //TODO: Descartar código após atualização do módulo de segurança da SERPRO
84                if($this->isSignedMenssage())
85                        $this->convertSignedMenssage($rawMessageData);
86                //////////////////////////////////////////////////////
87                       
88                       
89        /*
90         * Clean memory and close imap connection
91         */
92        $rawMessageData = null;
93        $decoder = null;
94        @imap_close($this->mbox);
95        //-----------------------------------------//
96    }
97
98        //TODO: Descartar código após atualização do módulo de segurança da SERPRO
99        private function isSignedMenssage()
100        {
101                if(strtolower($this->structure->ctype_primary) == 'application' && strtolower($this->structure->ctype_secondary) == 'x-pkcs7-mime' )
102                        return true;
103                else
104                        return false;     
105        }
106    //////////////////////////////////////////////////////////////////////////
107
108   //TODO: Descartar código após atualização do módulo de segurança da SERPRO
109   private function convertSignedMenssage($rawMessageData)
110        {
111                $decoder = new Mail_mimeDecode($this->extractSignedContents($rawMessageData));
112                $this->structure = $decoder->decode($this->decodeConf);         
113        }
114        ///////////////////////////////////////////////////////////////////////////
115       
116        //TODO: Descartar código após atualização do módulo de segurança da SERPRO
117        private function extractSignedContents( $data )
118                    {
119                        $pipes_desc = array(
120                            0 => array('pipe', 'r'),
121                            1 => array('pipe', 'w')
122                        );
123                 
124                        $fp = proc_open( 'openssl smime -verify -noverify -nochain', $pipes_desc, $pipes);
125                        if (!is_resource($fp)) {
126                           return false;
127                        }
128                 
129                        $output = '';
130                 
131                        /* $pipes[0] => writeable handle connected to child stdin
132                           $pipes[1] => readable handle connected to child stdout */
133                        fwrite($pipes[0], $data);
134                        fclose($pipes[0]);
135                 
136                        while (!feof($pipes[1])) {
137                            $output .= fgets($pipes[1], 1024);
138                        }
139                        fclose($pipes[1]);
140                        proc_close($fp);
141                 
142                        return $output;
143                    }
144        /////////////////////////////////////////////////////////////////////////////////////
145       
146    /**
147     * Set Stucture from Mail_mimeDecode Structure
148     * @license   http://www.gnu.org/copyleft/gpl.html GPL
149         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
150         * @param Mail_mimeDecode $structure
151     */
152    public function setStructure($structure)
153    {
154          $this->structure = $structure;
155    }
156
157    /**
158     *  Set Stucture from raw mail code
159         * @license   http://www.gnu.org/copyleft/gpl.html GPL
160         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
161     * @param Mail_mimeDecode $structure
162     */
163    public function setStructureFromRawMail($rawMail)
164    {
165        $decoder = new Mail_mimeDecode($rawMail);
166        $this->structure = $decoder->decode($this->decodeConf);
167               
168                //TODO: Descartar código após atualização do módulo de segurança da SERPRO
169                if($this->isSignedMenssage())
170                        $this->convertSignedMenssage($rawMail); 
171                //////////////////////////////////////////////////////////////////////////
172    }
173
174    /**
175     * Returns Attachment Decoded
176     * @license   http://www.gnu.org/copyleft/gpl.html GPL
177         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
178         * @param string $partNumber Index part
179     * @return string Attachment Decoded
180     */
181    public function getAttachment($partNumber)
182    {
183       $partContent = '';
184       $this->_getPartContent($this->structure, $partNumber, $partContent);
185       return $partContent;
186    }
187
188     /**
189     * Returns EmbeddedImages Infos
190     * @license   http://www.gnu.org/copyleft/gpl.html GPL
191         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
192         * @return array EmbeddedImages
193     */
194    public function getEmbeddedImagesInfo()
195    {
196        $imagesEmbedded = array();
197        $this->_getEmbeddedImagesInfo($this->structure,$imagesEmbedded);
198        return $imagesEmbedded;
199    }
200
201    /**
202     * Returns Attachments Infos
203     * @license   http://www.gnu.org/copyleft/gpl.html GPL
204         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
205         * @return array
206     */
207    public function getAttachmentsInfo()
208    {
209        $attachments = array();
210        $this->_getAttachmentsInfo($this->structure,$attachments);
211        return $attachments;
212    }
213
214    /**
215     * Returns Attachment Info
216     * @license   http://www.gnu.org/copyleft/gpl.html GPL
217         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
218         * @param string $partNumber Index part
219     * @return array
220     */
221    public function getAttachmentInfo($partNumber)
222    {
223        $attachment = array();
224        $this->_getPartInfo($this->structure,$partNumber,$attachment);
225        return $attachment[0];
226    }
227
228    /**
229     * returns the source code menssagem
230     * @license   http://www.gnu.org/copyleft/gpl.html GPL
231         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
232         * @return string  menssagem
233     */
234    private function _getRaw()
235    {
236                        /*
237                 * Chamada original imap_fetchheader($this->mbox, $this->msgNumber, FT_UID)."\r\n".imap_body($this->mbox, $this->msgNumber, FT_UID);
238                 * Inserido replace para corrigir um bug que acontece raramente em mensagens vindas do outlook com muitos destinatarios
239                 */
240                return str_replace("\r\n\t", '', imap_fetchheader($this->mbox, $this->msgNumber, FT_UID))."\r\n".imap_body($this->mbox, $this->msgNumber, FT_UID);
241    }
242
243    /**
244     * Returns content from the searched
245     * @license   http://www.gnu.org/copyleft/gpl.html GPL
246         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
247         * @param pointer $structure Structure object
248     * @param string $soughtIndex
249     * @param pointer $body Content
250     * @param string $pIndex
251     */
252    private function _getPartContent(&$structure, $soughtIndex,&$body,$pIndex = '0')
253    {
254        if($structure->parts)
255        {
256            foreach ($structure->parts  as $index => $part)
257            {
258                if(strtolower($part->ctype_primary) == 'multipart')
259                        $this->_getPartContent($part,$soughtIndex,$body,$pIndex.'.'.$index);
260                else
261                {
262                    if(strtolower($part->ctype_primary) == 'message' && is_array($part->parts) && $this->decodeConf['rfc_822bodies'] !== true )
263                            $this->_getPartContent($part,$soughtIndex,$body,$pIndex.'.'.$index);
264                    else
265                    {
266                        $currentIndex = $pIndex.'.'.$index;
267                        if($currentIndex === $soughtIndex)
268                        {
269                            $body = $part->body;
270                            break;
271                        }
272                    }
273                }
274            }
275        }
276        else if($soughtIndex == '0')
277           $body = $structure->body;
278    }
279
280        /**
281     * @license   http://www.gnu.org/copyleft/gpl.html GPL
282         * @author    Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
283     */
284    private function _getPartInfo(&$structure, $soughtIndex,&$info,$pIndex = '0')
285    {
286
287        if($structure->parts)
288        {
289            foreach ($structure->parts  as $index => $part)
290            {
291                if(strtolower($part->ctype_primary) == 'multipart')
292                    $this->_getPartInfo($part,$soughtIndex,$info,$pIndex.'.'.$index);
293                else
294                {
295                    if(strtolower($part->ctype_primary) == 'message' && is_array($part->parts) && $this->decodeConf['rfc_822bodies'] !== true)
296                         $this->_getPartInfo($part,$soughtIndex,$info,$pIndex.'.'.$index);
297                    else
298                    {
299                        $currentIndex = $pIndex.'.'.$index;
300                        if($currentIndex === $soughtIndex)
301                        {
302                                                        $this->_pushAttachmentsInfo($part,$info,$currentIndex);
303                            break;
304                        }
305                    }
306                }
307            }
308        }else if($soughtIndex == '0')
309                        $this->_pushAttachmentsInfo($structure,$info);
310    }
311
312
313
314     /**
315     * Write in $attachments, array with the information of attachments
316     * @param <type> $structure
317     * @param <type> $attachments
318     */
319    private function _getAttachmentsInfo($structure, &$attachments, $pIndex = '0')
320    {
321
322        if(isset($structure->parts))
323        {
324            foreach ($structure->parts  as $index => $part)
325            {
326                if(strtolower($part->ctype_primary) == 'multipart')
327                    $this->_getAttachmentsInfo($part,$attachments,$pIndex.'.'.$index);
328                else
329                {
330                    if(strtolower($part->ctype_primary) == 'message' && is_array($part->parts) && $this->decodeConf['rfc_822bodies'] !== true)
331                       $this->_getAttachmentsInfo($part,$attachments,$pIndex.'.'.$index);
332                    else
333                    {
334                        if(!$part->headers['content-transfer-encoding']) //Caso não esteja especificado a codificação
335                                    $part->headers['content-transfer-encoding'] = mb_detect_encoding ($part->body,array('BASE64','Quoted-Printable','7bit','8bit','ASCII'));
336                                                if($part->headers['content-transfer-encoding'] === ('ASCII' || false)) //Caso a codificação retorne ascii ou false especifica como base64
337                                                        $part->headers['content-transfer-encoding'] = 'base64';
338                                               
339                                                        $this->_pushAttachmentsInfo($part,$attachments,$pIndex.'.'.$index);
340                     
341                    }
342                }
343            }
344        }
345        else
346                        $this->_pushAttachmentsInfo($structure,$attachments);
347
348    }
349
350       
351        /**
352        * Write in $$attachments, array with the information of attachment
353        * @param <type> $structure
354        * @param <type> $attachments
355        * @param <type> $pIndex
356        */     
357        private function _pushAttachmentsInfo(&$structure, &$attachments, $pIndex = '0')
358        {
359                        $name = '';                               
360                        if((isset($structure->d_parameters['filename']))&& ($structure->d_parameters['filename'])) $name = $structure->d_parameters['filename'];
361                        else if((isset($structure->ctype_parameters['name']))&&($structure->ctype_parameters['name'])) $name = $structure->ctype_parameters['name'];
362                        else if(strtolower($structure->ctype_primary) == 'text' &&  strtolower($structure->ctype_secondary) == 'calendar') $name = 'calendar.ics';
363                 
364                            //Attachments com nomes grandes são quebrados em varias partes VER RFC2231
365                            if( !$name && isset($structure->disposition) && (strtolower($structure->disposition) === 'attachment' || strtolower($structure->ctype_primary) == 'image' ||  strtolower($structure->ctype_primary.'/'.$structure->ctype_secondary) == 'application/octet-stream'))
366                                        foreach ($structure->d_parameters as $i => $v)
367                                                if(strpos($i , 'filename') !== false)
368                                                        $name .= urldecode(str_ireplace(array('ISO-8859-1','UTF-8','US-ASCII'),'',$v));
369                             if( !$name && isset($structure->disposition) && (strtolower($structure->disposition) === 'attachment' || strtolower($structure->ctype_primary) == 'image' ||  strtolower($structure->ctype_primary.'/'.$structure->ctype_secondary) == 'application/octet-stream') )
370                                        foreach ($structure->ctype_parameters as $i => $v)
371                                                if(strpos($i , 'name') !== false)
372                                                        $name .= urldecode(str_ireplace(array('ISO-8859-1','UTF-8','US-ASCII'),'',$v));         
373                           ////////////////////////////////////////////////////////////////////////////////////
374                                               
375
376                        if($structure->ctype_primary == 'message') {
377                                $attach = new attachment();
378                                $attach->setStructureFromRawMail($structure->body);
379
380                                if (!$name)
381                                        $name = (isset($attach->structure->headers['subject'])) ? $attach->structure->headers['subject'] : 'no title';
382
383                                if (!preg_match("/\.eml$/", $name))
384                                        $name .= '.eml';
385                        }                                             
386
387                        if(!$name && strtolower($structure->ctype_primary) == 'image')
388                        {
389                            if(strlen($structure->ctype_secondary) === 3)
390                                $ext = strtolower($structure->ctype_secondary);
391
392                            $name = 'Embedded-Image.'.$ext;
393                        }
394                               
395                        if($name)
396                        {
397                            $codificao =  mb_detect_encoding($name.'x', 'UTF-8, ISO-8859-1');
398                            if($codificao == 'UTF-8') $name = utf8_decode($name);
399                             
400                            $definition['pid'] = $pIndex;
401                            $definition['name'] = addslashes(mb_convert_encoding($name, "ISO-8859-1"));
402                            $definition['encoding'] = $structure->headers['content-transfer-encoding'];
403                            $definition['type'] = strtolower($structure->ctype_primary).'/'.strtolower($structure->ctype_secondary);                                       
404                            $definition['fsize'] = mb_strlen($structure->body, $structure->headers['content-transfer-encoding']);
405                 
406                            array_push($attachments, $definition);
407                        }     
408        }
409       
410       
411       
412       
413       
414       
415    /**
416     * Write in $images, array with the information of Embedded Images
417     * @param <type> $structure
418     * @param <type> $attachments
419     */
420     private function _getEmbeddedImagesInfo($structure, &$images, $pIndex = '0')
421     {
422                if(isset($structure->parts))
423        foreach ($structure->parts  as $index => $part)
424        {
425            if(strtolower($part->ctype_primary) == 'multipart')
426                    $this->_getEmbeddedImagesInfo($part,$images,$pIndex.'.'.$index);
427            else
428            {
429                if(strtolower($part->ctype_primary) == 'message' && is_array($part->parts) && $this->decodeConf['rfc_822bodies'] !== true)
430                        $this->_getEmbeddedImagesInfo($part,$images,$pIndex.'.'.$index);
431                else
432                {
433                    if(is_array($part->ctype_parameters) && !array_key_exists('name', $part->ctype_parameters))
434                        if(isset($part->d_parameters['filename']))
435                         $name = $part->d_parameters['filename'];
436                    else
437                          $name = null;
438                    else
439                         $name = $part->ctype_parameters['name'];
440
441                     //Attachments com nomes grandes são quebrados em varias partes VER RFC2231
442                        if( !$name && isset($part->disposition) && (strtolower($part->disposition) === 'attachment' || strtolower($part->ctype_primary) == 'image' ||  strtolower($part->ctype_primary.'/'.$part->ctype_secondary) == 'application/octet-stream') )
443                                    foreach ($part->d_parameters as $i => $v)
444                                            if(strpos($i , 'filename') !== false)
445                                                    $name .= urldecode(str_ireplace(array('ISO-8859-1','UTF-8','US-ASCII'),'',$v));
446                         if( !$name && isset($part->disposition) && (strtolower($part->disposition) === 'attachment' || strtolower($part->ctype_primary) == 'image' ||  strtolower($part->ctype_primary.'/'.$part->ctype_secondary) == 'application/octet-stream') )
447                                    foreach ($part->ctype_parameters as $i => $v)
448                                            if(strpos($i , 'name') !== false)
449                                                    $name .= urldecode(str_ireplace(array('ISO-8859-1','UTF-8','US-ASCII'),'',$v));             
450                       ////////////////////////////////////////////////////////////////////////////////////
451                   
452                    if($name && (strlen($name) - (strrpos($name, '.')+1) === 3 ))
453                        $ext = strtolower(substr ( $name , (strrpos($name, '.')+1) ));         
454                    else if(strlen($structure->ctype_secondary) === 3)
455                        $ext = strtolower($structure->ctype_secondary);
456                   
457                    if(!$name && strtolower($structure->ctype_primary) == 'image') $name = 'Embedded-Image.'.$ext;
458                                       
459                    $ctype = strtolower($part->ctype_primary.'/'.$part->ctype_secondary);
460       
461                    if(strtolower($part->ctype_primary) == 'image' ||  ($ctype == 'application/octet-stream' && ($ext == 'png' || $ext == 'jpg' || $ext == 'gif' || $ext == 'bmp' || $ext == 'tif')))
462                    {
463                        $definition['pid'] = $pIndex.'.'.$index;
464                        $definition['name'] = addslashes($name);
465                        $definition['type'] = $ctype;
466                        $definition['encoding'] = isset($part->headers['content-transfer-encoding']) ? $part->headers['content-transfer-encoding'] : 'base64';
467                        $definition['cid'] = isset($part->headers['content-id']) ? $part->headers['content-id'] : '';
468                        array_push($images, $definition);
469                    }
470                }
471            }
472        }
473    }
474
475}
476
477?>
Note: See TracBrowser for help on using the repository browser.