[ Index ]
 

Code source de Horde 3.1.3

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

title

Body

[fermer]

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

   1  <?php
   2  
   3  require_once  'Horde/String.php';
   4  require_once dirname(__FILE__) . '/../MIME.php';
   5  
   6  /**
   7   * The character(s) used internally for EOLs.
   8   */
   9  define('MIME_PART_EOL', "\n");
  10  
  11  /**
  12   * The character string designated by RFCs 822/2045 to designate EOLs in MIME
  13   * messages.
  14   */
  15  define('MIME_PART_RFC_EOL', "\r\n");
  16  
  17  /* Default MIME parameters. */
  18  
  19  /**
  20   * The default MIME character set.
  21   */
  22  define('MIME_DEFAULT_CHARSET', 'us-ascii');
  23  
  24  /**
  25   * The default MIME description.
  26   */
  27  define('MIME_DEFAULT_DESCRIPTION', _("unnamed"));
  28  
  29  /**
  30   * The default MIME disposition.
  31   */
  32  define('MIME_DEFAULT_DISPOSITION', 'inline');
  33  
  34  /**
  35   * The default MIME encoding.
  36   */
  37  define('MIME_DEFAULT_ENCODING', '7bit');
  38  
  39  /**
  40   * The MIME_Part:: class provides a wrapper around MIME parts and methods
  41   * for dealing with them.
  42   *
  43   * $Horde: framework/MIME/MIME/Part.php,v 1.177.4.20 2006/03/09 21:59:31 chuck Exp $
  44   *
  45   * Copyright 1999-2006 Chuck Hagenbuch <chuck@horde.org>
  46   * Copyright 2002-2006 Michael Slusarz <slusarz@bigworm.colorado.edu>
  47   *
  48   * See the enclosed file COPYING for license information (LGPL). If you
  49   * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  50   *
  51   * @author  Chuck Hagenbuch <chuck@horde.org>
  52   * @author  Michael Slusarz <slusarz@bigworm.colorado.edu>
  53   * @since   Horde 1.3
  54   * @package Horde_MIME
  55   */
  56  class MIME_Part {
  57  
  58      /**
  59       * The type (ex.: text) of this part.
  60       * Per RFC 2045, the default is 'application'.
  61       *
  62       * @var string
  63       */
  64      var $_type = 'application';
  65  
  66      /**
  67       * The subtype (ex.: plain) of this part.
  68       * Per RFC 2045, the default is 'octet-stream'.
  69       *
  70       * @var string
  71       */
  72      var $_subtype = 'octet-stream';
  73  
  74      /**
  75       * The body of the part.
  76       *
  77       * @var string
  78       */
  79      var $_contents = '';
  80  
  81      /**
  82       * The desired transfer encoding of this part.
  83       *
  84       * @var string
  85       */
  86      var $_transferEncoding = MIME_DEFAULT_ENCODING;
  87  
  88      /**
  89       * The current transfer encoding of the contents of this part.
  90       *
  91       * @var string
  92       */
  93      var $_currentEncoding = null;
  94  
  95      /**
  96       * Should the message be encoded via 7-bit?
  97       *
  98       * @var boolean
  99       */
 100      var $_encode7bit = true;
 101  
 102      /**
 103       * The description of this part.
 104       *
 105       * @var string
 106       */
 107      var $_description = '';
 108  
 109      /**
 110       * The disposition of this part (inline or attachment).
 111       *
 112       * @var string
 113       */
 114      var $_disposition = MIME_DEFAULT_DISPOSITION;
 115  
 116      /**
 117       * The disposition parameters of this part.
 118       *
 119       * @var array
 120       */
 121      var $_dispositionParameters = array();
 122  
 123      /**
 124       * The content type parameters of this part.
 125       *
 126       * @var array
 127       */
 128      var $_contentTypeParameters = array();
 129  
 130      /**
 131       * The subparts of this part.
 132       *
 133       * @var array
 134       */
 135      var $_parts = array();
 136  
 137      /**
 138       * Information/Statistics on the subpart.
 139       *
 140       * @var array
 141       */
 142      var $_information = array();
 143  
 144      /**
 145       * The list of CIDs for this part.
 146       *
 147       * @var array
 148       */
 149      var $_cids = array();
 150  
 151      /**
 152       * The MIME ID of this part.
 153       *
 154       * @var string
 155       */
 156      var $_mimeid = null;
 157  
 158      /**
 159       * The sequence to use as EOL for this part.
 160       * The default is currently to output the EOL sequence internally as
 161       * just "\n" instead of the canonical "\r\n" required in RFC 822 & 2045.
 162       * To be RFC complaint, the full <CR><LF> EOL combination should be used
 163       * when sending a message.
 164       * It is not crucial here since the PHP/PEAR mailing functions will handle
 165       * the EOL details.
 166       *
 167       * @var string
 168       */
 169      var $_eol = MIME_PART_EOL;
 170  
 171      /**
 172       * Internal class flags.
 173       *
 174       * @var array
 175       */
 176      var $_flags = array();
 177  
 178      /**
 179       * Part -> ID mapping cache.
 180       *
 181       * @var array
 182       */
 183      var $_idmap = array();
 184  
 185      /**
 186       * Unique MIME_Part boundary string.
 187       *
 188       * @var string
 189       */
 190      var $_boundary = null;
 191  
 192      /**
 193       * Default value for this Part's size.
 194       *
 195       * @var integer
 196       */
 197      var $_bytes = 0;
 198  
 199      /**
 200       * The content-ID for this part.
 201       *
 202       * @var string
 203       */
 204      var $_contentid = null;
 205  
 206      /**
 207       * MIME_Part constructor.
 208       *
 209       * @param string $mimetype     The content type of the part.
 210       * @param string $contents     The body of the part.
 211       * @param string $charset      The character set of the part.
 212       * @param string $disposition  The content disposition of the part.
 213       * @param string $encoding     The content encoding of the contents.
 214       */
 215      function MIME_Part($mimetype = null, $contents = null,
 216                         $charset = MIME_DEFAULT_CHARSET, $disposition = null,
 217                         $encoding = null)
 218      {
 219          /* Create the unique MIME_Part boundary string. */
 220          $this->_generateBoundary();
 221  
 222          /* The character set should always be set, even if we are dealing
 223           * with Content-Types other than text/*. */
 224          $this->setCharset($charset);
 225  
 226          if (!is_null($mimetype)) {
 227              $this->setType($mimetype);
 228          }
 229          if (!is_null($contents)) {
 230              $this->setContents($contents, $encoding);
 231          }
 232          if (!is_null($disposition)) {
 233              $this->setDisposition($disposition);
 234          }
 235      }
 236  
 237      /**
 238       * Set the content-disposition of this part.
 239       *
 240       * @param string $disposition  The content-disposition to set (inline or
 241       *                             attachment).
 242       */
 243      function setDisposition($disposition)
 244      {
 245          $disposition = String::lower($disposition);
 246  
 247          if (($disposition == 'inline') || ($disposition == 'attachment')) {
 248              $this->_disposition = $disposition;
 249          }
 250      }
 251  
 252      /**
 253       * Get the content-disposition of this part.
 254       *
 255       * @return string  The part's content-disposition.
 256       */
 257      function getDisposition()
 258      {
 259          return $this->_disposition;
 260      }
 261  
 262      /**
 263       * Set the name of this part.
 264       *
 265       * @param string $name The name to set.
 266       */
 267      function setName($name)
 268      {
 269          $this->setContentTypeParameter('name', $name);
 270      }
 271  
 272      /**
 273       * Get the name of this part.
 274       *
 275       * @param boolean $decode   MIME decode description?
 276       * @param boolean $default  If the name parameter doesn't exist, should we
 277       *                          use the default name from the description
 278       *                          parameter?
 279       *
 280       * @return string  The name of the part.
 281       */
 282      function getName($decode = false, $default = false)
 283      {
 284          $name = $this->getContentTypeParameter('name');
 285  
 286          if ($default && empty($name)) {
 287              $name = preg_replace('|\W|', '_', $this->getDescription(false, true));
 288          }
 289  
 290          if ($decode) {
 291              return trim(MIME::decode($name));
 292          } else {
 293              return $name;
 294          }
 295      }
 296  
 297      /**
 298       * Set the body contents of this part.
 299       *
 300       * @param string $contents  The part body.
 301       * @param string $encoding  The current encoding of the contents.
 302       */
 303      function setContents($contents, $encoding = null)
 304      {
 305          $this->_contents = $contents;
 306          $this->_flags['contentsSet'] = true;
 307          $this->_currentEncoding = (is_null($encoding)) ? $this->getCurrentEncoding() : MIME::encoding($encoding, MIME_STRING);
 308      }
 309  
 310      /**
 311       * Add to the body contents of this part.
 312       *
 313       * @param string $contents  The contents to append to the current part
 314       *                          body.
 315       * @param string $encoding  The current encoding of the contents. If not
 316       *                          specified, will try to auto determine the
 317       *                          encoding.
 318       */
 319      function appendContents($contents, $encoding = null)
 320      {
 321          $this->setContents($this->_contents . $contents, $encoding);
 322      }
 323  
 324      /**
 325       * Clears the body contents of this part.
 326       */
 327      function clearContents()
 328      {
 329          $this->_contents = '';
 330          $this->_flags['contentsSet'] = false;
 331          $this->_currentEncoding = null;
 332      }
 333  
 334      /**
 335       * Return the body of the part.
 336       *
 337       * @return string  The raw body of the part.
 338       */
 339      function getContents()
 340      {
 341          return $this->_contents;
 342      }
 343  
 344      /**
 345       * Returns the contents in strict RFC 822 & 2045 output - namely, all
 346       * newlines end with the canonical <CR><LF> sequence.
 347       *
 348       * @return string  The entire MIME part.
 349       */
 350      function getCanonicalContents()
 351      {
 352          return $this->replaceEOL($this->_contents, MIME_PART_RFC_EOL);
 353      }
 354  
 355      /**
 356       * Transfer encode the contents (to the transfer encoding identified via
 357       * getTransferEncoding()) and set as the part's new contents.
 358       */
 359      function transferEncodeContents()
 360      {
 361          $contents = $this->transferEncode();
 362          $this->_currentEncoding = $this->_flags['lastTransferEncode'];
 363          $this->setContents($contents, $this->_currentEncoding);
 364          $this->setTransferEncoding($this->_currentEncoding);
 365      }
 366  
 367      /**
 368       * Transfer decode the contents and set them as the new contents.
 369       */
 370      function transferDecodeContents()
 371      {
 372          $contents = $this->transferDecode();
 373          $this->_currentEncoding = $this->_flags['lastTransferDecode'];
 374          $this->setTransferEncoding($this->_currentEncoding);
 375  
 376          /* Don't set contents if they are empty, because this will do stuff
 377             like reset the internal bytes field, even though we shouldn't do
 378             that (the user has their reasons to set the bytes field to a
 379             non-zero value without putting the contents into this part. */
 380          if (strlen($contents)) {
 381              $this->setContents($contents, $this->_currentEncoding);
 382          }
 383      }
 384  
 385      /**
 386       * Set the mimetype of this part.
 387       *
 388       * @param string $mimetype  The mimetype to set (ex.: text/plain).
 389       */
 390      function setType($mimetype)
 391      {
 392          /* RFC 2045: Any entity with unrecognized encoding must be treated
 393             as if it has a Content-Type of "application/octet-stream"
 394             regardless of what the Content-Type field actually says. */
 395          if ($this->_transferEncoding == 'x-unknown') {
 396              return;
 397          }
 398  
 399          /* Set the 'setType' flag. */
 400          $this->_flags['setType'] = true;
 401  
 402          list($this->_type, $this->_subtype) = explode('/', String::lower($mimetype));
 403          if (($type = MIME::type($this->_type, MIME_STRING))) {
 404              $this->_type = $type;
 405  
 406              /* Set the boundary string for 'multipart/*' parts. */
 407              if ($type == 'multipart') {
 408                  if (!$this->getContentTypeParameter('boundary')) {
 409                      $this->setContentTypeParameter('boundary', $this->_generateBoundary());
 410                  }
 411              } else {
 412                  $this->clearContentTypeParameter('boundary');
 413              }
 414          } else {
 415              $this->_type = 'x-unknown';
 416              $this->clearContentTypeParameter('boundary');
 417          }
 418      }
 419  
 420       /**
 421        * Get the full MIME Content-Type of this part.
 422        *
 423        * @param boolean $charset  Append character set information to the end of
 424        *                          the content type if this is a text/* part.
 425        *
 426        * @return string  The mimetype of this part
 427        *                 (ex.: text/plain; charset=us-ascii).
 428        */
 429       function getType($charset = false)
 430       {
 431           if (!isset($this->_type) || !isset($this->_subtype)) {
 432               return false;
 433           }
 434           $ptype = $this->getPrimaryType();
 435           $type = $ptype . '/' . $this->getSubType();
 436           if ($charset && ($ptype == 'text')) {
 437               $type .= '; charset=' . $this->getCharset();
 438           }
 439           return $type;
 440       }
 441  
 442      /**
 443       * If the subtype of a MIME part is unrecognized by an application, the
 444       * default type should be used instead (See RFC 2046).  This method
 445       * returns the default subtype for a particular primary MIME Type.
 446       *
 447       * @return string  The default mimetype of this part (ex.: text/plain).
 448       */
 449      function getDefaultType()
 450      {
 451          switch ($this->getPrimaryType()) {
 452          case 'text':
 453              /* RFC 2046 (4.1.4): text parts default to text/plain. */
 454              return 'text/plain';
 455  
 456          case 'multipart':
 457              /* RFC 2046 (5.1.3): multipart parts default to multipart/mixed. */
 458              return 'multipart/mixed';
 459  
 460          default:
 461              /* RFC 2046 (4.2, 4.3, 4.4, 4.5.3, 5.2.4): all others default to
 462                 application/octet-stream. */
 463              return 'application/octet-stream';
 464          }
 465      }
 466  
 467      /**
 468       * Get the primary type of this part.
 469       *
 470       * @return string  The primary MIME type of this part.
 471       */
 472      function getPrimaryType()
 473      {
 474          return $this->_type;
 475      }
 476  
 477      /**
 478       * Get the subtype of this part.
 479       *
 480       * @return string  The MIME subtype of this part.
 481       */
 482      function getSubType()
 483      {
 484          return $this->_subtype;
 485      }
 486  
 487      /**
 488       * Set the character set of this part.
 489       *
 490       * @param string $charset  The character set of this part.
 491       */
 492      function setCharset($charset)
 493      {
 494          $this->setContentTypeParameter('charset', $charset);
 495      }
 496  
 497      /**
 498       * Get the character set to use for of this part.  Returns a charset for
 499       * all types (not just 'text/*') since we use this charset to determine
 500       * how to encode text in MIME headers.
 501       *
 502       * @return string  The character set of this part.  Returns null if there
 503       *                 is no character set.
 504       */
 505      function getCharset()
 506      {
 507          $charset = $this->getContentTypeParameter('charset');
 508          return (empty($charset)) ? null : $charset;
 509      }
 510  
 511      /**
 512       * Set the description of this part.
 513       *
 514       * @param string $description  The description of this part.
 515       */
 516      function setDescription($description)
 517      {
 518          $this->_description = MIME::encode($description, $this->getCharset());
 519      }
 520  
 521      /**
 522       * Get the description of this part.
 523       *
 524       * @param boolean $decode   MIME decode description?
 525       * @param boolean $default  If the name parameter doesn't exist, should we
 526       *                          use the default name from the description
 527       *                          parameter?
 528       *
 529       * @return string  The description of this part.
 530       */
 531      function getDescription($decode = false, $default = false)
 532      {
 533          $desc = $this->_description;
 534  
 535          if ($default && empty($desc)) {
 536              $desc = $this->getName();
 537              if (empty($desc)) {
 538                  $desc = MIME_DEFAULT_DESCRIPTION;
 539              }
 540          }
 541  
 542          if ($decode) {
 543              return MIME::decode($desc);
 544          } else {
 545              return $desc;
 546          }
 547      }
 548  
 549      /**
 550       * Set the transfer encoding to use for this part.
 551       *
 552       * @param string $encoding  The transfer encoding to use.
 553       */
 554      function setTransferEncoding($encoding)
 555      {
 556          if (($mime_encoding = MIME::encoding($encoding, MIME_STRING))) {
 557              $this->_transferEncoding = $mime_encoding;
 558          } else {
 559              /* RFC 2045: Any entity with unrecognized encoding must be treated
 560                 as if it has a Content-Type of "application/octet-stream"
 561                 regardless of what the Content-Type field actually says. */
 562              $this->setType('application/octet-stream');
 563              $this->_transferEncoding = 'x-unknown';
 564          }
 565      }
 566  
 567      /**
 568       * Add a MIME subpart.
 569       *
 570       * @param MIME_Part $mime_part  Add a MIME_Part subpart to the current
 571       *                              MIME_Part.
 572       * @param string $index         The index of the added MIME_Part.
 573       */
 574      function addPart($mime_part, $index = null)
 575      {
 576          /* Add the part to the parts list. */
 577          if (is_null($index)) {
 578              end($this->_parts);
 579              $id = key($this->_parts) + 1;
 580              $ptr = &$this->_parts;
 581          } else {
 582              $ptr = &$this->_partFind($index, $this->_parts, true);
 583              if (($pos = strrpos($index, '.'))) {
 584                  $id = substr($index, $pos + 1);
 585              } else {
 586                  $id = $index;
 587              }
 588          }
 589  
 590          /* Set the MIME ID if it has not already been set. */
 591          if ($mime_part->getMIMEId() === null) {
 592              $mime_part->setMIMEId($id);
 593          }
 594  
 595          /* Store the part now. */
 596          $ptr[$id] = $mime_part;
 597  
 598          /* Clear the ID -> Part mapping cache. */
 599          $this->_idmap = array();
 600      }
 601  
 602      /**
 603       * Get a list of all MIME subparts.
 604       *
 605       * @return array  An array of the MIME_Part subparts.
 606       */
 607      function getParts()
 608      {
 609          return $this->_parts;
 610      }
 611  
 612      /**
 613       * Retrieve a specific MIME part.
 614       *
 615       * @param string $id  The MIME_Part ID string.
 616       *
 617       * @return MIME_Part  The MIME_Part requested, or false if the part
 618       *                    doesn't exist.
 619       */
 620      function getPart($id)
 621      {
 622          $mimeid = $this->getMIMEId();
 623  
 624          /* This will convert '#.0' to simply '#', which is how the part is
 625           * internally stored. */
 626          $search_id = $id;
 627          if (($str = strrchr($id, '.')) &&
 628              ($str == '.0')) {
 629              $search_id = substr($search_id, 0, -2);
 630          }
 631  
 632          /* Return this part if:
 633             1) There is only one part (e.g. the MIME ID is 0, or the
 634                MIME ID is 1 and there are no subparts.
 635             2) $id matches this parts MIME ID. */
 636          if (($search_id == 0) ||
 637              (($search_id == 1) && !count($this->_parts)) ||
 638              (!empty($mimeid) && ($search_id == $mimeid))) {
 639              $part = $this;
 640          } else {
 641              $part = $this->_partFind($id, $this->_parts);
 642          }
 643  
 644          if ($part &&
 645              ($search_id != $id) &&
 646              ($part->getType() == 'message/rfc822')) {
 647              $ret_part = Util::cloneObject($part);
 648              $ret_part->_parts = array();
 649              return $ret_part;
 650          }
 651  
 652          return $part;
 653      }
 654  
 655      /**
 656       * Remove a MIME_Part subpart.
 657       *
 658       * @param string $id  The MIME Part to delete.
 659       */
 660      function removePart($id)
 661      {
 662          if (($ptr = &$this->_partFind($id, $this->_parts))) {
 663              unset($ptr);
 664              $this->_idmap = array();
 665          }
 666      }
 667  
 668      /**
 669       * Alter a current MIME subpart.
 670       *
 671       * @param string $id            The MIME Part ID to alter.
 672       * @param MIME_Part $mime_part  The MIME Part to store.
 673       */
 674      function alterPart($id, $mime_part)
 675      {
 676          if (($ptr = &$this->_partFind($id, $this->_parts))) {
 677              $ptr = $mime_part;
 678              $this->_idmap = array();
 679          }
 680      }
 681  
 682      /**
 683       * Function used to find a specific MIME Part by ID.
 684       *
 685       * @access private
 686       *
 687       * @param string $id         The MIME_Part ID string.
 688       * @param array &$parts      A list of MIME_Part objects.
 689       * @param boolean $retarray  Return a pointer to the array that stores
 690       *                           (would store) the part rather than the part
 691       *                           itself?
 692       */
 693      function &_partFind($id, &$parts, $retarray = false)
 694      {
 695          /* Pointers don't persist through sessions; therefore, we must make
 696           * sure that the IdMap is destroyed at the end of each request.
 697           * How can we do this? We check to see if $_idmap contains an array
 698           * of MIME_Parts or an array of arrays. */
 699          $check = reset($this->_idmap);
 700          if (empty($check) || !is_a($check, 'MIME_Part')) {
 701              $this->_idmap = array();
 702              $this->_generateIdMap($this->_parts);
 703          }
 704  
 705          if ($retarray) {
 706              if ($pos = strrpos($id, '.')) {
 707                  $id = substr($id, 0, $pos);
 708              } else {
 709                  return $parts;
 710              }
 711          }
 712  
 713          if (isset($this->_idmap[$id])) {
 714              return $this->_idmap[$id];
 715          } else {
 716              $part = false;
 717              return $part;
 718          }
 719      }
 720  
 721      /**
 722       * Generates a mapping of MIME_Parts with their MIME IDs.
 723       *
 724       * @access private
 725       *
 726       * @param array &$parts  An array of MIME_Parts to map.
 727       */
 728      function _generateIdMap(&$parts)
 729      {
 730          if (!empty($parts)) {
 731              foreach (array_keys($parts) as $key) {
 732                  $ptr = &$parts[$key];
 733                  $this->_idmap[$ptr->getMIMEId()] = &$ptr;
 734                  $this->_generateIdMap($ptr->_parts);
 735              }
 736          }
 737      }
 738  
 739      /**
 740       * Add information about the MIME_Part.
 741       *
 742       * @param string $label  The information label.
 743       * @param mixed $data    The information to store.
 744       */
 745      function setInformation($label, $data)
 746      {
 747          $this->_information[$label] = $data;
 748      }
 749  
 750      /**
 751       * Retrieve information about the MIME_Part.
 752       *
 753       * @param string $label  The information label.
 754       *
 755       * @return mixed  The information requested.
 756       *                Returns false if $label is not set.
 757       */
 758      function getInformation($label)
 759      {
 760          return (isset($this->_information[$label])) ? $this->_information[$label] : false;
 761      }
 762  
 763      /**
 764       * Add a disposition parameter to this part.
 765       *
 766       * @param string $label  The disposition parameter label.
 767       * @param string $data   The disposition parameter data.
 768       */
 769      function setDispositionParameter($label, $data)
 770      {
 771          $this->_dispositionParameters[$label] = $data;
 772      }
 773  
 774      /**
 775       * Get a disposition parameter from this part.
 776       *
 777       * @param string $label  The disposition parameter label.
 778       *
 779       * @return string  The data requested.
 780       *                 Returns false if $label is not set.
 781       */
 782      function getDispositionParameter($label)
 783      {
 784          return (isset($this->_dispositionParameters[$label])) ? $this->_dispositionParameters[$label] : false;
 785      }
 786  
 787      /**
 788       * Get all parameters from the Content-Disposition header.
 789       *
 790       * @return array  An array of all the parameters
 791       *                Returns the empty array if no parameters set.
 792       */
 793      function getAllDispositionParameters()
 794      {
 795          return $this->_dispositionParameters;
 796      }
 797  
 798      /**
 799       * Add a content type parameter to this part.
 800       *
 801       * @param string $label  The disposition parameter label.
 802       * @param string $data   The disposition parameter data.
 803       */
 804      function setContentTypeParameter($label, $data)
 805      {
 806          $this->_contentTypeParameters[$label] = $data;
 807      }
 808  
 809      /**
 810       * Clears a content type parameter from this part.
 811       *
 812       * @param string $label  The disposition parameter label.
 813       * @param string $data   The disposition parameter data.
 814       */
 815      function clearContentTypeParameter($label)
 816      {
 817          unset($this->_contentTypeParameters[$label]);
 818      }
 819  
 820      /**
 821       * Get a content type parameter from this part.
 822       *
 823       * @param string $label  The content type parameter label.
 824       *
 825       * @return string  The data requested.
 826       *                 Returns false if $label is not set.
 827       */
 828      function getContentTypeParameter($label)
 829      {
 830          return (isset($this->_contentTypeParameters[$label])) ? $this->_contentTypeParameters[$label] : false;
 831      }
 832  
 833      /**
 834       * Get all parameters from the Content-Type header.
 835       *
 836       * @return array  An array of all the parameters
 837       *                Returns the empty array if no parameters set.
 838       */
 839      function getAllContentTypeParameters()
 840      {
 841          return $this->_contentTypeParameters;
 842      }
 843  
 844      /**
 845       * Sets a new string to use for EOLs.
 846       *
 847       * @param string $eol  The string to use for EOLs.
 848       */
 849      function setEOL($eol)
 850      {
 851          $this->_eol = $eol;
 852      }
 853  
 854      /**
 855       * Get the string to use for EOLs.
 856       *
 857       * @return string  The string to use for EOLs.
 858       */
 859      function getEOL()
 860      {
 861          return $this->_eol;
 862      }
 863  
 864      /**
 865       * Add the appropriate MIME headers for this part to an existing array.
 866       *
 867       * @param array $headers  An array of any other headers for the part.
 868       *
 869       * @return array  The headers, with the MIME headers added.
 870       */
 871      function header($headers = array())
 872      {
 873          $eol = $this->getEOL();
 874          $ptype = $this->getPrimaryType();
 875          $stype = $this->getSubType();
 876  
 877          /* Get the character set for this part. */
 878          $charset = $this->getCharset();
 879  
 880          /* Get the Content-Type - this is ALWAYS required. */
 881          $ctype = $this->getType(true);
 882          foreach ($this->getAllContentTypeParameters() as $key => $value) {
 883              /* Skip the charset key since that would have already been
 884               * added to $ctype by getType(). */
 885              if ($key == 'charset') {
 886                  continue;
 887              }
 888              $ctype .= '; ' . $key . '="' . str_replace('"', '\"', MIME::encode($value, $charset)) . '"';
 889          }
 890          $headers['Content-Type'] = MIME::wrapHeaders('Content-Type', $ctype, $eol);
 891  
 892          /* Get the description, if any. */
 893          if (($descrip = $this->getDescription())) {
 894              $headers['Content-Description'] = MIME::wrapHeaders('Content-Description', MIME::encode($descrip, $charset), $eol);
 895          }
 896  
 897          /* RFC 2045 [4] - message/rfc822 and message/partial require the
 898             MIME-Version header only if they themselves claim to be MIME
 899             compliant. */
 900          if (($ptype == 'message') &&
 901              (($stype == 'rfc822') || ($stype == 'partial')) &&
 902              (strpos($this->_contents, 'MIME-Version: 1.0') !== false)) {
 903              $headers['MIME-Version'] = '1.0';
 904          }
 905  
 906          /* message/* parts require no additional header information. */
 907          if ($ptype == 'message') {
 908              return $headers;
 909          }
 910  
 911          /* Don't show Content-Disposition for multipart messages unless
 912             there is a name parameter. */
 913          $name = $this->getName();
 914          if (($ptype != 'multipart') || !empty($name)) {
 915              $disp = $this->getDisposition();
 916  
 917              /* Add any disposition parameter information, if available. */
 918              if (!empty($name)) {
 919                  $disp .= '; ' . 'filename="' . MIME::encode($name, $charset) . '"';
 920              }
 921  
 922              $headers['Content-Disposition'] = MIME::wrapHeaders('Content-Disposition', $disp, $eol);
 923          }
 924  
 925          /* Add transfer encoding information. */
 926          $headers['Content-Transfer-Encoding'] = $this->getTransferEncoding();
 927  
 928          /* Add content ID information. */
 929          if (!is_null($this->_contentid)) {
 930              $headers['Content-ID'] = $this->_contentid;
 931          }
 932  
 933          return $headers;
 934      }
 935  
 936      /**
 937       * Return the entire part in MIME format. Includes headers on request.
 938       *
 939       * @param boolean $headers  Include the MIME headers?
 940       *
 941       * @return string  The MIME string.
 942       */
 943      function toString($headers = true)
 944      {
 945          $eol = $this->getEOL();
 946          $ptype = $this->getPrimaryType();
 947  
 948          if ($headers) {
 949              $text = '';
 950              foreach ($this->header() as $key => $val) {
 951                  $text .= $key . ': ' . $val . $eol;
 952              }
 953              $text .= $eol;
 954          }
 955  
 956          /* Any information about a message/* is embedded in the message
 957             contents themself. Simply output the contents of the part
 958             directly and return. */
 959          if ($ptype == 'message') {
 960              if (isset($text)) {
 961                  return $text . $this->_contents;
 962              } else {
 963                  return $this->_contents;
 964              }
 965          }
 966  
 967          if (isset($text)) {
 968              $text .= $this->transferEncode();
 969          } else {
 970              $text = $this->transferEncode();
 971          }
 972  
 973          /* Deal with multipart messages. */
 974          if ($ptype == 'multipart') {
 975              $boundary = trim($this->getContentTypeParameter('boundary'), '"');
 976              if (!strlen($this->_contents)) {
 977                  $text .= 'This message is in MIME format.' . $eol;
 978              }
 979              foreach ($this->getParts() as $part) {
 980                  $text .= $eol . '--' . $boundary . $eol;
 981                  $oldEOL = $part->getEOL();
 982                  $part->setEOL($eol);
 983                  $text .= $part->toString(true);
 984                  $part->setEOL($oldEOL);
 985              }
 986              $text .= $eol . '--' . $boundary . '--' . $eol;
 987          }
 988  
 989          return $text;
 990      }
 991  
 992      /**
 993       * Returns the encoded part in strict RFC 822 & 2045 output - namely, all
 994       * newlines end with the canonical <CR><LF> sequence.
 995       *
 996       * @param boolean $headers  Include the MIME headers?
 997       *
 998       * @return string  The entire MIME part.
 999       */
1000      function toCanonicalString($headers = true)
1001      {
1002          $string = $this->toString($headers);
1003          return $this->replaceEOL($string, MIME_PART_RFC_EOL);
1004      }
1005  
1006      /**
1007       * Should we make sure the message is encoded via 7-bit (e.g. to adhere
1008       * to mail delivery standards such as RFC 2821)?
1009       *
1010       * @param boolean $use7bit  Use 7-bit encoding?
1011       */
1012      function strict7bit($use7bit)
1013      {
1014          $this->_encode7bit = $use7bit;
1015      }
1016  
1017      /**
1018       * Get the transfer encoding for the part based on the user requested
1019       * transfer encoding and the current contents of the part.
1020       *
1021       * @return string  The transfer-encoding of this part.
1022       */
1023      function getTransferEncoding()
1024      {
1025          $encoding = $this->_transferEncoding;
1026          $ptype = $this->getPrimaryType();
1027          $text = str_replace($this->getEOL(), ' ', $this->_contents);
1028  
1029          /* If there are no contents, return whatever the current value of
1030             $_transferEncoding is. */
1031          if (empty($text)) {
1032              return $encoding;
1033          }
1034  
1035          switch ($ptype) {
1036          case 'message':
1037              /* RFC 2046 [5.2.1] - message/rfc822 messages only allow 7bit,
1038                 8bit, and binary encodings. If the current encoding is either
1039                 base64 or q-p, switch it to 8bit instead.
1040                 RFC 2046 [5.2.2, 5.2.3, 5.2.4] - All other message/* messages
1041                 only allow 7bit encodings. */
1042              $encoding = ($this->getSubType() == 'rfc822') ? '8bit' : '7bit';
1043              break;
1044  
1045          case 'text':
1046              if (MIME::is8bit($text)) {
1047                  $encoding = ($this->_encode7bit) ? 'quoted-printable' : '8bit';
1048              } elseif (preg_match("/(?:\n|^)[^\n]{999,}(?:\n|$)/", $text)) {
1049                  /* If the text is longer than 998 characters between
1050                   * linebreaks, use quoted-printable encoding to ensure the
1051                   * text will not be chopped (i.e. by sendmail if being sent
1052                   * as mail text). */
1053                  $encoding = 'quoted-printable';
1054              }
1055              break;
1056  
1057          default:
1058              if (MIME::is8bit($text)) {
1059                  $encoding = ($this->_encode7bit) ? 'base64' : '8bit';
1060              }
1061              break;
1062          }
1063  
1064          /* Need to do one last check for binary data if encoding is 7bit or
1065           * 8bit.  If the message contains a NULL character at all, the message
1066           * MUST be in binary format. RFC 2046 [2.7, 2.8, 2.9]. Q-P and base64
1067           * can handle binary data fine so no need to switch those encodings. */
1068          if ((($encoding == '8bit') || ($encoding == '7bit')) &&
1069              preg_match('/\x00/', $text)) {
1070              $encoding = ($this->_encode7bit) ? 'base64' : 'binary';
1071          }
1072  
1073          return $encoding;
1074      }
1075  
1076      /**
1077       * Retrieves the current encoding of the contents in the object.
1078       *
1079       * @return string  The current encoding.
1080       */
1081      function getCurrentEncoding()
1082      {
1083          return (is_null($this->_currentEncoding)) ? $this->_transferEncoding : $this->_currentEncoding;
1084      }
1085  
1086      /**
1087       * Encodes the contents with the part's transfer encoding.
1088       *
1089       * @return string  The encoded text.
1090       */
1091      function transferEncode()
1092      {
1093          $encoding = $this->getTransferEncoding();
1094          $eol = $this->getEOL();
1095  
1096          /* Set the 'lastTransferEncode' flag so that transferEncodeContents()
1097             can save a call to getTransferEncoding(). */
1098          $this->_flags['lastTransferEncode'] = $encoding;
1099  
1100          /* If contents are empty, or contents are already encoded to the
1101             correct encoding, return now. */
1102          if (!strlen($this->_contents) ||
1103              ($encoding == $this->_currentEncoding)) {
1104              return $this->_contents;
1105          }
1106  
1107          switch ($encoding) {
1108          /* Base64 Encoding: See RFC 2045, section 6.8 */
1109          case 'base64':
1110              /* Keeping these two lines separate seems to use much less
1111                 memory than combining them (as of PHP 4.3). */
1112              $encoded_contents = base64_encode($this->_contents);
1113              return chunk_split($encoded_contents, 76, $eol);
1114  
1115          /* Quoted-Printable Encoding: See RFC 2045, section 6.7 */
1116          case 'quoted-printable':
1117              $output = MIME::quotedPrintableEncode($this->_contents, $eol);
1118              if (($eollength = String::length($eol))) {
1119                  return substr($output, 0, $eollength * -1);
1120              } else {
1121                  return $output;
1122              }
1123  
1124          default:
1125              return $this->replaceEOL($this->_contents);
1126          }
1127      }
1128  
1129      /**
1130       * Decodes the contents of the part to either a 7bit or 8bit encoding.
1131       *
1132       * @return string  The decoded text.
1133       *                 Returns the empty string if there is no text to decode.
1134       */
1135      function transferDecode()
1136      {
1137          $encoding = $this->getCurrentEncoding();
1138  
1139          /* If the contents are empty, return now. */
1140          if (!strlen($this->_contents)) {
1141              $this->_flags['lastTransferDecode'] = $encoding;
1142              return $this->_contents;
1143          }
1144  
1145          switch ($encoding) {
1146          case 'base64':
1147              $message = base64_decode($this->_contents);
1148              $this->_flags['lastTransferDecode'] = '8bit';
1149              break;
1150  
1151          case 'quoted-printable':
1152              $message = preg_replace("/=\r?\n/", '', $this->_contents);
1153              $message = $this->replaceEOL($message);
1154              $message = quoted_printable_decode($message);
1155              $this->_flags['lastTransferDecode'] = (MIME::is8bit($message)) ? '8bit' : '7bit';
1156              break;
1157  
1158          /* Support for uuencoded encoding - although not required by RFCs,
1159             some mailers may still encode this way. */
1160          case 'uuencode':
1161          case 'x-uuencode':
1162          case 'x-uue':
1163              if (function_exists('convert_uudecode')) {
1164                  $message = convert_uuencode($this->_contents);
1165              } else {
1166                  require_once 'Mail/mimeDecode.php';
1167                  $files = &Mail_mimeDecode::uudecode($this->_contents);
1168                  $message = $files[0]['filedata'];
1169              }
1170              require_once 'Mail/mimeDecode.php';
1171              $files = &Mail_mimeDecode::uudecode($this->_contents);
1172              $message = $files[0]['filedata'];
1173              $this->_flags['lastTransferDecode'] = '8bit';
1174              break;
1175  
1176          default:
1177              if (isset($this->_flags['lastTransferDecode']) &&
1178                  ($this->_flags['lastTransferDecode'] != $encoding)) {
1179                  $message = $this->replaceEOL($this->_contents);
1180              } else {
1181                  $message = $this->_contents;
1182              }
1183              $this->_flags['lastTransferDecode'] = $encoding;
1184              break;
1185          }
1186  
1187          return $message;
1188      }
1189  
1190      /**
1191       * Split the contents of the current Part into its respective subparts,
1192       * if it is multipart MIME encoding. Unlike the imap_*() functions, this
1193       * will preserve all MIME header information.
1194       *
1195       * The boundary content-type parameter must be set for this function to
1196       * work correctly.
1197       *
1198       * @return boolean  True if the contents were successfully split.
1199       *                  False if any error occurred.
1200       */
1201      function splitContents()
1202      {
1203          if (!($boundary = $this->getContentTypeParameter('boundary'))) {
1204              return false;
1205          }
1206  
1207          if (!strlen($this->_contents)) {
1208              return false;
1209          }
1210  
1211          $eol = $this->getEOL();
1212          $retvalue = false;
1213  
1214          foreach (explode($eol, $this->_contents) as $line) {
1215              $pos = strpos($line, '--' . $boundary);
1216              if (($pos === false) && isset($part_ptr)) {
1217                  $data[] = $line;
1218              } elseif ($pos === 0) {
1219                  $retvalue = true;
1220                  if (isset($part_ptr)) {
1221                      $this->_parts[$part_ptr]->setContents(implode($eol, $data));
1222                      $this->_parts[$part_ptr]->splitContents();
1223                      next($this->_parts);
1224                  } else {
1225                      reset($this->_parts);
1226                  }
1227                  if (isset($data)) {
1228                      unset($data);
1229                  }
1230                  $data = array();
1231                  $part_ptr = key($this->_parts);
1232              }
1233          }
1234  
1235          return $retvalue;
1236      }
1237  
1238      /**
1239       * Replace newlines in this part's contents with those specified by either
1240       * the given newline sequence or the part's current EOL setting.
1241       *
1242       * @param string $text  The text to replace.
1243       * @param string $eol   The EOL sequence to use. If not present, uses the
1244       *                      part's current EOL setting.
1245       *
1246       * @return string  The text with the newlines replaced by the desired
1247       *                 newline sequence.
1248       */
1249      function replaceEOL($text, $eol = null)
1250      {
1251          if (is_null($eol)) {
1252              $eol = $this->getEOL();
1253          }
1254          return preg_replace("/\r?\n/", $eol, $text);
1255      }
1256  
1257      /**
1258       * Return the unique MIME_Part boundary string generated for this object.
1259       * This may not be the boundary string used when building the message
1260       * since a user defined 'boundary' Content-Type parameter will override
1261       * this value.
1262       *
1263       * @return string  The unique boundary string.
1264       */
1265      function getUniqueID()
1266      {
1267          return $this->_boundary;
1268      }
1269  
1270      /**
1271       * Determine the size of a MIME_Part and its child members.
1272       *
1273       * @return integer  Size of the MIME_Part, in bytes.
1274       */
1275      function getBytes()
1276      {
1277          $bytes = 0;
1278  
1279          if (empty($this->_flags['contentsSet']) && $this->_bytes) {
1280              $bytes = $this->_bytes;
1281          } elseif ($this->getPrimaryType() == 'multipart') {
1282              foreach ($this->getParts() as $part) {
1283                  /* Skip multipart entries (since this may result in double
1284                     counting). */
1285                  if ($part->getPrimaryType() != 'multipart') {
1286                      $bytes += $part->getBytes();
1287                  }
1288              }
1289          } else {
1290              if ($this->getPrimaryType() == 'text') {
1291                  $bytes = String::length($this->_contents, $this->getCharset());
1292              } else {
1293                  $bytes = strlen($this->_contents);
1294              }
1295          }
1296  
1297          return $bytes;
1298      }
1299  
1300      /**
1301       * Explicitly set the size (in bytes) of this part. This value will only
1302       * be returned (via getBytes()) if there are no contents currently set.
1303       * This function is useful for setting the size of the part when the
1304       * contents of the part are not fully loaded (i.e. creating a MIME_Part
1305       * object from IMAP header information without loading the data of the
1306       * part).
1307       *
1308       * @param integer $bytes  The size of this part in bytes.
1309       */
1310      function setBytes($bytes)
1311      {
1312          $this->_bytes = $bytes;
1313      }
1314  
1315      /**
1316       * Output the size of this MIME_Part in KB.
1317       *
1318       * @return string  Size of the MIME_Part, in string format.
1319       */
1320      function getSize()
1321      {
1322          $bytes = $this->getBytes();
1323          if (empty($bytes)) {
1324              return $bytes;
1325          }
1326  
1327          $localeinfo = NLS::getLocaleInfo();
1328          return number_format($bytes / 1024, 2, $localeinfo['decimal_point'], $localeinfo['thousands_sep']);
1329       }
1330  
1331      /**
1332       * Add to the list of CIDs for this part.
1333       *
1334       * @param array $cids  A list of MIME IDs of the part.
1335       *                     Key - MIME ID
1336       *                     Value - CID for the part
1337       */
1338      function addCID($cids = array())
1339      {
1340          $this->_cids += $cids;
1341      }
1342  
1343      /**
1344       * Returns the list of CIDs for this part.
1345       *
1346       * @return array  The list of CIDs for this part.
1347       */
1348      function getCIDList()
1349      {
1350          asort($this->_cids, SORT_STRING);
1351          return $this->_cids;
1352      }
1353  
1354      /**
1355       * Sets the Content-ID header for this part.
1356       *
1357       * @param string $cid  Use this CID (if not already set).  Else, generate a
1358       *                     random CID.
1359       */
1360      function setContentID($cid = null)
1361      {
1362          if (is_null($this->_contentid)) {
1363              $this->_contentid = (is_null($cid)) ? (base_convert(microtime(), 10, 36) . '@' . $_SERVER['SERVER_NAME']) : $cid;
1364          }
1365          return $this->_contentid;
1366      }
1367  
1368      /**
1369       * Returns the Content-ID for this part.
1370       *
1371       * @return string  The Content-ID for this part.
1372       */
1373      function getContentID()
1374      {
1375          return $this->_contentid;
1376      }
1377  
1378      /**
1379       * Alter the MIME ID of this part.
1380       *
1381       * @param string $mimeid  The MIME ID.
1382       */
1383      function setMIMEId($mimeid)
1384      {
1385          $this->_mimeid = $mimeid;
1386      }
1387  
1388      /**
1389       * Returns the MIME ID of this part.
1390       *
1391       * @return string  The MIME ID.
1392       */
1393      function getMIMEId()
1394      {
1395          return $this->_mimeid;
1396      }
1397  
1398      /**
1399       * Returns the relative MIME ID of this part.
1400       * e.g., if the base part has MIME ID of 2, and you want the first
1401       * subpart of the base part, the relative MIME ID is 2.1.
1402       *
1403       * @param string $id  The relative part ID.
1404       *
1405       * @return string  The relative MIME ID.
1406       */
1407      function getRelativeMIMEId($id)
1408      {
1409          $rel = $this->getMIMEId();
1410          return (empty($rel)) ? $id : $rel . '.' . $id;
1411      }
1412  
1413      /**
1414       * Returns a mapping of all MIME IDs to their content-types.
1415       *
1416       * @return array  KEY: MIME ID, VALUE: Content type
1417       */
1418      function contentTypeMap()
1419      {
1420          $map = array($this->getMIMEId() => $this->getType());
1421          foreach ($this->_parts as $val) {
1422              $map += $val->contentTypeMap();
1423          }
1424          return $map;
1425      }
1426  
1427      /**
1428       * Generate the unique boundary string (if not already done).
1429       *
1430       * @access private
1431       *
1432       * @return string  The boundary string.
1433       */
1434      function _generateBoundary()
1435      {
1436          if (is_null($this->_boundary)) {
1437              $this->_boundary = '=_' . base_convert(microtime(), 10, 36);
1438          }
1439          return $this->_boundary;
1440      }
1441  
1442  }


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