home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / Mail / mimePart.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  15.6 KB  |  440 lines

  1. <?php
  2. /**
  3.  * The Mail_mimePart class is used to create MIME E-mail messages
  4.  *
  5.  * This class enables you to manipulate and build a mime email
  6.  * from the ground up. The Mail_Mime class is a userfriendly api
  7.  * to this class for people who aren't interested in the internals
  8.  * of mime mail.
  9.  * This class however allows full control over the email.
  10.  *
  11.  * Compatible with PHP versions 4 and 5
  12.  *
  13.  * LICENSE: This LICENSE is in the BSD license style.
  14.  * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
  15.  * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
  16.  * All rights reserved.
  17.  *
  18.  * Redistribution and use in source and binary forms, with or
  19.  * without modification, are permitted provided that the following
  20.  * conditions are met:
  21.  *
  22.  * - Redistributions of source code must retain the above copyright
  23.  *   notice, this list of conditions and the following disclaimer.
  24.  * - Redistributions in binary form must reproduce the above copyright
  25.  *   notice, this list of conditions and the following disclaimer in the
  26.  *   documentation and/or other materials provided with the distribution.
  27.  * - Neither the name of the authors, nor the names of its contributors 
  28.  *   may be used to endorse or promote products derived from this 
  29.  *   software without specific prior written permission.
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  32.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  35.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  36.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  37.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  38.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  39.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  41.  * THE POSSIBILITY OF SUCH DAMAGE.
  42.  *
  43.  * @category   Mail
  44.  * @package    Mail_Mime
  45.  * @author     Richard Heyes  <richard@phpguru.org>
  46.  * @author     Cipriano Groenendal <cipri@php.net>
  47.  * @author     Sean Coates <sean@php.net>
  48.  * @copyright  2003-2006 PEAR <pear-group@php.net>
  49.  * @license    http://www.opensource.org/licenses/bsd-license.php BSD License
  50.  * @version    CVS: $Id: mimePart.php,v 1.25 2007/05/14 21:43:08 cipri Exp $
  51.  * @link       http://pear.php.net/package/Mail_mime
  52.  */
  53.  
  54.  
  55. /**
  56.  * The Mail_mimePart class is used to create MIME E-mail messages
  57.  *
  58.  * This class enables you to manipulate and build a mime email
  59.  * from the ground up. The Mail_Mime class is a userfriendly api
  60.  * to this class for people who aren't interested in the internals
  61.  * of mime mail.
  62.  * This class however allows full control over the email.
  63.  *
  64.  * @category   Mail
  65.  * @package    Mail_Mime
  66.  * @author     Richard Heyes  <richard@phpguru.org>
  67.  * @author     Cipriano Groenendal <cipri@php.net>
  68.  * @author     Sean Coates <sean@php.net>
  69.  * @copyright  2003-2006 PEAR <pear-group@php.net>
  70.  * @license    http://www.opensource.org/licenses/bsd-license.php BSD License
  71.  * @version    Release: @package_version@
  72.  * @link       http://pear.php.net/package/Mail_mime
  73.  */
  74. class Mail_mimePart {
  75.  
  76.    /**
  77.     * The encoding type of this part
  78.     *
  79.     * @var string
  80.     * @access private
  81.     */
  82.     var $_encoding;
  83.  
  84.    /**
  85.     * An array of subparts
  86.     *
  87.     * @var array
  88.     * @access private
  89.     */
  90.     var $_subparts;
  91.  
  92.    /**
  93.     * The output of this part after being built
  94.     *
  95.     * @var string
  96.     * @access private
  97.     */
  98.     var $_encoded;
  99.  
  100.    /**
  101.     * Headers for this part
  102.     *
  103.     * @var array
  104.     * @access private
  105.     */
  106.     var $_headers;
  107.  
  108.    /**
  109.     * The body of this part (not encoded)
  110.     *
  111.     * @var string
  112.     * @access private
  113.     */
  114.     var $_body;
  115.  
  116.     /**
  117.      * Constructor.
  118.      *
  119.      * Sets up the object.
  120.      *
  121.      * @param $body   - The body of the mime part if any.
  122.      * @param $params - An associative array of parameters:
  123.      *                  content_type - The content type for this part eg multipart/mixed
  124.      *                  encoding     - The encoding to use, 7bit, 8bit, base64, or quoted-printable
  125.      *                  cid          - Content ID to apply
  126.      *                  disposition  - Content disposition, inline or attachment
  127.      *                  dfilename    - Optional filename parameter for content disposition
  128.      *                  description  - Content description
  129.      *                  charset      - Character set to use
  130.      * @access public
  131.      */
  132.     function Mail_mimePart($body = '', $params = array())
  133.     {
  134.         if (!defined('MAIL_MIMEPART_CRLF')) {
  135.             define('MAIL_MIMEPART_CRLF', defined('MAIL_MIME_CRLF') ? MAIL_MIME_CRLF : "\r\n", TRUE);
  136.         }
  137.  
  138.         $contentType = array();
  139.         $contentDisp = array();
  140.         foreach ($params as $key => $value) {
  141.             switch ($key) {
  142.                 case 'content_type':
  143.                     $contentType['type'] = $value;
  144.                     //$headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : '');
  145.                     break;
  146.  
  147.                 case 'encoding':
  148.                     $this->_encoding = $value;
  149.                     $headers['Content-Transfer-Encoding'] = $value;
  150.                     break;
  151.  
  152.                 case 'cid':
  153.                     $headers['Content-ID'] = '<' . $value . '>';
  154.                     break;
  155.  
  156.                 case 'disposition':
  157.                     $contentDisp['disp'] = $value;
  158.                     break;
  159.  
  160.                 case 'dfilename':
  161.                     $contentDisp['filename'] = $value;
  162.                     $contentType['name'] = $value;
  163.                     break;
  164.  
  165.                 case 'description':
  166.                     $headers['Content-Description'] = $value;
  167.                     break;
  168.  
  169.                 case 'charset':
  170.                     $contentType['charset'] = $value;
  171.                     $contentDisp['charset'] = $value;
  172.                     break;
  173.  
  174.                 case 'language':
  175.                     $contentType['language'] = $value;
  176.                     $contentDisp['language'] = $value;
  177.                     break;
  178.  
  179.                 case 'location':
  180.                     $headers['Content-Location'] = $value;
  181.                     break;
  182.  
  183.             }
  184.         }
  185.         if (isset($contentType['type'])) {
  186.             $headers['Content-Type'] = $contentType['type'];
  187.             if (isset($contentType['name'])) {
  188.                 $headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF;
  189.                 $headers['Content-Type'] .= $this->_buildHeaderParam('name', $contentType['name'], 
  190.                                                 isset($contentType['charset']) ? $contentType['charset'] : 'US-ASCII', 
  191.                                                 isset($contentType['language']) ? $contentType['language'] : NULL);
  192.             } elseif (isset($contentType['charset'])) {
  193.                 $headers['Content-Type'] .= "; charset=\"{$contentType['charset']}\"";
  194.             }
  195.         }
  196.  
  197.  
  198.         if (isset($contentDisp['disp'])) {
  199.             $headers['Content-Disposition'] = $contentDisp['disp'];
  200.             if (isset($contentDisp['filename'])) {
  201.                 $headers['Content-Disposition'] .= ';' . MAIL_MIMEPART_CRLF;
  202.                 $headers['Content-Disposition'] .= $this->_buildHeaderParam('filename', $contentDisp['filename'], 
  203.                                                 isset($contentDisp['charset']) ? $contentDisp['charset'] : 'US-ASCII', 
  204.                                                 isset($contentDisp['language']) ? $contentDisp['language'] : NULL);
  205.             }
  206.         }
  207.         
  208.         
  209.         
  210.         
  211.         // Default content-type
  212.         if (!isset($headers['Content-Type'])) {
  213.             $headers['Content-Type'] = 'text/plain';
  214.         }
  215.  
  216.         //Default encoding
  217.         if (!isset($this->_encoding)) {
  218.             $this->_encoding = '7bit';
  219.         }
  220.  
  221.         // Assign stuff to member variables
  222.         $this->_encoded  = array();
  223.         $this->_headers  = $headers;
  224.         $this->_body     = $body;
  225.     }
  226.  
  227.     /**
  228.      * encode()
  229.      *
  230.      * Encodes and returns the email. Also stores
  231.      * it in the encoded member variable
  232.      *
  233.      * @return An associative array containing two elements,
  234.      *         body and headers. The headers element is itself
  235.      *         an indexed array.
  236.      * @access public
  237.      */
  238.     function encode()
  239.     {
  240.         $encoded =& $this->_encoded;
  241.  
  242.         if (count($this->_subparts)) {
  243.             srand((double)microtime()*1000000);
  244.             $boundary = '=_' . md5(rand() . microtime());
  245.             $this->_headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF . "\t" . 'boundary="' . $boundary . '"';
  246.  
  247.             // Add body parts to $subparts
  248.             for ($i = 0; $i < count($this->_subparts); $i++) {
  249.                 $headers = array();
  250.                 $tmp = $this->_subparts[$i]->encode();
  251.                 foreach ($tmp['headers'] as $key => $value) {
  252.                     $headers[] = $key . ': ' . $value;
  253.                 }
  254.                 $subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body'] . MAIL_MIMEPART_CRLF;
  255.             }
  256.  
  257.             $encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF . 
  258.                                rtrim(implode('--' . $boundary . MAIL_MIMEPART_CRLF , $subparts), MAIL_MIMEPART_CRLF) . MAIL_MIMEPART_CRLF . 
  259.                                '--' . $boundary.'--' . MAIL_MIMEPART_CRLF;
  260.  
  261.         } else {
  262.             $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding);
  263.         }
  264.  
  265.         // Add headers to $encoded
  266.         $encoded['headers'] =& $this->_headers;
  267.  
  268.         return $encoded;
  269.     }
  270.  
  271.     /**
  272.      * &addSubPart()
  273.      *
  274.      * Adds a subpart to current mime part and returns
  275.      * a reference to it
  276.      *
  277.      * @param $body   The body of the subpart, if any.
  278.      * @param $params The parameters for the subpart, same
  279.      *                as the $params argument for constructor.
  280.      * @return A reference to the part you just added. It is
  281.      *         crucial if using multipart/* in your subparts that
  282.      *         you use =& in your script when calling this function,
  283.      *         otherwise you will not be able to add further subparts.
  284.      * @access public
  285.      */
  286.     function &addSubPart($body, $params)
  287.     {
  288.         $this->_subparts[] = new Mail_mimePart($body, $params);
  289.         return $this->_subparts[count($this->_subparts) - 1];
  290.     }
  291.  
  292.     /**
  293.      * _getEncodedData()
  294.      *
  295.      * Returns encoded data based upon encoding passed to it
  296.      *
  297.      * @param $data     The data to encode.
  298.      * @param $encoding The encoding type to use, 7bit, base64,
  299.      *                  or quoted-printable.
  300.      * @access private
  301.      */
  302.     function _getEncodedData($data, $encoding)
  303.     {
  304.         switch ($encoding) {
  305.             case '8bit':
  306.             case '7bit':
  307.                 return $data;
  308.                 break;
  309.  
  310.             case 'quoted-printable':
  311.                 return $this->_quotedPrintableEncode($data);
  312.                 break;
  313.  
  314.             case 'base64':
  315.                 return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF));
  316.                 break;
  317.  
  318.             default:
  319.                 return $data;
  320.         }
  321.     }
  322.  
  323.     /**
  324.      * quotedPrintableEncode()
  325.      *
  326.      * Encodes data to quoted-printable standard.
  327.      *
  328.      * @param $input    The data to encode
  329.      * @param $line_max Optional max line length. Should
  330.      *                  not be more than 76 chars
  331.      *
  332.      * @access private
  333.      */
  334.     function _quotedPrintableEncode($input , $line_max = 76)
  335.     {
  336.         $lines  = preg_split("/\r?\n/", $input);
  337.         $eol    = MAIL_MIMEPART_CRLF;
  338.         $escape = '=';
  339.         $output = '';
  340.  
  341.         while (list(, $line) = each($lines)) {
  342.  
  343.             $line    = preg_split('||', $line, -1, PREG_SPLIT_NO_EMPTY);
  344.             $linlen     = count($line);
  345.             $newline = '';
  346.  
  347.             for ($i = 0; $i < $linlen; $i++) {
  348.                 $char = $line[$i];
  349.                 $dec  = ord($char);
  350.  
  351.                 if (($dec == 32) AND ($i == ($linlen - 1))) {    // convert space at eol only
  352.                     $char = '=20';
  353.  
  354.                 } elseif (($dec == 9) AND ($i == ($linlen - 1))) {  // convert tab at eol only
  355.                     $char = '=09';
  356.                 } elseif ($dec == 9) {
  357.                     ; // Do nothing if a tab.
  358.                 } elseif (($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) {
  359.                     $char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
  360.                 } elseif (($dec == 46) AND ($newline == '')) {
  361.                     //Bug #9722: convert full-stop at bol
  362.                     //Some Windows servers need this, won't break anything (cipri)
  363.                     $char = '=2E';
  364.                 }
  365.  
  366.                 if ((strlen($newline) + strlen($char)) >= $line_max) {        // MAIL_MIMEPART_CRLF is not counted
  367.                     $output  .= $newline . $escape . $eol;                    // soft line break; " =\r\n" is okay
  368.                     $newline  = '';
  369.                 }
  370.                 $newline .= $char;
  371.             } // end of for
  372.             $output .= $newline . $eol;
  373.         }
  374.         $output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf
  375.         return $output;
  376.     }
  377.  
  378.     /**
  379.      * _buildHeaderParam()
  380.      *
  381.      * Encodes the paramater of a header.
  382.      *
  383.      * @param $name         The name of the header-parameter
  384.      * @param $value        The value of the paramter
  385.      * @param $charset      The characterset of $value
  386.      * @param $language     The language used in $value
  387.      * @param $maxLength    The maximum length of a line. Defauls to 75
  388.      *
  389.      * @access private
  390.      */
  391.     function _buildHeaderParam($name, $value, $charset=NULL, $language=NULL, $maxLength=75)
  392.     {
  393.         //If we find chars to encode, or if charset or language
  394.         //is not any of the defaults, we need to encode the value.
  395.         $shouldEncode = 0;
  396.         $secondAsterisk = '';
  397.         if (preg_match('#([\x80-\xFF]){1}#', $value)) {
  398.             $shouldEncode = 1;
  399.         } elseif ($charset && (strtolower($charset) != 'us-ascii')) {
  400.             $shouldEncode = 1;
  401.         } elseif ($language && ($language != 'en' && $language != 'en-us')) {
  402.             $shouldEncode = 1;
  403.         }
  404.         if ($shouldEncode) {
  405.             $search  = array('%',   ' ',   "\t");
  406.             $replace = array('%25', '%20', '%09');
  407.             $encValue = str_replace($search, $replace, $value);
  408.             $encValue = preg_replace('#([\x80-\xFF])#e', '"%" . strtoupper(dechex(ord("\1")))', $encValue);
  409.             $value = "$charset'$language'$encValue";
  410.             $secondAsterisk = '*';
  411.         }
  412.         $header = " {$name}{$secondAsterisk}=\"{$value}\"; ";
  413.         if (strlen($header) <= $maxLength) {
  414.             return $header;
  415.         }
  416.  
  417.         $preLength = strlen(" {$name}*0{$secondAsterisk}=\"");
  418.         $sufLength = strlen("\";");
  419.         $maxLength = MAX(16, $maxLength - $preLength - $sufLength - 2);
  420.         $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";
  421.  
  422.         $headers = array();
  423.         $headCount = 0;
  424.         while ($value) {
  425.             $matches = array();
  426.             $found = preg_match($maxLengthReg, $value, $matches);
  427.             if ($found) {
  428.                 $headers[] = " {$name}*{$headCount}{$secondAsterisk}=\"{$matches[0]}\"";
  429.                 $value = substr($value, strlen($matches[0]));
  430.             } else {
  431.                 $headers[] = " {$name}*{$headCount}{$secondAsterisk}=\"{$value}\"";
  432.                 $value = "";
  433.             }
  434.             $headCount++;
  435.         }
  436.         $headers = implode(MAIL_MIMEPART_CRLF, $headers) . ';';
  437.         return $headers;
  438.     }
  439. } // End of class
  440.