Completed
Branch develop (c24f26)
by
unknown
26:13
created
htdocs/includes/nusoap/lib/Mail/mimePart.php 1 patch
Indentation   +1171 added lines, -1171 removed lines patch added patch discarded remove patch
@@ -75,520 +75,520 @@  discard block
 block discarded – undo
75 75
  */
76 76
 class Mail_mimePart
77 77
 {
78
-    /**
79
-    * The encoding type of this part
80
-    *
81
-    * @var string
82
-    * @access private
83
-    */
84
-    var $_encoding;
85
-
86
-    /**
87
-    * An array of subparts
88
-    *
89
-    * @var array
90
-    * @access private
91
-    */
92
-    var $_subparts;
93
-
94
-    /**
95
-    * The output of this part after being built
96
-    *
97
-    * @var string
98
-    * @access private
99
-    */
100
-    var $_encoded;
101
-
102
-    /**
103
-    * Headers for this part
104
-    *
105
-    * @var array
106
-    * @access private
107
-    */
108
-    var $_headers;
109
-
110
-    /**
111
-    * The body of this part (not encoded)
112
-    *
113
-    * @var string
114
-    * @access private
115
-    */
116
-    var $_body;
117
-
118
-    /**
119
-    * The location of file with body of this part (not encoded)
120
-    *
121
-    * @var string
122
-    * @access private
123
-    */
124
-    var $_body_file;
125
-
126
-    /**
127
-    * The end-of-line sequence
128
-    *
129
-    * @var string
130
-    * @access private
131
-    */
132
-    var $_eol = "\r\n";
133
-
134
-
135
-    /**
136
-    * Constructor.
137
-    *
138
-    * Sets up the object.
139
-    *
140
-    * @param string $body   The body of the mime part if any.
141
-    * @param array  $params An associative array of optional parameters:
142
-    *     content_type      - The content type for this part eg multipart/mixed
143
-    *     encoding          - The encoding to use, 7bit, 8bit,
144
-    *                         base64, or quoted-printable
145
-    *     charset           - Content character set
146
-    *     cid               - Content ID to apply
147
-    *     disposition       - Content disposition, inline or attachment
148
-    *     filename          - Filename parameter for content disposition
149
-    *     description       - Content description
150
-    *     name_encoding     - Encoding of the attachment name (Content-Type)
151
-    *                         By default filenames are encoded using RFC2231
152
-    *                         Here you can set RFC2047 encoding (quoted-printable
153
-    *                         or base64) instead
154
-    *     filename_encoding - Encoding of the attachment filename (Content-Disposition)
155
-    *                         See 'name_encoding'
156
-    *     headers_charset   - Charset of the headers e.g. filename, description.
157
-    *                         If not set, 'charset' will be used
158
-    *     eol               - End of line sequence. Default: "\r\n"
159
-    *     headers           - Hash array with additional part headers. Array keys can be
160
-    *                         in form of <header_name>:<parameter_name>
161
-    *     body_file         - Location of file with part's body (instead of $body)
162
-    *
163
-    * @access public
164
-    */
165
-    function Mail_mimePart($body = '', $params = array())
166
-    {
167
-        if (!empty($params['eol'])) {
168
-            $this->_eol = $params['eol'];
169
-        } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat.
170
-            $this->_eol = MAIL_MIMEPART_CRLF;
171
-        }
172
-
173
-        // Additional part headers
174
-        if (!empty($params['headers']) && is_array($params['headers'])) {
175
-            $headers = $params['headers'];
176
-        }
177
-
178
-        foreach ($params as $key => $value) {
179
-            switch ($key) {
180
-            case 'encoding':
181
-                $this->_encoding = $value;
182
-                $headers['Content-Transfer-Encoding'] = $value;
183
-                break;
184
-
185
-            case 'cid':
186
-                $headers['Content-ID'] = '<' . $value . '>';
187
-                break;
188
-
189
-            case 'location':
190
-                $headers['Content-Location'] = $value;
191
-                break;
192
-
193
-            case 'body_file':
194
-                $this->_body_file = $value;
195
-                break;
196
-
197
-            // for backward compatibility
198
-            case 'dfilename':
199
-                $params['filename'] = $value;
200
-                break;
201
-            }
202
-        }
203
-
204
-        // Default content-type
205
-        if (empty($params['content_type'])) {
206
-            $params['content_type'] = 'text/plain';
207
-        }
208
-
209
-        // Content-Type
210
-        $headers['Content-Type'] = $params['content_type'];
211
-        if (!empty($params['charset'])) {
212
-            $charset = "charset={$params['charset']}";
213
-            // place charset parameter in the same line, if possible
214
-            if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) {
215
-                $headers['Content-Type'] .= '; ';
216
-            } else {
217
-                $headers['Content-Type'] .= ';' . $this->_eol . ' ';
218
-            }
219
-            $headers['Content-Type'] .= $charset;
220
-
221
-            // Default headers charset
222
-            if (!isset($params['headers_charset'])) {
223
-                $params['headers_charset'] = $params['charset'];
224
-            }
225
-        }
226
-
227
-        // header values encoding parameters
228
-        $h_charset  = !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII';
229
-        $h_language = !empty($params['language']) ? $params['language'] : null;
230
-        $h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null;
231
-
232
-
233
-        if (!empty($params['filename'])) {
234
-            $headers['Content-Type'] .= ';' . $this->_eol;
235
-            $headers['Content-Type'] .= $this->_buildHeaderParam(
236
-                'name', $params['filename'], $h_charset, $h_language, $h_encoding
237
-            );
238
-        }
239
-
240
-        // Content-Disposition
241
-        if (!empty($params['disposition'])) {
242
-            $headers['Content-Disposition'] = $params['disposition'];
243
-            if (!empty($params['filename'])) {
244
-                $headers['Content-Disposition'] .= ';' . $this->_eol;
245
-                $headers['Content-Disposition'] .= $this->_buildHeaderParam(
246
-                    'filename', $params['filename'], $h_charset, $h_language,
247
-                    !empty($params['filename_encoding']) ? $params['filename_encoding'] : null
248
-                );
249
-            }
250
-
251
-            // add attachment size
252
-            $size = $this->_body_file ? filesize($this->_body_file) : strlen($body);
253
-            if ($size) {
254
-                $headers['Content-Disposition'] .= ';' . $this->_eol . ' size=' . $size;
255
-            }
256
-        }
257
-
258
-        if (!empty($params['description'])) {
259
-            $headers['Content-Description'] = $this->encodeHeader(
260
-                'Content-Description', $params['description'], $h_charset, $h_encoding,
261
-                $this->_eol
262
-            );
263
-        }
264
-
265
-        // Search and add existing headers' parameters
266
-        foreach ($headers as $key => $value) {
267
-            $items = explode(':', $key);
268
-            if (count($items) == 2) {
269
-                $header = $items[0];
270
-                $param  = $items[1];
271
-                if (isset($headers[$header])) {
272
-                    $headers[$header] .= ';' . $this->_eol;
273
-                }
274
-                $headers[$header] .= $this->_buildHeaderParam(
275
-                    $param, $value, $h_charset, $h_language, $h_encoding
276
-                );
277
-                unset($headers[$key]);
278
-            }
279
-        }
280
-
281
-        // Default encoding
282
-        if (!isset($this->_encoding)) {
283
-            $this->_encoding = '7bit';
284
-        }
285
-
286
-        // Assign stuff to member variables
287
-        $this->_encoded  = array();
288
-        $this->_headers  = $headers;
289
-        $this->_body     = $body;
290
-    }
291
-
292
-    /**
293
-     * Encodes and returns the email. Also stores
294
-     * it in the encoded member variable
295
-     *
296
-     * @param string $boundary Pre-defined boundary string
297
-     *
298
-     * @return An associative array containing two elements,
299
-     *         body and headers. The headers element is itself
300
-     *         an indexed array. On error returns PEAR error object.
301
-     * @access public
302
-     */
303
-    function encode($boundary=null)
304
-    {
305
-        $encoded =& $this->_encoded;
306
-
307
-        if (count($this->_subparts)) {
308
-            $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
309
-            $eol = $this->_eol;
310
-
311
-            $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
312
-
313
-            $encoded['body'] = ''; 
314
-
315
-            for ($i = 0; $i < count($this->_subparts); $i++) {
316
-                $encoded['body'] .= '--' . $boundary . $eol;
317
-                $tmp = $this->_subparts[$i]->encode();
318
-                if ($this->_isError($tmp)) {
319
-                    return $tmp;
320
-                }
321
-                foreach ($tmp['headers'] as $key => $value) {
322
-                    $encoded['body'] .= $key . ': ' . $value . $eol;
323
-                }
324
-                $encoded['body'] .= $eol . $tmp['body'] . $eol;
325
-            }
326
-
327
-            $encoded['body'] .= '--' . $boundary . '--' . $eol;
328
-
329
-        } else if ($this->_body) {
330
-            $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding);
331
-        } else if ($this->_body_file) {
332
-            // Temporarily reset magic_quotes_runtime for file reads and writes
333
-            if ($magic_quote_setting = get_magic_quotes_runtime()) {
334
-                @ini_set('magic_quotes_runtime', 0);
335
-            }
336
-            $body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding);
337
-            if ($magic_quote_setting) {
338
-                @ini_set('magic_quotes_runtime', $magic_quote_setting);
339
-            }
340
-
341
-            if ($this->_isError($body)) {
342
-                return $body;
343
-            }
344
-            $encoded['body'] = $body;
345
-        } else {
346
-            $encoded['body'] = '';
347
-        }
348
-
349
-        // Add headers to $encoded
350
-        $encoded['headers'] =& $this->_headers;
351
-
352
-        return $encoded;
353
-    }
354
-
355
-    /**
356
-     * Encodes and saves the email into file. File must exist.
357
-     * Data will be appended to the file.
358
-     *
359
-     * @param string  $filename  Output file location
360
-     * @param string  $boundary  Pre-defined boundary string
361
-     * @param boolean $skip_head True if you don't want to save headers
362
-     *
363
-     * @return array An associative array containing message headers
364
-     *               or PEAR error object
365
-     * @access public
366
-     * @since 1.6.0
367
-     */
368
-    function encodeToFile($filename, $boundary=null, $skip_head=false)
369
-    {
370
-        if (file_exists($filename) && !is_writable($filename)) {
371
-            $err = $this->_raiseError('File is not writeable: ' . $filename);
372
-            return $err;
373
-        }
374
-
375
-        if (!($fh = fopen($filename, 'ab'))) {
376
-            $err = $this->_raiseError('Unable to open file: ' . $filename);
377
-            return $err;
378
-        }
379
-
380
-        // Temporarily reset magic_quotes_runtime for file reads and writes
381
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
382
-            @ini_set('magic_quotes_runtime', 0);
383
-        }
384
-
385
-        $res = $this->_encodePartToFile($fh, $boundary, $skip_head);
386
-
387
-        fclose($fh);
388
-
389
-        if ($magic_quote_setting) {
390
-            @ini_set('magic_quotes_runtime', $magic_quote_setting);
391
-        }
392
-
393
-        return $this->_isError($res) ? $res : $this->_headers;
394
-    }
395
-
396
-    /**
397
-     * Encodes given email part into file
398
-     *
399
-     * @param string  $fh        Output file handle
400
-     * @param string  $boundary  Pre-defined boundary string
401
-     * @param boolean $skip_head True if you don't want to save headers
402
-     *
403
-     * @return array True on sucess or PEAR error object
404
-     * @access private
405
-     */
406
-    function _encodePartToFile($fh, $boundary=null, $skip_head=false)
407
-    {
408
-        $eol = $this->_eol;
409
-
410
-        if (count($this->_subparts)) {
411
-            $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
412
-            $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
413
-        }
414
-
415
-        if (!$skip_head) {
416
-            foreach ($this->_headers as $key => $value) {
417
-                fwrite($fh, $key . ': ' . $value . $eol);
418
-            }
419
-            $f_eol = $eol;
420
-        } else {
421
-            $f_eol = '';
422
-        }
423
-
424
-        if (count($this->_subparts)) {
425
-            for ($i = 0; $i < count($this->_subparts); $i++) {
426
-                fwrite($fh, $f_eol . '--' . $boundary . $eol);
427
-                $res = $this->_subparts[$i]->_encodePartToFile($fh);
428
-                if ($this->_isError($res)) {
429
-                    return $res;
430
-                }
431
-                $f_eol = $eol;
432
-            }
433
-
434
-            fwrite($fh, $eol . '--' . $boundary . '--' . $eol);
435
-
436
-        } else if ($this->_body) {
437
-            fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding));
438
-        } else if ($this->_body_file) {
439
-            fwrite($fh, $f_eol);
440
-            $res = $this->_getEncodedDataFromFile(
441
-                $this->_body_file, $this->_encoding, $fh
442
-            );
443
-            if ($this->_isError($res)) {
444
-                return $res;
445
-            }
446
-        }
447
-
448
-        return true;
449
-    }
450
-
451
-    /**
452
-     * Adds a subpart to current mime part and returns
453
-     * a reference to it
454
-     *
455
-     * @param string $body   The body of the subpart, if any.
456
-     * @param array  $params The parameters for the subpart, same
457
-     *                       as the $params argument for constructor.
458
-     *
459
-     * @return Mail_mimePart A reference to the part you just added. In PHP4, it is
460
-     *                       crucial if using multipart/* in your subparts that
461
-     *                       you use =& in your script when calling this function,
462
-     *                       otherwise you will not be able to add further subparts.
463
-     * @access public
464
-     */
465
-    function &addSubpart($body, $params)
466
-    {
467
-        $this->_subparts[] = $part = new Mail_mimePart($body, $params);
468
-        return $part;
469
-    }
470
-
471
-    /**
472
-     * Returns encoded data based upon encoding passed to it
473
-     *
474
-     * @param string $data     The data to encode.
475
-     * @param string $encoding The encoding type to use, 7bit, base64,
476
-     *                         or quoted-printable.
477
-     *
478
-     * @return string
479
-     * @access private
480
-     */
481
-    function _getEncodedData($data, $encoding)
482
-    {
483
-        switch ($encoding) {
484
-        case 'quoted-printable':
485
-            return $this->_quotedPrintableEncode($data);
486
-            break;
487
-
488
-        case 'base64':
489
-            return rtrim(chunk_split(base64_encode($data), 76, $this->_eol));
490
-            break;
491
-
492
-        case '8bit':
493
-        case '7bit':
494
-        default:
495
-            return $data;
496
-        }
497
-    }
498
-
499
-    /**
500
-     * Returns encoded data based upon encoding passed to it
501
-     *
502
-     * @param string   $filename Data file location
503
-     * @param string   $encoding The encoding type to use, 7bit, base64,
504
-     *                           or quoted-printable.
505
-     * @param resource $fh       Output file handle. If set, data will be
506
-     *                           stored into it instead of returning it
507
-     *
508
-     * @return string Encoded data or PEAR error object
509
-     * @access private
510
-     */
511
-    function _getEncodedDataFromFile($filename, $encoding, $fh=null)
512
-    {
513
-        if (!is_readable($filename)) {
514
-            $err = $this->_raiseError('Unable to read file: ' . $filename);
515
-            return $err;
516
-        }
517
-
518
-        if (!($fd = fopen($filename, 'rb'))) {
519
-            $err = $this->_raiseError('Could not open file: ' . $filename);
520
-            return $err;
521
-        }
522
-
523
-        $data = '';
524
-
525
-        switch ($encoding) {
526
-        case 'quoted-printable':
527
-            while (!feof($fd)) {
528
-                $buffer = $this->_quotedPrintableEncode(fgets($fd));
529
-                if ($fh) {
530
-                    fwrite($fh, $buffer);
531
-                } else {
532
-                    $data .= $buffer;
533
-                }
534
-            }
535
-            break;
536
-
537
-        case 'base64':
538
-            while (!feof($fd)) {
539
-                // Should read in a multiple of 57 bytes so that
540
-                // the output is 76 bytes per line. Don't use big chunks
541
-                // because base64 encoding is memory expensive
542
-                $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB
543
-                $buffer = base64_encode($buffer);
544
-                $buffer = chunk_split($buffer, 76, $this->_eol);
545
-                if (feof($fd)) {
546
-                    $buffer = rtrim($buffer);
547
-                }
548
-
549
-                if ($fh) {
550
-                    fwrite($fh, $buffer);
551
-                } else {
552
-                    $data .= $buffer;
553
-                }
554
-            }
555
-            break;
556
-
557
-        case '8bit':
558
-        case '7bit':
559
-        default:
560
-            while (!feof($fd)) {
561
-                $buffer = fread($fd, 1048576); // 1 MB
562
-                if ($fh) {
563
-                    fwrite($fh, $buffer);
564
-                } else {
565
-                    $data .= $buffer;
566
-                }
567
-            }
568
-        }
569
-
570
-        fclose($fd);
571
-
572
-        if (!$fh) {
573
-            return $data;
574
-        }
575
-    }
576
-
577
-    /**
578
-     * Encodes data to quoted-printable standard.
579
-     *
580
-     * @param string $input    The data to encode
581
-     * @param int    $line_max Optional max line length. Should
582
-     *                         not be more than 76 chars
583
-     *
584
-     * @return string Encoded data
585
-     *
586
-     * @access private
587
-     */
588
-    function _quotedPrintableEncode($input , $line_max = 76)
589
-    {
590
-        $eol = $this->_eol;
591
-        /*
78
+	/**
79
+	 * The encoding type of this part
80
+	 *
81
+	 * @var string
82
+	 * @access private
83
+	 */
84
+	var $_encoding;
85
+
86
+	/**
87
+	 * An array of subparts
88
+	 *
89
+	 * @var array
90
+	 * @access private
91
+	 */
92
+	var $_subparts;
93
+
94
+	/**
95
+	 * The output of this part after being built
96
+	 *
97
+	 * @var string
98
+	 * @access private
99
+	 */
100
+	var $_encoded;
101
+
102
+	/**
103
+	 * Headers for this part
104
+	 *
105
+	 * @var array
106
+	 * @access private
107
+	 */
108
+	var $_headers;
109
+
110
+	/**
111
+	 * The body of this part (not encoded)
112
+	 *
113
+	 * @var string
114
+	 * @access private
115
+	 */
116
+	var $_body;
117
+
118
+	/**
119
+	 * The location of file with body of this part (not encoded)
120
+	 *
121
+	 * @var string
122
+	 * @access private
123
+	 */
124
+	var $_body_file;
125
+
126
+	/**
127
+	 * The end-of-line sequence
128
+	 *
129
+	 * @var string
130
+	 * @access private
131
+	 */
132
+	var $_eol = "\r\n";
133
+
134
+
135
+	/**
136
+	 * Constructor.
137
+	 *
138
+	 * Sets up the object.
139
+	 *
140
+	 * @param string $body   The body of the mime part if any.
141
+	 * @param array  $params An associative array of optional parameters:
142
+	 *     content_type      - The content type for this part eg multipart/mixed
143
+	 *     encoding          - The encoding to use, 7bit, 8bit,
144
+	 *                         base64, or quoted-printable
145
+	 *     charset           - Content character set
146
+	 *     cid               - Content ID to apply
147
+	 *     disposition       - Content disposition, inline or attachment
148
+	 *     filename          - Filename parameter for content disposition
149
+	 *     description       - Content description
150
+	 *     name_encoding     - Encoding of the attachment name (Content-Type)
151
+	 *                         By default filenames are encoded using RFC2231
152
+	 *                         Here you can set RFC2047 encoding (quoted-printable
153
+	 *                         or base64) instead
154
+	 *     filename_encoding - Encoding of the attachment filename (Content-Disposition)
155
+	 *                         See 'name_encoding'
156
+	 *     headers_charset   - Charset of the headers e.g. filename, description.
157
+	 *                         If not set, 'charset' will be used
158
+	 *     eol               - End of line sequence. Default: "\r\n"
159
+	 *     headers           - Hash array with additional part headers. Array keys can be
160
+	 *                         in form of <header_name>:<parameter_name>
161
+	 *     body_file         - Location of file with part's body (instead of $body)
162
+	 *
163
+	 * @access public
164
+	 */
165
+	function Mail_mimePart($body = '', $params = array())
166
+	{
167
+		if (!empty($params['eol'])) {
168
+			$this->_eol = $params['eol'];
169
+		} else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat.
170
+			$this->_eol = MAIL_MIMEPART_CRLF;
171
+		}
172
+
173
+		// Additional part headers
174
+		if (!empty($params['headers']) && is_array($params['headers'])) {
175
+			$headers = $params['headers'];
176
+		}
177
+
178
+		foreach ($params as $key => $value) {
179
+			switch ($key) {
180
+			case 'encoding':
181
+				$this->_encoding = $value;
182
+				$headers['Content-Transfer-Encoding'] = $value;
183
+				break;
184
+
185
+			case 'cid':
186
+				$headers['Content-ID'] = '<' . $value . '>';
187
+				break;
188
+
189
+			case 'location':
190
+				$headers['Content-Location'] = $value;
191
+				break;
192
+
193
+			case 'body_file':
194
+				$this->_body_file = $value;
195
+				break;
196
+
197
+			// for backward compatibility
198
+			case 'dfilename':
199
+				$params['filename'] = $value;
200
+				break;
201
+			}
202
+		}
203
+
204
+		// Default content-type
205
+		if (empty($params['content_type'])) {
206
+			$params['content_type'] = 'text/plain';
207
+		}
208
+
209
+		// Content-Type
210
+		$headers['Content-Type'] = $params['content_type'];
211
+		if (!empty($params['charset'])) {
212
+			$charset = "charset={$params['charset']}";
213
+			// place charset parameter in the same line, if possible
214
+			if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) {
215
+				$headers['Content-Type'] .= '; ';
216
+			} else {
217
+				$headers['Content-Type'] .= ';' . $this->_eol . ' ';
218
+			}
219
+			$headers['Content-Type'] .= $charset;
220
+
221
+			// Default headers charset
222
+			if (!isset($params['headers_charset'])) {
223
+				$params['headers_charset'] = $params['charset'];
224
+			}
225
+		}
226
+
227
+		// header values encoding parameters
228
+		$h_charset  = !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII';
229
+		$h_language = !empty($params['language']) ? $params['language'] : null;
230
+		$h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null;
231
+
232
+
233
+		if (!empty($params['filename'])) {
234
+			$headers['Content-Type'] .= ';' . $this->_eol;
235
+			$headers['Content-Type'] .= $this->_buildHeaderParam(
236
+				'name', $params['filename'], $h_charset, $h_language, $h_encoding
237
+			);
238
+		}
239
+
240
+		// Content-Disposition
241
+		if (!empty($params['disposition'])) {
242
+			$headers['Content-Disposition'] = $params['disposition'];
243
+			if (!empty($params['filename'])) {
244
+				$headers['Content-Disposition'] .= ';' . $this->_eol;
245
+				$headers['Content-Disposition'] .= $this->_buildHeaderParam(
246
+					'filename', $params['filename'], $h_charset, $h_language,
247
+					!empty($params['filename_encoding']) ? $params['filename_encoding'] : null
248
+				);
249
+			}
250
+
251
+			// add attachment size
252
+			$size = $this->_body_file ? filesize($this->_body_file) : strlen($body);
253
+			if ($size) {
254
+				$headers['Content-Disposition'] .= ';' . $this->_eol . ' size=' . $size;
255
+			}
256
+		}
257
+
258
+		if (!empty($params['description'])) {
259
+			$headers['Content-Description'] = $this->encodeHeader(
260
+				'Content-Description', $params['description'], $h_charset, $h_encoding,
261
+				$this->_eol
262
+			);
263
+		}
264
+
265
+		// Search and add existing headers' parameters
266
+		foreach ($headers as $key => $value) {
267
+			$items = explode(':', $key);
268
+			if (count($items) == 2) {
269
+				$header = $items[0];
270
+				$param  = $items[1];
271
+				if (isset($headers[$header])) {
272
+					$headers[$header] .= ';' . $this->_eol;
273
+				}
274
+				$headers[$header] .= $this->_buildHeaderParam(
275
+					$param, $value, $h_charset, $h_language, $h_encoding
276
+				);
277
+				unset($headers[$key]);
278
+			}
279
+		}
280
+
281
+		// Default encoding
282
+		if (!isset($this->_encoding)) {
283
+			$this->_encoding = '7bit';
284
+		}
285
+
286
+		// Assign stuff to member variables
287
+		$this->_encoded  = array();
288
+		$this->_headers  = $headers;
289
+		$this->_body     = $body;
290
+	}
291
+
292
+	/**
293
+	 * Encodes and returns the email. Also stores
294
+	 * it in the encoded member variable
295
+	 *
296
+	 * @param string $boundary Pre-defined boundary string
297
+	 *
298
+	 * @return An associative array containing two elements,
299
+	 *         body and headers. The headers element is itself
300
+	 *         an indexed array. On error returns PEAR error object.
301
+	 * @access public
302
+	 */
303
+	function encode($boundary=null)
304
+	{
305
+		$encoded =& $this->_encoded;
306
+
307
+		if (count($this->_subparts)) {
308
+			$boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
309
+			$eol = $this->_eol;
310
+
311
+			$this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
312
+
313
+			$encoded['body'] = ''; 
314
+
315
+			for ($i = 0; $i < count($this->_subparts); $i++) {
316
+				$encoded['body'] .= '--' . $boundary . $eol;
317
+				$tmp = $this->_subparts[$i]->encode();
318
+				if ($this->_isError($tmp)) {
319
+					return $tmp;
320
+				}
321
+				foreach ($tmp['headers'] as $key => $value) {
322
+					$encoded['body'] .= $key . ': ' . $value . $eol;
323
+				}
324
+				$encoded['body'] .= $eol . $tmp['body'] . $eol;
325
+			}
326
+
327
+			$encoded['body'] .= '--' . $boundary . '--' . $eol;
328
+
329
+		} else if ($this->_body) {
330
+			$encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding);
331
+		} else if ($this->_body_file) {
332
+			// Temporarily reset magic_quotes_runtime for file reads and writes
333
+			if ($magic_quote_setting = get_magic_quotes_runtime()) {
334
+				@ini_set('magic_quotes_runtime', 0);
335
+			}
336
+			$body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding);
337
+			if ($magic_quote_setting) {
338
+				@ini_set('magic_quotes_runtime', $magic_quote_setting);
339
+			}
340
+
341
+			if ($this->_isError($body)) {
342
+				return $body;
343
+			}
344
+			$encoded['body'] = $body;
345
+		} else {
346
+			$encoded['body'] = '';
347
+		}
348
+
349
+		// Add headers to $encoded
350
+		$encoded['headers'] =& $this->_headers;
351
+
352
+		return $encoded;
353
+	}
354
+
355
+	/**
356
+	 * Encodes and saves the email into file. File must exist.
357
+	 * Data will be appended to the file.
358
+	 *
359
+	 * @param string  $filename  Output file location
360
+	 * @param string  $boundary  Pre-defined boundary string
361
+	 * @param boolean $skip_head True if you don't want to save headers
362
+	 *
363
+	 * @return array An associative array containing message headers
364
+	 *               or PEAR error object
365
+	 * @access public
366
+	 * @since 1.6.0
367
+	 */
368
+	function encodeToFile($filename, $boundary=null, $skip_head=false)
369
+	{
370
+		if (file_exists($filename) && !is_writable($filename)) {
371
+			$err = $this->_raiseError('File is not writeable: ' . $filename);
372
+			return $err;
373
+		}
374
+
375
+		if (!($fh = fopen($filename, 'ab'))) {
376
+			$err = $this->_raiseError('Unable to open file: ' . $filename);
377
+			return $err;
378
+		}
379
+
380
+		// Temporarily reset magic_quotes_runtime for file reads and writes
381
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
382
+			@ini_set('magic_quotes_runtime', 0);
383
+		}
384
+
385
+		$res = $this->_encodePartToFile($fh, $boundary, $skip_head);
386
+
387
+		fclose($fh);
388
+
389
+		if ($magic_quote_setting) {
390
+			@ini_set('magic_quotes_runtime', $magic_quote_setting);
391
+		}
392
+
393
+		return $this->_isError($res) ? $res : $this->_headers;
394
+	}
395
+
396
+	/**
397
+	 * Encodes given email part into file
398
+	 *
399
+	 * @param string  $fh        Output file handle
400
+	 * @param string  $boundary  Pre-defined boundary string
401
+	 * @param boolean $skip_head True if you don't want to save headers
402
+	 *
403
+	 * @return array True on sucess or PEAR error object
404
+	 * @access private
405
+	 */
406
+	function _encodePartToFile($fh, $boundary=null, $skip_head=false)
407
+	{
408
+		$eol = $this->_eol;
409
+
410
+		if (count($this->_subparts)) {
411
+			$boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
412
+			$this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
413
+		}
414
+
415
+		if (!$skip_head) {
416
+			foreach ($this->_headers as $key => $value) {
417
+				fwrite($fh, $key . ': ' . $value . $eol);
418
+			}
419
+			$f_eol = $eol;
420
+		} else {
421
+			$f_eol = '';
422
+		}
423
+
424
+		if (count($this->_subparts)) {
425
+			for ($i = 0; $i < count($this->_subparts); $i++) {
426
+				fwrite($fh, $f_eol . '--' . $boundary . $eol);
427
+				$res = $this->_subparts[$i]->_encodePartToFile($fh);
428
+				if ($this->_isError($res)) {
429
+					return $res;
430
+				}
431
+				$f_eol = $eol;
432
+			}
433
+
434
+			fwrite($fh, $eol . '--' . $boundary . '--' . $eol);
435
+
436
+		} else if ($this->_body) {
437
+			fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding));
438
+		} else if ($this->_body_file) {
439
+			fwrite($fh, $f_eol);
440
+			$res = $this->_getEncodedDataFromFile(
441
+				$this->_body_file, $this->_encoding, $fh
442
+			);
443
+			if ($this->_isError($res)) {
444
+				return $res;
445
+			}
446
+		}
447
+
448
+		return true;
449
+	}
450
+
451
+	/**
452
+	 * Adds a subpart to current mime part and returns
453
+	 * a reference to it
454
+	 *
455
+	 * @param string $body   The body of the subpart, if any.
456
+	 * @param array  $params The parameters for the subpart, same
457
+	 *                       as the $params argument for constructor.
458
+	 *
459
+	 * @return Mail_mimePart A reference to the part you just added. In PHP4, it is
460
+	 *                       crucial if using multipart/* in your subparts that
461
+	 *                       you use =& in your script when calling this function,
462
+	 *                       otherwise you will not be able to add further subparts.
463
+	 * @access public
464
+	 */
465
+	function &addSubpart($body, $params)
466
+	{
467
+		$this->_subparts[] = $part = new Mail_mimePart($body, $params);
468
+		return $part;
469
+	}
470
+
471
+	/**
472
+	 * Returns encoded data based upon encoding passed to it
473
+	 *
474
+	 * @param string $data     The data to encode.
475
+	 * @param string $encoding The encoding type to use, 7bit, base64,
476
+	 *                         or quoted-printable.
477
+	 *
478
+	 * @return string
479
+	 * @access private
480
+	 */
481
+	function _getEncodedData($data, $encoding)
482
+	{
483
+		switch ($encoding) {
484
+		case 'quoted-printable':
485
+			return $this->_quotedPrintableEncode($data);
486
+			break;
487
+
488
+		case 'base64':
489
+			return rtrim(chunk_split(base64_encode($data), 76, $this->_eol));
490
+			break;
491
+
492
+		case '8bit':
493
+		case '7bit':
494
+		default:
495
+			return $data;
496
+		}
497
+	}
498
+
499
+	/**
500
+	 * Returns encoded data based upon encoding passed to it
501
+	 *
502
+	 * @param string   $filename Data file location
503
+	 * @param string   $encoding The encoding type to use, 7bit, base64,
504
+	 *                           or quoted-printable.
505
+	 * @param resource $fh       Output file handle. If set, data will be
506
+	 *                           stored into it instead of returning it
507
+	 *
508
+	 * @return string Encoded data or PEAR error object
509
+	 * @access private
510
+	 */
511
+	function _getEncodedDataFromFile($filename, $encoding, $fh=null)
512
+	{
513
+		if (!is_readable($filename)) {
514
+			$err = $this->_raiseError('Unable to read file: ' . $filename);
515
+			return $err;
516
+		}
517
+
518
+		if (!($fd = fopen($filename, 'rb'))) {
519
+			$err = $this->_raiseError('Could not open file: ' . $filename);
520
+			return $err;
521
+		}
522
+
523
+		$data = '';
524
+
525
+		switch ($encoding) {
526
+		case 'quoted-printable':
527
+			while (!feof($fd)) {
528
+				$buffer = $this->_quotedPrintableEncode(fgets($fd));
529
+				if ($fh) {
530
+					fwrite($fh, $buffer);
531
+				} else {
532
+					$data .= $buffer;
533
+				}
534
+			}
535
+			break;
536
+
537
+		case 'base64':
538
+			while (!feof($fd)) {
539
+				// Should read in a multiple of 57 bytes so that
540
+				// the output is 76 bytes per line. Don't use big chunks
541
+				// because base64 encoding is memory expensive
542
+				$buffer = fread($fd, 57 * 9198); // ca. 0.5 MB
543
+				$buffer = base64_encode($buffer);
544
+				$buffer = chunk_split($buffer, 76, $this->_eol);
545
+				if (feof($fd)) {
546
+					$buffer = rtrim($buffer);
547
+				}
548
+
549
+				if ($fh) {
550
+					fwrite($fh, $buffer);
551
+				} else {
552
+					$data .= $buffer;
553
+				}
554
+			}
555
+			break;
556
+
557
+		case '8bit':
558
+		case '7bit':
559
+		default:
560
+			while (!feof($fd)) {
561
+				$buffer = fread($fd, 1048576); // 1 MB
562
+				if ($fh) {
563
+					fwrite($fh, $buffer);
564
+				} else {
565
+					$data .= $buffer;
566
+				}
567
+			}
568
+		}
569
+
570
+		fclose($fd);
571
+
572
+		if (!$fh) {
573
+			return $data;
574
+		}
575
+	}
576
+
577
+	/**
578
+	 * Encodes data to quoted-printable standard.
579
+	 *
580
+	 * @param string $input    The data to encode
581
+	 * @param int    $line_max Optional max line length. Should
582
+	 *                         not be more than 76 chars
583
+	 *
584
+	 * @return string Encoded data
585
+	 *
586
+	 * @access private
587
+	 */
588
+	function _quotedPrintableEncode($input , $line_max = 76)
589
+	{
590
+		$eol = $this->_eol;
591
+		/*
592 592
         // imap_8bit() is extremely fast, but doesn't handle properly some characters
593 593
         if (function_exists('imap_8bit') && $line_max == 76) {
594 594
             $input = preg_replace('/\r?\n/', "\r\n", $input);
@@ -599,662 +599,662 @@  discard block
 block discarded – undo
599 599
             return $input;
600 600
         }
601 601
         */
602
-        $lines  = preg_split("/\r?\n/", $input);
603
-        $escape = '=';
604
-        $output = '';
605
-
606
-        while (list($idx, $line) = each($lines)) {
607
-            $newline = '';
608
-            $i = 0;
609
-
610
-            while (isset($line[$i])) {
611
-                $char = $line[$i];
612
-                $dec  = ord($char);
613
-                $i++;
614
-
615
-                if (($dec == 32) && (!isset($line[$i]))) {
616
-                    // convert space at eol only
617
-                    $char = '=20';
618
-                } elseif ($dec == 9 && isset($line[$i])) {
619
-                    ; // Do nothing if a TAB is not on eol
620
-                } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
621
-                    $char = $escape . sprintf('%02X', $dec);
622
-                } elseif (($dec == 46) && (($newline == '')
623
-                    || ((strlen($newline) + strlen("=2E")) >= $line_max))
624
-                ) {
625
-                    // Bug #9722: convert full-stop at bol,
626
-                    // some Windows servers need this, won't break anything (cipri)
627
-                    // Bug #11731: full-stop at bol also needs to be encoded
628
-                    // if this line would push us over the line_max limit.
629
-                    $char = '=2E';
630
-                }
631
-
632
-                // Note, when changing this line, also change the ($dec == 46)
633
-                // check line, as it mimics this line due to Bug #11731
634
-                // EOL is not counted
635
-                if ((strlen($newline) + strlen($char)) >= $line_max) {
636
-                    // soft line break; " =\r\n" is okay
637
-                    $output  .= $newline . $escape . $eol;
638
-                    $newline  = '';
639
-                }
640
-                $newline .= $char;
641
-            } // end of for
642
-            $output .= $newline . $eol;
643
-            unset($lines[$idx]);
644
-        }
645
-        // Don't want last crlf
646
-        $output = substr($output, 0, -1 * strlen($eol));
647
-        return $output;
648
-    }
649
-
650
-    /**
651
-     * Encodes the parameter of a header.
652
-     *
653
-     * @param string $name      The name of the header-parameter
654
-     * @param string $value     The value of the paramter
655
-     * @param string $charset   The characterset of $value
656
-     * @param string $language  The language used in $value
657
-     * @param string $encoding  Parameter encoding. If not set, parameter value
658
-     *                          is encoded according to RFC2231
659
-     * @param int    $maxLength The maximum length of a line. Defauls to 75
660
-     *
661
-     * @return string
662
-     *
663
-     * @access private
664
-     */
665
-    function _buildHeaderParam($name, $value, $charset=null, $language=null,
666
-        $encoding=null, $maxLength=75
667
-    ) {
668
-        // RFC 2045:
669
-        // value needs encoding if contains non-ASCII chars or is longer than 78 chars
670
-        if (!preg_match('#[^\x20-\x7E]#', $value)) {
671
-            $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
672
-                . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
673
-            if (!preg_match($token_regexp, $value)) {
674
-                // token
675
-                if (strlen($name) + strlen($value) + 3 <= $maxLength) {
676
-                    return " {$name}={$value}";
677
-                }
678
-            } else {
679
-                // quoted-string
680
-                $quoted = addcslashes($value, '\\"');
681
-                if (strlen($name) + strlen($quoted) + 5 <= $maxLength) {
682
-                    return " {$name}=\"{$quoted}\"";
683
-                }
684
-            }
685
-        }
686
-
687
-        // RFC2047: use quoted-printable/base64 encoding
688
-        if ($encoding == 'quoted-printable' || $encoding == 'base64') {
689
-            return $this->_buildRFC2047Param($name, $value, $charset, $encoding);
690
-        }
691
-
692
-        // RFC2231:
693
-        $encValue = preg_replace_callback(
694
-            '/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/',
695
-            array($this, '_encodeReplaceCallback'), $value
696
-        );
697
-        $value = "$charset'$language'$encValue";
698
-
699
-        $header = " {$name}*={$value}";
700
-        if (strlen($header) <= $maxLength) {
701
-            return $header;
702
-        }
703
-
704
-        $preLength = strlen(" {$name}*0*=");
705
-        $maxLength = max(16, $maxLength - $preLength - 3);
706
-        $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";
707
-
708
-        $headers = array();
709
-        $headCount = 0;
710
-        while ($value) {
711
-            $matches = array();
712
-            $found = preg_match($maxLengthReg, $value, $matches);
713
-            if ($found) {
714
-                $headers[] = " {$name}*{$headCount}*={$matches[0]}";
715
-                $value = substr($value, strlen($matches[0]));
716
-            } else {
717
-                $headers[] = " {$name}*{$headCount}*={$value}";
718
-                $value = '';
719
-            }
720
-            $headCount++;
721
-        }
722
-
723
-        $headers = implode(';' . $this->_eol, $headers);
724
-        return $headers;
725
-    }
726
-
727
-    /**
728
-     * Encodes header parameter as per RFC2047 if needed
729
-     *
730
-     * @param string $name      The parameter name
731
-     * @param string $value     The parameter value
732
-     * @param string $charset   The parameter charset
733
-     * @param string $encoding  Encoding type (quoted-printable or base64)
734
-     * @param int    $maxLength Encoded parameter max length. Default: 76
735
-     *
736
-     * @return string Parameter line
737
-     * @access private
738
-     */
739
-    function _buildRFC2047Param($name, $value, $charset,
740
-        $encoding='quoted-printable', $maxLength=76
741
-    ) {
742
-        // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in
743
-        // parameter of a MIME Content-Type or Content-Disposition field",
744
-        // but... it's supported by many clients/servers
745
-        $quoted = '';
746
-
747
-        if ($encoding == 'base64') {
748
-            $value = base64_encode($value);
749
-            $prefix = '=?' . $charset . '?B?';
750
-            $suffix = '?=';
751
-
752
-            // 2 x SPACE, 2 x '"', '=', ';'
753
-            $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
754
-            $len = $add_len + strlen($value);
755
-
756
-            while ($len > $maxLength) { 
757
-                // We can cut base64-encoded string every 4 characters
758
-                $real_len = floor(($maxLength - $add_len) / 4) * 4;
759
-                $_quote = substr($value, 0, $real_len);
760
-                $value = substr($value, $real_len);
761
-
762
-                $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
763
-                $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
764
-                $len = strlen($value) + $add_len;
765
-            }
766
-            $quoted .= $prefix . $value . $suffix;
767
-
768
-        } else {
769
-            // quoted-printable
770
-            $value = $this->encodeQP($value);
771
-            $prefix = '=?' . $charset . '?Q?';
772
-            $suffix = '?=';
773
-
774
-            // 2 x SPACE, 2 x '"', '=', ';'
775
-            $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
776
-            $len = $add_len + strlen($value);
777
-
778
-            while ($len > $maxLength) {
779
-                $length = $maxLength - $add_len;
780
-                // don't break any encoded letters
781
-                if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) {
782
-                    $_quote = $matches[1];
783
-                }
784
-
785
-                $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
786
-                $value = substr($value, strlen($_quote));
787
-                $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
788
-                $len = strlen($value) + $add_len;
789
-            }
790
-
791
-            $quoted .= $prefix . $value . $suffix;
792
-        }
793
-
794
-        return " {$name}=\"{$quoted}\"";
795
-    }
796
-
797
-    /**
798
-     * Encodes a header as per RFC2047
799
-     *
800
-     * @param string $name     The header name
801
-     * @param string $value    The header data to encode
802
-     * @param string $charset  Character set name
803
-     * @param string $encoding Encoding name (base64 or quoted-printable)
804
-     * @param string $eol      End-of-line sequence. Default: "\r\n"
805
-     *
806
-     * @return string          Encoded header data (without a name)
807
-     * @access public
808
-     * @since 1.6.1
809
-     */
810
-    function encodeHeader($name, $value, $charset='ISO-8859-1',
811
-        $encoding='quoted-printable', $eol="\r\n"
812
-    ) {
813
-        // Structured headers
814
-        $comma_headers = array(
815
-            'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
816
-            'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
817
-            'resent-sender', 'resent-reply-to',
818
-            'mail-reply-to', 'mail-followup-to',
819
-            'return-receipt-to', 'disposition-notification-to',
820
-        );
821
-        $other_headers = array(
822
-            'references', 'in-reply-to', 'message-id', 'resent-message-id',
823
-        );
824
-
825
-        $name = strtolower($name);
826
-
827
-        if (in_array($name, $comma_headers)) {
828
-            $separator = ',';
829
-        } else if (in_array($name, $other_headers)) {
830
-            $separator = ' ';
831
-        }
832
-
833
-        if (!$charset) {
834
-            $charset = 'ISO-8859-1';
835
-        }
836
-
837
-        // Structured header (make sure addr-spec inside is not encoded)
838
-        if (!empty($separator)) {
839
-            // Simple e-mail address regexp
840
-            $email_regexp = '([^\s<]+|("[^\r\n"]+"))@\S+';
841
-
842
-            $parts = Mail_mimePart::_explodeQuotedString("[\t$separator]", $value);
843
-            $value = '';
844
-
845
-            foreach ($parts as $part) {
846
-                $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part);
847
-                $part = trim($part);
848
-
849
-                if (!$part) {
850
-                    continue;
851
-                }
852
-                if ($value) {
853
-                    $value .= $separator == ',' ? $separator . ' ' : ' ';
854
-                } else {
855
-                    $value = $name . ': ';
856
-                }
857
-
858
-                // let's find phrase (name) and/or addr-spec
859
-                if (preg_match('/^<' . $email_regexp . '>$/', $part)) {
860
-                    $value .= $part;
861
-                } else if (preg_match('/^' . $email_regexp . '$/', $part)) {
862
-                    // address without brackets and without name
863
-                    $value .= $part;
864
-                } else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) {
865
-                    // address with name (handle name)
866
-                    $address = $matches[0];
867
-                    $word = str_replace($address, '', $part);
868
-                    $word = trim($word);
869
-                    // check if phrase requires quoting
870
-                    if ($word) {
871
-                        // non-ASCII: require encoding
872
-                        if (preg_match('#([^\s\x21-\x7E]){1}#', $word)) {
873
-                            if ($word[0] == '"' && $word[strlen($word)-1] == '"') {
874
-                                // de-quote quoted-string, encoding changes
875
-                                // string to atom
876
-                                $search = array("\\\"", "\\\\");
877
-                                $replace = array("\"", "\\");
878
-                                $word = str_replace($search, $replace, $word);
879
-                                $word = substr($word, 1, -1);
880
-                            }
881
-                            // find length of last line
882
-                            if (($pos = strrpos($value, $eol)) !== false) {
883
-                                $last_len = strlen($value) - $pos;
884
-                            } else {
885
-                                $last_len = strlen($value);
886
-                            }
887
-                            $word = Mail_mimePart::encodeHeaderValue(
888
-                                $word, $charset, $encoding, $last_len, $eol
889
-                            );
890
-                        } else if (($word[0] != '"' || $word[strlen($word)-1] != '"')
891
-                            && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word)
892
-                        ) {
893
-                            // ASCII: quote string if needed
894
-                            $word = '"'.addcslashes($word, '\\"').'"';
895
-                        }
896
-                    }
897
-                    $value .= $word.' '.$address;
898
-                } else {
899
-                    // addr-spec not found, don't encode (?)
900
-                    $value .= $part;
901
-                }
902
-
903
-                // RFC2822 recommends 78 characters limit, use 76 from RFC2047
904
-                $value = wordwrap($value, 76, $eol . ' ');
905
-            }
906
-
907
-            // remove header name prefix (there could be EOL too)
908
-            $value = preg_replace(
909
-                '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value
910
-            );
911
-        } else {
912
-            // Unstructured header
913
-            // non-ASCII: require encoding
914
-            if (preg_match('#([^\s\x21-\x7E]){1}#', $value)) {
915
-                if ($value[0] == '"' && $value[strlen($value)-1] == '"') {
916
-                    // de-quote quoted-string, encoding changes
917
-                    // string to atom
918
-                    $search = array("\\\"", "\\\\");
919
-                    $replace = array("\"", "\\");
920
-                    $value = str_replace($search, $replace, $value);
921
-                    $value = substr($value, 1, -1);
922
-                }
923
-                $value = Mail_mimePart::encodeHeaderValue(
924
-                    $value, $charset, $encoding, strlen($name) + 2, $eol
925
-                );
926
-            } else if (strlen($name.': '.$value) > 78) {
927
-                // ASCII: check if header line isn't too long and use folding
928
-                $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value);
929
-                $tmp = wordwrap($name.': '.$value, 78, $eol . ' ');
930
-                $value = preg_replace('/^'.$name.':\s*/', '', $tmp);
931
-                // hard limit 998 (RFC2822)
932
-                $value = wordwrap($value, 998, $eol . ' ', true);
933
-            }
934
-        }
935
-
936
-        return $value;
937
-    }
938
-
939
-    /**
940
-     * Explode quoted string
941
-     *
942
-     * @param string $delimiter Delimiter expression string for preg_match()
943
-     * @param string $string    Input string
944
-     *
945
-     * @return array            String tokens array
946
-     * @access private
947
-     */
948
-    function _explodeQuotedString($delimiter, $string)
949
-    {
950
-        $result = array();
951
-        $strlen = strlen($string);
952
-
953
-        for ($q=$p=$i=0; $i < $strlen; $i++) {
954
-            if ($string[$i] == "\""
955
-                && (empty($string[$i-1]) || $string[$i-1] != "\\")
956
-            ) {
957
-                $q = $q ? false : true;
958
-            } else if (!$q && preg_match("/$delimiter/", $string[$i])) {
959
-                $result[] = substr($string, $p, $i - $p);
960
-                $p = $i + 1;
961
-            }
962
-        }
963
-
964
-        $result[] = substr($string, $p);
965
-        return $result;
966
-    }
967
-
968
-    /**
969
-     * Encodes a header value as per RFC2047
970
-     *
971
-     * @param string $value      The header data to encode
972
-     * @param string $charset    Character set name
973
-     * @param string $encoding   Encoding name (base64 or quoted-printable)
974
-     * @param int    $prefix_len Prefix length. Default: 0
975
-     * @param string $eol        End-of-line sequence. Default: "\r\n"
976
-     *
977
-     * @return string            Encoded header data
978
-     * @access public
979
-     * @since 1.6.1
980
-     */
981
-    function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n")
982
-    {
983
-        // #17311: Use multibyte aware method (requires mbstring extension)
984
-        if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) {
985
-            return $result;
986
-        }
987
-
988
-        // Generate the header using the specified params and dynamicly
989
-        // determine the maximum length of such strings.
990
-        // 75 is the value specified in the RFC.
991
-        $encoding = $encoding == 'base64' ? 'B' : 'Q';
992
-        $prefix = '=?' . $charset . '?' . $encoding .'?';
993
-        $suffix = '?=';
994
-        $maxLength = 75 - strlen($prefix . $suffix);
995
-        $maxLength1stLine = $maxLength - $prefix_len;
996
-
997
-        if ($encoding == 'B') {
998
-            // Base64 encode the entire string
999
-            $value = base64_encode($value);
1000
-
1001
-            // We can cut base64 every 4 characters, so the real max
1002
-            // we can get must be rounded down.
1003
-            $maxLength = $maxLength - ($maxLength % 4);
1004
-            $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4);
1005
-
1006
-            $cutpoint = $maxLength1stLine;
1007
-            $output = '';
1008
-
1009
-            while ($value) {
1010
-                // Split translated string at every $maxLength
1011
-                $part = substr($value, 0, $cutpoint);
1012
-                $value = substr($value, $cutpoint);
1013
-                $cutpoint = $maxLength;
1014
-                // RFC 2047 specifies that any split header should
1015
-                // be separated by a CRLF SPACE.
1016
-                if ($output) {
1017
-                    $output .= $eol . ' ';
1018
-                }
1019
-                $output .= $prefix . $part . $suffix;
1020
-            }
1021
-            $value = $output;
1022
-        } else {
1023
-            // quoted-printable encoding has been selected
1024
-            $value = Mail_mimePart::encodeQP($value);
1025
-
1026
-            // This regexp will break QP-encoded text at every $maxLength
1027
-            // but will not break any encoded letters.
1028
-            $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|";
1029
-            $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|";
1030
-
1031
-            if (strlen($value) > $maxLength1stLine) {
1032
-                // Begin with the regexp for the first line.
1033
-                $reg = $reg1st;
1034
-                $output = '';
1035
-                while ($value) {
1036
-                    // Split translated string at every $maxLength
1037
-                    // But make sure not to break any translated chars.
1038
-                    $found = preg_match($reg, $value, $matches);
1039
-
1040
-                    // After this first line, we need to use a different
1041
-                    // regexp for the first line.
1042
-                    $reg = $reg2nd;
1043
-
1044
-                    // Save the found part and encapsulate it in the
1045
-                    // prefix & suffix. Then remove the part from the
1046
-                    // $value_out variable.
1047
-                    if ($found) {
1048
-                        $part = $matches[0];
1049
-                        $len = strlen($matches[0]);
1050
-                        $value = substr($value, $len);
1051
-                    } else {
1052
-                        $part = $value;
1053
-                        $value = '';
1054
-                    }
1055
-
1056
-                    // RFC 2047 specifies that any split header should
1057
-                    // be separated by a CRLF SPACE
1058
-                    if ($output) {
1059
-                        $output .= $eol . ' ';
1060
-                    }
1061
-                    $output .= $prefix . $part . $suffix;
1062
-                }
1063
-                $value = $output;
1064
-            } else {
1065
-                $value = $prefix . $value . $suffix;
1066
-            }
1067
-        }
1068
-
1069
-        return $value;
1070
-    }
1071
-
1072
-    /**
1073
-     * Encodes the given string using quoted-printable
1074
-     *
1075
-     * @param string $str String to encode
1076
-     *
1077
-     * @return string     Encoded string
1078
-     * @access public
1079
-     * @since 1.6.0
1080
-     */
1081
-    function encodeQP($str)
1082
-    {
1083
-        // Bug #17226 RFC 2047 restricts some characters
1084
-        // if the word is inside a phrase, permitted chars are only:
1085
-        // ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
1086
-
1087
-        // "=",  "_",  "?" must be encoded
1088
-        $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1089
-        $str = preg_replace_callback(
1090
-            $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str
1091
-        );
1092
-
1093
-        return str_replace(' ', '_', $str);
1094
-    }
1095
-
1096
-    /**
1097
-     * Encodes the given string using base64 or quoted-printable.
1098
-     * This method makes sure that encoded-word represents an integral
1099
-     * number of characters as per RFC2047.
1100
-     *
1101
-     * @param string $str        String to encode
1102
-     * @param string $charset    Character set name
1103
-     * @param string $encoding   Encoding name (base64 or quoted-printable)
1104
-     * @param int    $prefix_len Prefix length. Default: 0
1105
-     * @param string $eol        End-of-line sequence. Default: "\r\n"
1106
-     *
1107
-     * @return string     Encoded string
1108
-     * @access public
1109
-     * @since 1.8.0
1110
-     */
1111
-    function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n")
1112
-    {
1113
-        if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
1114
-            return;
1115
-        }
1116
-
1117
-        $encoding = $encoding == 'base64' ? 'B' : 'Q';
1118
-        // 75 is the value specified in the RFC
1119
-        $prefix = '=?' . $charset . '?'.$encoding.'?';
1120
-        $suffix = '?=';
1121
-        $maxLength = 75 - strlen($prefix . $suffix);
1122
-
1123
-        // A multi-octet character may not be split across adjacent encoded-words
1124
-        // So, we'll loop over each character
1125
-        // mb_stlen() with wrong charset will generate a warning here and return null
1126
-        $length      = mb_strlen($str, $charset);
1127
-        $result      = '';
1128
-        $line_length = $prefix_len;
1129
-
1130
-        if ($encoding == 'B') {
1131
-            // base64
1132
-            $start = 0;
1133
-            $prev  = '';
1134
-
1135
-            for ($i=1; $i<=$length; $i++) {
1136
-                // See #17311
1137
-                $chunk = mb_substr($str, $start, $i-$start, $charset);
1138
-                $chunk = base64_encode($chunk);
1139
-                $chunk_len = strlen($chunk);
1140
-
1141
-                if ($line_length + $chunk_len == $maxLength || $i == $length) {
1142
-                    if ($result) {
1143
-                        $result .= "\n";
1144
-                    }
1145
-                    $result .= $chunk;
1146
-                    $line_length = 0;
1147
-                    $start = $i;
1148
-                } else if ($line_length + $chunk_len > $maxLength) {
1149
-                    if ($result) {
1150
-                        $result .= "\n";
1151
-                    }
1152
-                    if ($prev) {
1153
-                        $result .= $prev;
1154
-                    }
1155
-                    $line_length = 0;
1156
-                    $start = $i - 1;
1157
-                } else {
1158
-                    $prev = $chunk;
1159
-                }
1160
-            }
1161
-        } else {
1162
-            // quoted-printable
1163
-            // see encodeQP()
1164
-            $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1165
-
1166
-            for ($i=0; $i<=$length; $i++) {
1167
-                $char = mb_substr($str, $i, 1, $charset);
1168
-                // RFC recommends underline (instead of =20) in place of the space
1169
-                // that's one of the reasons why we're not using iconv_mime_encode()
1170
-                if ($char == ' ') {
1171
-                    $char = '_';
1172
-                    $char_len = 1;
1173
-                } else {
1174
-                    $char = preg_replace_callback(
1175
-                        $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char
1176
-                    );
1177
-                    $char_len = strlen($char);
1178
-                }
1179
-
1180
-                if ($line_length + $char_len > $maxLength) {
1181
-                    if ($result) {
1182
-                        $result .= "\n";
1183
-                    }
1184
-                    $line_length = 0;
1185
-                }
1186
-
1187
-                $result      .= $char;
1188
-                $line_length += $char_len;
1189
-            }
1190
-        }
1191
-
1192
-        if ($result) {
1193
-            $result = $prefix
1194
-                .str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix;
1195
-        }
1196
-
1197
-        return $result;
1198
-    }
1199
-
1200
-    /**
1201
-     * Callback function to replace extended characters (\x80-xFF) with their
1202
-     * ASCII values (RFC2047: quoted-printable)
1203
-     *
1204
-     * @param array $matches Preg_replace's matches array
1205
-     *
1206
-     * @return string        Encoded character string
1207
-     * @access private
1208
-     */
1209
-    function _qpReplaceCallback($matches)
1210
-    {
1211
-        return sprintf('=%02X', ord($matches[1]));
1212
-    }
1213
-
1214
-    /**
1215
-     * Callback function to replace extended characters (\x80-xFF) with their
1216
-     * ASCII values (RFC2231)
1217
-     *
1218
-     * @param array $matches Preg_replace's matches array
1219
-     *
1220
-     * @return string        Encoded character string
1221
-     * @access private
1222
-     */
1223
-    function _encodeReplaceCallback($matches)
1224
-    {
1225
-        return sprintf('%%%02X', ord($matches[1]));
1226
-    }
1227
-
1228
-    /**
1229
-     * PEAR::isError implementation
1230
-     *
1231
-     * @param mixed $data Object
1232
-     *
1233
-     * @return bool True if object is an instance of PEAR_Error
1234
-     * @access private
1235
-     */
1236
-    function _isError($data)
1237
-    {
1238
-        // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1239
-        if (is_object($data) && is_a($data, 'PEAR_Error')) {
1240
-            return true;
1241
-        }
1242
-
1243
-        return false;
1244
-    }
1245
-
1246
-    /**
1247
-     * PEAR::raiseError implementation
1248
-     *
1249
-     * @param $message A text error message
1250
-     *
1251
-     * @return PEAR_Error Instance of PEAR_Error
1252
-     * @access private
1253
-     */
1254
-    function _raiseError($message)
1255
-    {
1256
-        // PEAR::raiseError() is not PHP 5.4 compatible
1257
-        return new PEAR_Error($message);
1258
-    }
602
+		$lines  = preg_split("/\r?\n/", $input);
603
+		$escape = '=';
604
+		$output = '';
605
+
606
+		while (list($idx, $line) = each($lines)) {
607
+			$newline = '';
608
+			$i = 0;
609
+
610
+			while (isset($line[$i])) {
611
+				$char = $line[$i];
612
+				$dec  = ord($char);
613
+				$i++;
614
+
615
+				if (($dec == 32) && (!isset($line[$i]))) {
616
+					// convert space at eol only
617
+					$char = '=20';
618
+				} elseif ($dec == 9 && isset($line[$i])) {
619
+					; // Do nothing if a TAB is not on eol
620
+				} elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
621
+					$char = $escape . sprintf('%02X', $dec);
622
+				} elseif (($dec == 46) && (($newline == '')
623
+					|| ((strlen($newline) + strlen("=2E")) >= $line_max))
624
+				) {
625
+					// Bug #9722: convert full-stop at bol,
626
+					// some Windows servers need this, won't break anything (cipri)
627
+					// Bug #11731: full-stop at bol also needs to be encoded
628
+					// if this line would push us over the line_max limit.
629
+					$char = '=2E';
630
+				}
631
+
632
+				// Note, when changing this line, also change the ($dec == 46)
633
+				// check line, as it mimics this line due to Bug #11731
634
+				// EOL is not counted
635
+				if ((strlen($newline) + strlen($char)) >= $line_max) {
636
+					// soft line break; " =\r\n" is okay
637
+					$output  .= $newline . $escape . $eol;
638
+					$newline  = '';
639
+				}
640
+				$newline .= $char;
641
+			} // end of for
642
+			$output .= $newline . $eol;
643
+			unset($lines[$idx]);
644
+		}
645
+		// Don't want last crlf
646
+		$output = substr($output, 0, -1 * strlen($eol));
647
+		return $output;
648
+	}
649
+
650
+	/**
651
+	 * Encodes the parameter of a header.
652
+	 *
653
+	 * @param string $name      The name of the header-parameter
654
+	 * @param string $value     The value of the paramter
655
+	 * @param string $charset   The characterset of $value
656
+	 * @param string $language  The language used in $value
657
+	 * @param string $encoding  Parameter encoding. If not set, parameter value
658
+	 *                          is encoded according to RFC2231
659
+	 * @param int    $maxLength The maximum length of a line. Defauls to 75
660
+	 *
661
+	 * @return string
662
+	 *
663
+	 * @access private
664
+	 */
665
+	function _buildHeaderParam($name, $value, $charset=null, $language=null,
666
+		$encoding=null, $maxLength=75
667
+	) {
668
+		// RFC 2045:
669
+		// value needs encoding if contains non-ASCII chars or is longer than 78 chars
670
+		if (!preg_match('#[^\x20-\x7E]#', $value)) {
671
+			$token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
672
+				. '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
673
+			if (!preg_match($token_regexp, $value)) {
674
+				// token
675
+				if (strlen($name) + strlen($value) + 3 <= $maxLength) {
676
+					return " {$name}={$value}";
677
+				}
678
+			} else {
679
+				// quoted-string
680
+				$quoted = addcslashes($value, '\\"');
681
+				if (strlen($name) + strlen($quoted) + 5 <= $maxLength) {
682
+					return " {$name}=\"{$quoted}\"";
683
+				}
684
+			}
685
+		}
686
+
687
+		// RFC2047: use quoted-printable/base64 encoding
688
+		if ($encoding == 'quoted-printable' || $encoding == 'base64') {
689
+			return $this->_buildRFC2047Param($name, $value, $charset, $encoding);
690
+		}
691
+
692
+		// RFC2231:
693
+		$encValue = preg_replace_callback(
694
+			'/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/',
695
+			array($this, '_encodeReplaceCallback'), $value
696
+		);
697
+		$value = "$charset'$language'$encValue";
698
+
699
+		$header = " {$name}*={$value}";
700
+		if (strlen($header) <= $maxLength) {
701
+			return $header;
702
+		}
703
+
704
+		$preLength = strlen(" {$name}*0*=");
705
+		$maxLength = max(16, $maxLength - $preLength - 3);
706
+		$maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";
707
+
708
+		$headers = array();
709
+		$headCount = 0;
710
+		while ($value) {
711
+			$matches = array();
712
+			$found = preg_match($maxLengthReg, $value, $matches);
713
+			if ($found) {
714
+				$headers[] = " {$name}*{$headCount}*={$matches[0]}";
715
+				$value = substr($value, strlen($matches[0]));
716
+			} else {
717
+				$headers[] = " {$name}*{$headCount}*={$value}";
718
+				$value = '';
719
+			}
720
+			$headCount++;
721
+		}
722
+
723
+		$headers = implode(';' . $this->_eol, $headers);
724
+		return $headers;
725
+	}
726
+
727
+	/**
728
+	 * Encodes header parameter as per RFC2047 if needed
729
+	 *
730
+	 * @param string $name      The parameter name
731
+	 * @param string $value     The parameter value
732
+	 * @param string $charset   The parameter charset
733
+	 * @param string $encoding  Encoding type (quoted-printable or base64)
734
+	 * @param int    $maxLength Encoded parameter max length. Default: 76
735
+	 *
736
+	 * @return string Parameter line
737
+	 * @access private
738
+	 */
739
+	function _buildRFC2047Param($name, $value, $charset,
740
+		$encoding='quoted-printable', $maxLength=76
741
+	) {
742
+		// WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in
743
+		// parameter of a MIME Content-Type or Content-Disposition field",
744
+		// but... it's supported by many clients/servers
745
+		$quoted = '';
746
+
747
+		if ($encoding == 'base64') {
748
+			$value = base64_encode($value);
749
+			$prefix = '=?' . $charset . '?B?';
750
+			$suffix = '?=';
751
+
752
+			// 2 x SPACE, 2 x '"', '=', ';'
753
+			$add_len = strlen($prefix . $suffix) + strlen($name) + 6;
754
+			$len = $add_len + strlen($value);
755
+
756
+			while ($len > $maxLength) { 
757
+				// We can cut base64-encoded string every 4 characters
758
+				$real_len = floor(($maxLength - $add_len) / 4) * 4;
759
+				$_quote = substr($value, 0, $real_len);
760
+				$value = substr($value, $real_len);
761
+
762
+				$quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
763
+				$add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
764
+				$len = strlen($value) + $add_len;
765
+			}
766
+			$quoted .= $prefix . $value . $suffix;
767
+
768
+		} else {
769
+			// quoted-printable
770
+			$value = $this->encodeQP($value);
771
+			$prefix = '=?' . $charset . '?Q?';
772
+			$suffix = '?=';
773
+
774
+			// 2 x SPACE, 2 x '"', '=', ';'
775
+			$add_len = strlen($prefix . $suffix) + strlen($name) + 6;
776
+			$len = $add_len + strlen($value);
777
+
778
+			while ($len > $maxLength) {
779
+				$length = $maxLength - $add_len;
780
+				// don't break any encoded letters
781
+				if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) {
782
+					$_quote = $matches[1];
783
+				}
784
+
785
+				$quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
786
+				$value = substr($value, strlen($_quote));
787
+				$add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
788
+				$len = strlen($value) + $add_len;
789
+			}
790
+
791
+			$quoted .= $prefix . $value . $suffix;
792
+		}
793
+
794
+		return " {$name}=\"{$quoted}\"";
795
+	}
796
+
797
+	/**
798
+	 * Encodes a header as per RFC2047
799
+	 *
800
+	 * @param string $name     The header name
801
+	 * @param string $value    The header data to encode
802
+	 * @param string $charset  Character set name
803
+	 * @param string $encoding Encoding name (base64 or quoted-printable)
804
+	 * @param string $eol      End-of-line sequence. Default: "\r\n"
805
+	 *
806
+	 * @return string          Encoded header data (without a name)
807
+	 * @access public
808
+	 * @since 1.6.1
809
+	 */
810
+	function encodeHeader($name, $value, $charset='ISO-8859-1',
811
+		$encoding='quoted-printable', $eol="\r\n"
812
+	) {
813
+		// Structured headers
814
+		$comma_headers = array(
815
+			'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
816
+			'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
817
+			'resent-sender', 'resent-reply-to',
818
+			'mail-reply-to', 'mail-followup-to',
819
+			'return-receipt-to', 'disposition-notification-to',
820
+		);
821
+		$other_headers = array(
822
+			'references', 'in-reply-to', 'message-id', 'resent-message-id',
823
+		);
824
+
825
+		$name = strtolower($name);
826
+
827
+		if (in_array($name, $comma_headers)) {
828
+			$separator = ',';
829
+		} else if (in_array($name, $other_headers)) {
830
+			$separator = ' ';
831
+		}
832
+
833
+		if (!$charset) {
834
+			$charset = 'ISO-8859-1';
835
+		}
836
+
837
+		// Structured header (make sure addr-spec inside is not encoded)
838
+		if (!empty($separator)) {
839
+			// Simple e-mail address regexp
840
+			$email_regexp = '([^\s<]+|("[^\r\n"]+"))@\S+';
841
+
842
+			$parts = Mail_mimePart::_explodeQuotedString("[\t$separator]", $value);
843
+			$value = '';
844
+
845
+			foreach ($parts as $part) {
846
+				$part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part);
847
+				$part = trim($part);
848
+
849
+				if (!$part) {
850
+					continue;
851
+				}
852
+				if ($value) {
853
+					$value .= $separator == ',' ? $separator . ' ' : ' ';
854
+				} else {
855
+					$value = $name . ': ';
856
+				}
857
+
858
+				// let's find phrase (name) and/or addr-spec
859
+				if (preg_match('/^<' . $email_regexp . '>$/', $part)) {
860
+					$value .= $part;
861
+				} else if (preg_match('/^' . $email_regexp . '$/', $part)) {
862
+					// address without brackets and without name
863
+					$value .= $part;
864
+				} else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) {
865
+					// address with name (handle name)
866
+					$address = $matches[0];
867
+					$word = str_replace($address, '', $part);
868
+					$word = trim($word);
869
+					// check if phrase requires quoting
870
+					if ($word) {
871
+						// non-ASCII: require encoding
872
+						if (preg_match('#([^\s\x21-\x7E]){1}#', $word)) {
873
+							if ($word[0] == '"' && $word[strlen($word)-1] == '"') {
874
+								// de-quote quoted-string, encoding changes
875
+								// string to atom
876
+								$search = array("\\\"", "\\\\");
877
+								$replace = array("\"", "\\");
878
+								$word = str_replace($search, $replace, $word);
879
+								$word = substr($word, 1, -1);
880
+							}
881
+							// find length of last line
882
+							if (($pos = strrpos($value, $eol)) !== false) {
883
+								$last_len = strlen($value) - $pos;
884
+							} else {
885
+								$last_len = strlen($value);
886
+							}
887
+							$word = Mail_mimePart::encodeHeaderValue(
888
+								$word, $charset, $encoding, $last_len, $eol
889
+							);
890
+						} else if (($word[0] != '"' || $word[strlen($word)-1] != '"')
891
+							&& preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word)
892
+						) {
893
+							// ASCII: quote string if needed
894
+							$word = '"'.addcslashes($word, '\\"').'"';
895
+						}
896
+					}
897
+					$value .= $word.' '.$address;
898
+				} else {
899
+					// addr-spec not found, don't encode (?)
900
+					$value .= $part;
901
+				}
902
+
903
+				// RFC2822 recommends 78 characters limit, use 76 from RFC2047
904
+				$value = wordwrap($value, 76, $eol . ' ');
905
+			}
906
+
907
+			// remove header name prefix (there could be EOL too)
908
+			$value = preg_replace(
909
+				'/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value
910
+			);
911
+		} else {
912
+			// Unstructured header
913
+			// non-ASCII: require encoding
914
+			if (preg_match('#([^\s\x21-\x7E]){1}#', $value)) {
915
+				if ($value[0] == '"' && $value[strlen($value)-1] == '"') {
916
+					// de-quote quoted-string, encoding changes
917
+					// string to atom
918
+					$search = array("\\\"", "\\\\");
919
+					$replace = array("\"", "\\");
920
+					$value = str_replace($search, $replace, $value);
921
+					$value = substr($value, 1, -1);
922
+				}
923
+				$value = Mail_mimePart::encodeHeaderValue(
924
+					$value, $charset, $encoding, strlen($name) + 2, $eol
925
+				);
926
+			} else if (strlen($name.': '.$value) > 78) {
927
+				// ASCII: check if header line isn't too long and use folding
928
+				$value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value);
929
+				$tmp = wordwrap($name.': '.$value, 78, $eol . ' ');
930
+				$value = preg_replace('/^'.$name.':\s*/', '', $tmp);
931
+				// hard limit 998 (RFC2822)
932
+				$value = wordwrap($value, 998, $eol . ' ', true);
933
+			}
934
+		}
935
+
936
+		return $value;
937
+	}
938
+
939
+	/**
940
+	 * Explode quoted string
941
+	 *
942
+	 * @param string $delimiter Delimiter expression string for preg_match()
943
+	 * @param string $string    Input string
944
+	 *
945
+	 * @return array            String tokens array
946
+	 * @access private
947
+	 */
948
+	function _explodeQuotedString($delimiter, $string)
949
+	{
950
+		$result = array();
951
+		$strlen = strlen($string);
952
+
953
+		for ($q=$p=$i=0; $i < $strlen; $i++) {
954
+			if ($string[$i] == "\""
955
+				&& (empty($string[$i-1]) || $string[$i-1] != "\\")
956
+			) {
957
+				$q = $q ? false : true;
958
+			} else if (!$q && preg_match("/$delimiter/", $string[$i])) {
959
+				$result[] = substr($string, $p, $i - $p);
960
+				$p = $i + 1;
961
+			}
962
+		}
963
+
964
+		$result[] = substr($string, $p);
965
+		return $result;
966
+	}
967
+
968
+	/**
969
+	 * Encodes a header value as per RFC2047
970
+	 *
971
+	 * @param string $value      The header data to encode
972
+	 * @param string $charset    Character set name
973
+	 * @param string $encoding   Encoding name (base64 or quoted-printable)
974
+	 * @param int    $prefix_len Prefix length. Default: 0
975
+	 * @param string $eol        End-of-line sequence. Default: "\r\n"
976
+	 *
977
+	 * @return string            Encoded header data
978
+	 * @access public
979
+	 * @since 1.6.1
980
+	 */
981
+	function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n")
982
+	{
983
+		// #17311: Use multibyte aware method (requires mbstring extension)
984
+		if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) {
985
+			return $result;
986
+		}
987
+
988
+		// Generate the header using the specified params and dynamicly
989
+		// determine the maximum length of such strings.
990
+		// 75 is the value specified in the RFC.
991
+		$encoding = $encoding == 'base64' ? 'B' : 'Q';
992
+		$prefix = '=?' . $charset . '?' . $encoding .'?';
993
+		$suffix = '?=';
994
+		$maxLength = 75 - strlen($prefix . $suffix);
995
+		$maxLength1stLine = $maxLength - $prefix_len;
996
+
997
+		if ($encoding == 'B') {
998
+			// Base64 encode the entire string
999
+			$value = base64_encode($value);
1000
+
1001
+			// We can cut base64 every 4 characters, so the real max
1002
+			// we can get must be rounded down.
1003
+			$maxLength = $maxLength - ($maxLength % 4);
1004
+			$maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4);
1005
+
1006
+			$cutpoint = $maxLength1stLine;
1007
+			$output = '';
1008
+
1009
+			while ($value) {
1010
+				// Split translated string at every $maxLength
1011
+				$part = substr($value, 0, $cutpoint);
1012
+				$value = substr($value, $cutpoint);
1013
+				$cutpoint = $maxLength;
1014
+				// RFC 2047 specifies that any split header should
1015
+				// be separated by a CRLF SPACE.
1016
+				if ($output) {
1017
+					$output .= $eol . ' ';
1018
+				}
1019
+				$output .= $prefix . $part . $suffix;
1020
+			}
1021
+			$value = $output;
1022
+		} else {
1023
+			// quoted-printable encoding has been selected
1024
+			$value = Mail_mimePart::encodeQP($value);
1025
+
1026
+			// This regexp will break QP-encoded text at every $maxLength
1027
+			// but will not break any encoded letters.
1028
+			$reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|";
1029
+			$reg2nd = "|(.{0,$maxLength}[^\=][^\=])|";
1030
+
1031
+			if (strlen($value) > $maxLength1stLine) {
1032
+				// Begin with the regexp for the first line.
1033
+				$reg = $reg1st;
1034
+				$output = '';
1035
+				while ($value) {
1036
+					// Split translated string at every $maxLength
1037
+					// But make sure not to break any translated chars.
1038
+					$found = preg_match($reg, $value, $matches);
1039
+
1040
+					// After this first line, we need to use a different
1041
+					// regexp for the first line.
1042
+					$reg = $reg2nd;
1043
+
1044
+					// Save the found part and encapsulate it in the
1045
+					// prefix & suffix. Then remove the part from the
1046
+					// $value_out variable.
1047
+					if ($found) {
1048
+						$part = $matches[0];
1049
+						$len = strlen($matches[0]);
1050
+						$value = substr($value, $len);
1051
+					} else {
1052
+						$part = $value;
1053
+						$value = '';
1054
+					}
1055
+
1056
+					// RFC 2047 specifies that any split header should
1057
+					// be separated by a CRLF SPACE
1058
+					if ($output) {
1059
+						$output .= $eol . ' ';
1060
+					}
1061
+					$output .= $prefix . $part . $suffix;
1062
+				}
1063
+				$value = $output;
1064
+			} else {
1065
+				$value = $prefix . $value . $suffix;
1066
+			}
1067
+		}
1068
+
1069
+		return $value;
1070
+	}
1071
+
1072
+	/**
1073
+	 * Encodes the given string using quoted-printable
1074
+	 *
1075
+	 * @param string $str String to encode
1076
+	 *
1077
+	 * @return string     Encoded string
1078
+	 * @access public
1079
+	 * @since 1.6.0
1080
+	 */
1081
+	function encodeQP($str)
1082
+	{
1083
+		// Bug #17226 RFC 2047 restricts some characters
1084
+		// if the word is inside a phrase, permitted chars are only:
1085
+		// ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
1086
+
1087
+		// "=",  "_",  "?" must be encoded
1088
+		$regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1089
+		$str = preg_replace_callback(
1090
+			$regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str
1091
+		);
1092
+
1093
+		return str_replace(' ', '_', $str);
1094
+	}
1095
+
1096
+	/**
1097
+	 * Encodes the given string using base64 or quoted-printable.
1098
+	 * This method makes sure that encoded-word represents an integral
1099
+	 * number of characters as per RFC2047.
1100
+	 *
1101
+	 * @param string $str        String to encode
1102
+	 * @param string $charset    Character set name
1103
+	 * @param string $encoding   Encoding name (base64 or quoted-printable)
1104
+	 * @param int    $prefix_len Prefix length. Default: 0
1105
+	 * @param string $eol        End-of-line sequence. Default: "\r\n"
1106
+	 *
1107
+	 * @return string     Encoded string
1108
+	 * @access public
1109
+	 * @since 1.8.0
1110
+	 */
1111
+	function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n")
1112
+	{
1113
+		if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
1114
+			return;
1115
+		}
1116
+
1117
+		$encoding = $encoding == 'base64' ? 'B' : 'Q';
1118
+		// 75 is the value specified in the RFC
1119
+		$prefix = '=?' . $charset . '?'.$encoding.'?';
1120
+		$suffix = '?=';
1121
+		$maxLength = 75 - strlen($prefix . $suffix);
1122
+
1123
+		// A multi-octet character may not be split across adjacent encoded-words
1124
+		// So, we'll loop over each character
1125
+		// mb_stlen() with wrong charset will generate a warning here and return null
1126
+		$length      = mb_strlen($str, $charset);
1127
+		$result      = '';
1128
+		$line_length = $prefix_len;
1129
+
1130
+		if ($encoding == 'B') {
1131
+			// base64
1132
+			$start = 0;
1133
+			$prev  = '';
1134
+
1135
+			for ($i=1; $i<=$length; $i++) {
1136
+				// See #17311
1137
+				$chunk = mb_substr($str, $start, $i-$start, $charset);
1138
+				$chunk = base64_encode($chunk);
1139
+				$chunk_len = strlen($chunk);
1140
+
1141
+				if ($line_length + $chunk_len == $maxLength || $i == $length) {
1142
+					if ($result) {
1143
+						$result .= "\n";
1144
+					}
1145
+					$result .= $chunk;
1146
+					$line_length = 0;
1147
+					$start = $i;
1148
+				} else if ($line_length + $chunk_len > $maxLength) {
1149
+					if ($result) {
1150
+						$result .= "\n";
1151
+					}
1152
+					if ($prev) {
1153
+						$result .= $prev;
1154
+					}
1155
+					$line_length = 0;
1156
+					$start = $i - 1;
1157
+				} else {
1158
+					$prev = $chunk;
1159
+				}
1160
+			}
1161
+		} else {
1162
+			// quoted-printable
1163
+			// see encodeQP()
1164
+			$regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1165
+
1166
+			for ($i=0; $i<=$length; $i++) {
1167
+				$char = mb_substr($str, $i, 1, $charset);
1168
+				// RFC recommends underline (instead of =20) in place of the space
1169
+				// that's one of the reasons why we're not using iconv_mime_encode()
1170
+				if ($char == ' ') {
1171
+					$char = '_';
1172
+					$char_len = 1;
1173
+				} else {
1174
+					$char = preg_replace_callback(
1175
+						$regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char
1176
+					);
1177
+					$char_len = strlen($char);
1178
+				}
1179
+
1180
+				if ($line_length + $char_len > $maxLength) {
1181
+					if ($result) {
1182
+						$result .= "\n";
1183
+					}
1184
+					$line_length = 0;
1185
+				}
1186
+
1187
+				$result      .= $char;
1188
+				$line_length += $char_len;
1189
+			}
1190
+		}
1191
+
1192
+		if ($result) {
1193
+			$result = $prefix
1194
+				.str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix;
1195
+		}
1196
+
1197
+		return $result;
1198
+	}
1199
+
1200
+	/**
1201
+	 * Callback function to replace extended characters (\x80-xFF) with their
1202
+	 * ASCII values (RFC2047: quoted-printable)
1203
+	 *
1204
+	 * @param array $matches Preg_replace's matches array
1205
+	 *
1206
+	 * @return string        Encoded character string
1207
+	 * @access private
1208
+	 */
1209
+	function _qpReplaceCallback($matches)
1210
+	{
1211
+		return sprintf('=%02X', ord($matches[1]));
1212
+	}
1213
+
1214
+	/**
1215
+	 * Callback function to replace extended characters (\x80-xFF) with their
1216
+	 * ASCII values (RFC2231)
1217
+	 *
1218
+	 * @param array $matches Preg_replace's matches array
1219
+	 *
1220
+	 * @return string        Encoded character string
1221
+	 * @access private
1222
+	 */
1223
+	function _encodeReplaceCallback($matches)
1224
+	{
1225
+		return sprintf('%%%02X', ord($matches[1]));
1226
+	}
1227
+
1228
+	/**
1229
+	 * PEAR::isError implementation
1230
+	 *
1231
+	 * @param mixed $data Object
1232
+	 *
1233
+	 * @return bool True if object is an instance of PEAR_Error
1234
+	 * @access private
1235
+	 */
1236
+	function _isError($data)
1237
+	{
1238
+		// PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1239
+		if (is_object($data) && is_a($data, 'PEAR_Error')) {
1240
+			return true;
1241
+		}
1242
+
1243
+		return false;
1244
+	}
1245
+
1246
+	/**
1247
+	 * PEAR::raiseError implementation
1248
+	 *
1249
+	 * @param $message A text error message
1250
+	 *
1251
+	 * @return PEAR_Error Instance of PEAR_Error
1252
+	 * @access private
1253
+	 */
1254
+	function _raiseError($message)
1255
+	{
1256
+		// PEAR::raiseError() is not PHP 5.4 compatible
1257
+		return new PEAR_Error($message);
1258
+	}
1259 1259
 
1260 1260
 } // End of class
Please login to merge, or discard this patch.
htdocs/includes/nusoap/lib/Mail/mime.php 1 patch
Indentation   +1378 added lines, -1378 removed lines patch added patch discarded remove patch
@@ -94,852 +94,852 @@  discard block
 block discarded – undo
94 94
  */
95 95
 class Mail_mime
96 96
 {
97
-    /**
98
-     * Contains the plain text part of the email
99
-     *
100
-     * @var string
101
-     * @access private
102
-     */
103
-    var $_txtbody;
104
-
105
-    /**
106
-     * Contains the html part of the email
107
-     *
108
-     * @var string
109
-     * @access private
110
-     */
111
-    var $_htmlbody;
112
-
113
-    /**
114
-     * list of the attached images
115
-     *
116
-     * @var array
117
-     * @access private
118
-     */
119
-    var $_html_images = array();
120
-
121
-    /**
122
-     * list of the attachements
123
-     *
124
-     * @var array
125
-     * @access private
126
-     */
127
-    var $_parts = array();
128
-
129
-    /**
130
-     * Headers for the mail
131
-     *
132
-     * @var array
133
-     * @access private
134
-     */
135
-    var $_headers = array();
136
-
137
-    /**
138
-     * Build parameters
139
-     *
140
-     * @var array
141
-     * @access private
142
-     */
143
-    var $_build_params = array(
144
-        // What encoding to use for the headers
145
-        // Options: quoted-printable or base64
146
-        'head_encoding' => 'quoted-printable',
147
-        // What encoding to use for plain text
148
-        // Options: 7bit, 8bit, base64, or quoted-printable
149
-        'text_encoding' => 'quoted-printable',
150
-        // What encoding to use for html
151
-        // Options: 7bit, 8bit, base64, or quoted-printable
152
-        'html_encoding' => 'quoted-printable',
153
-        // The character set to use for html
154
-        'html_charset'  => 'ISO-8859-1',
155
-        // The character set to use for text
156
-        'text_charset'  => 'ISO-8859-1',
157
-        // The character set to use for headers
158
-        'head_charset'  => 'ISO-8859-1',
159
-        // End-of-line sequence
160
-        'eol'           => "\r\n",
161
-        // Delay attachment files IO until building the message
162
-        'delay_file_io' => false
163
-    );
164
-
165
-    /**
166
-     * Constructor function
167
-     *
168
-     * @param mixed $params Build parameters that change the way the email
169
-     *                      is built. Should be an associative array.
170
-     *                      See $_build_params.
171
-     *
172
-     * @return void
173
-     * @access public
174
-     */
175
-    function Mail_mime($params = array())
176
-    {
177
-        // Backward-compatible EOL setting
178
-        if (is_string($params)) {
179
-            $this->_build_params['eol'] = $params;
180
-        } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
181
-            $this->_build_params['eol'] = MAIL_MIME_CRLF;
182
-        }
183
-
184
-        // Update build parameters
185
-        if (!empty($params) && is_array($params)) {
186
-            while (list($key, $value) = each($params)) {
187
-                $this->_build_params[$key] = $value;
188
-            }
189
-        }
190
-    }
191
-
192
-    /**
193
-     * Set build parameter value
194
-     *
195
-     * @param string $name  Parameter name
196
-     * @param string $value Parameter value
197
-     *
198
-     * @return void
199
-     * @access public
200
-     * @since 1.6.0
201
-     */
202
-    function setParam($name, $value)
203
-    {
204
-        $this->_build_params[$name] = $value;
205
-    }
206
-
207
-    /**
208
-     * Get build parameter value
209
-     *
210
-     * @param string $name Parameter name
211
-     *
212
-     * @return mixed Parameter value
213
-     * @access public
214
-     * @since 1.6.0
215
-     */
216
-    function getParam($name)
217
-    {
218
-        return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null;
219
-    }
220
-
221
-    /**
222
-     * Accessor function to set the body text. Body text is used if
223
-     * it's not an html mail being sent or else is used to fill the
224
-     * text/plain part that emails clients who don't support
225
-     * html should show.
226
-     *
227
-     * @param string $data   Either a string or
228
-     *                       the file name with the contents
229
-     * @param bool   $isfile If true the first param should be treated
230
-     *                       as a file name, else as a string (default)
231
-     * @param bool   $append If true the text or file is appended to
232
-     *                       the existing body, else the old body is
233
-     *                       overwritten
234
-     *
235
-     * @return mixed         True on success or PEAR_Error object
236
-     * @access public
237
-     */
238
-    function setTXTBody($data, $isfile = false, $append = false)
239
-    {
240
-        if (!$isfile) {
241
-            if (!$append) {
242
-                $this->_txtbody = $data;
243
-            } else {
244
-                $this->_txtbody .= $data;
245
-            }
246
-        } else {
247
-            $cont = $this->_file2str($data);
248
-            if ($this->_isError($cont)) {
249
-                return $cont;
250
-            }
251
-            if (!$append) {
252
-                $this->_txtbody = $cont;
253
-            } else {
254
-                $this->_txtbody .= $cont;
255
-            }
256
-        }
257
-
258
-        return true;
259
-    }
260
-
261
-    /**
262
-     * Get message text body
263
-     *
264
-     * @return string Text body
265
-     * @access public
266
-     * @since 1.6.0
267
-     */
268
-    function getTXTBody()
269
-    {
270
-        return $this->_txtbody;
271
-    }
272
-
273
-    /**
274
-     * Adds a html part to the mail.
275
-     *
276
-     * @param string $data   Either a string or the file name with the
277
-     *                       contents
278
-     * @param bool   $isfile A flag that determines whether $data is a
279
-     *                       filename, or a string(false, default)
280
-     *
281
-     * @return bool          True on success
282
-     * @access public
283
-     */
284
-    function setHTMLBody($data, $isfile = false)
285
-    {
286
-        if (!$isfile) {
287
-            $this->_htmlbody = $data;
288
-        } else {
289
-            $cont = $this->_file2str($data);
290
-            if ($this->_isError($cont)) {
291
-                return $cont;
292
-            }
293
-            $this->_htmlbody = $cont;
294
-        }
295
-
296
-        return true;
297
-    }
298
-
299
-    /**
300
-     * Get message HTML body
301
-     *
302
-     * @return string HTML body
303
-     * @access public
304
-     * @since 1.6.0
305
-     */
306
-    function getHTMLBody()
307
-    {
308
-        return $this->_htmlbody;
309
-    }
310
-
311
-    /**
312
-     * Adds an image to the list of embedded images.
313
-     *
314
-     * @param string $file       The image file name OR image data itself
315
-     * @param string $c_type     The content type
316
-     * @param string $name       The filename of the image.
317
-     *                           Only used if $file is the image data.
318
-     * @param bool   $isfile     Whether $file is a filename or not.
319
-     *                           Defaults to true
320
-     * @param string $content_id Desired Content-ID of MIME part
321
-     *                           Defaults to generated unique ID
322
-     *
323
-     * @return bool          True on success
324
-     * @access public
325
-     */
326
-    function addHTMLImage($file,
327
-        $c_type='application/octet-stream',
328
-        $name = '',
329
-        $isfile = true,
330
-        $content_id = null
331
-    ) {
332
-        $bodyfile = null;
333
-
334
-        if ($isfile) {
335
-            // Don't load file into memory
336
-            if ($this->_build_params['delay_file_io']) {
337
-                $filedata = null;
338
-                $bodyfile = $file;
339
-            } else {
340
-                if ($this->_isError($filedata = $this->_file2str($file))) {
341
-                    return $filedata;
342
-                }
343
-            }
344
-            $filename = ($name ? $name : $file);
345
-        } else {
346
-            $filedata = $file;
347
-            $filename = $name;
348
-        }
349
-
350
-        if (!$content_id) {
351
-            $content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
352
-        }
353
-
354
-        $this->_html_images[] = array(
355
-            'body'      => $filedata,
356
-            'body_file' => $bodyfile,
357
-            'name'      => $filename,
358
-            'c_type'    => $c_type,
359
-            'cid'       => $content_id
360
-        );
361
-
362
-        return true;
363
-    }
364
-
365
-    /**
366
-     * Adds a file to the list of attachments.
367
-     *
368
-     * @param string $file        The file name of the file to attach
369
-     *                            or the file contents itself
370
-     * @param string $c_type      The content type
371
-     * @param string $name        The filename of the attachment
372
-     *                            Only use if $file is the contents
373
-     * @param bool   $isfile      Whether $file is a filename or not. Defaults to true
374
-     * @param string $encoding    The type of encoding to use. Defaults to base64.
375
-     *                            Possible values: 7bit, 8bit, base64 or quoted-printable.
376
-     * @param string $disposition The content-disposition of this file
377
-     *                            Defaults to attachment.
378
-     *                            Possible values: attachment, inline.
379
-     * @param string $charset     The character set of attachment's content.
380
-     * @param string $language    The language of the attachment
381
-     * @param string $location    The RFC 2557.4 location of the attachment
382
-     * @param string $n_encoding  Encoding of the attachment's name in Content-Type
383
-     *                            By default filenames are encoded using RFC2231 method
384
-     *                            Here you can set RFC2047 encoding (quoted-printable
385
-     *                            or base64) instead
386
-     * @param string $f_encoding  Encoding of the attachment's filename
387
-     *                            in Content-Disposition header.
388
-     * @param string $description Content-Description header
389
-     * @param string $h_charset   The character set of the headers e.g. filename
390
-     *                            If not specified, $charset will be used
391
-     * @param array  $add_headers Additional part headers. Array keys can be in form
392
-     *                            of <header_name>:<parameter_name>
393
-     *
394
-     * @return mixed              True on success or PEAR_Error object
395
-     * @access public
396
-     */
397
-    function addAttachment($file,
398
-        $c_type      = 'application/octet-stream',
399
-        $name        = '',
400
-        $isfile      = true,
401
-        $encoding    = 'base64',
402
-        $disposition = 'attachment',
403
-        $charset     = '',
404
-        $language    = '',
405
-        $location    = '',
406
-        $n_encoding  = null,
407
-        $f_encoding  = null,
408
-        $description = '',
409
-        $h_charset   = null,
410
-        $add_headers = array()
411
-    ) {
412
-        $bodyfile = null;
413
-
414
-        if ($isfile) {
415
-            // Don't load file into memory
416
-            if ($this->_build_params['delay_file_io']) {
417
-                $filedata = null;
418
-                $bodyfile = $file;
419
-            } else {
420
-                if ($this->_isError($filedata = $this->_file2str($file))) {
421
-                    return $filedata;
422
-                }
423
-            }
424
-            // Force the name the user supplied, otherwise use $file
425
-            $filename = ($name ? $name : $this->_basename($file));
426
-        } else {
427
-            $filedata = $file;
428
-            $filename = $name;
429
-        }
430
-
431
-        if (!strlen($filename)) {
432
-            $msg = "The supplied filename for the attachment can't be empty";
433
-            return $this->_raiseError($msg);
434
-        }
435
-
436
-        $this->_parts[] = array(
437
-            'body'        => $filedata,
438
-            'body_file'   => $bodyfile,
439
-            'name'        => $filename,
440
-            'c_type'      => $c_type,
441
-            'charset'     => $charset,
442
-            'encoding'    => $encoding,
443
-            'language'    => $language,
444
-            'location'    => $location,
445
-            'disposition' => $disposition,
446
-            'description' => $description,
447
-            'add_headers' => $add_headers,
448
-            'name_encoding'     => $n_encoding,
449
-            'filename_encoding' => $f_encoding,
450
-            'headers_charset'   => $h_charset,
451
-        );
452
-
453
-        return true;
454
-    }
455
-
456
-    /**
457
-     * Get the contents of the given file name as string
458
-     *
459
-     * @param string $file_name Path of file to process
460
-     *
461
-     * @return string           Contents of $file_name
462
-     * @access private
463
-     */
464
-    function _file2str($file_name)
465
-    {
466
-        // Check state of file and raise an error properly
467
-        if (!file_exists($file_name)) {
468
-            return $this->_raiseError('File not found: ' . $file_name);
469
-        }
470
-        if (!is_file($file_name)) {
471
-            return $this->_raiseError('Not a regular file: ' . $file_name);
472
-        }
473
-        if (!is_readable($file_name)) {
474
-            return $this->_raiseError('File is not readable: ' . $file_name);
475
-        }
476
-
477
-        // Temporarily reset magic_quotes_runtime and read file contents
478
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
479
-            @ini_set('magic_quotes_runtime', 0);
480
-        }
481
-        $cont = file_get_contents($file_name);
482
-        if ($magic_quote_setting) {
483
-            @ini_set('magic_quotes_runtime', $magic_quote_setting);
484
-        }
485
-
486
-        return $cont;
487
-    }
488
-
489
-    /**
490
-     * Adds a text subpart to the mimePart object and
491
-     * returns it during the build process.
492
-     *
493
-     * @param mixed  &$obj The object to add the part to, or
494
-     *                     anything else if a new object is to be created.
495
-     * @param string $text The text to add.
496
-     *
497
-     * @return object      The text mimePart object
498
-     * @access private
499
-     */
500
-    function &_addTextPart(&$obj, $text = '')
501
-    {
502
-        $params['content_type'] = 'text/plain';
503
-        $params['encoding']     = $this->_build_params['text_encoding'];
504
-        $params['charset']      = $this->_build_params['text_charset'];
505
-        $params['eol']          = $this->_build_params['eol'];
506
-
507
-        if (is_object($obj)) {
508
-            $ret = $obj->addSubpart($text, $params);
509
-        } else {
510
-            $ret = new Mail_mimePart($text, $params);
511
-        }
512
-
513
-        return $ret;
514
-    }
515
-
516
-    /**
517
-     * Adds a html subpart to the mimePart object and
518
-     * returns it during the build process.
519
-     *
520
-     * @param mixed &$obj The object to add the part to, or
521
-     *                    anything else if a new object is to be created.
522
-     *
523
-     * @return object     The html mimePart object
524
-     * @access private
525
-     */
526
-    function &_addHtmlPart(&$obj)
527
-    {
528
-        $params['content_type'] = 'text/html';
529
-        $params['encoding']     = $this->_build_params['html_encoding'];
530
-        $params['charset']      = $this->_build_params['html_charset'];
531
-        $params['eol']          = $this->_build_params['eol'];
532
-
533
-        if (is_object($obj)) {
534
-            $ret = $obj->addSubpart($this->_htmlbody, $params);
535
-        } else {
536
-            $ret = new Mail_mimePart($this->_htmlbody, $params);
537
-        }
538
-
539
-        return $ret;
540
-    }
541
-
542
-    /**
543
-     * Creates a new mimePart object, using multipart/mixed as
544
-     * the initial content-type and returns it during the
545
-     * build process.
546
-     *
547
-     * @return object The multipart/mixed mimePart object
548
-     * @access private
549
-     */
550
-    function &_addMixedPart()
551
-    {
552
-        $params['content_type'] = 'multipart/mixed';
553
-        $params['eol']          = $this->_build_params['eol'];
554
-
555
-        // Create empty multipart/mixed Mail_mimePart object to return
556
-        $ret = new Mail_mimePart('', $params);
557
-        return $ret;
558
-    }
559
-
560
-    /**
561
-     * Adds a multipart/alternative part to a mimePart
562
-     * object (or creates one), and returns it during
563
-     * the build process.
564
-     *
565
-     * @param mixed &$obj The object to add the part to, or
566
-     *                    anything else if a new object is to be created.
567
-     *
568
-     * @return object     The multipart/mixed mimePart object
569
-     * @access private
570
-     */
571
-    function &_addAlternativePart(&$obj)
572
-    {
573
-        $params['content_type'] = 'multipart/alternative';
574
-        $params['eol']          = $this->_build_params['eol'];
575
-
576
-        if (is_object($obj)) {
577
-            $ret = $obj->addSubpart('', $params);
578
-        } else {
579
-            $ret = new Mail_mimePart('', $params);
580
-        }
581
-
582
-        return $ret;
583
-    }
584
-
585
-    /**
586
-     * Adds a multipart/related part to a mimePart
587
-     * object (or creates one), and returns it during
588
-     * the build process.
589
-     *
590
-     * @param mixed &$obj The object to add the part to, or
591
-     *                    anything else if a new object is to be created
592
-     *
593
-     * @return object     The multipart/mixed mimePart object
594
-     * @access private
595
-     */
596
-    function &_addRelatedPart(&$obj)
597
-    {
598
-        $params['content_type'] = 'multipart/related';
599
-        $params['eol']          = $this->_build_params['eol'];
600
-
601
-        if (is_object($obj)) {
602
-            $ret = $obj->addSubpart('', $params);
603
-        } else {
604
-            $ret = new Mail_mimePart('', $params);
605
-        }
606
-
607
-        return $ret;
608
-    }
609
-
610
-    /**
611
-     * Adds an html image subpart to a mimePart object
612
-     * and returns it during the build process.
613
-     *
614
-     * @param object &$obj  The mimePart to add the image to
615
-     * @param array  $value The image information
616
-     *
617
-     * @return object       The image mimePart object
618
-     * @access private
619
-     */
620
-    function &_addHtmlImagePart(&$obj, $value)
621
-    {
622
-        $params['content_type'] = $value['c_type'];
623
-        $params['encoding']     = 'base64';
624
-        $params['disposition']  = 'inline';
625
-        $params['filename']     = $value['name'];
626
-        $params['cid']          = $value['cid'];
627
-        $params['body_file']    = $value['body_file'];
628
-        $params['eol']          = $this->_build_params['eol'];
629
-
630
-        if (!empty($value['name_encoding'])) {
631
-            $params['name_encoding'] = $value['name_encoding'];
632
-        }
633
-        if (!empty($value['filename_encoding'])) {
634
-            $params['filename_encoding'] = $value['filename_encoding'];
635
-        }
636
-
637
-        $ret = $obj->addSubpart($value['body'], $params);
638
-        return $ret;
639
-    }
640
-
641
-    /**
642
-     * Adds an attachment subpart to a mimePart object
643
-     * and returns it during the build process.
644
-     *
645
-     * @param object &$obj  The mimePart to add the image to
646
-     * @param array  $value The attachment information
647
-     *
648
-     * @return object       The image mimePart object
649
-     * @access private
650
-     */
651
-    function &_addAttachmentPart(&$obj, $value)
652
-    {
653
-        $params['eol']          = $this->_build_params['eol'];
654
-        $params['filename']     = $value['name'];
655
-        $params['encoding']     = $value['encoding'];
656
-        $params['content_type'] = $value['c_type'];
657
-        $params['body_file']    = $value['body_file'];
658
-        $params['disposition']  = isset($value['disposition']) ? 
659
-                                  $value['disposition'] : 'attachment';
660
-
661
-        // content charset
662
-        if (!empty($value['charset'])) {
663
-            $params['charset'] = $value['charset'];
664
-        }
665
-        // headers charset (filename, description)
666
-        if (!empty($value['headers_charset'])) {
667
-            $params['headers_charset'] = $value['headers_charset'];
668
-        }
669
-        if (!empty($value['language'])) {
670
-            $params['language'] = $value['language'];
671
-        }
672
-        if (!empty($value['location'])) {
673
-            $params['location'] = $value['location'];
674
-        }
675
-        if (!empty($value['name_encoding'])) {
676
-            $params['name_encoding'] = $value['name_encoding'];
677
-        }
678
-        if (!empty($value['filename_encoding'])) {
679
-            $params['filename_encoding'] = $value['filename_encoding'];
680
-        }
681
-        if (!empty($value['description'])) {
682
-            $params['description'] = $value['description'];
683
-        }
684
-        if (is_array($value['add_headers'])) {
685
-            $params['headers'] = $value['add_headers'];
686
-        }
687
-
688
-        $ret = $obj->addSubpart($value['body'], $params);
689
-        return $ret;
690
-    }
691
-
692
-    /**
693
-     * Returns the complete e-mail, ready to send using an alternative
694
-     * mail delivery method. Note that only the mailpart that is made
695
-     * with Mail_Mime is created. This means that,
696
-     * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF 
697
-     * using the $headers parameter!
698
-     * 
699
-     * @param string $separation The separation between these two parts.
700
-     * @param array  $params     The Build parameters passed to the
701
-     *                           get() function. See get() for more info.
702
-     * @param array  $headers    The extra headers that should be passed
703
-     *                           to the headers() method.
704
-     *                           See that function for more info.
705
-     * @param bool   $overwrite  Overwrite the existing headers with new.
706
-     *
707
-     * @return mixed The complete e-mail or PEAR error object
708
-     * @access public
709
-     */
710
-    function getMessage($separation = null, $params = null, $headers = null,
711
-        $overwrite = false
712
-    ) {
713
-        if ($separation === null) {
714
-            $separation = $this->_build_params['eol'];
715
-        }
716
-
717
-        $body = $this->get($params);
718
-
719
-        if ($this->_isError($body)) {
720
-            return $body;
721
-        }
722
-
723
-        return $this->txtHeaders($headers, $overwrite) . $separation . $body;
724
-    }
725
-
726
-    /**
727
-     * Returns the complete e-mail body, ready to send using an alternative
728
-     * mail delivery method.
729
-     * 
730
-     * @param array $params The Build parameters passed to the
731
-     *                      get() method. See get() for more info.
732
-     *
733
-     * @return mixed The e-mail body or PEAR error object
734
-     * @access public
735
-     * @since 1.6.0
736
-     */
737
-    function getMessageBody($params = null)
738
-    {
739
-        return $this->get($params, null, true);
740
-    }
741
-
742
-    /**
743
-     * Writes (appends) the complete e-mail into file.
744
-     * 
745
-     * @param string $filename  Output file location
746
-     * @param array  $params    The Build parameters passed to the
747
-     *                          get() method. See get() for more info.
748
-     * @param array  $headers   The extra headers that should be passed
749
-     *                          to the headers() function.
750
-     *                          See that function for more info.
751
-     * @param bool   $overwrite Overwrite the existing headers with new.
752
-     *
753
-     * @return mixed True or PEAR error object
754
-     * @access public
755
-     * @since 1.6.0
756
-     */
757
-    function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
758
-    {
759
-        // Check state of file and raise an error properly
760
-        if (file_exists($filename) && !is_writable($filename)) {
761
-            return $this->_raiseError('File is not writable: ' . $filename);
762
-        }
763
-
764
-        // Temporarily reset magic_quotes_runtime and read file contents
765
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
766
-            @ini_set('magic_quotes_runtime', 0);
767
-        }
768
-
769
-        if (!($fh = fopen($filename, 'ab'))) {
770
-            return $this->_raiseError('Unable to open file: ' . $filename);
771
-        }
772
-
773
-        // Write message headers into file (skipping Content-* headers)
774
-        $head = $this->txtHeaders($headers, $overwrite, true);
775
-        if (fwrite($fh, $head) === false) {
776
-            return $this->_raiseError('Error writing to file: ' . $filename);
777
-        }
778
-
779
-        fclose($fh);
780
-
781
-        if ($magic_quote_setting) {
782
-            @ini_set('magic_quotes_runtime', $magic_quote_setting);
783
-        }
784
-
785
-        // Write the rest of the message into file
786
-        $res = $this->get($params, $filename);
787
-
788
-        return $res ? $res : true;
789
-    }
790
-
791
-    /**
792
-     * Writes (appends) the complete e-mail body into file.
793
-     *
794
-     * @param string $filename Output file location
795
-     * @param array  $params   The Build parameters passed to the
796
-     *                         get() method. See get() for more info.
797
-     *
798
-     * @return mixed True or PEAR error object
799
-     * @access public
800
-     * @since 1.6.0
801
-     */
802
-    function saveMessageBody($filename, $params = null)
803
-    {
804
-        // Check state of file and raise an error properly
805
-        if (file_exists($filename) && !is_writable($filename)) {
806
-            return $this->_raiseError('File is not writable: ' . $filename);
807
-        }
808
-
809
-        // Temporarily reset magic_quotes_runtime and read file contents
810
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
811
-            @ini_set('magic_quotes_runtime', 0);
812
-        }
813
-
814
-        if (!($fh = fopen($filename, 'ab'))) {
815
-            return $this->_raiseError('Unable to open file: ' . $filename);
816
-        }
817
-
818
-        // Write the rest of the message into file
819
-        $res = $this->get($params, $filename, true);
820
-
821
-        return $res ? $res : true;
822
-    }
823
-
824
-    /**
825
-     * Builds the multipart message from the list ($this->_parts) and
826
-     * returns the mime content.
827
-     *
828
-     * @param array    $params    Build parameters that change the way the email
829
-     *                            is built. Should be associative. See $_build_params.
830
-     * @param resource $filename  Output file where to save the message instead of
831
-     *                            returning it
832
-     * @param boolean  $skip_head True if you want to return/save only the message
833
-     *                            without headers
834
-     *
835
-     * @return mixed The MIME message content string, null or PEAR error object
836
-     * @access public
837
-     */
838
-    function get($params = null, $filename = null, $skip_head = false)
839
-    {
840
-        if (isset($params)) {
841
-            while (list($key, $value) = each($params)) {
842
-                $this->_build_params[$key] = $value;
843
-            }
844
-        }
845
-
846
-        if (isset($this->_headers['From'])) {
847
-            // Bug #11381: Illegal characters in domain ID
848
-            if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) {
849
-                $domainID = $matches[1];
850
-            } else {
851
-                $domainID = '@localhost';
852
-            }
853
-            foreach ($this->_html_images as $i => $img) {
854
-                $cid = $this->_html_images[$i]['cid']; 
855
-                if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
856
-                    $this->_html_images[$i]['cid'] = $cid . $domainID;
857
-                }
858
-            }
859
-        }
860
-
861
-        if (count($this->_html_images) && isset($this->_htmlbody)) {
862
-            foreach ($this->_html_images as $key => $value) {
863
-                $regex   = array();
864
-                $regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
865
-                            preg_quote($value['name'], '#') . '\3#';
866
-                $regex[] = '#(?i)url(?-i)\(\s*(["\']?)' .
867
-                            preg_quote($value['name'], '#') . '\1\s*\)#';
868
-
869
-                $rep   = array();
870
-                $rep[] = '\1\2=\3cid:' . $value['cid'] .'\3';
871
-                $rep[] = 'url(\1cid:' . $value['cid'] . '\1)';
872
-
873
-                $this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody);
874
-                $this->_html_images[$key]['name']
875
-                    = $this->_basename($this->_html_images[$key]['name']);
876
-            }
877
-        }
878
-
879
-        $this->_checkParams();
880
-
881
-        $null        = -1;
882
-        $attachments = count($this->_parts) > 0;
883
-        $html_images = count($this->_html_images) > 0;
884
-        $html        = strlen($this->_htmlbody) > 0;
885
-        $text        = !$html && strlen($this->_txtbody);
886
-
887
-        switch (true) {
888
-        case $text && !$attachments:
889
-            $message =& $this->_addTextPart($null, $this->_txtbody);
890
-            break;
891
-
892
-        case !$text && !$html && $attachments:
893
-            $message =& $this->_addMixedPart();
894
-            for ($i = 0; $i < count($this->_parts); $i++) {
895
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
896
-            }
897
-            break;
898
-
899
-        case $text && $attachments:
900
-            $message =& $this->_addMixedPart();
901
-            $this->_addTextPart($message, $this->_txtbody);
902
-            for ($i = 0; $i < count($this->_parts); $i++) {
903
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
904
-            }
905
-            break;
906
-
907
-        case $html && !$attachments && !$html_images:
908
-            if (isset($this->_txtbody)) {
909
-                $message =& $this->_addAlternativePart($null);
910
-                $this->_addTextPart($message, $this->_txtbody);
911
-                $this->_addHtmlPart($message);
912
-            } else {
913
-                $message =& $this->_addHtmlPart($null);
914
-            }
915
-            break;
916
-
917
-        case $html && !$attachments && $html_images:
918
-            // * Content-Type: multipart/alternative;
919
-            //    * text
920
-            //    * Content-Type: multipart/related;
921
-            //       * html
922
-            //       * image...
923
-            if (isset($this->_txtbody)) {
924
-                $message =& $this->_addAlternativePart($null);
925
-                $this->_addTextPart($message, $this->_txtbody);
926
-
927
-                $ht =& $this->_addRelatedPart($message);
928
-                $this->_addHtmlPart($ht);
929
-                for ($i = 0; $i < count($this->_html_images); $i++) {
930
-                    $this->_addHtmlImagePart($ht, $this->_html_images[$i]);
931
-                }
932
-            } else {
933
-                // * Content-Type: multipart/related;
934
-                //    * html
935
-                //    * image...
936
-                $message =& $this->_addRelatedPart($null);
937
-                $this->_addHtmlPart($message);
938
-                for ($i = 0; $i < count($this->_html_images); $i++) {
939
-                    $this->_addHtmlImagePart($message, $this->_html_images[$i]);
940
-                }
941
-            }
942
-            /*
97
+	/**
98
+	 * Contains the plain text part of the email
99
+	 *
100
+	 * @var string
101
+	 * @access private
102
+	 */
103
+	var $_txtbody;
104
+
105
+	/**
106
+	 * Contains the html part of the email
107
+	 *
108
+	 * @var string
109
+	 * @access private
110
+	 */
111
+	var $_htmlbody;
112
+
113
+	/**
114
+	 * list of the attached images
115
+	 *
116
+	 * @var array
117
+	 * @access private
118
+	 */
119
+	var $_html_images = array();
120
+
121
+	/**
122
+	 * list of the attachements
123
+	 *
124
+	 * @var array
125
+	 * @access private
126
+	 */
127
+	var $_parts = array();
128
+
129
+	/**
130
+	 * Headers for the mail
131
+	 *
132
+	 * @var array
133
+	 * @access private
134
+	 */
135
+	var $_headers = array();
136
+
137
+	/**
138
+	 * Build parameters
139
+	 *
140
+	 * @var array
141
+	 * @access private
142
+	 */
143
+	var $_build_params = array(
144
+		// What encoding to use for the headers
145
+		// Options: quoted-printable or base64
146
+		'head_encoding' => 'quoted-printable',
147
+		// What encoding to use for plain text
148
+		// Options: 7bit, 8bit, base64, or quoted-printable
149
+		'text_encoding' => 'quoted-printable',
150
+		// What encoding to use for html
151
+		// Options: 7bit, 8bit, base64, or quoted-printable
152
+		'html_encoding' => 'quoted-printable',
153
+		// The character set to use for html
154
+		'html_charset'  => 'ISO-8859-1',
155
+		// The character set to use for text
156
+		'text_charset'  => 'ISO-8859-1',
157
+		// The character set to use for headers
158
+		'head_charset'  => 'ISO-8859-1',
159
+		// End-of-line sequence
160
+		'eol'           => "\r\n",
161
+		// Delay attachment files IO until building the message
162
+		'delay_file_io' => false
163
+	);
164
+
165
+	/**
166
+	 * Constructor function
167
+	 *
168
+	 * @param mixed $params Build parameters that change the way the email
169
+	 *                      is built. Should be an associative array.
170
+	 *                      See $_build_params.
171
+	 *
172
+	 * @return void
173
+	 * @access public
174
+	 */
175
+	function Mail_mime($params = array())
176
+	{
177
+		// Backward-compatible EOL setting
178
+		if (is_string($params)) {
179
+			$this->_build_params['eol'] = $params;
180
+		} else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
181
+			$this->_build_params['eol'] = MAIL_MIME_CRLF;
182
+		}
183
+
184
+		// Update build parameters
185
+		if (!empty($params) && is_array($params)) {
186
+			while (list($key, $value) = each($params)) {
187
+				$this->_build_params[$key] = $value;
188
+			}
189
+		}
190
+	}
191
+
192
+	/**
193
+	 * Set build parameter value
194
+	 *
195
+	 * @param string $name  Parameter name
196
+	 * @param string $value Parameter value
197
+	 *
198
+	 * @return void
199
+	 * @access public
200
+	 * @since 1.6.0
201
+	 */
202
+	function setParam($name, $value)
203
+	{
204
+		$this->_build_params[$name] = $value;
205
+	}
206
+
207
+	/**
208
+	 * Get build parameter value
209
+	 *
210
+	 * @param string $name Parameter name
211
+	 *
212
+	 * @return mixed Parameter value
213
+	 * @access public
214
+	 * @since 1.6.0
215
+	 */
216
+	function getParam($name)
217
+	{
218
+		return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null;
219
+	}
220
+
221
+	/**
222
+	 * Accessor function to set the body text. Body text is used if
223
+	 * it's not an html mail being sent or else is used to fill the
224
+	 * text/plain part that emails clients who don't support
225
+	 * html should show.
226
+	 *
227
+	 * @param string $data   Either a string or
228
+	 *                       the file name with the contents
229
+	 * @param bool   $isfile If true the first param should be treated
230
+	 *                       as a file name, else as a string (default)
231
+	 * @param bool   $append If true the text or file is appended to
232
+	 *                       the existing body, else the old body is
233
+	 *                       overwritten
234
+	 *
235
+	 * @return mixed         True on success or PEAR_Error object
236
+	 * @access public
237
+	 */
238
+	function setTXTBody($data, $isfile = false, $append = false)
239
+	{
240
+		if (!$isfile) {
241
+			if (!$append) {
242
+				$this->_txtbody = $data;
243
+			} else {
244
+				$this->_txtbody .= $data;
245
+			}
246
+		} else {
247
+			$cont = $this->_file2str($data);
248
+			if ($this->_isError($cont)) {
249
+				return $cont;
250
+			}
251
+			if (!$append) {
252
+				$this->_txtbody = $cont;
253
+			} else {
254
+				$this->_txtbody .= $cont;
255
+			}
256
+		}
257
+
258
+		return true;
259
+	}
260
+
261
+	/**
262
+	 * Get message text body
263
+	 *
264
+	 * @return string Text body
265
+	 * @access public
266
+	 * @since 1.6.0
267
+	 */
268
+	function getTXTBody()
269
+	{
270
+		return $this->_txtbody;
271
+	}
272
+
273
+	/**
274
+	 * Adds a html part to the mail.
275
+	 *
276
+	 * @param string $data   Either a string or the file name with the
277
+	 *                       contents
278
+	 * @param bool   $isfile A flag that determines whether $data is a
279
+	 *                       filename, or a string(false, default)
280
+	 *
281
+	 * @return bool          True on success
282
+	 * @access public
283
+	 */
284
+	function setHTMLBody($data, $isfile = false)
285
+	{
286
+		if (!$isfile) {
287
+			$this->_htmlbody = $data;
288
+		} else {
289
+			$cont = $this->_file2str($data);
290
+			if ($this->_isError($cont)) {
291
+				return $cont;
292
+			}
293
+			$this->_htmlbody = $cont;
294
+		}
295
+
296
+		return true;
297
+	}
298
+
299
+	/**
300
+	 * Get message HTML body
301
+	 *
302
+	 * @return string HTML body
303
+	 * @access public
304
+	 * @since 1.6.0
305
+	 */
306
+	function getHTMLBody()
307
+	{
308
+		return $this->_htmlbody;
309
+	}
310
+
311
+	/**
312
+	 * Adds an image to the list of embedded images.
313
+	 *
314
+	 * @param string $file       The image file name OR image data itself
315
+	 * @param string $c_type     The content type
316
+	 * @param string $name       The filename of the image.
317
+	 *                           Only used if $file is the image data.
318
+	 * @param bool   $isfile     Whether $file is a filename or not.
319
+	 *                           Defaults to true
320
+	 * @param string $content_id Desired Content-ID of MIME part
321
+	 *                           Defaults to generated unique ID
322
+	 *
323
+	 * @return bool          True on success
324
+	 * @access public
325
+	 */
326
+	function addHTMLImage($file,
327
+		$c_type='application/octet-stream',
328
+		$name = '',
329
+		$isfile = true,
330
+		$content_id = null
331
+	) {
332
+		$bodyfile = null;
333
+
334
+		if ($isfile) {
335
+			// Don't load file into memory
336
+			if ($this->_build_params['delay_file_io']) {
337
+				$filedata = null;
338
+				$bodyfile = $file;
339
+			} else {
340
+				if ($this->_isError($filedata = $this->_file2str($file))) {
341
+					return $filedata;
342
+				}
343
+			}
344
+			$filename = ($name ? $name : $file);
345
+		} else {
346
+			$filedata = $file;
347
+			$filename = $name;
348
+		}
349
+
350
+		if (!$content_id) {
351
+			$content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
352
+		}
353
+
354
+		$this->_html_images[] = array(
355
+			'body'      => $filedata,
356
+			'body_file' => $bodyfile,
357
+			'name'      => $filename,
358
+			'c_type'    => $c_type,
359
+			'cid'       => $content_id
360
+		);
361
+
362
+		return true;
363
+	}
364
+
365
+	/**
366
+	 * Adds a file to the list of attachments.
367
+	 *
368
+	 * @param string $file        The file name of the file to attach
369
+	 *                            or the file contents itself
370
+	 * @param string $c_type      The content type
371
+	 * @param string $name        The filename of the attachment
372
+	 *                            Only use if $file is the contents
373
+	 * @param bool   $isfile      Whether $file is a filename or not. Defaults to true
374
+	 * @param string $encoding    The type of encoding to use. Defaults to base64.
375
+	 *                            Possible values: 7bit, 8bit, base64 or quoted-printable.
376
+	 * @param string $disposition The content-disposition of this file
377
+	 *                            Defaults to attachment.
378
+	 *                            Possible values: attachment, inline.
379
+	 * @param string $charset     The character set of attachment's content.
380
+	 * @param string $language    The language of the attachment
381
+	 * @param string $location    The RFC 2557.4 location of the attachment
382
+	 * @param string $n_encoding  Encoding of the attachment's name in Content-Type
383
+	 *                            By default filenames are encoded using RFC2231 method
384
+	 *                            Here you can set RFC2047 encoding (quoted-printable
385
+	 *                            or base64) instead
386
+	 * @param string $f_encoding  Encoding of the attachment's filename
387
+	 *                            in Content-Disposition header.
388
+	 * @param string $description Content-Description header
389
+	 * @param string $h_charset   The character set of the headers e.g. filename
390
+	 *                            If not specified, $charset will be used
391
+	 * @param array  $add_headers Additional part headers. Array keys can be in form
392
+	 *                            of <header_name>:<parameter_name>
393
+	 *
394
+	 * @return mixed              True on success or PEAR_Error object
395
+	 * @access public
396
+	 */
397
+	function addAttachment($file,
398
+		$c_type      = 'application/octet-stream',
399
+		$name        = '',
400
+		$isfile      = true,
401
+		$encoding    = 'base64',
402
+		$disposition = 'attachment',
403
+		$charset     = '',
404
+		$language    = '',
405
+		$location    = '',
406
+		$n_encoding  = null,
407
+		$f_encoding  = null,
408
+		$description = '',
409
+		$h_charset   = null,
410
+		$add_headers = array()
411
+	) {
412
+		$bodyfile = null;
413
+
414
+		if ($isfile) {
415
+			// Don't load file into memory
416
+			if ($this->_build_params['delay_file_io']) {
417
+				$filedata = null;
418
+				$bodyfile = $file;
419
+			} else {
420
+				if ($this->_isError($filedata = $this->_file2str($file))) {
421
+					return $filedata;
422
+				}
423
+			}
424
+			// Force the name the user supplied, otherwise use $file
425
+			$filename = ($name ? $name : $this->_basename($file));
426
+		} else {
427
+			$filedata = $file;
428
+			$filename = $name;
429
+		}
430
+
431
+		if (!strlen($filename)) {
432
+			$msg = "The supplied filename for the attachment can't be empty";
433
+			return $this->_raiseError($msg);
434
+		}
435
+
436
+		$this->_parts[] = array(
437
+			'body'        => $filedata,
438
+			'body_file'   => $bodyfile,
439
+			'name'        => $filename,
440
+			'c_type'      => $c_type,
441
+			'charset'     => $charset,
442
+			'encoding'    => $encoding,
443
+			'language'    => $language,
444
+			'location'    => $location,
445
+			'disposition' => $disposition,
446
+			'description' => $description,
447
+			'add_headers' => $add_headers,
448
+			'name_encoding'     => $n_encoding,
449
+			'filename_encoding' => $f_encoding,
450
+			'headers_charset'   => $h_charset,
451
+		);
452
+
453
+		return true;
454
+	}
455
+
456
+	/**
457
+	 * Get the contents of the given file name as string
458
+	 *
459
+	 * @param string $file_name Path of file to process
460
+	 *
461
+	 * @return string           Contents of $file_name
462
+	 * @access private
463
+	 */
464
+	function _file2str($file_name)
465
+	{
466
+		// Check state of file and raise an error properly
467
+		if (!file_exists($file_name)) {
468
+			return $this->_raiseError('File not found: ' . $file_name);
469
+		}
470
+		if (!is_file($file_name)) {
471
+			return $this->_raiseError('Not a regular file: ' . $file_name);
472
+		}
473
+		if (!is_readable($file_name)) {
474
+			return $this->_raiseError('File is not readable: ' . $file_name);
475
+		}
476
+
477
+		// Temporarily reset magic_quotes_runtime and read file contents
478
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
479
+			@ini_set('magic_quotes_runtime', 0);
480
+		}
481
+		$cont = file_get_contents($file_name);
482
+		if ($magic_quote_setting) {
483
+			@ini_set('magic_quotes_runtime', $magic_quote_setting);
484
+		}
485
+
486
+		return $cont;
487
+	}
488
+
489
+	/**
490
+	 * Adds a text subpart to the mimePart object and
491
+	 * returns it during the build process.
492
+	 *
493
+	 * @param mixed  &$obj The object to add the part to, or
494
+	 *                     anything else if a new object is to be created.
495
+	 * @param string $text The text to add.
496
+	 *
497
+	 * @return object      The text mimePart object
498
+	 * @access private
499
+	 */
500
+	function &_addTextPart(&$obj, $text = '')
501
+	{
502
+		$params['content_type'] = 'text/plain';
503
+		$params['encoding']     = $this->_build_params['text_encoding'];
504
+		$params['charset']      = $this->_build_params['text_charset'];
505
+		$params['eol']          = $this->_build_params['eol'];
506
+
507
+		if (is_object($obj)) {
508
+			$ret = $obj->addSubpart($text, $params);
509
+		} else {
510
+			$ret = new Mail_mimePart($text, $params);
511
+		}
512
+
513
+		return $ret;
514
+	}
515
+
516
+	/**
517
+	 * Adds a html subpart to the mimePart object and
518
+	 * returns it during the build process.
519
+	 *
520
+	 * @param mixed &$obj The object to add the part to, or
521
+	 *                    anything else if a new object is to be created.
522
+	 *
523
+	 * @return object     The html mimePart object
524
+	 * @access private
525
+	 */
526
+	function &_addHtmlPart(&$obj)
527
+	{
528
+		$params['content_type'] = 'text/html';
529
+		$params['encoding']     = $this->_build_params['html_encoding'];
530
+		$params['charset']      = $this->_build_params['html_charset'];
531
+		$params['eol']          = $this->_build_params['eol'];
532
+
533
+		if (is_object($obj)) {
534
+			$ret = $obj->addSubpart($this->_htmlbody, $params);
535
+		} else {
536
+			$ret = new Mail_mimePart($this->_htmlbody, $params);
537
+		}
538
+
539
+		return $ret;
540
+	}
541
+
542
+	/**
543
+	 * Creates a new mimePart object, using multipart/mixed as
544
+	 * the initial content-type and returns it during the
545
+	 * build process.
546
+	 *
547
+	 * @return object The multipart/mixed mimePart object
548
+	 * @access private
549
+	 */
550
+	function &_addMixedPart()
551
+	{
552
+		$params['content_type'] = 'multipart/mixed';
553
+		$params['eol']          = $this->_build_params['eol'];
554
+
555
+		// Create empty multipart/mixed Mail_mimePart object to return
556
+		$ret = new Mail_mimePart('', $params);
557
+		return $ret;
558
+	}
559
+
560
+	/**
561
+	 * Adds a multipart/alternative part to a mimePart
562
+	 * object (or creates one), and returns it during
563
+	 * the build process.
564
+	 *
565
+	 * @param mixed &$obj The object to add the part to, or
566
+	 *                    anything else if a new object is to be created.
567
+	 *
568
+	 * @return object     The multipart/mixed mimePart object
569
+	 * @access private
570
+	 */
571
+	function &_addAlternativePart(&$obj)
572
+	{
573
+		$params['content_type'] = 'multipart/alternative';
574
+		$params['eol']          = $this->_build_params['eol'];
575
+
576
+		if (is_object($obj)) {
577
+			$ret = $obj->addSubpart('', $params);
578
+		} else {
579
+			$ret = new Mail_mimePart('', $params);
580
+		}
581
+
582
+		return $ret;
583
+	}
584
+
585
+	/**
586
+	 * Adds a multipart/related part to a mimePart
587
+	 * object (or creates one), and returns it during
588
+	 * the build process.
589
+	 *
590
+	 * @param mixed &$obj The object to add the part to, or
591
+	 *                    anything else if a new object is to be created
592
+	 *
593
+	 * @return object     The multipart/mixed mimePart object
594
+	 * @access private
595
+	 */
596
+	function &_addRelatedPart(&$obj)
597
+	{
598
+		$params['content_type'] = 'multipart/related';
599
+		$params['eol']          = $this->_build_params['eol'];
600
+
601
+		if (is_object($obj)) {
602
+			$ret = $obj->addSubpart('', $params);
603
+		} else {
604
+			$ret = new Mail_mimePart('', $params);
605
+		}
606
+
607
+		return $ret;
608
+	}
609
+
610
+	/**
611
+	 * Adds an html image subpart to a mimePart object
612
+	 * and returns it during the build process.
613
+	 *
614
+	 * @param object &$obj  The mimePart to add the image to
615
+	 * @param array  $value The image information
616
+	 *
617
+	 * @return object       The image mimePart object
618
+	 * @access private
619
+	 */
620
+	function &_addHtmlImagePart(&$obj, $value)
621
+	{
622
+		$params['content_type'] = $value['c_type'];
623
+		$params['encoding']     = 'base64';
624
+		$params['disposition']  = 'inline';
625
+		$params['filename']     = $value['name'];
626
+		$params['cid']          = $value['cid'];
627
+		$params['body_file']    = $value['body_file'];
628
+		$params['eol']          = $this->_build_params['eol'];
629
+
630
+		if (!empty($value['name_encoding'])) {
631
+			$params['name_encoding'] = $value['name_encoding'];
632
+		}
633
+		if (!empty($value['filename_encoding'])) {
634
+			$params['filename_encoding'] = $value['filename_encoding'];
635
+		}
636
+
637
+		$ret = $obj->addSubpart($value['body'], $params);
638
+		return $ret;
639
+	}
640
+
641
+	/**
642
+	 * Adds an attachment subpart to a mimePart object
643
+	 * and returns it during the build process.
644
+	 *
645
+	 * @param object &$obj  The mimePart to add the image to
646
+	 * @param array  $value The attachment information
647
+	 *
648
+	 * @return object       The image mimePart object
649
+	 * @access private
650
+	 */
651
+	function &_addAttachmentPart(&$obj, $value)
652
+	{
653
+		$params['eol']          = $this->_build_params['eol'];
654
+		$params['filename']     = $value['name'];
655
+		$params['encoding']     = $value['encoding'];
656
+		$params['content_type'] = $value['c_type'];
657
+		$params['body_file']    = $value['body_file'];
658
+		$params['disposition']  = isset($value['disposition']) ? 
659
+								  $value['disposition'] : 'attachment';
660
+
661
+		// content charset
662
+		if (!empty($value['charset'])) {
663
+			$params['charset'] = $value['charset'];
664
+		}
665
+		// headers charset (filename, description)
666
+		if (!empty($value['headers_charset'])) {
667
+			$params['headers_charset'] = $value['headers_charset'];
668
+		}
669
+		if (!empty($value['language'])) {
670
+			$params['language'] = $value['language'];
671
+		}
672
+		if (!empty($value['location'])) {
673
+			$params['location'] = $value['location'];
674
+		}
675
+		if (!empty($value['name_encoding'])) {
676
+			$params['name_encoding'] = $value['name_encoding'];
677
+		}
678
+		if (!empty($value['filename_encoding'])) {
679
+			$params['filename_encoding'] = $value['filename_encoding'];
680
+		}
681
+		if (!empty($value['description'])) {
682
+			$params['description'] = $value['description'];
683
+		}
684
+		if (is_array($value['add_headers'])) {
685
+			$params['headers'] = $value['add_headers'];
686
+		}
687
+
688
+		$ret = $obj->addSubpart($value['body'], $params);
689
+		return $ret;
690
+	}
691
+
692
+	/**
693
+	 * Returns the complete e-mail, ready to send using an alternative
694
+	 * mail delivery method. Note that only the mailpart that is made
695
+	 * with Mail_Mime is created. This means that,
696
+	 * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF 
697
+	 * using the $headers parameter!
698
+	 * 
699
+	 * @param string $separation The separation between these two parts.
700
+	 * @param array  $params     The Build parameters passed to the
701
+	 *                           get() function. See get() for more info.
702
+	 * @param array  $headers    The extra headers that should be passed
703
+	 *                           to the headers() method.
704
+	 *                           See that function for more info.
705
+	 * @param bool   $overwrite  Overwrite the existing headers with new.
706
+	 *
707
+	 * @return mixed The complete e-mail or PEAR error object
708
+	 * @access public
709
+	 */
710
+	function getMessage($separation = null, $params = null, $headers = null,
711
+		$overwrite = false
712
+	) {
713
+		if ($separation === null) {
714
+			$separation = $this->_build_params['eol'];
715
+		}
716
+
717
+		$body = $this->get($params);
718
+
719
+		if ($this->_isError($body)) {
720
+			return $body;
721
+		}
722
+
723
+		return $this->txtHeaders($headers, $overwrite) . $separation . $body;
724
+	}
725
+
726
+	/**
727
+	 * Returns the complete e-mail body, ready to send using an alternative
728
+	 * mail delivery method.
729
+	 * 
730
+	 * @param array $params The Build parameters passed to the
731
+	 *                      get() method. See get() for more info.
732
+	 *
733
+	 * @return mixed The e-mail body or PEAR error object
734
+	 * @access public
735
+	 * @since 1.6.0
736
+	 */
737
+	function getMessageBody($params = null)
738
+	{
739
+		return $this->get($params, null, true);
740
+	}
741
+
742
+	/**
743
+	 * Writes (appends) the complete e-mail into file.
744
+	 * 
745
+	 * @param string $filename  Output file location
746
+	 * @param array  $params    The Build parameters passed to the
747
+	 *                          get() method. See get() for more info.
748
+	 * @param array  $headers   The extra headers that should be passed
749
+	 *                          to the headers() function.
750
+	 *                          See that function for more info.
751
+	 * @param bool   $overwrite Overwrite the existing headers with new.
752
+	 *
753
+	 * @return mixed True or PEAR error object
754
+	 * @access public
755
+	 * @since 1.6.0
756
+	 */
757
+	function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
758
+	{
759
+		// Check state of file and raise an error properly
760
+		if (file_exists($filename) && !is_writable($filename)) {
761
+			return $this->_raiseError('File is not writable: ' . $filename);
762
+		}
763
+
764
+		// Temporarily reset magic_quotes_runtime and read file contents
765
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
766
+			@ini_set('magic_quotes_runtime', 0);
767
+		}
768
+
769
+		if (!($fh = fopen($filename, 'ab'))) {
770
+			return $this->_raiseError('Unable to open file: ' . $filename);
771
+		}
772
+
773
+		// Write message headers into file (skipping Content-* headers)
774
+		$head = $this->txtHeaders($headers, $overwrite, true);
775
+		if (fwrite($fh, $head) === false) {
776
+			return $this->_raiseError('Error writing to file: ' . $filename);
777
+		}
778
+
779
+		fclose($fh);
780
+
781
+		if ($magic_quote_setting) {
782
+			@ini_set('magic_quotes_runtime', $magic_quote_setting);
783
+		}
784
+
785
+		// Write the rest of the message into file
786
+		$res = $this->get($params, $filename);
787
+
788
+		return $res ? $res : true;
789
+	}
790
+
791
+	/**
792
+	 * Writes (appends) the complete e-mail body into file.
793
+	 *
794
+	 * @param string $filename Output file location
795
+	 * @param array  $params   The Build parameters passed to the
796
+	 *                         get() method. See get() for more info.
797
+	 *
798
+	 * @return mixed True or PEAR error object
799
+	 * @access public
800
+	 * @since 1.6.0
801
+	 */
802
+	function saveMessageBody($filename, $params = null)
803
+	{
804
+		// Check state of file and raise an error properly
805
+		if (file_exists($filename) && !is_writable($filename)) {
806
+			return $this->_raiseError('File is not writable: ' . $filename);
807
+		}
808
+
809
+		// Temporarily reset magic_quotes_runtime and read file contents
810
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
811
+			@ini_set('magic_quotes_runtime', 0);
812
+		}
813
+
814
+		if (!($fh = fopen($filename, 'ab'))) {
815
+			return $this->_raiseError('Unable to open file: ' . $filename);
816
+		}
817
+
818
+		// Write the rest of the message into file
819
+		$res = $this->get($params, $filename, true);
820
+
821
+		return $res ? $res : true;
822
+	}
823
+
824
+	/**
825
+	 * Builds the multipart message from the list ($this->_parts) and
826
+	 * returns the mime content.
827
+	 *
828
+	 * @param array    $params    Build parameters that change the way the email
829
+	 *                            is built. Should be associative. See $_build_params.
830
+	 * @param resource $filename  Output file where to save the message instead of
831
+	 *                            returning it
832
+	 * @param boolean  $skip_head True if you want to return/save only the message
833
+	 *                            without headers
834
+	 *
835
+	 * @return mixed The MIME message content string, null or PEAR error object
836
+	 * @access public
837
+	 */
838
+	function get($params = null, $filename = null, $skip_head = false)
839
+	{
840
+		if (isset($params)) {
841
+			while (list($key, $value) = each($params)) {
842
+				$this->_build_params[$key] = $value;
843
+			}
844
+		}
845
+
846
+		if (isset($this->_headers['From'])) {
847
+			// Bug #11381: Illegal characters in domain ID
848
+			if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) {
849
+				$domainID = $matches[1];
850
+			} else {
851
+				$domainID = '@localhost';
852
+			}
853
+			foreach ($this->_html_images as $i => $img) {
854
+				$cid = $this->_html_images[$i]['cid']; 
855
+				if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
856
+					$this->_html_images[$i]['cid'] = $cid . $domainID;
857
+				}
858
+			}
859
+		}
860
+
861
+		if (count($this->_html_images) && isset($this->_htmlbody)) {
862
+			foreach ($this->_html_images as $key => $value) {
863
+				$regex   = array();
864
+				$regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
865
+							preg_quote($value['name'], '#') . '\3#';
866
+				$regex[] = '#(?i)url(?-i)\(\s*(["\']?)' .
867
+							preg_quote($value['name'], '#') . '\1\s*\)#';
868
+
869
+				$rep   = array();
870
+				$rep[] = '\1\2=\3cid:' . $value['cid'] .'\3';
871
+				$rep[] = 'url(\1cid:' . $value['cid'] . '\1)';
872
+
873
+				$this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody);
874
+				$this->_html_images[$key]['name']
875
+					= $this->_basename($this->_html_images[$key]['name']);
876
+			}
877
+		}
878
+
879
+		$this->_checkParams();
880
+
881
+		$null        = -1;
882
+		$attachments = count($this->_parts) > 0;
883
+		$html_images = count($this->_html_images) > 0;
884
+		$html        = strlen($this->_htmlbody) > 0;
885
+		$text        = !$html && strlen($this->_txtbody);
886
+
887
+		switch (true) {
888
+		case $text && !$attachments:
889
+			$message =& $this->_addTextPart($null, $this->_txtbody);
890
+			break;
891
+
892
+		case !$text && !$html && $attachments:
893
+			$message =& $this->_addMixedPart();
894
+			for ($i = 0; $i < count($this->_parts); $i++) {
895
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
896
+			}
897
+			break;
898
+
899
+		case $text && $attachments:
900
+			$message =& $this->_addMixedPart();
901
+			$this->_addTextPart($message, $this->_txtbody);
902
+			for ($i = 0; $i < count($this->_parts); $i++) {
903
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
904
+			}
905
+			break;
906
+
907
+		case $html && !$attachments && !$html_images:
908
+			if (isset($this->_txtbody)) {
909
+				$message =& $this->_addAlternativePart($null);
910
+				$this->_addTextPart($message, $this->_txtbody);
911
+				$this->_addHtmlPart($message);
912
+			} else {
913
+				$message =& $this->_addHtmlPart($null);
914
+			}
915
+			break;
916
+
917
+		case $html && !$attachments && $html_images:
918
+			// * Content-Type: multipart/alternative;
919
+			//    * text
920
+			//    * Content-Type: multipart/related;
921
+			//       * html
922
+			//       * image...
923
+			if (isset($this->_txtbody)) {
924
+				$message =& $this->_addAlternativePart($null);
925
+				$this->_addTextPart($message, $this->_txtbody);
926
+
927
+				$ht =& $this->_addRelatedPart($message);
928
+				$this->_addHtmlPart($ht);
929
+				for ($i = 0; $i < count($this->_html_images); $i++) {
930
+					$this->_addHtmlImagePart($ht, $this->_html_images[$i]);
931
+				}
932
+			} else {
933
+				// * Content-Type: multipart/related;
934
+				//    * html
935
+				//    * image...
936
+				$message =& $this->_addRelatedPart($null);
937
+				$this->_addHtmlPart($message);
938
+				for ($i = 0; $i < count($this->_html_images); $i++) {
939
+					$this->_addHtmlImagePart($message, $this->_html_images[$i]);
940
+				}
941
+			}
942
+			/*
943 943
             // #13444, #9725: the code below was a non-RFC compliant hack
944 944
             // * Content-Type: multipart/related;
945 945
             //    * Content-Type: multipart/alternative;
@@ -958,537 +958,537 @@  discard block
 block discarded – undo
958 958
                 $this->_addHtmlImagePart($message, $this->_html_images[$i]);
959 959
             }
960 960
             */
961
-            break;
962
-
963
-        case $html && $attachments && !$html_images:
964
-            $message =& $this->_addMixedPart();
965
-            if (isset($this->_txtbody)) {
966
-                $alt =& $this->_addAlternativePart($message);
967
-                $this->_addTextPart($alt, $this->_txtbody);
968
-                $this->_addHtmlPart($alt);
969
-            } else {
970
-                $this->_addHtmlPart($message);
971
-            }
972
-            for ($i = 0; $i < count($this->_parts); $i++) {
973
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
974
-            }
975
-            break;
976
-
977
-        case $html && $attachments && $html_images:
978
-            $message =& $this->_addMixedPart();
979
-            if (isset($this->_txtbody)) {
980
-                $alt =& $this->_addAlternativePart($message);
981
-                $this->_addTextPart($alt, $this->_txtbody);
982
-                $rel =& $this->_addRelatedPart($alt);
983
-            } else {
984
-                $rel =& $this->_addRelatedPart($message);
985
-            }
986
-            $this->_addHtmlPart($rel);
987
-            for ($i = 0; $i < count($this->_html_images); $i++) {
988
-                $this->_addHtmlImagePart($rel, $this->_html_images[$i]);
989
-            }
990
-            for ($i = 0; $i < count($this->_parts); $i++) {
991
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
992
-            }
993
-            break;
994
-        }
995
-
996
-        if (!isset($message)) {
997
-            return null;
998
-        }
999
-
1000
-        // Use saved boundary
1001
-        if (!empty($this->_build_params['boundary'])) {
1002
-            $boundary = $this->_build_params['boundary'];
1003
-        } else {
1004
-            $boundary = null;
1005
-        }
1006
-
1007
-        // Write output to file
1008
-        if ($filename) {
1009
-            // Append mimePart message headers and body into file
1010
-            $headers = $message->encodeToFile($filename, $boundary, $skip_head);
1011
-            if ($this->_isError($headers)) {
1012
-                return $headers;
1013
-            }
1014
-            $this->_headers = array_merge($this->_headers, $headers);
1015
-            return null;
1016
-        } else {
1017
-            $output = $message->encode($boundary, $skip_head);
1018
-            if ($this->_isError($output)) {
1019
-                return $output;
1020
-            }
1021
-            $this->_headers = array_merge($this->_headers, $output['headers']);
1022
-            return $output['body'];
1023
-        }
1024
-    }
1025
-
1026
-    /**
1027
-     * Returns an array with the headers needed to prepend to the email
1028
-     * (MIME-Version and Content-Type). Format of argument is:
1029
-     * $array['header-name'] = 'header-value';
1030
-     *
1031
-     * @param array $xtra_headers Assoc array with any extra headers (optional)
1032
-     *                            (Don't set Content-Type for multipart messages here!)
1033
-     * @param bool  $overwrite    Overwrite already existing headers.
1034
-     * @param bool  $skip_content Don't return content headers: Content-Type,
1035
-     *                            Content-Disposition and Content-Transfer-Encoding
1036
-     * 
1037
-     * @return array              Assoc array with the mime headers
1038
-     * @access public
1039
-     */
1040
-    function headers($xtra_headers = null, $overwrite = false, $skip_content = false)
1041
-    {
1042
-        // Add mime version header
1043
-        $headers['MIME-Version'] = '1.0';
1044
-
1045
-        // Content-Type and Content-Transfer-Encoding headers should already
1046
-        // be present if get() was called, but we'll re-set them to make sure
1047
-        // we got them when called before get() or something in the message
1048
-        // has been changed after get() [#14780]
1049
-        if (!$skip_content) {
1050
-            $headers += $this->_contentHeaders();
1051
-        }
1052
-
1053
-        if (!empty($xtra_headers)) {
1054
-            $headers = array_merge($headers, $xtra_headers);
1055
-        }
1056
-
1057
-        if ($overwrite) {
1058
-            $this->_headers = array_merge($this->_headers, $headers);
1059
-        } else {
1060
-            $this->_headers = array_merge($headers, $this->_headers);
1061
-        }
1062
-
1063
-        $headers = $this->_headers;
1064
-
1065
-        if ($skip_content) {
1066
-            unset($headers['Content-Type']);
1067
-            unset($headers['Content-Transfer-Encoding']);
1068
-            unset($headers['Content-Disposition']);
1069
-        } else if (!empty($this->_build_params['ctype'])) {
1070
-            $headers['Content-Type'] = $this->_build_params['ctype'];
1071
-        }
1072
-
1073
-        $encodedHeaders = $this->_encodeHeaders($headers);
1074
-        return $encodedHeaders;
1075
-    }
1076
-
1077
-    /**
1078
-     * Get the text version of the headers
1079
-     * (usefull if you want to use the PHP mail() function)
1080
-     *
1081
-     * @param array $xtra_headers Assoc array with any extra headers (optional)
1082
-     *                            (Don't set Content-Type for multipart messages here!)
1083
-     * @param bool  $overwrite    Overwrite the existing headers with new.
1084
-     * @param bool  $skip_content Don't return content headers: Content-Type,
1085
-     *                            Content-Disposition and Content-Transfer-Encoding
1086
-     *
1087
-     * @return string             Plain text headers
1088
-     * @access public
1089
-     */
1090
-    function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
1091
-    {
1092
-        $headers = $this->headers($xtra_headers, $overwrite, $skip_content);
1093
-
1094
-        // Place Received: headers at the beginning of the message
1095
-        // Spam detectors often flag messages with it after the Subject: as spam
1096
-        if (isset($headers['Received'])) {
1097
-            $received = $headers['Received'];
1098
-            unset($headers['Received']);
1099
-            $headers = array('Received' => $received) + $headers;
1100
-        }
1101
-
1102
-        $ret = '';
1103
-        $eol = $this->_build_params['eol'];
1104
-
1105
-        foreach ($headers as $key => $val) {
1106
-            if (is_array($val)) {
1107
-                foreach ($val as $value) {
1108
-                    $ret .= "$key: $value" . $eol;
1109
-                }
1110
-            } else {
1111
-                $ret .= "$key: $val" . $eol;
1112
-            }
1113
-        }
1114
-
1115
-        return $ret;
1116
-    }
1117
-
1118
-    /**
1119
-     * Sets message Content-Type header.
1120
-     * Use it to build messages with various content-types e.g. miltipart/raport
1121
-     * not supported by _contentHeaders() function.
1122
-     *
1123
-     * @param string $type   Type name
1124
-     * @param array  $params Hash array of header parameters
1125
-     *
1126
-     * @return void
1127
-     * @access public
1128
-     * @since 1.7.0
1129
-     */
1130
-    function setContentType($type, $params = array())
1131
-    {
1132
-        $header = $type;
1133
-
1134
-        $eol = !empty($this->_build_params['eol'])
1135
-            ? $this->_build_params['eol'] : "\r\n";
1136
-
1137
-        // add parameters
1138
-        $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
1139
-            . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
1140
-        if (is_array($params)) {
1141
-            foreach ($params as $name => $value) {
1142
-                if ($name == 'boundary') {
1143
-                    $this->_build_params['boundary'] = $value;
1144
-                }
1145
-                if (!preg_match($token_regexp, $value)) {
1146
-                    $header .= ";$eol $name=$value";
1147
-                } else {
1148
-                    $value = addcslashes($value, '\\"');
1149
-                    $header .= ";$eol $name=\"$value\"";
1150
-                }
1151
-            }
1152
-        }
1153
-
1154
-        // add required boundary parameter if not defined
1155
-        if (preg_match('/^multipart\//i', $type)) {
1156
-            if (empty($this->_build_params['boundary'])) {
1157
-                $this->_build_params['boundary'] = '=_' . md5(rand() . microtime());
1158
-            }
1159
-
1160
-            $header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
1161
-        }
1162
-
1163
-        $this->_build_params['ctype'] = $header;
1164
-    }
1165
-
1166
-    /**
1167
-     * Sets the Subject header
1168
-     *
1169
-     * @param string $subject String to set the subject to.
1170
-     *
1171
-     * @return void
1172
-     * @access public
1173
-     */
1174
-    function setSubject($subject)
1175
-    {
1176
-        $this->_headers['Subject'] = $subject;
1177
-    }
1178
-
1179
-    /**
1180
-     * Set an email to the From (the sender) header
1181
-     *
1182
-     * @param string $email The email address to use
1183
-     *
1184
-     * @return void
1185
-     * @access public
1186
-     */
1187
-    function setFrom($email)
1188
-    {
1189
-        $this->_headers['From'] = $email;
1190
-    }
1191
-
1192
-    /**
1193
-     * Add an email to the To header
1194
-     * (multiple calls to this method are allowed)
1195
-     *
1196
-     * @param string $email The email direction to add
1197
-     *
1198
-     * @return void
1199
-     * @access public
1200
-     */
1201
-    function addTo($email)
1202
-    {
1203
-        if (isset($this->_headers['To'])) {
1204
-            $this->_headers['To'] .= ", $email";
1205
-        } else {
1206
-            $this->_headers['To'] = $email;
1207
-        }
1208
-    }
1209
-
1210
-    /**
1211
-     * Add an email to the Cc (carbon copy) header
1212
-     * (multiple calls to this method are allowed)
1213
-     *
1214
-     * @param string $email The email direction to add
1215
-     *
1216
-     * @return void
1217
-     * @access public
1218
-     */
1219
-    function addCc($email)
1220
-    {
1221
-        if (isset($this->_headers['Cc'])) {
1222
-            $this->_headers['Cc'] .= ", $email";
1223
-        } else {
1224
-            $this->_headers['Cc'] = $email;
1225
-        }
1226
-    }
1227
-
1228
-    /**
1229
-     * Add an email to the Bcc (blank carbon copy) header
1230
-     * (multiple calls to this method are allowed)
1231
-     *
1232
-     * @param string $email The email direction to add
1233
-     *
1234
-     * @return void
1235
-     * @access public
1236
-     */
1237
-    function addBcc($email)
1238
-    {
1239
-        if (isset($this->_headers['Bcc'])) {
1240
-            $this->_headers['Bcc'] .= ", $email";
1241
-        } else {
1242
-            $this->_headers['Bcc'] = $email;
1243
-        }
1244
-    }
1245
-
1246
-    /**
1247
-     * Since the PHP send function requires you to specify
1248
-     * recipients (To: header) separately from the other
1249
-     * headers, the To: header is not properly encoded.
1250
-     * To fix this, you can use this public method to 
1251
-     * encode your recipients before sending to the send
1252
-     * function
1253
-     *
1254
-     * @param string $recipients A comma-delimited list of recipients
1255
-     *
1256
-     * @return string            Encoded data
1257
-     * @access public
1258
-     */
1259
-    function encodeRecipients($recipients)
1260
-    {
1261
-        $input = array("To" => $recipients);
1262
-        $retval = $this->_encodeHeaders($input);
1263
-        return $retval["To"] ;
1264
-    }
1265
-
1266
-    /**
1267
-     * Encodes headers as per RFC2047
1268
-     *
1269
-     * @param array $input  The header data to encode
1270
-     * @param array $params Extra build parameters
1271
-     *
1272
-     * @return array        Encoded data
1273
-     * @access private
1274
-     */
1275
-    function _encodeHeaders($input, $params = array())
1276
-    {
1277
-        $build_params = $this->_build_params;
1278
-        while (list($key, $value) = each($params)) {
1279
-            $build_params[$key] = $value;
1280
-        }
1281
-
1282
-        foreach ($input as $hdr_name => $hdr_value) {
1283
-            if (is_array($hdr_value)) {
1284
-                foreach ($hdr_value as $idx => $value) {
1285
-                    $input[$hdr_name][$idx] = $this->encodeHeader(
1286
-                        $hdr_name, $value,
1287
-                        $build_params['head_charset'], $build_params['head_encoding']
1288
-                    );
1289
-                }
1290
-            } else {
1291
-                $input[$hdr_name] = $this->encodeHeader(
1292
-                    $hdr_name, $hdr_value,
1293
-                    $build_params['head_charset'], $build_params['head_encoding']
1294
-                );
1295
-            }
1296
-        }
1297
-
1298
-        return $input;
1299
-    }
1300
-
1301
-    /**
1302
-     * Encodes a header as per RFC2047
1303
-     *
1304
-     * @param string $name     The header name
1305
-     * @param string $value    The header data to encode
1306
-     * @param string $charset  Character set name
1307
-     * @param string $encoding Encoding name (base64 or quoted-printable)
1308
-     *
1309
-     * @return string          Encoded header data (without a name)
1310
-     * @access public
1311
-     * @since 1.5.3
1312
-     */
1313
-    function encodeHeader($name, $value, $charset, $encoding)
1314
-    {
1315
-        $mime_part = new Mail_mimePart;
1316
-        return $mime_part->encodeHeader(
1317
-            $name, $value, $charset, $encoding, $this->_build_params['eol']
1318
-        );
1319
-    }
1320
-
1321
-    /**
1322
-     * Get file's basename (locale independent) 
1323
-     *
1324
-     * @param string $filename Filename
1325
-     *
1326
-     * @return string          Basename
1327
-     * @access private
1328
-     */
1329
-    function _basename($filename)
1330
-    {
1331
-        // basename() is not unicode safe and locale dependent
1332
-        if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
1333
-            return preg_replace('/^.*[\\\\\\/]/', '', $filename);
1334
-        } else {
1335
-            return preg_replace('/^.*[\/]/', '', $filename);
1336
-        }
1337
-    }
1338
-
1339
-    /**
1340
-     * Get Content-Type and Content-Transfer-Encoding headers of the message
1341
-     *
1342
-     * @return array Headers array
1343
-     * @access private
1344
-     */
1345
-    function _contentHeaders()
1346
-    {
1347
-        $attachments = count($this->_parts)                 ? true : false;
1348
-        $html_images = count($this->_html_images)           ? true : false;
1349
-        $html        = strlen($this->_htmlbody)             ? true : false;
1350
-        $text        = (!$html && strlen($this->_txtbody))  ? true : false;
1351
-        $headers     = array();
1352
-
1353
-        // See get()
1354
-        switch (true) {
1355
-        case $text && !$attachments:
1356
-            $headers['Content-Type'] = 'text/plain';
1357
-            break;
1358
-
1359
-        case !$text && !$html && $attachments:
1360
-        case $text && $attachments:
1361
-        case $html && $attachments && !$html_images:
1362
-        case $html && $attachments && $html_images:
1363
-            $headers['Content-Type'] = 'multipart/mixed';
1364
-            break;
1365
-
1366
-        case $html && !$attachments && !$html_images && isset($this->_txtbody):
1367
-        case $html && !$attachments && $html_images && isset($this->_txtbody):
1368
-            $headers['Content-Type'] = 'multipart/alternative';
1369
-            break;
1370
-
1371
-        case $html && !$attachments && !$html_images && !isset($this->_txtbody):
1372
-            $headers['Content-Type'] = 'text/html';
1373
-            break;
1374
-
1375
-        case $html && !$attachments && $html_images && !isset($this->_txtbody):
1376
-            $headers['Content-Type'] = 'multipart/related';
1377
-            break;
1378
-
1379
-        default:
1380
-            return $headers;
1381
-        }
1382
-
1383
-        $this->_checkParams();
1384
-
1385
-        $eol = !empty($this->_build_params['eol'])
1386
-            ? $this->_build_params['eol'] : "\r\n";
1387
-
1388
-        if ($headers['Content-Type'] == 'text/plain') {
1389
-            // single-part message: add charset and encoding
1390
-            $charset = 'charset=' . $this->_build_params['text_charset'];
1391
-            // place charset parameter in the same line, if possible
1392
-            // 26 = strlen("Content-Type: text/plain; ")
1393
-            $headers['Content-Type']
1394
-                .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
1395
-            $headers['Content-Transfer-Encoding']
1396
-                = $this->_build_params['text_encoding'];
1397
-        } else if ($headers['Content-Type'] == 'text/html') {
1398
-            // single-part message: add charset and encoding
1399
-            $charset = 'charset=' . $this->_build_params['html_charset'];
1400
-            // place charset parameter in the same line, if possible
1401
-            $headers['Content-Type']
1402
-                .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
1403
-            $headers['Content-Transfer-Encoding']
1404
-                = $this->_build_params['html_encoding'];
1405
-        } else {
1406
-            // multipart message: and boundary
1407
-            if (!empty($this->_build_params['boundary'])) {
1408
-                $boundary = $this->_build_params['boundary'];
1409
-            } else if (!empty($this->_headers['Content-Type'])
1410
-                && preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
1411
-            ) {
1412
-                $boundary = $m[1];
1413
-            } else {
1414
-                $boundary = '=_' . md5(rand() . microtime());
1415
-            }
1416
-
1417
-            $this->_build_params['boundary'] = $boundary;
1418
-            $headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
1419
-        }
1420
-
1421
-        return $headers;
1422
-    }
1423
-
1424
-    /**
1425
-     * Validate and set build parameters
1426
-     *
1427
-     * @return void
1428
-     * @access private
1429
-     */
1430
-    function _checkParams()
1431
-    {
1432
-        $encodings = array('7bit', '8bit', 'base64', 'quoted-printable');
1433
-
1434
-        $this->_build_params['text_encoding']
1435
-            = strtolower($this->_build_params['text_encoding']);
1436
-        $this->_build_params['html_encoding']
1437
-            = strtolower($this->_build_params['html_encoding']);
1438
-
1439
-        if (!in_array($this->_build_params['text_encoding'], $encodings)) {
1440
-            $this->_build_params['text_encoding'] = '7bit';
1441
-        }
1442
-        if (!in_array($this->_build_params['html_encoding'], $encodings)) {
1443
-            $this->_build_params['html_encoding'] = '7bit';
1444
-        }
1445
-
1446
-        // text body
1447
-        if ($this->_build_params['text_encoding'] == '7bit'
1448
-            && !preg_match('/ascii/i', $this->_build_params['text_charset'])
1449
-            && preg_match('/[^\x00-\x7F]/', $this->_txtbody)
1450
-        ) {
1451
-            $this->_build_params['text_encoding'] = 'quoted-printable';
1452
-        }
1453
-        // html body
1454
-        if ($this->_build_params['html_encoding'] == '7bit'
1455
-            && !preg_match('/ascii/i', $this->_build_params['html_charset'])
1456
-            && preg_match('/[^\x00-\x7F]/', $this->_htmlbody)
1457
-        ) {
1458
-            $this->_build_params['html_encoding'] = 'quoted-printable';
1459
-        }
1460
-    }
1461
-
1462
-    /**
1463
-     * PEAR::isError implementation
1464
-     *
1465
-     * @param mixed $data Object
1466
-     *
1467
-     * @return bool True if object is an instance of PEAR_Error
1468
-     * @access private
1469
-     */
1470
-    function _isError($data)
1471
-    {
1472
-        // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1473
-        if (is_object($data) && is_a($data, 'PEAR_Error')) {
1474
-            return true;
1475
-        }
1476
-
1477
-        return false;
1478
-    }
1479
-
1480
-    /**
1481
-     * PEAR::raiseError implementation
1482
-     *
1483
-     * @param $message A text error message
1484
-     *
1485
-     * @return PEAR_Error Instance of PEAR_Error
1486
-     * @access private
1487
-     */
1488
-    function _raiseError($message)
1489
-    {
1490
-        // PEAR::raiseError() is not PHP 5.4 compatible
1491
-        return new PEAR_Error($message);
1492
-    }
961
+			break;
962
+
963
+		case $html && $attachments && !$html_images:
964
+			$message =& $this->_addMixedPart();
965
+			if (isset($this->_txtbody)) {
966
+				$alt =& $this->_addAlternativePart($message);
967
+				$this->_addTextPart($alt, $this->_txtbody);
968
+				$this->_addHtmlPart($alt);
969
+			} else {
970
+				$this->_addHtmlPart($message);
971
+			}
972
+			for ($i = 0; $i < count($this->_parts); $i++) {
973
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
974
+			}
975
+			break;
976
+
977
+		case $html && $attachments && $html_images:
978
+			$message =& $this->_addMixedPart();
979
+			if (isset($this->_txtbody)) {
980
+				$alt =& $this->_addAlternativePart($message);
981
+				$this->_addTextPart($alt, $this->_txtbody);
982
+				$rel =& $this->_addRelatedPart($alt);
983
+			} else {
984
+				$rel =& $this->_addRelatedPart($message);
985
+			}
986
+			$this->_addHtmlPart($rel);
987
+			for ($i = 0; $i < count($this->_html_images); $i++) {
988
+				$this->_addHtmlImagePart($rel, $this->_html_images[$i]);
989
+			}
990
+			for ($i = 0; $i < count($this->_parts); $i++) {
991
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
992
+			}
993
+			break;
994
+		}
995
+
996
+		if (!isset($message)) {
997
+			return null;
998
+		}
999
+
1000
+		// Use saved boundary
1001
+		if (!empty($this->_build_params['boundary'])) {
1002
+			$boundary = $this->_build_params['boundary'];
1003
+		} else {
1004
+			$boundary = null;
1005
+		}
1006
+
1007
+		// Write output to file
1008
+		if ($filename) {
1009
+			// Append mimePart message headers and body into file
1010
+			$headers = $message->encodeToFile($filename, $boundary, $skip_head);
1011
+			if ($this->_isError($headers)) {
1012
+				return $headers;
1013
+			}
1014
+			$this->_headers = array_merge($this->_headers, $headers);
1015
+			return null;
1016
+		} else {
1017
+			$output = $message->encode($boundary, $skip_head);
1018
+			if ($this->_isError($output)) {
1019
+				return $output;
1020
+			}
1021
+			$this->_headers = array_merge($this->_headers, $output['headers']);
1022
+			return $output['body'];
1023
+		}
1024
+	}
1025
+
1026
+	/**
1027
+	 * Returns an array with the headers needed to prepend to the email
1028
+	 * (MIME-Version and Content-Type). Format of argument is:
1029
+	 * $array['header-name'] = 'header-value';
1030
+	 *
1031
+	 * @param array $xtra_headers Assoc array with any extra headers (optional)
1032
+	 *                            (Don't set Content-Type for multipart messages here!)
1033
+	 * @param bool  $overwrite    Overwrite already existing headers.
1034
+	 * @param bool  $skip_content Don't return content headers: Content-Type,
1035
+	 *                            Content-Disposition and Content-Transfer-Encoding
1036
+	 * 
1037
+	 * @return array              Assoc array with the mime headers
1038
+	 * @access public
1039
+	 */
1040
+	function headers($xtra_headers = null, $overwrite = false, $skip_content = false)
1041
+	{
1042
+		// Add mime version header
1043
+		$headers['MIME-Version'] = '1.0';
1044
+
1045
+		// Content-Type and Content-Transfer-Encoding headers should already
1046
+		// be present if get() was called, but we'll re-set them to make sure
1047
+		// we got them when called before get() or something in the message
1048
+		// has been changed after get() [#14780]
1049
+		if (!$skip_content) {
1050
+			$headers += $this->_contentHeaders();
1051
+		}
1052
+
1053
+		if (!empty($xtra_headers)) {
1054
+			$headers = array_merge($headers, $xtra_headers);
1055
+		}
1056
+
1057
+		if ($overwrite) {
1058
+			$this->_headers = array_merge($this->_headers, $headers);
1059
+		} else {
1060
+			$this->_headers = array_merge($headers, $this->_headers);
1061
+		}
1062
+
1063
+		$headers = $this->_headers;
1064
+
1065
+		if ($skip_content) {
1066
+			unset($headers['Content-Type']);
1067
+			unset($headers['Content-Transfer-Encoding']);
1068
+			unset($headers['Content-Disposition']);
1069
+		} else if (!empty($this->_build_params['ctype'])) {
1070
+			$headers['Content-Type'] = $this->_build_params['ctype'];
1071
+		}
1072
+
1073
+		$encodedHeaders = $this->_encodeHeaders($headers);
1074
+		return $encodedHeaders;
1075
+	}
1076
+
1077
+	/**
1078
+	 * Get the text version of the headers
1079
+	 * (usefull if you want to use the PHP mail() function)
1080
+	 *
1081
+	 * @param array $xtra_headers Assoc array with any extra headers (optional)
1082
+	 *                            (Don't set Content-Type for multipart messages here!)
1083
+	 * @param bool  $overwrite    Overwrite the existing headers with new.
1084
+	 * @param bool  $skip_content Don't return content headers: Content-Type,
1085
+	 *                            Content-Disposition and Content-Transfer-Encoding
1086
+	 *
1087
+	 * @return string             Plain text headers
1088
+	 * @access public
1089
+	 */
1090
+	function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
1091
+	{
1092
+		$headers = $this->headers($xtra_headers, $overwrite, $skip_content);
1093
+
1094
+		// Place Received: headers at the beginning of the message
1095
+		// Spam detectors often flag messages with it after the Subject: as spam
1096
+		if (isset($headers['Received'])) {
1097
+			$received = $headers['Received'];
1098
+			unset($headers['Received']);
1099
+			$headers = array('Received' => $received) + $headers;
1100
+		}
1101
+
1102
+		$ret = '';
1103
+		$eol = $this->_build_params['eol'];
1104
+
1105
+		foreach ($headers as $key => $val) {
1106
+			if (is_array($val)) {
1107
+				foreach ($val as $value) {
1108
+					$ret .= "$key: $value" . $eol;
1109
+				}
1110
+			} else {
1111
+				$ret .= "$key: $val" . $eol;
1112
+			}
1113
+		}
1114
+
1115
+		return $ret;
1116
+	}
1117
+
1118
+	/**
1119
+	 * Sets message Content-Type header.
1120
+	 * Use it to build messages with various content-types e.g. miltipart/raport
1121
+	 * not supported by _contentHeaders() function.
1122
+	 *
1123
+	 * @param string $type   Type name
1124
+	 * @param array  $params Hash array of header parameters
1125
+	 *
1126
+	 * @return void
1127
+	 * @access public
1128
+	 * @since 1.7.0
1129
+	 */
1130
+	function setContentType($type, $params = array())
1131
+	{
1132
+		$header = $type;
1133
+
1134
+		$eol = !empty($this->_build_params['eol'])
1135
+			? $this->_build_params['eol'] : "\r\n";
1136
+
1137
+		// add parameters
1138
+		$token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
1139
+			. '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
1140
+		if (is_array($params)) {
1141
+			foreach ($params as $name => $value) {
1142
+				if ($name == 'boundary') {
1143
+					$this->_build_params['boundary'] = $value;
1144
+				}
1145
+				if (!preg_match($token_regexp, $value)) {
1146
+					$header .= ";$eol $name=$value";
1147
+				} else {
1148
+					$value = addcslashes($value, '\\"');
1149
+					$header .= ";$eol $name=\"$value\"";
1150
+				}
1151
+			}
1152
+		}
1153
+
1154
+		// add required boundary parameter if not defined
1155
+		if (preg_match('/^multipart\//i', $type)) {
1156
+			if (empty($this->_build_params['boundary'])) {
1157
+				$this->_build_params['boundary'] = '=_' . md5(rand() . microtime());
1158
+			}
1159
+
1160
+			$header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
1161
+		}
1162
+
1163
+		$this->_build_params['ctype'] = $header;
1164
+	}
1165
+
1166
+	/**
1167
+	 * Sets the Subject header
1168
+	 *
1169
+	 * @param string $subject String to set the subject to.
1170
+	 *
1171
+	 * @return void
1172
+	 * @access public
1173
+	 */
1174
+	function setSubject($subject)
1175
+	{
1176
+		$this->_headers['Subject'] = $subject;
1177
+	}
1178
+
1179
+	/**
1180
+	 * Set an email to the From (the sender) header
1181
+	 *
1182
+	 * @param string $email The email address to use
1183
+	 *
1184
+	 * @return void
1185
+	 * @access public
1186
+	 */
1187
+	function setFrom($email)
1188
+	{
1189
+		$this->_headers['From'] = $email;
1190
+	}
1191
+
1192
+	/**
1193
+	 * Add an email to the To header
1194
+	 * (multiple calls to this method are allowed)
1195
+	 *
1196
+	 * @param string $email The email direction to add
1197
+	 *
1198
+	 * @return void
1199
+	 * @access public
1200
+	 */
1201
+	function addTo($email)
1202
+	{
1203
+		if (isset($this->_headers['To'])) {
1204
+			$this->_headers['To'] .= ", $email";
1205
+		} else {
1206
+			$this->_headers['To'] = $email;
1207
+		}
1208
+	}
1209
+
1210
+	/**
1211
+	 * Add an email to the Cc (carbon copy) header
1212
+	 * (multiple calls to this method are allowed)
1213
+	 *
1214
+	 * @param string $email The email direction to add
1215
+	 *
1216
+	 * @return void
1217
+	 * @access public
1218
+	 */
1219
+	function addCc($email)
1220
+	{
1221
+		if (isset($this->_headers['Cc'])) {
1222
+			$this->_headers['Cc'] .= ", $email";
1223
+		} else {
1224
+			$this->_headers['Cc'] = $email;
1225
+		}
1226
+	}
1227
+
1228
+	/**
1229
+	 * Add an email to the Bcc (blank carbon copy) header
1230
+	 * (multiple calls to this method are allowed)
1231
+	 *
1232
+	 * @param string $email The email direction to add
1233
+	 *
1234
+	 * @return void
1235
+	 * @access public
1236
+	 */
1237
+	function addBcc($email)
1238
+	{
1239
+		if (isset($this->_headers['Bcc'])) {
1240
+			$this->_headers['Bcc'] .= ", $email";
1241
+		} else {
1242
+			$this->_headers['Bcc'] = $email;
1243
+		}
1244
+	}
1245
+
1246
+	/**
1247
+	 * Since the PHP send function requires you to specify
1248
+	 * recipients (To: header) separately from the other
1249
+	 * headers, the To: header is not properly encoded.
1250
+	 * To fix this, you can use this public method to 
1251
+	 * encode your recipients before sending to the send
1252
+	 * function
1253
+	 *
1254
+	 * @param string $recipients A comma-delimited list of recipients
1255
+	 *
1256
+	 * @return string            Encoded data
1257
+	 * @access public
1258
+	 */
1259
+	function encodeRecipients($recipients)
1260
+	{
1261
+		$input = array("To" => $recipients);
1262
+		$retval = $this->_encodeHeaders($input);
1263
+		return $retval["To"] ;
1264
+	}
1265
+
1266
+	/**
1267
+	 * Encodes headers as per RFC2047
1268
+	 *
1269
+	 * @param array $input  The header data to encode
1270
+	 * @param array $params Extra build parameters
1271
+	 *
1272
+	 * @return array        Encoded data
1273
+	 * @access private
1274
+	 */
1275
+	function _encodeHeaders($input, $params = array())
1276
+	{
1277
+		$build_params = $this->_build_params;
1278
+		while (list($key, $value) = each($params)) {
1279
+			$build_params[$key] = $value;
1280
+		}
1281
+
1282
+		foreach ($input as $hdr_name => $hdr_value) {
1283
+			if (is_array($hdr_value)) {
1284
+				foreach ($hdr_value as $idx => $value) {
1285
+					$input[$hdr_name][$idx] = $this->encodeHeader(
1286
+						$hdr_name, $value,
1287
+						$build_params['head_charset'], $build_params['head_encoding']
1288
+					);
1289
+				}
1290
+			} else {
1291
+				$input[$hdr_name] = $this->encodeHeader(
1292
+					$hdr_name, $hdr_value,
1293
+					$build_params['head_charset'], $build_params['head_encoding']
1294
+				);
1295
+			}
1296
+		}
1297
+
1298
+		return $input;
1299
+	}
1300
+
1301
+	/**
1302
+	 * Encodes a header as per RFC2047
1303
+	 *
1304
+	 * @param string $name     The header name
1305
+	 * @param string $value    The header data to encode
1306
+	 * @param string $charset  Character set name
1307
+	 * @param string $encoding Encoding name (base64 or quoted-printable)
1308
+	 *
1309
+	 * @return string          Encoded header data (without a name)
1310
+	 * @access public
1311
+	 * @since 1.5.3
1312
+	 */
1313
+	function encodeHeader($name, $value, $charset, $encoding)
1314
+	{
1315
+		$mime_part = new Mail_mimePart;
1316
+		return $mime_part->encodeHeader(
1317
+			$name, $value, $charset, $encoding, $this->_build_params['eol']
1318
+		);
1319
+	}
1320
+
1321
+	/**
1322
+	 * Get file's basename (locale independent) 
1323
+	 *
1324
+	 * @param string $filename Filename
1325
+	 *
1326
+	 * @return string          Basename
1327
+	 * @access private
1328
+	 */
1329
+	function _basename($filename)
1330
+	{
1331
+		// basename() is not unicode safe and locale dependent
1332
+		if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
1333
+			return preg_replace('/^.*[\\\\\\/]/', '', $filename);
1334
+		} else {
1335
+			return preg_replace('/^.*[\/]/', '', $filename);
1336
+		}
1337
+	}
1338
+
1339
+	/**
1340
+	 * Get Content-Type and Content-Transfer-Encoding headers of the message
1341
+	 *
1342
+	 * @return array Headers array
1343
+	 * @access private
1344
+	 */
1345
+	function _contentHeaders()
1346
+	{
1347
+		$attachments = count($this->_parts)                 ? true : false;
1348
+		$html_images = count($this->_html_images)           ? true : false;
1349
+		$html        = strlen($this->_htmlbody)             ? true : false;
1350
+		$text        = (!$html && strlen($this->_txtbody))  ? true : false;
1351
+		$headers     = array();
1352
+
1353
+		// See get()
1354
+		switch (true) {
1355
+		case $text && !$attachments:
1356
+			$headers['Content-Type'] = 'text/plain';
1357
+			break;
1358
+
1359
+		case !$text && !$html && $attachments:
1360
+		case $text && $attachments:
1361
+		case $html && $attachments && !$html_images:
1362
+		case $html && $attachments && $html_images:
1363
+			$headers['Content-Type'] = 'multipart/mixed';
1364
+			break;
1365
+
1366
+		case $html && !$attachments && !$html_images && isset($this->_txtbody):
1367
+		case $html && !$attachments && $html_images && isset($this->_txtbody):
1368
+			$headers['Content-Type'] = 'multipart/alternative';
1369
+			break;
1370
+
1371
+		case $html && !$attachments && !$html_images && !isset($this->_txtbody):
1372
+			$headers['Content-Type'] = 'text/html';
1373
+			break;
1374
+
1375
+		case $html && !$attachments && $html_images && !isset($this->_txtbody):
1376
+			$headers['Content-Type'] = 'multipart/related';
1377
+			break;
1378
+
1379
+		default:
1380
+			return $headers;
1381
+		}
1382
+
1383
+		$this->_checkParams();
1384
+
1385
+		$eol = !empty($this->_build_params['eol'])
1386
+			? $this->_build_params['eol'] : "\r\n";
1387
+
1388
+		if ($headers['Content-Type'] == 'text/plain') {
1389
+			// single-part message: add charset and encoding
1390
+			$charset = 'charset=' . $this->_build_params['text_charset'];
1391
+			// place charset parameter in the same line, if possible
1392
+			// 26 = strlen("Content-Type: text/plain; ")
1393
+			$headers['Content-Type']
1394
+				.= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
1395
+			$headers['Content-Transfer-Encoding']
1396
+				= $this->_build_params['text_encoding'];
1397
+		} else if ($headers['Content-Type'] == 'text/html') {
1398
+			// single-part message: add charset and encoding
1399
+			$charset = 'charset=' . $this->_build_params['html_charset'];
1400
+			// place charset parameter in the same line, if possible
1401
+			$headers['Content-Type']
1402
+				.= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
1403
+			$headers['Content-Transfer-Encoding']
1404
+				= $this->_build_params['html_encoding'];
1405
+		} else {
1406
+			// multipart message: and boundary
1407
+			if (!empty($this->_build_params['boundary'])) {
1408
+				$boundary = $this->_build_params['boundary'];
1409
+			} else if (!empty($this->_headers['Content-Type'])
1410
+				&& preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
1411
+			) {
1412
+				$boundary = $m[1];
1413
+			} else {
1414
+				$boundary = '=_' . md5(rand() . microtime());
1415
+			}
1416
+
1417
+			$this->_build_params['boundary'] = $boundary;
1418
+			$headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
1419
+		}
1420
+
1421
+		return $headers;
1422
+	}
1423
+
1424
+	/**
1425
+	 * Validate and set build parameters
1426
+	 *
1427
+	 * @return void
1428
+	 * @access private
1429
+	 */
1430
+	function _checkParams()
1431
+	{
1432
+		$encodings = array('7bit', '8bit', 'base64', 'quoted-printable');
1433
+
1434
+		$this->_build_params['text_encoding']
1435
+			= strtolower($this->_build_params['text_encoding']);
1436
+		$this->_build_params['html_encoding']
1437
+			= strtolower($this->_build_params['html_encoding']);
1438
+
1439
+		if (!in_array($this->_build_params['text_encoding'], $encodings)) {
1440
+			$this->_build_params['text_encoding'] = '7bit';
1441
+		}
1442
+		if (!in_array($this->_build_params['html_encoding'], $encodings)) {
1443
+			$this->_build_params['html_encoding'] = '7bit';
1444
+		}
1445
+
1446
+		// text body
1447
+		if ($this->_build_params['text_encoding'] == '7bit'
1448
+			&& !preg_match('/ascii/i', $this->_build_params['text_charset'])
1449
+			&& preg_match('/[^\x00-\x7F]/', $this->_txtbody)
1450
+		) {
1451
+			$this->_build_params['text_encoding'] = 'quoted-printable';
1452
+		}
1453
+		// html body
1454
+		if ($this->_build_params['html_encoding'] == '7bit'
1455
+			&& !preg_match('/ascii/i', $this->_build_params['html_charset'])
1456
+			&& preg_match('/[^\x00-\x7F]/', $this->_htmlbody)
1457
+		) {
1458
+			$this->_build_params['html_encoding'] = 'quoted-printable';
1459
+		}
1460
+	}
1461
+
1462
+	/**
1463
+	 * PEAR::isError implementation
1464
+	 *
1465
+	 * @param mixed $data Object
1466
+	 *
1467
+	 * @return bool True if object is an instance of PEAR_Error
1468
+	 * @access private
1469
+	 */
1470
+	function _isError($data)
1471
+	{
1472
+		// PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1473
+		if (is_object($data) && is_a($data, 'PEAR_Error')) {
1474
+			return true;
1475
+		}
1476
+
1477
+		return false;
1478
+	}
1479
+
1480
+	/**
1481
+	 * PEAR::raiseError implementation
1482
+	 *
1483
+	 * @param $message A text error message
1484
+	 *
1485
+	 * @return PEAR_Error Instance of PEAR_Error
1486
+	 * @access private
1487
+	 */
1488
+	function _raiseError($message)
1489
+	{
1490
+		// PEAR::raiseError() is not PHP 5.4 compatible
1491
+		return new PEAR_Error($message);
1492
+	}
1493 1493
 
1494 1494
 } // End of class
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/lazy/Carbon/TranslatorWeakType.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -12,21 +12,21 @@
 block discarded – undo
12 12
 namespace Carbon;
13 13
 
14 14
 if (!class_exists(LazyTranslator::class, false)) {
15
-    class LazyTranslator extends AbstractTranslator
16
-    {
17
-        /**
18
-         * Returns the translation.
19
-         *
20
-         * @param string|null $id
21
-         * @param array       $parameters
22
-         * @param string|null $domain
23
-         * @param string|null $locale
24
-         *
25
-         * @return string
26
-         */
27
-        public function trans($id, array $parameters = [], $domain = null, $locale = null)
28
-        {
29
-            return $this->translate($id, $parameters, $domain, $locale);
30
-        }
31
-    }
15
+	class LazyTranslator extends AbstractTranslator
16
+	{
17
+		/**
18
+		 * Returns the translation.
19
+		 *
20
+		 * @param string|null $id
21
+		 * @param array       $parameters
22
+		 * @param string|null $domain
23
+		 * @param string|null $locale
24
+		 *
25
+		 * @return string
26
+		 */
27
+		public function trans($id, array $parameters = [], $domain = null, $locale = null)
28
+		{
29
+			return $this->translate($id, $parameters, $domain, $locale);
30
+		}
31
+	}
32 32
 }
Please login to merge, or discard this patch.
php-imap/vendor/nesbot/carbon/lazy/Carbon/PHPStan/AbstractMacroBuiltin.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -16,16 +16,16 @@
 block discarded – undo
16 16
 use ReflectionMethod;
17 17
 
18 18
 if (!class_exists(AbstractReflectionMacro::class, false)) {
19
-    abstract class AbstractReflectionMacro extends AbstractMacro
20
-    {
21
-        /**
22
-         * {@inheritdoc}
23
-         */
24
-        public function getReflection(): ?ReflectionMethod
25
-        {
26
-            return $this->reflectionFunction instanceof ReflectionMethod
27
-                ? $this->reflectionFunction
28
-                : null;
29
-        }
30
-    }
19
+	abstract class AbstractReflectionMacro extends AbstractMacro
20
+	{
21
+		/**
22
+		 * {@inheritdoc}
23
+		 */
24
+		public function getReflection(): ?ReflectionMethod
25
+		{
26
+			return $this->reflectionFunction instanceof ReflectionMethod
27
+				? $this->reflectionFunction
28
+				: null;
29
+		}
30
+	}
31 31
 }
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/lazy/Carbon/PHPStan/MacroWeakType.php 1 patch
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -14,36 +14,36 @@
 block discarded – undo
14 14
 namespace Carbon\PHPStan;
15 15
 
16 16
 if (!class_exists(LazyMacro::class, false)) {
17
-    abstract class LazyMacro extends AbstractReflectionMacro
18
-    {
19
-        /**
20
-         * {@inheritdoc}
21
-         *
22
-         * @return string|false
23
-         */
24
-        public function getFileName()
25
-        {
26
-            return $this->reflectionFunction->getFileName();
27
-        }
17
+	abstract class LazyMacro extends AbstractReflectionMacro
18
+	{
19
+		/**
20
+		 * {@inheritdoc}
21
+		 *
22
+		 * @return string|false
23
+		 */
24
+		public function getFileName()
25
+		{
26
+			return $this->reflectionFunction->getFileName();
27
+		}
28 28
 
29
-        /**
30
-         * {@inheritdoc}
31
-         *
32
-         * @return int|false
33
-         */
34
-        public function getStartLine()
35
-        {
36
-            return $this->reflectionFunction->getStartLine();
37
-        }
29
+		/**
30
+		 * {@inheritdoc}
31
+		 *
32
+		 * @return int|false
33
+		 */
34
+		public function getStartLine()
35
+		{
36
+			return $this->reflectionFunction->getStartLine();
37
+		}
38 38
 
39
-        /**
40
-         * {@inheritdoc}
41
-         *
42
-         * @return int|false
43
-         */
44
-        public function getEndLine()
45
-        {
46
-            return $this->reflectionFunction->getEndLine();
47
-        }
48
-    }
39
+		/**
40
+		 * {@inheritdoc}
41
+		 *
42
+		 * @return int|false
43
+		 */
44
+		public function getEndLine()
45
+		{
46
+			return $this->reflectionFunction->getEndLine();
47
+		}
48
+	}
49 49
 }
Please login to merge, or discard this patch.
php-imap/vendor/nesbot/carbon/lazy/Carbon/PHPStan/MacroStrongType.php 1 patch
Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -14,30 +14,30 @@
 block discarded – undo
14 14
 namespace Carbon\PHPStan;
15 15
 
16 16
 if (!class_exists(LazyMacro::class, false)) {
17
-    abstract class LazyMacro extends AbstractReflectionMacro
18
-    {
19
-        /**
20
-         * {@inheritdoc}
21
-         */
22
-        public function getFileName(): ?string
23
-        {
24
-            return $this->reflectionFunction->getFileName();
25
-        }
17
+	abstract class LazyMacro extends AbstractReflectionMacro
18
+	{
19
+		/**
20
+		 * {@inheritdoc}
21
+		 */
22
+		public function getFileName(): ?string
23
+		{
24
+			return $this->reflectionFunction->getFileName();
25
+		}
26 26
 
27
-        /**
28
-         * {@inheritdoc}
29
-         */
30
-        public function getStartLine(): ?int
31
-        {
32
-            return $this->reflectionFunction->getStartLine();
33
-        }
27
+		/**
28
+		 * {@inheritdoc}
29
+		 */
30
+		public function getStartLine(): ?int
31
+		{
32
+			return $this->reflectionFunction->getStartLine();
33
+		}
34 34
 
35
-        /**
36
-         * {@inheritdoc}
37
-         */
38
-        public function getEndLine(): ?int
39
-        {
40
-            return $this->reflectionFunction->getEndLine();
41
-        }
42
-    }
35
+		/**
36
+		 * {@inheritdoc}
37
+		 */
38
+		public function getEndLine(): ?int
39
+		{
40
+			return $this->reflectionFunction->getEndLine();
41
+		}
42
+	}
43 43
 }
Please login to merge, or discard this patch.
php-imap/vendor/nesbot/carbon/lazy/Carbon/PHPStan/AbstractMacroStatic.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -17,25 +17,25 @@
 block discarded – undo
17 17
 use ReflectionMethod;
18 18
 
19 19
 if (!class_exists(AbstractReflectionMacro::class, false)) {
20
-    abstract class AbstractReflectionMacro extends AbstractMacro
21
-    {
22
-        /**
23
-         * {@inheritdoc}
24
-         */
25
-        public function getReflection(): ?Reflection\Adapter\ReflectionMethod
26
-        {
27
-            if ($this->reflectionFunction instanceof Reflection\Adapter\ReflectionMethod) {
28
-                return $this->reflectionFunction;
29
-            }
20
+	abstract class AbstractReflectionMacro extends AbstractMacro
21
+	{
22
+		/**
23
+		 * {@inheritdoc}
24
+		 */
25
+		public function getReflection(): ?Reflection\Adapter\ReflectionMethod
26
+		{
27
+			if ($this->reflectionFunction instanceof Reflection\Adapter\ReflectionMethod) {
28
+				return $this->reflectionFunction;
29
+			}
30 30
 
31
-            return $this->reflectionFunction instanceof ReflectionMethod
32
-                ? new Reflection\Adapter\ReflectionMethod(
33
-                    Reflection\ReflectionMethod::createFromName(
34
-                        $this->reflectionFunction->getDeclaringClass()->getName(),
35
-                        $this->reflectionFunction->getName()
36
-                    )
37
-                )
38
-                : null;
39
-        }
40
-    }
31
+			return $this->reflectionFunction instanceof ReflectionMethod
32
+				? new Reflection\Adapter\ReflectionMethod(
33
+					Reflection\ReflectionMethod::createFromName(
34
+						$this->reflectionFunction->getDeclaringClass()->getName(),
35
+						$this->reflectionFunction->getName()
36
+					)
37
+				)
38
+				: null;
39
+		}
40
+	}
41 41
 }
Please login to merge, or discard this patch.
webklex/php-imap/vendor/nesbot/carbon/lazy/Carbon/TranslatorStrongType.php 1 patch
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -14,39 +14,39 @@
 block discarded – undo
14 14
 use Symfony\Component\Translation\MessageCatalogueInterface;
15 15
 
16 16
 if (!class_exists(LazyTranslator::class, false)) {
17
-    class LazyTranslator extends AbstractTranslator implements TranslatorStrongTypeInterface
18
-    {
19
-        public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
20
-        {
21
-            return $this->translate($id, $parameters, $domain, $locale);
22
-        }
23
-
24
-        public function getFromCatalogue(MessageCatalogueInterface $catalogue, string $id, string $domain = 'messages')
25
-        {
26
-            $messages = $this->getPrivateProperty($catalogue, 'messages');
27
-
28
-            if (isset($messages[$domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX][$id])) {
29
-                return $messages[$domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX][$id];
30
-            }
31
-
32
-            if (isset($messages[$domain][$id])) {
33
-                return $messages[$domain][$id];
34
-            }
35
-
36
-            $fallbackCatalogue = $this->getPrivateProperty($catalogue, 'fallbackCatalogue');
37
-
38
-            if ($fallbackCatalogue !== null) {
39
-                return $this->getFromCatalogue($fallbackCatalogue, $id, $domain);
40
-            }
41
-
42
-            return $id;
43
-        }
44
-
45
-        private function getPrivateProperty($instance, string $field)
46
-        {
47
-            return (function (string $field) {
48
-                return $this->$field;
49
-            })->call($instance, $field);
50
-        }
51
-    }
17
+	class LazyTranslator extends AbstractTranslator implements TranslatorStrongTypeInterface
18
+	{
19
+		public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
20
+		{
21
+			return $this->translate($id, $parameters, $domain, $locale);
22
+		}
23
+
24
+		public function getFromCatalogue(MessageCatalogueInterface $catalogue, string $id, string $domain = 'messages')
25
+		{
26
+			$messages = $this->getPrivateProperty($catalogue, 'messages');
27
+
28
+			if (isset($messages[$domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX][$id])) {
29
+				return $messages[$domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX][$id];
30
+			}
31
+
32
+			if (isset($messages[$domain][$id])) {
33
+				return $messages[$domain][$id];
34
+			}
35
+
36
+			$fallbackCatalogue = $this->getPrivateProperty($catalogue, 'fallbackCatalogue');
37
+
38
+			if ($fallbackCatalogue !== null) {
39
+				return $this->getFromCatalogue($fallbackCatalogue, $id, $domain);
40
+			}
41
+
42
+			return $id;
43
+		}
44
+
45
+		private function getPrivateProperty($instance, string $field)
46
+		{
47
+			return (function (string $field) {
48
+				return $this->$field;
49
+			})->call($instance, $field);
50
+		}
51
+	}
52 52
 }
Please login to merge, or discard this patch.
php-imap/vendor/nesbot/carbon/src/Carbon/CarbonConverterInterface.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -15,5 +15,5 @@
 block discarded – undo
15 15
 
16 16
 interface CarbonConverterInterface
17 17
 {
18
-    public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface;
18
+	public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface;
19 19
 }
Please login to merge, or discard this patch.