[ Index ]

PHP Cross Reference of Eventum

title

Body

[close]

/include/ -> class.mime_helper.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */
   3  // +----------------------------------------------------------------------+
   4  // | Eventum - Issue Tracking System                                      |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 2003, 2004, 2005, 2006, 2007 MySQL AB                  |
   7  // |                                                                      |
   8  // | This program is free software; you can redistribute it and/or modify |
   9  // | it under the terms of the GNU General Public License as published by |
  10  // | the Free Software Foundation; either version 2 of the License, or    |
  11  // | (at your option) any later version.                                  |
  12  // |                                                                      |
  13  // | This program is distributed in the hope that it will be useful,      |
  14  // | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
  15  // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
  16  // | GNU General Public License for more details.                         |
  17  // |                                                                      |
  18  // | You should have received a copy of the GNU General Public License    |
  19  // | along with this program; if not, write to:                           |
  20  // |                                                                      |
  21  // | Free Software Foundation, Inc.                                       |
  22  // | 59 Temple Place - Suite 330                                          |
  23  // | Boston, MA 02111-1307, USA.                                          |
  24  // +----------------------------------------------------------------------+
  25  // | Authors: João Prado Maia <jpm@mysql.com>                             |
  26  // +----------------------------------------------------------------------+
  27  //
  28  
  29  /**
  30  * The MIME:: class provides methods for dealing with MIME standards.
  31  *
  32  * $Horde: horde/lib/MIME.php,v 1.121 2003/11/06 15:26:17 chuck Exp $
  33  *
  34  * Copyright 1999-2003 Chuck Hagenbuch <chuck@horde.org>
  35  *
  36  * See the enclosed file COPYING for license information (LGPL). If you
  37  * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  38  *
  39  */
  40  
  41  require_once(APP_PEAR_PATH . "Mail/mimeDecode.php");
  42  require_once (APP_INC_PATH . "class.error_handler.php");
  43  
  44  /**
  45   * Class to handle the business logic related to the MIME email
  46   * processing. The is8bit(), endode() and _encode() functions come from
  47   * the excellent Horde package at http://www.horde.org. These functions are
  48   * licensed under the LGPL, and Horde's copyright notice is available
  49   * above.
  50   *
  51   * @version 1.0
  52   * @author João Prado Maia <jpm@mysql.com>
  53   */
  54  class Mime_Helper
  55  {
  56      /**
  57       * Method used to get charset from raw email.
  58       *
  59       * @access  public
  60       * @param   mixed   $input The full body of the message or decoded email.
  61       * @return  string charset extracted from Content-Type header of email.
  62       */
  63      function getCharacterSet($input)
  64      {
  65          if (!is_object($input)) {
  66              $structure = Mime_Helper::decode($input, false, false);
  67          } else {
  68              $structure = $input;
  69          }
  70          if (empty($structure)) {
  71              return false;
  72          }
  73  
  74          if ($structure->ctype_primary == 'multipart' and $structure->ctype_secondary == 'mixed'
  75              and count($structure->parts) >= 1 and $structure->parts[0]->ctype_primary == 'text') {
  76              $content_type = $structure->parts[0]->headers['content-type'];
  77          } else {
  78              $content_type = @$structure->headers['content-type'];
  79          }
  80  
  81          if (preg_match('/charset\s*=\s*(["\'])?([-\w\d]+)(\1)?;?/i', $content_type, $matches)) {
  82              return $matches[2];
  83          }
  84  
  85          return false;
  86      }
  87  
  88  
  89      /**
  90       * Returns the appropriate message body for a given MIME-based decoded
  91       * structure.
  92       *
  93       * @access  public
  94       * @param   object $output The parsed message structure
  95       * @return  string The message body
  96       * @see     Mime_Helper::decode()
  97       */
  98      function getMessageBody(&$output)
  99      {
 100          $parts = array();
 101          Mime_Helper::parse_output($output, $parts);
 102          if (empty($parts)) {
 103              Error_Handler::logError(array("Mime_Helper::parse_output failed. Corrupted MIME in email?", $output), __FILE__, __LINE__);
 104              // we continue as if nothing happened until it's clear it's right check to do.
 105          }
 106          $str = '';
 107          $is_html = false;
 108          if (isset($parts["text"])) {
 109              $str = join("\n\n", $parts["text"]);
 110          } elseif (isset($parts["html"])) {
 111              $is_html = true;
 112              $str = join("\n\n", $parts["html"]);
 113  
 114              // hack for inotes to prevent content from being displayed all on one line.
 115              $str = str_replace("</DIV><DIV>", "\n", $str);
 116              $str = str_replace(array("<br>", "<br />", "<BR>", "<BR />"), "\n", $str);
 117          }
 118          // XXX: do we also need to do something here about base64 encoding?
 119          if ($is_html) {
 120              $str = strip_tags($str);
 121          }
 122          return $str;
 123      }
 124  
 125  
 126      /**
 127       * Method used to fix the encoding of MIME based strings.
 128       *
 129       * @access  public
 130       * @param   string $input The string to be fixed
 131       * @return  string The fixed string
 132       */
 133      function fixEncoding($input)
 134      {
 135          // Remove white space between encoded-words
 136          $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
 137          // For each encoded-word...
 138          while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
 139              $encoded  = $matches[1];
 140              $charset  = $matches[2];
 141              $encoding = $matches[3];
 142              $text     = $matches[4];
 143              switch (strtolower($encoding)) {
 144                  case 'b':
 145                      $text = base64_decode($text);
 146                      break;
 147                  case 'q':
 148                      $text = str_replace('_', ' ', $text);
 149                      preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
 150                      foreach($matches[1] as $value)
 151                          $text = str_replace('='.$value, chr(hexdec($value)), $text);
 152                      break;
 153              }
 154              $input = str_replace($encoded, $text, $input);
 155          }
 156          return $input;
 157      }
 158  
 159  
 160      /**
 161       * Method used to properly quote the sender of a given email address.
 162       *
 163       * @access  public
 164       * @param   string $address The full email address
 165       * @return  string The properly quoted email address
 166       */
 167      function quoteSender($address)
 168      {
 169          if (strstr($address, '<')) {
 170              $address = stripslashes($address);
 171              $first_part = substr($address, 0, strrpos($address, '<') - 1);
 172              $first_part = '"' . str_replace('"', '\"',($first_part)) . '"';
 173              $second_part = substr($address, strrpos($address, '<'));
 174              $address = $first_part . ' ' . $second_part;
 175          }
 176          return $address;
 177      }
 178  
 179  
 180      /**
 181       * Method used to remove any unnecessary quoting from an email address.
 182       *
 183       * @access  public
 184       * @param   string $address The full email address
 185       * @return  string The email address without quotes
 186       */
 187      function removeQuotes($address)
 188      {
 189          if (strstr($address, '<')) {
 190              $address = stripslashes($address);
 191              $first_part = substr($address, 0, strrpos($address, '<') - 1);
 192              $second_part = substr($address, strrpos($address, '<'));
 193              $address = $first_part;
 194          }
 195          if (preg_match('/^".*"/', $address)) {
 196              $address = preg_replace('/^"(.*)"/', '\\1', $address);
 197          }
 198          if (!empty($second_part)) {
 199              $address .= ' ' . $second_part;
 200          }
 201          return $address;
 202      }
 203  
 204  
 205      /**
 206       * Method used to properly encode an email address.
 207       *
 208       * @access  public
 209       * @param   string $address The full email address
 210       * @return  string The properly encoded email address
 211       */
 212      function encodeAddress($address)
 213      {
 214          $address = MIME_Helper::removeQuotes($address);
 215          if (Mime_Helper::is8bit($address)) {
 216              // split into name and address section
 217              preg_match("/(.*)<(.*)>/", $address, $matches);
 218             $address = "=?" . APP_CHARSET . "?Q?" .
 219                  str_replace(' ', '_', trim(preg_replace('/([\x80-\xFF]|[\x21-\x2F]|[\xFC]|\[|\])/e', '"=" . strtoupper(dechex(ord(stripslashes("\1"))))', $matches[1]))) . "?= <" . $matches[2] . ">";
 220             return $address;
 221          } else {
 222              return MIME_Helper::quoteSender($address);
 223          }
 224      }
 225  
 226  
 227      /**
 228       * Decodes a quoted printable encoded address and returns the string.
 229       *
 230       * @param   string $address The address to decode
 231       * @return  string The decoded address
 232       */
 233      function decodeAddress($address)
 234      {
 235          if (preg_match("/=\?.+\?Q\?(.+)\?= <(.+)>/i", $address, $matches)) {
 236              return str_replace("_", ' ', quoted_printable_decode($matches[1])) . " <" . $matches[2] . ">";
 237          } else {
 238              return Mime_Helper::removeQuotes($address);
 239          }
 240      }
 241  
 242  
 243      /**
 244       * Returns if a specified string contains a quoted printable address.
 245       *
 246       * @param   string $address The address
 247       * @return  boolean If the address is quoted printable encoded.
 248       */
 249      function isQuotedPrintable($address)
 250      {
 251          if (preg_match("/=\?.+\?Q\?.+\?= <.+>/i", $address)) {
 252              return true;
 253          } else {
 254              return false;
 255          }
 256      }
 257  
 258  
 259      /**
 260       * Determine if a string contains 8-bit characters.
 261       *
 262       * @access public
 263       *
 264       * @param string $string  The string to check.
 265       *
 266       * @return boolean  True if it does, false if it doesn't.
 267       */
 268      function is8bit($string)
 269      {
 270          if (is_string($string) && preg_match('/[\x80-\xff]+/', $string)) {
 271              return true;
 272          } else {
 273              return false;
 274          }
 275      }
 276  
 277  
 278      /**
 279       * Encode a string containing non-ASCII characters according to RFC 2047.
 280       *
 281       * @access public
 282       *
 283       * @param string $text     The text to encode.
 284       * @param string $charset  (optional) The character set of the text.
 285       *
 286       * @return string  The text, encoded only if it contains non-ASCII
 287       *                 characters.
 288       */
 289      function encode($text, $charset = APP_CHARSET)
 290      {
 291          /* Return if nothing needs to be encoded. */
 292          if (!MIME_Helper::is8bit($text)) {
 293              return $text;
 294          }
 295  
 296          $charset = strtolower($charset);
 297          $line = '';
 298  
 299          /* Get the list of elements in the string. */
 300          $size = preg_match_all("/([^\s]+)([\s]*)/", $text, $matches, PREG_SET_ORDER);
 301  
 302          foreach ($matches as $key => $val) {
 303              if (MIME_Helper::is8bit($val[1])) {
 304                  if ((($key + 1) < $size) &&
 305                      MIME_Helper::is8bit($matches[$key + 1][1])) {
 306                      $line .= MIME_Helper::_encode($val[1] . $val[2], $charset) . ' ';
 307                  } else {
 308                      $line .= MIME_Helper::_encode($val[1], $charset) . $val[2];
 309                  }
 310              } else {
 311                  $line .= $val[1] . $val[2];
 312              }
 313          }
 314  
 315          return rtrim($line);
 316      }
 317  
 318      /**
 319       * Internal recursive function to RFC 2047 encode a string.
 320       *
 321       * @access private
 322       *
 323       * @param string $text     The text to encode.
 324       * @param string $charset  The character set of the text.
 325       *
 326       * @return string  The text, encoded only if it contains non-ASCII
 327       *                 characters.
 328       */
 329      function _encode($text, $charset)
 330      {
 331          $char_len = strlen($charset);
 332          $txt_len = strlen($text) * 2;
 333  
 334          /* RFC 2047 [2] states that no encoded word can be more than 75
 335             characters long. If longer, you must split the word. */
 336          if (($txt_len + $char_len + 7) > 75) {
 337              $pos = intval((68 - $char_len) / 2);
 338              return MIME_Helper::_encode(substr($text, 0, $pos), $charset) . ' ' . MIME_Helper::_encode(substr($text, $pos), $charset);
 339          } else {
 340              return '=?' . $charset . '?b?' . trim(base64_encode($text)) . '?=';
 341          }
 342      }
 343  
 344  
 345      /**
 346       * Method used to encode a given string in the quoted-printable standard.
 347       *
 348       * @access  public
 349       * @param   string $hdr_value The string to be encoded
 350       * @param   string $charset The charset of the string
 351       * @return  string The encoded string
 352       */
 353      function encodeValue($hdr_value, $charset = 'iso-8859-1')
 354      {
 355          preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $hdr_value, $matches);
 356          foreach ($matches[1] as $value) {
 357              $replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
 358              $hdr_value = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $hdr_value);
 359          }
 360          return $hdr_value;
 361      }
 362  
 363  
 364      /**
 365       * Given a string containing a header and body
 366       * section, this function will split them (at the first
 367       * blank line) and return them.
 368       *
 369       * @access  public
 370       * @param   string $input Input to split apart
 371       * @return  array Contains header and body section
 372       */
 373      function splitBodyHeader($input)
 374      {
 375          if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
 376              return array($match[1], $match[2]);
 377          }
 378      }
 379  
 380  
 381      /**
 382       * Parse headers given in $input and return
 383       * as assoc array.
 384       *
 385       * @access  public
 386       * @param   string $input Headers to parse
 387       * @return  array Contains parsed headers
 388       */
 389      function getHeaderNames($input)
 390      {
 391          if ($input !== '') {
 392              // Unfold the input
 393              $input   = preg_replace("/\r?\n/", "\r\n", $input);
 394              $input   = preg_replace("/\r\n(\t| )+/", ' ', $input);
 395              $headers = explode("\r\n", trim($input));
 396              foreach ($headers as $value) {
 397                  $hdr_name = substr($value, 0, $pos = strpos($value, ':'));
 398                  $return[strtolower($hdr_name)] = $hdr_name;
 399              }
 400          } else {
 401              $return = array();
 402          }
 403          return $return;
 404      }
 405  
 406  
 407      /**
 408       * Method used to get an unique attachment name for a given
 409       * filename. This is specially useful for the emails that Microsoft
 410       * Outlook sends out with several attachments with the same name
 411       * when you embed several inline screenshots in the message
 412       *
 413       * @access  public
 414       * @param   array $list The nested array of mime parts
 415       * @param   string $filename The filename to search for
 416       * @return  string The unique attachment name
 417       */
 418      function getAttachmentName(&$list, $filename)
 419      {
 420          if (@in_array($filename, array_values($list))) {
 421              // check if the filename even has an extension...
 422              if (!strstr($filename, '.')) {
 423                  $first_part = $filename;
 424              } else {
 425                  $first_part = substr($filename, 0, strrpos($filename, '.'));
 426              }
 427              // check if this is already named Outlook-2.bmp (or similar)
 428              if (strstr($first_part, "-")) {
 429                  // if so, gotta get the number and increment it
 430                  $numeric_portion = substr($first_part, strrpos($first_part, "-")+1);
 431                  if (preg_match("/^[0-9]+$/", $numeric_portion)) {
 432                      $numeric_portion = intval($numeric_portion) + 1;
 433                  }
 434                  $first_part = substr($first_part, 0, strrpos($first_part, "-"));
 435              } else {
 436                  $numeric_portion = 1;
 437              }
 438              if (!strstr($filename, '.')) {
 439                  $filename = $first_part . "-" . $numeric_portion;
 440              } else {
 441                  $filename = $first_part . "-" . $numeric_portion . substr($filename, strrpos($filename, '.'));
 442              }
 443              return MIME_Helper::getAttachmentName($list, $filename);
 444          } else {
 445              return $filename;
 446          }
 447      }
 448  
 449  
 450      /**
 451       * Method used to check whether a given email message has any attachments.
 452       *
 453       * @access  public
 454       * @param   mixed   $message The full body of the message or parsed message structure.
 455       * @return  boolean
 456       */
 457      function hasAttachments($message)
 458      {
 459          if (!is_object($message)) {
 460              $message = Mime_Helper::decode($message, true);
 461          }
 462          $attachments = Mime_Helper::_getAttachmentDetails($message, TRUE);
 463          if (count($attachments) > 0) {
 464              return true;
 465          } else {
 466              return false;
 467          }
 468      }
 469  
 470  
 471      /**
 472       * Method used to parse and return the full list of attachments
 473       * associated with a message.
 474       *
 475       * @access  public
 476       * @param   mixed   $message The full body of the message or parsed message structure.
 477       * @return  array The list of attachments, if any
 478       */
 479      function getAttachments($message)
 480      {
 481          if (!is_object($message)) {
 482              $message = Mime_Helper::decode($message, true);
 483          }
 484          return Mime_Helper::_getAttachmentDetails($message, TRUE);
 485      }
 486  
 487  
 488      /**
 489       * Method used to parse and return the full list of attachment CIDs
 490       * associated with a message.
 491       *
 492       * @access  public
 493       * @param   mixed   $message The full body of the message or parsed message structure.
 494       * @return  array The list of attachment CIDs, if any
 495       */
 496      function getAttachmentCIDs($message)
 497      {
 498          if (!is_object($message)) {
 499              $message = Mime_Helper::decode($message, true);
 500          }
 501          return Mime_Helper::_getAttachmentDetails($message, true);
 502      }
 503  
 504  
 505      function _getAttachmentDetails(&$mime_part, $return_body = FALSE, $return_filename = FALSE, $return_cid = FALSE)
 506      {
 507          $attachments = array();
 508          if (isset($mime_part->parts)) {
 509              for ($i = 0; $i < count($mime_part->parts); $i++) {
 510                  $t = Mime_Helper::_getAttachmentDetails($mime_part->parts[$i], $return_body, $return_filename, $return_cid);
 511                  $attachments = array_merge($t, $attachments);
 512              }
 513          }
 514          // FIXME: content-type is always lowered by PEAR class (CHECKME) and why not $mime_part->content_type?
 515          $content_type = strtolower(@$mime_part->ctype_primary . '/' . @$mime_part->ctype_secondary);
 516          if ($content_type == '/') {
 517              $content_type = '';
 518          }
 519          $found = 0;
 520          // get the proper filename
 521          $mime_part_filename = @$mime_part->ctype_parameters['name'];
 522          if (empty($mime_part_filename)) {
 523              $mime_part_filename = @$mime_part->d_parameters['filename'];
 524          }
 525          // hack in order to treat inline images as normal attachments
 526          // (since Eventum does not display those embedded within the message)
 527          if (@$mime_part->ctype_primary == 'image') {
 528              // if requested, return only the details of a particular filename
 529              if (($return_filename != FALSE) && ($mime_part_filename != $return_filename)) {
 530                  return array();
 531              }
 532              // if requested, return only the details of
 533              // a particular attachment CID. Only really needed
 534              // as hack for inline images
 535              if (($return_cid != FALSE) && (@$mime_part->headers['content-id'] != $return_cid)) {
 536                  return array();
 537              }
 538              $found = 1;
 539          } else {
 540              if ((!in_array($content_type, Mime_Helper::_getInvalidContentTypes())) &&
 541                      (in_array(@strtolower($mime_part->disposition), Mime_Helper::_getValidDispositions())) &&
 542                      (!empty($mime_part_filename))) {
 543                  // if requested, return only the details of a particular filename
 544                  if (($return_filename != FALSE) && ($mime_part_filename != $return_filename)) {
 545                      return array();
 546                  }
 547                  $found = 1;
 548              }
 549          }
 550          if ($found) {
 551              $t = array(
 552                  'filename' => $mime_part_filename,
 553                  'cid'      => @$mime_part->headers['content-id'],
 554                  'filetype' => $content_type
 555              );
 556              // only include the body of the attachment when
 557              // requested to save some memory
 558              if ($return_body == TRUE) {
 559                  $t['blob'] = &$mime_part->body;
 560              }
 561              $attachments[] = $t;
 562          }
 563  
 564          return $attachments;
 565      }
 566  
 567  
 568      /**
 569       * Method used to get the encoded content of a specific message
 570       * attachment.
 571       *
 572       * @access  public
 573       * @param   mixed   $message The full content of the message or parsed message structure.
 574       * @param   string $filename The filename to look for
 575       * @param   string $cid The content-id to look for, if any
 576       * @return  string The full encoded content of the attachment
 577       */
 578      function getAttachment($message, $filename, $cid = FALSE)
 579      {
 580          $parts = array();
 581          if (!is_object($message)) {
 582              $message = Mime_Helper::decode($message, true);
 583          }
 584          $details = Mime_Helper::_getAttachmentDetails($message, TRUE, $filename, $cid);
 585          if (count($details) == 1) {
 586              return array(
 587                  $details[0]['filetype'],
 588                  $details[0]['blob']
 589              );
 590          } else {
 591              return array();
 592          }
 593      }
 594  
 595  
 596      /**
 597       * Method used to decode the content of a MIME encoded message.
 598       *
 599       * @access  public
 600       * @param   string $message The full body of the message
 601       * @param   boolean $include_bodies Whether to include the bodies in the return value or not
 602       * @return  mixed The decoded content of the message
 603       */
 604      function decode($message, $include_bodies = FALSE, $decode_bodies = TRUE)
 605      {
 606          // need to fix a pretty annoying bug where if the 'boundary' part of a
 607          // content-type header is split into another line, the PEAR library would
 608          // not work correctly. this fix will make the boundary part go to the
 609          // same line as the content-type one
 610          if (preg_match('/^boundary=/m', $message)) {
 611              $pattern = "#(Content-Type: multipart/.+); ?\r?\n(boundary=)$#im";
 612              $replacement = '$1; $2';
 613              $message = preg_replace($pattern, $replacement, $message);
 614          }
 615  
 616          $params = array(
 617              'crlf'           => "\r\n",
 618              'include_bodies' => $include_bodies,
 619              'decode_headers' => TRUE,
 620              'decode_bodies'  => $decode_bodies
 621          );
 622          $decode = new Mail_mimeDecode($message);
 623          return $decode->decode($params);
 624      }
 625  
 626  
 627      /**
 628       * Method used to parse the decoded object structure of a MIME
 629       * message into something more manageable.
 630       *
 631       * @access  public
 632       * @param   object $obj The decoded object structure of the MIME message
 633       * @param   array $parts The parsed parts of the MIME message
 634       * @return  void
 635       */
 636      function parse_output($obj, &$parts)
 637      {
 638          if (!empty($obj->parts)) {
 639              for ($i = 0; $i < count($obj->parts); $i++) {
 640                  Mime_Helper::parse_output($obj->parts[$i], $parts);
 641              }
 642          } else {
 643              $ctype = @strtolower($obj->ctype_primary.'/'.$obj->ctype_secondary);
 644              switch($ctype){
 645                  case 'text/plain':
 646                      if (((!empty($obj->disposition)) && (strtolower($obj->disposition) == 'attachment')) || (!empty($obj->d_parameters['filename']))) {
 647                          @$parts['attachments'][] = $obj->body;
 648                      } else {
 649                          @$parts['text'][] = $obj->body;
 650                      }
 651                      break;
 652                  case 'text/html':
 653                      if ((!empty($obj->disposition)) && (strtolower($obj->disposition) == 'attachment')) {
 654                          @$parts['attachments'][] = $obj->body;
 655                      } else {
 656                          @$parts['html'][] = $obj->body;
 657                      }
 658                      break;
 659                  // special case for Apple Mail
 660                  case 'text/enriched':
 661                      if ((!empty($obj->disposition)) && (strtolower($obj->disposition) == 'attachment')) {
 662                          @$parts['attachments'][] = $obj->body;
 663                      } else {
 664                          @$parts['html'][] = $obj->body;
 665                      }
 666                      break;
 667                  default:
 668                      // avoid treating forwarded messages as attachments
 669                      if ((!empty($obj->disposition)) && (strtolower($obj->disposition) == 'inline') &&
 670                              ($ctype != 'message/rfc822')) {
 671                          @$parts['attachments'][] = $obj->body;
 672                      } elseif (stristr($ctype, 'image')) {
 673                          // handle inline images
 674                          @$parts['attachments'][] = $obj->body;
 675                      } elseif(strtolower(@$obj->disposition) == 'attachment') {
 676                          @$parts['attachments'][] = $obj->body;
 677                      } else {
 678                          @$parts['text'][] = $obj->body;
 679                      }
 680              }
 681          }
 682      }
 683  
 684  
 685      /**
 686       * Given a quoted-printable string, this
 687       * function will decode and return it.
 688       *
 689       * @access private
 690       * @param  string Input body to decode
 691       * @return string Decoded body
 692       */
 693      function _quotedPrintableDecode($input)
 694      {
 695          // Remove soft line breaks
 696          $input = preg_replace("/=\r?\n/", '', $input);
 697  
 698          // Replace encoded characters
 699          $input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input);
 700  
 701          return $input;
 702      }
 703  
 704  
 705      /**
 706       * Returns the internal list of content types that we do not support as
 707       * valid attachment types.
 708       *
 709       * @access private
 710       * @return array The list of content types
 711       */
 712      function _getInvalidContentTypes()
 713      {
 714          return array(
 715              'message/rfc822',
 716              'application/pgp-signature',
 717              'application/ms-tnef',
 718          );
 719      }
 720  
 721  
 722      /**
 723       * Returns the internal list of attachment dispositions that we do not
 724       * support as valid attachment types.
 725       *
 726       * @access private
 727       * @return array The list of valid dispositions
 728       */
 729      function _getValidDispositions()
 730      {
 731          return array(
 732              'attachment',
 733              'inline'
 734          );
 735      }
 736  
 737  
 738      /**
 739       * Splits the full email into headers and body
 740       *
 741       * @access  public
 742       * @param   string $message The full email message
 743       * @param   boolean $unfold If headers should be unfolded
 744       * @return  array An array containing the headers and body
 745       */
 746      function splitHeaderBody($message, $unfold = true)
 747      {
 748          if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $message, $match)) {
 749              return array(($unfold) ? Mail_API::unfold($match[1]) : $match[1], $match[2]);
 750          }
 751          return array();
 752      }
 753  }
 754  
 755  // benchmarking the included file (aka setup time)
 756  if (APP_BENCHMARK) {
 757      $GLOBALS['bench']->setMarker('Included Mime_Helper Class');
 758  }


Generated: Wed Dec 19 21:21:33 2007 Cross-referenced by PHPXref 0.7