📄 parseutil.cpp
字号:
{ token = scanner.getToken(); if ( token->tokType == Token::CRLF || token->tokType == Token::WHITESPACE ) { if ( count == 0 ) { // no uri; bad req line scanner.pushBack(); throw e; } else { break; } } else { count++; uri += token->s; } }}// *************************************#endif /* no_such_deff */// reads comma separated list header values// precond:// scanner points after the header name;// the colon and any whitespace around it has also been skipped// minItems: at least this many items should be in list// maxItems: no more than this many items should be in list// -1 means maxItems = infinity// --------// adds HttpHeaderValues to the list, 0..infin items could be// added// throws HttpParseException.PARSERR_BAD_LISTCOUNT if// item count is not in range [minItems, maxItems]// throws HttpParseException.PARSERR_BAD_COMMALIST if// list does not have a correct comma-separated formatstatic void ReadCommaSeparatedList( IN Tokenizer& scanner, OUT HttpHeaderValueList& list, IN int minItems, IN int maxItems, IN bool qIsUsed, IN CreateNewValueCallback createCallback, IN AddValueToListCallback addCallback = NULL ){ Token* token; HttpHeaderValue* value = NULL; int itemCount = 0; try { // at this point, all LWS has been skipped; // empty list is indicated by a CRLF token = scanner.getToken(); if ( token->tokType == Token::CRLF ) { scanner.pushBack(); throw -2; // end of list } scanner.pushBack(); // return item for value to parse while ( true ) { // create new item value = createCallback(); if ( value == NULL ) { throw OutOfMemoryException( "ReadCommaSeparatedList()" ); } // allow q to be read if ( qIsUsed ) { HttpQHeaderValue* qvalue; qvalue = (HttpQHeaderValue*) value; qvalue->qIsUsed = true; } // read list item value->load( scanner ); if ( addCallback == NULL ) { list.addAfterTail( value ); } else { addCallback( list, value ); } itemCount++; // skip comma and whitespace // SkipOptionalLWS( scanner ); token = scanner.getToken(); if ( token->s == "," ) { // ok } else if ( token->tokType == Token::CRLF ) { scanner.pushBack(); throw -2; // end of list } else { scanner.pushBack(); throw -3; // unexpected element } SkipOptionalLWS( scanner ); } } catch ( int code ) { if ( code == -2 ) { HttpParseException e("ReadCommaSeparatedList():end of list", scanner.getLineNum() ); e.setErrorCode( PARSERR_BAD_LISTCOUNT ); // end of list if ( itemCount < minItems ) { throw e; // too few items } // maxItems == -1 means no limit if ( maxItems >= 0 && itemCount > maxItems ) { throw e; // too many items } } else if ( code == -3 ) { // unexpected element where comma should've been HttpParseException e("ReadCommaSeparatedList(): comma expected", scanner.getLineNum() ); e.setErrorCode( PARSERR_BAD_COMMALIST ); throw e; } } catch ( HttpParseException& ) { if( value ) delete value; }}////////////////////// returns integer number 0..INT_MAX from scanner// throws ParseFailException.PARSERR_BAD_NUMBER if number is// invalid or negative; the bad token is put back in the scanner//static int loadNum( Tokenizer& scanner, int base ){ Token *token; char *endptr; int num = 0; token = scanner.getToken(); errno = 0; // set this to explicitly avoid bugs num = strtol( token->s.c_str(), &endptr, base ); if ( *endptr != '\0' || num < 0 ) { xstring msg("loadNum(): bad number " ); msg += token->s; scanner.pushBack(); throw HttpParseException( msg.c_str(), scanner.getLineNum() ); } if ( (num == LONG_MIN || num == LONG_MAX) && (errno == ERANGE) ) { xstring msg("loadNum(): out of range '" ); msg += token->s; msg += "'"; scanner.pushBack(); throw HttpParseException( msg.c_str(), scanner.getLineNum() ); } return num;}void NumberToString( int num, xstring& s ){ char buf[50]; sprintf( buf, "%d", num ); s += buf;}static void LoadDateTime( Tokenizer& scanner, tm& datetime ){ xstring rawValue; int numCharsParsed; int success; ParseHeaderValue( scanner, rawValue ); const char* cstr = rawValue.c_str(); success = ParseDateTime( cstr, &datetime, &numCharsParsed ); if ( success == -1 ) { throw HttpParseException( "LoadDateTime() bad date/time", scanner.getLineNum() ); } // skip all whitespace after date/time const char* s2 = &cstr[numCharsParsed]; while ( *s2 == ' ' || *s2 == '\t' ) { s2++; } if ( *s2 != '\0' ) { throw HttpParseException( "LoadDateTime() bad trailer", scanner.getLineNum() ); } }static void LoadUri( IN Tokenizer& scanner, OUT uri_type& uri, OUT xstring& uriStr ){ Token *token; uriStr = ""; while ( true ) { token = scanner.getToken(); if ( token->tokType == Token::IDENTIFIER || token->tokType == Token::SEPARATOR || token->tokType == Token::QUOTED_STRING ) { uriStr += token->s; } else { scanner.pushBack(); break; } } if ( uriStr.length() == 0 ) { throw HttpParseException( "LoadUri(): no uri", scanner.getLineNum() ); } int len; len = parse_uri( (char*)(uriStr.c_str()), uriStr.length(), &uri ); if ( len < 0 ) { throw HttpParseException( "LoadUri(): bad uri", scanner.getLineNum() ); }}static void ParseMajorMinorNumbers( const char *s, int& majorVers, int& minorVers ){ int major, minor; char* endptr; char* s2; try { errno = 0; major = strtol( s, &endptr, 10 ); if ( (major < 0) || ((major == LONG_MAX || major == LONG_MIN) && (errno == ERANGE)) ) { throw -1; } if ( *endptr != '.' ) { throw -1; } s2 = endptr + 1; errno = 0; minor = strtol( s2, &endptr, 10 ); if ( (minor < 0) || (*endptr != 0) || ((minor == LONG_MAX || minor == LONG_MIN) && (errno == ERANGE)) ) { throw -1; } majorVers = major; minorVers = minor; } catch ( int code ) { if ( code == -1 ) { HttpParseException e("ParseMajorMinorNumbers(): " "bad http version: " ); e.appendMessage( s ); throw e; } }}static void ParseHttpVersion( IN Tokenizer& scanner, OUT int& majorVers, OUT int& minorVers ){ Token* token; HttpParseException eVers( "ParseHttpVersion(): bad http version" ); token = scanner.getToken(); if ( token->s.compareNoCase("HTTP") != 0 ) { throw eVers; } token = scanner.getToken(); // skip optional whitespace if ( token->tokType == Token::WHITESPACE ) { token = scanner.getToken(); } if ( token->s != '/' ) { throw eVers; } token = scanner.getToken(); if ( token->tokType == Token::WHITESPACE ) { // skip optional whitespace and read version token = scanner.getToken(); } ParseMajorMinorNumbers( token->s.c_str(), majorVers, minorVers ); /* ***************** old code ************ token = scanner.getToken(); if ( token->tokType != Token::WHITESPACE ) { scanner.pushBack(); } majorVers = loadNum( scanner, 10 ); token = scanner.getToken(); if ( token->tokType == Token::WHITESPACE ) { token = scanner.getToken(); } if ( token->s != '.' ) { throw eVers; } token = scanner.getToken(); if ( token->tokType != Token::WHITESPACE ) { scanner.pushBack(); } minorVers = loadNum( scanner, 10 ); ******************************** old code end ***** */}static void PrintHttpVersion( int major, int minor, xstring& s ){ s += "HTTP/"; NumberToString( major, s ); s += '.'; NumberToString( minor, s );}static void HeaderValueListToString( IN HttpHeaderValueList& list, INOUT xstring& s ){ HttpHeaderValueNode* node; HttpHeaderValue* value; node = list.getFirstItem(); for ( int i = 0; i < list.length(); i++ ) { value = (HttpHeaderValue *) node->data; value->toString( s ); node = list.next( node ); }}//static void QToString( float q, INOUT xstring& s )//{// char buf[50]; // sprintf( buf, ";q=%1.3f", q );// s += buf;//}// match: ( 0 ['.' 0*3DIGIT] ) | ( '1' 0*3('0') )// returns 0.0 to 1.0 on success;// throws HttpParseExecptionstatic float ParseQValue( const char *s ){ char c; int i; char dot; int count; char *endptr; float value = 0.0; bool partial; i = 0; partial = true; try { c = s[i++]; if ( !(c == '0' || c == '1') ) { throw -1; } dot = s[i++]; if ( dot == '.' ) { if ( c == '1' ) { // match 3 zeros for ( count = 0; count < 3; count++ ) { c = s[i++]; if ( c == '\0' ) { partial = false; break; // done; success } if ( c != '0' ) { throw -1; } } } else { // c == 0, match digits for ( count = 0; count < 3; count++ ) { c = s[i++]; if ( c == 0 ) { partial = false; break; } if ( !(c >= '0' && c <= '9') ) { throw -1; } } } // all chars must be processed if ( partial && s[i] != '\0' ) { throw -1; } } else if ( dot != '\0' ) { throw -1; } value = (float)strtod( s, &endptr ); } catch ( int code ) { if ( code == -1 ) { xstring msg("ParseQValue(): "); msg += s; throw HttpParseException( msg.c_str() ); } } return value;}// match: q = floatValuestatic float LoadQValue( Tokenizer& scanner ){ Token* token; float q; token = scanner.getToken(); if ( token->s != 'q' ) { scanner.pushBack(); throw HttpParseException( "LoadQValue(): 'q' expected", scanner.getLineNum() ); } SkipOptionalLWS( scanner ); token = scanner.getToken(); if ( token->s != '=' ) { scanner.pushBack(); throw HttpParseException( "LoadQValue(): '=' expected", scanner.getLineNum() ); } SkipOptionalLWS( scanner ); token = scanner.getToken(); if ( token->tokType != Token::IDENTIFIER ) { scanner.pushBack(); throw HttpParseException( "LoadQValue(): number expected", scanner.getLineNum() ); } // ident to q = ParseQValue( token->s.c_str() ); if ( q < 0 ) { throw HttpParseException( "LoadQValue(): invalid value", scanner.getLineNum() ); } return q;}static void PrintCommaSeparatedList( HttpHeaderValueList& list, xstring& s ){ bool first = true; HttpHeaderValueNode* node; node = list.getFirstItem(); while ( node != NULL ) { if ( !first ) { s += ", "; } else { first = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -