imapprotocol.php

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

PHP
2,423
字号

            $this->_parseSpace($str , __LINE__ , __FILE__ );
            while($str[0] != ')' && $str!=''){
                $params_arr[] = $this->_arrayfy_content($str);
            }

            return $params_arr;
    }






    /**
    * Makes the content an Array
    *
    * @param string the IMAP's server response
    *
    * @return Array containing  the parsed  response
    * @access private
    * @since  1.0
    */
    function _arrayfy_content(&$str)
    {
        $params_arr=array();
        $this->_getNextToken($str,$params);
        if($params != '(' ){
            return $params;
        }
        $this->_getNextToken($str,$params,false,false);
        while ( $str != '' && $params != ')'){
                if($params != '' ){
                    if($params[0] == '(' ){
                        $params=$this->_arrayfy_content( $params );
                    }
                    if($params != ' ' ){
                        //I don't remove the colons (") to handle the case of retriving " "
                        // If I remove the colons the parser will interpret this field as an imap separator (space)
                        // instead of a valid field so I remove the colons here
                        if($params=='""'){
                            $params='';
                        }else{
                            if($params[0]=='"'){
                                $params=substr($params,1,strlen($params)-2);
                            }
                        }
                        $params_arr[]=$params;
                    }
                }else{
                    //if params if empty (for example i'm parsing 2 quotes ("")
                    // I'll append an array entry to mantain compatibility
                    $params_arr[]=$params;
                }
                $this->_getNextToken($str,$params,false,false);
        }
        return $params_arr;
    }




    /**
    * Parses the BODY[],BODY[TEXT],.... responses
    *
    * @param string the IMAP's server response
    *
    * @return Array containing  the parsed  response
    * @access private
    * @since  1.0
    */
    function _parseContentresponse(&$str, $command)
    {
        $content = '';
        $this->_parseSpace($str , __LINE__ , __FILE__ );
        $size  =$this->_getNextToken($str,$content);
        return array( "CONTENT"=> $content , "CONTENT_SIZE" =>$size );
    }








    /**
    * Parses the ENVELOPE response
    *
    * @param string the IMAP's server response
    *
    * @return Array containing  the parsed  response
    * @access private
    * @since  1.0
    */
    function _parseENVELOPEresponse(&$str)
    {
        $content = '';
        $this->_parseSpace($str , __LINE__ , __FILE__ );

        $this->_getNextToken($str,$parenthesis);
        if( $parenthesis != '(' ){
                $this->_prot_error("must be a '(' but is a '$parenthesis' !!!!" , __LINE__ , __FILE__ );
        }
        // Get the email's Date
        $this->_getNextToken($str,$date);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        // Get the email's Subject:
        $this->_getNextToken($str,$subject);
        //$subject=$this->decode($subject);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        //FROM LIST;
        $from_arr = $this->_getAddressList($str);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        //"SENDER LIST\n";
        $sender_arr = $this->_getAddressList($str);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        //"REPLY-TO LIST\n";
        $reply_to_arr=$this->_getAddressList($str);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        //"TO LIST\n";
        $to_arr = $this->_getAddressList($str);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        //"CC LIST\n";
        $cc_arr = $this->_getAddressList($str);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        //"BCC LIST|$str|\n";
        $bcc_arr = $this->_getAddressList($str);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        $this->_getNextToken($str,$in_reply_to);

        $this->_parseSpace($str , __LINE__ , __FILE__ );

        $this->_getNextToken($str,$message_id);

        $this->_getNextToken($str,$parenthesis);

        if( $parenthesis != ')' ){
            $this->_prot_error("must be a ')' but is a '$parenthesis' !!!!" , __LINE__ , __FILE__ );
        }

        return array( "DATE"=> $date , "SUBJECT" => $subject,"FROM" => $from_arr,
            "SENDER" => $sender_arr , "REPLY_TO" => $reply_to_arr, "TO" => $to_arr,
            "CC" =>$cc_arr, "BCC"=> $bcc_arr, "IN_REPLY_TO" =>$in_reply_to, "MESSAGE_ID"=>$message_id  );
    }





    /**
    * Parses the ARRDLIST as defined in RFC
    *
    * @param string the IMAP's server response
    *
    * @return Array containing  the parsed  response
    * @access private
    * @since  1.0
    */
    function _getAddressList(&$str)
    {
        $params_arr = $this->_arrayfy_content($str);
        if( !isset( $params_arr ) ){
            return $params_arr;
        }


        if( is_array($params_arr) ){
            $personal_name  = $params_arr[0][0];
            $at_domain_list = $params_arr[0][1];
            $mailbox_name   = $params_arr[0][2];
            $host_name      = $params_arr[0][3];
            if( $mailbox_name!='' && $host_name!='' ){
                $email=$mailbox_name . "@" . $host_name;
            }else{
                $email=false;
            }
            if($email==false){
                $rfc822_email=false;
            }else{
                if(!isset($personal_name)){
                    $rfc822_email= "<". $email . ">";
                }else{
                    $rfc822_email= "\"". $personal_name ."\" <". $email . ">";
                }
            }
            $email_arr[] = array ( "PERSONAL_NAME"=> $personal_name , "AT_DOMAIN_LIST"=>$at_domain_list ,
                                   "MAILBOX_NAME"=> $this->utf_7_decode($mailbox_name), "HOST_NAME"=> $host_name,
                                   "EMAIL"=>$email , "RFC822_EMAIL" => $rfc822_email );
            return $email_arr;
        }

        return array();
    }







    /**
    * Utility funcion to find the closing parenthesis ")" Position it takes care of quoted ones
    *
    * @param string the IMAP's server response
    *
    * @return int containing  the pos of the closing parenthesis ")"
    * @access private
    * @since  1.0
    */
    function _getClosingBracesPos($str_line, $startDelim ='(', $stopDelim = ')' )
    {
        $len = strlen( $str_line );
        $pos = 0;
        // ignore all extra characters
        // If inside of a string, skip string -- Boundary IDs and other
        // things can have ) in them.
        if ( $str_line[$pos] != $startDelim ) {
            $this->_prot_error("_getClosingParenthesisPos: must start with a '(' but is a '". $str_line[$pos] ."'!!!!\n" .
                "STR_LINE:$str_line|size:$len|POS: $pos\n" , __LINE__ , __FILE__ );
            return( $len );
        }
        for( $pos = 1 ; $pos < $len ; $pos++ ){
            if ($str_line[$pos] == $stopDelim ) {
                break;
            }
            if ($str_line[$pos] == '"') {
                $pos++;
                while ( $str_line[$pos] != '"' && $pos < $len ) {
                    if ($str_line[$pos] == "\\" && $str_line[$pos + 1 ] == '"' )
                        $pos++;
                    if ($str_line[$pos] == "\\" && $str_line[$pos + 1 ] == "\\" )
                        $pos++;
                    $pos++;
                }
            }
            if ( $str_line[$pos] == $startDelim ) {
                $str_line_aux = substr( $str_line , $pos );
                $pos_aux = $this->_getClosingBracesPos( $str_line_aux );
                $pos+=$pos_aux;
            }
        }
        if( $str_line[$pos] != $stopDelim ){
            $this->_prot_error("_getClosingBracesPos: must be a $stopDelim but is a '". $str_line[$pos] ."'|POS:$pos|STR_LINE:$str_line!!!!" , __LINE__ , __FILE__ );
        }

        if( $pos >= $len )
            return false;
        return $pos;
    }






    /**
    * Utility funcion to get from here to the end of the line
    *
    * @param string the IMAP's server response
    *
    * @return string containing  the string to the end of the line
    * @access private
    * @since  1.0
    */

    function _getToEOL(&$str , $including = true)
    {
        $len = strlen( $str );
        if( $including ){
            for($i=0;$i<$len;$i++){
                if( $str[$i] =="\n" )
                    break;
            }
            $content=substr($str,0,$i + 1);
            $str=substr($str,$i + 1);
            return $content;

        }else{
            for( $i = 0 ; $i < $len ; $i++ ){
                if( $str[$i] =="\n" || $str[$i] == "\r")
                    break;
            }
            $content = substr( $str ,0 , $i );
            $str = substr( $str , $i );
            return $content;
        }
    }




    /**
    * Fetches the next IMAP token or parenthesis
    *
    * @param string the IMAP's server response
    * @param string the next token
    * @param boolean true: the parenthesis IS a token, false: I consider
    *        all the response in parenthesis as a token
    *
    * @return int containing  the content size
    * @access private
    * @since  1.0
    */


    function _getNextToken(&$str, &$content, $parenthesisIsToken=true,$colonIsToken=true){
        $len = strlen($str);
        $pos = 0;
        $content_size = false;
        $content = false;
        if($str == '' || $len < 2 ){
            $content=$str;
            return $len;
        }
        switch( $str[0] ){
        case '{':
            if( ($posClosingBraces = $this->_getClosingBracesPos($str, '{' , '}' )) == false ){
                $this->_prot_error("_getClosingBracesPos() error!!!" , __LINE__ , __FILE__ );
            }
            if(! is_numeric( ( $strBytes = substr( $str , 1 , $posClosingBraces - 1) ) ) ){
                $this->_prot_error("must be a number but is a '" . $strBytes ."'!!!!" , __LINE__ , __FILE__ );
            }
            if( $str[$posClosingBraces] != '}' ){
                $this->_prot_error("must be a '}'  but is a '" . $str[$posClosingBraces] ."'!!!!" , __LINE__ , __FILE__ );
            }
            if( $str[$posClosingBraces + 1] != "\r" ){
                $this->_prot_error("must be a '\\r'  but is a '" . $str[$posClosingBraces + 1] ."'!!!!" , __LINE__ , __FILE__ );
            }
            if( $str[$posClosingBraces + 2] != "\n" ){
                $this->_prot_error("must be a '\\n'  but is a '" . $str[$posClosingBraces + 2] ."'!!!!" , __LINE__ , __FILE__ );
            }
            $content = substr( $str , $posClosingBraces + 3 , $strBytes );
            if( strlen( $content ) != $strBytes ){
                $this->_prot_error("content size is ". strlen($content) . " but the string reports a size of $strBytes!!!\n" , __LINE__ , __FILE__ );
            }
            $content_size = $strBytes;
            //Advance the string
            $str = substr( $str , $posClosingBraces + $strBytes + 3 );
            break;
        case '"':
            if($colonIsToken){
                for($pos=1;$pos<$len;$pos++){
                    if ( $str[$pos] == "\"" ) {
                        break;
                    }
                    if ($str[$pos] == "\\" && $str[$pos + 1 ] == "\"" )
                        $pos++;
                    if ($str[$pos] == "\\" && $str[$pos + 1 ] == "\\" )
                        $pos++;
                }
                if($str[$pos] != '"' ){
                    $this->_prot_error("must be a '\"'  but is a '" . $str[$pos] ."'!!!!" , __LINE__ , __FILE__ );
                }
                $content_size = $pos;
                $content = substr( $str , 1 , $pos - 1 );
                //Advance the string
                $str = substr( $str , $pos + 1 );
            }else{
                for($pos=1;$pos<$len;$pos++){
                    if ( $str[$pos] == "\"" ) {
                        break;
                    }
                    if ($str[$pos] == "\\" && $str[$pos + 1 ] == "\"" )
                        $pos++;
                    if ($str[$pos] == "\\" && $str[$pos + 1 ] == "\\" )
                        $pos++;
                }
                if($str[$pos] != '"' ){
                    $this->_prot_error("must be a '\"'  but is a '" . $str[$pos] ."'!!!!" , __LINE__ , __FILE__ );
                }
                $content_size = $pos;
                $content = substr( $str , 0 , $pos + 1 );
                //Advance the string
                $str = substr( $str , $pos + 1 );

            }
            break;

        case "\r":
            $pos = 1;
            if( $str[1] == "\n")
                $pos++;
            $content_size = $pos;
            $content = substr( $str , 0 , $pos );
            $str = substr( $str , $pos );
            break;
        case "\n":
            $pos = 1;
            $content_size = $pos;
            $content = substr( $str , 0 , $pos );
            $str = substr( $str , $pos );
            break;
        case '(':
            if( $parenthesisIsToken == false ){
                $pos = $this->_getClosingBracesPos( $str );
                $content_size = $pos + 1;
                $content = substr( $str , 0 , $pos + 1 );
                $str = substr( $str , $pos + 1 );
            }else{
                $pos = 1;
                $content_size = $pos;
                $content = substr( $str , 0 , $pos );
                $str = substr( $str , $pos );
            }
            break;
        case ')':
            $pos = 1;
            $content_size = $pos;
            $content = substr( $str , 0 , $pos );
            $str = substr( $str , $pos );
            break;
        case ' ':
            $pos = 1;
            $content_size = $pos;
            $content = substr( $str , 0 , $pos );
            $str = substr( $str , $pos );
            break;
        default:
            for( $pos = 0 ; $pos < $len ; $pos++ ){
                if ( $str[$pos] == ' ' || $str[$pos] == "\r" || $str[$pos] == ')' || $str[$pos] == '(' || $str[$pos] == "\n" ) {
                    break;
                }
                if ( $str[$pos] == "\\" && $str[$pos + 1 ] == ' '  )
                    $pos++;
                if ( $str[$pos] == "\\" && $str[$pos + 1 ] == "\\" )
                    $pos++;
            }
            //Advance the string
            if( $pos == 0 ){
                $content_size = 1;
                $content = substr( $str , 0 , 1 );
                $str = substr( $str , 1 );
            }else{
                $content_size = $pos;
                $content = substr( $str , 0 , $pos );
                if($pos < $len){
                    $str = substr( $str , $pos  );
                }else{
                //if this is the end of the string... exit the switch
                    break;
                }


            }
            break;
        }
        return $content_size;
    }






    /**
    * Utility funcion to display to console the protocol errors
    *
    * @param string the error
    * @param int the line producing the error
    * @param string file where the error was produced
    *
    * @return string containing  the error
    * @access private
    * @since  1.0
    */
    function _prot_error($str , $line , $file,$printError=t

⌨️ 快捷键说明

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