Changeset 19941 for branches/version-2_5-dev/data/module/Mail/mimePart.php
- Timestamp:
- 2011/01/17 14:34:18 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/version-2_5-dev/data/module/Mail/mimePart.php
r16300 r19941 1 1 <?php 2 // +-----------------------------------------------------------------------+3 // | Copyright (c) 2002-2003 Richard Heyes |4 // | All rights reserved. |5 // | |6 // | Redistribution and use in source and binary forms, with or without |7 // | modification, are permitted provided that the following conditions |8 // | are met: |9 // | |10 // | o Redistributions of source code must retain the above copyright |11 // | notice, this list of conditions and the following disclaimer. |12 // | o Redistributions in binary form must reproduce the above copyright |13 // | notice, this list of conditions and the following disclaimer in the |14 // | documentation and/or other materials provided with the distribution.|15 // | o The names of the authors may not be used to endorse or promote |16 // | products derived from this software without specific prior written |17 // | permission. |18 // | |19 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |20 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |21 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |22 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |23 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |24 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |25 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |26 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |27 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |28 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |29 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |30 // | |31 // +-----------------------------------------------------------------------+32 // | Author: Richard Heyes <richard@phpguru.org> |33 // +-----------------------------------------------------------------------+34 35 2 /** 36 * 37 * Raw mime encoding class 38 * 39 * What is it? 40 * This class enables you to manipulate and build 41 * a mime email from the ground up. 42 * 43 * Why use this instead of mime.php? 44 * mime.php is a userfriendly api to this class for 45 * people who aren't interested in the internals of 46 * mime mail. This class however allows full control 47 * over the email. 48 * 49 * Eg. 50 * 51 * // Since multipart/mixed has no real body, (the body is 52 * // the subpart), we set the body argument to blank. 53 * 54 * $params['content_type'] = 'multipart/mixed'; 55 * $email = new Mail_mimePart('', $params); 56 * 57 * // Here we add a text part to the multipart we have 58 * // already. Assume $body contains plain text. 59 * 60 * $params['content_type'] = 'text/plain'; 61 * $params['encoding'] = '7bit'; 62 * $text = $email->addSubPart($body, $params); 63 * 64 * // Now add an attachment. Assume $attach is 65 * the contents of the attachment 66 * 67 * $params['content_type'] = 'application/zip'; 68 * $params['encoding'] = 'base64'; 69 * $params['disposition'] = 'attachment'; 70 * $params['dfilename'] = 'example.zip'; 71 * $attach =& $email->addSubPart($body, $params); 72 * 73 * // Now build the email. Note that the encode 74 * // function returns an associative array containing two 75 * // elements, body and headers. You will need to add extra 76 * // headers, (eg. Mime-Version) before sending. 77 * 78 * $email = $message->encode(); 79 * $email['headers'][] = 'Mime-Version: 1.0'; 80 * 81 * 82 * Further examples are available at http://www.phpguru.org 83 * 84 * TODO: 85 * - Set encode() to return the $obj->encoded if encode() 86 * has already been run. Unless a flag is passed to specifically 87 * re-build the message. 88 * 89 * @author Richard Heyes <richard@phpguru.org> 90 * @version $Revision: 1.13 $ 91 * @package Mail 92 */ 93 94 class Mail_mimePart { 95 96 /** 3 * The Mail_mimePart class is used to create MIME E-mail messages 4 * 5 * This class enables you to manipulate and build a mime email 6 * from the ground up. The Mail_Mime class is a userfriendly api 7 * to this class for people who aren't interested in the internals 8 * of mime mail. 9 * This class however allows full control over the email. 10 * 11 * Compatible with PHP versions 4 and 5 12 * 13 * LICENSE: This LICENSE is in the BSD license style. 14 * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org> 15 * Copyright (c) 2003-2006, PEAR <pear-group@php.net> 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or 19 * without modification, are permitted provided that the following 20 * conditions are met: 21 * 22 * - Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * - Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * - Neither the name of the authors, nor the names of its contributors 28 * may be used to endorse or promote products derived from this 29 * software without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 35 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 39 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 41 * THE POSSIBILITY OF SUCH DAMAGE. 42 * 43 * @category Mail 44 * @package Mail_Mime 45 * @author Richard Heyes <richard@phpguru.org> 46 * @author Cipriano Groenendal <cipri@php.net> 47 * @author Sean Coates <sean@php.net> 48 * @author Aleksander Machniak <alec@php.net> 49 * @copyright 2003-2006 PEAR <pear-group@php.net> 50 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 51 * @version CVS: $Id$ 52 * @link http://pear.php.net/package/Mail_mime 53 */ 54 55 56 /** 57 * The Mail_mimePart class is used to create MIME E-mail messages 58 * 59 * This class enables you to manipulate and build a mime email 60 * from the ground up. The Mail_Mime class is a userfriendly api 61 * to this class for people who aren't interested in the internals 62 * of mime mail. 63 * This class however allows full control over the email. 64 * 65 * @category Mail 66 * @package Mail_Mime 67 * @author Richard Heyes <richard@phpguru.org> 68 * @author Cipriano Groenendal <cipri@php.net> 69 * @author Sean Coates <sean@php.net> 70 * @author Aleksander Machniak <alec@php.net> 71 * @copyright 2003-2006 PEAR <pear-group@php.net> 72 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 73 * @version Release: @package_version@ 74 * @link http://pear.php.net/package/Mail_mime 75 */ 76 class Mail_mimePart 77 { 78 /** 97 79 * The encoding type of this part 80 * 98 81 * @var string 82 * @access private 99 83 */ 100 84 var $_encoding; 101 85 102 /**86 /** 103 87 * An array of subparts 88 * 104 89 * @var array 90 * @access private 105 91 */ 106 92 var $_subparts; 107 93 108 /**94 /** 109 95 * The output of this part after being built 96 * 110 97 * @var string 98 * @access private 111 99 */ 112 100 var $_encoded; 113 101 114 /**102 /** 115 103 * Headers for this part 104 * 116 105 * @var array 106 * @access private 117 107 */ 118 108 var $_headers; 119 109 120 /**110 /** 121 111 * The body of this part (not encoded) 112 * 122 113 * @var string 114 * @access private 123 115 */ 124 116 var $_body; 125 117 126 118 /** 127 * Constructor. 128 * 129 * Sets up the object. 130 * 131 * @param $body - The body of the mime part if any. 132 * @param $params - An associative array of parameters: 133 * content_type - The content type for this part eg multipart/mixed 134 * encoding - The encoding to use, 7bit, 8bit, base64, or quoted-printable 135 * cid - Content ID to apply 136 * disposition - Content disposition, inline or attachment 137 * dfilename - Optional filename parameter for content disposition 138 * description - Content description 139 * charset - Character set to use 140 * @access public 141 */ 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 * Constructor. 136 * 137 * Sets up the object. 138 * 139 * @param string $body The body of the mime part if any. 140 * @param array $params An associative array of optional parameters: 141 * content_type - The content type for this part eg multipart/mixed 142 * encoding - The encoding to use, 7bit, 8bit, 143 * base64, or quoted-printable 144 * charset - Content character set 145 * cid - Content ID to apply 146 * disposition - Content disposition, inline or attachment 147 * dfilename - Filename parameter for content disposition 148 * description - Content description 149 * name_encoding - Encoding of the attachment name (Content-Type) 150 * By default filenames are encoded using RFC2231 151 * Here you can set RFC2047 encoding (quoted-printable 152 * or base64) instead 153 * filename_encoding - Encoding of the attachment filename (Content-Disposition) 154 * See 'name_encoding' 155 * headers_charset - Charset of the headers e.g. filename, description. 156 * If not set, 'charset' will be used 157 * eol - End of line sequence. Default: "\r\n" 158 * body_file - Location of file with part's body (instead of $body) 159 * 160 * @access public 161 */ 142 162 function Mail_mimePart($body = '', $params = array()) 143 163 { 144 if (!defined('MAIL_MIMEPART_CRLF')) { 145 define('MAIL_MIMEPART_CRLF', defined('MAIL_MIME_CRLF') ? MAIL_MIME_CRLF : "\r\n", TRUE); 164 if (!empty($params['eol'])) { 165 $this->_eol = $params['eol']; 166 } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat. 167 $this->_eol = MAIL_MIMEPART_CRLF; 146 168 } 147 169 148 170 foreach ($params as $key => $value) { 149 171 switch ($key) { 150 case 'content_type': 151 $headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : ''); 152 break; 153 154 case 'encoding': 155 $this->_encoding = $value; 156 $headers['Content-Transfer-Encoding'] = $value; 157 break; 158 159 case 'cid': 160 $headers['Content-ID'] = '<' . $value . '>'; 161 break; 162 163 case 'disposition': 164 $headers['Content-Disposition'] = $value . (isset($dfilename) ? '; filename="' . $dfilename . '"' : ''); 165 break; 166 167 case 'dfilename': 168 if (isset($headers['Content-Disposition'])) { 169 $headers['Content-Disposition'] .= '; filename="' . $value . '"'; 170 } else { 171 $dfilename = $value; 172 } 173 break; 174 175 case 'description': 176 $headers['Content-Description'] = $value; 177 break; 178 179 case 'charset': 180 if (isset($headers['Content-Type'])) { 181 $headers['Content-Type'] .= '; charset="' . $value . '"'; 182 } else { 183 $charset = $value; 184 } 185 break; 172 case 'encoding': 173 $this->_encoding = $value; 174 $headers['Content-Transfer-Encoding'] = $value; 175 break; 176 177 case 'cid': 178 $headers['Content-ID'] = '<' . $value . '>'; 179 break; 180 181 case 'location': 182 $headers['Content-Location'] = $value; 183 break; 184 185 case 'body_file': 186 $this->_body_file = $value; 187 break; 186 188 } 187 189 } 188 190 189 191 // Default content-type 190 if (!isset($headers['Content-Type'])) { 191 $headers['Content-Type'] = 'text/plain'; 192 } 193 194 //Default encoding 192 if (empty($params['content_type'])) { 193 $params['content_type'] = 'text/plain'; 194 } 195 196 // Content-Type 197 $headers['Content-Type'] = $params['content_type']; 198 if (!empty($params['charset'])) { 199 $charset = "charset={$params['charset']}"; 200 // place charset parameter in the same line, if possible 201 if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) { 202 $headers['Content-Type'] .= '; '; 203 } else { 204 $headers['Content-Type'] .= ';' . $this->_eol . ' '; 205 } 206 $headers['Content-Type'] .= $charset; 207 208 // Default headers charset 209 if (!isset($params['headers_charset'])) { 210 $params['headers_charset'] = $params['charset']; 211 } 212 } 213 if (!empty($params['filename'])) { 214 $headers['Content-Type'] .= ';' . $this->_eol; 215 $headers['Content-Type'] .= $this->_buildHeaderParam( 216 'name', $params['filename'], 217 !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII', 218 !empty($params['language']) ? $params['language'] : null, 219 !empty($params['name_encoding']) ? $params['name_encoding'] : null 220 ); 221 } 222 223 // Content-Disposition 224 if (!empty($params['disposition'])) { 225 $headers['Content-Disposition'] = $params['disposition']; 226 if (!empty($params['filename'])) { 227 $headers['Content-Disposition'] .= ';' . $this->_eol; 228 $headers['Content-Disposition'] .= $this->_buildHeaderParam( 229 'filename', $params['filename'], 230 !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII', 231 !empty($params['language']) ? $params['language'] : null, 232 !empty($params['filename_encoding']) ? $params['filename_encoding'] : null 233 ); 234 } 235 } 236 237 if (!empty($params['description'])) { 238 $headers['Content-Description'] = $this->encodeHeader( 239 'Content-Description', $params['description'], 240 !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII', 241 !empty($params['name_encoding']) ? $params['name_encoding'] : 'quoted-printable', 242 $this->_eol 243 ); 244 } 245 246 // Default encoding 195 247 if (!isset($this->_encoding)) { 196 248 $this->_encoding = '7bit'; … … 204 256 205 257 /** 206 * encode()207 *208 258 * Encodes and returns the email. Also stores 209 259 * it in the encoded member variable 210 260 * 261 * @param string $boundary Pre-defined boundary string 262 * 211 263 * @return An associative array containing two elements, 212 264 * body and headers. The headers element is itself 213 * an indexed array. 265 * an indexed array. On error returns PEAR error object. 214 266 * @access public 215 267 */ 216 function encode( )268 function encode($boundary=null) 217 269 { 218 270 $encoded =& $this->_encoded; 219 271 220 if (!empty($this->_subparts)) { 221 srand((double)microtime()*1000000); 222 $boundary = '=_' . md5(rand() . microtime()); 223 $this->_headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF . "\t" . 'boundary="' . $boundary . '"'; 224 225 // Add body parts to $subparts 272 if (count($this->_subparts)) { 273 $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime()); 274 $eol = $this->_eol; 275 276 $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; 277 278 $encoded['body'] = ''; 279 226 280 for ($i = 0; $i < count($this->_subparts); $i++) { 227 $ headers = array();281 $encoded['body'] .= '--' . $boundary . $eol; 228 282 $tmp = $this->_subparts[$i]->encode(); 283 if (PEAR::isError($tmp)) { 284 return $tmp; 285 } 229 286 foreach ($tmp['headers'] as $key => $value) { 230 $headers[] = $key . ': ' . $value; 231 } 232 $subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body']; 233 } 234 235 $encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF . 236 implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) . 237 '--' . $boundary.'--' . MAIL_MIMEPART_CRLF; 238 287 $encoded['body'] .= $key . ': ' . $value . $eol; 288 } 289 $encoded['body'] .= $eol . $tmp['body'] . $eol; 290 } 291 292 $encoded['body'] .= '--' . $boundary . '--' . $eol; 293 294 } else if ($this->_body) { 295 $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding); 296 } else if ($this->_body_file) { 297 // Temporarily reset magic_quotes_runtime for file reads and writes 298 if ($magic_quote_setting = get_magic_quotes_runtime()) { 299 @ini_set('magic_quotes_runtime', 0); 300 } 301 $body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding); 302 if ($magic_quote_setting) { 303 @ini_set('magic_quotes_runtime', $magic_quote_setting); 304 } 305 306 if (PEAR::isError($body)) { 307 return $body; 308 } 309 $encoded['body'] = $body; 239 310 } else { 240 $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF;311 $encoded['body'] = ''; 241 312 } 242 313 … … 248 319 249 320 /** 250 * &addSubPart() 251 * 321 * Encodes and saves the email into file. File must exist. 322 * Data will be appended to the file. 323 * 324 * @param string $filename Output file location 325 * @param string $boundary Pre-defined boundary string 326 * @param boolean $skip_head True if you don't want to save headers 327 * 328 * @return array An associative array containing message headers 329 * or PEAR error object 330 * @access public 331 * @since 1.6.0 332 */ 333 function encodeToFile($filename, $boundary=null, $skip_head=false) 334 { 335 if (file_exists($filename) && !is_writable($filename)) { 336 $err = PEAR::raiseError('File is not writeable: ' . $filename); 337 return $err; 338 } 339 340 if (!($fh = fopen($filename, 'ab'))) { 341 $err = PEAR::raiseError('Unable to open file: ' . $filename); 342 return $err; 343 } 344 345 // Temporarily reset magic_quotes_runtime for file reads and writes 346 if ($magic_quote_setting = get_magic_quotes_runtime()) { 347 @ini_set('magic_quotes_runtime', 0); 348 } 349 350 $res = $this->_encodePartToFile($fh, $boundary, $skip_head); 351 352 fclose($fh); 353 354 if ($magic_quote_setting) { 355 @ini_set('magic_quotes_runtime', $magic_quote_setting); 356 } 357 358 return PEAR::isError($res) ? $res : $this->_headers; 359 } 360 361 /** 362 * Encodes given email part into file 363 * 364 * @param string $fh Output file handle 365 * @param string $boundary Pre-defined boundary string 366 * @param boolean $skip_head True if you don't want to save headers 367 * 368 * @return array True on sucess or PEAR error object 369 * @access private 370 */ 371 function _encodePartToFile($fh, $boundary=null, $skip_head=false) 372 { 373 $eol = $this->_eol; 374 375 if (count($this->_subparts)) { 376 $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime()); 377 $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; 378 } 379 380 if (!$skip_head) { 381 foreach ($this->_headers as $key => $value) { 382 fwrite($fh, $key . ': ' . $value . $eol); 383 } 384 $f_eol = $eol; 385 } else { 386 $f_eol = ''; 387 } 388 389 if (count($this->_subparts)) { 390 for ($i = 0; $i < count($this->_subparts); $i++) { 391 fwrite($fh, $f_eol . '--' . $boundary . $eol); 392 $res = $this->_subparts[$i]->_encodePartToFile($fh); 393 if (PEAR::isError($res)) { 394 return $res; 395 } 396 $f_eol = $eol; 397 } 398 399 fwrite($fh, $eol . '--' . $boundary . '--' . $eol); 400 401 } else if ($this->_body) { 402 fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding)); 403 } else if ($this->_body_file) { 404 fwrite($fh, $f_eol); 405 $res = $this->_getEncodedDataFromFile( 406 $this->_body_file, $this->_encoding, $fh 407 ); 408 if (PEAR::isError($res)) { 409 return $res; 410 } 411 } 412 413 return true; 414 } 415 416 /** 252 417 * Adds a subpart to current mime part and returns 253 418 * a reference to it 254 419 * 255 * @param $body The body of the subpart, if any. 256 * @param $params The parameters for the subpart, same 257 * as the $params argument for constructor. 258 * @return A reference to the part you just added. It is 259 * crucial if using multipart/* in your subparts that 260 * you use =& in your script when calling this function, 261 * otherwise you will not be able to add further subparts. 420 * @param string $body The body of the subpart, if any. 421 * @param array $params The parameters for the subpart, same 422 * as the $params argument for constructor. 423 * 424 * @return Mail_mimePart A reference to the part you just added. It is 425 * crucial if using multipart/* in your subparts that 426 * you use =& in your script when calling this function, 427 * otherwise you will not be able to add further subparts. 262 428 * @access public 263 429 */ 264 function &addSub Part($body, $params)430 function &addSubpart($body, $params) 265 431 { 266 432 $this->_subparts[] = new Mail_mimePart($body, $params); … … 269 435 270 436 /** 271 * _getEncodedData()272 *273 437 * Returns encoded data based upon encoding passed to it 274 438 * 275 * @param $data The data to encode. 276 * @param $encoding The encoding type to use, 7bit, base64, 277 * or quoted-printable. 439 * @param string $data The data to encode. 440 * @param string $encoding The encoding type to use, 7bit, base64, 441 * or quoted-printable. 442 * 443 * @return string 278 444 * @access private 279 445 */ … … 281 447 { 282 448 switch ($encoding) { 283 case '8bit': 284 case '7bit': 285 return $data; 286 break; 287 288 case 'quoted-printable': 289 return $this->_quotedPrintableEncode($data); 290 break; 291 292 case 'base64': 293 return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF)); 294 break; 295 296 default: 297 return $data; 298 } 299 } 300 301 /** 302 * quoteadPrintableEncode() 303 * 449 case 'quoted-printable': 450 return $this->_quotedPrintableEncode($data); 451 break; 452 453 case 'base64': 454 return rtrim(chunk_split(base64_encode($data), 76, $this->_eol)); 455 break; 456 457 case '8bit': 458 case '7bit': 459 default: 460 return $data; 461 } 462 } 463 464 /** 465 * Returns encoded data based upon encoding passed to it 466 * 467 * @param string $filename Data file location 468 * @param string $encoding The encoding type to use, 7bit, base64, 469 * or quoted-printable. 470 * @param resource $fh Output file handle. If set, data will be 471 * stored into it instead of returning it 472 * 473 * @return string Encoded data or PEAR error object 474 * @access private 475 */ 476 function _getEncodedDataFromFile($filename, $encoding, $fh=null) 477 { 478 if (!is_readable($filename)) { 479 $err = PEAR::raiseError('Unable to read file: ' . $filename); 480 return $err; 481 } 482 483 if (!($fd = fopen($filename, 'rb'))) { 484 $err = PEAR::raiseError('Could not open file: ' . $filename); 485 return $err; 486 } 487 488 $data = ''; 489 490 switch ($encoding) { 491 case 'quoted-printable': 492 while (!feof($fd)) { 493 $buffer = $this->_quotedPrintableEncode(fgets($fd)); 494 if ($fh) { 495 fwrite($fh, $buffer); 496 } else { 497 $data .= $buffer; 498 } 499 } 500 break; 501 502 case 'base64': 503 while (!feof($fd)) { 504 // Should read in a multiple of 57 bytes so that 505 // the output is 76 bytes per line. Don't use big chunks 506 // because base64 encoding is memory expensive 507 $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB 508 $buffer = base64_encode($buffer); 509 $buffer = chunk_split($buffer, 76, $this->_eol); 510 if (feof($fd)) { 511 $buffer = rtrim($buffer); 512 } 513 514 if ($fh) { 515 fwrite($fh, $buffer); 516 } else { 517 $data .= $buffer; 518 } 519 } 520 break; 521 522 case '8bit': 523 case '7bit': 524 default: 525 while (!feof($fd)) { 526 $buffer = fread($fd, 1048576); // 1 MB 527 if ($fh) { 528 fwrite($fh, $buffer); 529 } else { 530 $data .= $buffer; 531 } 532 } 533 } 534 535 fclose($fd); 536 537 if (!$fh) { 538 return $data; 539 } 540 } 541 542 /** 304 543 * Encodes data to quoted-printable standard. 305 544 * 306 * @param $input The data to encode 307 * @param $line_max Optional max line length. Should 308 * not be more than 76 chars 545 * @param string $input The data to encode 546 * @param int $line_max Optional max line length. Should 547 * not be more than 76 chars 548 * 549 * @return string Encoded data 309 550 * 310 551 * @access private … … 312 553 function _quotedPrintableEncode($input , $line_max = 76) 313 554 { 555 $eol = $this->_eol; 556 /* 557 // imap_8bit() is extremely fast, but doesn't handle properly some characters 558 if (function_exists('imap_8bit') && $line_max == 76) { 559 $input = preg_replace('/\r?\n/', "\r\n", $input); 560 $input = imap_8bit($input); 561 if ($eol != "\r\n") { 562 $input = str_replace("\r\n", $eol, $input); 563 } 564 return $input; 565 } 566 */ 314 567 $lines = preg_split("/\r?\n/", $input); 315 $eol = MAIL_MIMEPART_CRLF;316 568 $escape = '='; 317 569 $output = ''; 318 570 319 while(list(, $line) = each($lines)){ 320 321 $linlen = strlen($line); 571 while (list($idx, $line) = each($lines)) { 322 572 $newline = ''; 323 324 for ($i = 0; $i < $linlen; $i++) { 325 $char = substr($line, $i, 1); 573 $i = 0; 574 575 while (isset($line[$i])) { 576 $char = $line[$i]; 326 577 $dec = ord($char); 327 328 if (($dec == 32) AND ($i == ($linlen - 1))){ // convert space at eol only 578 $i++; 579 580 if (($dec == 32) && (!isset($line[$i]))) { 581 // convert space at eol only 329 582 $char = '=20'; 330 331 } elseif(($dec == 9) AND ($i == ($linlen - 1))) { // convert tab at eol only 332 $char = '=09'; 333 } elseif($dec == 9) { 334 ; // Do nothing if a tab. 335 } elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) { 336 $char = $escape . strtoupper(sprintf('%02s', dechex($dec))); 337 } 338 339 if ((strlen($newline) + strlen($char)) >= $line_max) { // MAIL_MIMEPART_CRLF is not counted 340 $output .= $newline . $escape . $eol; // soft line break; " =\r\n" is okay 583 } elseif ($dec == 9 && isset($line[$i])) { 584 ; // Do nothing if a TAB is not on eol 585 } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) { 586 $char = $escape . sprintf('%02X', $dec); 587 } elseif (($dec == 46) && (($newline == '') 588 || ((strlen($newline) + strlen("=2E")) >= $line_max)) 589 ) { 590 // Bug #9722: convert full-stop at bol, 591 // some Windows servers need this, won't break anything (cipri) 592 // Bug #11731: full-stop at bol also needs to be encoded 593 // if this line would push us over the line_max limit. 594 $char = '=2E'; 595 } 596 597 // Note, when changing this line, also change the ($dec == 46) 598 // check line, as it mimics this line due to Bug #11731 599 // EOL is not counted 600 if ((strlen($newline) + strlen($char)) >= $line_max) { 601 // soft line break; " =\r\n" is okay 602 $output .= $newline . $escape . $eol; 341 603 $newline = ''; 342 604 } … … 344 606 } // end of for 345 607 $output .= $newline . $eol; 346 } 347 $output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf 608 unset($lines[$idx]); 609 } 610 // Don't want last crlf 611 $output = substr($output, 0, -1 * strlen($eol)); 348 612 return $output; 349 613 } 614 615 /** 616 * Encodes the paramater of a header. 617 * 618 * @param string $name The name of the header-parameter 619 * @param string $value The value of the paramter 620 * @param string $charset The characterset of $value 621 * @param string $language The language used in $value 622 * @param string $encoding Parameter encoding. If not set, parameter value 623 * is encoded according to RFC2231 624 * @param int $maxLength The maximum length of a line. Defauls to 75 625 * 626 * @return string 627 * 628 * @access private 629 */ 630 function _buildHeaderParam($name, $value, $charset=null, $language=null, 631 $encoding=null, $maxLength=75 632 ) { 633 // RFC 2045: 634 // value needs encoding if contains non-ASCII chars or is longer than 78 chars 635 if (!preg_match('#[^\x20-\x7E]#', $value)) { 636 $token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D' 637 . ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#'; 638 if (!preg_match($token_regexp, $value)) { 639 // token 640 if (strlen($name) + strlen($value) + 3 <= $maxLength) { 641 return " {$name}={$value}"; 642 } 643 } else { 644 // quoted-string 645 $quoted = addcslashes($value, '\\"'); 646 if (strlen($name) + strlen($quoted) + 5 <= $maxLength) { 647 return " {$name}=\"{$quoted}\""; 648 } 649 } 650 } 651 652 // RFC2047: use quoted-printable/base64 encoding 653 if ($encoding == 'quoted-printable' || $encoding == 'base64') { 654 return $this->_buildRFC2047Param($name, $value, $charset, $encoding); 655 } 656 657 // RFC2231: 658 $encValue = preg_replace_callback( 659 '/([^\x21,\x23,\x24,\x26,\x2B,\x2D,\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])/', 660 array($this, '_encodeReplaceCallback'), $value 661 ); 662 $value = "$charset'$language'$encValue"; 663 664 $header = " {$name}*={$value}"; 665 if (strlen($header) <= $maxLength) { 666 return $header; 667 } 668 669 $preLength = strlen(" {$name}*0*="); 670 $maxLength = max(16, $maxLength - $preLength - 3); 671 $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|"; 672 673 $headers = array(); 674 $headCount = 0; 675 while ($value) { 676 $matches = array(); 677 $found = preg_match($maxLengthReg, $value, $matches); 678 if ($found) { 679 $headers[] = " {$name}*{$headCount}*={$matches[0]}"; 680 $value = substr($value, strlen($matches[0])); 681 } else { 682 $headers[] = " {$name}*{$headCount}*={$value}"; 683 $value = ''; 684 } 685 $headCount++; 686 } 687 688 $headers = implode(';' . $this->_eol, $headers); 689 return $headers; 690 } 691 692 /** 693 * Encodes header parameter as per RFC2047 if needed 694 * 695 * @param string $name The parameter name 696 * @param string $value The parameter value 697 * @param string $charset The parameter charset 698 * @param string $encoding Encoding type (quoted-printable or base64) 699 * @param int $maxLength Encoded parameter max length. Default: 76 700 * 701 * @return string Parameter line 702 * @access private 703 */ 704 function _buildRFC2047Param($name, $value, $charset, 705 $encoding='quoted-printable', $maxLength=76 706 ) { 707 // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in 708 // parameter of a MIME Content-Type or Content-Disposition field", 709 // but... it's supported by many clients/servers 710 $quoted = ''; 711 712 if ($encoding == 'base64') { 713 $value = base64_encode($value); 714 $prefix = '=?' . $charset . '?B?'; 715 $suffix = '?='; 716 717 // 2 x SPACE, 2 x '"', '=', ';' 718 $add_len = strlen($prefix . $suffix) + strlen($name) + 6; 719 $len = $add_len + strlen($value); 720 721 while ($len > $maxLength) { 722 // We can cut base64-encoded string every 4 characters 723 $real_len = floor(($maxLength - $add_len) / 4) * 4; 724 $_quote = substr($value, 0, $real_len); 725 $value = substr($value, $real_len); 726 727 $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' '; 728 $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';' 729 $len = strlen($value) + $add_len; 730 } 731 $quoted .= $prefix . $value . $suffix; 732 733 } else { 734 // quoted-printable 735 $value = $this->encodeQP($value); 736 $prefix = '=?' . $charset . '?Q?'; 737 $suffix = '?='; 738 739 // 2 x SPACE, 2 x '"', '=', ';' 740 $add_len = strlen($prefix . $suffix) + strlen($name) + 6; 741 $len = $add_len + strlen($value); 742 743 while ($len > $maxLength) { 744 $length = $maxLength - $add_len; 745 // don't break any encoded letters 746 if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) { 747 $_quote = $matches[1]; 748 } 749 750 $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' '; 751 $value = substr($value, strlen($_quote)); 752 $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';' 753 $len = strlen($value) + $add_len; 754 } 755 756 $quoted .= $prefix . $value . $suffix; 757 } 758 759 return " {$name}=\"{$quoted}\""; 760 } 761 762 /** 763 * Encodes a header as per RFC2047 764 * 765 * @param string $name The header name 766 * @param string $value The header data to encode 767 * @param string $charset Character set name 768 * @param string $encoding Encoding name (base64 or quoted-printable) 769 * @param string $eol End-of-line sequence. Default: "\r\n" 770 * 771 * @return string Encoded header data (without a name) 772 * @access public 773 * @since 1.6.1 774 */ 775 function encodeHeader($name, $value, $charset='ISO-8859-1', 776 $encoding='quoted-printable', $eol="\r\n" 777 ) { 778 // Structured headers 779 $comma_headers = array( 780 'from', 'to', 'cc', 'bcc', 'sender', 'reply-to', 781 'resent-from', 'resent-to', 'resent-cc', 'resent-bcc', 782 'resent-sender', 'resent-reply-to', 783 'return-receipt-to', 'disposition-notification-to', 784 ); 785 $other_headers = array( 786 'references', 'in-reply-to', 'message-id', 'resent-message-id', 787 ); 788 789 $name = strtolower($name); 790 791 if (in_array($name, $comma_headers)) { 792 $separator = ','; 793 } else if (in_array($name, $other_headers)) { 794 $separator = ' '; 795 } 796 797 if (!$charset) { 798 $charset = 'ISO-8859-1'; 799 } 800 801 // Structured header (make sure addr-spec inside is not encoded) 802 if (!empty($separator)) { 803 $parts = Mail_mimePart::_explodeQuotedString($separator, $value); 804 $value = ''; 805 806 foreach ($parts as $part) { 807 $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part); 808 $part = trim($part); 809 810 if (!$part) { 811 continue; 812 } 813 if ($value) { 814 $value .= $separator==',' ? $separator.' ' : ' '; 815 } else { 816 $value = $name . ': '; 817 } 818 819 // let's find phrase (name) and/or addr-spec 820 if (preg_match('/^<\S+@\S+>$/', $part)) { 821 $value .= $part; 822 } else if (preg_match('/^\S+@\S+$/', $part)) { 823 // address without brackets and without name 824 $value .= $part; 825 } else if (preg_match('/<*\S+@\S+>*$/', $part, $matches)) { 826 // address with name (handle name) 827 $address = $matches[0]; 828 $word = str_replace($address, '', $part); 829 $word = trim($word); 830 // check if phrase requires quoting 831 if ($word) { 832 // non-ASCII: require encoding 833 if (preg_match('#([\x80-\xFF]){1}#', $word)) { 834 if ($word[0] == '"' && $word[strlen($word)-1] == '"') { 835 // de-quote quoted-string, encoding changes 836 // string to atom 837 $search = array("\\\"", "\\\\"); 838 $replace = array("\"", "\\"); 839 $word = str_replace($search, $replace, $word); 840 $word = substr($word, 1, -1); 841 } 842 // find length of last line 843 if (($pos = strrpos($value, $eol)) !== false) { 844 $last_len = strlen($value) - $pos; 845 } else { 846 $last_len = strlen($value); 847 } 848 $word = Mail_mimePart::encodeHeaderValue( 849 $word, $charset, $encoding, $last_len, $eol 850 ); 851 } else if (($word[0] != '"' || $word[strlen($word)-1] != '"') 852 && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word) 853 ) { 854 // ASCII: quote string if needed 855 $word = '"'.addcslashes($word, '\\"').'"'; 856 } 857 } 858 $value .= $word.' '.$address; 859 } else { 860 // addr-spec not found, don't encode (?) 861 $value .= $part; 862 } 863 864 // RFC2822 recommends 78 characters limit, use 76 from RFC2047 865 $value = wordwrap($value, 76, $eol . ' '); 866 } 867 868 // remove header name prefix (there could be EOL too) 869 $value = preg_replace( 870 '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value 871 ); 872 873 } else { 874 // Unstructured header 875 // non-ASCII: require encoding 876 if (preg_match('#([\x80-\xFF]){1}#', $value)) { 877 if ($value[0] == '"' && $value[strlen($value)-1] == '"') { 878 // de-quote quoted-string, encoding changes 879 // string to atom 880 $search = array("\\\"", "\\\\"); 881 $replace = array("\"", "\\"); 882 $value = str_replace($search, $replace, $value); 883 $value = substr($value, 1, -1); 884 } 885 $value = Mail_mimePart::encodeHeaderValue( 886 $value, $charset, $encoding, strlen($name) + 2, $eol 887 ); 888 } else if (strlen($name.': '.$value) > 78) { 889 // ASCII: check if header line isn't too long and use folding 890 $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value); 891 $tmp = wordwrap($name.': '.$value, 78, $eol . ' '); 892 $value = preg_replace('/^'.$name.':\s*/', '', $tmp); 893 // hard limit 998 (RFC2822) 894 $value = wordwrap($value, 998, $eol . ' ', true); 895 } 896 } 897 898 return $value; 899 } 900 901 /** 902 * Explode quoted string 903 * 904 * @param string $delimiter Delimiter expression string for preg_match() 905 * @param string $string Input string 906 * 907 * @return array String tokens array 908 * @access private 909 */ 910 function _explodeQuotedString($delimiter, $string) 911 { 912 $result = array(); 913 $strlen = strlen($string); 914 915 for ($q=$p=$i=0; $i < $strlen; $i++) { 916 if ($string[$i] == "\"" 917 && (empty($string[$i-1]) || $string[$i-1] != "\\") 918 ) { 919 $q = $q ? false : true; 920 } else if (!$q && preg_match("/$delimiter/", $string[$i])) { 921 $result[] = substr($string, $p, $i - $p); 922 $p = $i + 1; 923 } 924 } 925 926 $result[] = substr($string, $p); 927 return $result; 928 } 929 930 /** 931 * Encodes a header value as per RFC2047 932 * 933 * @param string $value The header data to encode 934 * @param string $charset Character set name 935 * @param string $encoding Encoding name (base64 or quoted-printable) 936 * @param int $prefix_len Prefix length. Default: 0 937 * @param string $eol End-of-line sequence. Default: "\r\n" 938 * 939 * @return string Encoded header data 940 * @access public 941 * @since 1.6.1 942 */ 943 function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n") 944 { 945 // #17311: Use multibyte aware method (requires mbstring extension) 946 if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) { 947 return $result; 948 } 949 950 // Generate the header using the specified params and dynamicly 951 // determine the maximum length of such strings. 952 // 75 is the value specified in the RFC. 953 $encoding = $encoding == 'base64' ? 'B' : 'Q'; 954 $prefix = '=?' . $charset . '?' . $encoding .'?'; 955 $suffix = '?='; 956 $maxLength = 75 - strlen($prefix . $suffix); 957 $maxLength1stLine = $maxLength - $prefix_len; 958 959 if ($encoding == 'B') { 960 // Base64 encode the entire string 961 $value = base64_encode($value); 962 963 // We can cut base64 every 4 characters, so the real max 964 // we can get must be rounded down. 965 $maxLength = $maxLength - ($maxLength % 4); 966 $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4); 967 968 $cutpoint = $maxLength1stLine; 969 $output = ''; 970 971 while ($value) { 972 // Split translated string at every $maxLength 973 $part = substr($value, 0, $cutpoint); 974 $value = substr($value, $cutpoint); 975 $cutpoint = $maxLength; 976 // RFC 2047 specifies that any split header should 977 // be seperated by a CRLF SPACE. 978 if ($output) { 979 $output .= $eol . ' '; 980 } 981 $output .= $prefix . $part . $suffix; 982 } 983 $value = $output; 984 } else { 985 // quoted-printable encoding has been selected 986 $value = Mail_mimePart::encodeQP($value); 987 988 // This regexp will break QP-encoded text at every $maxLength 989 // but will not break any encoded letters. 990 $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|"; 991 $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|"; 992 993 if (strlen($value) > $maxLength1stLine) { 994 // Begin with the regexp for the first line. 995 $reg = $reg1st; 996 $output = ''; 997 while ($value) { 998 // Split translated string at every $maxLength 999 // But make sure not to break any translated chars. 1000 $found = preg_match($reg, $value, $matches); 1001 1002 // After this first line, we need to use a different 1003 // regexp for the first line. 1004 $reg = $reg2nd; 1005 1006 // Save the found part and encapsulate it in the 1007 // prefix & suffix. Then remove the part from the 1008 // $value_out variable. 1009 if ($found) { 1010 $part = $matches[0]; 1011 $len = strlen($matches[0]); 1012 $value = substr($value, $len); 1013 } else { 1014 $part = $value; 1015 $value = ''; 1016 } 1017 1018 // RFC 2047 specifies that any split header should 1019 // be seperated by a CRLF SPACE 1020 if ($output) { 1021 $output .= $eol . ' '; 1022 } 1023 $output .= $prefix . $part . $suffix; 1024 } 1025 $value = $output; 1026 } else { 1027 $value = $prefix . $value . $suffix; 1028 } 1029 } 1030 1031 return $value; 1032 } 1033 1034 /** 1035 * Encodes the given string using quoted-printable 1036 * 1037 * @param string $str String to encode 1038 * 1039 * @return string Encoded string 1040 * @access public 1041 * @since 1.6.0 1042 */ 1043 function encodeQP($str) 1044 { 1045 // Bug #17226 RFC 2047 restricts some characters 1046 // if the word is inside a phrase, permitted chars are only: 1047 // ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_" 1048 1049 // "=", "_", "?" must be encoded 1050 $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/'; 1051 $str = preg_replace_callback( 1052 $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str 1053 ); 1054 1055 return str_replace(' ', '_', $str); 1056 } 1057 1058 /** 1059 * Encodes the given string using base64 or quoted-printable. 1060 * This method makes sure that encoded-word represents an integral 1061 * number of characters as per RFC2047. 1062 * 1063 * @param string $str String to encode 1064 * @param string $charset Character set name 1065 * @param string $encoding Encoding name (base64 or quoted-printable) 1066 * @param int $prefix_len Prefix length. Default: 0 1067 * @param string $eol End-of-line sequence. Default: "\r\n" 1068 * 1069 * @return string Encoded string 1070 * @access public 1071 * @since 1.8.0 1072 */ 1073 function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n") 1074 { 1075 if (!function_exists('mb_substr') || !function_exists('mb_strlen')) { 1076 return; 1077 } 1078 1079 $encoding = $encoding == 'base64' ? 'B' : 'Q'; 1080 // 75 is the value specified in the RFC 1081 $prefix = '=?' . $charset . '?'.$encoding.'?'; 1082 $suffix = '?='; 1083 $maxLength = 75 - strlen($prefix . $suffix); 1084 1085 // A multi-octet character may not be split across adjacent encoded-words 1086 // So, we'll loop over each character 1087 // mb_stlen() with wrong charset will generate a warning here and return null 1088 $length = mb_strlen($str, $charset); 1089 $result = ''; 1090 $line_length = $prefix_len; 1091 1092 if ($encoding == 'B') { 1093 // base64 1094 $start = 0; 1095 $prev = ''; 1096 1097 for ($i=1; $i<=$length; $i++) { 1098 // See #17311 1099 $chunk = mb_substr($str, $start, $i-$start, $charset); 1100 $chunk = base64_encode($chunk); 1101 $chunk_len = strlen($chunk); 1102 1103 if ($line_length + $chunk_len == $maxLength || $i == $length) { 1104 if ($result) { 1105 $result .= "\n"; 1106 } 1107 $result .= $chunk; 1108 $line_length = 0; 1109 $start = $i; 1110 } else if ($line_length + $chunk_len > $maxLength) { 1111 if ($result) { 1112 $result .= "\n"; 1113 } 1114 if ($prev) { 1115 $result .= $prev; 1116 } 1117 $line_length = 0; 1118 $start = $i - 1; 1119 } else { 1120 $prev = $chunk; 1121 } 1122 } 1123 } else { 1124 // quoted-printable 1125 // see encodeQP() 1126 $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/'; 1127 1128 for ($i=0; $i<=$length; $i++) { 1129 $char = mb_substr($str, $i, 1, $charset); 1130 // RFC recommends underline (instead of =20) in place of the space 1131 // that's one of the reasons why we're not using iconv_mime_encode() 1132 if ($char == ' ') { 1133 $char = '_'; 1134 $char_len = 1; 1135 } else { 1136 $char = preg_replace_callback( 1137 $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char 1138 ); 1139 $char_len = strlen($char); 1140 } 1141 1142 if ($line_length + $char_len > $maxLength) { 1143 if ($result) { 1144 $result .= "\n"; 1145 } 1146 $line_length = 0; 1147 } 1148 1149 $result .= $char; 1150 $line_length += $char_len; 1151 } 1152 } 1153 1154 if ($result) { 1155 $result = $prefix 1156 .str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix; 1157 } 1158 1159 return $result; 1160 } 1161 1162 /** 1163 * Callback function to replace extended characters (\x80-xFF) with their 1164 * ASCII values (RFC2047: quoted-printable) 1165 * 1166 * @param array $matches Preg_replace's matches array 1167 * 1168 * @return string Encoded character string 1169 * @access private 1170 */ 1171 function _qpReplaceCallback($matches) 1172 { 1173 return sprintf('=%02X', ord($matches[1])); 1174 } 1175 1176 /** 1177 * Callback function to replace extended characters (\x80-xFF) with their 1178 * ASCII values (RFC2231) 1179 * 1180 * @param array $matches Preg_replace's matches array 1181 * 1182 * @return string Encoded character string 1183 * @access private 1184 */ 1185 function _encodeReplaceCallback($matches) 1186 { 1187 return sprintf('%%%02X', ord($matches[1])); 1188 } 1189 350 1190 } // End of class 351 ?>
Note: See TracChangeset
for help on using the changeset viewer.