[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/Horde/MIME/ -> Structure.php (source)

   1  <?php
   2  
   3  require_once dirname(__FILE__) . '/Message.php';
   4  require_once dirname(__FILE__) . '/Part.php';
   5  require_once dirname(__FILE__) . '/../MIME.php';
   6  
   7  /**
   8   * $Horde: framework/MIME/MIME/Structure.php,v 1.87.10.19 2006/05/04 18:03:25 slusarz Exp $
   9   *
  10   * The MIME_Structure:: class provides methods for dealing with MIME mail.
  11   *
  12   * The default character set to use for messages should be defined in the
  13   * variable $GLOBALS['mime_structure']['default_charset'] (defaults to US-ASCII
  14   * per RFC 2045).
  15   *
  16   * TODO: Convert to OO
  17   *
  18   * Copyright 1999-2006 Chuck Hagenbuch <chuck@horde.org>
  19   * Copyright 2002-2006 Michael Slusarz <slusarz@bigworm.colorado.edu>
  20   *
  21   * See the enclosed file COPYING for license information (LGPL). If you
  22   * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  23   *
  24   * @author  Chuck Hagenbuch <chuck@horde.org>
  25   * @author  Michael Slusarz <slusarz@bigworm.colorado.edu>
  26   * @since   Horde 1.3
  27   * @package Horde_MIME
  28   */
  29  class MIME_Structure {
  30  
  31      /**
  32       * Given the results of imap_fetchstructure(), parse the structure
  33       * of the message, figuring out correct bodypart numbers, etc.
  34       *
  35       * @param stdClass $body  The result of imap_fetchstructure().
  36       *
  37       * @return &MIME_Message  The message parsed into a MIME_Message object.
  38       */
  39      function &parse($body)
  40      {
  41          $msgOb = &new MIME_Message();
  42          $msgOb->addPart(MIME_Structure::_parse($body));
  43          $msgOb->buildMessage();
  44  
  45          $ptr = array(&$msgOb);
  46          MIME_Structure::_addMultipartInfo($ptr);
  47  
  48          return $msgOb;
  49      }
  50  
  51      /**
  52       * Given the results of imap_fetchstructure(), parse the structure
  53       * of the message, figuring out correct bodypart numbers, etc.
  54       *
  55       * @access private
  56       *
  57       * @param stdClass $body  The result of imap_fetchstructure().
  58       * @param string $ref     The current bodypart.
  59       *
  60       * @return MIME_Part  A MIME_Part object.
  61       */
  62      function &_parse($body, $ref = 0)
  63      {
  64          static $message, $multipart;
  65  
  66          if (!isset($message)) {
  67              $message = MIME::type('message');
  68              $multipart = MIME::type('multipart');
  69          }
  70  
  71          $mime_part = &new MIME_Part();
  72  
  73          /* Top multiparts don't get their own line. */
  74          if (empty($ref) &&
  75              (!isset($body->type) || ($body->type != $multipart))) {
  76              $ref = 1;
  77          }
  78  
  79          MIME_Structure::_setInfo($body, $mime_part, $ref);
  80  
  81          if (isset($body->type) && ($body->type == $message) &&
  82              $body->ifsubtype && ($body->subtype == 'RFC822')) {
  83              $mime_part->setMIMEId($ref . '.0');
  84          } else {
  85              $mime_part->setMIMEId($ref);
  86          }
  87  
  88          /* Deal with multipart data. */
  89          if (isset($body->parts)) {
  90              $sub_id = 1;
  91              foreach ($body->parts as $sub_part) {
  92                  /* Are we dealing with a multipart message? */
  93                  if (isset($body->type) && ($body->type == $message) &&
  94                      isset($sub_part->type) && ($sub_part->type == $multipart)) {
  95                      $sub_ref = $ref;
  96                  } else {
  97                      $sub_ref = (empty($ref)) ? $sub_id : $ref . '.' . $sub_id;
  98                  }
  99                  $mime_part->addPart(MIME_Structure::_parse($sub_part, $sub_ref), $sub_id++);
 100              }
 101          }
 102  
 103          return $mime_part;
 104      }
 105  
 106      /**
 107       * Given a mime part from imap_fetchstructure(), munge it into a
 108       * useful form and make sure that any parameters which are missing
 109       * are given default values.
 110       *
 111       * To specify the default character set, define the global variable
 112       * $GLOBALS['mime_strucutre']['default_charset'].
 113       *
 114       * @access private
 115       *
 116       * @param stdClass $part  The original part info.
 117       * @param MIME_Part &$ob  A MIME_Part object.
 118       * @param string $ref     The ID of this part.
 119       */
 120      function _setInfo($part, &$ob, $ref)
 121      {
 122          /* Store Content-type information. */
 123          $primary_type = (isset($part->type)) ? String::lower($part->type) : MIME::type('text');
 124          $sec_type = ($part->ifsubtype && $part->subtype) ? String::lower($part->subtype) : 'x-unknown';
 125          $ob->setType($primary_type . '/' . $sec_type);
 126  
 127          /* Set transfer encoding. */
 128          if (isset($part->encoding)) {
 129              $encoding = $part->encoding;
 130              $ob->setTransferEncoding($encoding);
 131          } else {
 132              $encoding = null;
 133          }
 134  
 135          /* Set transfer disposition. */
 136          $ob->setDisposition(($part->ifdisposition) ? String::lower($part->disposition) : MIME_DEFAULT_DISPOSITION);
 137  
 138          /* If 'body' is set, set as the contents of the part. */
 139          if (isset($part->body)) {
 140              $ob->setContents($part->body, $encoding);
 141          }
 142  
 143          /* If 'bytes' is set, store as information variable. */
 144          if (isset($part->bytes)) {
 145              $ob->setBytes($part->bytes);
 146          }
 147  
 148          /* Set the part's identification string, if available. */
 149          if (!empty($ref) && $part->ifid) {
 150              $ob->setContentID($part->id);
 151          }
 152  
 153          /* Go through the content-type parameters, if any. */
 154          foreach (MIME_Structure::_getParameters($part, 1) as $key => $val) {
 155              if ($key == 'charset') {
 156                  $ob->setCharset($val);
 157              } else {
 158                  $ob->setContentTypeParameter($key, $val);
 159              }
 160          }
 161  
 162          /* Set the default character set. */
 163          if (($ob->getCharset() == 'us-ascii') &&
 164              isset($GLOBALS['mime_structure']['default_charset'])) {
 165              $ob->setCharset($GLOBALS['mime_structure']['default_charset']);
 166          }
 167  
 168          /* Go through the disposition parameters, if any. */
 169          foreach (MIME_Structure::_getParameters($part, 2) as $key => $val) {
 170              $ob->setDispositionParameter($key, $val);
 171          }
 172  
 173          /* Set the name. */
 174          if ($ob->getContentTypeParameter('filename')) {
 175              $ob->setName($ob->getContentTypeParameter('filename'));
 176          } elseif ($ob->getDispositionParameter('filename')) {
 177              $ob->setName($ob->getDispositionParameter('filename'));
 178          }
 179  
 180          /* Set the description. */
 181          if (isset($part->description)) {
 182              $ob->setDescription($part->description);
 183          }
 184      }
 185  
 186      /**
 187       * Get all parameters for a given portion of a message.
 188       *
 189       * @access private
 190       *
 191       * @param stdClass $part  The original part info.
 192       * @param integer $type   The parameter type to retrieve.
 193       *                        1 = content
 194       *                        2 = disposition
 195       *
 196       * @return array  An array of parameter key/value pairs.
 197       */
 198      function _getParameters($part, $type)
 199      {
 200          $param_list = array();
 201  
 202          if ($type == 1) {
 203              $ptype = 'parameters';
 204          } elseif ($type == 2) {
 205              $ptype = 'dparameters';
 206          }
 207          $pexists = 'if' . $ptype;
 208  
 209          if ($part->$pexists) {
 210              foreach ($part->$ptype as $param) {
 211                  $param->value = str_replace(array("\t", '\"'), array(' ', '"'), $param->value);
 212  
 213                  $res = MIME::decodeRFC2231($param->attribute . '=' . $param->value);
 214                  if ($res) {
 215                      $param->attribute = $res['attribute'];
 216                      $param->value = $res['value'];
 217                  }
 218                  $field = String::lower($param->attribute);
 219                  if ($field == 'type') {
 220                      if (($type = MIME::type($param->value))) {
 221                          $param_list['type'] = $type;
 222                      }
 223                  } else {
 224                      $param_list[$field] = $param->value;
 225                  }
 226              }
 227          }
 228  
 229          return $param_list;
 230      }
 231  
 232      /**
 233       * Set the special information for certain MIME types.
 234       *
 235       * @access private
 236       *
 237       * @param array &$parts  The list of parts contained within the multipart
 238       *                       object.
 239       * @param array $info    Information about the multipart structure.
 240       */
 241      function _addMultipartInfo(&$parts, $info = array())
 242      {
 243          if (empty($parts)) {
 244              return;
 245          }
 246  
 247          foreach (array_keys($parts) as $key) {
 248              $ptr = &$parts[$key];
 249              $new_info = $info;
 250  
 251              if (isset($info['alt'])) {
 252                  $ptr->setInformation('alternative', (is_null($info['alt'])) ? '-' : $info['alt']);
 253              }
 254              if (isset($info['related'])) {
 255                  $ptr->setInformation('related_part', $info['related']->getMIMEId());
 256                  if ($id = $ptr->getContentID()) {
 257                      $info['related']->addCID(array($ptr->getMIMEId() => $id));
 258                  }
 259              }
 260              if (isset($info['rfc822'])) {
 261                  $ptr->setInformation('rfc822_part', $info['rfc822']);
 262              }
 263  
 264              switch ($ptr->getType()) {
 265              case 'multipart/alternative':
 266                  $new_info['alt'] = $ptr->getMIMEId();
 267                  break;
 268  
 269              case 'multipart/related':
 270                  $new_info['related'] = &$ptr;
 271                  break;
 272  
 273              case 'message/rfc822':
 274                  $new_info['rfc822'] = $ptr->getMIMEId();
 275                  $ptr->setInformation('header', true);
 276                  break;
 277              }
 278  
 279              MIME_Structure::_addMultipartInfo($ptr->_parts, $new_info);
 280          }
 281      }
 282  
 283  
 284      /**
 285       * Attempts to build a MIME_Message object from a text message.
 286       *
 287       * @param string $text  The text of the MIME message.
 288       *
 289       * @return MIME_Message  A MIME_Message object, or false on error.
 290       */
 291      function &parseTextMIMEMessage($text)
 292      {
 293          require_once 'Mail/mimeDecode.php';
 294  
 295          /* Set up the options for the mimeDecode class. */
 296          $decode_args = array();
 297          $decode_args['include_bodies'] = true;
 298          $decode_args['decode_bodies'] = false;
 299          $decode_args['decode_headers'] = false;
 300  
 301          $mimeDecode = &new Mail_mimeDecode($text, MIME_PART_EOL);
 302          if (!($structure = $mimeDecode->decode($decode_args))) {
 303              $message = false;
 304          } else {
 305              /* Put the object into imap_parsestructure() form. */
 306              MIME_Structure::_convertMimeDecodeData($structure);
 307  
 308              $message = MIME_Structure::parse($structure);
 309          }
 310  
 311          return $message;
 312      }
 313  
 314      /**
 315       * Convert the output from mimeDecode::decode() into a structure that
 316       * matches imap_fetchstructure() output.
 317       *
 318       * @access private
 319       *
 320       * @param stdClass &$ob  The output from mimeDecode::decode().
 321       */
 322      function _convertMimeDecodeData(&$ob)
 323      {
 324          /* Primary content-type. */
 325          $ob->type = intval(MIME::type($ob->ctype_primary));
 326  
 327          /* Secondary content-type. */
 328          if (isset($ob->ctype_secondary)) {
 329              $ob->subtype = String::upper($ob->ctype_secondary);
 330              $ob->ifsubtype = 1;
 331          } else {
 332              $ob->ifsubtype = 0;
 333          }
 334  
 335          /* Content transfer encoding. */
 336          if (isset($ob->headers['content-transfer-encoding'])) {
 337              $ob->encoding = MIME::encoding($ob->headers['content-transfer-encoding']);
 338          }
 339  
 340          /* Content-type and Disposition parameters. */
 341          $param_types = array ('ctype_parameters' => 'parameters',
 342                                'd_parameters' => 'dparameters');
 343          foreach ($param_types as $param_key => $param_value) {
 344              $if_var = 'if' . $param_value;
 345              if (isset($ob->$param_key)) {
 346                  $ob->$if_var = 1;
 347                  $ob->$param_value = array();
 348                  foreach ($ob->$param_key as $key => $val) {
 349                      $newOb = &new stdClass;
 350                      $newOb->attribute = $key;
 351                      $newOb->value = $val;
 352                      array_push($ob->$param_value, $newOb);
 353                  }
 354              } else {
 355                  $ob->$if_var = 0;
 356              }
 357          }
 358  
 359          /* Content-Disposition. */
 360          if (isset($ob->headers['content-disposition'])) {
 361              $ob->ifdisposition = 1;
 362              $hdr = $ob->headers['content-disposition'];
 363              $pos = strpos($hdr, ';');
 364              if ($pos !== false) {
 365                  $hdr = substr($hdr, 0, $pos);
 366              }
 367              $ob->disposition = $hdr;
 368          } else {
 369              $ob->ifdisposition = 0;
 370          }
 371  
 372          /* Content-ID. */
 373          if (isset($ob->headers['content-id'])) {
 374              $ob->ifid = 1;
 375              $ob->id = $ob->headers['content-id'];
 376          } else {
 377              $ob->ifid = 0;
 378          }
 379  
 380          /* Get file size (if 'body' text is set). */
 381          if (isset($ob->body)) {
 382              $ob->bytes = strlen($ob->body);
 383          }
 384  
 385          /* Process parts also. */
 386          if (isset($ob->parts)) {
 387              foreach (array_keys($ob->parts) as $key) {
 388                  MIME_Structure::_convertMimeDecodeData($ob->parts[$key]);
 389              }
 390          }
 391      }
 392  
 393      /**
 394       * Builds an array consisting of MIME header/value pairs.
 395       *
 396       * @param string $headers     A text string containing the headers (e.g.
 397       *                            output from imap_fetchheader()).
 398       * @param boolean $decode     Should the headers be decoded?
 399       * @param boolean $lowercase  Should the keys be in lowercase?
 400       *
 401       * @return array  An array consisting of the header name as the key and
 402       *                the header value as the value.
 403       *                A header with multiple entries will be stored in
 404       *                'value' as an array.
 405       */
 406      function parseMIMEHeaders($headers, $decode = true, $lowercase = false)
 407      {
 408          $header = '';
 409          $ob = array();
 410  
 411          foreach (explode("\n", $headers) as $val) {
 412              if ($decode) {
 413                  $val = MIME::decode($val);
 414              }
 415              if (preg_match("/^([^\s]+)\:(.*)/", $val, $matches)) {
 416                  $val = trim($matches[2]);
 417                  $header = $matches[1];
 418                  if (isset($ob[$header])) {
 419                      if (!is_array($ob[$header])) {
 420                          $temp = $ob[$header];
 421                          $ob[$header] = array();
 422                          $ob[$header][] = $temp;
 423                      }
 424                      $ob[$header][] = $val;
 425                      continue;
 426                  }
 427              } else {
 428                  $val = ' ' . trim($val);
 429              }
 430  
 431              if (!empty($header)) {
 432                  if (isset($ob[$header])) {
 433                      if (is_array($ob[$header])) {
 434                          end($ob[$header]);
 435                          $ob[$header][key($ob[$header])] .= $val;
 436                      } else {
 437                          $ob[$header] .= $val;
 438                      }
 439                  } else {
 440                      $ob[$header] = $val;
 441                  }
 442              }
 443          }
 444  
 445          return ($lowercase) ? array_change_key_case($ob, CASE_LOWER) : $ob;
 446      }
 447  
 448  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7