httpparser.c

来自「原来由英特尔制定的UPnP SDK的」· C语言 代码 · 共 2,179 行 · 第 1/5 页

C
2,179
字号
/////////////////////////////////////////////////////////////////////////////// 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.************************************************************************/#define _GNU_SOURCE	// For strcasestr() in string.h#include "config.h"#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"// entity positions#define NUM_HTTP_METHODS 9static 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 33str_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 UPNP_INLINE voidscanner_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 UPNP_INLINE xbooleanis_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 UPNP_INLINE xbooleanis_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 UPNP_INLINE xbooleanis_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 UPNP_INLINE xbooleanis_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_tscanner_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 UPNP_INLINE 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 :************************************************************************/#ifndef WIN32#warning The only use of the function 'scanner_pushback()' in the code is commented out.#warning 'scanner_pushback()' is a candidate for removal.#else#pragma message ("The only use of the function 'scanner_pushback()' in the code is commented out.")#pragma message ("'scanner_pushback()' is a candidate for removal.")#endifstatic UPNP_INLINE voidscanner_pushback( INOUT scanner_t * scanner,                  IN size_t pushback_bytes ){    scanner->cursor -= pushback_bytes;}/***********************************************************************//*************                end of scanner              **************//***********************************************************************//***********************************************************************//*************                    parser                  **************//***********************************************************************//***********************************************************************//*************                 http_message_t             **************//***********************************************************************//************************************************************************* Function :	httpmsg_compare** Parameters :*	void* param1 ;	*	void* param2 ;	*

⌨️ 快捷键说明

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