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

📄 httpparser.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2003 Intel Corporation 
// All rights reserved. 
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met: 
//
// * Redistributions of source code must retain the above copyright notice, 
// this list of conditions and the following disclaimer. 
// * Redistributions in binary form must reproduce the above copyright notice, 
// this list of conditions and the following disclaimer in the documentation 
// and/or other materials provided with the distribution. 
// * Neither name of Intel Corporation nor the names of its contributors 
// may be used to endorse or promote products derived from this software 
// without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////

/************************************************************************
* Purpose: This file contains functions for scanner and parser for http 
* messages.
************************************************************************/

#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <stdarg.h>
#include "strintmap.h"
#include "httpparser.h"
#include "statcodes.h"
#include "unixutil.h"

// Content Type Header
const char *ClientContentTypeHeader =
    "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n";


// entity positions
#define NUM_HTTP_METHODS 9
static str_int_entry Http_Method_Table[NUM_HTTP_METHODS] = {
    {"GET", HTTPMETHOD_GET},
    {"HEAD", HTTPMETHOD_HEAD},
    {"M-POST", HTTPMETHOD_MPOST},
    {"M-SEARCH", HTTPMETHOD_MSEARCH},
    {"NOTIFY", HTTPMETHOD_NOTIFY},
    {"POST", HTTPMETHOD_POST},
    {"SUBSCRIBE", HTTPMETHOD_SUBSCRIBE},
    {"UNSUBSCRIBE", HTTPMETHOD_UNSUBSCRIBE},
    {"POST", SOAPMETHOD_POST},

};

#define NUM_HTTP_HEADER_NAMES 33
str_int_entry Http_Header_Names[NUM_HTTP_HEADER_NAMES] = {
    {"ACCEPT", HDR_ACCEPT},
    {"ACCEPT-CHARSET", HDR_ACCEPT_CHARSET},
    {"ACCEPT-ENCODING", HDR_ACCEPT_ENCODING},
    {"ACCEPT-LANGUAGE", HDR_ACCEPT_LANGUAGE},
    {"ACCEPT-RANGES", HDR_ACCEPT_RANGE},
    {"CACHE-CONTROL", HDR_CACHE_CONTROL},
    {"CALLBACK", HDR_CALLBACK},
    {"CONTENT-ENCODING", HDR_CONTENT_ENCODING},
    {"CONTENT-LANGUAGE", HDR_CONTENT_LANGUAGE},
    {"CONTENT-LENGTH", HDR_CONTENT_LENGTH},
    {"CONTENT-LOCATION", HDR_CONTENT_LOCATION},
    {"CONTENT-RANGE", HDR_CONTENT_RANGE},
    {"CONTENT-TYPE", HDR_CONTENT_TYPE},
    {"DATE", HDR_DATE},
    {"EXT", HDR_EXT},
    {"HOST", HDR_HOST},
    {"IF-RANGE", HDR_IF_RANGE},
    {"LOCATION", HDR_LOCATION},
    {"MAN", HDR_MAN},
    {"MX", HDR_MX},
    {"NT", HDR_NT},
    {"NTS", HDR_NTS},
    {"RANGE", HDR_RANGE},
    {"SEQ", HDR_SEQ},
    {"SERVER", HDR_SERVER},
    {"SID", HDR_SID},
    {"SOAPACTION", HDR_SOAPACTION},
    {"ST", HDR_ST},
    {"TE", HDR_TE},
    {"TIMEOUT", HDR_TIMEOUT},
    {"TRANSFER-ENCODING", HDR_TRANSFER_ENCODING},
    {"USER-AGENT", HDR_USER_AGENT},
    {"USN", HDR_USN}
};

/***********************************************************************/

/*************				 scanner					  **************/

/***********************************************************************/

#define TOKCHAR_CR		0xD
#define TOKCHAR_LF		0xA

/************************************************************************
*	Function :	scanner_init
*
*	Parameters :
*		OUT scanner_t* scanner ; Scanner Object to be initialized
*		IN membuffer* bufptr ;	 Buffer to be copied
*
*	Description :	Intialize scanner
*
*	Return : void ;
*
*	Note :
************************************************************************/
static XINLINE void
scanner_init( OUT scanner_t * scanner,
              IN membuffer * bufptr )
{
    scanner->cursor = 0;
    scanner->msg = bufptr;
    scanner->entire_msg_loaded = FALSE;
}

/************************************************************************
*	Function :	is_separator_char
*
*	Parameters :
*		IN char c ;	character to be tested against used separator values
*
*	Description :	Finds the separator character.
*
*	Return : xboolean ;
*
*	Note :
************************************************************************/
static XINLINE xboolean
is_separator_char( IN char c )
{
    return strchr( " \t()<>@,;:\\\"/[]?={}", c ) != NULL;
}

/************************************************************************
*	Function :	is_identifier_char
*
*	Parameters :
*		IN char c ;	character to be tested for separator values
*
*	Description :	Calls the function to indentify separator character 
*
*	Return : xboolean ;
*
*	Note :
************************************************************************/
static XINLINE xboolean
is_identifier_char( IN char c )
{
    return ( c >= 32 && c <= 126 ) && !is_separator_char( c );
}

/************************************************************************
*	Function :	is_control_char
*
*	Parameters :
*		IN char c ;	character to be tested for a control character
*
*	Description :	Determines if the passed value is a control character
*
*	Return : xboolean ;
*
*	Note :
************************************************************************/
static XINLINE xboolean
is_control_char( IN char c )
{
    return ( ( c >= 0 && c <= 31 ) || ( c == 127 ) );
}

/************************************************************************
*	Function :	is_qdtext_char
*
*	Parameters :
*		IN char cc ; character to be tested for CR/LF
*
*	Description :	Checks to see if the passed in value is CR/LF
*
*	Return : xboolean ;
*
*	Note :
************************************************************************/
static XINLINE xboolean
is_qdtext_char( IN char cc )
{
    unsigned char c = ( unsigned char )cc;

    // we don't check for this; it's checked in get_token()
    assert( c != '"' );

    if( ( c >= 32 && c != 127 ) ||
        ( c == TOKCHAR_CR || c == TOKCHAR_LF || c == '\t' )
         ) {
        return TRUE;
    } else {
        return FALSE;
    }
}

/************************************************************************
*	Function :	scanner_get_token
*
*	Parameters :
*		INOUT scanner_t* scanner ;	Scanner Object
*		OUT memptr* token ;			Token 
*		OUT token_type_t* tok_type ; Type of token
*
*	Description :	reads next token from the input stream				
*		note: 0 and is used as a marker, and will not be valid in a quote
*
*	Return : parse_status_t ;
*		PARSE_OK															
*		PARSE_INCOMPLETE		-- not enuf chars to get a token			
*		PARSE_FAILURE			-- bad msg format							
*
*	Note :
************************************************************************/
static parse_status_t
scanner_get_token( INOUT scanner_t * scanner,
                   OUT memptr * token,
                   OUT token_type_t * tok_type )
{
    char *cursor;
    char *null_terminator;      // point to null-terminator in buffer
    char c;
    token_type_t token_type;
    xboolean got_end_quote;

    assert( scanner );
    assert( token );
    assert( tok_type );

    // point to next char in buffer
    cursor = scanner->msg->buf + scanner->cursor;
    null_terminator = scanner->msg->buf + scanner->msg->length;

    // not enough chars in input to parse
    if( cursor == null_terminator ) {
        return PARSE_INCOMPLETE;
    }

    c = *cursor;
    if( is_identifier_char( c ) ) {
        // scan identifier

        token->buf = cursor++;
        token_type = TT_IDENTIFIER;

        while( is_identifier_char( *cursor ) ) {
            cursor++;
        }

        if( !scanner->entire_msg_loaded && cursor == null_terminator ) {
            // possibly more valid chars
            return PARSE_INCOMPLETE;
        }
        // calc token length
        token->length = cursor - token->buf;
    } else if( c == ' ' || c == '\t' ) {
        token->buf = cursor++;
        token_type = TT_WHITESPACE;

        while( *cursor == ' ' || *cursor == '\t' ) {
            cursor++;
        }

        if( !scanner->entire_msg_loaded && cursor == null_terminator ) {
            // possibly more chars
            return PARSE_INCOMPLETE;
        }
        token->length = cursor - token->buf;
    } else if( c == TOKCHAR_CR ) {
        // scan CRLF

        token->buf = cursor++;
        if( cursor == null_terminator ) {
            // not enuf info to determine CRLF
            return PARSE_INCOMPLETE;
        }
        if( *cursor != TOKCHAR_LF ) {
            // couldn't match CRLF; match as CR
            token_type = TT_CTRL;   // ctrl char
            token->length = 1;
        } else {
            // got CRLF
            token->length = 2;
            token_type = TT_CRLF;
            cursor++;
        }
    } else if( c == TOKCHAR_LF )    // accept \n as CRLF
    {
        token->buf = cursor++;
        token->length = 1;
        token_type = TT_CRLF;
    } else if( c == '"' ) {
        // quoted text
        token->buf = cursor++;
        token_type = TT_QUOTEDSTRING;
        got_end_quote = FALSE;

        while( cursor < null_terminator ) {
            c = *cursor++;
            if( c == '"' ) {
                got_end_quote = TRUE;
                break;
            } else if( c == '\\' ) {
                if( cursor < null_terminator ) {
                    c = *cursor++;
                    //if ( !(c > 0 && c <= 127) )
                    if( c == 0 ) {
                        return PARSE_FAILURE;
                    }
                }
                // else, while loop handles incomplete buf
            } else if( is_qdtext_char( c ) ) {
                // just accept char
            } else {
                // bad quoted text
                return PARSE_FAILURE;
            }
        }
        if( got_end_quote ) {
            token->length = cursor - token->buf;
        } else                  // incomplete
        {
            assert( cursor == null_terminator );
            return PARSE_INCOMPLETE;
        }
    } else if( is_separator_char( c ) ) {
        // scan separator

        token->buf = cursor++;
        token_type = TT_SEPARATOR;
        token->length = 1;
    } else if( is_control_char( c ) ) {
        // scan ctrl char

        token->buf = cursor++;
        token_type = TT_CTRL;
        token->length = 1;
    } else {
        return PARSE_FAILURE;
    }

    scanner->cursor += token->length;   // move to next token
    *tok_type = token_type;
    return PARSE_OK;
}

/************************************************************************
*	Function :	scanner_get_str
*
*	Parameters :
*		IN scanner_t* scanner ;	Scanner Object
*
*	Description :	returns ptr to next char in string
*
*	Return : char* ;
*
*	Note :
************************************************************************/
static XINLINE char *
scanner_get_str( IN scanner_t * scanner )
{
    return scanner->msg->buf + scanner->cursor;
}

/************************************************************************
*	Function :	scanner_pushback
*
*	Parameters :
*		INOUT scanner_t* scanner ;	Scanner Object
*		IN size_t pushback_bytes ;	Bytes to be moved back
*
*	Description :	Move back by a certain number of bytes.				
*		This is used to put back one or more tokens back into the input		
*
*	Return : void ;
*
*	Note :
************************************************************************/
static XINLINE void
scanner_pushback( INOUT scanner_t * scanner,
                  IN size_t pushback_bytes )
{
    scanner->cursor -= pushback_bytes;
}

/***********************************************************************/

/*************				end of scanner				  **************/

/***********************************************************************/

⌨️ 快捷键说明

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