Net_IMAP-Protocol
[ class tree: Net_IMAP-Protocol ] [ index: Net_IMAP-Protocol ] [ all elements ]

Source for file IMAPProtocol.php

Documentation is available at IMAPProtocol.php

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 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/2_02.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: Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>       |
  17. // +----------------------------------------------------------------------+
  18. require_once 'Net/Socket.php';
  19.  
  20.  
  21.  
  22. /**
  23.  * Provides an implementation of the IMAP protocol using PEAR's
  24.  * Net_Socket:: class.
  25.  *
  26.  * @package Net_IMAP/Protocol
  27.  * @author  Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>
  28.  */
  29.  
  30.  
  31.     /**
  32.     * The auth methods this class support
  33.     * @var array 
  34.     */
  35.     var $supportedAuthMethods=array('DIGEST-MD5''CRAM-MD5''LOGIN');
  36.  
  37.  
  38.     /**
  39.     * The auth methods this class support
  40.     * @var array 
  41.     */
  42.     var $supportedSASLAuthMethods=array('DIGEST-MD5''CRAM-MD5');
  43.  
  44.      /**
  45.      * _serverAuthMethods
  46.      * @var boolean 
  47.      */
  48.     var $_serverAuthMethods = null;
  49.  
  50.  
  51.     /**
  52.      * The the current mailbox
  53.      * @var string 
  54.      */
  55.     var $currentMailbox = "INBOX" ;
  56.  
  57.  
  58.     /**
  59.      * The socket resource being used to connect to the IMAP server.
  60.      * @var resource 
  61.      */
  62.     var $_socket = null;
  63.  
  64.      /**
  65.      * To allow class debuging
  66.      * @var boolean 
  67.      */
  68.     var $_debug = false;
  69.  
  70.     var $dbgDialog = '';
  71.  
  72.      /**
  73.      * Command Number
  74.      * @var int 
  75.      */
  76.     var $_cmd_counter = 1;
  77.  
  78.  
  79.      /**
  80.      * Command Number for IMAP commands
  81.      * @var int 
  82.      */
  83.     var $_lastCmdID = 1;
  84.  
  85.      /**
  86.      * Command Number
  87.      * @var boolean 
  88.      */
  89.     var $_unParsedReturn = false;
  90.  
  91.  
  92.  
  93.      /**
  94.      * _connected: checks if there is a connection made to a imap server or not
  95.      * @var boolean 
  96.      */
  97.     var $_connected = false;
  98.      /**
  99.      * Capabilities
  100.      * @var boolean 
  101.      */
  102.     var $_serverSupportedCapabilities = null;
  103.  
  104.  
  105.  
  106.      /**
  107.      * Use UTF-7 funcionallity
  108.      * @var boolean 
  109.      */
  110.     //var $_useUTF_7 = false;
  111.     var $_useUTF_7 = true;
  112.  
  113.  
  114.  
  115.     /**
  116.      * Constructor
  117.      *
  118.      * Instantiates a new Net_IMAP object.
  119.      *
  120.      * @since  1.0
  121.      */
  122.     function Net_IMAPProtocol()
  123.     {
  124.         $this->_socket = new Net_Socket();
  125.  
  126.         /*
  127.          * Include the Auth_SASL package.  If the package is not available,
  128.          * we disable the authentication methods that depend upon it.
  129.          */
  130.  
  131.  
  132.         if ((@include_once 'Auth/SASL.php'== false{
  133.             foreach($this->supportedSASLAuthMethods as $SASLMethod){
  134.                 $pos array_search$SASLMethod $this->supportedAuthMethods);
  135.                 unset($this->supportedAuthMethods[$pos]);
  136.             }
  137.         }
  138.  
  139.     }
  140.  
  141.  
  142.     /**
  143.      * Attempt to connect to the IMAP server.
  144.      *
  145.      * @return mixed Returns a PEAR_Error with an error message on any
  146.      *                kind of failure, or true on success.
  147.      * @access public
  148.      * @since  1.0
  149.      */
  150.     function cmdConnect($host"localhost"  $port = 143)
  151.     {
  152.         if$this->_connected ){
  153.             return new PEAR_Error'already connected, logout first!' );
  154.         }
  155.         if PEAR::isError$this->_socket->connect$host $port ) ) ) {
  156.             return new PEAR_Error'unable to open socket' );
  157.         }
  158.         if PEAR::isError$this->_getRawResponse() ) ) {
  159.             return new PEAR_Error'unable to open socket' );
  160.         }
  161.         $this->_connected = true;
  162.         return true;
  163.     }
  164.  
  165.  
  166.     /**
  167.      * get the cmd ID
  168.      *
  169.      * @return string Returns the CmdID and increment the counter
  170.      *
  171.      * @access private
  172.      * @since  1.0
  173.      */
  174.     function _getCmdId()
  175.     {
  176.         $this->_lastCmdID "A000" $this->_cmd_counter ;
  177.         $this->_cmd_counter++;
  178.         return $this->_lastCmdID;
  179.     }
  180.  
  181.  
  182.     /**
  183.      * get the last cmd ID
  184.      *
  185.      * @return string Returns the last cmdId
  186.      *
  187.      * @access public
  188.      * @since  1.0
  189.      */
  190.     function getLastCmdId()
  191.     {
  192.         return $this->_lastCmdID;
  193.     }
  194.  
  195.  
  196.  
  197.  
  198.     /**
  199.      * get current mailbox name
  200.      *
  201.      * @return string Returns the current mailbox
  202.      *
  203.      * @access public
  204.      * @since  1.0
  205.      */
  206.     function getCurrentMailbox()
  207.     {
  208.         return $this->currentMailbox;
  209.     }
  210.  
  211.  
  212.  
  213.  
  214.     /**
  215.      * Sets the debuging information on or off
  216.      *
  217.      * @param boolean True or false
  218.      *
  219.      * @return nothing 
  220.      * @access public
  221.      * @since  1.0
  222.      */
  223.     function setDebug($debug = true)
  224.     {
  225.         $this->_debug $debug;
  226.     }
  227.  
  228.  
  229.     function getDebugDialog()
  230.     {
  231.         return $this->dbgDialog;
  232.     }
  233.  
  234.  
  235.  
  236.     /**
  237.      * Send the given string of data to the server.
  238.      *
  239.      * @param   string  $data    The string of data to send.
  240.      *
  241.      * @return  mixed   True on success or a PEAR_Error object on failure.
  242.      *
  243.      * @access  private
  244.      * @since  1.0
  245.      */
  246.     function _send($data)
  247.     {
  248.         if($this->_socket->eof() ){
  249.             return new PEAR_Error'Failed to write to socket: (connection lost!) ' );
  250.         }
  251.         if PEAR::isError$error $this->_socket->write$data ) ) ) {
  252.  
  253.             return new PEAR_Error'Failed to write to socket: ' .
  254.                                   $error->getMessage() );
  255.         }
  256.  
  257.         if$this->_debug ){
  258.             // C: means this data was sent by  the client (this class)
  259.             echo "C: $data";
  260.             $this->dbgDialog.="C: $data";
  261.         }
  262.         return true;
  263.     }
  264.  
  265.     /**
  266.      * Receive the given string of data from the server.
  267.      *
  268.      * @return  mixed   a line of response on success or a PEAR_Error object on failure.
  269.      *
  270.      * @access  private
  271.      * @since  1.0
  272.      */
  273.     function _recvLn()
  274.     {
  275.  
  276.         if (PEAR::isError$this->lastline $this->_socket->gets8192 ) ) ) {
  277.             return new PEAR_Error('Failed to write to socket: ' .
  278.                                               $this->lastline->getMessage() );
  279.         }
  280.         if($this->_debug){
  281.             // S: means this data was sent by  the IMAP Server
  282.             echo "S: " $this->lastline "" ;
  283.             $this->dbgDialog.="S: " $this->lastline "" ;
  284.         }
  285.         if$this->lastline == '' ){
  286.             return new PEAR_Error('Failed to receive from the  socket: '  );
  287.         }
  288.         return $this->lastline;
  289.     }
  290.  
  291.  
  292.  
  293.  
  294.  
  295.     /**
  296.      * Send a command to the server with an optional string of arguments.
  297.      * A carriage return / linefeed (CRLF) sequence will be appended to each
  298.      * command string before it is sent to the IMAP server.
  299.      *
  300.      * @param   string  $commandId  The IMAP cmdID to send to the server.
  301.      * @param   string  $command    The IMAP command to send to the server.
  302.      * @param   string  $args       A string of optional arguments to append
  303.      *                               to the command.
  304.      *
  305.      * @return  mixed   The result of the _send() call.
  306.      *
  307.      * @access  private
  308.      * @since  1.0
  309.      */
  310.     function _putCMD($commandId $command$args '')
  311.     {
  312.         if !empty$args ) ) {
  313.             return $this->_send$commandId " " $command " " $args "\r\n" );
  314.         }
  315.         return $this->_send$commandId " " $command "\r\n" );
  316.     }
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.     /**
  324.      * Get a response from the server with an optional string of commandID.
  325.      * A carriage return / linefeed (CRLF) sequence will be appended to each
  326.      * command string before it is sent to the IMAP server.
  327.      *
  328.      * @param   string  $commandid    The IMAP commandid retrive from the server.
  329.      *
  330.      * @return  string   The result response.
  331.      *
  332.      * @access  private
  333.      */
  334.     function _getRawResponse($commandId '*')
  335.     {
  336.        $arguments '';
  337.        while !PEAR::isError$this->_recvLn() ) ) {
  338.            $reply_code strtok$this->lastline ' ' );
  339.            $arguments.= $this->lastline;
  340.            if !(strcmp$commandId $reply_code ) ) ) {
  341.            return $arguments;
  342.            }
  343.        }
  344.        return $arguments;
  345.      }
  346.  
  347.  
  348.  
  349.  
  350.  
  351.      /**
  352.      * get the "returning of the unparsed response" feature status
  353.      *
  354.      * @return boolean return if the unparsed response is returned or not
  355.      *
  356.      * @access public
  357.      * @since  1.0
  358.      *
  359.      */
  360.     function getUnparsedResponse()
  361.     {
  362.         return $this->_unParsedReturn;
  363.     }
  364.  
  365.  
  366.  
  367.  
  368.  
  369.  
  370.      /**
  371.      * set the "returning of the unparsed response" feature on or off
  372.      *
  373.      * @param  boolean  $status: true: feature is on
  374.      * @return nothing 
  375.      *
  376.      * @access public
  377.      * @since  1.0
  378.      */
  379.     function setUnparsedResponse($status)
  380.     {
  381.         $this->_unParsedReturn $status;
  382.     }
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.     /**
  390.      * Attempt to login to the iMAP server.
  391.      *
  392.      * @param string The userid to authenticate as.
  393.      * @param string The password to authenticate with.
  394.      *
  395.      * @return array Returns an array containing the response
  396.      *
  397.      * @access public
  398.      * @since  1.0
  399.      */
  400.     function cmdLogin($uid $pwd)
  401.     {
  402.         $param="\"$uid\" \"$pwd\"";
  403.         return $this->_genericCommand('LOGIN'$param);
  404.     }
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.     /**
  412.      * Attempt to authenticate to the iMAP server.
  413.      * @param string The userid to authenticate as.
  414.      * @param string The password to authenticate with.
  415.      * @param string The cmdID.
  416.      *
  417.      * @return array Returns an array containing the response
  418.      *
  419.      * @access public
  420.      * @since  1.0
  421.      */
  422.     function cmdAuthenticate($uid $pwd $userMethod = null)
  423.     {
  424.  
  425.         if!$this->_connected ){
  426.             return new PEAR_Error('not connected!');
  427.         }
  428.  
  429.         $cmdid $this->_getCmdId();
  430.  
  431.  
  432.         if PEAR::isError$method $this->_getBestAuthMethod($userMethod) ) ) {
  433.             return $method;
  434.         }
  435.  
  436.  
  437.         switch ($method{
  438.             case 'DIGEST-MD5':
  439.                 $result $this->_authDigest_MD5$uid $pwd $cmdid );
  440.                 break;
  441.             case 'CRAM-MD5':
  442.                 $result $this->_authCRAM_MD5$uid $pwd ,$cmdid );
  443.                 break;
  444.             case 'LOGIN':
  445.                 $result $this->_authLOGIN$uid $pwd $cmdid );
  446.                 break;
  447.  
  448.             default :
  449.                 $result = new PEAR_Error"$method is not a supported authentication method);
  450.                 break;
  451.         }
  452.  
  453.         $args $this->_getRawResponse$cmdid );
  454.         return $this->_genericImapResponseParser$args $cmdid );
  455.  
  456.     }
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.      /* Authenticates the user using the DIGEST-MD5 method.
  466.      *
  467.      * @param string The userid to authenticate as.
  468.      * @param string The password to authenticate with.
  469.      * @param string The cmdID.
  470.      *
  471.      * @return array Returns an array containing the response
  472.      *
  473.      * @access private
  474.      * @since  1.0
  475.      */
  476.     function _authDigest_MD5($uid $pwd $cmdid)
  477.     {
  478.  
  479.         if PEAR::isError($error $this->_putCMD$cmdid ,"AUTHENTICATE" "DIGEST-MD5") ) ) {
  480.             return $error;
  481.         }
  482.  
  483.         if (PEAR::isError$args $this->_recvLn() ) ) {
  484.             return $args;
  485.         }
  486.  
  487.         $this->_getNextToken$args $plus );
  488.  
  489.         $this->_getNextToken$args $space );
  490.  
  491.         $this->_getNextToken$args $challenge );
  492.  
  493.         $challenge base64_decode$challenge );
  494.  
  495.         $digest &Auth_SASL::factory('digestmd5');
  496.  
  497.         $auth_str base64_encode($digest->getResponse($uid$pwd$challenge,"localhost""imap"));
  498.  
  499.         if PEAR::isError$error $this->_send("$auth_str\r\n"))) {
  500.             return $error;
  501.         }
  502.  
  503.         if PEAR::isError$args $this->_recvLn() )) {
  504.             return $args;
  505.         }
  506.         /*
  507.          * We don't use the protocol's third step because IMAP doesn't allow
  508.          * subsequent authentication, so we just silently ignore it.
  509.          */
  510.         if PEAR::isError$error $this->_send"\r\n" ) ) ) {
  511.             return $error;
  512.         }
  513.     }
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.      /* Authenticates the user using the CRAM-MD5 method.
  523.      *
  524.      * @param string The userid to authenticate as.
  525.      * @param string The password to authenticate with.
  526.      * @param string The cmdID.
  527.      *
  528.      * @return array Returns an array containing the response
  529.      *
  530.      * @access private
  531.      * @since  1.0
  532.      */
  533.     function _authCRAM_MD5($uid$pwd$cmdid)
  534.     {
  535.  
  536.  
  537.  
  538.         if PEAR::isError($error $this->_putCMD$cmdid ,"AUTHENTICATE" "CRAM-MD5") ) ) {
  539.             return $error;
  540.         }
  541.  
  542.         if PEAR::isError$args $this->_recvLn() ) ) {
  543.             return $args;
  544.         }
  545.  
  546.         $this->_getNextToken$args $plus );
  547.  
  548.         $this->_getNextToken$args $space );
  549.  
  550.         $this->_getNextToken$args $challenge );
  551.  
  552.         $challenge base64_decode$challenge );
  553.  
  554.         $cram &Auth_SASL::factory('crammd5');
  555.  
  556.         $auth_str base64_encode$cram->getResponse$uid $pwd $challenge ) );
  557.  
  558.         if PEAR::isError$error $this->_send$auth_str."\r\n" ) ) ) {
  559.             return $error;
  560.         }
  561.  
  562.     }
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.      /* Authenticates the user using the LOGIN method.
  573.      *
  574.      * @param string The userid to authenticate as.
  575.      * @param string The password to authenticate with.
  576.      * @param string The cmdID.
  577.      *
  578.      * @return array Returns an array containing the response
  579.      *
  580.      * @access private
  581.      * @since  1.0
  582.      */
  583.     function _authLOGIN($uid$pwd$cmdid)
  584.     {
  585.  
  586.         if (PEAR::isError($error $this->_putCMD($cmdid,"AUTHENTICATE""LOGIN"))) {
  587.             return $error;
  588.         }
  589.  
  590.         if (PEAR::isError($args $this->_recvLn() )) {
  591.             return $args;
  592.         }
  593.  
  594.         $this->_getNextToken$args $plus );
  595.  
  596.         $this->_getNextToken$args $space );
  597.  
  598.         $this->_getNextToken$args $challenge );
  599.  
  600.         $challenge base64_decode$challenge );
  601.  
  602.         $auth_str base64_encode"$uid);
  603.  
  604.         if PEAR::isError$error $this->_send$auth_str."\r\n" ) ) ) {
  605.             return $error;
  606.         }
  607.  
  608.         if (PEAR::isError$args $this->_recvLn() ) ) {
  609.             return $args;
  610.         }
  611.  
  612.         $auth_str base64_encode"$pwd);
  613.  
  614.         if PEAR::isError($error $this->_send$auth_str."\r\n" ) ) ) {
  615.             return $error;
  616.         }
  617.  
  618.     }
  619.  
  620.  
  621.  
  622.  
  623.  
  624.  
  625.  
  626.  
  627.     /**
  628.      * Returns the name of the best authentication method that the server
  629.      * has advertised.
  630.      *
  631.      * @param string if !=null,authenticate with this method ($userMethod).
  632.      *
  633.      * @return mixed    Returns a string containing the name of the best
  634.      *                   supported authentication method or a PEAR_Error object
  635.      *                   if a failure condition is encountered.
  636.      * @access private
  637.      * @since  1.0
  638.      */
  639.     function _getBestAuthMethod($userMethod = null)
  640.     {
  641.        $this->cmdCapability();
  642.  
  643.         if($userMethod != null ){
  644.  
  645.             $methods = array();
  646.  
  647.             $methods[$userMethod;
  648.  
  649.         }else{
  650.             $methods $this->supportedAuthMethods;
  651.         }
  652.  
  653.         if( ($methods != null&& ($this->_serverAuthMethods != null)){
  654.             foreach $methods as $method {
  655.                 if in_array$method $this->_serverAuthMethods ) ) {
  656.                     return $method;
  657.                 }
  658.             }
  659.             $serverMethods=implode(',' ,$this->_serverAuthMethods);
  660.             $myMethods=implode(',' ,$this->supportedAuthMethods);
  661.             return new PEAR_Error("$method NOT supported authentication method!. This IMAP server " .
  662.                 "supports these methods: $serverMethods, but I support $myMethods");
  663.         }else{
  664.             return new PEAR_Error("This IMAP server don't support any Auth methods");
  665.         }
  666.     }
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.     /**
  677.      * Attempt to disconnect from the iMAP server.
  678.      *
  679.      * @return array Returns an array containing the response
  680.      *
  681.      * @access public
  682.      * @since  1.0
  683.      */
  684.     function cmdLogout()
  685.     {
  686.         if!$this->_connected ){
  687.             return new PEAR_Error'not connected!' );
  688.         }
  689.  
  690.         if PEAR::isError$args $this->_genericCommand'LOGOUT' ) ) ) {
  691.             return $args;
  692.         }
  693.         if (PEAR::isError$this->_socket->disconnect() ) ) {
  694.             return new PEAR_Error('socket disconnect failed');
  695.         }
  696.  
  697.         return $args;
  698.         // not for now
  699.         //return $this->_genericImapResponseParser($args,$cmdid);
  700.  
  701.     }
  702.  
  703.  
  704.  
  705.  
  706.  
  707.     /**
  708.      * Send the NOOP command.
  709.      *
  710.      * @return array Returns an array containing the response
  711.      *
  712.      * @access public
  713.      * @since  1.0
  714.      */
  715.     function cmdNoop()
  716.     {
  717.         return $this->_genericCommand('NOOP');
  718.     }
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.     /**
  729.      * Send the CHECK command.
  730.      *
  731.      * @return array Returns an array containing the response
  732.      *
  733.      * @access public
  734.      * @since  1.0
  735.      */
  736.     function cmdCheck()
  737.     {
  738.         return $this->_genericCommand('CHECK');
  739.     }
  740.  
  741.  
  742.  
  743.  
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.     /**
  751.      * Send the  Select Mailbox Command
  752.      *
  753.      * @param string The mailbox to select.
  754.      *
  755.      * @return array Returns an array containing the response
  756.      *
  757.      * @access public
  758.      * @since  1.0
  759.      */
  760.     function cmdSelect($mailbox)
  761.     {
  762.         $mailbox_name=$this->_createQuotedString($mailbox);
  763.         if!PEAR::isError$ret$this->_genericCommand('SELECT'$mailbox_name) ) ){
  764.             $this->currentMailbox  = $mailbox;
  765.         }
  766.         return $ret;
  767.     }
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.     /**
  779.      * Send the  EXAMINE  Mailbox Command
  780.      *
  781.      * @param string The mailbox to examine.
  782.      * @return array Returns an array containing the response
  783.      *
  784.      * @access public
  785.      * @since  1.0
  786.      */
  787.     function cmdExamine($mailbox)
  788.     {
  789.  
  790.         $mailbox_name=$this->_createQuotedString($mailbox);
  791.         $ret=$this->_genericCommand('EXAMINE'$mailbox_name);
  792.         $parsed='';
  793.         if(isset$ret["PARSED") ){
  794.             for($i=0;$i<count($ret["PARSED"])$i++)$command=$ret["PARSED"][$i]["EXT"];
  795.                     $parsed[key($command)]=$command[key($command)];
  796.             }
  797.         }
  798.         return array("PARSED"=>$parsed,"RESPONSE"=>$ret["RESPONSE"]);
  799.     }
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.     /**
  808.      * Send the  CREATE Mailbox Command
  809.      *
  810.      * @param string $mailbox The mailbox to create.
  811.      * @param array  $options options to pass to create
  812.      * @return array Returns an array containing the response
  813.      *
  814.      * @access public
  815.      * @since  1.0
  816.      */
  817.     function cmdCreate($mailbox$options = null)
  818.     {
  819.         $args "";
  820.         $mailbox_name=$this->_createQuotedString($mailbox);
  821.         $args $this->_getCreateParams($options);
  822.         return $this->_genericCommand('CREATE'$mailbox_name.$args);
  823.     }
  824.  
  825.     /**
  826.      * Send the  RENAME Mailbox Command
  827.      *
  828.      * @param string $mailbox     The old mailbox name.
  829.      * @param string $new_mailbox The new (renamed) mailbox name.
  830.      * @param array  $options     options to pass to create
  831.      *
  832.      * @return array Returns an array containing the response
  833.      *
  834.      * @access public
  835.      * @since  1.0
  836.      */
  837.     function cmdRename($mailbox$new_mailbox$options = null)
  838.     {
  839.         $mailbox_name=$this->_createQuotedString($mailbox);
  840.         $new_mailbox_name=$this->_createQuotedString($new_mailbox);
  841.         $args $this->_getCreateParams($options);
  842.         return $this->_genericCommand('RENAME'"$mailbox_name $new_mailbox_name".$args );
  843.     }
  844.  
  845.     /**
  846.      * Send the  DELETE Mailbox Command
  847.      *
  848.      * @param string The mailbox name to delete.
  849.      *
  850.      * @return array Returns an array containing the response
  851.      *
  852.      * @access public
  853.      * @since  1.0
  854.      */
  855.     function cmdDelete($mailbox)
  856.     {
  857.         $mailbox_name=$this->_createQuotedString($mailbox);
  858.         return $this->_genericCommand('DELETE'$mailbox_name);
  859.     }
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.     /**
  868.      * Send the  SUSCRIBE  Mailbox Command
  869.      *
  870.      * @param string The mailbox name to suscribe.
  871.      *
  872.      * @return array Returns an array containing the response
  873.      *
  874.      * @access public
  875.      * @since  1.0
  876.      */
  877.     function cmdSubscribe($mailbox)
  878.     {
  879.         $mailbox_name=$this->_createQuotedString($mailbox);
  880.         return $this->_genericCommand('SUBSCRIBE'$mailbox_name );
  881.     }
  882.  
  883.  
  884.  
  885.  
  886.  
  887.  
  888.  
  889.  
  890.     /**
  891.      * Send the  UNSUSCRIBE  Mailbox Command
  892.      *
  893.      * @return mixed Returns a PEAR_Error with an error message on any
  894.      *                kind of failure, or true on success.
  895.      * @access public
  896.      * @since  1.0
  897.      */
  898.     function cmdUnsubscribe($mailbox)
  899.     {
  900.         $mailbox_name=$this->_createQuotedString($mailbox);
  901.         return $this->_genericCommand('UNSUBSCRIBE'$mailbox_name );
  902.     }
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.     /**
  912.      * Send the  FETCH Command
  913.      *
  914.      * @return mixed Returns a PEAR_Error with an error message on any
  915.      *                kind of failure, or true on success.
  916.      * @access public
  917.      * @since  1.0
  918.      */
  919.     function cmdFetch($msgset$fetchparam)
  920.     {
  921.         return $this->_genericCommand('FETCH' "$msgset $fetchparam);
  922.     }
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.     /**
  931.      * Send the  CAPABILITY Command
  932.      *
  933.      * @return mixed Returns a PEAR_Error with an error message on any
  934.      *                kind of failure, or true on success.
  935.      * @access public
  936.      * @since  1.0
  937.      */
  938.     function cmdCapability()
  939.     {
  940.         $ret $this->_genericCommand'CAPABILITY' );
  941.  
  942.         if(isset$ret["PARSED") ){
  943.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"]["CAPABILITY"];
  944.             //fill the $this->_serverAuthMethods and $this->_serverSupportedCapabilities arrays
  945.             foreach$ret["PARSED"]["CAPABILITIES"as $auth_method ){
  946.                 ifstrtouppersubstr$auth_method ,) ) == "AUTH=" )
  947.                     $this->_serverAuthMethods[substr$auth_method );
  948.             }
  949.             // Keep the capabilities response to use ir later
  950.             $this->_serverSupportedCapabilities $ret["PARSED"]["CAPABILITIES"];
  951.         }
  952.  
  953.         return $ret;
  954.     }
  955.  
  956.     /**
  957.      * Send the  CAPABILITY Command
  958.      *
  959.      * @return mixed Returns a PEAR_Error with an error message on any
  960.      *                kind of failure, or true on success.
  961.      * @access public
  962.      * @since  1.0
  963.      */
  964.     function cmdNamespace()
  965.     {
  966.         $ret $this->_genericCommand'NAMESPACE' );
  967.  
  968.         if(isset$ret["PARSED") ){
  969.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"]["NAMESPACE"];
  970.             // Keep the namespace response for later use
  971.             $this->_namespace $ret["PARSED"]["NAMESPACES"];
  972.         }
  973.  
  974.         return $ret;
  975.     }
  976.  
  977.  
  978.     /**
  979.      * Send the  STATUS Mailbox Command
  980.      *
  981.      * @param string $mailbox the mailbox name
  982.      * @param mixed  $request the request status
  983.      *                         it could be an array or space separated string of
  984.      *                         MESSAGES | RECENT | UIDNEXT
  985.      *                         UIDVALIDITY | UNSEEN
  986.      * @return array Returns a Parsed Response
  987.      *
  988.      * @access public
  989.      * @since  1.0
  990.      */
  991.     function cmdStatus($mailbox$request)
  992.     {
  993.         $mailbox_name=$this->_createQuotedString($mailbox);
  994.  
  995.         // make array from $request if it is none
  996.         if (!is_array($request)) {
  997.             $request explode(' '$request);
  998.         }
  999.  
  1000.         // see RFC 3501
  1001.         $valid_status_data = array('MESSAGES''RECENT''UIDNEXT''UIDVALIDITY''UNSEEN');
  1002.  
  1003.         foreach ($request as $status_data{
  1004.             if (!in_array($status_data$valid_status_data)) {
  1005.                 $this->_prot_error("request '$status_data' is invalid! see RFC 3501!!!!__LINE__ __FILE__);
  1006.             }
  1007.         }
  1008.         
  1009.         // back to space separated string
  1010.         $request implode(' '$request);
  1011.  
  1012.         $ret $this->_genericCommand('STATUS'$mailbox_name.' ('.$request.')');
  1013.         if (isset($ret['PARSED'])) {
  1014.             $ret['PARSED']=$ret['PARSED'][count($ret['PARSED'])-1]['EXT'];
  1015.         }
  1016.         return $ret;
  1017.     }
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.     /**
  1025.      * Send the  LIST  Command
  1026.      *
  1027.      * @return mixed Returns a PEAR_Error with an error message on any
  1028.      *                kind of failure, or true on success.
  1029.      * @access public
  1030.      * @since  1.0
  1031.      */
  1032.     function cmdList($mailbox_base$mailbox)
  1033.     {
  1034.         $mailbox_name=$this->_createQuotedString($mailbox);
  1035.         $mailbox_base=$this->_createQuotedString($mailbox_base);
  1036.         return $this->_genericCommand('LIST'"$mailbox_base $mailbox_name);
  1037.     }
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.     /**
  1045.      * Send the  LSUB  Command
  1046.      *
  1047.      * @return mixed Returns a PEAR_Error with an error message on any
  1048.      *                kind of failure, or true on success.
  1049.      * @access public
  1050.      * @since  1.0
  1051.      */
  1052.     function cmdLsub($mailbox_base$mailbox)
  1053.     {
  1054.         $mailbox_name=$this->_createQuotedString($mailbox);
  1055.         $mailbox_base=$this->_createQuotedString($mailbox_base);
  1056.         return $this->_genericCommand('LSUB'"$mailbox_base $mailbox_name);
  1057.     }
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.     /**
  1065.      * Send the  APPEND  Command
  1066.      *
  1067.      * @return mixed Returns a PEAR_Error with an error message on any
  1068.      *                kind of failure, or true on success.
  1069.      * @access public
  1070.      * @since  1.0
  1071.      */
  1072.     function cmdAppend($mailbox$msg $flags_list '' ,$time '')
  1073.     {
  1074.         if(!$this->_connected){
  1075.             return new PEAR_Error('not connected!');
  1076.         }
  1077.  
  1078.  
  1079.         $cmdid=$this->_getCmdId();
  1080.         $msg_size=$this->_getLineLength($msg);
  1081.  
  1082.         $mailbox_name=$this->_createQuotedString($mailbox);
  1083.         if($flags_list != ''{
  1084.           $flags_list = " ($flags_list)";
  1085.         }
  1086.         // TODO:
  1087.         // Falta el codigo para que flags list y time hagan algo!!
  1088.         if$this->hasCapability"LITERAL+" == true ){
  1089.             $param=sprintf("%s%s%s {%s+}\r\n%s",$mailbox_name,$flags_list,$time,$msg_size,$msg);
  1090.             if (PEAR::isError($error $this->_putCMD($cmdid 'APPEND' $param ) ) ) {
  1091.                 return $error;
  1092.             }
  1093.         }else{
  1094.             $param=sprintf("%s%s%s {%s}",$mailbox_name,$flags_list,$time,$msg_size);
  1095.             if (PEAR::isError($error $this->_putCMD($cmdid 'APPEND' $param ) ) ) {
  1096.             return $error;
  1097.             }
  1098.             if (PEAR::isError($error $this->_recvLn() ) ) {
  1099.             return $error;
  1100.             }
  1101.  
  1102.             if (PEAR::isError($error $this->_send$msg."\r\n" ) ) ) {
  1103.             return $error;
  1104.             }
  1105.         }
  1106.  
  1107.  
  1108.         $args=$this->_getRawResponse($cmdid);
  1109.         $ret $this->_genericImapResponseParser($args,$cmdid);
  1110.         return $ret;
  1111.     }
  1112.  
  1113.  
  1114.  
  1115.     /**
  1116.      * Send the CLOSE command.
  1117.      *
  1118.      * @return mixed Returns a PEAR_Error with an error message on any
  1119.      *                kind of failure, or true on success.
  1120.      * @access public
  1121.      * @since  1.0
  1122.      */
  1123.     function cmdClose()
  1124.     {
  1125.         return $this->_genericCommand('CLOSE');
  1126.     }
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.     /**
  1134.      * Send the EXPUNGE command.
  1135.      *
  1136.      * @return mixed Returns a PEAR_Error with an error message on any
  1137.      *                kind of failure, or true on success.
  1138.      * @access public
  1139.      * @since  1.0
  1140.      */
  1141.     function cmdExpunge()
  1142.     {
  1143.         $ret=$this->_genericCommand('EXPUNGE');
  1144.  
  1145.         if(isset$ret["PARSED") ){
  1146.            $parsed=$ret["PARSED"];
  1147.             unset($ret["PARSED"]);
  1148.             foreach($parsed as $command){
  1149.                 ifstrtoupper($command["COMMAND"]== 'EXPUNGE' ){
  1150.                         $ret["PARSED"][$command["COMMAND"]][]=$command["NRO"];
  1151.                 }else{
  1152.                         $ret["PARSED"][$command["COMMAND"]]=$command["NRO"];
  1153.                 }
  1154.             }
  1155.         }
  1156.         return $ret;
  1157.     }
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.     /**
  1166.      * Send the SEARCH command.
  1167.      *
  1168.      * @return mixed Returns a PEAR_Error with an error message on any
  1169.      *                kind of failure, or true on success.
  1170.      * @access public
  1171.      * @since  1.0
  1172.      */
  1173.  
  1174.     function cmdSearch($search_cmd)
  1175.     {
  1176.         /*        if($_charset != '' )
  1177.                     $_charset = "[$_charset] ";
  1178.                 $param=sprintf("%s%s",$charset,$search_cmd);
  1179.         */
  1180.         $ret $this->_genericCommand('SEARCH'$search_cmd );
  1181.         if(isset$ret["PARSED") ){
  1182.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1183.         }
  1184.         return $ret;
  1185.     }
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.     /**
  1193.      * Send the STORE command.
  1194.      *
  1195.      * @param string $message_set  the sessage_set
  1196.      * @param string $dataitem: the way we store the flags
  1197.      *           FLAGS: replace the flags whith $value
  1198.      *           FLAGS.SILENT: replace the flags whith $value but don't return untagged responses
  1199.      *
  1200.      *           +FLAGS: Add the flags whith $value
  1201.      *           +FLAGS.SILENT: Add the flags whith $value but don't return untagged responses
  1202.      *
  1203.      *           -FLAGS: Remove the flags whith $value
  1204.      *           -FLAGS.SILENT: Remove the flags whith $value but don't return untagged responses
  1205.      *
  1206.      * @param string $value 
  1207.      * @return mixed Returns a PEAR_Error with an error message on any
  1208.      *                kind of failure, or true on success.
  1209.      * @access public
  1210.      * @since  1.0
  1211.      */
  1212.  
  1213.     function cmdStore($message_set$dataitem$value)
  1214.     {
  1215.         /* As said in RFC2060...
  1216.         C: A003 STORE 2:4 +FLAGS (\Deleted)
  1217.         S: * 2 FETCH FLAGS (\Deleted \Seen)
  1218.         S: * 3 FETCH FLAGS (\Deleted)
  1219.         S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen)
  1220.         S: A003 OK STORE completed
  1221.         */
  1222.         if$dataitem!="FLAGS" && $dataitem!="FLAGS.SILENT" && $dataitem!="+FLAGS" &&
  1223.             $dataitem!="+FLAGS.SILENT" && $dataitem!="-FLAGS" && $dataitem!="-FLAGS.SILENT" ){
  1224.             $this->_prot_error("dataitem '$dataitem' is invalid! see RFC2060!!!!__LINE__ __FILE__ );
  1225.         }
  1226.         $param=sprintf("%s %s (%s)",$message_set,$dataitem,$value);
  1227.         return $this->_genericCommand('STORE'$param );
  1228.     }
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.     /**
  1237.      * Send the COPY command.
  1238.      *
  1239.      * @return mixed Returns a PEAR_Error with an error message on any
  1240.      *                kind of failure, or true on success.
  1241.      * @access public
  1242.      * @since  1.0
  1243.      */
  1244.  
  1245.     function cmdCopy($message_set$mailbox)
  1246.     {
  1247.         $mailbox_name=$this->_createQuotedString($mailbox);
  1248.         return $this->_genericCommand('COPY'sprintf("%s %s",$message_set,$mailbox_name) );
  1249.     }
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261.  
  1262.  
  1263.     function cmdUidFetch($msgset$fetchparam)
  1264.     {
  1265.         return $this->_genericCommand('UID FETCH'sprintf("%s %s",$msgset,$fetchparam) );
  1266.     }
  1267.  
  1268.  
  1269.  
  1270.  
  1271.  
  1272.  
  1273.  
  1274.  
  1275.     function cmdUidCopy($message_set$mailbox)
  1276.     {
  1277.         $mailbox_name=$this->_createQuotedString($mailbox);
  1278.         return $this->_genericCommand('UID COPY'sprintf("%s %s",$message_set,$mailbox_name) );
  1279.     }
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287.  
  1288.      /**
  1289.      * Send the UID STORE command.
  1290.      *
  1291.      * @param string $message_set  the sessage_set
  1292.      * @param string $dataitem: the way we store the flags
  1293.      *           FLAGS: replace the flags whith $value
  1294.      *           FLAGS.SILENT: replace the flags whith $value but don't return untagged responses
  1295.      *
  1296.      *           +FLAGS: Add the flags whith $value
  1297.      *           +FLAGS.SILENT: Add the flags whith $value but don't return untagged responses
  1298.      *
  1299.      *           -FLAGS: Remove the flags whith $value
  1300.      *           -FLAGS.SILENT: Remove the flags whith $value but don't return untagged responses
  1301.      *
  1302.      * @param string $value 
  1303.      * @return mixed Returns a PEAR_Error with an error message on any
  1304.      *                kind of failure, or true on success.
  1305.      * @access public
  1306.      * @since  1.0
  1307.      */
  1308.  
  1309.     function cmdUidStore($message_set$dataitem$value)
  1310.     {
  1311.         /* As said in RFC2060...
  1312.         C: A003 STORE 2:4 +FLAGS (\Deleted)
  1313.         S: * 2 FETCH FLAGS (\Deleted \Seen)
  1314.         S: * 3 FETCH FLAGS (\Deleted)
  1315.         S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen)
  1316.         S: A003 OK STORE completed
  1317.         */
  1318.         if$dataitem!="FLAGS" && $dataitem!="FLAGS.SILENT" && $dataitem!="+FLAGS" &&
  1319.             $dataitem!="+FLAGS.SILENT" && $dataitem!="-FLAGS" && $dataitem!="-FLAGS.SILENT" ){
  1320.             $this->_prot_error("dataitem '$dataitem' is invalid! see RFC2060!!!!__LINE__ __FILE__ );
  1321.         }
  1322.         return $this->_genericCommand('UID STORE'sprintf("%s %s (%s)",$message_set,$dataitem,$value) );
  1323.     }
  1324.  
  1325.  
  1326.  
  1327.  
  1328.  
  1329.  
  1330.  
  1331.  
  1332.  
  1333.  
  1334.     /**
  1335.      * Send the SEARCH command.
  1336.      *
  1337.      * @return mixed Returns a PEAR_Error with an error message on any
  1338.      *                kind of failure, or true on success.
  1339.      * @access public
  1340.      * @since  1.0
  1341.      */
  1342.  
  1343.     function cmdUidSearch($search_cmd)
  1344.     {
  1345.         $ret=$this->_genericCommand('UID SEARCH'sprintf("%s",$search_cmd) );
  1346.         if(isset$ret["PARSED") ){
  1347.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1348.         }
  1349.         return $ret;
  1350.     }
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.     /**
  1363.      * Send the X command.
  1364.      *
  1365.      * @return mixed Returns a PEAR_Error with an error message on any
  1366.      *                kind of failure, or true on success.
  1367.      * @access public
  1368.      * @since  1.0
  1369.      */
  1370.  
  1371.     function cmdX($atom$parameters)
  1372.     {
  1373.         return $this->_genericCommand("X$atom"$parameters );
  1374.     }
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383. /********************************************************************
  1384. ***
  1385. ***             HERE ENDS the RFC2060 IMAPS FUNCTIONS
  1386. ***             AND BEGIN THE EXTENSIONS FUNCTIONS
  1387. ***
  1388. ********************************************************************/
  1389.  
  1390.  
  1391.  
  1392.  
  1393.  
  1394.  
  1395.  
  1396. /********************************************************************
  1397. ***             RFC2087 IMAP4 QUOTA extension BEGINS HERE
  1398. ********************************************************************/
  1399.  
  1400.  
  1401.     /**
  1402.      * Send the GETQUOTA command.
  1403.      *
  1404.      * @param string $mailbox_name the mailbox name to query for quota data
  1405.      * @return mixed Returns a PEAR_Error with an error message on any
  1406.      *                kind of failure, or quota data on success
  1407.      * @access public
  1408.      * @since  1.0
  1409.      */
  1410.  
  1411.     function cmdGetQuota($mailbox_name)
  1412.     {
  1413.  
  1414.  
  1415.         //Check if the IMAP server has QUOTA support
  1416.         if$this->hasQuotaSupport() ){
  1417.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1418.         }
  1419.         $mailbox_name=sprintf("%s",$this->utf_7_encode($mailbox_name) );
  1420.         $ret $this->_genericCommand('GETQUOTA'$mailbox_name );
  1421.         if(isset$ret["PARSED") ){
  1422.         // remove the array index because the quota response returns only 1 line of output
  1423.             $ret['PARSED']=$ret["PARSED"][0];
  1424.         }
  1425.         return $ret;
  1426.     }
  1427.  
  1428.  
  1429.     /**
  1430.      * Send the GETQUOTAROOT command.
  1431.      *
  1432.      * @param string $mailbox_name the mailbox name to query for quota data
  1433.      * @return mixed Returns a PEAR_Error with an error message on any
  1434.      *                kind of failure, or quota data on success
  1435.      * @access public
  1436.      * @since  1.0
  1437.      */
  1438.  
  1439.     function cmdGetQuotaRoot($mailbox_name)
  1440.     {
  1441.         //Check if the IMAP server has QUOTA support
  1442.         if$this->hasQuotaSupport() ){
  1443.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1444.         }
  1445.         $mailbox_name=sprintf("%s",$this->utf_7_encode($mailbox_name) );
  1446.         $ret $this->_genericCommand('GETQUOTAROOT'$mailbox_name );
  1447.  
  1448.         if(isset$ret["PARSED") ){
  1449.         // remove the array index because the quota response returns only 1 line of output
  1450.             $ret['PARSED']=$ret["PARSED"][1];
  1451.         }
  1452.         return $ret;
  1453.     }
  1454.  
  1455.  
  1456.  
  1457.  
  1458.     /**
  1459.      * Send the SETQUOTA command.
  1460.      *
  1461.      * @param string $mailbox_name the mailbox name to query for quota data
  1462.      * @param string $storageQuota sets the max number of bytes this mailbox can handle
  1463.      * @param string $messagesQuota sets the max number of messages this mailbox can handle
  1464.      * @return mixed Returns a PEAR_Error with an error message on any
  1465.      *                kind of failure, or quota data on success
  1466.      * @access public
  1467.      * @since  1.0
  1468.      */
  1469. // TODO:  implement the quota by number of emails!!
  1470.     function cmdSetQuota($mailbox_name$storageQuota = null ,$messagesQuota = null )
  1471.     {
  1472.         //Check if the IMAP server has QUOTA support
  1473.         if$this->hasQuotaSupport() ){
  1474.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1475.         }
  1476.  
  1477.         if( ($messagesQuota == null&& $storageQuota == null) ){
  1478.             return new PEAR_Error('$storageQuota and $messagesQuota parameters can\'t be both null if you want to use quota');
  1479.         }
  1480.         $mailbox_name=$this->_createQuotedString($mailbox_name);
  1481.         //Make the command request
  1482.         $param=sprintf("%s (",$mailbox_name);
  1483.         if($storageQuota != null ){
  1484.             if ($storageQuota == -1{
  1485.                 // set -1 to remove a quota
  1486.                 $param sprintf("%s"$param);
  1487.             elseif ($storageQuota == strtolower('remove')) {
  1488.                 // this is a cyrus rmquota specific feature
  1489.                 // see http://email.uoa.gr/projects/cyrus/quota-patches/rmquota/
  1490.                 $param sprintf("%sREMOVE 1"$param);
  1491.             else {
  1492.                 $param sprintf("%sSTORAGE %s"$param$storageQuota);
  1493.             }
  1494.             if$messagesQuota != null ){
  1495.                 //if we have both types of quota on the same call we must append an space between
  1496.                 // those parameters
  1497.                 $param=sprintf("%s ",$param);
  1498.             }
  1499.         }
  1500.         if($messagesQuota != null ){
  1501.             $param=sprintf("%sMESSAGES %s",$param,$messagesQuota);
  1502.  
  1503.         }
  1504.         $param=sprintf("%s)",$param);
  1505.  
  1506.         return $this->_genericCommand('SETQUOTA'$param );
  1507.     }
  1508.  
  1509.  
  1510.  
  1511.     /**
  1512.      * Send the SETQUOTAROOT command.
  1513.      *
  1514.      * @param string $mailbox_name the mailbox name to query for quota data
  1515.      * @param string $storageQuota sets the max number of bytes this mailbox can handle
  1516.      * @param string $messagesQuota sets the max number of messages this mailbox can handle
  1517.      * @return mixed Returns a PEAR_Error with an error message on any
  1518.      *                kind of failure, or quota data on success
  1519.      * @access public
  1520.      * @since  1.0
  1521.      */
  1522.     function cmdSetQuotaRoot($mailbox_name$storageQuota = null ,$messagesQuota = null)
  1523.     {
  1524.         //Check if the IMAP server has QUOTA support
  1525.         if$this->hasQuotaSupport() ){
  1526.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1527.         }
  1528.  
  1529.         if( ($messagesQuota == null&& $storageQuota == null) ){
  1530.             return new PEAR_Error('$storageQuota and $messagesQuota parameters can\'t be both null if you want to use quota');
  1531.         }
  1532.         $mailbox_name=$this->_createQuotedString($mailbox_name);
  1533.         //Make the command request
  1534.         $param=sprintf("%s (",$mailbox_name);
  1535.         if($storageQuota != null ){
  1536.             $param=sprintf("%sSTORAGE %s",$param,$storageQuota);
  1537.             if$messagesQuota != null ){
  1538.                 //if we have both types of quota on the same call we must append an space between
  1539.                 // those parameters
  1540.                 $param=sprintf("%s ",$param);
  1541.             }
  1542.         }
  1543.         if($messagesQuota != null ){
  1544.             $param=sprintf("%sMESSAGES %s",$param,$messagesQuota);
  1545.  
  1546.         }
  1547.         $param=sprintf("%s)",$param);
  1548.  
  1549.         return $this->_genericCommand('SETQUOTAROOT'$param );
  1550.     }
  1551.  
  1552.  
  1553.  
  1554. /********************************************************************
  1555. ***             RFC2087 IMAP4 QUOTA extension ENDS HERE
  1556. ********************************************************************/
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563. /********************************************************************
  1564. ***             RFC2086 IMAP4 ACL extension BEGINS HERE
  1565. ********************************************************************/
  1566.  
  1567.  
  1568.  
  1569.  
  1570.     function cmdSetACL($mailbox_name$user$acl)
  1571.     {
  1572.  
  1573.         //Check if the IMAP server has ACL support
  1574.         if$this->hasAclSupport() ){
  1575.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1576.         }
  1577.         $mailbox_name=$this->_createQuotedString($mailbox_name);
  1578.         $user_name=$this->_createQuotedString($user);
  1579.         if(is_array($acl)){
  1580.             $acl=implode('',$acl);
  1581.         }
  1582.         return $this->_genericCommand('SETACL'sprintf("%s %s \"%s\"",$mailbox_name,$user_name,$acl) );
  1583.     }
  1584.  
  1585.  
  1586.  
  1587.  
  1588.  
  1589.  
  1590.     function cmdDeleteACL($mailbox_name$user)
  1591.     {
  1592.         //Check if the IMAP server has ACL support
  1593.         if$this->hasAclSupport() ){
  1594.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1595.         }
  1596.         $mailbox_name=$this->_createQuotedString($mailbox_name);
  1597.         
  1598.         return $this->_genericCommand('DELETEACL'sprintf("%s \"%s\"",$mailbox_name,$user) );
  1599.     }
  1600.  
  1601.  
  1602.  
  1603.  
  1604.  
  1605.  
  1606.  
  1607.  
  1608.  
  1609.     function cmdGetACL($mailbox_name)
  1610.     {
  1611.         //Check if the IMAP server has ACL support
  1612.         if$this->hasAclSupport() ){
  1613.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1614.         }
  1615.         $mailbox_name=$this->_createQuotedString($mailbox_name);
  1616.         $ret $this->_genericCommand('GETACL'sprintf("%s",$mailbox_name) );
  1617.         if(isset$ret["PARSED") ){
  1618.             $ret['PARSED']=$ret["PARSED"][0]["EXT"];
  1619.  
  1620.         }
  1621.         return $ret;
  1622.    }
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630.     function cmdListRights($mailbox_name$user)
  1631.     {
  1632.         //Check if the IMAP server has ACL support
  1633.         if$this->hasAclSupport() ){
  1634.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1635.         }
  1636.         $mailbox_name=$this->_createQuotedString($mailbox_name);
  1637.         $ret $this->_genericCommand('LISTRIGHTS'sprintf("%s \"%s\"",$mailbox_name,$user) );
  1638.         if(isset$ret["PARSED") ){
  1639.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1640.         }
  1641.         return $ret;
  1642.     }
  1643.  
  1644.  
  1645.  
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.     function cmdMyRights($mailbox_name)
  1653.     {
  1654.         //Check if the IMAP server has ACL support
  1655.         if$this->hasAclSupport() ){
  1656.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1657.         }
  1658.         $mailbox_name=$this->_createQuotedString($mailbox_name);
  1659.         $ret $this->_genericCommand('MYRIGHTS'sprintf("%s",$mailbox_name) );
  1660.         if(isset$ret["PARSED") ){
  1661.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1662.         }
  1663.         return $ret;
  1664.     }
  1665.  
  1666.  
  1667. /********************************************************************
  1668. ***             RFC2086 IMAP4 ACL extension ENDs HERE
  1669. ********************************************************************/
  1670.  
  1671.  
  1672.  
  1673.  
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.  
  1680.  
  1681.  
  1682. /*******************************************************************************
  1683. ***  draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension BEGINS HERE
  1684. ********************************************************************************/
  1685.  
  1686.  
  1687.  
  1688.     function cmdSetAnnotation($mailbox_name$entry$values)
  1689.     {
  1690.         // Check if the IMAP server has ANNOTATEMORE support
  1691.         if(!$this->hasAnnotateMoreSupport()) {
  1692.             return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!');
  1693.         }
  1694.         if (!is_array($values)) {
  1695.             return new PEAR_Error('Invalid $values argument passed to cmdSetAnnotation');
  1696.         }
  1697.  
  1698.         $vallist '';
  1699.         foreach ($values as $name => $value{
  1700.             $vallist .= "\"$name\" \"$value\" ";
  1701.         }
  1702.         $vallist rtrim($vallist);
  1703.  
  1704.         return $this->_genericCommand('SETANNOTATION'sprintf('"%s" "%s" (%s)'$mailbox_name$entry$vallist));
  1705.     }
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.     function cmdDeleteAnnotation($mailbox_name$entry$values)
  1720.     {
  1721.         // Check if the IMAP server has ANNOTATEMORE support
  1722.         if(!$this->hasAnnotateMoreSupport()) {
  1723.             return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!');
  1724.         }
  1725.         if (!is_array($values)) {
  1726.             return new PEAR_Error('Invalid $values argument passed to cmdDeleteAnnotation');
  1727.         }
  1728.  
  1729.         $vallist '';
  1730.         foreach ($values as $name{
  1731.             $vallist .= "\"$name\" NIL ";
  1732.         }
  1733.         $vallist rtrim($vallist);
  1734.  
  1735.         return $this->_genericCommand('SETANNOTATION'sprintf('"%s" "%s" (%s)'$mailbox_name$entry$vallist));
  1736.     }
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744.  
  1745.  
  1746.  
  1747.  
  1748.  
  1749.     function cmdGetAnnotation($mailbox_name$entries$values)
  1750.     {
  1751.         // Check if the IMAP server has ANNOTATEMORE support
  1752.         if(!$this->hasAnnotateMoreSupport()) {
  1753.             return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!');
  1754.         }
  1755.  
  1756.         $entlist '';
  1757.  
  1758.        if (!is_array($entries)) {
  1759.             $entries = array($entries);
  1760.        }
  1761.  
  1762.         foreach ($entries as $name{
  1763.             $entlist .= "\"$name\" ";
  1764.         }
  1765.         $entlist rtrim($entlist);
  1766.         if (count($entries> 1{
  1767.             $entlist = "($entlist)";
  1768.         }
  1769.  
  1770.  
  1771.  
  1772.         $vallist '';
  1773.         if (!is_array($values)) {
  1774.             $values = array($values);
  1775.         }
  1776.  
  1777.         foreach ($values as $name{
  1778.             $vallist .= "\"$name\" ";
  1779.         }
  1780.         $vallist rtrim($vallist);
  1781.         if (count($values> 1{
  1782.             $vallist = "($vallist)";
  1783.         }
  1784.  
  1785.         return $this->_genericCommand('GETANNOTATION'sprintf('"%s" %s %s'$mailbox_name$entlist$vallist));
  1786.    }
  1787.  
  1788.  
  1789. /*****************************************************************************
  1790. ***  draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension ENDs HERE
  1791. ******************************************************************************/
  1792.  
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.  
  1799. /********************************************************************
  1800. ***
  1801. ***             HERE ENDS THE EXTENSIONS FUNCTIONS
  1802. ***             AND BEGIN THE AUXILIARY FUNCTIONS
  1803. ***
  1804. ********************************************************************/
  1805.  
  1806.  
  1807.  
  1808.  
  1809.  
  1810.     /**
  1811.     * tell if the server has capability $capability
  1812.     *
  1813.     * @return true or false
  1814.     *
  1815.     * @access public
  1816.     * @since  1.0
  1817.     */
  1818.     function getServerAuthMethods()
  1819.     {
  1820.         if$this->_serverAuthMethods == null ){
  1821.             $this->cmdCapability();
  1822.             return $this->_serverAuthMethods;
  1823.         }
  1824.         return false;
  1825.     }
  1826.  
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.  
  1833.     /**
  1834.     * tell if the server has capability $capability
  1835.     *
  1836.     * @return true or false
  1837.     *
  1838.     * @access public
  1839.     * @since  1.0
  1840.     */
  1841.     function hasCapability($capability)
  1842.     {
  1843.         if$this->_serverSupportedCapabilities == null ){
  1844.             $this->cmdCapability();
  1845.         }
  1846.         if($this->_serverSupportedCapabilities != null ){
  1847.             ifin_array$capability $this->_serverSupportedCapabilities ) ){
  1848.                 return true;
  1849.             }
  1850.         }
  1851.         return false;
  1852.     }
  1853.  
  1854.  
  1855.  
  1856.     /**
  1857.     * tell if the server has Quota support
  1858.     *
  1859.     * @return true or false
  1860.     *
  1861.     * @access public
  1862.     * @since  1.0
  1863.     */
  1864.     function hasQuotaSupport()
  1865.     {
  1866.         return $this->hasCapability('QUOTA');
  1867.     }
  1868.  
  1869.  
  1870.  
  1871.  
  1872.  
  1873.     /**
  1874.     * tell if the server has Quota support
  1875.     *
  1876.     * @return true or false
  1877.     *
  1878.     * @access public
  1879.     * @since  1.0
  1880.     */
  1881.     function hasAclSupport()
  1882.     {
  1883.         return $this->hasCapability('ACL');
  1884.     }
  1885.  
  1886.  
  1887.  
  1888.  
  1889.  
  1890.     /**
  1891.     * tell if the server has support for the ANNOTATEMORE extension
  1892.     *
  1893.     * @return true or false
  1894.     *
  1895.     * @access public
  1896.     * @since  1.0
  1897.     */
  1898.     function hasAnnotateMoreSupport()
  1899.     {
  1900.         return $this->hasCapability('ANNOTATEMORE');
  1901.     }
  1902.  
  1903.  
  1904.  
  1905.     function _createQuotedString($mailbox
  1906.     {
  1907.       $search = array('\\''"');
  1908.       $replace = array('\\\\''\\"');
  1909.  
  1910.       $mailbox_name str_replace($search$replace$mailbox);
  1911.       $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1912.  
  1913.       return $mailbox_name;
  1914.     }
  1915.  
  1916.  
  1917.  
  1918.  
  1919.  
  1920.  
  1921.     /**
  1922.     * Parses the responses like RFC822.SIZE and INTERNALDATE
  1923.     *
  1924.     * @param string the IMAP's server response
  1925.     *
  1926.     * @return string containing  the parsed response
  1927.     * @access private
  1928.     * @since  1.0
  1929.     */
  1930.  
  1931.     function _parseOneStringResponse(&$str$line,$file)
  1932.     {
  1933.         $this->_parseSpace($str $line $file );
  1934.         $size $this->_getNextToken($str,$uid);
  1935.         return $uid;
  1936.     }
  1937.  
  1938.  
  1939.     /**
  1940.     * Parses the FLAG response
  1941.     *
  1942.     * @param string the IMAP's server response
  1943.     *
  1944.     * @return Array containing  the parsed  response
  1945.     * @access private
  1946.     * @since  1.0
  1947.     */
  1948.     function _parseFLAGSresponse(&$str)
  1949.     {
  1950.         $this->_parseSpace($str __LINE__ __FILE__ );
  1951.         $params_arr[$this->_arrayfy_content($str);
  1952.         $flags_arr=array();
  1953.         for$i = 0 ; $i count($params_arr[0]$i++ ){
  1954.             $flags_arr[$params_arr[0][$i];
  1955.         }
  1956.         return $flags_arr;
  1957.     }
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.     /**
  1964.     * Parses the BODY response
  1965.     *
  1966.     * @param string the IMAP's server response
  1967.     *
  1968.     * @return Array containing  the parsed  response
  1969.     * @access private
  1970.     * @since  1.0
  1971.     */
  1972.  
  1973.     function _parseBodyResponse(&$str$command){
  1974.  
  1975.             $this->_parseSpace($str __LINE__ __FILE__ );
  1976.             while($str[0!= ')' && $str!=''){
  1977.                 $params_arr[$this->_arrayfy_content($str);
  1978.             }
  1979.  
  1980.             return $params_arr;
  1981.     }
  1982.  
  1983.  
  1984.  
  1985.  
  1986.  
  1987.  
  1988.     /**
  1989.     * Makes the content an Array
  1990.     *
  1991.     * @param string the IMAP's server response
  1992.     *
  1993.     * @return Array containing  the parsed  response
  1994.     * @access private
  1995.     * @since  1.0
  1996.     */
  1997.     function _arrayfy_content(&$str)
  1998.     {
  1999.         $params_arr=array();
  2000.         $this->_getNextToken($str,$params);
  2001.         if($params != '(' ){
  2002.             return $params;
  2003.         }
  2004.         $this->_getNextToken($str,$params,false,false);
  2005.         while $str != '' && $params != ')'){
  2006.                 if($params != '' ){
  2007.                     if($params[0== '(' ){
  2008.                         $params=$this->_arrayfy_content$params );
  2009.                     }
  2010.                     if($params != ' ' ){
  2011.                         //I don't remove the colons (") to handle the case of retriving " "
  2012.                         // If I remove the colons the parser will interpret this field as an imap separator (space)
  2013.                         // instead of a valid field so I remove the colons here
  2014.                         if($params=='""'){
  2015.                             $params='';
  2016.                         }else{
  2017.                             if($params[0]=='"'){
  2018.                                 $params=substr($params,1,$this->_getLineLength($params)-2);
  2019.                             }
  2020.                         }
  2021.                         $params_arr[]=$params;
  2022.                     }
  2023.                 }else{
  2024.                     //if params if empty (for example i'm parsing 2 quotes ("")
  2025.                     // I'll append an array entry to mantain compatibility
  2026.                     $params_arr[]=$params;
  2027.                 }
  2028.                 $this->_getNextToken($str,$params,false,false);
  2029.         }
  2030.         return $params_arr;
  2031.     }
  2032.  
  2033.  
  2034.  
  2035.  
  2036.     /**
  2037.     * Parses the BODY[],BODY[TEXT],.... responses
  2038.     *
  2039.     * @param string the IMAP's server response
  2040.     *
  2041.     * @return Array containing  the parsed  response
  2042.     * @access private
  2043.     * @since  1.0
  2044.     */
  2045.     function _parseContentresponse(&$str$command)
  2046.     {
  2047.         $content '';
  2048.         $this->_parseSpace($str __LINE__ __FILE__ );
  2049.         $size  =$this->_getNextToken($str,$content);
  2050.         return array"CONTENT"=> $content "CONTENT_SIZE" =>$size );
  2051.     }
  2052.  
  2053.  
  2054.  
  2055.  
  2056.  
  2057.  
  2058.  
  2059.  
  2060.     /**
  2061.     * Parses the ENVELOPE response
  2062.     *
  2063.     * @param string the IMAP's server response
  2064.     *
  2065.     * @return Array containing  the parsed  response
  2066.     * @access private
  2067.     * @since  1.0
  2068.     */
  2069.     function _parseENVELOPEresponse(&$str)
  2070.     {
  2071.         $content '';
  2072.         $this->_parseSpace($str __LINE__ __FILE__ );
  2073.  
  2074.         $this->_getNextToken($str,$parenthesis);
  2075.         if$parenthesis != '(' ){
  2076.                 $this->_prot_error("must be a '(' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2077.         }
  2078.         // Get the email's Date
  2079.         $this->_getNextToken($str,$date);
  2080.  
  2081.         $this->_parseSpace($str __LINE__ __FILE__ );
  2082.  
  2083.         // Get the email's Subject:
  2084.         $this->_getNextToken($str,$subject);
  2085.         //$subject=$this->decode($subject);
  2086.  
  2087.         $this->_parseSpace($str __LINE__ __FILE__ );
  2088.  
  2089.         //FROM LIST;
  2090.         $from_arr $this->_getAddressList($str);
  2091.  
  2092.         $this->_parseSpace($str __LINE__ __FILE__ );
  2093.  
  2094.         //"SENDER LIST\n";
  2095.         $sender_arr $this->_getAddressList($str);
  2096.  
  2097.         $this->_parseSpace($str __LINE__ __FILE__ );
  2098.  
  2099.         //"REPLY-TO LIST\n";
  2100.         $reply_to_arr=$this->_getAddressList($str);
  2101.  
  2102.         $this->_parseSpace($str __LINE__ __FILE__ );
  2103.  
  2104.         //"TO LIST\n";
  2105.         $to_arr $this->_getAddressList($str);
  2106.  
  2107.         $this->_parseSpace($str __LINE__ __FILE__ );
  2108.  
  2109.         //"CC LIST\n";
  2110.         $cc_arr $this->_getAddressList($str);
  2111.  
  2112.         $this->_parseSpace($str __LINE__ __FILE__ );
  2113.  
  2114.         //"BCC LIST|$str|\n";
  2115.         $bcc_arr $this->_getAddressList($str);
  2116.  
  2117.         $this->_parseSpace($str __LINE__ __FILE__ );
  2118.  
  2119.         $this->_getNextToken($str,$in_reply_to);
  2120.  
  2121.         $this->_parseSpace($str __LINE__ __FILE__ );
  2122.  
  2123.         $this->_getNextToken($str,$message_id);
  2124.  
  2125.         $this->_getNextToken($str,$parenthesis);
  2126.  
  2127.         if$parenthesis != ')' ){
  2128.             $this->_prot_error("must be a ')' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2129.         }
  2130.  
  2131.         return array"DATE"=> $date "SUBJECT" => $subject,"FROM" => $from_arr,
  2132.             "SENDER" => $sender_arr "REPLY_TO" => $reply_to_arr"TO" => $to_arr,
  2133.             "CC" =>$cc_arr"BCC"=> $bcc_arr"IN_REPLY_TO" =>$in_reply_to"MESSAGE_ID"=>$message_id  );
  2134.     }
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140.     /**
  2141.     * Parses the ARRDLIST as defined in RFC
  2142.     *
  2143.     * @param string the IMAP's server response
  2144.     *
  2145.     * @return Array containing  the parsed  response
  2146.     * @access private
  2147.     * @since  1.0
  2148.     */
  2149.     function _getAddressList(&$str)
  2150.     {
  2151.         $params_arr $this->_arrayfy_content($str);
  2152.         if!isset$params_arr ) ){
  2153.             return $params_arr;
  2154.         }
  2155.  
  2156.         ifis_array($params_arr) ){
  2157.             foreach ($params_arr as $index => $address_arr{
  2158.                 $personal_name  $address_arr[0];
  2159.                 $at_domain_list $address_arr[1];
  2160.                 $mailbox_name   $address_arr[2];
  2161.                 $host_name      $address_arr[3];
  2162.                 if$mailbox_name!='' && $host_name!='' ){
  2163.                         $email=$mailbox_name "@" $host_name;
  2164.                 }else{
  2165.                         $email=false;
  2166.                 }
  2167.                 if($email==false){
  2168.                         $rfc822_email=false;
  2169.                 }else{
  2170.                         if(!isset($personal_name)){
  2171.                         $rfc822_email"<"$email ">";
  2172.                         }else{
  2173.                         $rfc822_email"\""$personal_name ."\" <"$email ">";
  2174.                         }
  2175.                 }
  2176.                 $email_arr[= array "PERSONAL_NAME"=> $personal_name "AT_DOMAIN_LIST"=>$at_domain_list ,
  2177.                                         "MAILBOX_NAME"=> $this->utf_7_decode($mailbox_name)"HOST_NAME"=> $host_name,
  2178.                                         "EMAIL"=>$email "RFC822_EMAIL" => $rfc822_email );
  2179.             }
  2180.             return $email_arr;
  2181.         }
  2182.  
  2183.         return array();
  2184.     }
  2185.  
  2186.  
  2187.  
  2188.  
  2189.  
  2190.  
  2191.  
  2192.     /**
  2193.     * Utility funcion to find the closing parenthesis ")" Position it takes care of quoted ones
  2194.     *
  2195.     * @param string the IMAP's server response
  2196.     *
  2197.     * @return int containing  the pos of the closing parenthesis ")"
  2198.     * @access private
  2199.     * @since  1.0
  2200.     */
  2201.     function _getClosingBracesPos($str_line$startDelim ='('$stopDelim ')' )
  2202.     {
  2203.         $len $this->_getLineLength$str_line );
  2204.         $pos = 0;
  2205.         // ignore all extra characters
  2206.         // If inside of a string, skip string -- Boundary IDs and other
  2207.         // things can have ) in them.
  2208.         if $str_line[$pos!= $startDelim {
  2209.             $this->_prot_error("_getClosingParenthesisPos: must start with a '(' but is a '"$str_line[$pos."'!!!!\n" .
  2210.                 "STR_LINE:$str_line|size:$len|POS: $pos\n__LINE__ __FILE__ );
  2211.             return$len );
  2212.         }
  2213.         for$pos = 1 ; $pos $len $pos++ ){
  2214.             if ($str_line[$pos== $stopDelim {
  2215.                 break;
  2216.             }
  2217.             if ($str_line[$pos== '"'{
  2218.                 $pos++;
  2219.                 while $str_line[$pos!= '"' && $pos $len {
  2220.                     if ($str_line[$pos== "\\" && $str_line[$pos + 1 == '"' )
  2221.                         $pos++;
  2222.                     if ($str_line[$pos== "\\" && $str_line[$pos + 1 == "\\" )
  2223.                         $pos++;
  2224.                     $pos++;
  2225.                 }
  2226.             }
  2227.             if $str_line[$pos== $startDelim {
  2228.                 $str_line_aux substr$str_line $pos );
  2229.                 $pos_aux $this->_getClosingBracesPos$str_line_aux );
  2230.                 $pos+=$pos_aux;
  2231.             }
  2232.         }
  2233.         if$str_line[$pos!= $stopDelim ){
  2234.             $this->_prot_error("_getClosingBracesPos: must be a $stopDelim but is a '". $str_line[$pos."'|POS:$pos|STR_LINE:$str_line!!!!__LINE__ __FILE__ );
  2235.         }
  2236.  
  2237.         if$pos >= $len )
  2238.             return false;
  2239.         return $pos;
  2240.     }
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.     /**
  2248.     * Utility funcion to get from here to the end of the line
  2249.     *
  2250.     * @param string the IMAP's server response
  2251.     *
  2252.     * @return string containing  the string to the end of the line
  2253.     * @access private
  2254.     * @since  1.0
  2255.     */
  2256.  
  2257.     function _getToEOL(&$str $including = true)
  2258.     {
  2259.         $len $this->_getLineLength$str );
  2260.         if$including ){
  2261.             for($i=0;$i<$len;$i++){
  2262.                 if$str[$i=="\n" )
  2263.                     break;
  2264.             }
  2265.             $content=substr($str,0,$i + 1);
  2266.             $str=substr($str,$i + 1);
  2267.             return $content;
  2268.  
  2269.         }else{
  2270.             for$i = 0 ; $i $len $i++ ){
  2271.                 if$str[$i=="\n" || $str[$i== "\r")
  2272.                     break;
  2273.             }
  2274.             $content substr$str ,$i );
  2275.             $str substr$str $i );
  2276.             return $content;
  2277.         }
  2278.     }
  2279.  
  2280.  
  2281.  
  2282.  
  2283.     /**
  2284.     * Fetches the next IMAP token or parenthesis
  2285.     *
  2286.     * @param string the IMAP's server response
  2287.     * @param string the next token
  2288.     * @param boolean true: the parenthesis IS a token, false: I consider
  2289.     *         all the response in parenthesis as a token
  2290.     *
  2291.     * @return int containing  the content size
  2292.     * @access private
  2293.     * @since  1.0
  2294.     */
  2295.  
  2296.  
  2297.     function _getNextToken(&$str&$content$parenthesisIsToken=true,$colonIsToken=true){
  2298.         $len $this->_getLineLength($str);
  2299.         $pos = 0;
  2300.         $content_size = false;
  2301.         $content = false;
  2302.         if($str == '' || $len < 2 ){
  2303.             $content=$str;
  2304.             return $len;
  2305.         }
  2306.         switch$str[0){
  2307.         case '{':
  2308.             if( ($posClosingBraces $this->_getClosingBracesPos($str'{' '}' )) == false ){
  2309.                 $this->_prot_error("_getClosingBracesPos() error!!!" __LINE__ __FILE__ );
  2310.             }
  2311.             if(is_numeric( ( $strBytes substr$str $posClosingBraces - 1) ) ) ){
  2312.                 $this->_prot_error("must be a number but is a '" $strBytes ."'!!!!" __LINE__ __FILE__ );
  2313.             }
  2314.             if$str[$posClosingBraces!= '}' ){
  2315.                 $this->_prot_error("must be a '}'  but is a '" $str[$posClosingBraces."'!!!!" __LINE__ __FILE__ );
  2316.             }
  2317.             if$str[$posClosingBraces + 1!= "\r" ){
  2318.                 $this->_prot_error("must be a '\\r'  but is a '" $str[$posClosingBraces + 1."'!!!!" __LINE__ __FILE__ );
  2319.             }
  2320.             if$str[$posClosingBraces + 2!= "\n" ){
  2321.                 $this->_prot_error("must be a '\\n'  but is a '" $str[$posClosingBraces + 2."'!!!!" __LINE__ __FILE__ );
  2322.             }
  2323.             $content $this->_getSubstr$str $posClosingBraces + 3 $strBytes );
  2324.             if$this->_getLineLength$content != $strBytes ){
  2325.                 $this->_prot_error("content size is "$this->_getLineLength($content. " but the string reports a size of $strBytes!!!\n__LINE__ __FILE__ );
  2326.             }
  2327.             $content_size $strBytes;
  2328.             //Advance the string
  2329.             $str $this->_getSubstr$str $posClosingBraces $strBytes + 3 );
  2330.             break;
  2331.         case '"':
  2332.             if($colonIsToken){
  2333.                 for($pos=1;$pos<$len;$pos++){
  2334.                     if $str[$pos== "\"" {
  2335.                         break;
  2336.                     }
  2337.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\"" )
  2338.                         $pos++;
  2339.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\\" )
  2340.                         $pos++;
  2341.                 }
  2342.                 if($str[$pos!= '"' ){
  2343.                     $this->_prot_error("must be a '\"'  but is a '" $str[$pos."'!!!!" __LINE__ __FILE__ );
  2344.                 }
  2345.                 $content_size $pos;
  2346.                 $content substr$str $pos - 1 );
  2347.                 //Advance the string
  2348.                 $str substr$str $pos + 1 );
  2349.             }else{
  2350.                 for($pos=1;$pos<$len;$pos++){
  2351.                     if $str[$pos== "\"" {
  2352.                         break;
  2353.                     }
  2354.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\"" )
  2355.                         $pos++;
  2356.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\\" )
  2357.                         $pos++;
  2358.                 }
  2359.                 if($str[$pos!= '"' ){
  2360.                     $this->_prot_error("must be a '\"'  but is a '" $str[$pos."'!!!!" __LINE__ __FILE__ );
  2361.                 }
  2362.                 $content_size $pos;
  2363.                 $content substr$str $pos + 1 );
  2364.                 //Advance the string
  2365.                 $str substr$str $pos + 1 );
  2366.  
  2367.             }
  2368.             # we need to strip slashes for a quoted string
  2369.             $content stripslashes($content);
  2370.             break;
  2371.  
  2372.         case "\r":
  2373.             $pos = 1;
  2374.             if$str[1== "\n")
  2375.                 $pos++;
  2376.             $content_size $pos;
  2377.             $content substr$str $pos );
  2378.             $str substr$str $pos );
  2379.             break;
  2380.         case "\n":
  2381.             $pos = 1;
  2382.             $content_size $pos;
  2383.             $content substr$str $pos );
  2384.             $str substr$str $pos );
  2385.             break;
  2386.         case '(':
  2387.             if$parenthesisIsToken == false ){
  2388.                 $pos $this->_getClosingBracesPos$str );
  2389.                 $content_size $pos + 1;
  2390.                 $content substr$str $pos + 1 );
  2391.                 $str substr$str $pos + 1 );
  2392.             }else{
  2393.                 $pos = 1;
  2394.                 $content_size $pos;
  2395.                 $content substr$str $pos );
  2396.                 $str substr$str $pos );
  2397.             }
  2398.             break;
  2399.         case ')':
  2400.             $pos = 1;
  2401.             $content_size $pos;
  2402.             $content substr$str $pos );
  2403.             $str substr$str $pos );
  2404.             break;
  2405.         case ' ':
  2406.             $pos = 1;
  2407.             $content_size $pos;
  2408.             $content substr$str $pos );
  2409.             $str substr$str $pos );
  2410.             break;
  2411.         default:
  2412.             for$pos = 0 ; $pos $len $pos++ ){
  2413.                 if(substr$str == 'BODY[' || substr$str == 'BODY.'{
  2414.                     if($str[$pos== ']'{
  2415.                       $pos++;
  2416.                       break;
  2417.                     }
  2418.                 elseif $str[$pos== ' ' || $str[$pos== "\r" || $str[$pos== ')' || $str[$pos== '(' || $str[$pos== "\n" {
  2419.                     break;
  2420.                 }
  2421.                 if $str[$pos== "\\" && $str[$pos + 1 == ' '  )
  2422.                     $pos++;
  2423.                 if $str[$pos== "\\" && $str[$pos + 1 == "\\" )
  2424.                     $pos++;
  2425.             }
  2426.             //Advance the string
  2427.             if$pos == 0 ){
  2428.                 $content_size = 1;
  2429.                 $content substr$str );
  2430.                 $str substr$str );
  2431.             }else{
  2432.                 $content_size $pos;
  2433.                 $content substr$str $pos );
  2434.                 if($pos $len){
  2435.                     $str substr$str $pos  );
  2436.                 }else{
  2437.                 //if this is the end of the string... exit the switch
  2438.                     break;
  2439.                 }
  2440.  
  2441.  
  2442.             }
  2443.             break;
  2444.         }
  2445.         return $content_size;
  2446.     }
  2447.  
  2448.  
  2449.  
  2450.  
  2451.  
  2452.  
  2453.     /**
  2454.     * Utility funcion to display to console the protocol errors
  2455.     *
  2456.     * @param string the error
  2457.     * @param int the line producing the error
  2458.     * @param string file where the error was produced
  2459.     *
  2460.     * @return string containing  the error
  2461.     * @access private
  2462.     * @since  1.0
  2463.     */
  2464.     function _prot_error($str $line $file,$printError=true)
  2465.     {
  2466.         if($printError){
  2467.             echo "$line,$file,PROTOCOL ERROR!:$str\n";
  2468.         }
  2469.     }
  2470.  
  2471.  
  2472.  
  2473.  
  2474.  
  2475.  
  2476.  
  2477.     function _getEXTarray(&$str $startDelim '(' $stopDelim ')'){
  2478.         /* I let choose the $startDelim  and $stopDelim to allow parsing
  2479.            the OK response  so I also can parse a response like this
  2480.            * OK [UIDNEXT 150] Predicted next UID
  2481.         */
  2482.         $this->_getNextToken$str $parenthesis );
  2483.         if$parenthesis != $startDelim ){
  2484.             $this->_prot_error("must be a '$startDelim' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2485.         }
  2486.         $parenthesis '';
  2487.         $struct_arr = array();
  2488.         while$parenthesis != $stopDelim && $str != '' ){
  2489.             // The command
  2490.             $this->_getNextToken$str $token );
  2491.             $token strtoupper$token );
  2492.  
  2493.             if( ( $ret $this->_retrParsedResponse$str $token ) ) != false ){
  2494.                 //$struct_arr[$token] = $ret;
  2495.                 $struct_arr=array_merge($struct_arr$ret);
  2496.             }
  2497.  
  2498.             $parenthesis=$token;
  2499.  
  2500.         }//While
  2501.  
  2502.        if$parenthesis != $stopDelim  ){
  2503.             $this->_prot_error("1_must be a '$stopDelim' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2504.        }
  2505.         return $struct_arr;
  2506.     }
  2507.  
  2508.  
  2509.  
  2510.  
  2511.  
  2512.     function _retrParsedResponse&$str $token$previousToken = null)
  2513.     {
  2514.  
  2515.     //echo "\n\nTOKEN:$token\r\n";
  2516.         switch$token ){
  2517.         case "RFC822.SIZE" :
  2518.             return array($token=>$this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2519.             break;
  2520. //        case "RFC822.TEXT" :
  2521.  
  2522. //        case "RFC822.HEADER" :
  2523.  
  2524.  
  2525.         case "RFC822" :
  2526.             return array($token=>$this->_parseContentresponse$str $token ));
  2527.             break;
  2528.         case "FLAGS" :
  2529.  
  2530.         case "PERMANENTFLAGS" :
  2531.             return array($token=>$this->_parseFLAGSresponse$str ));
  2532.             break;
  2533.  
  2534.         case "ENVELOPE" :
  2535.             return array($token=>$this->_parseENVELOPEresponse$str ));
  2536.             break;
  2537.         case "EXPUNGE" :
  2538.             return false;
  2539.             break;
  2540.  
  2541.         case "UID" :
  2542.  
  2543.         case "UIDNEXT" :
  2544.  
  2545.         case "UIDVALIDITY" :
  2546.  
  2547.         case "UNSEEN" :
  2548.  
  2549.         case "MESSAGES" :
  2550.  
  2551.         case "UIDNEXT" :
  2552.  
  2553.         case "UIDVALIDITY" :
  2554.  
  2555.         case "UNSEEN" :
  2556.  
  2557.         case "INTERNALDATE" :
  2558.             return array($token=>$this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2559.             break;
  2560.         case "BODY" :
  2561.  
  2562.         case "BODYSTRUCTURE" :
  2563.             return array($token=>$this->_parseBodyResponse$str $token ));
  2564.             break;
  2565.         case "RECENT" :
  2566.             if$previousToken != null ){
  2567.                 $aux["RECENT"]=$previousToken;
  2568.                 return $aux;
  2569.             }else{
  2570.                 return array($token=>$this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2571.             }
  2572.             break;
  2573.  
  2574.         case "EXISTS" :
  2575.             return array($token=>$previousToken);
  2576.             break;
  2577.         case "READ-WRITE" :
  2578.  
  2579.         case "READ-ONLY" :
  2580.             return array($token=>$token);
  2581.             break;
  2582.         case "QUOTA" :
  2583.             /*
  2584.             A tipical GETQUOTA DIALOG IS AS FOLLOWS
  2585.  
  2586.                 C: A0004 GETQUOTA user.damian
  2587.                 S: * QUOTA user.damian (STORAGE 1781460 4000000)
  2588.                 S: A0004 OK Completed
  2589.  
  2590.             RFC 2087 section 5.1 says the list could be empty:
  2591.  
  2592.                 C: A0004 GETQUOTA user.damian
  2593.                 S: * QUOTA user.damian ()
  2594.                 S: A0004 OK Completed
  2595.             */
  2596.             $mailbox $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2597.             // courier fix
  2598.             if ($str[0].$str[1== "\r\n"{
  2599.                 $ret_aux = array("MAILBOX"=>$this->utf_7_decode($mailbox) );
  2600.                 return array($token => $ret_aux);
  2601.             }
  2602.             $this->_parseSpace$str __LINE__ __FILE__ );
  2603.             $this->_parseString$str '(' __LINE__ __FILE__ );
  2604.  
  2605.             $ret_aux = array("MAILBOX"=>$this->utf_7_decode($mailbox) );
  2606.             $this->_getNextToken$str $quota_resp );
  2607.             if ($quota_resp == ')' {
  2608.                 // empty list, apparently no STORAGE or MESSAGE quota set
  2609.                 return array($token => $ret_aux);
  2610.             }
  2611.             if( ( $ext $this->_retrParsedResponse$str $quota_resp )) == false){
  2612.                     $this->_prot_error("bogus response!!!!" __LINE__ __FILE__ );
  2613.             }
  2614.             $ret_aux=array_merge($ret_aux,$ext);
  2615.  
  2616.             $this->_getNextToken$str $separator );
  2617.             if$separator == ')' ){
  2618.                 return array($token=>$ret_aux);
  2619.             }
  2620.  
  2621.  
  2622.             $this->_parseSpace$str __LINE__ __FILE__ );
  2623.  
  2624.             $this->_getNextToken$str $quota_resp );
  2625.             if( ( $ext $this->_retrParsedResponse$str $quota_resp )) == false){
  2626.                     $this->_prot_error("bogus response!!!!" __LINE__ __FILE__ );
  2627.             }
  2628.             $ret_aux=array_merge($ret_aux,$ext);
  2629.  
  2630.             $this->_parseString$str ')' __LINE__ __FILE__ );
  2631.             return array($token=>$ret_aux);
  2632.             break;
  2633.  
  2634.         case "QUOTAROOT" :
  2635.             /*
  2636.             A tipical GETQUOTA DIALOG IS AS FOLLOWS
  2637.  
  2638.                 C: A0004 GETQUOTA user.damian
  2639.                 S: * QUOTA user.damian (STORAGE 1781460 4000000)
  2640.                 S: A0004 OK Completed
  2641.             */
  2642.             $mailbox $this->utf_7_decode($this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2643.  
  2644.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2645.             if(empty($str_line)) {
  2646.               $ret @array"MAILBOX"=>$this->utf_7_decode($mailbox));
  2647.             else {
  2648.               $quotaroot $this->_parseOneStringResponse$str_line,__LINE__ __FILE__ );
  2649.               $ret @array"MAILBOX"=>$this->utf_7_decode($mailbox$token=>$quotaroot );
  2650.             }
  2651.             return array($token=>$ret);
  2652.             break;
  2653.         case "STORAGE" :
  2654.                 $used $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2655.                 $qmax $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2656.                 return array($token=>array("USED"=> $used"QMAX" => $qmax));
  2657.         break;
  2658.         case "MESSAGE" :
  2659.                 $mused $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2660.                 $mmax $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2661.                 return array($token=>array("MUSED"=> $mused"MMAX" => $mmax));
  2662.         break;
  2663.         case "FETCH" :
  2664.                 $this->_parseSpace$str  ,__LINE__  ,__FILE__ );
  2665.                 // Get the parsed pathenthesis
  2666.                 $struct_arr $this->_getEXTarray$str );
  2667.                 return $struct_arr;
  2668.             break;
  2669.         case "NAMESPACE" :
  2670.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2671.                 $this->_getNextToken($str $personalfalse);
  2672.                 $struct_arr['NAMESPACES']['personal'$this->_arrayfy_content($personal);
  2673.  
  2674.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2675.                 $this->_getNextToken($str $othersfalse);
  2676.                 $struct_arr['NAMESPACES']['others'$this->_arrayfy_content($others);
  2677.  
  2678.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2679.                 $this->_getNextToken($str $sharedfalse);
  2680.                 $struct_arr['NAMESPACES']['shared'$this->_arrayfy_content($shared);
  2681.                 
  2682.                 return array($token=>$struct_arr);
  2683.             break;
  2684.         case "CAPABILITY" :
  2685.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2686.                 $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2687.                 $struct_arr["CAPABILITIES"explode' ' $str_line );
  2688.                 return array($token=>$struct_arr);
  2689.             break;
  2690.         case "STATUS" :
  2691.                 $mailbox $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2692.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2693.                 $ext $this->_getEXTarray$str );
  2694.                 $struct_arr["MAILBOX"$this->utf_7_decode($mailbox);
  2695.                 $struct_arr["ATTRIBUTES"$ext;
  2696.                 return array($token=>$struct_arr);
  2697.             break;
  2698.         case "LIST" :
  2699.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2700.                 $params_arr $this->_arrayfy_content$str );
  2701.  
  2702.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2703.                 $this->_getNextToken$str $hierarchydelim );
  2704.  
  2705.                 $this->_parseSpace$str,__LINE__ __FILE__);
  2706.                 $this->_getNextToken$str $mailbox_name );
  2707.  
  2708.                 $result_array = array"NAME_ATTRIBUTES"=>$params_arr "HIERACHY_DELIMITER"=>$hierarchydelim "MAILBOX_NAME"=>  $this->utf_7_decode($mailbox_name) );
  2709.                 return array($token=>$result_array);
  2710.             break;
  2711.         case "LSUB" :
  2712.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2713.                 $params_arr $this->_arrayfy_content$str );
  2714.  
  2715.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2716.                 $this->_getNextToken$str $hierarchydelim );
  2717.  
  2718.                 $this->_parseSpace$str,__LINE__ __FILE__);
  2719.                 $this->_getNextToken$str $mailbox_name );
  2720.  
  2721.                 $result_array = array"NAME_ATTRIBUTES"=>$params_arr "HIERACHY_DELIMITER"=>$hierarchydelim "MAILBOX_NAME"=> $this->utf_7_decode($mailbox_name) );
  2722.                 return array($token=>$result_array);
  2723.             break;
  2724.  
  2725.             case "SEARCH" :
  2726.                 $str_line rtrimsubstr$this->_getToEOL$str false 1) );
  2727.                 $struct_arr["SEARCH_LIST"explode' ' $str_line );
  2728.                 if(count($struct_arr["SEARCH_LIST"]== 1 && $struct_arr["SEARCH_LIST"][0]==''){
  2729.                     $struct_arr["SEARCH_LIST"]=null;
  2730.                 }
  2731.                 return array($token=>$struct_arr);
  2732.             break;
  2733.             case "OK" :
  2734.                 /* TODO:
  2735.                     parse the [ .... ] part of the response, use the method
  2736.                     _getEXTarray(&$str,'[',$stopDelim=']')
  2737.  
  2738.                 */
  2739.                 $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2740.                 if($str_line[0== '[' ){
  2741.                     $braceLen=$this->_getClosingBracesPos($str_line'['']' );
  2742.                     $str_aux='('substr($str_line,1,$braceLen -1)')';
  2743.                     $ext_arr=$this->_getEXTarray($str_aux);
  2744.                     //$ext_arr=array($token=>$this->_getEXTarray($str_aux));
  2745.                 }else{
  2746.                     $ext_arr=$str_line;
  2747.                     //$ext_arr=array($token=>$str_line);
  2748.                 }
  2749.                 $result_array =  $ext_arr;
  2750.                 return $result_array;
  2751.                 break;
  2752.         case "NO" :
  2753.         /* TODO:
  2754.             parse the [ .... ] part of the response, use the method
  2755.             _getEXTarray(&$str,'[',$stopDelim=']')
  2756.  
  2757.         */
  2758.  
  2759.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2760.             $result_array[@array"COMMAND"=>$token "EXT"=>$str_line );
  2761.             return $result_array;
  2762.             break;
  2763.         case "BAD" :
  2764.         /* TODO:
  2765.             parse the [ .... ] part of the response, use the method
  2766.             _getEXTarray(&$str,'[',$stopDelim=']')
  2767.  
  2768.         */
  2769.  
  2770.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2771.             $result_array[= array"COMMAND"=>$token "EXT"=>$str_line );
  2772.             return $result_array;
  2773.             break;
  2774.         case "BYE" :
  2775.         /* TODO:
  2776.             parse the [ .... ] part of the response, use the method
  2777.             _getEXTarray(&$str,'[',$stopDelim=']')
  2778.  
  2779.         */
  2780.  
  2781.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2782.             $result_array[= array"COMMAND"=>$token "EXT"=> $str_line );
  2783.             return $result_array;
  2784.             break;
  2785.  
  2786.         case "LISTRIGHTS" :
  2787.                 $this->_parseSpace$str ,__LINE__ __FILE__ );
  2788.                 $this->_getNextToken$str $mailbox );
  2789.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2790.                 $this->_getNextToken$str $user );
  2791.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2792.                 $this->_getNextToken$str $granted );
  2793.  
  2794.                 $ungranted explode' ' rtrimsubstr$this->_getToEOL$str false ) ) );
  2795.  
  2796.                 $result_array @array"MAILBOX"=>$this->utf_7_decode($mailbox"USER"=>$user "GRANTED"=>$granted "UNGRANTED"=>$ungranted );
  2797.                 return $result_array;
  2798.             break;
  2799.  
  2800.         case "MYRIGHTS" :
  2801.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2802.                 $this->_getNextToken$str ,$mailbox );
  2803.                 // Patch to handle the alternate MYRIGHTS response from Courier-IMAP
  2804.                 if ($str==')'){
  2805.                     $granted $mailbox;
  2806.                     $mailbox $this->currentMailbox;
  2807.                 }else{
  2808.                     $this->_parseSpace$str __LINE__ __FILE__ );
  2809.                     $this->_getNextToken$str $granted );
  2810.                 }
  2811.                 // End Patch
  2812.  
  2813.                 $result_array = array"MAILBOX"=>$this->utf_7_decode($mailbox"GRANTED"=>$granted );
  2814.                 return $result_array;
  2815.             break;
  2816.  
  2817.         case "ACL" :
  2818.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2819.                 $this->_getNextToken$str $mailbox );
  2820.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2821.                 $acl_arr explode' ' rtrimsubstr$this->_getToEOL$str false ) ) );
  2822.  
  2823.                 for$i = 0 ; $i count$acl_arr $i += 2 ){
  2824.                     $arr[= array"USER"=>$acl_arr[$i"RIGHTS"=>$acl_arr$i + 1 );
  2825.                 }
  2826.  
  2827.                 $result_array = array"MAILBOX"=>$this->utf_7_decode($mailbox"USERS"=>$arr );
  2828.                 return $result_array;
  2829.             break;
  2830.  
  2831.         case "ANNOTATION" :
  2832.                 $this->_parseSpace($str__LINE____FILE__);
  2833.                 $this->_getNextToken($str$mailbox);
  2834.  
  2835.                 $this->_parseSpace($str__LINE____FILE__);
  2836.                 $this->_getNextToken($str$entry);
  2837.  
  2838.                 $this->_parseSpace($str__LINE____FILE__);
  2839.                 $attrs $this->_arrayfy_content($str);
  2840.  
  2841.                 $result_array = array('MAILBOX' => $mailbox'ENTRY' => $entry 'ATTRIBUTES' => $attrs);
  2842.                 return $result_array;
  2843.             break;
  2844.  
  2845.         case "":
  2846.             $this->_prot_error"PROTOCOL ERROR!:str empty!!" __LINE__ __FILE__ );
  2847.             break;
  2848.         case "(":
  2849.             $this->_prot_error("OPENING PARENTHESIS ERROR!!!!!!!!!!!!!!!!!" __LINE__ __FILE__ );
  2850.             break;
  2851.         case ")":
  2852.             //"CLOSING PARENTHESIS BREAK!!!!!!!"
  2853.             break;
  2854.         case "\r\n":
  2855.             $this->_prot_error("BREAK!!!!!!!!!!!!!!!!!" __LINE__ __FILE__ );
  2856.             break;
  2857.         case ' ':
  2858.             // this can happen and we just ignore it
  2859.             // This happens when - for example - fetch returns more than 1 parammeter
  2860.             // for example you ask to get RFC822.SIZE and UID
  2861.             //$this->_prot_error("SPACE BREAK!!!!!!!!!!!!!!!!!" , __LINE__ , __FILE__ );
  2862.             break;
  2863.         default:
  2864.             $body_token=strtoupper(substr($token,0,5));
  2865.             $rfc822_token=strtoupper(substr($token,0,7));
  2866.  
  2867.             if$body_token == 'BODY[' || $body_token == 'BODY.' || $rfc822_token == 'RFC822.' {
  2868.                 //echo "TOKEN:$token\n";
  2869.                 //$this->_getNextToken( $str , $mailbox );
  2870.                 return array($token=>$this->_parseContentresponse$str $token ));
  2871.             }else{
  2872.                 $this->_prot_error"UNIMPLEMMENTED! I don't know the parameter '$token' !!!__LINE__ __FILE__ );
  2873.             }
  2874.             break;
  2875.         }
  2876.         return false;
  2877. }
  2878.  
  2879.  
  2880.  
  2881.  
  2882.  
  2883.  
  2884.     /*
  2885.     * Verifies that the next character IS a space
  2886.     */
  2887.     function _parseSpace(&$str,$line,$file$printError = true)
  2888.     {
  2889.     /*
  2890.         This code repeats a lot in this class
  2891.         so i make it a function to make all the code shorter
  2892.     */
  2893.         $this->_getNextToken$str $space );
  2894.         if$space != ' ' ){
  2895.             $this->_prot_error("must be a ' ' but is a '$space' !!!!$line $file,$printError );
  2896.         }
  2897.         return $space;
  2898.     }
  2899.  
  2900.  
  2901.  
  2902.  
  2903.  
  2904.  
  2905.     function _parseString&$str $char $line $file )
  2906.     {
  2907.     /*
  2908.         This code repeats a lot in this class
  2909.         so i make it a function to make all the code shorter
  2910.     */
  2911.         $this->_getNextToken$str $char_aux );
  2912.         ifstrtoupper($char_aux!= strtoupper$char ) ){
  2913.             $this->_prot_error("must be a $char but is a '$char_aux' !!!!"$line $file );
  2914.         }
  2915.         return $char_aux;
  2916.     }
  2917.  
  2918.  
  2919.  
  2920.  
  2921.  
  2922.     function _genericImapResponseParser&$str $cmdid = null )
  2923.     {
  2924.  
  2925.         $result_array=array();
  2926.         if$this->_unParsedReturn ){
  2927.             $unparsed_str $str;
  2928.         }
  2929.  
  2930.         $this->_getNextToken$str $token );
  2931.  
  2932.         while$token != $cmdid && $str != '' ){
  2933.         if($token == "+" ){
  2934.         //if the token  is + ignore the line
  2935.         // TODO: verify that this is correct!!!
  2936.             $this->_getToEOL$str );
  2937.             $this->_getNextToken$str $token );
  2938.         }
  2939.  
  2940.             $this->_parseString$str ' ' __LINE__ __FILE__ );
  2941.  
  2942.             $this->_getNextToken$str $token );
  2943.         if$token == '+' ){
  2944.             $this->_getToEOL$str );
  2945.             $this->_getNextToken$str $token );
  2946.         }else
  2947.             ifis_numeric$token ) ){
  2948.                 // The token is a NUMBER so I store it
  2949.                 $msg_nro $token;
  2950.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2951.  
  2952.                 // I get the command
  2953.                 $this->_getNextToken$str $command );
  2954.  
  2955.                 if( ( $ext_arr $this->_retrParsedResponse$str $command$msg_nro ) ) == false ){
  2956.                 //  if this bogus response cis a FLAGS () or EXPUNGE response
  2957.                 // the ignore it
  2958.                     if$command != 'FLAGS' && $command != 'EXPUNGE' ){
  2959.                         $this->_prot_error("bogus response!!!!" __LINE__ __FILE__false);
  2960.                     }
  2961.                 }
  2962.                 $result_array[= array"COMMAND"=>$command "NRO"=>$msg_nro "EXT"=>$ext_arr );
  2963.             }else{
  2964.                 // OK the token is not a NUMBER so it MUST be a COMMAND
  2965.                 $command $token;
  2966.  
  2967.                 /* Call the parser return the array
  2968.                     take care of bogus responses!
  2969.                 */
  2970.  
  2971.                 if( ( $ext_arr $this->_retrParsedResponse$str $command ) ) == false ){
  2972.                     $this->_prot_error"bogus response!!!! (COMMAND:$command)__LINE__ __FILE__ );
  2973.                 }
  2974.                 $result_array[= array"COMMAND"=>$command "EXT"=>$ext_arr );
  2975.  
  2976.  
  2977.             }
  2978.  
  2979.  
  2980.             $this->_getNextToken$str $token );
  2981.  
  2982.             $token strtoupper$token );
  2983.             if$token != "\r\n" && $token != '' ){
  2984.                 $this->_prot_error("PARSE ERROR!!! must be a '\\r\\n' here  but is a '$token'!!!! (getting the next line)|STR:|$str|__LINE__ __FILE__ );
  2985.             }
  2986.             $this->_getNextToken$str $token );
  2987.  
  2988.             if($token == "+" ){
  2989.                 //if the token  is + ignore the line
  2990.                 // TODO: verify that this is correct!!!
  2991.                 $this->_getToEOL$str );
  2992.                 $this->_getNextToken$str $token );
  2993.             }
  2994.         }//While
  2995.         // OK we finish the UNTAGGED Response now we must parse the FINAL TAGGED RESPONSE
  2996.         //TODO: make this a litle more elegant!
  2997.  
  2998.         $this->_parseSpace$str __LINE__ __FILE__false );
  2999.  
  3000.         $this->_getNextToken$str $cmd_status );
  3001.  
  3002.         $str_line rtrim (substr$this->_getToEOL$str ) );
  3003.  
  3004.  
  3005.         $response["RESPONSE"]=array"CODE"=>$cmd_status "STR_CODE"=>$str_line "CMDID"=>$cmdid );
  3006.  
  3007.         $ret=$response;
  3008.         if!empty($result_array)){
  3009.             $ret=array_merge($ret,array("PARSED"=>$result_array) );
  3010.         }
  3011.  
  3012.         if$this->_unParsedReturn ){
  3013.             $unparsed["UNPARSED"]=$unparsed_str;
  3014.             $ret=array_merge($ret,$unparsed);
  3015.         }
  3016.  
  3017.  
  3018.         ifisset($status_arr) ){
  3019.             $status["STATUS"]=$status_arr;
  3020.             $ret=array_merge($ret,$status);
  3021.         }
  3022.         return $ret;
  3023.  
  3024. }
  3025.  
  3026.  
  3027.  
  3028.  
  3029.     function _genericCommand($command$params '')
  3030.     {
  3031.         if!$this->_connected ){
  3032.             return new PEAR_Error"not connected! (CMD:$command));
  3033.         }
  3034.         $cmdid $this->_getCmdId();
  3035.         $this->_putCMD$cmdid $command $params );
  3036.         $args=$this->_getRawResponse$cmdid );
  3037.         return $this->_genericImapResponseParser$args $cmdid );
  3038.     }
  3039.  
  3040.  
  3041.  
  3042.      function utf_7_encode($str)
  3043.     {
  3044.         if($this->_useUTF_7 == false ){
  3045.             return $str;
  3046.         }
  3047.  
  3048.         if(function_exists('mb_convert_encoding')) {
  3049.           return mb_convert_encoding($str"UTF7-IMAP""ISO-8859-1");
  3050.         }
  3051.         
  3052.         $encoded_utf7 '';
  3053.         $base64_part  '';
  3054.         if(is_array($str)){
  3055.           return new PEAR_Error('error');
  3056.         }
  3057.  
  3058.         for ($i = 0; $i $this->_getLineLength($str)$i++{
  3059.             //those chars should be base64 encoded
  3060.             if ( ((ord($str[$i]>= 39 and (ord($str[$i]<= 126 )) or ((ord($str[$i]>= 32 and (ord($str[$i]<= 37 )) ) {
  3061.                 if ($base64_part{
  3062.                     $encoded_utf7 sprintf("%s&%s-"$encoded_utf7str_replace('=''',base64_encode($base64_part))  );
  3063.                     $base64_part '';
  3064.                 }
  3065.                 $encoded_utf7 sprintf("%s%s",$encoded_utf7 $str[$i]);
  3066.             else {
  3067.                 //handle &
  3068.                 if (ord($str[$i]== 38 {
  3069.                     if ($base64_part{
  3070.                         $encoded_utf7 sprintf("%s&%s-"$encoded_utf7str_replace('=''',base64_encode($base64_part))  );
  3071.                         $base64_part '';
  3072.                     }
  3073.                     $encoded_utf7 sprintf("%s&-"$encoded_utf7 );
  3074.                 else {
  3075.                     $base64_part sprintf("%s%s",$base64_part  $str[$i]);
  3076.                     //$base64_part = sprintf("%s%s%s",$base64_part , chr(0) , $str[$i]);
  3077.                 }
  3078.             }
  3079.         }
  3080.         if ($base64_part{
  3081.             $encoded_utf7 sprintf("%s&%s-"$encoded_utf7str_replace('=''',base64_encode($base64_part))   );
  3082.             $base64_part '';
  3083.         }
  3084.  
  3085.         return $encoded_utf7;
  3086.     }
  3087.  
  3088.  
  3089.     function utf_7_decode($str)
  3090.     {
  3091.  
  3092.         if($this->_useUTF_7 == false ){
  3093.             return $str;
  3094.         }
  3095.  
  3096.         //return imap_utf7_decode($str);
  3097.  
  3098.         if(function_exists('mb_convert_encoding')) {
  3099.           return mb_convert_encoding($str"ISO-8859-1""UTF7-IMAP");
  3100.         }
  3101.  
  3102.         $base64_part '';
  3103.         $decoded_utf7 '';
  3104.  
  3105.         for ($i = 0; $i $this->_getLineLength($str)$i++{
  3106.             if $this->_getLineLength($base64_part> 0 {
  3107.                 if ($str[$i== '-'{
  3108.                     if ($base64_part == '&'{
  3109.                         $decoded_utf7 sprintf("%s&" $decoded_utf7 );
  3110.                     else {
  3111.                         $next_part_decodedbase64_decodesubstr$base64_part) ) ;
  3112.                         $decoded_utf7 sprintf("%s%s"$decoded_utf7 $next_part_decoded );
  3113.                     }
  3114.                     $base64_part '';
  3115.  
  3116.                 else {
  3117.                     $base64_part sprintf("%s%s"$base64_part $str[$i);
  3118.                 }
  3119.             else {
  3120.                 if ($str[$i== '&'{
  3121.                     $base64_part '&';
  3122.                 else {
  3123.                     $decoded_utf7 sprintf("%s%s"$decoded_utf7 $str[$i);
  3124.                 }
  3125.             }
  3126.         }
  3127.         return $decoded_utf7;
  3128.     }
  3129.  
  3130.     /**
  3131.      * Make  CREATE/RENAME compatible option params
  3132.      *
  3133.      * @param array  $options options to format
  3134.      * @return string Returns a string for formatted parameters
  3135.      *
  3136.      * @access private
  3137.      * @since  1.1
  3138.      */
  3139.     function _getCreateParams($options)
  3140.     {
  3141.         $args "";
  3142.         if(is_null($options=== false && is_array($options=== true{
  3143.             foreach($options as $opt => $data{
  3144.                 switch(strtoupper($opt)) {
  3145.                     case "PARTITION":
  3146.                         $args .= sprintf(" %s",$this->utf_7_encode($data));
  3147.                         break;
  3148.                     default:
  3149.                         // ignore any unknown options
  3150.                         break;
  3151.                 }
  3152.             }
  3153.         }
  3154.         return $args;
  3155.     }
  3156.  
  3157.     /**
  3158.     * Return true if the TLS negotiation was successful
  3159.     *
  3160.     * @access public
  3161.     * @return mixed              true on success, PEAR_Error on failure
  3162.     */
  3163.     function cmdStartTLS()
  3164.     {
  3165.         if (PEAR::isError($res $this->_genericCommand("STARTTLS"))) {
  3166.             return $res;
  3167.         }
  3168.  
  3169.         if(stream_socket_enable_crypto($this->_socket->fptrueSTREAM_CRYPTO_METHOD_TLS_CLIENT== false{
  3170.             $msg 'Failed to establish TLS connection';
  3171.             return new PEAR_Error($msg);
  3172.         }
  3173.  
  3174.         if($this->_debug === true{
  3175.             echo "STARTTLS Negotiation Successful\n";
  3176.         }
  3177.  
  3178.         // RFC says we need to query the server capabilities again
  3179.         if(PEAR::isError($res $this->cmdCapability() )) {
  3180.             $msg 'Failed to connect, server said: ' $res->getMessage();
  3181.             return new PEAR_Error($msg);
  3182.         }
  3183.         return true;
  3184.     }
  3185.     
  3186.     function _getLineLength($string
  3187.     {
  3188.         if (extension_loaded('mbstring')) {
  3189.             return mb_strlen($string,'latin1');
  3190.         else {
  3191.             return strlen($string);
  3192.         }
  3193.     }
  3194.  
  3195.     function _getSubstr($string$start$length = false
  3196.     {
  3197.         if (extension_loaded('mbstring')) {
  3198.             if($length !== false{
  3199.               return mb_substr($string$start$length'latin1');
  3200.             else {
  3201.               $strlen mb_strlen($string,'latin1');
  3202.               return mb_substr($string$start$strlen'latin1');
  3203.             }
  3204.         else {
  3205.           if($length !== false{
  3206.             return substr($string$start$length);
  3207.           else {
  3208.             return substr($string$start);
  3209.           }
  3210.         }
  3211.     }
  3212.  
  3213. }//Class
  3214. ?>

Documentation generated on Mon, 11 Mar 2019 14:54:15 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.