Mail_IMAP
[ class tree: Mail_IMAP ] [ index: Mail_IMAP ] [ all elements ]

Source for file IMAP.php

Documentation is available at IMAP.php

  1. <?php
  2.  
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/3_0.txt                                   |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Richard York <rich_y@php.net>                                |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id
  20.  
  21. require_once 'PEAR.php';
  22.  
  23. // {{{ constants
  24. // {{{ Mail_IMAP::connect action options
  25. define('MAIL_IMAP_GET_INFO',        5);
  26. define('MAIL_IMAP_NO_INFO',         6);
  27. // }}}
  28. // {{{ Mail_IMAP::getBody action options
  29. define('MAIL_IMAP_BODY',            0);
  30. define('MAIL_IMAP_LITERAL',         1);
  31. define('MAIL_IMAP_LITERAL_DECODE',  2);
  32. // }}}
  33. // {{{ Mail_IMAP::setFlags action options
  34. define('MAIL_IMAP_SET_FLAGS',       3);
  35. define('MAIL_IMAP_CLEAR_FLAGS',     4);
  36. // }}}
  37. // {{{ Mail_IMAP::Mail_IMAP error reporting options
  38. define('MAIL_IMAP_E_DEBUG',         100);
  39. // }}}
  40. // }}}
  41.  
  42. /**
  43. * <p>Mail_IMAP provides a simplified backend for working with the c-client (IMAP) extension.
  44. * It serves as an OO wrapper for commonly used c-client functions.
  45. * It provides structure and header parsing as well as body retrieval.</p>
  46. * <p>This package requires the c-client extension.  To download the latest version of
  47. * the c-client extension goto: http://www.php.net/imap.</p>
  48. *
  49. * <b>PEAR PREREQUISITES:</p>
  50. *   <ul>
  51. *       <li>Net_URL (Required if you will be using a URI abstraction to connect.)</li>
  52. *   </ul>
  53. *
  54. * <b>Known Bugs:</b>
  55. *   <p>Potential bugs may arise from the detection of certain multipart/* messages.
  56. *   Application parses and adjusts for anomalies in multipart/mixed,
  57. *   multipart/related and multipart/alternative messages.  Bugs may arise from
  58. *   untested and unincluded multipart message types, multipart/parallel,
  59. *   multipart/report, multipart/signed and multipart/digest.</p>
  60. *   <p>Have been told about a float conversion when passing a pid like 2.10 to
  61. *   array_search, have not yet reproduced.</p>
  62. *   <p>CID handling is not tested or yet perfected, some bugs may rise up there.</p>
  63. *
  64. * <b>What to do when a message bombs on Mail_IMAP:</b>
  65. * <ol>
  66. *   <li>File a bug report at http://pear.php.net/bugs</li>
  67. *   <li>Mail a copy of the message preserving the structure as you now see it
  68. *       e.g. don't send as an attachment of another message to
  69. *       demo@smilingsouls.net.</li>
  70. *   <li>Include "Mail_IMAP", the MIME type and a short summary of what's wrong in
  71. *       the subject line, for instance if bombing on a multipart/related message,
  72. *       include that MIME type, if you aren't sure what MIME type the message is,
  73. *       don't worry about it :). Altering the subject line is important, otherwise
  74. *       I may think the message is spam and delete it.</li>
  75. * </ol>
  76. *
  77. * <b>Having trouble finding the example files?</b>
  78. *   Examples are located in the PEAR install directory under /docs/Mail_IMAP/examples
  79. *
  80. * <b>Extended documentation available at:</b>
  81. *   http://www.spicypeanut.net
  82. *
  83. * <b>The following URL will *sometimes* have a more recent version of IMAP.php than PEAR:</b>
  84. *   <p>http://www.spicypeanut.net/index.html?content=373
  85. *   This is where I post my working copy of Mail_IMAP between releases, use at your
  86. *   own risk (any API changes made there may not make it into the official release).</p>
  87. *
  88. @author       Richard York <rich_y@php.net>
  89. @category     Mail
  90. @package      Mail_IMAP
  91. @license      PHP
  92. @version      1.1.0
  93. @copyright    (c) Copyright 2004, Richard York, All Rights Reserved.
  94. @since        PHP 4.2.0
  95. *
  96. @example      examples/IMAP.inbox.php
  97. *    Mail_IMAP Inbox
  98. *
  99. @example      examples/IMAP.message.php
  100. *    Mail_IMAP Message
  101. *
  102. @example      examples/IMAP.connection_wizard.php
  103. *    Mail_IMAP Connection Wizard
  104. *
  105. @example      examples/IMAP.connection_wizard_example.php
  106. *    Mail_IMAP Connection Wizard
  107. *
  108. @todo imap_mail_copy
  109. @todo imap_mail_move
  110. */
  111.  
  112. // {{{ class Mail_IMAP
  113. class Mail_IMAP {
  114.  
  115.     // {{{ properties
  116.     /**
  117.      * Contains the imap resource stream.
  118.      * @var     resource $mailbox 
  119.      * @access  public
  120.      */
  121.     var $mailbox;
  122.  
  123.     /**
  124.      * Contains information about the current mailbox.
  125.      * @var     array $mailboxInfo 
  126.      * @access  public
  127.      */
  128.     var $mailboxInfo;
  129.  
  130.     /**
  131.      * Set flags for various imap_* functions.
  132.      *
  133.      * Use associative indices to indicate the imap_* function to set flags for,
  134.      *  create the indice omitting the 'imap_' portion of the function name.
  135.      *  see: Mail_IMAP::setOptions for more information.
  136.      *
  137.      * @var     array $option 
  138.      * @access  public
  139.      */
  140.     var $option;
  141.  
  142.     /**
  143.      * (string) contains the various possible data types.
  144.      * @var     array $_dataTypes 
  145.      * @access  private
  146.      */
  147.     var $_dataTypes = array('text''multipart''message''application''audio''image''video''other');
  148.  
  149.     /**
  150.      * (string) Contains the various possible encoding types.
  151.      * @var     array $_encodingTypes 
  152.      * @access  private
  153.      */
  154.     var $_encodingTypes = array('7bit''8bit''binary''base64''quoted-printable''other');
  155.  
  156.     // --------------------------ALL MESSAGE PARTS-----------------------------
  157.     /**
  158.      * (object) Contains the object returned by {@link imap_fetchstructure}.
  159.      * @var     array $_structure 
  160.      * @access  private
  161.      */
  162.     var $_structure;
  163.  
  164.     /**
  165.      * (str) Contains all of the part ids for a given message.
  166.      * @var     array $_pid 
  167.      * @access  private
  168.      */
  169.     var $_pid;
  170.  
  171.     /**
  172.      * (string) Contains all of the part mime types for a given message.
  173.      * @var     array $_ftype 
  174.      * @access  private
  175.      */
  176.     var $_ftype;
  177.  
  178.     /**
  179.      * (int) Contains the file size in bytes for message parts.
  180.      * @var     array $_fsize 
  181.      * @access  private
  182.      */
  183.     var $_fsize;
  184.  
  185.     /**
  186.      * (str) Contains the original file name for a message part (if any).
  187.      * @var     array $_fname 
  188.      * @access  private
  189.      */
  190.     var $_fname;
  191.  
  192.     /**
  193.      * (string) Contains the part disposition inline | attachment.
  194.      * @var     array $_disposition 
  195.      * @access  private
  196.      */
  197.     var $_disposition;
  198.  
  199.     /**
  200.      * (str) Contains the part encoding.
  201.      * @var     array $_encoding 
  202.      * @access  private
  203.      */
  204.     var $_encoding;
  205.  
  206.     /**
  207.      * (str) Contains the part id for multipart/related (if any).
  208.      * @var     array $_inlineId 
  209.      * @access  private
  210.      */
  211.     var $_inlineId;
  212.  
  213.     /**
  214.      * (bool) Determines whether the current part has attachments.
  215.      * @var     array $_hasAttachments 
  216.      * @access  private
  217.      */
  218.     var $_hasAttachments;
  219.  
  220.     /**
  221.      * (str) contains the default PID.
  222.      * @var     array $defaultPid 
  223.      * @access  public
  224.      */
  225.     var $defaultPid;
  226.  
  227.     // --------------------------INLINE MESSAGE PARTS-----------------------------
  228.     /**
  229.      * (str) Inline part id.
  230.      * @var     array $inPid 
  231.      * @access  public
  232.      */
  233.     var $inPid;
  234.  
  235.     /**
  236.      * (str) Inline part MIME type.
  237.      * @var     array $inFtype 
  238.      * @access  public
  239.      */
  240.     var $inFtype;
  241.  
  242.     /**
  243.      * (int) Inline file size of the part in bytes.
  244.      * @var     array $inFsize 
  245.      * @access  public
  246.      */
  247.     var $inFsize;
  248.  
  249.     /**
  250.      * (int) Inline file name of the part, if any.
  251.      * @var     array $inFname 
  252.      * @access  public
  253.      */
  254.     var $inFname;
  255.  
  256.     /**
  257.      * (bool) Inline part has attachments?
  258.      * @var     array $inHasAttach 
  259.      * @access  public
  260.      */
  261.     var $inHasAttach;
  262.  
  263.     /**
  264.      * (str) Inline CID for multipart/related.
  265.      * @var     array $inInlineId 
  266.      * @access  public
  267.      */
  268.     var $inInlineId;
  269.  
  270.     // --------------------------ATTACHMENT MESSAGE PARTS-----------------------------
  271.     /**
  272.      * (str) Attachment part id.
  273.      * @var     array $attachPid 
  274.      * @access  public
  275.      */
  276.     var $attachPid;
  277.  
  278.     /**
  279.      * (str) Attachment MIME type.
  280.      * @var     array $attachFtype 
  281.      * @access  public
  282.      */
  283.     var $attachFtype;
  284.  
  285.     /**
  286.      * (int) Attachment file size in bytes.
  287.      * @var     array $attachFsize 
  288.      * @access  public
  289.      */
  290.     var $attachFsize;
  291.  
  292.     /**
  293.      * (str) Attachment original file name (if any, if not file name is empty string).
  294.      * @var     array $attachFname 
  295.      * @access  public
  296.      */
  297.     var $attachFname;
  298.  
  299.     /**
  300.      * (bool) Attachment has attachments?
  301.      * @var     array $attachHasAttach 
  302.      * @access  public
  303.      */
  304.     var $attachHasAttach;
  305.  
  306.     // -------------------------- MESSAGE HEADERS -----------------------------
  307.     /**
  308.      * (str) Contains raw message headers fetched from {@link imap_fetchbody}
  309.      * or {@link imap_fetchheader} depending on which message part is being retrieved.
  310.      * @var     array $rawHeaders 
  311.      * @access  public
  312.      */
  313.     var $rawHeaders;
  314.  
  315.     /**
  316.      * (array)(mixed) Associative array containing information gathered by {@link imap_headerinfo}
  317.      * or {@link imap_rfc822_parse_headers}.
  318.      * @var    header array $header
  319.      */
  320.     var $header;
  321.     // }}}
  322.  
  323.     // {{{ constructor
  324.     /**
  325.     * Constructor. Optionally set the IMAP resource stream.
  326.     *
  327.     * If IMAP connection arguments are not supplied, returns NULL.  Accepts
  328.     * a URI abstraction of the standard imap_open connection argument
  329.     * (see {@link connect}) or the imap resource indicator.
  330.     *
  331.     * @param     string         $connect  (optional) server URL to connect to
  332.     * @param     int            $options  (optional) options see imap_open (DEPRECATED, use $this->option['open'] instead)
  333.     * @param     int            $error_reporting 
  334.     *    (optional), one of E_ALL or 0, tells Mail_IMAP to report more about the messages it is
  335.     *    parsing and where hacks are being used, such as fallback PIDs. This level of
  336.     *    error reporting can become annoying, to turn it off, set to 0.
  337.     *
  338.     * @access    public
  339.     * @return    BOOL|NULL|PEAR_Error
  340.     * @see       connect
  341.     * @see       imap_open
  342.     */
  343.     function Mail_IMAP($connection = NULL$options = NULL$error_reporting = E_ALL)
  344.     {
  345.         if (!defined('MAIL_IMAP_ERROR_REPORTING')) {
  346.             define('MAIL_IMAP_ERROR_REPORTING'$error_reporting);
  347.         }
  348.  
  349.         if (is_resource($connection)) {
  350.             if (get_resource_type($connection== 'imap'{
  351.                 $this->mailbox = $connection;
  352.                 $ret = TRUE;
  353.             else {
  354.                 $ret = PEAR::raiseError('Mail_IMAP::Mail_IMAP: Supplied resource is not a valid IMAP stream.');
  355.             }
  356.         else {
  357.             $ret ($connection == NULL)? NULL : Mail_IMAP::connect($connection$options);
  358.         }
  359.  
  360.         return $ret;
  361.     }
  362.     // }}}
  363.  
  364.     // {{{ connect()
  365.     /**
  366.     * Wrapper method for {@link imap_open}.  Accepts a URI abstraction in
  367.     * the following format: imap://user:pass@mail.example.com:143/INBOX#notls
  368.     * instead of the standard connection arguments used in imap_open.
  369.     * Replace the protocol with one of pop3|pop3s imap|imaps nntp|nntps.
  370.     * Place intial folder in the file path portion, and optionally append
  371.     * tls|notls|novalidate-cert in the anchor portion of the URL.  A port
  372.     * number is optional, however, leaving it off could lead to a serious
  373.     * degradation in preformance.
  374.     *
  375.     * Examples of a well-formed connection argument:
  376.     *
  377.     * For IMAP:        imap://user:pass@mail.example.com:143/INBOX
  378.     *
  379.     * For IMAP SSL:    imaps://user:pass@example.com:993/INBOX
  380.     *
  381.     * For POP3:        pop3://user:pass@mail.example.com:110/INBOX
  382.     *
  383.     * For POP3 SSL:    pop3s://user:pass@mail.example.com:993/INBOX
  384.     *
  385.     * For NNTP:        nntp://user:pass@mail.example.com:119/comp.test
  386.     *
  387.     * For 'notls' OR 'novalidate-cert' append to the URL as an anchor.
  388.     * For 'tls' use secure protocol and add the 'tls' option to the anchor.
  389.     *
  390.     * Examples:
  391.     *
  392.     * For notls:       imap://user:pass@mail.example.com:143/INBOX#notls
  393.     *
  394.     * For tls:         imaps://user:pass@mail.example.com:143/INBOX#tls
  395.     *
  396.     * tls no-validate: imaps://user:pass@mail.example.com:143/INBOX#tls/novalidate-cert
  397.     *
  398.     * ssl no-validate: imaps://user:pass@mail.example.com:143/INBOX#novalidate-cert
  399.     *
  400.     * If the username is an email address or contains invalid URL characters,
  401.     * urlencode the username portion of the string before passing it.
  402.     *
  403.     * Use the IMAP.connection_wizard_example.php file to automatically detect
  404.     * the correct URI to pass to this function.  This file is located in the
  405.     * examples directory.
  406.     *
  407.     * @param    string           $connect   server URL
  408.     * @param    int              (optional) options (DEPRECATED, use $this->option['open'] instead)
  409.     *    As of Mail_IMAP 1.1.0 the $options argument accepts an action for
  410.     *    retrieving various mailbox information. If set to MAIL_IMAP_GET_INFO (the default action)
  411.     *    Mail_IMAP::connect will make a call to {@link getMailboxInfo}. If set to MAIL_IMAP_NO_INFO
  412.     *    this call will not be made. In the upcoming Mail_IMAP 2.0.0 release the $options argument
  413.     *    will be no longer specify optional flags for {@link imap_open} and will server
  414.     *    exclusively as an action toggle for {@link getMailboxInfo}.
  415.     *
  416.     * @return   PEAR_Error|TRUE
  417.     * @access   public
  418.     * @see      imap_open
  419.     * @see      debug
  420.     * @see      getMailboxInfo
  421.     */
  422.     function connect($connect$options = NULL)
  423.     {
  424.         if (!class_exists('Net_URL')) {
  425.             if (!@include_once('Net/URL.php')) {
  426.                 return PEAR::raiseError('Mail_IMAP::connect: Inclusion of Net_URL not successful.');
  427.             }
  428.         }
  429.  
  430.         if (isset($this->option['open'])) {
  431.             $options $this->option['open'];
  432.         }
  433.  
  434.         $url =new Net_URL($connect);
  435.  
  436.         $connect  '{'.$url->host;
  437.  
  438.         if (!empty($url->port)) {
  439.             $connect .= ':'.$url->port;
  440.         }
  441.  
  442.         $secure   ('tls' == substr($url->anchor03))'' '/ssl';
  443.         $connect .= ('s' == (substr($url->protocol-1)))'/'.substr($url->protocol04).$secure '/'.$url->protocol;
  444.  
  445.         if (!empty($url->anchor)) {
  446.             $connect .= '/'.$url->anchor;
  447.         }
  448.  
  449.         $connect .= '}';
  450.  
  451.         $this->mailboxInfo['host']   $connect;
  452.  
  453.         // Trim off the leading slash '/'
  454.         if (!empty($url->path)) {
  455.             $this->mailboxInfo['folder'substr($url->path1(strlen($url->path- 1));
  456.             $connect .= $this->mailboxInfo['folder'];
  457.         }
  458.  
  459.         $this->mailboxInfo['user']   urldecode($url->user);
  460.  
  461.         $ret (FALSE === ($this->mailbox = @imap_open($connecturldecode($url->user)$url->pass$options)))? PEAR::raiseError('Mail_IMAP::connect: Unable to build a connection to the specified mail server.': TRUE;
  462.  
  463.         // get mailbox info
  464.         if ($options != MAIL_IMAP_NO_INFO{
  465.             Mail_IMAP::getMailboxInfo(FALSE);
  466.         }
  467.  
  468.         // Do debugger
  469.         if ((isset($_GET['dump_mid'])) && (MAIL_IMAP_ERROR_REPORTING == E_ALL || MAIL_IMAP_ERROR_REPORTING == MAIL_IMAP_E_DEBUG)) {
  470.             Mail_IMAP::debug($_GET['dump_mid']);
  471.         }
  472.  
  473.         return $ret;
  474.     }
  475.     // }}}
  476.  
  477.     // {{{ getMailboxInfo()
  478.     /**
  479.     * Adds to the {@link $mailboxInfo} member variable information about the current
  480.     * mailbox from {@link imap_mailboxmsginfo}.
  481.     *
  482.     * Note: This method is automatically called on by default by {@link connect}.
  483.     *
  484.     * @param    string           $connect   server URL
  485.     * @param    bool             $get_info 
  486.     *    (optional) TRUE by default. If TRUE, make a call to {@link getMailboxInfo}
  487.     *    if FALSE do not call {@link getMailboxInfo}
  488.     *
  489.     * @return   PEAR_Error|TRUE
  490.     * @access   public
  491.     * @see      imap_open
  492.     */
  493.     function getMailboxInfo($ret = TRUE)
  494.     {
  495.         // It's possible that this function has already been called by Mail_IMAP::connect
  496.         // If so, the 'Mailbox' indice will already exist and the user just wants
  497.         // the contents of the mailboxInfo member variable.
  498.         if (!isset($this->mailboxInfo['Mailbox'])) {
  499.             $this->mailboxInfo = @array_merge($this->mailboxInfoget_object_vars(imap_mailboxmsginfo($this->mailbox)));
  500.         }
  501.  
  502.         if ($ret == TRUE{
  503.             return $this->mailboxInfo;
  504.         }
  505.     }
  506.     // }}}
  507.  
  508.     // {{{ setOptions()
  509.     /**
  510.     * Set the $option member variable, which is used to specify optional imap_* function
  511.     * arguments (labeled in the manual as flags or options e.g. FT_UID, OP_READONLY, etc).
  512.     *
  513.     * Example:
  514.     *    $msg->setOptions(array('body', 'fetchbody', 'fetchheader'), 'FT_UID');
  515.     *
  516.     * This results in imap_body, imap_fetchbody and imap_fetchheader being passed the FT_UID
  517.     * option in the flags/options argument where ever these are called on by Mail_IMAP.
  518.     *
  519.     * Note: this method only sets arguments labeled as flags/options.
  520.     *
  521.     * @param    array          $option_set - function names to pass the arugument to
  522.     * @param    string         $constant   - constant name to pass.
  523.     * @return   PEAR_Error|TRUE
  524.     * @access   public
  525.     * @see      $option
  526.     */
  527.     function setOptions($option_set$constant)
  528.     {
  529.         if (is_array($option_set&& !empty($option_set)) {
  530.             foreach ($option_set as $value{
  531.                 if (!$this->option[$value@constant($constant)) {
  532.                     return PEAR::raiseError('Mail_IMAP::setOptions: The constant: '.$constant.' is not defined!');
  533.                 }
  534.             }
  535.         else {
  536.             return PEAR::raiseError('Mail_IMAP::setOptions: The first argument must be an array.');
  537.         }
  538.  
  539.         return TRUE;
  540.     }
  541.     // }}}
  542.  
  543.     // {{{ close()
  544.     /**
  545.     * Wrapper method for {@link imap_close}.  Close the IMAP resource stream.
  546.     *
  547.     * @param    int           $options    (optional) sets the second argument of imap_close (DEPRECATED, use $this->option['close'] instead)
  548.     * @return   PEAR_Error|TRUE
  549.     * @access   public
  550.     * @see      imap_close
  551.     */
  552.     function close($options = NULL)
  553.     {
  554.         if (isset($this->option['close'])) {
  555.             $options $this->option['close'];
  556.         }
  557.  
  558.         return (@imap_close($this->mailbox$options))? TRUE : PEAR::raiseError('Mail_IMAP::close: Unable to close the connection to the mail server.');
  559.     }
  560.     // }}}
  561.  
  562.     // {{{ messageCount()
  563.     /**
  564.     * Wrapper method for {@link imap_num_msg}.
  565.     *
  566.     * @return   int mailbox message count
  567.     * @access   public
  568.     * @see      imap_num_msg
  569.     */
  570.     function messageCount()
  571.     {
  572.         return @imap_num_msg($this->mailbox);
  573.     }
  574.     // }}}
  575.  
  576.     // {{{ _declareParts()
  577.     /**
  578.     * Gather message information returned by {@link imap_fetchstructure} and recursively iterate
  579.     * through each parts array.  Concatenate part numbers in the following format `1.1`
  580.     * each part id is separated by a period, each referring to a part or subpart of a
  581.     * multipart message.  Create part numbers as such that they are compatible with
  582.     * {@link imap_fetchbody}.
  583.     *
  584.     * @param    int           &$mid         message id
  585.     * @param    array         $sub_part     recursive
  586.     * @param    string        $sub_pid      recursive parent part id
  587.     * @param    int           $n            recursive counter
  588.     * @param    bool          $is_sub_part  recursive
  589.     * @param    bool          $skip_part    recursive
  590.     * @return   mixed 
  591.     * @access   private
  592.     * @see      imap_fetchstructure
  593.     * @see      imap_fetchbody
  594.     */
  595.     function _declareParts(&$mid$sub_part = NULL$sub_pid = NULL$n = 0$is_sub_part = FALSE$skip_part = FALSE)
  596.     {
  597.         if (!is_array($sub_part)) {
  598.             $this->_structure[$mid(isset($this->option['fetchstructure']))@imap_fetchstructure($this->mailbox$mid$this->option['fetchstructure']@imap_fetchstructure($this->mailbox$mid);
  599.         }
  600.  
  601.         if (isset($this->_structure[$mid]->parts|| is_array($sub_part)) {
  602.  
  603.             if ($is_sub_part == FALSE{
  604.                 $parts $this->_structure[$mid]->parts;
  605.             else {
  606.                 $parts $sub_part;
  607.                 $n++;
  608.             }
  609.  
  610.             for ($p = 0$i = 1; $p count($parts)$n++$p++$i++{
  611.                 // Skip the following...
  612.                 // multipart/mixed!
  613.                 // subsequent multipart/alternative if this part is message/rfc822
  614.                 // multipart/related
  615.                 //
  616.                 // Have noticed the existence of several other multipart/* types of messages
  617.                 // but have yet had the opportunity to test on those.
  618.                 $ftype        (empty($parts[$p]->type))?    $this->_dataTypes[0].'/'.strtolower($parts[$p]->subtype$this->_dataTypes[$parts[$p]->type].'/'.strtolower($parts[$p]->subtype);
  619.                 $skip_next    ($ftype == 'message/rfc822')? TRUE : FALSE;
  620.  
  621.                 if ($ftype == 'multipart/mixed' || $skip_part == TRUE && $ftype == 'multipart/alternative' || $ftype == 'multipart/related' && count($parts== 1{
  622.                     $n--;
  623.                     $skipped = TRUE;
  624.                 else {
  625.  
  626.                     $skipped = FALSE;
  627.  
  628.                     $this->_pid[$mid][$n($is_sub_part == FALSE)? (string) "$i" : (string) "$sub_pid.$i";
  629.  
  630.                     $this->_ftype[$mid][$n]     $ftype;
  631.                     $this->_encoding[$mid][$n]  (empty($parts[$p]->encoding))$this->_encodingTypes[0$this->_encodingTypes[$parts[$p]->encoding];
  632.                     $this->_fsize[$mid][$n]     (!isset($parts[$p]->bytes|| empty($parts[$p]->bytes))? 0 : $parts[$p]->bytes;
  633.  
  634.                     // Force inline disposition if none is present
  635.                     if ($parts[$p]->ifdisposition == TRUE{
  636.  
  637.                         $this->_disposition[$mid][$nstrtolower($parts[$p]->disposition);
  638.  
  639.                         if ($parts[$p]->ifdparameters == TRUE{
  640.  
  641.                             $params $parts[$p]->dparameters;
  642.  
  643.                             foreach ($params as $param{
  644.  
  645.                                 if (strtolower($param->attribute== 'filename'{
  646.                                     $this->_fname[$mid][$n$param->value;
  647.                                     break;
  648.                                 }
  649.                             }
  650.                         }
  651.  
  652.                     else {
  653.                         $this->_disposition[$mid][$n'inline';
  654.                     }
  655.  
  656.                     if ($parts[$p]->ifid == TRUE{
  657.                         $this->_inlineId[$mid][$n$parts[$p]->id;
  658.                     }
  659.                 }
  660.  
  661.                 if (isset($parts[$p]->parts&& is_array($parts[$p]->parts)) {
  662.                     if ($skipped == FALSE{
  663.                         $this->_hasAttachments[$mid][$n= TRUE;
  664.                     }
  665.  
  666.                     $n Mail_IMAP::_declareParts($mid$parts[$p]->parts$this->_pid[$mid][$n]$nTRUE$skip_next);
  667.  
  668.                 else if ($skipped == FALSE{
  669.                     $this->_hasAttachments[$mid][$n= FALSE;
  670.                 }
  671.             }
  672.  
  673.             if ($is_sub_part == TRUE{
  674.                 return $n;
  675.             }
  676.  
  677.          else {
  678.  
  679.              // $parts is not an array... message is flat
  680.             $this->_pid[$mid][0= 1;
  681.  
  682.             if (empty($this->_structure[$mid]->type)) {
  683.                 $this->_structure[$mid]->type        = (int) 0;
  684.             }
  685.  
  686.             if (isset($this->_structure[$mid]->subtype)) {
  687.                 $this->_ftype[$mid][0]               $this->_dataTypes[$this->_structure[$mid]->type].'/'.strtolower($this->_structure[$mid]->subtype);
  688.             }
  689.  
  690.             if (empty($this->_structure[$mid]->encoding)) {
  691.                 $this->_structure[$mid]->encoding    = (int) 0;
  692.             }
  693.  
  694.             $this->_encoding[$mid][0]                $this->_encodingTypes[$this->_structure[$mid]->encoding];
  695.  
  696.             if (isset($this->_structure[$mid]->bytes)) {
  697.                 $this->_fsize[$mid][0]               strtolower($this->_structure[$mid]->bytes);
  698.             }
  699.  
  700.             $this->_disposition[$mid][0]             'inline';
  701.             $this->_hasAttachments[$mid][0]          = FALSE;
  702.         }
  703.  
  704.         return;
  705.     }
  706.     // }}}
  707.  
  708.     // {{{ _checkIfParsed()
  709.     /**
  710.     * Checks if the part has been parsed, if not calls on _declareParts to
  711.     * parse the message.
  712.     *
  713.     * @param    int          &$mid         message id
  714.     * @param    bool         $checkPid 
  715.     * @return   void 
  716.     * @access   private
  717.     */
  718.     function _checkIfParsed(&$mid$checkPid = TRUE)
  719.     {
  720.         if (!isset($this->_pid[$mid])) {
  721.            Mail_IMAP::_declareParts($mid);
  722.         }
  723.  
  724.         if ($checkPid == TRUE && !isset($this->defaultPid[$mid])) {
  725.            Mail_IMAP::getDefaultPid($mid);
  726.         }
  727.         return;
  728.     }
  729.     // }}}
  730.  
  731.     // {{{ getParts()
  732.     /**
  733.     * sets up member variables containing inline parts and attachments for a specific part
  734.     * in member variable arrays beginning with 'in' and 'attach'.
  735.     * If inline parts are present, sets {@link $inPid}{@link $inFtype}{@link $inFsize},
  736.     * {@link $inHasAttach}{@link $inInlineId} (if an inline CID is specified).
  737.     * If attachments are present, sets, {@link $attachPid}{@link $attachFsize}{@link $attachHasAttach},
  738.     * {@link $attachFname} (if a filename is present, empty string otherwise).
  739.     *
  740.     * Typically the text/html part is displayed by default by a message viewer, this part is
  741.     * excluded from the inline member variable arrays thourgh $excludeMime by default.  If
  742.     * $getInline is TRUE the text/plain alternative part will be returned in the inline array
  743.     * and may be included as an attachment.  Useful for mail developement/debugging of multipart
  744.     * messages.
  745.     *
  746.     * @param    int           &$mid         message id
  747.     * @param    int           &$pid         part id
  748.     * @param    string        $MIME 
  749.     *        (optional) values: text/plain|text/html, the part MIME type that will be
  750.     *        retrieved by default.
  751.     *
  752.     * @param    bool          $getAlternative 
  753.     *        (optional) include the plain/text alternative part in the created inline parts
  754.     *        array if $MIME is text/html, if $MIME is text/plain, include the text/html
  755.     *        alternative part.
  756.     *
  757.     * @param    bool          $retrieve_all 
  758.     *        (optional) Instead of just finding parts relative to this part, get *all* parts
  759.     *        using this option *all* sub parts are included in the $in* and $attach* variables.
  760.     *
  761.     * @return   bool 
  762.     * @access   public
  763.     * @since    PHP 4.2.0
  764.     */
  765.     function getParts(&$mid&$pid$MIME 'text/html'$getAlternative = TRUE$retrieve_all = FALSE)
  766.     {
  767.         Mail_IMAP::_checkIfParsed($mid);
  768.  
  769.         if (count($this->_pid[$mid]== 1{
  770.             return TRUE;
  771.         }
  772.  
  773.         // retrieve key for this part, so that the information may be accessed
  774.         if (FALSE !== ($i array_search((string) $pid$this->_pid[$mid]))) {
  775.             if ($retrieve_all == TRUE{
  776.                 Mail_IMAP::_scanMultipart($mid$pid$i$MIME'add''none'2$getAlternative);
  777.             else {
  778.                 if ($pid == $this->defaultPid[$mid]{
  779.                     Mail_IMAP::_scanMultipart($mid$pid$i$MIME'add''top'2$getAlternative);
  780.                 else if ($this->_ftype[$mid][$i== 'message/rfc822'{
  781.                     Mail_IMAP::_scanMultipart($mid$pid$i$MIME'add''all'1$getAlternative);
  782.                 }
  783.             }
  784.         else {
  785.             PEAR::raiseError('Mail_IMAP::getParts: Unable to retrieve a valid part id from the pid passed.'nullPEAR_ERROR_TRIGGERE_USER_WARNING'mid: '.$mid.' pid: '.$pid);
  786.             return FALSE;
  787.         }
  788.  
  789.         return TRUE;
  790.     }
  791.     // }}}
  792.  
  793.     // {{{ _scanMultipart()
  794.     /**
  795.     * Finds message parts relevant to the message part currently being displayed or
  796.     * looks through a message and determines which is the best body to display.
  797.     *
  798.     * @param    int           &$mid         message id
  799.     * @param    int           &$pid         part id
  800.     * @param    int           $i            offset indice correlating to the pid
  801.     * @param    str           $MIME         one of text/plain or text/html the default MIME to retrieve.
  802.     * @param    str           $action       one of add|get
  803.     * @param    str           $lookAt       one of all|multipart|top|none
  804.     * @param    int           $pidAdd       determines the level of nesting.
  805.     * @param    bool          $getAlternative 
  806.     *    Determines whether the program retrieves the alternative part in a
  807.     *    multipart/alternative message.
  808.     *
  809.     * @return   string|FALSE
  810.     * @access   private
  811.     */
  812.     function _scanMultipart(&$mid&$pid&$i$MIME$action 'add'$lookAt 'all'$pidAdd = 1$getAlternative = TRUE)
  813.     {
  814.         // Find subparts, create variables
  815.         // Create inline parts first, and attachments second
  816.  
  817.         // Get all top level parts, with the exception of the part currently being viewed
  818.         // If top level part contains multipart/alternative go into that subpart to
  819.         // retrieve the other inline message part to display
  820.  
  821.         // If this part is message/rfc822 get subparts that begin with this part id
  822.         // Skip multipart/alternative message part
  823.         // Find the displayable message, get plain/text part if $getInline is TRUE
  824.  
  825.         if ($action == 'add'{
  826.  
  827.            $excludeMIME $MIME;
  828.            $MIME        ($excludeMIME == 'text/plain')'text/html' 'text/plain';
  829.            $in          = 0;
  830.            $a           = 0;
  831.  
  832.         else if ($action == 'get'{
  833.  
  834.            $excludeMIME = NULL;
  835.         }
  836.  
  837.         $pid_len      strlen($pid);
  838.         $this_nesting count(explode('.'$pid));
  839.  
  840.         foreach ($this->_pid[$midas $p => $id{
  841.  
  842.             // To look at the next level of nesting one needs to determine at which level
  843.             // of nesting the program currently resides, this needs to be independent of the
  844.             // part id length, since part ids can get into double digits (let's hope they
  845.             // don't get into triple digits!)
  846.  
  847.             // To accomplish this we'll explode the part id on the dot to get a count of the
  848.             // nesting, then compare the string with the next level in.
  849.  
  850.             $nesting count(explode('.'$this->_pid[$mid][$p]));
  851.  
  852.             switch ($lookAt{
  853.                 case 'all':
  854.                 {
  855.                     $condition (($nesting == ($this_nesting + 1)) && $pid == substr($this->_pid[$mid][$p]0$pid_len));
  856.                     break;
  857.                 }
  858.                 case 'multipart':
  859.                 {
  860.                     $condition (($nesting == ($this_nesting + 1)) && ($pid == substr($this->_pid[$mid][$p]0)));
  861.                     break;
  862.                 }
  863.                 // Used if *all* parts are being retrieved
  864.                 case 'none':
  865.                 {
  866.                     $condition = TRUE;
  867.                     break;
  868.                 }
  869.                 // To gaurantee a top-level part, detect whether a period appears in the pid string
  870.                 case 'top':
  871.                 default:
  872.                 {
  873.                     if (Mail_IMAP::_isMultipartRelated($mid)) {
  874.                         $condition (!strstr($this->_pid[$mid][$p]'.'|| ($nesting == 2&& substr($this->defaultPid[$mid]01== substr($this->_pid[$mid][$p]01));
  875.                     else {
  876.                         $condition (!strstr($this->_pid[$mid][$p]'.'));
  877.                     }
  878.                 }
  879.             }
  880.  
  881.             if ($condition == TRUE{
  882.  
  883.                 if ($this->_ftype[$mid][$p== 'multipart/alternative'{
  884.  
  885.                     foreach ($this->_pid[$midas $mp => $mpid{
  886.  
  887.                         // Part must begin with last matching part id and be two levels in
  888.  
  889.                         $sub_nesting count(explode('.'$this->_pid[$mid][$p]));
  890.  
  891.                         if (( $this->_ftype[$mid][$mp== $MIME &&
  892.                               $getAlternative == TRUE &&
  893.                               ($sub_nesting == ($this_nesting $pidAdd)) &&
  894.                               ($pid == substr($this->_pid[$mid][$mp]0strlen($this->_pid[$mid][$p])))
  895.                            )) {
  896.  
  897.                             if ($action == 'add'{
  898.  
  899.                                  Mail_IMAP::_addInlinePart($in$mid$mp);
  900.                                  break;
  901.  
  902.                             else if ($action == 'get' && !isset($this->_fname[$mid][$mp]&& empty($this->_fname[$mid][$mp])) {
  903.  
  904.                                 return $this->_pid[$mid][$mp];
  905.  
  906.                             }
  907.  
  908.                         else if ($this->_ftype[$mid][$mp== 'multipart/alternative' && $action == 'get'{
  909.  
  910.                             // Need to match this PID to next level in
  911.                             $pid          = (string) $this->_pid[$mid][$mp];
  912.                             $pid_len      strlen($pid);
  913.                             $this_nesting count(explode('.'$pid));
  914.                             $pidAdd       = 2;
  915.                             continue;
  916.                         }
  917.                     }
  918.  
  919.                 else if ($this->_disposition[$mid][$p== 'inline' && $this->_ftype[$mid][$p!= 'multipart/related'{
  920.  
  921.                     if (( $action == 'add' &&
  922.                           $this->_ftype[$mid][$p!= $excludeMIME &&
  923.                           $pid != $this->_pid[$mid][$p]
  924.                        || (
  925.                           $action == 'add' &&
  926.                           $this->_ftype[$mid][$p== $excludeMIME &&
  927.                           isset($this->_fname[$mid][$p]&&
  928.                           $pid != $this->_pid[$mid][$p]
  929.                        )) {
  930.  
  931.                         Mail_IMAP::_addInlinePart($in$mid$p);
  932.  
  933.                     else if ($action == 'get' && $this->_ftype[$mid][$p== $MIME && !isset($this->_fname[$mid][$p])) {
  934.  
  935.                         return $this->_pid[$mid][$p];
  936.                     }
  937.  
  938.                 else if ($action == 'add' && $this->_disposition[$mid][$p== 'attachment'{
  939.  
  940.                     Mail_IMAP::_addAttachment($a$mid$p);
  941.  
  942.                 }
  943.  
  944.             }
  945.  
  946.         }
  947.  
  948.         return FALSE;
  949.     }
  950.     // }}}
  951.  
  952.     // {{{ _isMultipartRelated()
  953.     /**
  954.     * Determines whether a message contains a multipart/related part.
  955.     * Only called on by Mail_IMAP::_scanMultipart
  956.     *
  957.     * @return   BOOL 
  958.     * @access   private
  959.     * @see      _scanMultipart
  960.     */
  961.     function _isMultipartRelated($mid)
  962.     {
  963.         $ret Mail_IMAP::extractMIME($mid'multipart/related');
  964.         return (!empty($ret&& is_array($ret&& count($ret>= 1)? TRUE : FALSE;
  965.     }
  966.     // }}}
  967.  
  968.     // {{{ unsetParts()
  969.     /**
  970.     * Destroys variables set by {@link getParts} and _declareParts.
  971.     *
  972.     * @param    integer  &$mid   message id
  973.     * @return   void 
  974.     * @access   public
  975.     * @see      getParts
  976.     */
  977.     function unsetParts(&$mid)
  978.     {
  979.         unset($this->inPid[$mid]);
  980.         unset($this->inFtype[$mid]);
  981.         unset($this->inFsize[$mid]);
  982.         unset($this->inHasAttach[$mid]);
  983.         unset($this->inInlineId[$mid]);
  984.  
  985.         unset($this->attachPid[$mid]);
  986.         unset($this->attachFtype[$mid]);
  987.         unset($this->attachFsize[$mid]);
  988.         unset($this->attachFname[$mid]);
  989.         unset($this->attachHasAttach[$mid]);
  990.  
  991.         unset($this->_structure[$mid]);
  992.         unset($this->_pid[$mid]);
  993.         unset($this->_disposition[$mid]);
  994.         unset($this->_encoding[$mid]);
  995.         unset($this->_ftype[$mid]);
  996.         unset($this->_fsize[$mid]);
  997.         unset($this->_fname[$mid]);
  998.         unset($this->_inlineId[$mid]);
  999.         unset($this->_hasAttachments[$mid]);
  1000.  
  1001.         return;
  1002.     }
  1003.     // }}}
  1004.  
  1005.     // {{{ _addInlinePart()
  1006.     /**
  1007.     * Adds information to the member variable inline parts arrays.
  1008.     *
  1009.     * @param    int     &$in   offset inline counter
  1010.     * @param    int     &$mid  message id
  1011.     * @param    int     &$i    offset structure reference counter
  1012.     * @return   void 
  1013.     * @access   private
  1014.     */
  1015.     function _addInlinePart(&$in&$mid&$i)
  1016.     {
  1017.         $this->inFname[$mid][$in(isset($this->_fname[$mid][$i]&& !empty($this->_fname[$mid][$i]))$this->_fname[$mid][$i'';
  1018.  
  1019.         $this->inPid[$mid][$in]            $this->_pid[$mid][$i];
  1020.         $this->inFtype[$mid][$in]          $this->_ftype[$mid][$i];
  1021.         $this->inFsize[$mid][$in]          $this->_fsize[$mid][$i];
  1022.         $this->inHasAttach[$mid][$in]      $this->_hasAttachments[$mid][$i];
  1023.  
  1024.         if (isset($this->_inlineId[$mid][$i])) {
  1025.             $this->inInlineId[$mid][$in]   $this->_inlineId[$mid][$i];
  1026.         }
  1027.  
  1028.         $in++;
  1029.  
  1030.         return;
  1031.     }
  1032.     // }}}
  1033.  
  1034.     // {{{ _addAttachment()
  1035.     /**
  1036.     * Adds information to the member variable attachment parts arrays.
  1037.     *
  1038.     * @param    int     &$a    offset attachment counter
  1039.     * @param    int     &$mid  message id
  1040.     * @param    int     &$i    offset structure reference counter
  1041.     * @return   void 
  1042.     * @access   private
  1043.     */
  1044.     function _addAttachment(&$a&$mid&$i)
  1045.     {
  1046.         if (!isset($this->_fname[$mid][$i])) {
  1047.             $this->_fname[$mid][$i'';
  1048.         }
  1049.  
  1050.         $this->attachPid[$mid][$a]         $this->_pid[$mid][$i];
  1051.         $this->attachFtype[$mid][$a]       $this->_ftype[$mid][$i];
  1052.         $this->attachFsize[$mid][$a]       $this->_fsize[$mid][$i];
  1053.         $this->attachFname[$mid][$a]       $this->_fname[$mid][$i];
  1054.         $this->attachHasAttach[$mid][$a]   $this->_hasAttachments[$mid][$i];
  1055.  
  1056.         $a++;
  1057.  
  1058.         return;
  1059.     }
  1060.     // }}}
  1061.  
  1062.     // {{{ getRawMessage()
  1063.     /**
  1064.     * Returns entire unparsed message body.  See {@link imap_body} for options.
  1065.     *
  1066.     * @param    int     &$mid      message id
  1067.     * @param    int     $options   flags       (DEPRECATED, use $this->option['body'] instead)
  1068.     * @return   void 
  1069.     * @access   public
  1070.     * @see      imap_body
  1071.     */
  1072.     function getRawMessage(&$mid$options = NULL)
  1073.     {
  1074.         if (isset($this->option['body'])) {
  1075.             $options $this->option['body'];
  1076.         }
  1077.  
  1078.         return imap_body($this->mailbox$mid$options);
  1079.     }
  1080.     // }}}
  1081.  
  1082.     // {{{ getBody()
  1083.     /**
  1084.     * Searches parts array set in Mail_IMAP::_declareParts() for a displayable message.
  1085.     * If the part id passed is message/rfc822 looks in subparts for a displayable body.
  1086.     * Attempts to return a text/html inline message part by default. And will
  1087.     * automatically attempt to find a text/plain part if a text/html part could
  1088.     * not be found.
  1089.     *
  1090.     * Returns an array containing three associative indices; 'ftype', 'fname' and
  1091.     * 'message'.  'ftype' contains the MIME type of the message, 'fname', the original
  1092.     * file name, if any, empty string otherwise.  And 'message', which contains the
  1093.     * message body itself which is returned decoded from base64 or quoted-printable if
  1094.     * either of those encoding types are specified, returns untouched otherwise.
  1095.     * Returns FALSE on failure.
  1096.     *
  1097.     * @param    int     &$mid                    message id
  1098.     * @param    string  $pid                     part id
  1099.     * @param    int     $action 
  1100.     *       (optional) options for body return.  Set to one of the following:
  1101.     *       MAIL_IMAP_BODY (default), if part is message/rfc822 searches subparts for a
  1102.     *       displayable body and returns the body decoded as part of an array.
  1103.     *       MAIL_IMAP_LITERAL, return the message for the specified $pid without searching
  1104.     *       subparts or decoding the message (may return unparsed message) body is returned
  1105.     *       undecoded as a string.
  1106.     *       MAIL_IMAP_LITERAL_DECODE, same as MAIL_IMAP_LITERAL, except message decoding is
  1107.     *       attempted from base64 or quoted-printable encoding, returns undecoded string
  1108.     *       if decoding failed.
  1109.     *
  1110.     * @param    string  $getPart 
  1111.     *       (optional) one of text/plain or text/html, allows the specification of the default
  1112.     *       part to return from multipart messages, text/html by default.
  1113.     *
  1114.     * @param    int     $options 
  1115.     *       (optional) allows the specification of the forth argument of imap_fetchbody
  1116.     *       (DEPRECATED, use $this->option['fetchbody'] instead)
  1117.     *
  1118.     * @return   array|string|FALSE
  1119.     * @access   public
  1120.     * @see      imap_fetchbody
  1121.     * @see      Mail_IMAP::getParts
  1122.     * @since    PHP 4.2.0
  1123.     */
  1124.     function getBody(&$mid$pid '1'$action = 0$getPart 'text/html'$options = NULL$attempt = 1)
  1125.     {
  1126.         if (isset($this->option['fetchbody'])) {
  1127.             $options $this->option['fetchbody'];
  1128.         }
  1129.  
  1130.         if ($action == MAIL_IMAP_LITERAL{
  1131.             return ($options == NULL)? imap_fetchbody($this->mailbox$mid$pid: imap_fetchbody($this->mailbox$mid$pid$options);
  1132.         }
  1133.  
  1134.         Mail_IMAP::_checkIfParsed($mid);
  1135.  
  1136.         if (FALSE !== ($i array_search((string) $pid$this->_pid[$mid]))) {
  1137.             if ($action == MAIL_IMAP_LITERAL_DECODE{
  1138.                 $msg_body = imap_fetchbody($this->mailbox$mid$pid$options);
  1139.                 return Mail_IMAP::_decodeMessage($msg_body$this->_encoding[$mid][$i]);
  1140.             }
  1141.  
  1142.             // If this is an attachment, and the part is message/rfc822 update the pid to the subpart
  1143.             // If this is an attachment, and the part is multipart/alternative update the pid to the subpart
  1144.             if ($this->_ftype[$mid][$i== 'message/rfc822' || $this->_ftype[$mid][$i== 'multipart/related' || $this->_ftype[$mid][$i== 'multipart/alternative'{
  1145.  
  1146.                 $new_pid ($this->_ftype[$mid][$i== 'message/rfc822' || $this->_ftype[$mid][$i== 'multipart/related')Mail_IMAP::_scanMultipart($mid$pid$i$getPart'get''all'1Mail_IMAP::_scanMultipart($mid$pid$i$getPart'get''multipart'1);
  1147.  
  1148.                 // if a new pid for text/html couldn't be found, try again, this time look for text/plain
  1149.                 switch(TRUE{
  1150.                     case (!empty($new_pid)):                             $pid $new_pid; break;
  1151.                     case (empty($new_pid&& $getPart == 'text/html'):   return ($attempt == 1)Mail_IMAP::getBody($mid$pid$action'text/plain'$options2: FALSE;
  1152.                     case (empty($new_pid&& $getPart == 'text/plain'):  return ($attempt == 1)Mail_IMAP::getBody($mid$pid$action'text/html'$options2: FALSE;
  1153.                 }
  1154.             }
  1155.  
  1156.             // Update the key for the new pid
  1157.             if (!empty($new_pid)) {
  1158.                 if (FALSE === ($i array_search((string) $pid$this->_pid[$mid]))) {
  1159.                     // Something's afoot!
  1160.                     PEAR::raiseError('Mail_IMAP::getBody: Unable to find a suitable replacement part ID for: '.$pid.'. Message: '.$mid.' may be poorly formed, corrupted, or not supported by the Mail_IMAP parser.'NULLPEAR_ERROR_TRIGGERE_USER_WARNING);
  1161.                     return FALSE;
  1162.                 }
  1163.             }
  1164.  
  1165.             $msg_body = imap_fetchbody($this->mailbox$mid$pid$options);
  1166.  
  1167.             if ($msg_body == NULL{
  1168.                 PEAR::raiseError('Mail_IMAP::getBody: Message body was NULL for pid: '.$pid.', is not a valid part number.'NULLPEAR_ERROR_TRIGGERE_USER_NOTICE);
  1169.                 return FALSE;
  1170.             }
  1171.  
  1172.             // Decode message.
  1173.             // Because the body returned may not correspond with the original PID, return
  1174.             // an array which also contains the MIME type and original file name, if any.
  1175.             $body['message'Mail_IMAP::_decodeMessage($msg_body$this->_encoding[$mid][$i]);
  1176.             $body['ftype']   $this->_ftype[$mid][$i];
  1177.             $body['fname']   (isset($this->_fname[$mid][$i]))$this->_fname[$mid][$i'';
  1178.  
  1179.             return $body;
  1180.         else {
  1181.             PEAR::raiseError('Mail_IMAP::getBody: Unable to retrieve message body, invalid part id: '.$pidNULLPEAR_ERROR_TRIGGERE_USER_WARNING);
  1182.             return FALSE;
  1183.         }
  1184.  
  1185.         return FALSE;
  1186.     }
  1187.     // }}}
  1188.  
  1189.     // {{{ _decodeMessage()
  1190.     /**
  1191.     * Decode a string from quoted-printable or base64 encoding.  If
  1192.     * neither of those encoding types are specified, returns string
  1193.     * untouched.
  1194.     *
  1195.     * @param    string  &$body           string to decode
  1196.     * @param    string  &$encoding       encoding to decode from.
  1197.     * @return   string 
  1198.     * @access   private
  1199.     */
  1200.     function _decodeMessage(&$body&$encoding)
  1201.     {
  1202.         switch ($encoding{
  1203.             case 'quoted-printable':  return imap_qprint($body);
  1204.             case 'base64':            return imap_base64($body);
  1205.             default:                  return $body;
  1206.         }
  1207.     }
  1208.     // }}}
  1209.  
  1210.     // {{{ getDefaultPid()
  1211.     /**
  1212.     * Searches structure defined in Mail_IMAP::_declareParts for the top-level default message.
  1213.     * Attempts to find a text/html default part, if no text/html part is found,
  1214.     * automatically attempts to find a text/plain part. Returns the part id for the default
  1215.     * top level message part on success. Returns FALSE on failure.
  1216.     *
  1217.     * @param    int     &$mid           message id
  1218.     * @param    string  $getPart 
  1219.     *      (optional) default MIME type to look for, one of text/html or text/plain
  1220.     *      text/html by default.
  1221.     * @return   string 
  1222.     * @access   public
  1223.     */
  1224.     function getDefaultPid(&$mid$getPart 'text/html'$attempt = 1)
  1225.     {
  1226.         // Check to see if this part has already been parsed
  1227.         Mail_IMAP::_checkIfParsed($midFALSE);
  1228.  
  1229.         // Look for a text/html message part
  1230.         // If no text/html message part was found look for a text/plain message part
  1231.         $part ($getPart == 'text/html')? array('text/html''text/plain': array('text/plain''text/html');
  1232.  
  1233.         foreach ($part as $mime{
  1234.             if (0 !== count($msg_part @array_keys($this->_ftype[$mid]$mime))) {
  1235.                 foreach ($msg_part as $i{
  1236.                     if ($this->_disposition[$mid][$i== 'inline' && !strstr($this->_pid[$mid][$i]'.')) {
  1237.                         $this->defaultPid[$mid$this->_pid[$mid][$i];
  1238.                         return $this->_pid[$mid][$i];
  1239.                     }
  1240.                 }
  1241.             }
  1242.         }
  1243.  
  1244.         // If no text/plain or text/html part was found
  1245.         // Look for a multipart/alternative part
  1246.         $mp_nesting = 1;
  1247.         $pid_len    = 1;
  1248.  
  1249.         foreach ($this->_pid[$midas $p => $id{
  1250.             $nesting count(explode('.'$this->_pid[$mid][$p]));
  1251.  
  1252.             if (!isset($mpid)) {
  1253.                 if ($nesting == 1 && $this->_ftype[$mid][$p== 'multipart/related'{
  1254.                     $mp_nesting = 2;
  1255.                     $pid_len    = 3;
  1256.                     continue;
  1257.                 }
  1258.                 if ($nesting == $mp_nesting && $this->_ftype[$mid][$p== 'multipart/alternative'{
  1259.                     $mpid $this->_pid[$mid][$p];
  1260.                     continue;
  1261.                 }
  1262.             }
  1263.  
  1264.             if (isset($mpid&& $nesting == ($mp_nesting + 1&& $this->_ftype[$mid][$p== $getPart && $mpid == substr($this->_pid[$mid][$p]0$pid_len)) {
  1265.                 $this->defaultPid[$mid$this->_pid[$mid][$p];
  1266.                 return $this->_pid[$mid][$p];
  1267.             }
  1268.         }
  1269.  
  1270.         // if a text/html part was not found, call on the function again
  1271.         // and look for text/plain
  1272.         // if the application was unable to find a text/plain part
  1273.         switch ($getPart{
  1274.             case 'text/html':  $ret ($attempt == 1)Mail_IMAP::getDefaultPid($mid'text/plain'2: FALSE;
  1275.             case 'text/plain'$ret ($attempt == 1)Mail_IMAP::getDefaultPid($mid'text/html'2: FALSE;
  1276.             default:           $ret = FALSE;
  1277.         }
  1278.  
  1279.         if ($ret == FALSE && MAIL_IMAP_ERROR_REPORTING == E_ALL && $attempt == 2{
  1280.             PEAR::raiseError('Mail_IMAP::getDefaultPid: Fallback pid used for mid: '.$midNULLPEAR_ERROR_TRIGGERE_USER_NOTICE);
  1281.         }
  1282.  
  1283.         $this->defaultPid[$mid($ret == FALSE)? 1 : $ret;
  1284.  
  1285.         return $this->defaultPid[$mid];
  1286.     }
  1287.  
  1288.     // }}}
  1289.  
  1290.     // {{{ extractMIME()
  1291.     /**
  1292.     * Searches all message parts for the specified MIME type.  Use {@link getBody}
  1293.     * with $action option MAIL_IMAP_LITERAL_DECODE to view MIME type parts retrieved.
  1294.     * If you need to access the MIME type with filename use normal {@link getBody}
  1295.     * with no action specified.
  1296.     *
  1297.     * Returns an array of part ids on success.
  1298.     * Returns FALSE if MIME couldn't be found, or on failure.
  1299.     *
  1300.     * @param    int           &$mid           message id
  1301.     * @param    string|array $MIME           mime type to extract
  1302.     * @return   array|FALSE
  1303.     * @access   public
  1304.     */
  1305.     function extractMIME(&$mid$MIME)
  1306.     {
  1307.         Mail_IMAP::_checkIfParsed($mid);
  1308.  
  1309.         if (is_array($this->_ftype[$mid])) {
  1310.             if (!is_array($MIME)) {
  1311.                 if (0 !== count($pids array_keys($this->_ftype[$mid]$MIME))) {
  1312.                     foreach ($pids as $i{
  1313.                         $rtn[$this->_pid[$mid][$i];
  1314.                     }
  1315.                 else {
  1316.                     $rtn = FALSE;
  1317.                 }
  1318.             else {
  1319.                 foreach ($MIME as $mtype{
  1320.                     if (0 !== count($pids array_keys($this->_ftype[$mid]$mtype))) {
  1321.                         foreach ($pids as $i{
  1322.                             $rtn[$this->_pid[$mid][$i];
  1323.                         }
  1324.                     else {
  1325.                         $rtn = FALSE;
  1326.                     }
  1327.                 }
  1328.             }
  1329.         else {
  1330.             $rtn = FALSE;
  1331.         }
  1332.  
  1333.         return $rtn;
  1334.     }
  1335.     // }}}
  1336.  
  1337.     // {{{ getRawHeaders()
  1338.     /**
  1339.     * Set member variable {@link $rawHeaders} to contain Raw Header information
  1340.     * for a part.  Returns default header part id on success, returns FALSE on failure.
  1341.     *
  1342.     * @param    int     &$mid          message_id
  1343.     * @param    string  $pid           part id
  1344.     * @param    int     $options       flags/options for imap_fetchbody
  1345.     * @param    bool    $rtn           return the raw headers (returns the headers by default)
  1346.     * @return   string|FALSE
  1347.     * @access   public
  1348.     * @see      imap_fetchbody
  1349.     * @see      getHeaders
  1350.     */
  1351.     function getRawHeaders(&$mid$pid '0'$options = NULL$rtn = TRUE)
  1352.     {
  1353.         if (FALSE !== ($pid Mail_IMAP::_defaultHeaderPid($mid$pid))) {
  1354.             if ($pid == '0'{
  1355.                 $this->rawHeaders[$mid(isset($this->option['fetchheader']))? imap_fetchheader($this->mailbox$mid$this->option['fetchheader']: imap_fetchheader($this->mailbox$mid);
  1356.             else {
  1357.                 if (isset($this->option['fetchbody'])) {
  1358.                     $options $this->option['fetchbody'];
  1359.                 }
  1360.                 $this->rawHeaders[$mid= imap_fetchbody($this->mailbox$mid$pid$options);
  1361.             }
  1362.  
  1363.             return ($rtn == TRUE)$this->rawHeaders[$mid$pid;
  1364.         else {
  1365.             PEAR::raiseError('Mail_IMAP::getRawHeaders: Unable to retrieve headers, invalid part id: '.$pidNULLPEAR_ERROR_TRIGGERE_USER_WARNING);
  1366.             return FALSE;
  1367.         }
  1368.     }
  1369.     // }}}
  1370.  
  1371.     // {{{ getHeaders()
  1372.     /**
  1373.     * Set member variable containing header information.  Creates an array containing associative indices
  1374.     * referring to various header information.  Use {@link var_dump} or {@link print_r} on the {@link $header}
  1375.     * member variable to view information gathered by this function.
  1376.     *
  1377.     * Returns header information on success and FALSE on failure.
  1378.     *
  1379.     * @param    int     &$mid           message id
  1380.     * @param    string  &$pid           part id
  1381.     * @param    int     $from_length    (optional) from length for imap_headerinfo
  1382.     * @param    int     $subject_length (optional) subject length for imap_headerinfo
  1383.     * @param    string  $default_host   (optional) default host for imap_headerinfo & imap_rfc822_parse_headers
  1384.     * @param    int     $options        (optional) flags/options for imap_fetchbody (DEPRECATED, use $this->option['fetchbody'])
  1385.     * @return   Array|BOOL
  1386.     * @access   public
  1387.     * @see      getParts
  1388.     * @see      imap_fetchheader
  1389.     * @see      imap_fetchbody
  1390.     * @see      imap_headerinfo
  1391.     * @see      imap_rfc822_parse_headers
  1392.     */
  1393.     function getHeaders(&$mid$pid '0'$from_length = 1024$subject_length = 1024$default_host = NULL$options = NULL)
  1394.     {
  1395.         if (FALSE === ($hpid Mail_IMAP::getRawHeaders($mid$pid$optionsFALSE))) {
  1396.             return FALSE;
  1397.         }
  1398.  
  1399.         // $default_host contains the host information for addresses where it is not
  1400.         // present.  Specify it or attempt to use SERVER_NAME
  1401.         if ($default_host == NULL && isset($_SERVER['SERVER_NAME']&& !empty($_SERVER['SERVER_NAME'])) {
  1402.             $default_host $_SERVER['SERVER_NAME'];
  1403.         else if ($default_host == NULL{
  1404.             $default_host 'UNSPECIFIED-HOST-NAME';
  1405.         }
  1406.  
  1407.         // Parse the headers
  1408.         $header_info ($hpid == '0')? imap_headerinfo($this->mailbox$mid$from_length$subject_length$default_host: imap_rfc822_parse_headers($this->rawHeaders[$mid]$default_host);
  1409.  
  1410.         // Since individual member variable creation might create extra overhead,
  1411.         // and having individual variables referencing this data and the original
  1412.         // object would be too much as well, we'll just copy the object into an
  1413.         // associative array, preform clean-up on those elements that require it,
  1414.         // and destroy the original object after copying.
  1415.  
  1416.         if (!is_object($header_info)) {
  1417.             PEAR::raiseError('Mail_IMAP::getHeaders: Unable to retrieve header object, invalid part id: '.$pidNULLPEAR_ERROR_TRIGGERE_USER_WARNING);
  1418.             return FALSE;
  1419.         }
  1420.  
  1421.         $headers get_object_vars($header_info);
  1422.  
  1423.         foreach ($headers as $key => $value{
  1424.             if (!is_object($value&& !is_array($value)) {
  1425.                 $this->header[$mid][$key$value;
  1426.             }
  1427.         }
  1428.  
  1429.         // copy udate or create it from date string.
  1430.         $this->header[$mid]['udate'(isset($header_info->udate&& !empty($header_info->udate))$header_info->udate : strtotime($header_info->Date);
  1431.  
  1432.         // clean up addresses
  1433.         $line['from';
  1434.         $line['reply_to';
  1435.         $line['sender';
  1436.         $line['return_path';
  1437.         $line['to';
  1438.         $line['cc';
  1439.         $line['bcc';
  1440.  
  1441.         for ($i = 0; $i count($line)$i++{
  1442.             if (isset($header_info->$line[$i])) {
  1443.                 Mail_IMAP::_parseHeaderLine($mid$header_info->$line[$i]$line[$i]);
  1444.             }
  1445.         }
  1446.  
  1447.         // All possible information has been copied, destroy original object
  1448.         unset($header_info);
  1449.  
  1450.         return $this->header[$mid];
  1451.     }
  1452.     // }}}
  1453.  
  1454.     // {{{ _parseHeaderLine()
  1455.     /**
  1456.     * Parse header information from the given line and add it to the {@link $header}
  1457.     * array.  This function is only used by {@link getRawHeaders}.
  1458.     *
  1459.     * @param     string   &$line 
  1460.     * @param     string   $name 
  1461.     * @return    void 
  1462.     * @access    private
  1463.     */
  1464.     function _parseHeaderLine(&$mid&$line$name{
  1465.         if (isset($line&& count($line>= 1{
  1466.             $i = 0;
  1467.             foreach ($line as $object{
  1468.                 if (isset($object->personal)) {
  1469.                     $this->header[$mid][$name.'_personal'][$i$object->personal;
  1470.                 }
  1471.  
  1472.                 if (isset($object->mailbox&& isset($object->host)) {
  1473.                     $this->header[$mid][$name][$i$object->mailbox.'@'.$object->host;
  1474.                 }
  1475.                 $i++;
  1476.             }
  1477.         }
  1478.         return;
  1479.     }
  1480.     // }}}
  1481.  
  1482.     // {{{ _defaultHeaderPid()
  1483.     /**
  1484.     * Finds and returns a default part id for headers and matches any sub message part to
  1485.     * the appropriate headers.  Returns FALSE on failure and may return a value that
  1486.     * evaluates to false, use the '===' operator for testing this function's return value.
  1487.     *
  1488.     * @param    int     &$mid            message id
  1489.     * @param    string  $pid             part id
  1490.     * @return   string|FALSE
  1491.     * @access   private
  1492.     * @see      getHeaders
  1493.     * @see      getRawHeaders
  1494.     */
  1495.     function _defaultHeaderPid(&$mid$pid)
  1496.     {
  1497.         // pid is modified in this function, so don't pass by reference (will create a logic error)
  1498.         Mail_IMAP::_checkIfParsed($mid);
  1499.  
  1500.         // retrieve key for this part, so that the information may be accessed
  1501.         if (FALSE !== ($i array_search((string) $pid$this->_pid[$mid]))) {
  1502.  
  1503.             // If this part is message/rfc822 display headers for this part
  1504.             if ($this->_ftype[$mid][$i== 'message/rfc822'{
  1505.  
  1506.                 $ret = (string) $pid.'.0';
  1507.  
  1508.             else if ($pid == $this->defaultPid[$mid]{
  1509.  
  1510.                 $ret = (string) '0';
  1511.  
  1512.             else {
  1513.  
  1514.                 $pid_len strlen($pid);
  1515.                 $this_nesting count(explode('.'$pid));
  1516.  
  1517.                 // Deeper searching may be required, go back to this part's parent.
  1518.                 if (!strstr($pid'.'|| ($this_nesting - 1== 1{
  1519.  
  1520.                     $ret = (string) '0';
  1521.  
  1522.                 else if ($this_nesting > 2{
  1523.  
  1524.                     // Look at previous parts until a message/rfc822 part is found.
  1525.                     for ($pos $this_nesting - 1; $pos > 0; $pos -= 1{
  1526.  
  1527.                         foreach ($this->_pid[$midas $p => $aid{
  1528.  
  1529.                             $nesting count(explode('.'$this->_pid[$mid][$p]));
  1530.  
  1531.                             if ($nesting == $pos && ($this->_ftype[$mid][$p== 'message/rfc822' || $this->_ftype[$mid][$p== 'multipart/related')) {
  1532.                                 // Break iteration and return!
  1533.                                 return (string) $this->_pid[$mid][$p].'.0';
  1534.                             }
  1535.                         }
  1536.                     }
  1537.  
  1538.                     $ret ($pid_len == 3)? (string) '0' : FALSE;
  1539.  
  1540.                 else {
  1541.                     $ret = FALSE;
  1542.                 }
  1543.             }
  1544.  
  1545.             return $ret;
  1546.  
  1547.         else {
  1548.             // Something's afoot!
  1549.             PEAR::raiseError('Mail_IMAP::_defaultHeaderPid: Unable to retrieve headers, invalid part id: '.$pidNULLPEAR_ERROR_TRIGGERE_USER_WARNING);
  1550.             return FALSE;
  1551.         }
  1552.     }
  1553.     // }}}
  1554.  
  1555.     // {{{ unsetHeaders()
  1556.     /**
  1557.     * Destroys variables set by {@link getHeaders}.
  1558.     *
  1559.     * @param    int     &$mid            message id
  1560.     * @return   void 
  1561.     * @access   public
  1562.     * @see      getHeaders
  1563.     */
  1564.     function unsetHeaders(&$mid)
  1565.     {
  1566.         unset($this->rawHeaders[$mid]);
  1567.         unset($this->header[$mid]);
  1568.         return;
  1569.     }
  1570.     // }}}
  1571.  
  1572.     // {{{ convertBytes()
  1573.     /**
  1574.     * Converts an integer containing the number of bytes in a file to one of Bytes, Kilobytes,
  1575.     * Megabytes, or Gigabytes, appending the unit of measurement.
  1576.     *
  1577.     * This method may be called statically.
  1578.     *
  1579.     * @param    int     $bytes 
  1580.     * @return   string 
  1581.     * @access   public
  1582.     * @static
  1583.     */
  1584.     function convertBytes($bytes)
  1585.     {
  1586.         switch (TRUE{
  1587.             case ($bytes pow(2,10)):                             return $bytes.' Bytes';
  1588.             case ($bytes >= pow(2,10&& $bytes pow(2,20)):      return round($bytes pow(2,10)0).' KB';
  1589.             case ($bytes >= pow(2,20&& $bytes pow(2,30)):      return round($bytes pow(2,20)1).' MB';
  1590.             case ($bytes pow(2,30)):                             return round($bytes pow(2,30)2).' GB';
  1591.         }
  1592.     }
  1593.     // }}}
  1594.  
  1595.     // {{{ delete()
  1596.     /**
  1597.     * Wrapper function for {@link imap_delete}.  Sets the marked for deletion flag.  Note: POP3
  1598.     * mailboxes do not remember flag settings between connections, for POP3 mailboxes
  1599.     * this function should be used in addtion to {@link expunge}.
  1600.     *
  1601.     * @param    int     &$mid   message id
  1602.     * @return   TRUE|PEAR_Error
  1603.     * @access   public
  1604.     * @see      imap_delete
  1605.     * @see      expunge
  1606.     */
  1607.     function delete(&$mid$separator "<br />\n")
  1608.     {
  1609.         if (!is_array($mid)) {
  1610.             return (imap_delete($this->mailbox$mid))? TRUE : PEAR::raiseError('Mail_IMAP::delete: Unable to mark message: '.$mid.' for deletion.');
  1611.         else {
  1612.             foreach ($mid as $id{
  1613.                 if (!imap_delete($this->mailbox$id)) {
  1614.                     $stack['Mail_IMAP::delete: Unable to mark message: '.$id."for deletion.";
  1615.                 }
  1616.             }
  1617.             return (isset($stack&& is_array($stack))? PEAR::raiseError(implode($separator$stack)) : TRUE;
  1618.         }
  1619.     }
  1620.     // }}}
  1621.  
  1622.     // {{{ expunge()
  1623.     /**
  1624.     * Wrapper function for {@link imap_expunge}.  Expunges messages marked for deletion.
  1625.     *
  1626.     * @return   TRUE|PEAR_Error
  1627.     * @access   public
  1628.     * @see      imap_expunge
  1629.     * @see      delete
  1630.     */
  1631.     function expunge()
  1632.     {
  1633.         return (imap_expunge($this->mailbox))? TRUE : PEAR::raiseError('Mail_IMAP::expunge: Unable to expunge mailbox.');
  1634.     }
  1635.     // }}}
  1636.  
  1637.     // {{{ errors()
  1638.     /**
  1639.     * Wrapper function for {@link imap_errors}.  Implodes the array returned by imap_errors,
  1640.     * (if any) and returns the error text.
  1641.     *
  1642.     * @param    string    $seperator     Characters to seperate each error message. '<br />\n' by default.
  1643.     * @return   string|FALSE
  1644.     * @access   public
  1645.     * @see      imap_errors
  1646.     * @see      alerts
  1647.     */
  1648.     function errors($seperator "<br />\n")
  1649.     {
  1650.         $errors = imap_errors();
  1651.         return (is_array($errors&& !empty($errors))implode($seperator$errors: FALSE;
  1652.     }
  1653.     // }}}
  1654.  
  1655.     // {{{ alerts()
  1656.     /**
  1657.     * Wrapper function for {@link imap_alerts}.  Implodes the array returned by imap_alerts,
  1658.     * (if any) and returns the text.
  1659.     *
  1660.     * @param    string    $seperator     Characters to seperate each alert message. '<br />\n' by default.
  1661.     * @return   string|FALSE
  1662.     * @access   public
  1663.     * @see      imap_alerts
  1664.     * @see      errors
  1665.     */
  1666.     function alerts($seperator "<br />\n")
  1667.     {
  1668.         $alerts = imap_alerts();
  1669.         return (is_array($alerts&& !empty($alerts))implode($seperator$alerts: FALSE;
  1670.     }
  1671.     // }}}
  1672.  
  1673.     // {{{ getQuota()
  1674.     /**
  1675.     * Retreives information about the current mailbox's quota.  Rounds up quota sizes and
  1676.     * appends the unit of measurment.  Returns information in a multi-dimensional associative
  1677.     * array.
  1678.     *
  1679.     * @param    string   $folder    Folder to retrieve quota for.
  1680.     * @return   array|PEAR_Error
  1681.     * @throws   Quota not available on this server.  Remedy: none.
  1682.     * @access   public
  1683.     * @see      imap_get_quotaroot
  1684.     */
  1685.     function getQuota($folder = NULL)
  1686.     {
  1687.         if (empty($folder&& !isset($this->mailboxInfo['folder'])) {
  1688.             $folder 'INBOX';
  1689.         else if (empty($folder&& isset($this->mailboxInfo['folder'])) {
  1690.             $folder $this->mailboxInfo['folder'];
  1691.         }
  1692.  
  1693.         $quota @imap_get_quotaroot($this->mailbox$folder);
  1694.  
  1695.         // STORAGE Values are returned in KB
  1696.         // Convert back to bytes first
  1697.         // Then round these to the simpliest unit of measurement
  1698.         if (isset($quota['STORAGE']['usage']&& isset($quota['STORAGE']['limit'])) {
  1699.             $rtn['STORAGE']['usage'Mail_IMAP::convertBytes($quota['STORAGE']['usage'* 1024);
  1700.             $rtn['STORAGE']['limit'Mail_IMAP::convertBytes($quota['STORAGE']['limit'* 1024);
  1701.         }
  1702.         if (isset($quota['MESSAGE']['usage']&& isset($quota['MESSAGE']['limit'])) {
  1703.             $rtn['MESSAGE']['usage'Mail_IMAP::convertBytes($quota['MESSAGE']['usage']);
  1704.             $rtn['MESSAGE']['limit'Mail_IMAP::convertBytes($quota['MESSAGE']['limit']);
  1705.         }
  1706.  
  1707.         return (empty($quota['STORAGE']['usage']&& empty($quota['STORAGE']['limit']))? PEAR::raiseError('Mail_IMAP::getQuota: Quota not available for this server.'$rtn;
  1708.     }
  1709.     // }}}
  1710.  
  1711.     // {{{ setFlags()
  1712.     /**
  1713.     * Wrapper function for {@link imap_setflag_full}.  Sets various message flags.
  1714.     * Accepts an array of message ids and an array of flags to be set.
  1715.     *
  1716.     * The flags which you can set are "\\Seen", "\\Answered", "\\Flagged",
  1717.     * "\\Deleted", and "\\Draft" (as defined by RFC2060).
  1718.     *
  1719.     * Warning: POP3 mailboxes do not remember flag settings from connection to connection.
  1720.     *
  1721.     * @param    array  $mids        Array of message ids to set flags on.
  1722.     * @param    array  $flags       Array of flags to set on messages.
  1723.     * @param    int    $action      Flag operation toggle one of MAIL_IMAP_SET_FLAGS (default) or
  1724.     *                                MAIL_IMAP_CLEAR_FLAGS.
  1725.     * @param    int    $options 
  1726.     *    (optional) sets the forth argument of {@link imap_setflag_full} or {@imap_clearflag_full}. 
  1727.     *
  1728.     * @return   BOOL|PEAR_Error
  1729.     * @throws   Message IDs and Flags are to be supplied as arrays.  Remedy: place message ids
  1730.     *            and flags in arrays.
  1731.     * @access   public
  1732.     * @see      imap_setflag_full
  1733.     * @see      imap_clearflag_full
  1734.     */
  1735.     function setFlags($mids$flags$action = 3$options = NULL)
  1736.     {
  1737.         if (is_array($mids&& is_array($flags)) {
  1738.             if ($action == MAIL_IMAP_SET_FLAGS{
  1739.  
  1740.                 if (isset($this->option['setflag_full'])) {
  1741.                     $options $this->option['setflag_full'];
  1742.                 }
  1743.  
  1744.                 return @imap_setflag_full($this->mailboximplode(','$mids)implode(' '$flags)$options);
  1745.             else {
  1746.  
  1747.                 if (isset($this->option['clearflag_full'])) {
  1748.                     $options $this->option['clearflag_full'];
  1749.                 }
  1750.  
  1751.                 return @imap_clearflag_full($this->mailboximplode(','$mids)implode(' '$flags)$options);
  1752.             }
  1753.         else {
  1754.             return PEAR::raiseError('Mail_IMAP::setFlags: First and second arguments must be arrays.');
  1755.         }
  1756.     }
  1757.     // }}}
  1758.  
  1759.     // {{{ debug()
  1760.     /**
  1761.     * Dumps various information about a message for debugging. Mail_IMAP::debug
  1762.     * is called automatically from Mail_IMAP::connect if $_GET['dump_mid'] isset
  1763.     * and MAIL_IMAP_ERROR_REPORTING == E_ALL || MAIL_IMAP_E_DEBUG.
  1764.     *
  1765.     * $_GET['dump_pid'] - var_dump the $this->_pid[$mid] variable.
  1766.     * $_GET['dump_structure'] - var_dump the structure returned by imap_fetchstructure.
  1767.     * $_GET['test_pid'] - output the body returned by imap_fetchbody.
  1768.     *
  1769.     * Calling on the debugger exits script execution after debugging operations
  1770.     * have been completed.
  1771.     *
  1772.     * @param    int  $mid         $mid to debug
  1773.     * @return   void 
  1774.     * @access   public
  1775.     */
  1776.     function debug($mid = 0)
  1777.     {
  1778.         Mail_IMAP::_checkIfParsed($mid);
  1779.  
  1780.         if (isset($_GET['dump_cid'])) {
  1781.             Mail_IMAP::dump($this->_inlineId[$mid]);
  1782.         }
  1783.         if (isset($_GET['dump_pid'])) {
  1784.             Mail_IMAP::dump($this->_pid[$mid]);
  1785.         }
  1786.         if (isset($_GET['dump_ftype'])) {
  1787.             Mail_IMAP::dump($this->_ftype[$mid]);
  1788.         }
  1789.         if (isset($_GET['dump_structure'])) {
  1790.             Mail_IMAP::dump(imap_fetchstructure($this->mailbox$midNULL));
  1791.         }
  1792.         if (isset($_GET['test_pid'])) {
  1793.             echo imap_fetchbody($this->mailbox$mid$_GET['test_pid']NULL);
  1794.         }
  1795.         if (isset($_GET['dump_mb_list'])) {
  1796.             Mail_IMAP::dump(Mail_IMAP::getMailboxes());
  1797.         }
  1798.         if (isset($_GET['dump_mb_info'])) {
  1799.             Mail_IMAP::dump($this->mailboxInfo);
  1800.         }
  1801.  
  1802.         // Skip everything else in debug mode
  1803.         exit;
  1804.     }
  1805.     // }}}
  1806.  
  1807.     // {{{ dump()
  1808.     /**
  1809.     * Calls on var_dump and outputs with HTML <pre> tags.
  1810.     *
  1811.     * @param    mixed  $thing         $thing to dump.
  1812.     * @return   void 
  1813.     * @access   public
  1814.     */
  1815.     function dump(&$thing)
  1816.     {
  1817.         echo "<pre>\n";
  1818.         var_dump($thing);
  1819.         echo "</pre><br />\n";
  1820.     }
  1821.     // }}}
  1822.  
  1823.     // {{{ getMailboxes()
  1824.     /**
  1825.     * Wrapper method for imap_list.  Calling on this function will return a list of mailboxes.
  1826.     * This method receives the host argument automatically via Mail_IMAP::connect in the
  1827.     * $this->mailboxInfo['host'] variable if a connection URI is used.
  1828.     *
  1829.     * @param    string  (optional) host name.
  1830.     * @return   array   list of mailboxes on the current server.
  1831.     * @access   public
  1832.     * @see      imap_list
  1833.     */
  1834.     function getMailboxes($host = NULL$pattern '*')
  1835.     {
  1836.         if (empty($host&& !isset($this->mailboxInfo['host'])) {
  1837.             return PEAR::raiseError('Mail_IMAP::getMailboxes: Supplied host is not valid!');
  1838.         else if (empty($host&& isset($this->mailboxInfo['host'])) {
  1839.             $host $this->mailboxInfo['host'];
  1840.         }
  1841.  
  1842.         if ($list @imap_list($this->mailbox$host$pattern)) {
  1843.             if (is_array($list)) {
  1844.                 foreach ($list as $val{
  1845.                     $ret[str_replace($host''imap_utf7_decode($val));
  1846.                 }
  1847.             }
  1848.         else {
  1849.             $ret = PEAR::raiseError('Mail_IMAP::getMailboxes: Cannot fetch mailbox names.');
  1850.         }
  1851.  
  1852.         return $ret;
  1853.     }
  1854.     // }}}
  1855. }
  1856. // }}}
  1857. ?>

Documentation generated on Mon, 11 Mar 2019 13:52:29 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.