⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpparser.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 5 页
字号:
            scanner->cursor = save_pos;
            done = TRUE;
        }
    }

    if( status == PARSE_OK ) {
        // trim whitespace on right side of value
        while( raw_value->length > 0 ) {
            // get last char
            c = raw_value->buf[raw_value->length - 1];

            if( c != ' ' && c != '\t' &&
                c != TOKCHAR_CR && c != TOKCHAR_LF ) {
                // done; no more whitespace
                break;
            }
            // remove whitespace
            raw_value->length--;
        }
    }

    return status;
}

/************************************************************************
* Function: match_int													
*																		
* Parameters:															
*	INOUT scanner_t* scanner ;  Scanner Object											
*	IN int base :				Base of number in the string; 
*								valid values: 10 or 16	
*	OUT int* value ;			Number stored here									
*																		
* Description: Matches an unsigned integer value in the input. The		
*	integer is returned in 'value'. Except for PARSE_OK result, the		
*	scanner's cursor is moved back to its original position on error.	
*																		
* Returns:																
*   PARSE_OK															
*   PARSE_NO_MATCH		-- got different kind of token					
*   PARSE_FAILURE		-- bad input									
*   PARSE_INCOMPLETE													
************************************************************************/
static XINLINE int
match_int( INOUT scanner_t * scanner,
           IN int base,
           OUT int *value )
{
    memptr token;
    token_type_t tok_type;
    parse_status_t status;
    int num;
    char *end_ptr;
    size_t save_pos;

    save_pos = scanner->cursor;

    status = scanner_get_token( scanner, &token, &tok_type );
    if( status == PARSE_OK ) {
        if( tok_type == TT_IDENTIFIER ) {
            errno = 0;

            num = strtol( token.buf, &end_ptr, base );
            if( ( num < 0 )
                // all and only those chars in token should be used for num
                || ( end_ptr != token.buf + token.length )
                || ( ( num == LONG_MIN || num == LONG_MAX )
                     && ( errno == ERANGE ) )
                 ) {
                status = PARSE_NO_MATCH;
            }

            *value = num;       // save result
        } else {
            status = PARSE_NO_MATCH;    // token must be an identifier
        }
    }

    if( status != PARSE_OK ) {
        // restore scanner position for bad values
        scanner->cursor = save_pos;
    }

    return status;
}

/************************************************************************
* Function: read_until_crlf												
*																		
* Parameters:															
*	INOUT scanner_t* scanner ;	Scanner Object											
*	OUT memptr* str ;			Buffer to copy scanner buffer contents to
*																		
* Description: Reads data until end of line; the crlf at the end of		
*	line is not consumed. On error, scanner is not restored. On			
*	success, 'str' points to a string that runs until eol				
*																		
* Returns:																
*   PARSE_OK															
*   PARSE_FAILURE														
*   PARSE_INCOMPLETE													
************************************************************************/
static XINLINE int
read_until_crlf( INOUT scanner_t * scanner,
                 OUT memptr * str )
{
    memptr token;
    token_type_t tok_type;
    parse_status_t status;
    size_t start_pos;

    start_pos = scanner->cursor;
    str->buf = scanner_get_str( scanner );

    // read until we hit a crlf
    do {
        status = scanner_get_token( scanner, &token, &tok_type );
    } while( status == PARSE_OK && tok_type != TT_CRLF );

    if( status == PARSE_OK ) {
        // pushback crlf in stream
        scanner->cursor -= token.length;

        // str should include all strings except crlf at the end
        str->length = scanner->cursor - start_pos;
    }

    return status;
}

/************************************************************************
* Function: skip_to_end_of_header										
*																		
* Parameters:															
*	INOUT scanner_t* scanner ; Scanner Object
*																		
* Description: Skip to end of header									
*																		
* Returns:																
*   PARSE_OK															
*   PARSE_FAILURE														
*   PARSE_INCOMPLETE													
************************************************************************/
static XINLINE int
skip_to_end_of_header( INOUT scanner_t * scanner )
{
    memptr dummy_raw_value;
    parse_status_t status;

    status = match_raw_value( scanner, &dummy_raw_value );
    return status;
}

/************************************************************************
* Function: match_char													
*																		
* Parameters:															
*	INOUT scanner_t* scanner ;  Scanner Object											
*	IN char c ;					Character to be compared with 															
*	IN xboolean case_sensitive; Flag indicating whether comparison should 
*								be case sensitive
*																		
* Description: Compares a character to the next char in the scanner;	
*	on error, scanner chars are not restored							
*																		
* Returns:																
*   PARSE_OK															
*   PARSE_NO_MATCH														
*   PARSE_INCOMPLETE													
************************************************************************/
static XINLINE parse_status_t
match_char( INOUT scanner_t * scanner,
            IN char c,
            IN xboolean case_sensitive )
{
    char scan_char;

    if( scanner->cursor >= scanner->msg->length ) {
        return PARSE_INCOMPLETE;
    }
    // read next char from scanner
    scan_char = scanner->msg->buf[scanner->cursor++];

    if( case_sensitive ) {
        return c == scan_char ? PARSE_OK : PARSE_NO_MATCH;
    } else {
        return tolower( c ) == tolower( scan_char ) ?
            PARSE_OK : PARSE_NO_MATCH;
    }
}

////////////////////////////////////////////////////////////////////////
// args for ...
//   %d,    int *     (31-bit positive integer)
//   %x,    int *     (31-bit postive number encoded as hex)
//   %s,    memptr*  (simple identifier)
//   %q,    memptr*  (quoted string)
//   %S,    memptr*  (non-whitespace string)
//   %R,    memptr*  (raw value)
//   %U,    uri_type* (url)
//   %L,    memptr*  (string until end of line)
//   %P,    int * (current index of the string being scanned)
//
// no args for
//   ' '    LWS*
//   \t     whitespace
//   "%%"   matches '%'
//   "% "   matches ' '
//   %c     matches CRLF
//   %i     ignore case in literal matching
//   %n     case-sensitive matching in literals
//   %w     optional whitespace; (similar to '\t', 
//                  except whitespace is optional)
//   %0     (zero) match null-terminator char '\0' 
//              (can only be used as last char in fmt)
//              use only in matchstr(), not match()
//   other chars match literally
//
// returns:
//   PARSE_OK
//   PARSE_INCOMPLETE
//   PARSE_FAILURE      -- bad input
//   PARSE_NO_MATCH     -- input does not match pattern

/************************************************************************
*	Function :	vfmatch
*
*	Parameters :
*		INOUT scanner_t* scanner ;  Scanner Object	
*		IN const char* fmt ;		Pattern Format 
*		va_list argp ;				List of variable arguments
*
*	Description :	Extracts variable parameters depending on the passed 
*		in format parameter. Parses data also based on the passed in 
*		format parameter.
*
*	Return : int ;
*		PARSE_OK
*		PARSE_INCOMPLETE
*		PARSE_FAILURE		- bad input
*		PARSE_NO_MATCH		- input does not match pattern
*
*	Note :
************************************************************************/
static int
vfmatch( INOUT scanner_t * scanner,
         IN const char *fmt,
         va_list argp )
{
    char c;
    const char *fmt_ptr = fmt;
    parse_status_t status;
    memptr *str_ptr;
    memptr temp_str;
    int *int_ptr;
    uri_type *uri_ptr;
    size_t save_pos;
    int stat;
    xboolean case_sensitive = TRUE;
    memptr token;
    token_type_t tok_type;
    int base;

    assert( scanner != NULL );
    assert( fmt != NULL );

    // save scanner pos; to aid error recovery
    save_pos = scanner->cursor;

    status = PARSE_OK;
    while( ( ( c = *fmt_ptr++ ) != 0 ) && ( status == PARSE_OK )
         ) {
        if( c == '%' ) {
            c = *fmt_ptr++;

            switch ( c ) {

                case 'R':      // raw value
                    str_ptr = va_arg( argp, memptr * );
                    assert( str_ptr != NULL );
                    status = match_raw_value( scanner, str_ptr );
                    break;

                case 's':      // simple identifier
                    str_ptr = va_arg( argp, memptr * );
                    assert( str_ptr != NULL );
                    status = scanner_get_token( scanner, str_ptr,
                                                &tok_type );
                    if( status == PARSE_OK && tok_type != TT_IDENTIFIER ) {
                        // not an identifier
                        status = PARSE_NO_MATCH;
                    }
                    break;

                case 'c':      // crlf
                    status = scanner_get_token( scanner,
                                                &token, &tok_type );
                    if( status == PARSE_OK && tok_type != TT_CRLF ) {
                        // not CRLF token
                        status = PARSE_NO_MATCH;
                    }
                    break;

                case 'd':      // integer
                case 'x':      // hex number
                    int_ptr = va_arg( argp, int * );

                    assert( int_ptr != NULL );
                    base = ( c == 'd' ? 10 : 16 );
                    status = match_int( scanner, base, int_ptr );
                    break;

                case 'S':      // non-whitespace string
                case 'U':      // uri
                    if( c == 'S' ) {
                        str_ptr = va_arg( argp, memptr * );
                    } else {
                        str_ptr = &temp_str;
                    }
                    assert( str_ptr != NULL );
                    status = match_non_ws_string( scanner, str_ptr );
                    if( c == 'U' && status == PARSE_OK ) {
                        uri_ptr = va_arg( argp, uri_type * );
                        assert( uri_ptr != NULL );
                        stat = parse_uri( str_ptr->buf, str_ptr->length,
                                          uri_ptr );
                        if( stat != HTTP_SUCCESS ) {
                            status = PARSE_NO_MATCH;
                        }
                    }
                    break;

                case 'L':      // string till eol
                    str_ptr = va_arg( argp, memptr * );
                    assert( str_ptr != NULL );
                    status = read_until_crlf( scanner, str_ptr );
                    break;

                case ' ':      // match space
                case '%':      // match percentage symbol
                    status = match_char( scanner, c, case_sensitive );
                    break;

                case 'n':      // case-sensitive match
                    case_sensitive = TRUE;
                    break;

                case 'i':      // ignore case
                    case_sensitive = FALSE;
                    break;

                case 'q':      // quoted string
                    str_ptr = ( memptr * ) va_arg( argp, memptr * );
                    status =
                        scanner_get_token( scanner, str_ptr, &tok_type );
                    if( status == PARSE_OK && tok_type != TT_QUOTEDSTRING ) {
                        status = PARSE_NO_MATCH;    // not a quoted string
                    }
                    break;

                case 'w':      // optional whitespace
                    status = scanner_get_token( scanner,
                                                &token, &tok_type );
                    if( status == PARSE_OK && tok_type != TT_WHITESPACE ) {
                        // restore non-whitespace token
                        scanner->cursor -= token.length;
                    }
                    break;

                case 'P':      // current pos of scanner
                    int_ptr = va_arg( argp, int * );

                    assert( int_ptr != NULL );
                    *int_ptr = scanner->cursor;
                    break;

                    // valid only in matchstr()
                case '0':      // end of msg?
                    // check that we are 1 beyond last char
                    if( scanner->cursor == scanner->msg->length &&
                        scanner->msg->buf[scanner->cursor] == '\0' ) {
                        status = PARSE_OK;
                    } else {
                        status = PARSE_NO_MATCH;
                    }
                    break;

                default:
                    assert( 0 );    // unknown option
            }
        } else {
            switch ( c ) {
                case ' ':      // LWS*
                    status = skip_lws( scanner );
                    break;

                case '\t':     // Whitespace
                    status = scanner_get_token( scanner,
                                                &token, &tok_type );
                    if( status == PARSE_OK && tok_type != TT_WHITESPACE ) {
                        // not whitespace token
                        status = PARSE_NO_MATCH;
                    }
                    break;

                default:       // match characters
                    {
                        status = match_char( scanner, c, case_sensitive );
                    }
            }
        }
    }

⌨️ 快捷键说明

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