home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / mimePart.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  12.4 KB  |  350 lines

  1. <?php
  2. // +-----------------------------------------------------------------------+
  3. // | Copyright (c) 2002  Richard Heyes                                     |
  4. // | All rights reserved.                                                  |
  5. // |                                                                       |
  6. // | Redistribution and use in source and binary forms, with or without    |
  7. // | modification, are permitted provided that the following conditions    |
  8. // | are met:                                                              |
  9. // |                                                                       |
  10. // | o Redistributions of source code must retain the above copyright      |
  11. // |   notice, this list of conditions and the following disclaimer.       |
  12. // | o Redistributions in binary form must reproduce the above copyright   |
  13. // |   notice, this list of conditions and the following disclaimer in the |
  14. // |   documentation and/or other materials provided with the distribution.|
  15. // | o The names of the authors may not be used to endorse or promote      |
  16. // |   products derived from this software without specific prior written  |
  17. // |   permission.                                                         |
  18. // |                                                                       |
  19. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
  20. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
  21. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  22. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
  23. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  24. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
  25. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  26. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  27. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
  28. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  29. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
  30. // |                                                                       |
  31. // +-----------------------------------------------------------------------+
  32. // | Author: Richard Heyes <richard@phpguru.org>                           |
  33. // +-----------------------------------------------------------------------+
  34.  
  35. /**
  36. *
  37. *  Raw mime encoding class
  38. *
  39. * What is it?
  40. *   This class enables you to manipulate and build
  41. *   a mime email from the ground up.
  42. *
  43. * Why use this instead of mime.php?
  44. *   mime.php is a userfriendly api to this class for
  45. *   people who aren't interested in the internals of
  46. *   mime mail. This class however allows full control
  47. *   over the email.
  48. *
  49. * Eg.
  50. *
  51. * // Since multipart/mixed has no real body, (the body is
  52. * // the subpart), we set the body argument to blank.
  53. *
  54. * $params['content_type'] = 'multipart/mixed';
  55. * $email = new Mail_mimePart('', $params);
  56. *
  57. * // Here we add a text part to the multipart we have
  58. * // already. Assume $body contains plain text.
  59. *
  60. * $params['content_type'] = 'text/plain';
  61. * $params['encoding']     = '7bit';
  62. * $text = $email->addSubPart($body, $params);
  63. *
  64. * // Now add an attachment. Assume $attach is
  65. * the contents of the attachment
  66. *
  67. * $params['content_type'] = 'application/zip';
  68. * $params['encoding']     = 'base64';
  69. * $params['disposition']  = 'attachment';
  70. * $params['dfilename']    = 'example.zip';
  71. * $attach =& $email->addSubPart($body, $params);
  72. *
  73. * // Now build the email. Note that the encode
  74. * // function returns an associative array containing two
  75. * // elements, body and headers. You will need to add extra
  76. * // headers, (eg. Mime-Version) before sending.
  77. *
  78. * $email = $message->encode();
  79. * $email['headers'][] = 'Mime-Version: 1.0';
  80. *
  81. *
  82. * Further examples are available at http://www.phpguru.org
  83. *
  84. * TODO:
  85. *  - Set encode() to return the $obj->encoded if encode()
  86. *    has already been run. Unless a flag is passed to specifically
  87. *    re-build the message.
  88. *
  89. * @author  Richard Heyes <richard@phpguru.org>
  90. * @version $Revision: 1.10 $
  91. * @package Mail
  92. */
  93.  
  94. class Mail_mimePart {
  95.  
  96.    /**
  97.     * The encoding type of this part
  98.     * @var string
  99.     */
  100.     var $_encoding;
  101.  
  102.    /**
  103.     * An array of subparts
  104.     * @var array
  105.     */
  106.     var $_subparts;
  107.  
  108.    /**
  109.     * The output of this part after being built
  110.     * @var string
  111.     */
  112.     var $_encoded;
  113.  
  114.    /**
  115.     * Headers for this part
  116.     * @var array
  117.     */
  118.     var $_headers;
  119.  
  120.    /**
  121.     * The body of this part (not encoded)
  122.     * @var string
  123.     */
  124.     var $_body;
  125.  
  126.     /**
  127.      * Constructor.
  128.      *
  129.      * Sets up the object.
  130.      *
  131.      * @param $body   - The body of the mime part if any.
  132.      * @param $params - An associative array of parameters:
  133.      *                  content_type - The content type for this part eg multipart/mixed
  134.      *                  encoding     - The encoding to use, 7bit, 8bit, base64, or quoted-printable
  135.      *                  cid          - Content ID to apply
  136.      *                  disposition  - Content disposition, inline or attachment
  137.      *                  dfilename    - Optional filename parameter for content disposition
  138.      *                  description  - Content description
  139.      *                  charset      - Character set to use
  140.      * @access public
  141.      */
  142.     function Mail_mimePart($body = '', $params = array())
  143.     {
  144.         if (!defined('MAIL_MIMEPART_CRLF')) {
  145.             define('MAIL_MIMEPART_CRLF', defined('MAIL_MIME_CRLF') ? MAIL_MIME_CRLF : "\r\n", TRUE);
  146.         }
  147.  
  148.         foreach ($params as $key => $value) {
  149.             switch ($key) {
  150.                 case 'content_type':
  151.                     $headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : '');
  152.                     break;
  153.  
  154.                 case 'encoding':
  155.                     $this->_encoding = $value;
  156.                     $headers['Content-Transfer-Encoding'] = $value;
  157.                     break;
  158.  
  159.                 case 'cid':
  160.                     $headers['Content-ID'] = '<' . $value . '>';
  161.                     break;
  162.  
  163.                 case 'disposition':
  164.                     $headers['Content-Disposition'] = $value . (isset($dfilename) ? '; filename="' . $dfilename . '"' : '');
  165.                     break;
  166.  
  167.                 case 'dfilename':
  168.                     if (isset($headers['Content-Disposition'])) {
  169.                         $headers['Content-Disposition'] .= '; filename="' . $value . '"';
  170.                     } else {
  171.                         $dfilename = $value;
  172.                     }
  173.                     break;
  174.  
  175.                 case 'description':
  176.                     $headers['Content-Description'] = $value;
  177.                     break;
  178.  
  179.                 case 'charset':
  180.                     if (isset($headers['Content-Type'])) {
  181.                         $headers['Content-Type'] .= '; charset="' . $value . '"';
  182.                     } else {
  183.                         $charset = $value;
  184.                     }
  185.                     break;
  186.             }
  187.         }
  188.  
  189.         // Default content-type
  190.         if (!isset($headers['Content-Type'])) {
  191.             $headers['Content-Type'] = 'text/plain';
  192.         }
  193.  
  194.         //Default encoding
  195.         if (!isset($this->_encoding)) {
  196.             $this->_encoding = '7bit';
  197.         }
  198.  
  199.         // Assign stuff to member variables
  200.         $this->_encoded  = array();
  201.         $this->_headers  = $headers;
  202.         $this->_body     = $body;
  203.     }
  204.  
  205.     /**
  206.      * encode()
  207.      *
  208.      * Encodes and returns the email. Also stores
  209.      * it in the encoded member variable
  210.      *
  211.      * @return An associative array containing two elements,
  212.      *         body and headers. The headers element is itself
  213.      *         an indexed array.
  214.      * @access public
  215.      */
  216.     function encode()
  217.     {
  218.         $encoded =& $this->_encoded;
  219.  
  220.         if (!empty($this->_subparts)) {
  221.             srand((double)microtime()*1000000);
  222.             $boundary = '=_' . md5(uniqid(rand()) . microtime());
  223.             $this->_headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF . "\t" . 'boundary="' . $boundary . '"';
  224.  
  225.             // Add body parts to $subparts
  226.             for ($i = 0; $i < count($this->_subparts); $i++) {
  227.                 $headers = array();
  228.                 $tmp = $this->_subparts[$i]->encode();
  229.                 foreach ($tmp['headers'] as $key => $value) {
  230.                     $headers[] = $key . ': ' . $value;
  231.                 }
  232.                 $subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body'];
  233.             }
  234.  
  235.             $encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF .
  236.                                implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) .
  237.                                '--' . $boundary.'--' . MAIL_MIMEPART_CRLF;
  238.  
  239.         } else {
  240.             $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF;
  241.         }
  242.  
  243.         // Add headers to $encoded
  244.         $encoded['headers'] =& $this->_headers;
  245.  
  246.         return $encoded;
  247.     }
  248.  
  249.     /**
  250.      * &addSubPart()
  251.      *
  252.      * Adds a subpart to current mime part and returns
  253.      * a reference to it
  254.      *
  255.      * @param $body   The body of the subpart, if any.
  256.      * @param $params The parameters for the subpart, same
  257.      *                as the $params argument for constructor.
  258.      * @return A reference to the part you just added. It is
  259.      *         crucial if using multipart/* in your subparts that
  260.      *         you use =& in your script when calling this function,
  261.      *         otherwise you will not be able to add further subparts.
  262.      * @access public
  263.      */
  264.     function &addSubPart($body, $params)
  265.     {
  266.         $this->_subparts[] = new Mail_mimePart($body, $params);
  267.         return $this->_subparts[count($this->_subparts) - 1];
  268.     }
  269.  
  270.     /**
  271.      * _getEncodedData()
  272.      *
  273.      * Returns encoded data based upon encoding passed to it
  274.      *
  275.      * @param $data     The data to encode.
  276.      * @param $encoding The encoding type to use, 7bit, base64,
  277.      *                  or quoted-printable.
  278.      * @access private
  279.      */
  280.     function _getEncodedData($data, $encoding)
  281.     {
  282.         switch ($encoding) {
  283.             case '8bit':
  284.             case '7bit':
  285.                 return $data;
  286.                 break;
  287.  
  288.             case 'quoted-printable':
  289.                 return $this->_quotedPrintableEncode($data);
  290.                 break;
  291.  
  292.             case 'base64':
  293.                 return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF));
  294.                 break;
  295.  
  296.             default:
  297.                 return $data;
  298.         }
  299.     }
  300.  
  301.     /**
  302.      * quoteadPrintableEncode()
  303.      *
  304.      * Encodes data to quoted-printable standard.
  305.      *
  306.      * @param $input    The data to encode
  307.      * @param $line_max Optional max line length. Should
  308.      *                  not be more than 76 chars
  309.      *
  310.      * @access private
  311.      */
  312.     function _quotedPrintableEncode($input , $line_max = 76)
  313.     {
  314.         $lines  = preg_split("/\r?\n/", $input);
  315.         $eol    = MAIL_MIMEPART_CRLF;
  316.         $escape = '=';
  317.         $output = '';
  318.  
  319.         while(list(, $line) = each($lines)){
  320.  
  321.             $linlen     = strlen($line);
  322.             $newline = '';
  323.  
  324.             for ($i = 0; $i < $linlen; $i++) {
  325.                 $char = substr($line, $i, 1);
  326.                 $dec  = ord($char);
  327.  
  328.                 if (($dec == 32) AND ($i == ($linlen - 1))){    // convert space at eol only
  329.                     $char = '=20';
  330.  
  331.                 } elseif($dec == 9) {
  332.                     ; // Do nothing if a tab.
  333.                 } elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) {
  334.                     $char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
  335.                 }
  336.  
  337.                 if ((strlen($newline) + strlen($char)) >= $line_max) {        // MAIL_MIMEPART_CRLF is not counted
  338.                     $output  .= $newline . $escape . $eol;                    // soft line break; " =\r\n" is okay
  339.                     $newline  = '';
  340.                 }
  341.                 $newline .= $char;
  342.             } // end of for
  343.             $output .= $newline . $eol;
  344.         }
  345.         $output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf
  346.         return $output;
  347.     }
  348. } // End of class
  349. ?>
  350.