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

📄 httpparser.c

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

    if( status != PARSE_OK ) {
        // on error, restore original scanner pos
        scanner->cursor = save_pos;
    }

    return status;
}

/************************************************************************
* Function: match														
*																		
* Parameters:															
*	INOUT scanner_t* scanner ; Scanner Object											
*	IN const char* fmt;			Pattern format													
*	...																	
*																		
* Description: matches a variable parameter list and takes necessary	
*	actions based on the data type specified.							
*																		
* Returns:																
*   PARSE_OK															
*   PARSE_NO_MATCH														
*   PARSE_INCOMPLETE													
************************************************************************/
static int
match( INOUT scanner_t * scanner,
       IN const char *fmt,
       ... )
{
    int ret_code;
    va_list args;

    va_start( args, fmt );
    ret_code = vfmatch( scanner, fmt, args );
    va_end( args );

    return ret_code;
}

/************************************************************************
* Function: matchstr													
*																		
* Parameters:															
*	IN char *str ;		 String to be matched														
*	IN size_t slen ;     Length of the string														
*	IN const char* fmt ; Pattern format												
*	...																	
*																		
* Description: Matches a variable parameter list with a string			
*	and takes actions based on the data type specified.					
*																		
* Returns:																
*   PARSE_OK															
*   PARSE_NO_MATCH -- failure to match pattern 'fmt'					
*   PARSE_FAILURE	-- 'str' is bad input							
************************************************************************/
int
matchstr( IN char *str,
          IN size_t slen,
          IN const char *fmt,
          ... )
{
    int ret_code;
    char save_char;
    scanner_t scanner;
    membuffer buf;
    va_list arg_list;

    // null terminate str
    save_char = str[slen];
    str[slen] = '\0';

    membuffer_init( &buf );

    // under no circumstances should this buffer be modifed because its memory
    //  might have not come from malloc()
    membuffer_attach( &buf, str, slen );

    scanner_init( &scanner, &buf );
    scanner.entire_msg_loaded = TRUE;

    va_start( arg_list, fmt );
    ret_code = vfmatch( &scanner, fmt, arg_list );
    va_end( arg_list );

    // restore str
    str[slen] = save_char;

    // don't destroy buf

    return ret_code;
}

/************************************************************************
* Function: parser_init													
*																		
* Parameters:															
*	OUT http_parser_t* parser ; HTTP Parser object
*																		
* Description: Initializes the parser object.							
*																		
* Returns:																
*	void																
************************************************************************/
static XINLINE void
parser_init( OUT http_parser_t * parser )
{
    memset( parser, 0, sizeof( http_parser_t ) );

    parser->http_error_code = HTTP_BAD_REQUEST; // err msg by default
    parser->ent_position = ENTREAD_DETERMINE_READ_METHOD;
    parser->valid_ssdp_notify_hack = FALSE;

    httpmsg_init( &parser->msg );
    scanner_init( &parser->scanner, &parser->msg.msg );
}

/************************************************************************
* Function: parser_parse_requestline									
*																		
* Parameters:															
*	INOUT http_parser_t* parser ; HTTP Parser  object						
*																		
* Description: Get HTTP Method, URL location and version information.	
*																		
* Returns:																
*	PARSE_OK															
*	PARSE_SUCCESS														
*	PARSE_FAILURE														
************************************************************************/
static parse_status_t
parser_parse_requestline( INOUT http_parser_t * parser )
{
    parse_status_t status;
    http_message_t *hmsg = &parser->msg;
    memptr method_str;
    memptr version_str;
    int index;
    char save_char;
    int num_scanned;
    memptr url_str;

    assert( parser->position == POS_REQUEST_LINE );

    status = skip_blank_lines( &parser->scanner );
    if( status != PARSE_OK ) {
        return status;
    }
    //simple get http 0.9 as described in http 1.0 spec

    status =
        match( &parser->scanner, "%s\t%S%w%c", &method_str, &url_str );

    if( status == PARSE_OK ) {

        index =
            map_str_to_int( method_str.buf, method_str.length,
                            Http_Method_Table, NUM_HTTP_METHODS, TRUE );

        if( index < 0 ) {
            // error; method not found
            parser->http_error_code = HTTP_NOT_IMPLEMENTED;
            return PARSE_FAILURE;
        }

        if( Http_Method_Table[index].id != HTTPMETHOD_GET ) {
            parser->http_error_code = HTTP_BAD_REQUEST;
            return PARSE_FAILURE;
        }

        hmsg->method = HTTPMETHOD_SIMPLEGET;

        // store url
        hmsg->urlbuf = str_alloc( url_str.buf, url_str.length );
        if( hmsg->urlbuf == NULL ) {
            // out of mem
            parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
            return PARSE_FAILURE;
        }
        if( parse_uri( hmsg->urlbuf, url_str.length, &hmsg->uri ) !=
            HTTP_SUCCESS ) {
            return PARSE_FAILURE;
        }

        parser->position = POS_COMPLETE;    // move to headers

        return PARSE_SUCCESS;
    }

    status = match( &parser->scanner,
                    "%s\t%S\t%ihttp%w/%w%L%c", &method_str, &url_str,
                    &version_str );
    if( status != PARSE_OK ) {
        return status;
    }
    // store url
    hmsg->urlbuf = str_alloc( url_str.buf, url_str.length );
    if( hmsg->urlbuf == NULL ) {
        // out of mem
        parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
        return PARSE_FAILURE;
    }
    if( parse_uri( hmsg->urlbuf, url_str.length, &hmsg->uri ) !=
        HTTP_SUCCESS ) {
        return PARSE_FAILURE;
    }
    // scan version
    save_char = version_str.buf[version_str.length];
    version_str.buf[version_str.length] = '\0'; // null-terminate
    num_scanned = sscanf( version_str.buf, "%d . %d",
                          &hmsg->major_version, &hmsg->minor_version );
    version_str.buf[version_str.length] = save_char;    // restore
    if( num_scanned != 2 ||
        hmsg->major_version < 0 || hmsg->minor_version < 0 ) {
        // error; bad http version
        return PARSE_FAILURE;
    }

    index =
        map_str_to_int( method_str.buf, method_str.length,
                        Http_Method_Table, NUM_HTTP_METHODS, TRUE );
    if( index < 0 ) {
        // error; method not found
        parser->http_error_code = HTTP_NOT_IMPLEMENTED;
        return PARSE_FAILURE;
    }

    hmsg->method = Http_Method_Table[index].id;
    parser->position = POS_HEADERS; // move to headers

    return PARSE_OK;
}

/************************************************************************
* Function: parser_parse_responseline									
*																		
* Parameters:															
*	INOUT http_parser_t* parser	; HTTP Parser object					
*																		
* Description: Get HTTP Method, URL location and version information.	
*																		
* Returns:																
*	PARSE_OK															
*	PARSE_SUCCESS														
*	PARSE_FAILURE														
************************************************************************/
parse_status_t
parser_parse_responseline( INOUT http_parser_t * parser )
{
    parse_status_t status;
    http_message_t *hmsg = &parser->msg;
    memptr line;
    char save_char;
    int num_scanned;
    int i;
    char *p;

    assert( parser->position == POS_RESPONSE_LINE );

    status = skip_blank_lines( &parser->scanner );
    if( status != PARSE_OK ) {
        return status;
    }
    // response line
    //status = match( &parser->scanner, "%ihttp%w/%w%d\t.\t%d\t%d\t%L%c",
    //  &hmsg->major_version, &hmsg->minor_version,
    //  &hmsg->status_code, &hmsg->status_msg );

    status = match( &parser->scanner, "%ihttp%w/%w%L%c", &line );
    if( status != PARSE_OK ) {
        return status;
    }

    save_char = line.buf[line.length];
    line.buf[line.length] = '\0';   // null-terminate

    // scan http version and ret code
    num_scanned = sscanf( line.buf, "%d . %d %d",
                          &hmsg->major_version, &hmsg->minor_version,
                          &hmsg->status_code );

    line.buf[line.length] = save_char;  // restore

    if( num_scanned != 3 ||
        hmsg->major_version < 0 ||
        hmsg->minor_version < 0 || hmsg->status_code < 0 ) {
        // bad response line
        return PARSE_FAILURE;
    }
    //
    // point to status msg
    //

    p = line.buf;

    // skip 3 ints
    for( i = 0; i < 3; i++ ) {
        // go to start of num
        while( !isdigit( *p ) ) {
            p++;
        }

        // skip int
        while( isdigit( *p ) ) {
            p++;
        }
    }

    // whitespace must exist after status code
    if( *p != ' ' && *p != '\t' ) {
        return PARSE_FAILURE;
    }
    // skip whitespace
    while( *p == ' ' || *p == '\t' ) {
        p++;
    }

    // now, p is at start of status msg
    if( membuffer_assign( &hmsg->status_msg, p,
                          line.length - ( p - line.buf ) ) != 0 ) {
        // out of mem
        parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
        return PARSE_FAILURE;
    }

    parser->position = POS_HEADERS; // move to headers

    return PARSE_OK;
}

/************************************************************************
* Function: parser_parse_headers									
*																		
* Parameters:															
*	INOUT http_parser_t* parser	; HTTP Parser object										
*													
* Description: Get HTTP Method, URL location and version information.	
*																		
* Returns:																
*	PARSE_OK															
*	PARSE_SUCCESS														
*	PARSE_FAILURE														
************************************************************************/
parse_status_t
parser_parse_headers( INOUT http_parser_t * parser )
{
    parse_status_t status;
    memptr token;
    memptr hdr_value;
    token_type_t tok_type;
    scanner_t *scanner = &parser->scanner;
    size_t save_pos;
    http_header_t *header;
    int header_id;
    int ret = 0;
    int index;
    http_header_t *orig_header;
    char save_char;
    int ret2;

    assert( parser->position == POS_HEADERS ||
            parser->ent_position == ENTREAD_CHUNKY_HEADERS );

    while( TRUE ) {
        save_pos = scanner->cursor;

        //
        // check end of headers
        //
        status = scanner_get_token( scanner, &token, &tok_type );
        if( status != PARSE_OK ) {
            return status;
        }

        if( tok_type == TT_CRLF ) {

            // end of headers
            if( ( parser->msg.is_request )
                && ( parser->msg.method == HTTPMETHOD_POST ) ) {
                parser->position = POS_COMPLETE;    //post entity parsing
                //is handled separately 
                return PARSE_SUCCESS;
            }

            parser->position = POS_ENTITY;  // read entity next
            return PARSE_OK;
        }
        //
        // not end; read header
        //
        if( tok_type != TT_IDENTIFIER ) {
            return PARSE_FAILURE;   // didn't see header name
        }

        status = match( scanner, " : %R%c", &hdr_value );
        if( status != PARSE_OK ) {
            // pushback tokens; useful only on INCOMPLETE error
            scanner->cursor = save_pos;
            return status;
        }
        //
        // add header
        //

        // find header
        index = map_str_to_int( token.buf, token.length, Http_Header_Names,
                                NUM_HTTP_HEADER_NAMES, FALSE );
        if( index != -1 ) {

            //Check if it is a soap header
            if( Http_Header_Names[index].id == HDR_SOAPACTION ) {

⌨️ 快捷键说明

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