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.         $cmdid $this->_getCmdId();
  691.         if PEAR::isError$error $this->_putCMD$cmdid 'LOGOUT' ) ) ) {
  692.             return $error;
  693.         }
  694.         if PEAR::isError($args $this->_getRawResponse() ) ) {
  695.             return $args;
  696.         }
  697.         if (PEAR::isError$this->_socket->disconnect() ) ) {
  698.             return new PEAR_Error('socket disconnect failed');
  699.         }
  700.  
  701.         return $args;
  702.         // not for now
  703.         //return $this->_genericImapResponseParser($args,$cmdid);
  704.  
  705.     }
  706.  
  707.  
  708.  
  709.  
  710.  
  711.     /**
  712.      * Send the NOOP command.
  713.      *
  714.      * @return array Returns an array containing the response
  715.      *
  716.      * @access public
  717.      * @since  1.0
  718.      */
  719.     function cmdNoop()
  720.     {
  721.         return $this->_genericCommand('NOOP');
  722.     }
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.     /**
  733.      * Send the CHECK command.
  734.      *
  735.      * @return array Returns an array containing the response
  736.      *
  737.      * @access public
  738.      * @since  1.0
  739.      */
  740.     function cmdCheck()
  741.     {
  742.         return $this->_genericCommand('CHECK');
  743.     }
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754.     /**
  755.      * Send the  Select Mailbox Command
  756.      *
  757.      * @param string The mailbox to select.
  758.      *
  759.      * @return array Returns an array containing the response
  760.      *
  761.      * @access public
  762.      * @since  1.0
  763.      */
  764.     function cmdSelect($mailbox)
  765.     {
  766.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  767.         if!PEAR::isError$ret$this->_genericCommand('SELECT'$mailbox_name) ) ){
  768.             $this->currentMailbox  = $mailbox;
  769.         }
  770.         return $ret;
  771.     }
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.     /**
  783.      * Send the  EXAMINE  Mailbox Command
  784.      *
  785.      * @param string The mailbox to examine.
  786.      * @return array Returns an array containing the response
  787.      *
  788.      * @access public
  789.      * @since  1.0
  790.      */
  791.     function cmdExamine($mailbox)
  792.     {
  793.  
  794.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  795.         $ret=$this->_genericCommand('EXAMINE'$mailbox_name);
  796.         $parsed='';
  797.         if(isset$ret["PARSED") ){
  798.             for($i=0;$i<count($ret["PARSED"])$i++)$command=$ret["PARSED"][$i]["EXT"];
  799.                     $parsed[key($command)]=$command[key($command)];
  800.             }
  801.         }
  802.         return array("PARSED"=>$parsed,"RESPONSE"=>$ret["RESPONSE"]);
  803.     }
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.     /**
  812.      * Send the  CREATE Mailbox Command
  813.      *
  814.      * @param string The mailbox to create.
  815.      * @return array Returns an array containing the response
  816.      *
  817.      * @access public
  818.      * @since  1.0
  819.      */
  820.     function cmdCreate($mailbox)
  821.     {
  822.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  823.         return $this->_genericCommand('CREATE'$mailbox_name);
  824.     }
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.     /**
  833.      * Send the  RENAME Mailbox Command
  834.      *
  835.      * @param string The old mailbox name.
  836.      * @param string The new (renamed) mailbox name.
  837.      *
  838.      * @return array Returns an array containing the response
  839.      *
  840.      * @access public
  841.      * @since  1.0
  842.      */
  843.     function cmdRename($mailbox$new_mailbox)
  844.     {
  845.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  846.         $new_mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($new_mailbox) );
  847.         return $this->_genericCommand('RENAME'"$mailbox_name $new_mailbox_name);
  848.     }
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.     /**
  858.      * Send the  DELETE Mailbox Command
  859.      *
  860.      * @param string The mailbox name to delete.
  861.      *
  862.      * @return array Returns an array containing the response
  863.      *
  864.      * @access public
  865.      * @since  1.0
  866.      */
  867.     function cmdDelete($mailbox)
  868.     {
  869.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  870.         return $this->_genericCommand('DELETE'$mailbox_name);
  871.     }
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.     /**
  880.      * Send the  SUSCRIBE  Mailbox Command
  881.      *
  882.      * @param string The mailbox name to suscribe.
  883.      *
  884.      * @return array Returns an array containing the response
  885.      *
  886.      * @access public
  887.      * @since  1.0
  888.      */
  889.     function cmdSubscribe($mailbox)
  890.     {
  891.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  892.         return $this->_genericCommand('SUBSCRIBE'$mailbox_name );
  893.     }
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.     /**
  903.      * Send the  UNSUSCRIBE  Mailbox Command
  904.      *
  905.      * @return mixed Returns a PEAR_Error with an error message on any
  906.      *                kind of failure, or true on success.
  907.      * @access public
  908.      * @since  1.0
  909.      */
  910.     function cmdUnsubscribe($mailbox)
  911.     {
  912.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  913.         return $this->_genericCommand('UNSUBSCRIBE'$mailbox_name );
  914.     }
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.     /**
  924.      * Send the  FETCH Command
  925.      *
  926.      * @return mixed Returns a PEAR_Error with an error message on any
  927.      *                kind of failure, or true on success.
  928.      * @access public
  929.      * @since  1.0
  930.      */
  931.     function cmdFetch($msgset$fetchparam)
  932.     {
  933.         return $this->_genericCommand('FETCH' "$msgset $fetchparam);
  934.     }
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.     /**
  943.      * Send the  CAPABILITY Command
  944.      *
  945.      * @return mixed Returns a PEAR_Error with an error message on any
  946.      *                kind of failure, or true on success.
  947.      * @access public
  948.      * @since  1.0
  949.      */
  950.     function cmdCapability()
  951.     {
  952.         $ret $this->_genericCommand'CAPABILITY' );
  953.  
  954.         if(isset$ret["PARSED") ){
  955.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"]["CAPABILITY"];
  956.             //fill the $this->_serverAuthMethods and $this->_serverSupportedCapabilities arrays
  957.             foreach$ret["PARSED"]["CAPABILITIES"as $auth_method ){
  958.                 ifstrtouppersubstr$auth_method ,) ) == "AUTH=" )
  959.                     $this->_serverAuthMethods[substr$auth_method );
  960.             }
  961.             // Keep the capabilities response to use ir later
  962.             $this->_serverSupportedCapabilities $ret["PARSED"]["CAPABILITIES"];
  963.         }
  964.  
  965.         return $ret;
  966.     }
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.     /**
  978.      * Send the  STATUS Mailbox Command
  979.      *
  980.      * @param string $mailbox the mailbox name
  981.      * @param string $request the request status it could be:
  982.      *               MESSAGES | RECENT | UIDNEXT
  983.      *               UIDVALIDITY | UNSEEN
  984.      * @return array Returns a Parsed Response
  985.      *
  986.      * @access public
  987.      * @since  1.0
  988.      */
  989.     function cmdStatus($mailbox$request)
  990.     {
  991.  
  992.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  993.  
  994.         if$request!="MESSAGES" && $request!="RECENT" && $request!="UIDNEXT" &&
  995.             $request!="UIDVALIDITY" && $request!="UNSEEN" ){
  996.             // TODO:  fix this error!
  997.             $this->_prot_error("request '$request' is invalid! see RFC2060!!!!__LINE__ __FILE__false );
  998.         }
  999.         $ret $this->_genericCommand('STATUS'"$mailbox_name ($request));
  1000.         if(isset$ret["PARSED") ){
  1001.             $ret['PARSED']=$ret["PARSED"][count($ret['PARSED'])-1]["EXT"];
  1002.         }
  1003.         return $ret;
  1004.     }
  1005.  
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011.     /**
  1012.      * Send the  LIST  Command
  1013.      *
  1014.      * @return mixed Returns a PEAR_Error with an error message on any
  1015.      *                kind of failure, or true on success.
  1016.      * @access public
  1017.      * @since  1.0
  1018.      */
  1019.     function cmdList($mailbox_base$mailbox)
  1020.     {
  1021.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  1022.         $mailbox_base=sprintf("\"%s\"",$this->utf_7_encode($mailbox_base) );
  1023.         return $this->_genericCommand('LIST'"$mailbox_base $mailbox_name);
  1024.     }
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.     /**
  1032.      * Send the  LSUB  Command
  1033.      *
  1034.      * @return mixed Returns a PEAR_Error with an error message on any
  1035.      *                kind of failure, or true on success.
  1036.      * @access public
  1037.      * @since  1.0
  1038.      */
  1039.     function cmdLsub($mailbox_base$mailbox)
  1040.     {
  1041.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  1042.         $mailbox_base=sprintf("\"%s\"",$this->utf_7_encode($mailbox_base) );
  1043.         return $this->_genericCommand('LSUB'"$mailbox_base $mailbox_name);
  1044.     }
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.     /**
  1052.      * Send the  APPEND  Command
  1053.      *
  1054.      * @return mixed Returns a PEAR_Error with an error message on any
  1055.      *                kind of failure, or true on success.
  1056.      * @access public
  1057.      * @since  1.0
  1058.      */
  1059.     function cmdAppend($mailbox$msg $flags_list '' ,$time '')
  1060.     {
  1061.         if(!$this->_connected){
  1062.             return new PEAR_Error('not connected!');
  1063.         }
  1064.  
  1065.  
  1066.         $cmdid=$this->_getCmdId();
  1067.         $msg_size=strlen($msg);
  1068.  
  1069.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  1070.         // TODO:
  1071.         // Falta el codigo para que flags list y time hagan algo!!
  1072.         if$this->hasCapability"LITERAL+" == true ){
  1073.             $param=sprintf("%s %s%s{%s+}\r\n%s",$mailbox_name,$flags_list,$time,$msg_size,$msg);
  1074.             if (PEAR::isError($error $this->_putCMD($cmdid 'APPEND' $param ) ) ) {
  1075.                 return $error;
  1076.             }
  1077.         }else{
  1078.             $param=sprintf("%s %s%s{%s}\r\n",$mailbox_name,$flags_list,$time,$msg_size);
  1079.             if (PEAR::isError($error $this->_putCMD($cmdid 'APPEND' $param ) ) ) {
  1080.             return $error;
  1081.             }
  1082.             if (PEAR::isError($error $this->_recvLn() ) ) {
  1083.             return $error;
  1084.             }
  1085.  
  1086.             if (PEAR::isError($error $this->_send$msg ) ) ) {
  1087.             return $error;
  1088.             }
  1089.         }
  1090.  
  1091.  
  1092.         $args=$this->_getRawResponse($cmdid);
  1093.         $ret $this->_genericImapResponseParser($args,$cmdid);
  1094.         return $ret;
  1095.     }
  1096.  
  1097.  
  1098.  
  1099.     /**
  1100.      * Send the CLOSE command.
  1101.      *
  1102.      * @return mixed Returns a PEAR_Error with an error message on any
  1103.      *                kind of failure, or true on success.
  1104.      * @access public
  1105.      * @since  1.0
  1106.      */
  1107.     function cmdClose()
  1108.     {
  1109.         return $this->_genericCommand('CLOSE');
  1110.     }
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.     /**
  1118.      * Send the EXPUNGE command.
  1119.      *
  1120.      * @return mixed Returns a PEAR_Error with an error message on any
  1121.      *                kind of failure, or true on success.
  1122.      * @access public
  1123.      * @since  1.0
  1124.      */
  1125.     function cmdExpunge()
  1126.     {
  1127.         $ret=$this->_genericCommand('EXPUNGE');
  1128.  
  1129.         if(isset$ret["PARSED") ){
  1130.            $parsed=$ret["PARSED"];
  1131.             unset($ret["PARSED"]);
  1132.             foreach($parsed as $command){
  1133.                 ifstrtoupper($command["COMMAND"]== 'EXPUNGE' ){
  1134.                         $ret["PARSED"][$command["COMMAND"]][]=$command["NRO"];
  1135.                 }else{
  1136.                         $ret["PARSED"][$command["COMMAND"]]=$command["NRO"];
  1137.                 }
  1138.             }
  1139.         }
  1140.         return $ret;
  1141.     }
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.     /**
  1150.      * Send the SEARCH command.
  1151.      *
  1152.      * @return mixed Returns a PEAR_Error with an error message on any
  1153.      *                kind of failure, or true on success.
  1154.      * @access public
  1155.      * @since  1.0
  1156.      */
  1157.  
  1158.     function cmdSearch($search_cmd)
  1159.     {
  1160.         /*        if($_charset != '' )
  1161.                     $_charset = "[$_charset] ";
  1162.                 $param=sprintf("%s%s",$charset,$search_cmd);
  1163.         */
  1164.         $ret $this->_genericCommand('SEARCH'$search_cmd );
  1165.         if(isset$ret["PARSED") ){
  1166.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1167.         }
  1168.         return $ret;
  1169.     }
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.     /**
  1177.      * Send the STORE command.
  1178.      *
  1179.      * @param string $message_set  the sessage_set
  1180.      * @param string $dataitem: the way we store the flags
  1181.      *           FLAGS: replace the flags whith $value
  1182.      *           FLAGS.SILENT: replace the flags whith $value but don't return untagged responses
  1183.      *
  1184.      *           +FLAGS: Add the flags whith $value
  1185.      *           +FLAGS.SILENT: Add the flags whith $value but don't return untagged responses
  1186.      *
  1187.      *           -FLAGS: Remove the flags whith $value
  1188.      *           -FLAGS.SILENT: Remove the flags whith $value but don't return untagged responses
  1189.      *
  1190.      * @param string $value 
  1191.      * @return mixed Returns a PEAR_Error with an error message on any
  1192.      *                kind of failure, or true on success.
  1193.      * @access public
  1194.      * @since  1.0
  1195.      */
  1196.  
  1197.     function cmdStore($message_set$dataitem$value)
  1198.     {
  1199.         /* As said in RFC2060...
  1200.         C: A003 STORE 2:4 +FLAGS (\Deleted)
  1201.         S: * 2 FETCH FLAGS (\Deleted \Seen)
  1202.         S: * 3 FETCH FLAGS (\Deleted)
  1203.         S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen)
  1204.         S: A003 OK STORE completed
  1205.         */
  1206.         if$dataitem!="FLAGS" && $dataitem!="FLAGS.SILENT" && $dataitem!="+FLAGS" &&
  1207.             $dataitem!="+FLAGS.SILENT" && $dataitem!="-FLAGS" && $dataitem!="-FLAGS.SILENT" ){
  1208.             $this->_prot_error("dataitem '$dataitem' is invalid! see RFC2060!!!!__LINE__ __FILE__ );
  1209.         }
  1210.         $param=sprintf("%s %s (%s)",$message_set,$dataitem,$value);
  1211.         return $this->_genericCommand('STORE'$param );
  1212.     }
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.     /**
  1221.      * Send the COPY command.
  1222.      *
  1223.      * @return mixed Returns a PEAR_Error with an error message on any
  1224.      *                kind of failure, or true on success.
  1225.      * @access public
  1226.      * @since  1.0
  1227.      */
  1228.  
  1229.     function cmdCopy($message_set$mailbox)
  1230.     {
  1231.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  1232.         return $this->_genericCommand('COPY'sprintf("%s %s",$message_set,$mailbox_name) );
  1233.     }
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.     function cmdUidFetch($msgset$fetchparam)
  1248.     {
  1249.         return $this->_genericCommand('UID FETCH'sprintf("%s %s",$msgset,$fetchparam) );
  1250.     }
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.     function cmdUidCopy($message_set$mailbox)
  1260.     {
  1261.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox) );
  1262.         return $this->_genericCommand('UID COPY'sprintf("%s %s",$message_set,$mailbox_name) );
  1263.     }
  1264.  
  1265.  
  1266.  
  1267.  
  1268.  
  1269.  
  1270.  
  1271.  
  1272.      /**
  1273.      * Send the UID STORE command.
  1274.      *
  1275.      * @param string $message_set  the sessage_set
  1276.      * @param string $dataitem: the way we store the flags
  1277.      *           FLAGS: replace the flags whith $value
  1278.      *           FLAGS.SILENT: replace the flags whith $value but don't return untagged responses
  1279.      *
  1280.      *           +FLAGS: Add the flags whith $value
  1281.      *           +FLAGS.SILENT: Add the flags whith $value but don't return untagged responses
  1282.      *
  1283.      *           -FLAGS: Remove the flags whith $value
  1284.      *           -FLAGS.SILENT: Remove the flags whith $value but don't return untagged responses
  1285.      *
  1286.      * @param string $value 
  1287.      * @return mixed Returns a PEAR_Error with an error message on any
  1288.      *                kind of failure, or true on success.
  1289.      * @access public
  1290.      * @since  1.0
  1291.      */
  1292.  
  1293.     function cmdUidStore($message_set$dataitem$value)
  1294.     {
  1295.         /* As said in RFC2060...
  1296.         C: A003 STORE 2:4 +FLAGS (\Deleted)
  1297.         S: * 2 FETCH FLAGS (\Deleted \Seen)
  1298.         S: * 3 FETCH FLAGS (\Deleted)
  1299.         S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen)
  1300.         S: A003 OK STORE completed
  1301.         */
  1302.         if$dataitem!="FLAGS" && $dataitem!="FLAGS.SILENT" && $dataitem!="+FLAGS" &&
  1303.             $dataitem!="+FLAGS.SILENT" && $dataitem!="-FLAGS" && $dataitem!="-FLAGS.SILENT" ){
  1304.             $this->_prot_error("dataitem '$dataitem' is invalid! see RFC2060!!!!__LINE__ __FILE__ );
  1305.         }
  1306.         return $this->_genericCommand('UID STORE'sprintf("%s %s (%s)",$message_set,$dataitem,$value) );
  1307.     }
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.     /**
  1319.      * Send the SEARCH command.
  1320.      *
  1321.      * @return mixed Returns a PEAR_Error with an error message on any
  1322.      *                kind of failure, or true on success.
  1323.      * @access public
  1324.      * @since  1.0
  1325.      */
  1326.  
  1327.     function cmdUidSearch($search_cmd)
  1328.     {
  1329.         $ret=$this->_genericCommand('UID SEARCH'sprintf("%s",$search_cmd) );
  1330.         if(isset$ret["PARSED") ){
  1331.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1332.         }
  1333.         return $ret;
  1334.     }
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.     /**
  1347.      * Send the X command.
  1348.      *
  1349.      * @return mixed Returns a PEAR_Error with an error message on any
  1350.      *                kind of failure, or true on success.
  1351.      * @access public
  1352.      * @since  1.0
  1353.      */
  1354.  
  1355.     function cmdX($atom$parameters)
  1356.     {
  1357.         return $this->_genericCommand("X$atom"$parameters );
  1358.     }
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367. /********************************************************************
  1368. ***
  1369. ***             HERE ENDS the RFC2060 IMAPS FUNCTIONS
  1370. ***             AND BEGIN THE EXTENSIONS FUNCTIONS
  1371. ***
  1372. ********************************************************************/
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380. /********************************************************************
  1381. ***             RFC2087 IMAP4 QUOTA extension BEGINS HERE
  1382. ********************************************************************/
  1383.  
  1384.  
  1385.     /**
  1386.      * Send the GETQUOTA command.
  1387.      *
  1388.      * @param string $mailbox_name the mailbox name to query for quota data
  1389.      * @return mixed Returns a PEAR_Error with an error message on any
  1390.      *                kind of failure, or quota data on success
  1391.      * @access public
  1392.      * @since  1.0
  1393.      */
  1394.  
  1395.     function cmdGetQuota($mailbox_name)
  1396.     {
  1397.  
  1398.  
  1399.         //Check if the IMAP server has QUOTA support
  1400.         if$this->hasQuotaSupport() ){
  1401.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1402.         }
  1403.         $mailbox_name=sprintf("%s",$this->utf_7_encode($mailbox_name) );
  1404.         $ret $this->_genericCommand('GETQUOTA'$mailbox_name );
  1405.         if(isset$ret["PARSED") ){
  1406.         // remove the array index because the quota response returns only 1 line of output
  1407.             $ret['PARSED']=$ret["PARSED"][0];
  1408.         }
  1409.         return $ret;
  1410.     }
  1411.  
  1412.  
  1413.     /**
  1414.      * Send the GETQUOTAROOT command.
  1415.      *
  1416.      * @param string $mailbox_name the mailbox name to query for quota data
  1417.      * @return mixed Returns a PEAR_Error with an error message on any
  1418.      *                kind of failure, or quota data on success
  1419.      * @access public
  1420.      * @since  1.0
  1421.      */
  1422.  
  1423.     function cmdGetQuotaRoot($mailbox_name)
  1424.     {
  1425.         //Check if the IMAP server has QUOTA support
  1426.         if$this->hasQuotaSupport() ){
  1427.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1428.         }
  1429.         $mailbox_name=sprintf("%s",$this->utf_7_encode($mailbox_name) );
  1430.         $ret $this->_genericCommand('GETQUOTAROOT'$mailbox_name );
  1431.  
  1432.         if(isset$ret["PARSED") ){
  1433.         // remove the array index because the quota response returns only 1 line of output
  1434.             $ret['PARSED']=$ret["PARSED"][0];
  1435.         }
  1436.         return $ret;
  1437.     }
  1438.  
  1439.  
  1440.  
  1441.  
  1442.     /**
  1443.      * Send the SETQUOTA command.
  1444.      *
  1445.      * @param string $mailbox_name the mailbox name to query for quota data
  1446.      * @param string $storageQuota sets the max number of bytes this mailbox can handle
  1447.      * @param string $messagesQuota sets the max number of messages this mailbox can handle
  1448.      * @return mixed Returns a PEAR_Error with an error message on any
  1449.      *                kind of failure, or quota data on success
  1450.      * @access public
  1451.      * @since  1.0
  1452.      */
  1453. // TODO:  implement the quota by number of emails!!
  1454.     function cmdSetQuota($mailbox_name$storageQuota = null ,$messagesQuota = null )
  1455.     {
  1456.         //Check if the IMAP server has QUOTA support
  1457.         if$this->hasQuotaSupport() ){
  1458.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1459.         }
  1460.  
  1461.         if( ($messagesQuota == null&& $storageQuota == null) ){
  1462.             return new PEAR_Error('$storageQuota and $messagesQuota parameters can\'t be both null if you want to use quota');
  1463.         }
  1464.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1465.         //Make the command request
  1466.         $param=sprintf("%s (",$mailbox_name);
  1467.         if($storageQuota != null ){
  1468.             $param=sprintf("%sSTORAGE %s",$param,$storageQuota);
  1469.             if$messagesQuota != null ){
  1470.                 //if we have both types of quota on the same call we must append an space between
  1471.                 // those parameters
  1472.                 $param=sprintf("%s ",$param);
  1473.             }
  1474.         }
  1475.         if($messagesQuota != null ){
  1476.             $param=sprintf("%sMESSAGES %s",$param,$messagesQuota);
  1477.  
  1478.         }
  1479.         $param=sprintf("%s)",$param);
  1480.  
  1481.         return $this->_genericCommand('SETQUOTA'$param );
  1482.     }
  1483.  
  1484.  
  1485.  
  1486.     /**
  1487.      * Send the SETQUOTAROOT command.
  1488.      *
  1489.      * @param string $mailbox_name the mailbox name to query for quota data
  1490.      * @param string $storageQuota sets the max number of bytes this mailbox can handle
  1491.      * @param string $messagesQuota sets the max number of messages this mailbox can handle
  1492.      * @return mixed Returns a PEAR_Error with an error message on any
  1493.      *                kind of failure, or quota data on success
  1494.      * @access public
  1495.      * @since  1.0
  1496.      */
  1497.     function cmdSetQuotaRoot($mailbox_name$storageQuota = null ,$messagesQuota = null)
  1498.     {
  1499.         //Check if the IMAP server has QUOTA support
  1500.         if$this->hasQuotaSupport() ){
  1501.             return new PEAR_Error("This IMAP server does not support QUOTA's! ");
  1502.         }
  1503.  
  1504.         if( ($messagesQuota == null&& $storageQuota == null) ){
  1505.             return new PEAR_Error('$storageQuota and $messagesQuota parameters can\'t be both null if you want to use quota');
  1506.         }
  1507.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1508.         //Make the command request
  1509.         $param=sprintf("%s (",$mailbox_name);
  1510.         if($storageQuota != null ){
  1511.             $param=sprintf("%sSTORAGE %s",$param,$storageQuota);
  1512.             if$messagesQuota != null ){
  1513.                 //if we have both types of quota on the same call we must append an space between
  1514.                 // those parameters
  1515.                 $param=sprintf("%s ",$param);
  1516.             }
  1517.         }
  1518.         if($messagesQuota != null ){
  1519.             $param=sprintf("%sMESSAGES %s",$param,$messagesQuota);
  1520.  
  1521.         }
  1522.         $param=sprintf("%s)",$param);
  1523.  
  1524.         return $this->_genericCommand('SETQUOTAROOT'$param );
  1525.     }
  1526.  
  1527.  
  1528.  
  1529. /********************************************************************
  1530. ***             RFC2087 IMAP4 QUOTA extension ENDS HERE
  1531. ********************************************************************/
  1532.  
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  
  1538. /********************************************************************
  1539. ***             RFC2086 IMAP4 ACL extension BEGINS HERE
  1540. ********************************************************************/
  1541.  
  1542.  
  1543.  
  1544.  
  1545.     function cmdSetACL($mailbox_name$user$acl)
  1546.     {
  1547.  
  1548.         //Check if the IMAP server has ACL support
  1549.         if$this->hasAclSupport() ){
  1550.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1551.         }
  1552.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1553.         $user_name=sprintf("\"%s\"",$this->utf_7_encode($user) );
  1554.         if(is_array($acl)){
  1555.             $acl=implode('',$acl);
  1556.         }
  1557.         return $this->_genericCommand('SETACL'sprintf("%s %s \"%s\"",$mailbox_name,$user_name,$acl) );
  1558.     }
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.     function cmdDeleteACL($mailbox_name$user)
  1566.     {
  1567.         //Check if the IMAP server has ACL support
  1568.         if$this->hasAclSupport() ){
  1569.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1570.         }
  1571.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1572.         
  1573.         return $this->_genericCommand('DELETEACL'sprintf("%s \"%s\"",$mailbox_name,$user) );
  1574.     }
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583.  
  1584.     function cmdGetACL($mailbox_name)
  1585.     {
  1586.         //Check if the IMAP server has ACL support
  1587.         if$this->hasAclSupport() ){
  1588.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1589.         }
  1590.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1591.         $ret $this->_genericCommand('GETACL'sprintf("%s",$mailbox_name) );
  1592.         if(isset$ret["PARSED") ){
  1593.             $ret['PARSED']=$ret["PARSED"][0]["EXT"];
  1594.  
  1595.         }
  1596.         return $ret;
  1597.    }
  1598.  
  1599.  
  1600.  
  1601.  
  1602.  
  1603.  
  1604.  
  1605.     function cmdListRights($mailbox_name$user)
  1606.     {
  1607.         //Check if the IMAP server has ACL support
  1608.         if$this->hasAclSupport() ){
  1609.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1610.         }
  1611.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1612.         $ret $this->_genericCommand('LISTRIGHTS'sprintf("%s \"%s\"",$mailbox_name,$user) );
  1613.         if(isset$ret["PARSED") ){
  1614.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1615.         }
  1616.         return $ret;
  1617.     }
  1618.  
  1619.  
  1620.  
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.     function cmdMyRights($mailbox_name)
  1628.     {
  1629.         //Check if the IMAP server has ACL support
  1630.         if$this->hasAclSupport() ){
  1631.             return new PEAR_Error("This IMAP server does not support ACL's! ");
  1632.         }
  1633.         $mailbox_name=sprintf("\"%s\"",$this->utf_7_encode($mailbox_name) );
  1634.         $ret $this->_genericCommand('MYRIGHTS'sprintf("%s",$mailbox_name) );
  1635.         if(isset$ret["PARSED") ){
  1636.             $ret["PARSED"]=$ret["PARSED"][0]["EXT"];
  1637.         }
  1638.         return $ret;
  1639.     }
  1640.  
  1641.  
  1642. /********************************************************************
  1643. ***             RFC2086 IMAP4 ACL extension ENDs HERE
  1644. ********************************************************************/
  1645.  
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.  
  1653.  
  1654.  
  1655.  
  1656.  
  1657. /*******************************************************************************
  1658. ***  draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension BEGINS HERE
  1659. ********************************************************************************/
  1660.  
  1661.  
  1662.  
  1663.     function cmdSetAnnotation($mailbox_name$entry$values)
  1664.     {
  1665.         // Check if the IMAP server has ANNOTATEMORE support
  1666.         if(!$this->hasAnnotateMoreSupport()) {
  1667.             return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!');
  1668.         }
  1669.         if (!is_array($values)) {
  1670.             return new PEAR_Error('Invalid $values argument passed to cmdSetAnnotation');
  1671.         }
  1672.  
  1673.         $vallist '';
  1674.         foreach ($values as $name => $value{
  1675.             $vallist .= "\"$name\" \"$value\" ";
  1676.         }
  1677.         $vallist rtrim($vallist);
  1678.  
  1679.         return $this->_genericCommand('SETANNOTATION'sprintf('"%s" "%s" (%s)'$mailbox_name$entry$vallist));
  1680.     }
  1681.  
  1682.  
  1683.  
  1684.  
  1685.  
  1686.  
  1687.  
  1688.  
  1689.  
  1690.  
  1691.  
  1692.  
  1693.  
  1694.     function cmdDeleteAnnotation($mailbox_name$entry$values)
  1695.     {
  1696.         // Check if the IMAP server has ANNOTATEMORE support
  1697.         if(!$this->hasAnnotateMoreSupport()) {
  1698.             return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!');
  1699.         }
  1700.         if (!is_array($values)) {
  1701.             return new PEAR_Error('Invalid $values argument passed to cmdDeleteAnnotation');
  1702.         }
  1703.  
  1704.         $vallist '';
  1705.         foreach ($values as $name{
  1706.             $vallist .= "\"$name\" NIL ";
  1707.         }
  1708.         $vallist rtrim($vallist);
  1709.  
  1710.         return $this->_genericCommand('SETANNOTATION'sprintf('"%s" "%s" (%s)'$mailbox_name$entry$vallist));
  1711.     }
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.  
  1724.     function cmdGetAnnotation($mailbox_name$entries$values)
  1725.     {
  1726.         // Check if the IMAP server has ANNOTATEMORE support
  1727.         if(!$this->hasAnnotateMoreSupport()) {
  1728.             return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!');
  1729.         }
  1730.  
  1731.         $entlist '';
  1732.  
  1733.        if (!is_array($entries)) {
  1734.             $entries = array($entries);
  1735.        }
  1736.  
  1737.         foreach ($entries as $name{
  1738.             $entlist .= "\"$name\" ";
  1739.         }
  1740.         $entlist rtrim($entlist);
  1741.         if (count($entries> 1{
  1742.             $entlist = "($entlist)";
  1743.         }
  1744.  
  1745.  
  1746.  
  1747.         $vallist '';
  1748.         if (!is_array($values)) {
  1749.             $values = array($values);
  1750.         }
  1751.  
  1752.         foreach ($values as $name{
  1753.             $vallist .= "\"$name\" ";
  1754.         }
  1755.         $vallist rtrim($vallist);
  1756.         if (count($values> 1{
  1757.             $vallist = "($vallist)";
  1758.         }
  1759.  
  1760.         return $this->_genericCommand('GETANNOTATION'sprintf('"%s" %s %s'$mailbox_name$entlist$vallist));
  1761.    }
  1762.  
  1763.  
  1764. /*****************************************************************************
  1765. ***  draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension ENDs HERE
  1766. ******************************************************************************/
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774. /********************************************************************
  1775. ***
  1776. ***             HERE ENDS THE EXTENSIONS FUNCTIONS
  1777. ***             AND BEGIN THE AUXILIARY FUNCTIONS
  1778. ***
  1779. ********************************************************************/
  1780.  
  1781.  
  1782.  
  1783.  
  1784.  
  1785.     /**
  1786.     * tell if the server has capability $capability
  1787.     *
  1788.     * @return true or false
  1789.     *
  1790.     * @access public
  1791.     * @since  1.0
  1792.     */
  1793.     function getServerAuthMethods()
  1794.     {
  1795.         if$this->_serverAuthMethods == null ){
  1796.             $this->cmdCapability();
  1797.             return $this->_serverAuthMethods;
  1798.         }
  1799.         return false;
  1800.     }
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.     /**
  1809.     * tell if the server has capability $capability
  1810.     *
  1811.     * @return true or false
  1812.     *
  1813.     * @access public
  1814.     * @since  1.0
  1815.     */
  1816.     function hasCapability($capability)
  1817.     {
  1818.         if$this->_serverSupportedCapabilities == null ){
  1819.             $this->cmdCapability();
  1820.         }
  1821.         if($this->_serverSupportedCapabilities != null ){
  1822.             ifin_array$capability $this->_serverSupportedCapabilities ) ){
  1823.                 return true;
  1824.             }
  1825.         }
  1826.         return false;
  1827.     }
  1828.  
  1829.  
  1830.  
  1831.     /**
  1832.     * tell if the server has Quota support
  1833.     *
  1834.     * @return true or false
  1835.     *
  1836.     * @access public
  1837.     * @since  1.0
  1838.     */
  1839.     function hasQuotaSupport()
  1840.     {
  1841.         return $this->hasCapability('QUOTA');
  1842.     }
  1843.  
  1844.  
  1845.  
  1846.  
  1847.  
  1848.     /**
  1849.     * tell if the server has Quota support
  1850.     *
  1851.     * @return true or false
  1852.     *
  1853.     * @access public
  1854.     * @since  1.0
  1855.     */
  1856.     function hasAclSupport()
  1857.     {
  1858.         return $this->hasCapability('ACL');
  1859.     }
  1860.  
  1861.  
  1862.  
  1863.  
  1864.  
  1865.     /**
  1866.     * tell if the server has support for the ANNOTATEMORE extension
  1867.     *
  1868.     * @return true or false
  1869.     *
  1870.     * @access public
  1871.     * @since  1.0
  1872.     */
  1873.     function hasAnnotateMoreSupport()
  1874.     {
  1875.         return $this->hasCapability('ANNOTATEMORE');
  1876.     }
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886.  
  1887.     /**
  1888.     * Parses the responses like RFC822.SIZE and INTERNALDATE
  1889.     *
  1890.     * @param string the IMAP's server response
  1891.     *
  1892.     * @return string containing  the parsed response
  1893.     * @access private
  1894.     * @since  1.0
  1895.     */
  1896.  
  1897.     function _parseOneStringResponse(&$str$line,$file)
  1898.     {
  1899.         $this->_parseSpace($str $line $file );
  1900.         $size $this->_getNextToken($str,$uid);
  1901.         return $uid;
  1902.     }
  1903.  
  1904.  
  1905.     /**
  1906.     * Parses the FLAG response
  1907.     *
  1908.     * @param string the IMAP's server response
  1909.     *
  1910.     * @return Array containing  the parsed  response
  1911.     * @access private
  1912.     * @since  1.0
  1913.     */
  1914.     function _parseFLAGSresponse(&$str)
  1915.     {
  1916.         $this->_parseSpace($str __LINE__ __FILE__ );
  1917.         $params_arr[$this->_arrayfy_content($str);
  1918.         $flags_arr=array();
  1919.         for$i = 0 ; $i count($params_arr[0]$i++ ){
  1920.             $flags_arr[$params_arr[0][$i];
  1921.         }
  1922.         return $flags_arr;
  1923.     }
  1924.  
  1925.  
  1926.  
  1927.  
  1928.  
  1929.     /**
  1930.     * Parses the BODY response
  1931.     *
  1932.     * @param string the IMAP's server response
  1933.     *
  1934.     * @return Array containing  the parsed  response
  1935.     * @access private
  1936.     * @since  1.0
  1937.     */
  1938.  
  1939.     function _parseBodyResponse(&$str$command){
  1940.  
  1941.             $this->_parseSpace($str __LINE__ __FILE__ );
  1942.             while($str[0!= ')' && $str!=''){
  1943.                 $params_arr[$this->_arrayfy_content($str);
  1944.             }
  1945.  
  1946.             return $params_arr;
  1947.     }
  1948.  
  1949.  
  1950.  
  1951.  
  1952.  
  1953.  
  1954.     /**
  1955.     * Makes the content an Array
  1956.     *
  1957.     * @param string the IMAP's server response
  1958.     *
  1959.     * @return Array containing  the parsed  response
  1960.     * @access private
  1961.     * @since  1.0
  1962.     */
  1963.     function _arrayfy_content(&$str)
  1964.     {
  1965.         $params_arr=array();
  1966.         $this->_getNextToken($str,$params);
  1967.         if($params != '(' ){
  1968.             return $params;
  1969.         }
  1970.         $this->_getNextToken($str,$params,false,false);
  1971.         while $str != '' && $params != ')'){
  1972.                 if($params != '' ){
  1973.                     if($params[0== '(' ){
  1974.                         $params=$this->_arrayfy_content$params );
  1975.                     }
  1976.                     if($params != ' ' ){
  1977.                         //I don't remove the colons (") to handle the case of retriving " "
  1978.                         // If I remove the colons the parser will interpret this field as an imap separator (space)
  1979.                         // instead of a valid field so I remove the colons here
  1980.                         if($params=='""'){
  1981.                             $params='';
  1982.                         }else{
  1983.                             if($params[0]=='"'){
  1984.                                 $params=substr($params,1,strlen($params)-2);
  1985.                             }
  1986.                         }
  1987.                         $params_arr[]=$params;
  1988.                     }
  1989.                 }else{
  1990.                     //if params if empty (for example i'm parsing 2 quotes ("")
  1991.                     // I'll append an array entry to mantain compatibility
  1992.                     $params_arr[]=$params;
  1993.                 }
  1994.                 $this->_getNextToken($str,$params,false,false);
  1995.         }
  1996.         return $params_arr;
  1997.     }
  1998.  
  1999.  
  2000.  
  2001.  
  2002.     /**
  2003.     * Parses the BODY[],BODY[TEXT],.... responses
  2004.     *
  2005.     * @param string the IMAP's server response
  2006.     *
  2007.     * @return Array containing  the parsed  response
  2008.     * @access private
  2009.     * @since  1.0
  2010.     */
  2011.     function _parseContentresponse(&$str$command)
  2012.     {
  2013.         $content '';
  2014.         $this->_parseSpace($str __LINE__ __FILE__ );
  2015.         $size  =$this->_getNextToken($str,$content);
  2016.         return array"CONTENT"=> $content "CONTENT_SIZE" =>$size );
  2017.     }
  2018.  
  2019.  
  2020.  
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026.     /**
  2027.     * Parses the ENVELOPE response
  2028.     *
  2029.     * @param string the IMAP's server response
  2030.     *
  2031.     * @return Array containing  the parsed  response
  2032.     * @access private
  2033.     * @since  1.0
  2034.     */
  2035.     function _parseENVELOPEresponse(&$str)
  2036.     {
  2037.         $content '';
  2038.         $this->_parseSpace($str __LINE__ __FILE__ );
  2039.  
  2040.         $this->_getNextToken($str,$parenthesis);
  2041.         if$parenthesis != '(' ){
  2042.                 $this->_prot_error("must be a '(' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2043.         }
  2044.         // Get the email's Date
  2045.         $this->_getNextToken($str,$date);
  2046.  
  2047.         $this->_parseSpace($str __LINE__ __FILE__ );
  2048.  
  2049.         // Get the email's Subject:
  2050.         $this->_getNextToken($str,$subject);
  2051.         //$subject=$this->decode($subject);
  2052.  
  2053.         $this->_parseSpace($str __LINE__ __FILE__ );
  2054.  
  2055.         //FROM LIST;
  2056.         $from_arr $this->_getAddressList($str);
  2057.  
  2058.         $this->_parseSpace($str __LINE__ __FILE__ );
  2059.  
  2060.         //"SENDER LIST\n";
  2061.         $sender_arr $this->_getAddressList($str);
  2062.  
  2063.         $this->_parseSpace($str __LINE__ __FILE__ );
  2064.  
  2065.         //"REPLY-TO LIST\n";
  2066.         $reply_to_arr=$this->_getAddressList($str);
  2067.  
  2068.         $this->_parseSpace($str __LINE__ __FILE__ );
  2069.  
  2070.         //"TO LIST\n";
  2071.         $to_arr $this->_getAddressList($str);
  2072.  
  2073.         $this->_parseSpace($str __LINE__ __FILE__ );
  2074.  
  2075.         //"CC LIST\n";
  2076.         $cc_arr $this->_getAddressList($str);
  2077.  
  2078.         $this->_parseSpace($str __LINE__ __FILE__ );
  2079.  
  2080.         //"BCC LIST|$str|\n";
  2081.         $bcc_arr $this->_getAddressList($str);
  2082.  
  2083.         $this->_parseSpace($str __LINE__ __FILE__ );
  2084.  
  2085.         $this->_getNextToken($str,$in_reply_to);
  2086.  
  2087.         $this->_parseSpace($str __LINE__ __FILE__ );
  2088.  
  2089.         $this->_getNextToken($str,$message_id);
  2090.  
  2091.         $this->_getNextToken($str,$parenthesis);
  2092.  
  2093.         if$parenthesis != ')' ){
  2094.             $this->_prot_error("must be a ')' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2095.         }
  2096.  
  2097.         return array"DATE"=> $date "SUBJECT" => $subject,"FROM" => $from_arr,
  2098.             "SENDER" => $sender_arr "REPLY_TO" => $reply_to_arr"TO" => $to_arr,
  2099.             "CC" =>$cc_arr"BCC"=> $bcc_arr"IN_REPLY_TO" =>$in_reply_to"MESSAGE_ID"=>$message_id  );
  2100.     }
  2101.  
  2102.  
  2103.  
  2104.  
  2105.  
  2106.     /**
  2107.     * Parses the ARRDLIST as defined in RFC
  2108.     *
  2109.     * @param string the IMAP's server response
  2110.     *
  2111.     * @return Array containing  the parsed  response
  2112.     * @access private
  2113.     * @since  1.0
  2114.     */
  2115.     function _getAddressList(&$str)
  2116.     {
  2117.         $params_arr $this->_arrayfy_content($str);
  2118.         if!isset$params_arr ) ){
  2119.             return $params_arr;
  2120.         }
  2121.  
  2122.  
  2123.         ifis_array($params_arr) ){
  2124.             $personal_name  $params_arr[0][0];
  2125.             $at_domain_list $params_arr[0][1];
  2126.             $mailbox_name   $params_arr[0][2];
  2127.             $host_name      $params_arr[0][3];
  2128.             if$mailbox_name!='' && $host_name!='' ){
  2129.                 $email=$mailbox_name "@" $host_name;
  2130.             }else{
  2131.                 $email=false;
  2132.             }
  2133.             if($email==false){
  2134.                 $rfc822_email=false;
  2135.             }else{
  2136.                 if(!isset($personal_name)){
  2137.                     $rfc822_email"<"$email ">";
  2138.                 }else{
  2139.                     $rfc822_email"\""$personal_name ."\" <"$email ">";
  2140.                 }
  2141.             }
  2142.             $email_arr[= array "PERSONAL_NAME"=> $personal_name "AT_DOMAIN_LIST"=>$at_domain_list ,
  2143.                                    "MAILBOX_NAME"=> $this->utf_7_decode($mailbox_name)"HOST_NAME"=> $host_name,
  2144.                                    "EMAIL"=>$email "RFC822_EMAIL" => $rfc822_email );
  2145.             return $email_arr;
  2146.         }
  2147.  
  2148.         return array();
  2149.     }
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.     /**
  2158.     * Utility funcion to find the closing parenthesis ")" Position it takes care of quoted ones
  2159.     *
  2160.     * @param string the IMAP's server response
  2161.     *
  2162.     * @return int containing  the pos of the closing parenthesis ")"
  2163.     * @access private
  2164.     * @since  1.0
  2165.     */
  2166.     function _getClosingBracesPos($str_line$startDelim ='('$stopDelim ')' )
  2167.     {
  2168.         $len strlen$str_line );
  2169.         $pos = 0;
  2170.         // ignore all extra characters
  2171.         // If inside of a string, skip string -- Boundary IDs and other
  2172.         // things can have ) in them.
  2173.         if $str_line[$pos!= $startDelim {
  2174.             $this->_prot_error("_getClosingParenthesisPos: must start with a '(' but is a '"$str_line[$pos."'!!!!\n" .
  2175.                 "STR_LINE:$str_line|size:$len|POS: $pos\n__LINE__ __FILE__ );
  2176.             return$len );
  2177.         }
  2178.         for$pos = 1 ; $pos $len $pos++ ){
  2179.             if ($str_line[$pos== $stopDelim {
  2180.                 break;
  2181.             }
  2182.             if ($str_line[$pos== '"'{
  2183.                 $pos++;
  2184.                 while $str_line[$pos!= '"' && $pos $len {
  2185.                     if ($str_line[$pos== "\\" && $str_line[$pos + 1 == '"' )
  2186.                         $pos++;
  2187.                     if ($str_line[$pos== "\\" && $str_line[$pos + 1 == "\\" )
  2188.                         $pos++;
  2189.                     $pos++;
  2190.                 }
  2191.             }
  2192.             if $str_line[$pos== $startDelim {
  2193.                 $str_line_aux substr$str_line $pos );
  2194.                 $pos_aux $this->_getClosingBracesPos$str_line_aux );
  2195.                 $pos+=$pos_aux;
  2196.             }
  2197.         }
  2198.         if$str_line[$pos!= $stopDelim ){
  2199.             $this->_prot_error("_getClosingBracesPos: must be a $stopDelim but is a '". $str_line[$pos."'|POS:$pos|STR_LINE:$str_line!!!!__LINE__ __FILE__ );
  2200.         }
  2201.  
  2202.         if$pos >= $len )
  2203.             return false;
  2204.         return $pos;
  2205.     }
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.     /**
  2213.     * Utility funcion to get from here to the end of the line
  2214.     *
  2215.     * @param string the IMAP's server response
  2216.     *
  2217.     * @return string containing  the string to the end of the line
  2218.     * @access private
  2219.     * @since  1.0
  2220.     */
  2221.  
  2222.     function _getToEOL(&$str $including = true)
  2223.     {
  2224.         $len strlen$str );
  2225.         if$including ){
  2226.             for($i=0;$i<$len;$i++){
  2227.                 if$str[$i=="\n" )
  2228.                     break;
  2229.             }
  2230.             $content=substr($str,0,$i + 1);
  2231.             $str=substr($str,$i + 1);
  2232.             return $content;
  2233.  
  2234.         }else{
  2235.             for$i = 0 ; $i $len $i++ ){
  2236.                 if$str[$i=="\n" || $str[$i== "\r")
  2237.                     break;
  2238.             }
  2239.             $content substr$str ,$i );
  2240.             $str substr$str $i );
  2241.             return $content;
  2242.         }
  2243.     }
  2244.  
  2245.  
  2246.  
  2247.  
  2248.     /**
  2249.     * Fetches the next IMAP token or parenthesis
  2250.     *
  2251.     * @param string the IMAP's server response
  2252.     * @param string the next token
  2253.     * @param boolean true: the parenthesis IS a token, false: I consider
  2254.     *         all the response in parenthesis as a token
  2255.     *
  2256.     * @return int containing  the content size
  2257.     * @access private
  2258.     * @since  1.0
  2259.     */
  2260.  
  2261.  
  2262.     function _getNextToken(&$str&$content$parenthesisIsToken=true,$colonIsToken=true){
  2263.         $len strlen($str);
  2264.         $pos = 0;
  2265.         $content_size = false;
  2266.         $content = false;
  2267.         if($str == '' || $len < 2 ){
  2268.             $content=$str;
  2269.             return $len;
  2270.         }
  2271.         switch$str[0){
  2272.         case '{':
  2273.             if( ($posClosingBraces $this->_getClosingBracesPos($str'{' '}' )) == false ){
  2274.                 $this->_prot_error("_getClosingBracesPos() error!!!" __LINE__ __FILE__ );
  2275.             }
  2276.             if(is_numeric( ( $strBytes substr$str $posClosingBraces - 1) ) ) ){
  2277.                 $this->_prot_error("must be a number but is a '" $strBytes ."'!!!!" __LINE__ __FILE__ );
  2278.             }
  2279.             if$str[$posClosingBraces!= '}' ){
  2280.                 $this->_prot_error("must be a '}'  but is a '" $str[$posClosingBraces."'!!!!" __LINE__ __FILE__ );
  2281.             }
  2282.             if$str[$posClosingBraces + 1!= "\r" ){
  2283.                 $this->_prot_error("must be a '\\r'  but is a '" $str[$posClosingBraces + 1."'!!!!" __LINE__ __FILE__ );
  2284.             }
  2285.             if$str[$posClosingBraces + 2!= "\n" ){
  2286.                 $this->_prot_error("must be a '\\n'  but is a '" $str[$posClosingBraces + 2."'!!!!" __LINE__ __FILE__ );
  2287.             }
  2288.             $content substr$str $posClosingBraces + 3 $strBytes );
  2289.             ifstrlen$content != $strBytes ){
  2290.                 $this->_prot_error("content size is "strlen($content. " but the string reports a size of $strBytes!!!\n__LINE__ __FILE__ );
  2291.             }
  2292.             $content_size $strBytes;
  2293.             //Advance the string
  2294.             $str substr$str $posClosingBraces $strBytes + 3 );
  2295.             break;
  2296.         case '"':
  2297.             if($colonIsToken){
  2298.                 for($pos=1;$pos<$len;$pos++){
  2299.                     if $str[$pos== "\"" {
  2300.                         break;
  2301.                     }
  2302.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\"" )
  2303.                         $pos++;
  2304.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\\" )
  2305.                         $pos++;
  2306.                 }
  2307.                 if($str[$pos!= '"' ){
  2308.                     $this->_prot_error("must be a '\"'  but is a '" $str[$pos."'!!!!" __LINE__ __FILE__ );
  2309.                 }
  2310.                 $content_size $pos;
  2311.                 $content substr$str $pos - 1 );
  2312.                 //Advance the string
  2313.                 $str substr$str $pos + 1 );
  2314.             }else{
  2315.                 for($pos=1;$pos<$len;$pos++){
  2316.                     if $str[$pos== "\"" {
  2317.                         break;
  2318.                     }
  2319.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\"" )
  2320.                         $pos++;
  2321.                     if ($str[$pos== "\\" && $str[$pos + 1 == "\\" )
  2322.                         $pos++;
  2323.                 }
  2324.                 if($str[$pos!= '"' ){
  2325.                     $this->_prot_error("must be a '\"'  but is a '" $str[$pos."'!!!!" __LINE__ __FILE__ );
  2326.                 }
  2327.                 $content_size $pos;
  2328.                 $content substr$str $pos + 1 );
  2329.                 //Advance the string
  2330.                 $str substr$str $pos + 1 );
  2331.  
  2332.             }
  2333.             break;
  2334.  
  2335.         case "\r":
  2336.             $pos = 1;
  2337.             if$str[1== "\n")
  2338.                 $pos++;
  2339.             $content_size $pos;
  2340.             $content substr$str $pos );
  2341.             $str substr$str $pos );
  2342.             break;
  2343.         case "\n":
  2344.             $pos = 1;
  2345.             $content_size $pos;
  2346.             $content substr$str $pos );
  2347.             $str substr$str $pos );
  2348.             break;
  2349.         case '(':
  2350.             if$parenthesisIsToken == false ){
  2351.                 $pos $this->_getClosingBracesPos$str );
  2352.                 $content_size $pos + 1;
  2353.                 $content substr$str $pos + 1 );
  2354.                 $str substr$str $pos + 1 );
  2355.             }else{
  2356.                 $pos = 1;
  2357.                 $content_size $pos;
  2358.                 $content substr$str $pos );
  2359.                 $str substr$str $pos );
  2360.             }
  2361.             break;
  2362.         case ')':
  2363.             $pos = 1;
  2364.             $content_size $pos;
  2365.             $content substr$str $pos );
  2366.             $str substr$str $pos );
  2367.             break;
  2368.         case ' ':
  2369.             $pos = 1;
  2370.             $content_size $pos;
  2371.             $content substr$str $pos );
  2372.             $str substr$str $pos );
  2373.             break;
  2374.         default:
  2375.             for$pos = 0 ; $pos $len $pos++ ){
  2376.                 if $str[$pos== ' ' || $str[$pos== "\r" || $str[$pos== ')' || $str[$pos== '(' || $str[$pos== "\n" {
  2377.                     break;
  2378.                 }
  2379.                 if $str[$pos== "\\" && $str[$pos + 1 == ' '  )
  2380.                     $pos++;
  2381.                 if $str[$pos== "\\" && $str[$pos + 1 == "\\" )
  2382.                     $pos++;
  2383.             }
  2384.             //Advance the string
  2385.             if$pos == 0 ){
  2386.                 $content_size = 1;
  2387.                 $content substr$str );
  2388.                 $str substr$str );
  2389.             }else{
  2390.                 $content_size $pos;
  2391.                 $content substr$str $pos );
  2392.                 if($pos $len){
  2393.                     $str substr$str $pos  );
  2394.                 }else{
  2395.                 //if this is the end of the string... exit the switch
  2396.                     break;
  2397.                 }
  2398.  
  2399.  
  2400.             }
  2401.             break;
  2402.         }
  2403.         return $content_size;
  2404.     }
  2405.  
  2406.  
  2407.  
  2408.  
  2409.  
  2410.  
  2411.     /**
  2412.     * Utility funcion to display to console the protocol errors
  2413.     *
  2414.     * @param string the error
  2415.     * @param int the line producing the error
  2416.     * @param string file where the error was produced
  2417.     *
  2418.     * @return string containing  the error
  2419.     * @access private
  2420.     * @since  1.0
  2421.     */
  2422.     function _prot_error($str $line $file,$printError=true)
  2423.     {
  2424.         if($printError){
  2425.             echo "$line,$file,PROTOCOL ERROR!:$str\n";
  2426.         }
  2427.     }
  2428.  
  2429.  
  2430.  
  2431.  
  2432.  
  2433.  
  2434.  
  2435.     function _getEXTarray(&$str $startDelim '(' $stopDelim ')'){
  2436.         /* I let choose the $startDelim  and $stopDelim to allow parsing
  2437.            the OK response  so I also can parse a response like this
  2438.            * OK [UIDNEXT 150] Predicted next UID
  2439.         */
  2440.         $this->_getNextToken$str $parenthesis );
  2441.         if$parenthesis != $startDelim ){
  2442.             $this->_prot_error("must be a '$startDelim' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2443.         }
  2444.         $parenthesis '';
  2445.         $struct_arr = array();
  2446.         while$parenthesis != $stopDelim && $str != '' ){
  2447.             // The command
  2448.             $this->_getNextToken$str $token );
  2449.             $token strtoupper$token );
  2450.  
  2451.             if( ( $ret $this->_retrParsedResponse$str $token ) ) != false ){
  2452.                 //$struct_arr[$token] = $ret;
  2453.                 $struct_arr=array_merge($struct_arr$ret);
  2454.             }
  2455.  
  2456.             $parenthesis=$token;
  2457.  
  2458.         }//While
  2459.  
  2460.        if$parenthesis != $stopDelim  ){
  2461.             $this->_prot_error("1_must be a '$stopDelim' but is a '$parenthesis' !!!!__LINE__ __FILE__ );
  2462.        }
  2463.         return $struct_arr;
  2464.     }
  2465.  
  2466.  
  2467.  
  2468.  
  2469.  
  2470.     function _retrParsedResponse&$str $token$previousToken = null)
  2471.     {
  2472.  
  2473.     //echo "\n\nTOKEN:$token\r\n";
  2474.         switch$token ){
  2475.         case "RFC822.SIZE" :
  2476.             return array($token=>$this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2477.             break;
  2478. //        case "RFC822.TEXT" :
  2479.  
  2480. //        case "RFC822.HEADER" :
  2481.  
  2482.  
  2483.         case "RFC822" :
  2484.             return array($token=>$this->_parseContentresponse$str $token ));
  2485.             break;
  2486.         case "FLAGS" :
  2487.  
  2488.         case "PERMANENTFLAGS" :
  2489.             return array($token=>$this->_parseFLAGSresponse$str ));
  2490.             break;
  2491.  
  2492.         case "ENVELOPE" :
  2493.             return array($token=>$this->_parseENVELOPEresponse$str ));
  2494.             break;
  2495.         case "EXPUNGE" :
  2496.             return false;
  2497.             break;
  2498.  
  2499.         case "UID" :
  2500.  
  2501.         case "UIDNEXT" :
  2502.  
  2503.         case "UIDVALIDITY" :
  2504.  
  2505.         case "UNSEEN" :
  2506.  
  2507.         case "MESSAGES" :
  2508.  
  2509.         case "UIDNEXT" :
  2510.  
  2511.         case "UIDVALIDITY" :
  2512.  
  2513.         case "UNSEEN" :
  2514.  
  2515.         case "INTERNALDATE" :
  2516.             return array($token=>$this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2517.             break;
  2518.         case "BODY" :
  2519.  
  2520.         case "BODYSTRUCTURE" :
  2521.             return array($token=>$this->_parseBodyResponse$str $token ));
  2522.             break;
  2523.         case "RECENT" :
  2524.             if$previousToken != null ){
  2525.                 $aux["RECENT"]=$previousToken;
  2526.                 return $aux;
  2527.             }else{
  2528.                 return array($token=>$this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2529.             }
  2530.             break;
  2531.  
  2532.         case "EXISTS" :
  2533.             return array($token=>$previousToken);
  2534.             break;
  2535.         case "READ-WRITE" :
  2536.  
  2537.         case "READ-ONLY" :
  2538.             return array($token=>$token);
  2539.             break;
  2540.         case "QUOTA" :
  2541.             /*
  2542.             A tipical GETQUOTA DIALOG IS AS FOLLOWS
  2543.  
  2544.                 C: A0004 GETQUOTA user.damian
  2545.                 S: * QUOTA user.damian (STORAGE 1781460 4000000)
  2546.                 S: A0004 OK Completed
  2547.             */
  2548.  
  2549.             $mailbox $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2550.             $this->_parseSpace$str __LINE__ __FILE__ );
  2551.             $this->_parseString$str '(' __LINE__ __FILE__ );
  2552.  
  2553.             $ret_aux = array("MAILBOX"=>$this->utf_7_decode($mailbox) );
  2554.             $this->_getNextToken$str $quota_resp );
  2555.             if( ( $ext $this->_retrParsedResponse$str $quota_resp )) == false){
  2556.                     $this->_prot_error("bogus response!!!!" __LINE__ __FILE__ );
  2557.             }
  2558.             $ret_aux=array_merge($ret_aux,$ext);
  2559.  
  2560.             $this->_getNextToken$str $separator );
  2561.             if$separator == ')' ){
  2562.                 return array($token=>$ret_aux);
  2563.             }
  2564.  
  2565.  
  2566.             $this->_parseSpace$str __LINE__ __FILE__ );
  2567.  
  2568.             $this->_getNextToken$str $quota_resp );
  2569.             if( ( $ext $this->_retrParsedResponse$str $quota_resp )) == false){
  2570.                     $this->_prot_error("bogus response!!!!" __LINE__ __FILE__ );
  2571.             }
  2572.             $ret_aux=array_merge($ret_aux,$ext);
  2573.  
  2574.             $this->_parseString$str ')' __LINE__ __FILE__ );
  2575.             return array($token=>$ret_aux);
  2576.             break;
  2577.  
  2578.         case "QUOTAROOT" :
  2579.             /*
  2580.             A tipical GETQUOTA DIALOG IS AS FOLLOWS
  2581.  
  2582.                 C: A0004 GETQUOTA user.damian
  2583.                 S: * QUOTA user.damian (STORAGE 1781460 4000000)
  2584.                 S: A0004 OK Completed
  2585.             */
  2586.             $mailbox $this->utf_7_decode($this->_parseOneStringResponse$str,__LINE__ __FILE__ ));
  2587.  
  2588.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2589.  
  2590.             $quotaroot $this->_parseOneStringResponse$str_line,__LINE__ __FILE__ );
  2591.             $ret @array"MAILBOX"=>$this->utf_7_decode($mailbox$token=>$quotaroot );
  2592.             return array($token=>$ret);
  2593.             break;
  2594.         case "STORAGE" :
  2595.                 $used $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2596.                 $qmax $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2597.                 return array($token=>array("USED"=> $used"QMAX" => $qmax));
  2598.         break;
  2599.         case "MESSAGE" :
  2600.                 $mused $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2601.                 $mmax $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2602.                 return array($token=>array("MUSED"=> $mused"MMAX" => $mmax));
  2603.         break;
  2604.         case "FETCH" :
  2605.                 $this->_parseSpace$str  ,__LINE__  ,__FILE__ );
  2606.                 // Get the parsed pathenthesis
  2607.                 $struct_arr $this->_getEXTarray$str );
  2608.                 return $struct_arr;
  2609.             break;
  2610.         case "CAPABILITY" :
  2611.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2612.                 $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2613.                 $struct_arr["CAPABILITIES"explode' ' $str_line );
  2614.                 return array($token=>$struct_arr);
  2615.             break;
  2616.         case "STATUS" :
  2617.                 $mailbox $this->_parseOneStringResponse$str,__LINE__ __FILE__ );
  2618.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2619.                 $ext $this->_getEXTarray$str );
  2620.                 $struct_arr["MAILBOX"$this->utf_7_decode($mailbox);
  2621.                 $struct_arr["ATTRIBUTES"$ext;
  2622.                 return array($token=>$struct_arr);
  2623.             break;
  2624.         case "LIST" :
  2625.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2626.                 $params_arr $this->_arrayfy_content$str );
  2627.  
  2628.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2629.                 $this->_getNextToken$str $hierarchydelim );
  2630.  
  2631.                 $this->_parseSpace$str,__LINE__ __FILE__);
  2632.                 $this->_getNextToken$str $mailbox_name );
  2633.  
  2634.                 $result_array = array"NAME_ATTRIBUTES"=>$params_arr "HIERACHY_DELIMITER"=>$hierarchydelim "MAILBOX_NAME"=>  $this->utf_7_decode($mailbox_name) );
  2635.                 return array($token=>$result_array);
  2636.             break;
  2637.         case "LSUB" :
  2638.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2639.                 $params_arr $this->_arrayfy_content$str );
  2640.  
  2641.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2642.                 $this->_getNextToken$str $hierarchydelim );
  2643.  
  2644.                 $this->_parseSpace$str,__LINE__ __FILE__);
  2645.                 $this->_getNextToken$str $mailbox_name );
  2646.  
  2647.                 $result_array = array"NAME_ATTRIBUTES"=>$params_arr "HIERACHY_DELIMITER"=>$hierarchydelim "MAILBOX_NAME"=> $this->utf_7_decode($mailbox_name) );
  2648.                 return array($token=>$result_array);
  2649.             break;
  2650.  
  2651.             case "SEARCH" :
  2652.                 $str_line rtrimsubstr$this->_getToEOL$str false 1) );
  2653.                 $struct_arr["SEARCH_LIST"explode' ' $str_line );
  2654.                 if(count($struct_arr["SEARCH_LIST"]== 1 && $struct_arr["SEARCH_LIST"][0]==''){
  2655.                     $struct_arr["SEARCH_LIST"]=null;
  2656.                 }
  2657.                 return array($token=>$struct_arr);
  2658.             break;
  2659.             case "OK" :
  2660.                 /* TODO:
  2661.                     parse the [ .... ] part of the response, use the method
  2662.                     _getEXTarray(&$str,'[',$stopDelim=']')
  2663.  
  2664.                 */
  2665.                 $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2666.                 if($str_line[0== '[' ){
  2667.                     $braceLen=$this->_getClosingBracesPos($str_line'['']' );
  2668.                     $str_aux='('substr($str_line,1,$braceLen -1)')';
  2669.                     $ext_arr=$this->_getEXTarray($str_aux);
  2670.                     //$ext_arr=array($token=>$this->_getEXTarray($str_aux));
  2671.                 }else{
  2672.                     $ext_arr=$str_line;
  2673.                     //$ext_arr=array($token=>$str_line);
  2674.                 }
  2675.                 $result_array =  $ext_arr;
  2676.                 return $result_array;
  2677.                 break;
  2678.         case "NO" :
  2679.         /* TODO:
  2680.             parse the [ .... ] part of the response, use the method
  2681.             _getEXTarray(&$str,'[',$stopDelim=']')
  2682.  
  2683.         */
  2684.  
  2685.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2686.             $result_array[@array"COMMAND"=>$token "EXT"=>$str_line );
  2687.             return $result_array;
  2688.             break;
  2689.         case "BAD" :
  2690.         /* TODO:
  2691.             parse the [ .... ] part of the response, use the method
  2692.             _getEXTarray(&$str,'[',$stopDelim=']')
  2693.  
  2694.         */
  2695.  
  2696.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2697.             $result_array[= array"COMMAND"=>$token "EXT"=>$str_line );
  2698.             return $result_array;
  2699.             break;
  2700.         case "BYE" :
  2701.         /* TODO:
  2702.             parse the [ .... ] part of the response, use the method
  2703.             _getEXTarray(&$str,'[',$stopDelim=']')
  2704.  
  2705.         */
  2706.  
  2707.             $str_line rtrimsubstr$this->_getToEOL$str false ) );
  2708.             $result_array[= array"COMMAND"=>$command "EXT"=> $str_line );
  2709.             return $result_array;
  2710.             break;
  2711.  
  2712.         case "LISTRIGHTS" :
  2713.                 $this->_parseSpace$str ,__LINE__ __FILE__ );
  2714.                 $this->_getNextToken$str $mailbox );
  2715.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2716.                 $this->_getNextToken$str $user );
  2717.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2718.                 $this->_getNextToken$str $granted );
  2719.  
  2720.                 $ungranted explode' ' rtrimsubstr$this->_getToEOL$str false ) ) );
  2721.  
  2722.                 $result_array @array"MAILBOX"=>$this->utf_7_decode($mailbox"USER"=>$user "GRANTED"=>$granted "UNGRANTED"=>$ungranted );
  2723.                 return $result_array;
  2724.             break;
  2725.  
  2726.         case "MYRIGHTS" :
  2727.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2728.                 $this->_getNextToken$str ,$mailbox );
  2729.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2730.                 $this->_getNextToken$str $granted );
  2731.  
  2732.                 $result_array = array"MAILBOX"=>$this->utf_7_decode($mailbox"GRANTED"=>$granted );
  2733.                 return $result_array;
  2734.             break;
  2735.  
  2736.         case "ACL" :
  2737.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2738.                 $this->_getNextToken$str $mailbox );
  2739.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2740.                 $acl_arr explode' ' rtrimsubstr$this->_getToEOL$str false ) ) );
  2741.  
  2742.                 for$i = 0 ; $i count$acl_arr $i += 2 ){
  2743.                     $arr[= array"USER"=>$acl_arr[$i"RIGHTS"=>$acl_arr$i + 1 );
  2744.                 }
  2745.  
  2746.                 $result_array = array"MAILBOX"=>$this->utf_7_decode($mailbox"USERS"=>$arr );
  2747.                 return $result_array;
  2748.             break;
  2749.  
  2750.         case "ANNOTATION" :
  2751.                 $this->_parseSpace($str__LINE____FILE__);
  2752.                 $this->_getNextToken($str$mailbox);
  2753.  
  2754.                 $this->_parseSpace($str__LINE____FILE__);
  2755.                 $this->_getNextToken($str$entry);
  2756.  
  2757.                 $this->_parseSpace($str__LINE____FILE__);
  2758.                 $attrs $this->_arrayfy_content($str);
  2759.  
  2760.                 $result_array = array('MAILBOX' => $mailbox'ENTRY' => $entry 'ATTRIBUTES' => $attrs);
  2761.                 return $result_array;
  2762.             break;
  2763.  
  2764.         case "":
  2765.             $this->_prot_error"PROTOCOL ERROR!:str empty!!" __LINE__ __FILE__ );
  2766.             break;
  2767.         case "(":
  2768.             $this->_prot_error("OPENING PARENTHESIS ERROR!!!!!!!!!!!!!!!!!" __LINE__ __FILE__ );
  2769.             break;
  2770.         case ")":
  2771.             //"CLOSING PARENTHESIS BREAK!!!!!!!"
  2772.             break;
  2773.         case "\r\n":
  2774.             $this->_prot_error("BREAK!!!!!!!!!!!!!!!!!" __LINE__ __FILE__ );
  2775.             break;
  2776.         case ' ':
  2777.             // this can happen and we just ignore it
  2778.             // This happens when - for example - fetch returns more than 1 parammeter
  2779.             // for example you ask to get RFC822.SIZE and UID
  2780.             //$this->_prot_error("SPACE BREAK!!!!!!!!!!!!!!!!!" , __LINE__ , __FILE__ );
  2781.             break;
  2782.         default:
  2783.             $body_token=strtoupper(substr($token,0,5));
  2784.             //echo "BODYYYYYYY: $body_token\n";
  2785.             $rfc822_token=strtoupper(substr($token,0,7));
  2786.             //echo "BODYYYYYYY: $rfc822_token|$token\n";
  2787.  
  2788.             if$body_token == 'BODY[' || $body_token == 'BODY.' || $rfc822_token == 'RFC822.' {
  2789.                 //echo "TOKEN:$token\n";
  2790.                 //$this->_getNextToken( $str , $mailbox );
  2791.                 return array($token=>$this->_parseContentresponse$str $token ));
  2792.             }else{
  2793.                 $this->_prot_error"UNIMPLEMMENTED! I don't know the parameter '$token' !!!__LINE__ __FILE__ );
  2794.             }
  2795.             break;
  2796.         }
  2797.         return false;
  2798. }
  2799.  
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.     /*
  2806.     * Verifies that the next character IS a space
  2807.     */
  2808.     function _parseSpace(&$str,$line,$file$printError = true)
  2809.     {
  2810.     /*
  2811.         This code repeats a lot in this class
  2812.         so i make it a function to make all the code shorter
  2813.     */
  2814.         $this->_getNextToken$str $space );
  2815.         if$space != ' ' ){
  2816.             $this->_prot_error("must be a ' ' but is a '$space' !!!!$line $file,$printError );
  2817.         }
  2818.         return $space;
  2819.     }
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.     function _parseString&$str $char $line $file )
  2827.     {
  2828.     /*
  2829.         This code repeats a lot in this class
  2830.         so i make it a function to make all the code shorter
  2831.     */
  2832.         $this->_getNextToken$str $char_aux );
  2833.         ifstrtoupper($char_aux!= strtoupper$char ) ){
  2834.             $this->_prot_error("must be a $char but is a '$char_aux' !!!!"$line $file );
  2835.         }
  2836.         return $char_aux;
  2837.     }
  2838.  
  2839.  
  2840.  
  2841.  
  2842.  
  2843.     function _genericImapResponseParser&$str $cmdid = null )
  2844.     {
  2845.  
  2846.         $result_array=array();
  2847.         if$this->_unParsedReturn ){
  2848.             $unparsed_str $str;
  2849.         }
  2850.  
  2851.         $this->_getNextToken$str $token );
  2852.  
  2853.         while$token != $cmdid && $str != '' ){
  2854.         if($token == "+" ){
  2855.         //if the token  is + ignore the line
  2856.         // TODO: verify that this is correct!!!
  2857.             $this->_getToEOL$str );
  2858.             $this->_getNextToken$str $token );
  2859.         }
  2860.  
  2861.             $this->_parseString$str ' ' __LINE__ __FILE__ );
  2862.  
  2863.             $this->_getNextToken$str $token );
  2864.         if$token == '+' ){
  2865.             $this->_getToEOL$str );
  2866.             $this->_getNextToken$str $token );
  2867.         }else
  2868.             ifis_numeric$token ) ){
  2869.                 // The token is a NUMBER so I store it
  2870.                 $msg_nro $token;
  2871.                 $this->_parseSpace$str __LINE__ __FILE__ );
  2872.  
  2873.                 // I get the command
  2874.                 $this->_getNextToken$str $command );
  2875.  
  2876.                 if( ( $ext_arr $this->_retrParsedResponse$str $command$msg_nro ) ) == false ){
  2877.                 //  if this bogus response cis a FLAGS () or EXPUNGE response
  2878.                 // the ignore it
  2879.                     if$command != 'FLAGS' && $command != 'EXPUNGE' ){
  2880.                         $this->_prot_error("bogus response!!!!" __LINE__ __FILE__false);
  2881.                     }
  2882.                 }
  2883.                 $result_array[= array"COMMAND"=>$command "NRO"=>$msg_nro "EXT"=>$ext_arr );
  2884.             }else{
  2885.                 // OK the token is not a NUMBER so it MUST be a COMMAND
  2886.                 $command $token;
  2887.  
  2888.                 /* Call the parser return the array
  2889.                     take care of bogus responses!
  2890.                 */
  2891.  
  2892.                 if( ( $ext_arr $this->_retrParsedResponse$str $command ) ) == false ){
  2893.                     $this->_prot_error"bogus response!!!! (COMMAND:$command)__LINE__ __FILE__ );
  2894.                 }
  2895.                 $result_array[= array"COMMAND"=>$command "EXT"=>$ext_arr );
  2896.  
  2897.  
  2898.             }
  2899.  
  2900.  
  2901.             $this->_getNextToken$str $token );
  2902.  
  2903.             $token strtoupper$token );
  2904.             if$token != "\r\n" && $token != '' ){
  2905.                 $this->_prot_error("PARSE ERROR!!! must be a '\\r\\n' here  but is a '$token'!!!! (getting the next line)|STR:|$str|__LINE__ __FILE__ );
  2906.             }
  2907.             $this->_getNextToken$str $token );
  2908.  
  2909.             if($token == "+" ){
  2910.                 //if the token  is + ignore the line
  2911.                 // TODO: verify that this is correct!!!
  2912.                 $this->_getToEOL$str );
  2913.                 $this->_getNextToken$str $token );
  2914.             }
  2915.         }//While
  2916.         // OK we finish the UNTAGGED Response now we must parse the FINAL TAGGED RESPONSE
  2917.         //TODO: make this a litle more elegant!
  2918.  
  2919.         $this->_parseSpace$str __LINE__ __FILE__false );
  2920.  
  2921.         $this->_getNextToken$str $cmd_status );
  2922.  
  2923.         $str_line rtrim (substr$this->_getToEOL$str ) );
  2924.  
  2925.  
  2926.         $response["RESPONSE"]=array"CODE"=>$cmd_status "STR_CODE"=>$str_line "CMDID"=>$cmdid );
  2927.  
  2928.         $ret=$response;
  2929.         if!empty($result_array)){
  2930.             $ret=array_merge($ret,array("PARSED"=>$result_array) );
  2931.         }
  2932.  
  2933.         if$this->_unParsedReturn ){
  2934.             $unparsed["UNPARSED"]=$unparsed_str;
  2935.             $ret=array_merge($ret,$unparsed);
  2936.         }
  2937.  
  2938.  
  2939.         ifisset($status_arr) ){
  2940.             $status["STATUS"]=$status_arr;
  2941.             $ret=array_merge($ret,$status);
  2942.         }
  2943.         return $ret;
  2944.  
  2945. }
  2946.  
  2947.  
  2948.  
  2949.  
  2950.     function _genericCommand($command$params '')
  2951.     {
  2952.         if!$this->_connected ){
  2953.             return new PEAR_Error"not connected! (CMD:$command));
  2954.         }
  2955.         $cmdid $this->_getCmdId();
  2956.         $this->_putCMD$cmdid $command $params );
  2957.         $args=$this->_getRawResponse$cmdid );
  2958.         return $this->_genericImapResponseParser$args $cmdid );
  2959.     }
  2960.  
  2961.  
  2962.  
  2963.      function utf_7_encode($str)
  2964.     {
  2965.         if($this->_useUTF_7 == false ){
  2966.             return $str;
  2967.         }
  2968.         //return imap_utf7_encode($str);
  2969.  
  2970.         $encoded_utf7 '';
  2971.         $base64_part  '';
  2972.     if(is_array($str)){
  2973.         return new PEAR_Error('error');
  2974.     }
  2975.  
  2976.  
  2977.         for ($i = 0; $i strlen($str)$i++{
  2978.             //those chars should be base64 encoded
  2979.             if ( ((ord($str[$i]>= 39 and (ord($str[$i]<= 126 )) or ((ord($str[$i]>= 32 and (ord($str[$i]<= 37 )) ) {
  2980.                 if ($base64_part{
  2981.                     $encoded_utf7 sprintf("%s&%s-"$encoded_utf7str_replace('=''',base64_encode($base64_part))  );
  2982.                     $base64_part '';
  2983.                 }
  2984.                 $encoded_utf7 sprintf("%s%s",$encoded_utf7 $str[$i]);
  2985.             else {
  2986.                 //handle &
  2987.                 if (ord($str[$i]== 38 {
  2988.                     if ($base64_part{
  2989.                         $encoded_utf7 sprintf("%s&%s-"$encoded_utf7str_replace('=''',base64_encode($base64_part))  );
  2990.                         $base64_part '';
  2991.                     }
  2992.                     $encoded_utf7 sprintf("%s&-"$encoded_utf7 );
  2993.                 else {
  2994.                     $base64_part sprintf("%s%s",$base64_part  $str[$i]);
  2995.                     //$base64_part = sprintf("%s%s%s",$base64_part , chr(0) , $str[$i]);
  2996.                 }
  2997.             }
  2998.         }
  2999.         if ($base64_part{
  3000.             $encoded_utf7 sprintf("%s&%s-"$encoded_utf7str_replace('=''',base64_encode($base64_part))   );
  3001.             $base64_part '';
  3002.         }
  3003.         return $encoded_utf7;
  3004.     }
  3005.  
  3006.  
  3007.     function utf_7_decode($str)
  3008.     {
  3009.  
  3010.         if($this->_useUTF_7 == false ){
  3011.             return $str;
  3012.         }
  3013.  
  3014.         //return imap_utf7_decode($str);
  3015.  
  3016.         $base64_part '';
  3017.         $decoded_utf7 '';
  3018.  
  3019.         for ($i = 0; $i strlen($str)$i++{
  3020.             if strlen($base64_part> 0 {
  3021.                 if ($str[$i== '-'{
  3022.                     if ($base64_part == '&'{
  3023.                         $decoded_utf7 sprintf("%s&" $decoded_utf7 );
  3024.                     else {
  3025.                         $next_part_decodedbase64_decodesubstr$base64_part) ) ;
  3026.                         $decoded_utf7 sprintf("%s%s"$decoded_utf7 $next_part_decoded );
  3027.                     }
  3028.                     $base64_part '';
  3029.  
  3030.                 else {
  3031.                     $base64_part sprintf("%s%s"$base64_part $str[$i);
  3032.                 }
  3033.             else {
  3034.                 if ($str[$i== '&'{
  3035.                     $base64_part '&';
  3036.                 else {
  3037.                     $decoded_utf7 sprintf("%s%s"$decoded_utf7 $str[$i);
  3038.                 }
  3039.             }
  3040.         }
  3041.         return $decoded_utf7;
  3042.     }
  3043.  
  3044.  
  3045.  
  3046. }//Class
  3047. ?>

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