home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 March / PCWorld_2003-03_cd.bin / Software / Vyzkuste / phptriad / phptriad2-2-1.exe / php / pear / Mail / mimePart.php < prev    next >
Encoding:
PHP Script  |  2001-11-13  |  10.9 KB  |  325 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0                                                      |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2001 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Richard Heyes <richard@phpguru.org>                         |
  17. // +----------------------------------------------------------------------+
  18.  
  19.     require_once('PEAR.php');
  20.  
  21. /**
  22. *
  23. *  Raw mime encoding class
  24. *
  25. * What is it?
  26. *   This class enables you to manipulate and build
  27. *   a mime email from the ground up.
  28. *
  29. * Why use this instead of mime.php?
  30. *   mime.php is a userfriendly api to this class for
  31. *   people who aren't interested in the internals of
  32. *   mime mail. This class however allows full control
  33. *   over the email.
  34. *
  35. * Eg.
  36. *
  37. * // Since multipart/mixed has no real body, (the body is
  38. * // the subpart), we set the body argument to blank.
  39. *
  40. * $params['content_type'] = 'multipart/mixed';
  41. * $email = new Mail_mimePart('', $params);
  42. *
  43. * // Here we add a text part to the multipart we have
  44. * // already. Assume $body contains plain text.
  45. *
  46. * $params['content_type'] = 'text/plain';
  47. * $params['encoding']     = '7bit';
  48. * $text = $email->addSubPart($body, $params);
  49. *
  50. * // Now add an attachment. Assume $attach is
  51. * the contents of the attachment
  52. *
  53. * $params['content_type'] = 'application/zip';
  54. * $params['encoding']     = 'base64';
  55. * $params['disposition']  = 'attachment';
  56. * $params['dfilename']    = 'example.zip';
  57. * $attach =& $email->addSubPart($body, $params);
  58. *
  59. * // Now build the email. Note that the encode
  60. * // function returns an associative array containing two
  61. * // elements, body and headers. You will need to add extra
  62. * // headers, (eg. Mime-Version) before sending.
  63. *
  64. * $email = $message->encode();
  65. * $email['headers'][] = 'Mime-Version: 1.0';
  66. *
  67. * Further examples are available at http://www.phpguru.org
  68. *
  69. * TODO:
  70. *  - Set encode() to return the $obj->encoded if encode()
  71. *    has already been run. Unless a flag is passed to specifically
  72. *    re-build the message.
  73. *
  74. * @author  Richard Heyes <richard@phpguru.org>
  75. * @version $Revision: 1.4.2.1 $
  76. * @package Mail
  77. */
  78.  
  79. class Mail_mimePart extends PEAR{
  80.  
  81.    /**
  82.     * The encoding type of this part
  83.     * @var string
  84.     */
  85.     var $_encoding;
  86.  
  87.    /**
  88.     * An array of subparts
  89.     * @var array
  90.     */
  91.     var $_subparts;
  92.  
  93.    /**
  94.     * The output of this part after being built
  95.     * @var string
  96.     */
  97.     var $_encoded;
  98.  
  99.    /**
  100.     * Headers for this part
  101.     * @var array
  102.     */
  103.     var $_headers;
  104.  
  105.    /**
  106.     * The body of this part (not encoded)
  107.     * @var string
  108.     */
  109.     var $_body;
  110.  
  111.     /**
  112.      * Constructor.
  113.      * 
  114.      * Sets up the object.
  115.      *
  116.      * @param $body   - The body of the mime part if any.
  117.      * @param $params - An associative array of parameters:
  118.      *                  content_type - The content type for this part eg multipart/mixed
  119.      *                  encoding     - The encoding to use, 7bit, base64, or quoted-printable
  120.      *                  cid          - Content ID to apply
  121.      *                  disposition  - Content disposition, inline or attachment
  122.      *                  dfilename    - Optional filename parameter for content disposition
  123.      *                  description  - Content description
  124.      * @access public
  125.      */
  126.     function Mail_mimePart($body, $params = array())
  127.     {
  128.         if (!defined('MAIL_MIMEPART_CRLF')) {
  129.             define('MAIL_MIMEPART_CRLF', "\r\n", TRUE);
  130.         }
  131.  
  132.         foreach ($params as $key => $value) {
  133.             switch ($key) {
  134.                 case 'content_type':
  135.                     $headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : '');
  136.                     break;
  137.  
  138.                 case 'encoding':
  139.                     $this->_encoding = $value;
  140.                     $headers['Content-Transfer-Encoding'] = $value;
  141.                     break;
  142.  
  143.                 case 'cid':
  144.                     $headers['Content-ID'] = '<' . $value . '>';
  145.                     break;
  146.  
  147.                 case 'disposition':
  148.                     $headers['Content-Disposition'] = $value . (isset($dfilename) ? '; filename="' . $dfilename . '"' : '');
  149.                     break;
  150.  
  151.                 case 'dfilename':
  152.                     if (isset($headers['Content-Disposition'])) {
  153.                         $headers['Content-Disposition'] .= '; filename="' . $value . '"';
  154.                     } else {
  155.                         $dfilename = $value;
  156.                     }
  157.                     break;
  158.  
  159.                 case 'description':
  160.                     $headers['Content-Description'] = $value;
  161.                     break;
  162.  
  163.                 case 'charset':
  164.                     if (isset($headers['Content-Type'])) {
  165.                         $headers['Content-Type'] .= '; charset="' . $value . '"';
  166.                     } else {
  167.                         $charset = $value;
  168.                     }
  169.                     break;
  170.             }
  171.         }
  172.  
  173.         // Default content-type
  174.         if (!isset($_headers['Content-Type'])) {
  175.             $_headers['Content-Type'] = 'text/plain';
  176.         }
  177.  
  178.         // Assign stuff to member variables
  179.         $this->_encoded  =  array();
  180.         $this->_headers  =& $headers;
  181.         $this->_body     =  $body;
  182.     }
  183.  
  184.     /**
  185.      * encode()
  186.      * 
  187.      * Encodes and returns the email. Also stores
  188.      * it in the encoded member variable
  189.      *
  190.      * @return An associative array containing two elements,
  191.      *         body and headers. The headers element is itself
  192.      *         an indexed array.
  193.      * @access public
  194.      */
  195.     function encode()
  196.     {
  197.         $encoded =& $this->_encoded;
  198.  
  199.         if (!empty($this->_subparts)) {
  200.             srand((double)microtime()*1000000);
  201.             $boundary = '=_' . md5(uniqid(rand()) . microtime());
  202.             $this->_headers['Content-Type'] .= '; ' . 'boundary="' . $boundary . '"';
  203.  
  204.             // Add body parts to $subparts
  205.             for ($i = 0; $i < count($this->_subparts); $i++) {
  206.                 $headers = array();
  207.                 $tmp = $this->_subparts[$i]->encode();
  208.                 foreach ($tmp['headers'] as $key => $value) {
  209.                     $headers[] = $key . ': ' . $value;
  210.                 }
  211.                 $subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body'];
  212.             }
  213.  
  214.             $encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF .
  215.                                implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) .
  216.                                '--' . $boundary.'--' . MAIL_MIMEPART_CRLF;
  217.  
  218.         } else {
  219.             $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF;
  220.         }
  221.  
  222.         // Add headers to $encoded
  223.         $encoded['headers'] =& $this->_headers;
  224.  
  225.         return $encoded;
  226.     }
  227.  
  228.     /**
  229.      * &addSubPart()
  230.      * 
  231.      * Adds a subpart to current mime part and returns
  232.      * a reference to it
  233.      *
  234.      * @param $body   The body of the subpart, if any.
  235.      * @param $params The parameters for the subpart, same
  236.      *                as the $params argument for constructor.
  237.      * @return A reference to the part you just added. It is
  238.      *         crucial if using multipart/* in your subparts that
  239.      *         you use =& in your script when calling this function,
  240.      *         otherwise you will not be able to add further subparts.
  241.      * @access public
  242.      */
  243.     function &addSubPart($body, $params)
  244.     {
  245.         $this->_subparts[] = new Mail_mimePart($body, $params);
  246.         return $this->_subparts[count($this->_subparts) - 1];
  247.     }
  248.  
  249.     /**
  250.      * _getEncodedData()
  251.      * 
  252.      * Returns encoded data based upon encoding passed to it
  253.      *
  254.      * @param $data     The data to encode.
  255.      * @param $encoding The encoding type to use, 7bit, base64,
  256.      *                  or quoted-printable.
  257.      * @access private
  258.      */
  259.     function _getEncodedData($data, $encoding)
  260.     {
  261.         switch ($encoding) {
  262.             case '7bit':
  263.                 return $data;
  264.                 break;
  265.  
  266.             case 'quoted-printable':
  267.                 return $this->_quotedPrintableEncode($data);
  268.                 break;
  269.  
  270.             case 'base64':
  271.                 return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF));
  272.                 break;
  273.         }
  274.     }
  275.  
  276.     /**
  277.      * quoteadPrintableEncode()
  278.      * 
  279.      * Encodes data to quoted-printable standard.
  280.      *
  281.      * @param $input    The data to encode
  282.      * @param $line_max Optional max line length. Should 
  283.      *                  not be more than 76 chars
  284.      *
  285.      * @access private
  286.      */
  287.     function _quotedPrintableEncode($input , $line_max = 76)
  288.     {
  289.         $lines    = preg_split("/\r\n|\r|\n/", $input);
  290.         $eol    = MAIL_MIMEPART_CRLF;
  291.         $escape    = '=';
  292.         $output    = '';
  293.         
  294.         while(list(, $line) = each($lines)){
  295.  
  296.             $linlen     = strlen($line);
  297.             $newline = '';
  298.  
  299.             for ($i = 0; $i < $linlen; $i++) {
  300.                 $char = substr($line, $i, 1);
  301.                 $dec  = ord($char);
  302.  
  303.                 if (($dec == 32) AND ($i == ($linlen - 1))){    // convert space at eol only
  304.                     $char = '=20';
  305.  
  306.                 } elseif($dec == 9) {
  307.                     ; // Do nothing if a tab.
  308.                 } elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) {
  309.                     $char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
  310.                 }
  311.     
  312.                 if ((strlen($newline) + strlen($char)) >= $line_max) {        // MAIL_MIMEPART_CRLF is not counted
  313.                     $output  .= $newline . $escape . $eol;                    // soft line break; " =\r\n" is okay
  314.                     $newline  = '';
  315.                 }
  316.                 $newline .= $char;
  317.             } // end of for
  318.             $output .= $newline . $eol;
  319.         }
  320.         $output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf
  321.         return $output;
  322.     }
  323. } // End of class
  324. ?>