httpparser.c

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

C
2,179
字号
static UPNP_INLINE intmatch_int( INOUT scanner_t * scanner,           IN int base,           OUT int *value ){    memptr token;    token_type_t   tok_type;    parse_status_t status;    long           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 UPNP_INLINE intread_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************************************************************************/#ifndef WIN32#warning There are currently no uses of the function 'skip_to_end_of_header()' in the code.#warning 'skip_to_end_of_header()' is a candidate for removal.#else#pragma message("There are currently no uses of the function 'skip_to_end_of_header()' in the code.")#pragma message("'skip_to_end_of_header()' is a candidate for removal.")#endifstatic UPNP_INLINE intskip_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 UPNP_INLINE parse_status_tmatch_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 intvfmatch( 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 );                    }            }        }    }    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 intmatch( 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************************************************************************/intmatchstr( IN char *str,          IN size_t slen,

⌨️ 快捷键说明

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