Subversion Repositories Applications.papyrus

Rev

Rev 1987 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
929 alexandre_ 1
<?php
2
// +-----------------------------------------------------------------------+
3
// | Copyright (c) 2002-2003  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.1 $
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(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) AND ($i == ($linlen - 1))) {  // convert tab at eol only
332
                    $char = '=09';
333
                } elseif($dec == 9) {
334
                    ; // Do nothing if a tab.
335
                } elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) {
336
                    $char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
337
                }
338
 
339
                if ((strlen($newline) + strlen($char)) >= $line_max) {        // MAIL_MIMEPART_CRLF is not counted
340
                    $output  .= $newline . $escape . $eol;                    // soft line break; " =\r\n" is okay
341
                    $newline  = '';
342
                }
343
                $newline .= $char;
344
            } // end of for
345
            $output .= $newline . $eol;
346
        }
347
        $output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf
348
        return $output;
349
    }
350
} // End of class
351
?>