sieve.php

来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· PHP 代码 · 共 1,165 行 · 第 1/3 页

PHP
1,165
字号
    function haveSpace($scriptname,$quota)
    {
        if (NET_SIEVE_STATE_TRANSACTION != $this->_state) {
            $msg='Not currently in TRANSACTION state';
            $code=1;
            return $this->_raiseError($msg,$code);
        }

        if (PEAR::isError($res = $this->_doCmd(sprintf('HAVESPACE "%s" %s', $scriptname, $quota) ) ) ) {
        //if (PEAR::isError($res = $this->_doCmd(sprintf('HAVESPACE %d "%s"',  $quota,$scriptname ) ) ) ) {
            return $res;
        }

        return true;
    }




    /**
    * Parses the response from the capability command. Storesq
    * the result in $this->_capability
    *
    * @access private
    */
    function _parseCapability($data)
    {
        $data = preg_split('/\r?\n/', $data, -1, PREG_SPLIT_NO_EMPTY);

        for ($i = 0; $i < count($data); $i++) {
            if (preg_match('/^"([a-z]+)" ("(.*)")?$/i', $data[$i], $matches)) {
                switch (strtolower($matches[1])) {
                    case 'implementation':
                        $this->_capability['implementation'] = $matches[3];
                        break;

                    case 'sasl':
                        $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]);
                        break;

                    case 'sieve':
                        $this->_capability['extensions'] = preg_split('/\s+/', $matches[3]);
                        break;

                    case 'starttls':
                        $this->_capability['starttls'] = true;
                }
            }
        }
    }

    /**
    * Sends a command to the server
    *
    * @access private
    * @param string $cmd The command to send
    */
    function _sendCmd($cmd)
    {
        $status = $this->_sock->getStatus();
        if (PEAR::isError($status) || $status['eof']) {
            return new PEAR_Error( 'Failed to write to socket: (connection lost!) ' );
        }
        if ( PEAR::isError( $error = $this->_sock->write( $cmd . "\r\n" ) ) ) {
            return new PEAR_Error( 'Failed to write to socket: ' . $error->getMessage() );
        }

        if( $this->_debug ){
            // C: means this data was sent by  the client (this class)
            echo "C:$cmd\n";
        }
        return true;


    }



    /**
    * Sends a string response to the server
    *
    * @access private
    * @param string $cmd The command to send
    */
    function _sendStringResponse($str)
    {
        $response='{' .  strlen($str) . "+}\r\n" . $str  ;
        return $this->_sendCmd($response);
    }




    function _recvLn()
    {
        $lastline='';
        if (PEAR::isError( $lastline = $this->_sock->gets( 8192 ) ) ) {
            return new PEAR_Error('Failed to write to socket: ' . $lastline->getMessage() );
        }
        $lastline=rtrim($lastline);
        if($this->_debug){
            // S: means this data was sent by  the IMAP Server
            echo "S:$lastline\n" ;
        }

/*        if( $lastline === '' ){
            return new PEAR_Error('Failed to receive from the  socket: '  );
        }
*/
        return $lastline;
    }





    /**
    * Send a command and retrieves a response from the server.
    *
    *
    * @access private
    * @param string $cmd The command to send
    * @return mixed Reponse string if an OK response, PEAR_Error if a NO response
    */
    function _doCmd($cmd = '' )
    {

        $referralCount=0;
        while($referralCount < $this->_maxReferralCount ){


            if($cmd != '' ){
                if(PEAR::isError($error = $this->_sendCmd($cmd) )) {
                    return $error;
                }
            }
            $response = '';

            while (true) {
                    if(PEAR::isError( $line=$this->_recvLn() )){
                        return $line;
                    }
                    if ('ok' === strtolower(substr($line, 0, 2))) {
                        $response .= $line;
                        return rtrim($response);

                    } elseif ('no' === strtolower(substr($line, 0, 2))) {
                        // Check for string literal error message
                        if (preg_match('/^no {([0-9]+)\+?}/i', $line, $matches)) {
                            $line .= str_replace("\r\n", ' ', $this->_sock->read($matches[1] + 2 ));
                            if($this->_debug){
                                echo "S:$line\n";
                            }
                        }
                        $msg=trim($response . substr($line, 2));
                        $code=3;
                        return $this->_raiseError($msg,$code);
                        //return PEAR::raiseError(trim($response . substr($line, 2)));
                    } elseif ('bye' === strtolower(substr($line, 0, 3))) {

                        if(PEAR::isError($error = $this->disconnect(false) ) ){
                            $msg="Can't handle bye, The error was= " . $error->getMessage() ;
                            $code=4;
                            return $this->_raiseError($msg,$code);
                            //return PEAR::raiseError("Can't handle bye, The error was= " . $error->getMessage() );
                        }
                        //if (preg_match('/^bye \(referral "([^"]+)/i', $line, $matches)) {
                        if (preg_match('/^bye \(referral "(sieve:\/\/)?([^"]+)/i', $line, $matches)) {
                            // Check for referral, then follow it.  Otherwise, carp an error.
                            //$this->_data['host'] = $matches[1];
                            $this->_data['host'] = $matches[2];
                            if (PEAR::isError($error = $this->_handleConnectAndLogin() ) ){
                                $msg="Can't follow referral to " . $this->_data['host'] . ", The error was= " . $error->getMessage() ;
                                $code=5;
                                return $this->_raiseError($msg,$code);
                                //return PEAR::raiseError("Can't follow referral to " . $this->_data['host'] . ", The error was= " . $error->getMessage() );
                            }
                            break;
                            // Retry the command
                            if(PEAR::isError($error = $this->_sendCmd($cmd) )) {
                                return $error;
                            }
                            continue;
                        }
                        $msg=trim($response . $line);
                        $code=6;
                        return $this->_raiseError($msg,$code);
                        //return PEAR::raiseError(trim($response . $line));
                    } elseif (preg_match('/^{([0-9]+)\+?}/i', $line, $matches)) {
                        // Matches String Responses.
                        //$line = str_replace("\r\n", ' ', $this->_sock->read($matches[1] + 2 ));
                        $line = $this->_sock->read($matches[1] + 2 );
                        if($this->_debug){
                            echo "S:$line\n";
                        }
                        return $line;
                    }
                    $response .= $line . "\r\n";
                    $referralCount++;
                }
        }
        $msg="Max referral count reached ($referralCount times) Cyrus murder loop error?";
        $code=7;
        return $this->_raiseError($msg,$code);
        //return PEAR::raiseError("Max referral count reached ($referralCount times) Cyrus murder loop error?" );
    }




    /**
    * Sets the bebug state
    *
    * @access public
    * @return void
    */
    function setDebug($debug=true)
    {
        $this->_debug=$debug;
    }

    /**
    * Disconnect from the Sieve server
    *
    * @access public
    * @param  string $scriptname The name of the script to be set as active
    * @return mixed              true on success, PEAR_Error on failure
    */
    function disconnect($sendLogoutCMD=true)
    {
        return $this->_cmdLogout($sendLogoutCMD);
    }


    /**
     * Returns the name of the best authentication method that the server
     * has advertised.
     *
     * @param string if !=null,authenticate with this method ($userMethod).
     *
     * @return mixed    Returns a string containing the name of the best
     *                  supported authentication method or a PEAR_Error object
     *                  if a failure condition is encountered.
     * @access private
     * @since  1.0
     */
    function _getBestAuthMethod($userMethod = null)
    {

       if( isset($this->_capability['sasl']) ){
           $serverMethods=$this->_capability['sasl'];
       }else{
           // if the server don't send an sasl capability fallback to login auth
           //return 'LOGIN';
           return new PEAR_Error("This server don't support any Auth methods SASL problem?");
       }

        if($userMethod != null ){
            $methods = array();
            $methods[] = $userMethod;
        }else{

            $methods = $this->supportedAuthMethods;
        }
        if( ($methods != null) && ($serverMethods != null)){
            foreach ( $methods as $method ) {
                if ( in_array( $method , $serverMethods ) ) {
                    return $method;
                }
            }
            $serverMethods=implode(',' , $serverMethods );
            $myMethods=implode(',' ,$this->supportedAuthMethods);
            return new PEAR_Error("$method NOT supported authentication method!. This server " .
                "supports these methods= $serverMethods, but I support $myMethods");
        }else{
            return new PEAR_Error("This server don't support any Auth methods");
        }
    }





    /**
    * Return the list of extensions the server supports
    *
    * @access public
    * @return mixed              array  on success, PEAR_Error on failure
    */
    function getExtensions()
    {
        if (NET_SIEVE_STATE_DISCONNECTED === $this->_state) {
            $msg='Not currently connected';
            $code=7;
            return $this->_raiseError($msg,$code);
            //return PEAR::raiseError('Not currently connected');
        }

        return $this->_capability['extensions'];
    }





    /**
    * Return true if tyhe server has that extension
    *
    * @access public
    * @param string  the extension to compare
    * @return mixed              array  on success, PEAR_Error on failure
    */
    function hasExtension($extension)
    {
        if (NET_SIEVE_STATE_DISCONNECTED === $this->_state) {
            $msg='Not currently connected';
            $code=7;
            return $this->_raiseError($msg,$code);
            //return PEAR::raiseError('Not currently connected');
        }

        if(is_array($this->_capability['extensions'] ) ){
            foreach( $this->_capability['extensions'] as $ext){
                if( trim( strtolower( $ext ) ) === trim( strtolower( $extension ) ) )
                    return true;
            }
        }
        return false;
    }



    /**
    * Return the list of auth methods the server supports
    *
    * @access public
    * @return mixed              array  on success, PEAR_Error on failure
    */
    function getAuthMechs()
    {
        if (NET_SIEVE_STATE_DISCONNECTED === $this->_state) {
            $msg='Not currently connected';
            $code=7;
            return $this->_raiseError($msg,$code);
            //return PEAR::raiseError('Not currently connected');
        }
        if(!isset($this->_capability['sasl']) ){
            $this->_capability['sasl']=array();
        }
        return $this->_capability['sasl'];
    }





    /**
    * Return true if tyhe server has that extension
    *
    * @access public
    * @param string  the extension to compare
    * @return mixed              array  on success, PEAR_Error on failure
    */
    function hasAuthMech($method)
    {
        if (NET_SIEVE_STATE_DISCONNECTED === $this->_state) {
            $msg='Not currently connected';
            $code=7;
            return $this->_raiseError($msg,$code);
            //return PEAR::raiseError('Not currently connected');
        }

        if(is_array($this->_capability['sasl'] ) ){
            foreach( $this->_capability['sasl'] as $ext){
                if( trim( strtolower( $ext ) ) === trim( strtolower( $method ) ) )
                    return true;
            }
        }
        return false;
    }





}
?>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?