📄 httpparser.c
字号:
/////////////////////////////////////////////////////////////////////////////// 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"// 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 XINLINE 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 XINLINE 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 XINLINE 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 XINLINE 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 XINLINE 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 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 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 :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -