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

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