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

Source for file Sieve.php

Documentation is available at Sieve.php

  1. <?php
  2. // +-----------------------------------------------------------------------+
  3. // | Copyright (c) 2002-2003, Richard Heyes                                     |
  4. // | All rights reserved.                                                  |
  5. // |                                                                       |
  6. // | Redistribution and use in source and binary forms, with or without    |
  7. // | modification, are permitted provided that the following conditions    |
  8. // | are met:                                                              |
  9. // |                                                                       |
  10. // | o Redistributions of source code must retain the above copyright      |
  11. // |   notice, this list of conditions and the following disclaimer.       |
  12. // | o Redistributions in binary form must reproduce the above copyright   |
  13. // |   notice, this list of conditions and the following disclaimer in the |
  14. // |   documentation and/or other materials provided with the distribution.|
  15. // | o The names of the authors may not be used to endorse or promote      |
  16. // |   products derived from this software without specific prior written  |
  17. // |   permission.                                                         |
  18. // |                                                                       |
  19. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
  20. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
  21. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  22. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
  23. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  24. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
  25. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  26. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  27. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
  28. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  29. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
  30. // |                                                                       |
  31. // +-----------------------------------------------------------------------+
  32. // | Author: Richard Heyes <richard@phpguru.org>                           |
  33. // | Co-Author: Damian Fernandez Sosa <damlists@cnba.uba.ar>               |
  34. // +-----------------------------------------------------------------------+
  35.  
  36. require_once('Net/Socket.php');
  37.  
  38. /**
  39. * TODO
  40. *
  41. * o supportsAuthMech()
  42. */
  43.  
  44. /**
  45. * Disconnected state
  46. @const NET_SIEVE_STATE_DISCONNECTED
  47. */
  48. define('NET_SIEVE_STATE_DISCONNECTED',  1true);
  49.  
  50. /**
  51. * Authorisation state
  52. @const NET_SIEVE_STATE_AUTHORISATION
  53. */
  54. define('NET_SIEVE_STATE_AUTHORISATION'2true);
  55.  
  56. /**
  57. * Transaction state
  58. @const NET_SIEVE_STATE_TRANSACTION
  59. */
  60. define('NET_SIEVE_STATE_TRANSACTION',   3true);
  61.  
  62. /**
  63. * A class for talking to the timsieved server which
  64. * comes with Cyrus IMAP. the HAVESPACE
  65. * command which appears to be broken (Cyrus 2.0.16).
  66. *
  67. @author  Richard Heyes <richard@php.net>
  68. @author  Damian Fernandez Sosa <damlists@cnba.uba.ar>
  69. @access  public
  70. @version 0.9.1
  71. @package Net_Sieve
  72. */
  73.  
  74. class Net_Sieve
  75. {
  76.     /**
  77.     * The socket object
  78.     * @var object 
  79.     */
  80.     var $_sock;
  81.  
  82.     /**
  83.     * Info about the connect
  84.     * @var array 
  85.     */
  86.     var $_data;
  87.  
  88.     /**
  89.     * Current state of the connection
  90.     * @var integer 
  91.     */
  92.     var $_state;
  93.  
  94.     /**
  95.     * Constructor error is any
  96.     * @var object 
  97.     */
  98.     var $_error;
  99.  
  100.  
  101.     /**
  102.     * To allow class debuging
  103.     * @var boolean 
  104.     */
  105.     var $_debug = false;
  106.  
  107.  
  108.     /**
  109.     * The auth methods this class support
  110.     * @var array 
  111.     */
  112.  
  113.     var $supportedAuthMethods=array('DIGEST-MD5''CRAM-MD5''PLAIN' 'LOGIN');
  114.     //if you have problems using DIGEST-MD5 authentication  please commente the line above and discomment the following line
  115.     //var $supportedAuthMethods=array( 'CRAM-MD5', 'PLAIN' , 'LOGIN');
  116.  
  117.     //var $supportedAuthMethods=array( 'PLAIN' , 'LOGIN');
  118.  
  119.  
  120.     /**
  121.     * The auth methods this class support
  122.     * @var array 
  123.     */
  124.     var $supportedSASLAuthMethods=array('DIGEST-MD5''CRAM-MD5');
  125.  
  126.  
  127.  
  128.     /**
  129.     * Handles posible referral loops
  130.     * @var array 
  131.     */
  132.     var $_maxReferralCount = 15;
  133.  
  134.     /**
  135.     * Constructor
  136.     * Sets up the object, connects to the server and logs in. stores
  137.     * any generated error in $this->_error, which can be retrieved
  138.     * using the getError() method.
  139.     *
  140.     * @access public
  141.     * @param  string $user      Login username
  142.     * @param  string $pass      Login password
  143.     * @param  string $host      Hostname of server
  144.     * @param  string $port      Port of server
  145.     * @param  string $logintype Type of login to perform
  146.     * @param  string $euser     Effective User (if $user=admin, login as $euser)
  147.     */
  148.     function Net_Sieve($user = null $pass  = null $host 'localhost'$port = 2000$logintype ''$euser ''$debug = false)
  149.     {
  150.         $this->_state NET_SIEVE_STATE_DISCONNECTED;
  151.         $this->_data['user'$user;
  152.         $this->_data['pass'$pass;
  153.         $this->_data['host'$host;
  154.         $this->_data['port'$port;
  155.         $this->_data['logintype'$logintype;
  156.         $this->_data['euser'$euser;
  157.         $this->_sock &new Net_Socket();
  158.         $this->_debug  $debug;
  159.         /*
  160.         * Include the Auth_SASL package.  If the package is not available,
  161.         * we disable the authentication methods that depend upon it.
  162.         */
  163.         if ((@include_once 'Auth/SASL.php'=== false{
  164.             if($this->_debug){
  165.                 echo "AUTH_SASL NOT PRESENT!\n";
  166.             }
  167.             foreach($this->supportedSASLAuthMethods as $SASLMethod){
  168.                 $pos array_search$SASLMethod$this->supportedAuthMethods );
  169.                 if($this->_debug){
  170.                     echo "DISABLING METHOD $SASLMethod\n";
  171.                 }
  172.                 unset($this->supportedAuthMethods[$pos]);
  173.             }
  174.         }
  175.         if( ($user != null&& ($pass != null) ){
  176.             $this->_error $this->_handleConnectAndLogin();
  177.         }
  178.     }
  179.  
  180.  
  181.  
  182.     /**
  183.     * Handles the errors the class can find
  184.     * on the server
  185.     *
  186.     * @access private
  187.     * @return PEAR_Error 
  188.     */
  189.  
  190.     function _raiseError($msg$code)
  191.     {
  192.     include_once 'PEAR.php';
  193.     return PEAR::raiseError($msg$code);
  194.     }
  195.  
  196.  
  197.  
  198.  
  199.  
  200.     /**
  201.     * Handles connect and login.
  202.     * on the server
  203.     *
  204.     * @access private
  205.     * @return mixed Indexed array of scriptnames or PEAR_Error on failure
  206.     */
  207.     function _handleConnectAndLogin(){
  208.         if (PEAR::isError($res $this->connect($this->_data['host'$this->_data['port'))) {
  209.             return $res;
  210.         }
  211.         if (PEAR::isError($res $this->login($this->_data['user']$this->_data['pass']$this->_data['logintype'$this->_data['euser') ) ) {
  212.             return $res;
  213.         }
  214.         return true;
  215.  
  216.     }
  217.  
  218.  
  219.  
  220.  
  221.     /**
  222.     * Returns an indexed array of scripts currently
  223.     * on the server
  224.     *
  225.     * @access public
  226.     * @return mixed Indexed array of scriptnames or PEAR_Error on failure
  227.     */
  228.     function listScripts()
  229.     {
  230.         if (is_array($scripts $this->_cmdListScripts())) {
  231.             $this->_active $scripts[1];
  232.             return $scripts[0];
  233.         else {
  234.             return $scripts;
  235.         }
  236.     }
  237.  
  238.     /**
  239.     * Returns the active script
  240.     *
  241.     * @access public
  242.     * @return mixed The active scriptname or PEAR_Error on failure
  243.     */
  244.     function getActive()
  245.     {
  246.         if (!empty($this->_active)) {
  247.             return $this->_active;
  248.  
  249.         elseif (is_array($scripts $this->_cmdListScripts())) {
  250.             $this->_active $scripts[1];
  251.             return $scripts[1];
  252.         }
  253.     }
  254.  
  255.     /**
  256.     * Sets the active script
  257.     *
  258.     * @access public
  259.     * @param  string $scriptname The name of the script to be set as active
  260.     * @return mixed              true on success, PEAR_Error on failure
  261.     */
  262.     function setActive($scriptname)
  263.     {
  264.         return $this->_cmdSetActive($scriptname);
  265.     }
  266.  
  267.     /**
  268.     * Retrieves a script
  269.     *
  270.     * @access public
  271.     * @param  string $scriptname The name of the script to be retrieved
  272.     * @return mixed              The script on success, PEAR_Error on failure
  273.     */
  274.     function getScript($scriptname)
  275.     {
  276.         return $this->_cmdGetScript($scriptname);
  277.     }
  278.  
  279.     /**
  280.     * Adds a script to the server
  281.     *
  282.     * @access public
  283.     * @param  string $scriptname Name of the script
  284.     * @param  string $script     The script
  285.     * @param  bool   $makeactive Whether to make this the active script
  286.     * @return mixed              true on success, PEAR_Error on failure
  287.     */
  288.     function installScript($scriptname$script$makeactive = false)
  289.     {
  290.         if (PEAR::isError($res $this->_cmdPutScript($scriptname$script))) {
  291.             return $res;
  292.  
  293.         elseif ($makeactive{
  294.             return $this->_cmdSetActive($scriptname);
  295.  
  296.         else {
  297.             return true;
  298.         }
  299.     }
  300.  
  301.     /**
  302.     * Removes a script from the server
  303.     *
  304.     * @access public
  305.     * @param  string $scriptname Name of the script
  306.     * @return mixed              True on success, PEAR_Error on failure
  307.     */
  308.     function removeScript($scriptname)
  309.     {
  310.         return $this->_cmdDeleteScript($scriptname);
  311.     }
  312.  
  313.     /**
  314.     * Returns any error that may have been generated in the
  315.     * constructor
  316.     *
  317.     * @access public
  318.     * @return mixed False if no error, PEAR_Error otherwise
  319.     */
  320.     function getError()
  321.     {
  322.         return PEAR::isError($this->_error$this->_error : false;
  323.     }
  324.  
  325.     /**
  326.     * Handles connecting to the server and checking the
  327.     * response is valid.
  328.     *
  329.     * @access private
  330.     * @param  string $host Hostname of server
  331.     * @param  string $port Port of server
  332.     * @return mixed        True on success, PEAR_Error otherwise
  333.     */
  334.     function connect($host$port)
  335.     {
  336.         if (NET_SIEVE_STATE_DISCONNECTED != $this->_state{
  337.             $msg='Not currently in DISCONNECTED state';
  338.             $code=1;
  339.             return $this->_raiseError($msg,$code);
  340.         }
  341.  
  342.         if (PEAR::isError($res $this->_sock->connect($host$portnull5))) {
  343.             return $res;
  344.         }
  345.  
  346.  
  347.         $this->_state NET_SIEVE_STATE_AUTHORISATION;
  348.         if (PEAR::isError($res $this->_doCmd())) {
  349.             return $res;
  350.         }
  351.         /*
  352.         if(PEAR::isError($res = $this->_cmdCapability() )) {
  353.             $msg='Failed to connect, server said: ' . $res->getMessage();
  354.             $code=2;
  355.             return $this->_raiseError($msg,$code);
  356.         }
  357. */
  358.         // Get logon greeting/capability and parse
  359.         $this->_parseCapability($res);
  360.  
  361.         return true;
  362.     }
  363.  
  364.     /**
  365.     * Logs into server.
  366.     *
  367.     * @access public
  368.     * @param  string  $user          Login username
  369.     * @param  string  $pass          Login password
  370.     * @param  string  $logintype     Type of login method to use
  371.     * @param  string  $euser         Effective UID (perform on behalf of $euser)
  372.     * @param  boolean $bypassAuth    dont perform auth
  373.     * @return mixed                  True on success, PEAR_Error otherwise
  374.     */
  375.     function login($user$pass$logintype = null $euser ''$bypassAuth=false)
  376.     {
  377.         if (NET_SIEVE_STATE_AUTHORISATION != $this->_state{
  378.             $msg='Not currently in AUTHORISATION state';
  379.             $code=1;
  380.             return $this->_raiseError($msg,$code);
  381.         }
  382.  
  383.  
  384.         
  385.         if$bypassAuth === false ){
  386.             if(PEAR::isError($res=$this->_cmdAuthenticate($user $pass $logintype$euser ) ) ){
  387.                 return $res;
  388.             }
  389.         }
  390.         $this->_state NET_SIEVE_STATE_TRANSACTION;
  391.         return true;
  392.     }
  393.  
  394.  
  395.  
  396.      /* Handles the authentication using any known method
  397.      *
  398.      * @param string The userid to authenticate as.
  399.      * @param string The password to authenticate with.
  400.      * @param string The method to use ( if $usermethod == '' then the class chooses the best method (the stronger is the best ) )
  401.      * @param string The effective uid to authenticate as.
  402.      *
  403.      * @return mixed  string or PEAR_Error
  404.      *
  405.      * @access private
  406.      * @since  1.0
  407.      */
  408.     function _cmdAuthenticate($uid $pwd $userMethod = null $euser '' )
  409.     {
  410.  
  411.  
  412.         if PEAR::isError$method $this->_getBestAuthMethod($userMethod) ) ) {
  413.             return $method;
  414.         }
  415.         switch ($method{
  416.             case 'DIGEST-MD5':
  417.                 $result $this->_authDigest_MD5$uid $pwd $euser );
  418.                 return $result;
  419.                 break;
  420.             case 'CRAM-MD5':
  421.                 $result $this->_authCRAM_MD5$uid $pwd$euser);
  422.                 break;
  423.             case 'LOGIN':
  424.                 $result $this->_authLOGIN$uid $pwd $euser );
  425.                 break;
  426.             case 'PLAIN':
  427.                 $result $this->_authPLAIN$uid $pwd $euser );
  428.                 break;
  429.             default :
  430.                 $result = new PEAR_Error"$method is not a supported authentication method);
  431.                 break;
  432.         }
  433.  
  434.  
  435.         if (PEAR::isError($res $this->_doCmd() )) {
  436.             return $res;
  437.         }
  438.         return $result;
  439.     }
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.      /* Authenticates the user using the PLAIN method.
  450.      *
  451.      * @param string The userid to authenticate as.
  452.      * @param string The password to authenticate with.
  453.      * @param string The effective uid to authenticate as.
  454.      *
  455.      * @return array Returns an array containing the response
  456.      *
  457.      * @access private
  458.      * @since  1.0
  459.      */
  460.     function _authPLAIN($user$pass $euser )
  461.     {
  462.  
  463.         if ($euser != ''{
  464.             $cmd=sprintf('AUTHENTICATE "PLAIN" "%s"'base64_encode($euser chr(0$user chr(0$pass ) ) ;
  465.         else {
  466.             $cmd=sprintf('AUTHENTICATE "PLAIN" "%s"'base64_encodechr(0$user chr(0$pass ) );
  467.         }
  468.         return  $this->_sendCmd$cmd ;
  469.  
  470.     }
  471.  
  472.  
  473.  
  474.      /* Authenticates the user using the PLAIN method.
  475.      *
  476.      * @param string The userid to authenticate as.
  477.      * @param string The password to authenticate with.
  478.      * @param string The effective uid to authenticate as.
  479.      *
  480.      * @return array Returns an array containing the response
  481.      *
  482.      * @access private
  483.      * @since  1.0
  484.      */
  485.     function _authLOGIN($user$pass $euser )
  486.     {
  487.         $this->_sendCmd('AUTHENTICATE "LOGIN"');
  488.         $this->_doCmd(sprintf('"%s"'base64_encode($user)));
  489.         $this->_doCmd(sprintf('"%s"'base64_encode($pass)));
  490.  
  491.     }
  492.  
  493.  
  494.  
  495.  
  496.      /* Authenticates the user using the CRAM-MD5 method.
  497.      *
  498.      * @param string The userid to authenticate as.
  499.      * @param string The password to authenticate with.
  500.      * @param string The cmdID.
  501.      *
  502.      * @return array Returns an array containing the response
  503.      *
  504.      * @access private
  505.      * @since  1.0
  506.      */
  507.     function _authCRAM_MD5($uid$pwd$euser)
  508.     {
  509.  
  510.         if PEAR::isError$challenge $this->_doCmd'AUTHENTICATE "CRAM-MD5"' ) ) ) {
  511.             $this->_error=challenge ;
  512.             return challenge ;
  513.         }
  514.         $challenge=trim($challenge);
  515.         $challenge base64_decodetrim($challenge) );
  516.         $cram &Auth_SASL::factory('crammd5');
  517.         if PEAR::isError($resp=$cram->getResponse$uid $pwd $challenge ) ) ) {
  518.             $this->_error=$resp;
  519.             return $resp;
  520.         }
  521.         $auth_str base64_encode$resp );
  522.         if PEAR::isError($error $this->_sendStringResponse$auth_str  ) ) ) {
  523.             $this->_error=$error;
  524.             return $error;
  525.         }
  526.  
  527.     }
  528.  
  529.  
  530.  
  531.      /* Authenticates the user using the DIGEST-MD5 method.
  532.      *
  533.      * @param string The userid to authenticate as.
  534.      * @param string The password to authenticate with.
  535.      * @param string The efective user
  536.      *
  537.      * @return array Returns an array containing the response
  538.      *
  539.      * @access private
  540.      * @since  1.0
  541.      */
  542.     function _authDigest_MD5($uid$pwd$euser)
  543.     {
  544.  
  545.         if PEAR::isError$challenge $this->_doCmd('AUTHENTICATE "DIGEST-MD5"') ) ) {
  546.             $this->_error=challenge ;
  547.             return challenge ;
  548.         }
  549.         $challenge base64_decode$challenge );
  550.         $digest &Auth_SASL::factory('digestmd5');
  551.         
  552.         
  553.         if(PEAR::isError($param=$digest->getResponse($uid$pwd$challenge"localhost""sieve" $euser) )) {
  554.             return $param;
  555.         }
  556.         $auth_str base64_encode($param);
  557.  
  558.         if PEAR::isError($error $this->_sendStringResponse$auth_str  ) ) ) {
  559.             $this->_error=$error;
  560.             return $error;
  561.         }
  562.  
  563.  
  564.  
  565.         if PEAR::isError$challenge $this->_doCmd() ) ) {
  566.             $this->_error=$challenge ;
  567.             return $challenge ;
  568.         }
  569.  
  570.         ifstrtoupper(substr($challenge,0,2))== 'OK' ){
  571.                 return true;
  572.         }
  573.         
  574.  
  575.         /*
  576.         * We don't use the protocol's third step because SIEVE doesn't allow
  577.         * subsequent authentication, so we just silently ignore it.
  578.         */
  579.  
  580.  
  581.         if PEAR::isError($error $this->_sendStringResponse'' ) ) ) {
  582.             $this->_error=$error;
  583.             return $error;
  584.         }
  585.  
  586.         if (PEAR::isError($res $this->_doCmd() )) {
  587.             return $res;
  588.         }
  589.  
  590.  
  591.     }
  592.  
  593.  
  594.  
  595.  
  596.     /**
  597.     * Removes a script from the server
  598.     *
  599.     * @access private
  600.     * @param  string $scriptname Name of the script to delete
  601.     * @return mixed              True on success, PEAR_Error otherwise
  602.     */
  603.     function _cmdDeleteScript($scriptname)
  604.     {
  605.         if (NET_SIEVE_STATE_TRANSACTION != $this->_state{
  606.             $msg='Not currently in AUTHORISATION state';
  607.             $code=1;
  608.             return $this->_raiseError($msg,$code);
  609.         }
  610.         if (PEAR::isError($res $this->_doCmd(sprintf('DELETESCRIPT "%s"'$scriptname) ) )) {
  611.             return $res;
  612.         }
  613.         return true;
  614.     }
  615.  
  616.     /**
  617.     * Retrieves the contents of the named script
  618.     *
  619.     * @access private
  620.     * @param  string $scriptname Name of the script to retrieve
  621.     * @return mixed              The script if successful, PEAR_Error otherwise
  622.     */
  623.     function _cmdGetScript($scriptname)
  624.     {
  625.         if (NET_SIEVE_STATE_TRANSACTION != $this->_state{
  626.             $msg='Not currently in AUTHORISATION state';
  627.             $code=1;
  628.             return $this->_raiseError($msg,$code);
  629.         }
  630.  
  631.         if (PEAR::isError($res $this->_doCmd(sprintf('GETSCRIPT "%s"'$scriptname) ) ) ) {
  632.             return $res;
  633.         }
  634.  
  635.         return preg_replace('/{[0-9]+}\r\n/'''$res);
  636.     }
  637.  
  638.     /**
  639.     * Sets the ACTIVE script, ie the one that gets run on new mail
  640.     * by the server
  641.     *
  642.     * @access private
  643.     * @param  string $scriptname The name of the script to mark as active
  644.     * @return mixed              True on success, PEAR_Error otherwise
  645.     */
  646.     function _cmdSetActive($scriptname)
  647.     {
  648.         if (NET_SIEVE_STATE_TRANSACTION != $this->_state{
  649.             $msg='Not currently in AUTHORISATION state';
  650.             $code=1;
  651.             return $this->_raiseError($msg,$code);
  652.         }
  653.  
  654.         if (PEAR::isError($res $this->_doCmd(sprintf('SETACTIVE "%s"'$scriptname) ) ) ) {
  655.             return $res;
  656.         }
  657.  
  658.         $this->_activeScript $scriptname;
  659.         return true;
  660.     }
  661.  
  662.     /**
  663.     * Sends the LISTSCRIPTS command
  664.     *
  665.     * @access private
  666.     * @return mixed Two item array of scripts, and active script on success,
  667.     *                PEAR_Error otherwise.
  668.     */
  669.     function _cmdListScripts()
  670.     {
  671.  
  672.         if (NET_SIEVE_STATE_TRANSACTION != $this->_state{
  673.             $msg='Not currently in AUTHORISATION state';
  674.             $code=1;
  675.             return $this->_raiseError($msg,$code);
  676.         }
  677.  
  678.         $scripts = array();
  679.         $activescript = null;
  680.  
  681.         if (PEAR::isError($res $this->_doCmd('LISTSCRIPTS'))) {
  682.             return $res;
  683.         }
  684.  
  685.         $res explode("\r\n"$res);
  686.  
  687.         foreach ($res as $value{
  688.             if (preg_match('/^"(.*)"( ACTIVE)?$/i'$value$matches)) {
  689.                 $scripts[$matches[1];
  690.                 if (!empty($matches[2])) {
  691.                     $activescript $matches[1];
  692.                 }
  693.             }
  694.         }
  695.  
  696.         return array($scripts$activescript);
  697.     }
  698.  
  699.     /**
  700.     * Sends the PUTSCRIPT command to add a script to
  701.     * the server.
  702.     *
  703.     * @access private
  704.     * @param  string $scriptname Name of the new script
  705.     * @param  string $scriptdata The new script
  706.     * @return mixed              True on success, PEAR_Error otherwise
  707.     */
  708.     function _cmdPutScript($scriptname$scriptdata)
  709.     {
  710.         if (NET_SIEVE_STATE_TRANSACTION != $this->_state{
  711.             $msg='Not currently in TRANSACTION state';
  712.             $code=1;
  713.             return $this->_raiseError($msg,$code);
  714.         }
  715.  
  716.         if (PEAR::isError($res $this->_doCmd(sprintf("PUTSCRIPT \"%s\" {%d+}\r\n%s"$scriptnamestrlen($scriptdata),$scriptdata ) ))) {
  717.             return $res;
  718.         }
  719.  
  720.         return true;
  721.     }
  722.  
  723.     /**
  724.     * Sends the LOGOUT command and terminates the connection
  725.     *
  726.     * @access private
  727.     * @return mixed True on success, PEAR_Error otherwise
  728.     */
  729.     function _cmdLogout($sendLogoutCMD=true)
  730.     {
  731.         if (NET_SIEVE_STATE_DISCONNECTED === $this->_state{
  732.             $msg='Not currently connected';
  733.             $code=1;
  734.             return $this->_raiseError($msg,$code);
  735.             //return PEAR::raiseError('Not currently connected');
  736.         }
  737.  
  738.         if($sendLogoutCMD){
  739.             if (PEAR::isError($res $this->_doCmd('LOGOUT'))) {
  740.                 return $res;
  741.             }
  742.         }
  743.  
  744.         $this->_sock->disconnect();
  745.         $this->_state NET_SIEVE_STATE_DISCONNECTED;
  746.         return true;
  747.     }
  748.  
  749.     /**
  750.     * Sends the CAPABILITY command
  751.     *
  752.     * @access private
  753.     * @return mixed True on success, PEAR_Error otherwise
  754.     */
  755.     function _cmdCapability()
  756.     {
  757.         if (NET_SIEVE_STATE_DISCONNECTED === $this->_state{
  758.             $msg='Not currently connected';
  759.             $code=1;
  760.             return $this->_raiseError($msg,$code);
  761.         }
  762.         
  763.         if (PEAR::isError($res $this->_doCmd('CAPABILITY'))) {
  764.             return $res;
  765.         }
  766.         $this->_parseCapability($res);
  767.         return true;
  768.     }
  769.  
  770.  
  771.     /**
  772.     * Checks if the server has space to store the script
  773.     * by the server
  774.     *
  775.     * @access public
  776.     * @param  string $scriptname The name of the script to mark as active
  777.     * @return mixed              True on success, PEAR_Error otherwise
  778.     */
  779.     function haveSpace($scriptname,$quota)
  780.     {
  781.         if (NET_SIEVE_STATE_TRANSACTION != $this->_state{
  782.             $msg='Not currently in TRANSACTION state';
  783.             $code=1;
  784.             return $this->_raiseError($msg,$code);
  785.         }
  786.  
  787.         if (PEAR::isError($res $this->_doCmd(sprintf('HAVESPACE "%s" %s'$scriptname$quota) ) ) ) {
  788.         //if (PEAR::isError($res = $this->_doCmd(sprintf('HAVESPACE %d "%s"',  $quota,$scriptname ) ) ) ) {
  789.             return $res;
  790.         }
  791.  
  792.         return true;
  793.     }
  794.  
  795.  
  796.  
  797.  
  798.     /**
  799.     * Parses the response from the capability command. Storesq
  800.     * the result in $this->_capability
  801.     *
  802.     * @access private
  803.     */
  804.     function _parseCapability($data)
  805.     {
  806.         $data preg_split('/\r?\n/'$data-1PREG_SPLIT_NO_EMPTY);
  807.  
  808.         for ($i = 0; $i count($data)$i++{
  809.             if (preg_match('/^"([a-z]+)" ("(.*)")?$/i'$data[$i]$matches)) {
  810.                 switch (strtolower($matches[1])) {
  811.                     case 'implementation':
  812.                         $this->_capability['implementation'$matches[3];
  813.                         break;
  814.  
  815.                     case 'sasl':
  816.                         $this->_capability['sasl'preg_split('/\s+/'$matches[3]);
  817.                         break;
  818.  
  819.                     case 'sieve':
  820.                         $this->_capability['extensions'preg_split('/\s+/'$matches[3]);
  821.                         break;
  822.  
  823.                     case 'starttls':
  824.                         $this->_capability['starttls'= true;
  825.                 }
  826.             }
  827.         }
  828.     }
  829.  
  830.     /**
  831.     * Sends a command to the server
  832.     *
  833.     * @access private
  834.     * @param string $cmd The command to send
  835.     */
  836.     function _sendCmd($cmd)
  837.     {
  838.         $status $this->_sock->getStatus();
  839.         if (PEAR::isError($status|| $status['eof']{
  840.             return new PEAR_Error'Failed to write to socket: (connection lost!) ' );
  841.         }
  842.         if PEAR::isError$error $this->_sock->write$cmd "\r\n" ) ) ) {
  843.             return new PEAR_Error'Failed to write to socket: ' $error->getMessage() );
  844.         }
  845.  
  846.         if$this->_debug ){
  847.             // C: means this data was sent by  the client (this class)
  848.             echo "C:$cmd\n";
  849.         }
  850.         return true;
  851.  
  852.  
  853.     }
  854.  
  855.  
  856.  
  857.     /**
  858.     * Sends a string response to the server
  859.     *
  860.     * @access private
  861.     * @param string $cmd The command to send
  862.     */
  863.     function _sendStringResponse($str)
  864.     {
  865.         $response='{' .  strlen($str"+}\r\n" $str  ;
  866.         return $this->_sendCmd($response);
  867.     }
  868.  
  869.  
  870.  
  871.  
  872.     function _recvLn()
  873.     {
  874.         $lastline='';
  875.         if (PEAR::isError$lastline $this->_sock->gets8192 ) ) ) {
  876.             return new PEAR_Error('Failed to write to socket: ' $lastline->getMessage() );
  877.         }
  878.         $lastline=rtrim($lastline);
  879.         if($this->_debug){
  880.             // S: means this data was sent by  the IMAP Server
  881.             echo "S:$lastline\n" ;
  882.         }
  883.  
  884. /*        if( $lastline === '' ){
  885.             return new PEAR_Error('Failed to receive from the  socket: '  );
  886.         }
  887. */
  888.         return $lastline;
  889.     }
  890.  
  891.  
  892.  
  893.  
  894.  
  895.     /**
  896.     * Send a command and retrieves a response from the server.
  897.     *
  898.     *
  899.     * @access private
  900.     * @param string $cmd The command to send
  901.     * @return mixed Reponse string if an OK response, PEAR_Error if a NO response
  902.     */
  903.     function _doCmd($cmd '' )
  904.     {
  905.  
  906.         $referralCount=0;
  907.         while($referralCount $this->_maxReferralCount ){
  908.  
  909.  
  910.             if($cmd != '' ){
  911.                 if(PEAR::isError($error $this->_sendCmd($cmd) )) {
  912.                     return $error;
  913.                 }
  914.             }
  915.             $response '';
  916.  
  917.             while (true{
  918.                     if(PEAR::isError$line=$this->_recvLn() )){
  919.                         return $line;
  920.                     }
  921.                     if ('ok' === strtolower(substr($line02))) {
  922.                         $response .= $line;
  923.                         return rtrim($response);
  924.  
  925.                     elseif ('no' === strtolower(substr($line02))) {
  926.                         // Check for string literal error message
  927.                         if (preg_match('/^no {([0-9]+)\+?}/i'$line$matches)) {
  928.                             $line .= str_replace("\r\n"' '$this->_sock->read($matches[1+ 2 ));
  929.                             if($this->_debug){
  930.                                 echo "S:$line\n";
  931.                             }
  932.                         }
  933.                         $msg=trim($response substr($line2));
  934.                         $code=3;
  935.                         return $this->_raiseError($msg,$code);
  936.                         //return PEAR::raiseError(trim($response . substr($line, 2)));
  937.                     elseif ('bye' === strtolower(substr($line03))) {
  938.  
  939.                         if(PEAR::isError($error $this->disconnect(false) ) ){
  940.                             $msg="Can't handle bye, The error was= " $error->getMessage(;
  941.                             $code=4;
  942.                             return $this->_raiseError($msg,$code);
  943.                             //return PEAR::raiseError("Can't handle bye, The error was= " . $error->getMessage() );
  944.                         }
  945.                         //if (preg_match('/^bye \(referral "([^"]+)/i', $line, $matches)) {
  946.                         if (preg_match('/^bye \(referral "(sieve:\/\/)?([^"]+)/i'$line$matches)) {
  947.                             // Check for referral, then follow it.  Otherwise, carp an error.
  948.                             //$this->_data['host'] = $matches[1];
  949.                             $this->_data['host'$matches[2];
  950.                             if (PEAR::isError($error $this->_handleConnectAndLogin() ) ){
  951.                                 $msg="Can't follow referral to " $this->_data['host'", The error was= " $error->getMessage(;
  952.                                 $code=5;
  953.                                 return $this->_raiseError($msg,$code);
  954.                                 //return PEAR::raiseError("Can't follow referral to " . $this->_data['host'] . ", The error was= " . $error->getMessage() );
  955.                             }
  956.                             break;
  957.                             // Retry the command
  958.                             if(PEAR::isError($error $this->_sendCmd($cmd) )) {
  959.                                 return $error;
  960.                             }
  961.                             continue;
  962.                         }
  963.                         $msg=trim($response $line);
  964.                         $code=6;
  965.                         return $this->_raiseError($msg,$code);
  966.                         //return PEAR::raiseError(trim($response . $line));
  967.                     elseif (preg_match('/^{([0-9]+)\+?}/i'$line$matches)) {
  968.                         // Matches String Responses.
  969.                         //$line = str_replace("\r\n", ' ', $this->_sock->read($matches[1] + 2 ));
  970.                         $line $this->_sock->read($matches[1+ 2 );
  971.                         if($this->_debug){
  972.                             echo "S:$line\n";
  973.                         }
  974.                         return $line;
  975.                     }
  976.                     $response .= $line "\r\n";
  977.                     $referralCount++;
  978.                 }
  979.         }
  980.         $msg="Max referral count reached ($referralCount times) Cyrus murder loop error?";
  981.         $code=7;
  982.         return $this->_raiseError($msg,$code);
  983.         //return PEAR::raiseError("Max referral count reached ($referralCount times) Cyrus murder loop error?" );
  984.     }
  985.  
  986.  
  987.  
  988.  
  989.     /**
  990.     * Sets the bebug state
  991.     *
  992.     * @access public
  993.     * @return void 
  994.     */
  995.     function setDebug($debug=true)
  996.     {
  997.         $this->_debug=$debug;
  998.     }
  999.  
  1000.     /**
  1001.     * Disconnect from the Sieve server
  1002.     *
  1003.     * @access public
  1004.     * @param  string $scriptname The name of the script to be set as active
  1005.     * @return mixed              true on success, PEAR_Error on failure
  1006.     */
  1007.     function disconnect($sendLogoutCMD=true)
  1008.     {
  1009.         return $this->_cmdLogout($sendLogoutCMD);
  1010.     }
  1011.  
  1012.  
  1013.     /**
  1014.      * Returns the name of the best authentication method that the server
  1015.      * has advertised.
  1016.      *
  1017.      * @param string if !=null,authenticate with this method ($userMethod).
  1018.      *
  1019.      * @return mixed    Returns a string containing the name of the best
  1020.      *                   supported authentication method or a PEAR_Error object
  1021.      *                   if a failure condition is encountered.
  1022.      * @access private
  1023.      * @since  1.0
  1024.      */
  1025.     function _getBestAuthMethod($userMethod = null)
  1026.     {
  1027.  
  1028.        ifisset($this->_capability['sasl']) ){
  1029.            $serverMethods=$this->_capability['sasl'];
  1030.        }else{
  1031.            // if the server don't send an sasl capability fallback to login auth
  1032.            //return 'LOGIN';
  1033.            return new PEAR_Error("This server don't support any Auth methods SASL problem?");
  1034.        }
  1035.  
  1036.         if($userMethod != null ){
  1037.             $methods = array();
  1038.             $methods[$userMethod;
  1039.         }else{
  1040.  
  1041.             $methods $this->supportedAuthMethods;
  1042.         }
  1043.         if( ($methods != null&& ($serverMethods != null)){
  1044.             foreach $methods as $method {
  1045.                 if in_array$method $serverMethods ) ) {
  1046.                     return $method;
  1047.                 }
  1048.             }
  1049.             $serverMethods=implode(',' $serverMethods );
  1050.             $myMethods=implode(',' ,$this->supportedAuthMethods);
  1051.             return new PEAR_Error("$method NOT supported authentication method!. This server " .
  1052.                 "supports these methods= $serverMethods, but I support $myMethods");
  1053.         }else{
  1054.             return new PEAR_Error("This server don't support any Auth methods");
  1055.         }
  1056.     }
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.     /**
  1063.     * Return the list of extensions the server supports
  1064.     *
  1065.     * @access public
  1066.     * @return mixed              array  on success, PEAR_Error on failure
  1067.     */
  1068.     function getExtensions()
  1069.     {
  1070.         if (NET_SIEVE_STATE_DISCONNECTED === $this->_state{
  1071.             $msg='Not currently connected';
  1072.             $code=7;
  1073.             return $this->_raiseError($msg,$code);
  1074.             //return PEAR::raiseError('Not currently connected');
  1075.         }
  1076.  
  1077.         return $this->_capability['extensions'];
  1078.     }
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.     /**
  1085.     * Return true if tyhe server has that extension
  1086.     *
  1087.     * @access public
  1088.     * @param string  the extension to compare
  1089.     * @return mixed              array  on success, PEAR_Error on failure
  1090.     */
  1091.     function hasExtension($extension)
  1092.     {
  1093.         if (NET_SIEVE_STATE_DISCONNECTED === $this->_state{
  1094.             $msg='Not currently connected';
  1095.             $code=7;
  1096.             return $this->_raiseError($msg,$code);
  1097.             //return PEAR::raiseError('Not currently connected');
  1098.         }
  1099.  
  1100.         if(is_array($this->_capability['extensions') ){
  1101.             foreach$this->_capability['extensions'as $ext){
  1102.                 iftrimstrtolower$ext ) ) === trimstrtolower$extension ) ) )
  1103.                     return true;
  1104.             }
  1105.         }
  1106.         return false;
  1107.     }
  1108.  
  1109.  
  1110.  
  1111.     /**
  1112.     * Return the list of auth methods the server supports
  1113.     *
  1114.     * @access public
  1115.     * @return mixed              array  on success, PEAR_Error on failure
  1116.     */
  1117.     function getAuthMechs()
  1118.     {
  1119.         if (NET_SIEVE_STATE_DISCONNECTED === $this->_state{
  1120.             $msg='Not currently connected';
  1121.             $code=7;
  1122.             return $this->_raiseError($msg,$code);
  1123.             //return PEAR::raiseError('Not currently connected');
  1124.         }
  1125.         if(!isset($this->_capability['sasl']) ){
  1126.             $this->_capability['sasl']=array();
  1127.         }
  1128.         return $this->_capability['sasl'];
  1129.     }
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135.     /**
  1136.     * Return true if tyhe server has that extension
  1137.     *
  1138.     * @access public
  1139.     * @param string  the extension to compare
  1140.     * @return mixed              array  on success, PEAR_Error on failure
  1141.     */
  1142.     function hasAuthMech($method)
  1143.     {
  1144.         if (NET_SIEVE_STATE_DISCONNECTED === $this->_state{
  1145.             $msg='Not currently connected';
  1146.             $code=7;
  1147.             return $this->_raiseError($msg,$code);
  1148.             //return PEAR::raiseError('Not currently connected');
  1149.         }
  1150.  
  1151.         if(is_array($this->_capability['sasl') ){
  1152.             foreach$this->_capability['sasl'as $ext){
  1153.                 iftrimstrtolower$ext ) ) === trimstrtolower$method ) ) )
  1154.                     return true;
  1155.             }
  1156.         }
  1157.         return false;
  1158.     }
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164. }
  1165. ?>

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