Zend Framework - Zend_Mail
Current view: /usr/local/lib/zend/trunk/incubator/library/Zend/Mime/Decode.php
Date: Tue Feb 6 18:30:06 CET 2007 Executable lines: 70
Code covered: 97.14% Executed lines: 68
Legend: executed not executed dead code


       1                 : <?php                                                                                                            
       2                 : /**                                                                                                              
       3                 :  * Zend Framework                                                                                                
       4                 :  *                                                                                                               
       5                 :  * LICENSE                                                                                                       
       6                 :  *                                                                                                               
       7                 :  * This source file is subject to the new BSD license that is bundled                                            
       8                 :  * with this package in the file LICENSE.txt.                                                                    
       9                 :  * It is also available through the world-wide-web at this URL:                                                  
      10                 :  * http://framework.zend.com/license/new-bsd                                                                     
      11                 :  * If you did not receive a copy of the license and are unable to                                                
      12                 :  * obtain it through the world-wide-web, please send an email                                                    
      13                 :  * to license@zend.com so we can send you a copy immediately.                                                    
      14                 :  *                                                                                                               
      15                 :  * @category   Zend                                                                                              
      16                 :  * @package    Zend_Mime                                                                                         
      17                 :  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)                          
      18                 :  * @license    http://framework.zend.com/license/new-bsd     New BSD License                                     
      19                 :  */                                                                                                              
      20                 :                                                                                                                  
      21                 : /**                                                                                                              
      22                 :  * Zend_Mime                                                                                                     
      23                 :  */                                                                                                              
      24                 : require_once 'Zend/Mime.php';                                                                                    
      25                 :                                                                                                                  
      26                 : /**                                                                                                              
      27                 :  * @category   Zend                                                                                              
      28                 :  * @package    Zend_Mime                                                                                         
      29                 :  * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)                          
      30                 :  * @license    http://framework.zend.com/license/new-bsd     New BSD License                                     
      31                 :  */                                                                                                              
      32                 : class Zend_Mime_Decode                                                                                           
      33                 : {                                                                                                                
      34                 :     /**                                                                                                          
      35                 :      * Explode MIME multipart string into seperate parts                                                         
      36                 :      *                                                                                                           
      37                 :      * Parts consist of the header and the body of each MIME part.                                               
      38                 :      *                                                                                                           
      39                 :      * @param string $body                                                                                       
      40                 :      * @param string $boundary                                                                                   
      41                 :      * @return array                                                                                             
      42                 :      */                                                                                                          
      43                 :     public static function splitMime($body, $boundary)                                                           
      44                 :     {                                                                                                            
      45                 :         // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r?
      46               5 :         $body = str_replace("\r", '', $body);                                                                    
      47                 :                                                                                                                  
      48               5 :         $start = 0;                                                                                              
      49               5 :         $res = array();                                                                                          
      50                 :         // find every mime part limiter and cut out the                                                          
      51                 :         // string before it.                                                                                     
      52                 :         // the part before the first boundary string is discarded:                                               
      53               5 :         $p = strpos($body, '--' . $boundary . "\n", $start);                                                     
      54               5 :         if ($p === false) {                                                                                      
      55                 :             // no parts found!                                                                                   
      56               1 :             return array();                                                                                      
      57                 :         }                                                                                                        
      58                 :                                                                                                                  
      59                 :         // position after first boundary line                                                                    
      60               4 :         $start = $p + 3 + strlen($boundary);                                                                     
      61                 :                                                                                                                  
      62               4 :         while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) {                                
      63               3 :             $res[] = substr($body, $start, $p-$start);                                                           
      64               3 :             $start = $p + 3 + strlen($boundary);                                                                 
      65               3 :         }                                                                                                        
      66                 :                                                                                                                  
      67                 :         // no more parts, find end boundary                                                                      
      68               4 :         $p = strpos($body, '--' . $boundary . '--', $start);                                                     
      69               4 :         if ($p===false) {                                                                                        
      70               1 :             throw new Zend_Exception('Not a valid Mime Message: End Missing');                                   
      71                 :         }                                                                                                        
      72                 :                                                                                                                  
      73                 :         // the remaining part also needs to be parsed:                                                           
      74               3 :         $res[] = substr($body, $start, $p-$start);                                                               
      75               3 :         return $res;                                                                                             
      76                 :     }                                                                                                            
      77                 :                                                                                                                  
      78                 :     /**                                                                                                          
      79                 :      * decodes a mime encoded String and returns a                                                               
      80                 :      * struct of parts with header and body                                                                      
      81                 :      *                                                                                                           
      82                 :      * @param string $message                                                                                    
      83                 :      * @param string $boundary                                                                                   
      84                 :      * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}                                     
      85                 :      * @return array                                                                                             
      86                 :      */                                                                                                          
      87                 :     public static function splitMessageStruct($message, $boundary, $EOL = Zend_Mime::LINEEND)                    
      88                 :     {                                                                                                            
      89               5 :         $parts = self::splitMime($message, $boundary);                                                           
      90               4 :         if (count($parts) <= 0) {                                                                                
      91               1 :             return null;                                                                                         
      92                 :         }                                                                                                        
      93               3 :         $result = array();                                                                                       
      94               3 :         foreach($parts as $part) {                                                                               
      95               3 :             self::splitMessage($part, $headers, $body, $EOL);                                                    
      96               3 :             $result[] = array('header' => $headers,                                                              
      97               3 :                               'body'   => $body    );                                                            
      98               3 :         }                                                                                                        
      99               3 :         return $result;                                                                                          
     100                 :     }                                                                                                            
     101                 :                                                                                                                  
     102                 :     /**                                                                                                          
     103                 :      * split a message in header and body part, if no header or an                                               
     104                 :      * invalid header is found $headers is empty                                                                 
     105                 :      *                                                                                                           
     106                 :      * @param string $message                                                                                    
     107                 :      * @param mixed $headers, output param, out type is array                                                    
     108                 :      * @param mixed $body, output param, out type is string                                                      
     109                 :      * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND}                                     
     110                 :      */                                                                                                          
     111                 :     public static function splitMessage($message, &$headers, &$body, $EOL = Zend_Mime::LINEEND)                  
     112                 :     {                                                                                                            
     113                 :         // check for valid header at first line                                                                        
     114              35 :         $firstline = strtok($message, "\n");                                                                           
     115              35 :         if(!preg_match('%^[^\s]+[^:]*:%', $firstline)) {                                                               
     116               1 :             $headers = array();                                                                                           
     117               1 :             $body = str_replace(array("\r", "\n"), array('', $EOL), $message);                                            
     118               1 :             return;                                                                                                       
     119                 :         }                                                                                                              
     120                 :                                                                                                                          
     121                 :         // find an empty line between headers and body                                                                 
     122                 :         // default is set new line                                                                                     
     123              34 :         if(strpos($message, $EOL . $EOL)) {                                                                            
     124              17 :             list($headers, $body) = explode($EOL . $EOL, $message, 2);                                                 
     125                 :         // next is the standard new line                                                                               
     126              34 :         } else if($EOL != "\r\n" && strpos($message, "\r\n\r\n")) {                                                    
     127               0 :             list($headers, $body) = explode("\r\n\r\n", $message, 2);                                                  
     128                 :         // next is the other "standard" new line                                                                       
     129              20 :         } else if($EOL != "\n" && strpos($message, "\n\n")) {                                                          
     130               3 :             list($headers, $body) = explode("\n\n", $message, 2);                                                      
     131                 :         // at last resort find anything that looks like a new line                                                  
     132               3 :         } else {                                                                                                       
     133              17 :             @list($headers, $body) = @preg_split("%([\r\n]+)\\1%U", $message, 2);                                         
     134                 :         }                                                                                                              
     135                 :                                                                                                                          
     136              34 :         $headers = iconv_mime_decode_headers($headers, ICONV_MIME_DECODE_CONTINUE_ON_ERROR);                           
     137                 :                                                                                                                          
     138                 :         // normalize header names                                                                                      
     139              34 :         foreach($headers as $name => $header) {                                                                        
     140              34 :             $lower = strtolower($name);                                                                                   
     141              34 :             if($lower == $name) {                                                                                         
     142              34 :                 continue;                                                                                                    
     143                 :             }                                                                                                             
     144              34 :             unset($headers[$name]);                                                                                       
     145              34 :             if(!isset($headers[$lower])) {                                                                                
     146              34 :                 $headers[$lower] = $header;                                                                                  
     147              34 :                 continue;                                                                                                    
     148                 :             }                                                                                                             
     149               1 :             if(is_array($headers[$lower])) {                                                                              
     150               1 :                 $headers[$lower][] = $header;                                                                                
     151               1 :                 continue;                                                                                                    
     152                 :             }                                                                                                             
     153               1 :             $headers[$lower] = array($headers[$lower], $header);                                                          
     154               1 :         }                                                                                                              
     155              34 :     }                                                                                                            
     156                 :                                                                                                                  
     157                 :     /**                                                                                                          
     158                 :      * split a content type in its different parts - maybe that could                                            
     159                 :      * get a more generic name and code as many fields use this format                                           
     160                 :      *                                                                                                           
     161                 :      * @param string content-type                                                                                
     162                 :      * @param string the wanted part, else an array with all parts is returned                                   
     163                 :      *                                                                                                           
     164                 :      * @return string|array wanted part or all parts                                                             
     165                 :      */                                                                                                          
     166                 :     public static function splitContentType($type, $wantedPart = null)                                           
     167                 :     {                                                                                                            
     168               4 :         return self::splitHeaderField($type, $wantedPart, 'type');                                               
     169                 :     }                                                                                                            
     170                 :                                                                                                                  
     171                 :     /**                                                                                                          
     172                 :      * split a header field like content type in its different parts                                             
     173                 :      *                                                                                                           
     174                 :      * @param string header field                                                                                
     175                 :      * @param string the wanted part, else an array with all parts is returned                                   
     176                 :      * @param string key name for the first field                                                                
     177                 :      *                                                                                                           
     178                 :      * @return string|array wanted part or all parts                                                             
     179                 :      */                                                                                                          
     180                 :     public static function splitHeaderField($type, $wantedPart = null, $firstName = 0)                           
     181                 :     {                                                                                                            
     182               4 :         $split = array();                                                                                        
     183               4 :         $type = explode(';', $type);                                                                             
     184                 :         // this is already prepared for a                                                                        
     185               4 :         $split[$firstName] = array_shift($type);                                                                 
     186               4 :         foreach($type as $part) {                                                                                
     187               4 :             $part = trim($part);                                                                                 
     188               4 :             list($key, $value) = explode('=', $part);                                                            
     189               4 :             if($value[0] == '"') {                                                                               
     190               4 :                 $value = substr($value, 1, -1);                                                                  
     191               4 :             }                                                                                                    
     192               4 :             $split[$key] = $value;                                                                               
     193               4 :         }                                                                                                        
     194                 :                                                                                                                  
     195               4 :         if($wantedPart) {                                                                                        
     196               3 :             return isset($split[$wantedPart]) ? $split[$wantedPart] : null;                                      
     197                 :         }                                                                                                        
     198               1 :         return $split;                                                                                           
     199                 :     }                                                                                                            
     200                 :                                                                                                                  
     201                 :     /**                                                                                                          
     202                 :      *                                                                                                           
     203                 :      * decode a quoted printable encoded string                                                                  
     204                 :      *                                                                                                           
     205                 :      * @param string encoded string                                                                              
     206                 :      * @return string decoded string                                                                             
     207                 :      */                                                                                                          
     208                 :     public static function decodeQuotedPrintable($string)                                                        
     209                 :     {                                                                                                            
     210               0 :         return iconv_mime_decode($string, ICONV_MIME_DECODE_CONTINUE_ON_ERROR);                                        
     211                 :     }                                                                                                            
     212                 : }                                                                                                                
     213                 : 

Generated by: PHPUnit 3.0.0 and Xdebug 2.0.0RC2-dev.