/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * */ /* File: AdminQuery.cpp Contains: Implements Admin Query */ #ifndef __Win32__ #include /* for getopt() et al */ #endif #include #include /* for //qtss_printf */ #include /* for getloadavg & other useful stuff */ #include "QTSSAdminModule.h" #include "OSArrayObjectDeleter.h" #include "StringParser.h" #include "StrPtrLen.h" #include "QTSSModuleUtils.h" #include "OSHashTable.h" #include "OSMutex.h" #include "StrPtrLen.h" #include "OSRef.h" #include "AdminElementNode.h" #include "AdminQuery.h" #include "OSMemory.h" #include "StringTranslator.h" /* r = recurse -> walk downward in hierarchy v = verbose -> return full path in name a = access -> return read/write access t = type -> return type of value ** perhaps better not to support f = filter -> return filter p = path -> return path i = indexed -> return indexed representation of attributes d = debug -> return debug info on errors */ StrPtrLen * QueryURI::NextSegment(StrPtrLen *currentPathPtr, StrPtrLen *outNextPtr) { StrPtrLen *result = NULL; StrPtrLen *theURLPtr = GetURL(); if (outNextPtr) outNextPtr->Set(NULL,0); if (currentPathPtr && outNextPtr && theURLPtr && currentPathPtr->Len > 0) { if ( (currentPathPtr->Ptr >= theURLPtr->Ptr) && (currentPathPtr->Ptr < &theURLPtr->Ptr[theURLPtr->Len] ) ) { //qtss_printf("theURLPtr="); PRINT_STR(theURLPtr); //qtss_printf("QueryURI::NextSegment currentPathPtr="); PRINT_STR(currentPathPtr); UInt32 len = (PointerSizedInt)&(theURLPtr->Ptr[theURLPtr->Len -1]) - ((PointerSizedInt) currentPathPtr->Ptr + (currentPathPtr->Len -1)); char *startPtr = (char *) ( (PointerSizedInt) currentPathPtr->Ptr + currentPathPtr->Len) ; StrPtrLen tempPath(startPtr,len); StringParser URLparser(&tempPath); URLparser.ConsumeLength(NULL, 1); URLparser.ConsumeUntil(outNextPtr,(UInt8*) sNotQueryData); result = outNextPtr; //qtss_printf("QueryURI::NextSegment nextPathPtr=");PRINT_STR(outNextPtr); } } return result; }; QueryURI::URIField QueryURI::sURIFields[] = { /* fAttrName, len, id, fDataptr*/ { "modules", strlen("modules"), eModuleID, NULL }, { "admin", strlen("admin"), eRootID, NULL }, { "URL", strlen("URL"), eURL, NULL }, { "QUERY", strlen("QUERY"), eQuery, NULL }, { "parameters", strlen("parameters"), eParameters,NULL }, { "snapshot", strlen("snapshot"), eSnapshot, NULL }, { "command", strlen("command"), eCommand, NULL }, { "value", strlen("value"), eValue, NULL }, { "type", strlen("type"), eType, NULL }, { "access", strlen("access"), eAccess, NULL }, { "name", strlen("name"), eName, NULL }, { "filter1", strlen("filter1"), eFilter1, NULL }, { "filter2", strlen("filter2"), eFilter2, NULL }, { "filter3", strlen("filter3"), eFilter3, NULL }, { "filter4", strlen("filter4"), eFilter4, NULL }, { "filter5", strlen("filter5"), eFilter5, NULL }, { "filter6", strlen("filter6"), eFilter6, NULL }, { "filter7", strlen("filter7"), eFilter7, NULL }, { "filter8", strlen("filter8"), eFilter8, NULL }, { "filter9", strlen("filter9"), eFilter9, NULL }, { "filter10", strlen("filter10"), eFilter10, NULL }, { "", 0, -1, NULL } }; char *QueryURI::sCommandDefs[] = { "GET", "SET", "ADD", "DEL" }; UInt8 QueryURI::sNotQueryData[] = // query stops { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //0-9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //10-19 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //20-29 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, //30-39 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, //40-49 allow * . and - and all numbers 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //50-59 allow : 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, //60-69 //stop on every character except a letter 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, //90-99 _ is a word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //100-109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, //120-129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //130-139 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //140-149 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //150-159 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //160-169 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //170-179 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //180-189 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //190-199 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //200-209 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //210-219 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //220-229 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //230-239 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //240-249 1, 1, 1, 1, 1, 0 //250-255 }; UInt8 QueryURI::sWhiteQuoteOrEOL[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //0-9 // \t is a stop 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, //10-19 //'\r' & '\n' are stop conditions 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-29 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, //30-39 ' ' , '"' is a stop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40-49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50-59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //60-69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //90-99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //100-109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //120-129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //130-139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140-149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150-159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160-169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170-179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180-189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190-199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200-209 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210-219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220-229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230-239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240-249 0, 0, 0, 0, 0, 0 //250-255 }; UInt8 QueryURI::sWhitespaceOrQuoteMask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //0-9 // \t is a stop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10-19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-29 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, //30-39 ' ' , '"' is a stop 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40-49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50-59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //60-69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //90-99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //100-109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //120-129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //130-139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140-149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150-159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160-169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170-179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180-189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190-199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200-209 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210-219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220-229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230-239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240-249 0, 0, 0, 0, 0, 0 //250-255 }; QueryURI::QueryURI (StrPtrLen *inStream) { fIsAdminQuery = false; fUseSnapShot = false; fURIFieldsPtr = &sURIFields[0]; fTheCommand = -1; for (short testField = 0; testField < eNumAttributes; testField++) fURIFieldsPtr[testField].fData = NULL; memset(fURIBuffer,0,QueryURI::eMaxBufferSize); memset(fQueryBuffer,0,QueryURI::eMaxBufferSize); fParamBits = 0; fSnapshotID = 0; fAccessFlags = 0; fQueryHasResponse = false; fLastPath[0] = 0; fIsPref = false; fNumFilters = 0; fHasQuery = false; URLParse(inStream); SetQueryData(); } void QueryURI::SetSnapShot() { StrPtrLen *snapshotSPL = GetSnapshot(); if (snapshotSPL != NULL) { StringParser parser(snapshotSPL); fSnapshotID = parser.ConsumeInteger(NULL); fUseSnapShot = true; } }; void QueryURI::SetCommand() { StrPtrLen commandDef; StrPtrLen *queryCommandPtr; Bool16 foundCommand = false; SInt16 commandIndex; queryCommandPtr = this->GetCommand(); if (queryCommandPtr == NULL || queryCommandPtr->Len == 0) // Default command { fTheCommand = kGETCommand; return; } for (commandIndex = 0; commandIndex < kLastCommand; commandIndex ++) { foundCommand = queryCommandPtr->EqualIgnoreCase(sCommandDefs[commandIndex],strlen(sCommandDefs[commandIndex])); if (foundCommand) { fTheCommand = commandIndex; } } }; void QueryURI::SetAccessFlags() { StrPtrLen tempStr; SInt16 theChar; StringParser parser(GetAccess()); fAccessFlags = 0; while (parser.GetDataRemaining() != 0) { parser.ConsumeLength(&tempStr, 1); if(tempStr.Len > 0) { theChar = *tempStr.Ptr; switch(theChar) { case 'r': fAccessFlags |= qtssAttrModeRead; break; case 'w': fAccessFlags |= qtssAttrModeWrite; break; case 'p': fAccessFlags |= qtssAttrModePreempSafe; break; //case 'd': fAccessFlags |= qtssAttrModeRemoveable; //break; } } tempStr.Len = 0; } } void QueryURI::SetParamBits(UInt32 forcebits) { StrPtrLen tempStr; SInt16 theChar; StringParser parser(GetParameters()); fParamBits = forcebits; while (parser.GetDataRemaining() != 0) { parser.ConsumeLength(&tempStr, 1); if(tempStr.Len > 0) { theChar = *tempStr.Ptr; switch(theChar) { case 'r': fParamBits |= kRecurseParam; break; case 'v': fParamBits |= kVerboseParam; break; case 'a': fParamBits |= kAccessParam; break; case 't': fParamBits |= kTypeParam; break; case 'f': fParamBits |= kFilterParam; break; case 'p': fParamBits |= kPathParam; break; case 'd': fParamBits |= kDebugParam; break; case 'i': fParamBits |= kIndexParam; break; } } tempStr.Len = 0; } } QueryURI::~QueryURI() { /* for (int count = 0; fURIFieldsPtr[count].fID != -1 ; count++) { //qtss_printf("QueryURI::~QueryURI delete %s=",fURIFieldsPtr[count].fFieldName); PRINT_STR(fURIFieldsPtr[count].fData); if (fURIFieldsPtr[count].fData && fURIFieldsPtr[count].fData->Ptr) delete fURIFieldsPtr[count].fData->Ptr; fURIFieldsPtr[count].fData = NULL; } */ } UInt32 QueryURI::CheckInvalidIterator(char* evalMessageBuff) { UInt32 result = 0; StringParser parser(GetURL()); parser.ConsumeUntil(NULL,'*'); if (parser.PeekFast() == '*') { result = 405; static char *message = "* iterator not valid"; qtss_sprintf(evalMessageBuff, "%s",message); } return result; } UInt32 QueryURI::CheckInvalidArrayIterator(char* evalMessageBuff) { UInt32 result = 0; StringParser parser(GetURL()); parser.ConsumeUntil(NULL,':'); if (parser.PeekFast() == ':') { result = 405; static char *message = ": array iterator not valid"; qtss_sprintf(evalMessageBuff, "%s",message); } return result; } UInt32 QueryURI::CheckInvalidRecurseParam(char* evalMessageBuff) { UInt32 result = 0; if (RecurseParam()) { result = 405; static char *message = "(r)ecurse parameter not valid"; qtss_sprintf(evalMessageBuff, "%s",message); } return result; } UInt32 QueryURI::EvalQuery(UInt32 *forceResultPtr, char *forceMessagePtr) { UInt32 result = 0; const SInt16 messageLen = 512; char evalMessageBuff[messageLen] = {0}; StrPtrLen evalMessage; evalMessage.Set(evalMessageBuff, messageLen); if (forceResultPtr != NULL) { result = *forceResultPtr; switch(*forceResultPtr) { case 404: qtss_sprintf(fQueryMessageBuff,"reason=\"No data found\"" ); fQueryEvalMessage.Set(fQueryMessageBuff, strlen(fQueryMessageBuff)); break; default: { SInt32 theID = GetCommandID(); StrPtrLen *commandPtr = GetCommand(); if (theID < 0) { if (commandPtr) { qtss_sprintf(fQueryMessageBuff,"reason=\"%s for command %s\"",forceMessagePtr,commandPtr->Ptr); } } else { qtss_sprintf(fQueryMessageBuff,"reason=\"%s for command %s\"",forceMessagePtr, QueryURI::sCommandDefs[GetCommandID()]); } } fQueryEvalMessage.Set(fQueryMessageBuff, strlen(fQueryMessageBuff)); } } else { switch(GetCommandID()) { case kGETCommand: { // special case test. A query with no parameters is a get. A query with parameters requires a command. if (fHasQuery && (this->GetCommand() == NULL || this->GetCommand()->Len == 0)) { result = 400; static char *message = "reason=\"command parameter is missing\""; qtss_sprintf(evalMessageBuff, "%s",message); fQueryEvalMessage.Set(evalMessageBuff, strlen(evalMessageBuff)); fQueryEvalResult = result; return result; } } break; case kSETCommand: { if (NULL==GetValue()) { result = 400; static char *message = "No value"; qtss_sprintf(evalMessageBuff, "%s",message); break; } result = CheckInvalidRecurseParam( (char *) evalMessageBuff); if (result != 0) break; result = CheckInvalidIterator( (char *) evalMessageBuff); if (result != 0) break; result = CheckInvalidArrayIterator( (char *) evalMessageBuff); if (result != 0) break; } break; case kADDCommand: { if (0) { result = 501; static char *message="No implementation"; qtss_sprintf(evalMessageBuff, "%s",message); break; } if (NULL==GetValue()) { result = 400; static char *message = "Attribute value not defined"; qtss_sprintf(evalMessageBuff, "%s",message); break; } result = CheckInvalidRecurseParam( (char *) evalMessageBuff); if (result != 0) break; result = CheckInvalidIterator( (char *) evalMessageBuff); if (result != 0) break; result = CheckInvalidArrayIterator( (char *) evalMessageBuff); if (result != 0) break; } break; case kDELCommand: { result = CheckInvalidRecurseParam( (char *) evalMessageBuff); if (result != 0) break; result = CheckInvalidIterator( (char *) evalMessageBuff); if (result != 0) break; result = CheckInvalidArrayIterator( (char *) evalMessageBuff); if (result != 0) break; } break; default: { result = 501; static char *message="No implementation"; qtss_sprintf(evalMessageBuff, "%s",message); break; } } if (result != 0) { SInt32 theID = GetCommandID(); StrPtrLen *commandPtr = GetCommand(); if (theID < 0) { if (commandPtr) { qtss_sprintf(fQueryMessageBuff,"reason=\"%s for command %s\"",evalMessage.Ptr,commandPtr->Ptr); } } else { //qtss_printf("Set fQueryMessageBuff=%s\n",evalMessage.Ptr); qtss_sprintf(fQueryMessageBuff,"reason=\"%s for command %s\"",evalMessage.Ptr, QueryURI::sCommandDefs[GetCommandID()]); } } else { qtss_sprintf(fQueryMessageBuff,"reason=\"OK\""); } fQueryEvalMessage.Set(fQueryMessageBuff, strlen(fQueryMessageBuff)); //qtss_printf("fQueryMessageBuff=%s\n",fQueryMessageBuff); } fQueryEvalResult = result; return result; } void QueryURI::ParseQueryString(StringParser *parserPtr,StrPtrLen *urlStreamPtr) { StrPtrLen queryStr; StringParser tempQueryParse(parserPtr->GetStream());// point to local copy xx char *stopCharPtr = NULL; char *startCharPtr = NULL; UInt32 len = 0; tempQueryParse.ConsumeUntil(NULL, sWhiteQuoteOrEOL); // stop on whitespace '"' tempQueryParse.ConsumeWhitespace(); tempQueryParse.ConsumeUntil(NULL, '?'); // stop at start of query tempQueryParse.Expect('?'); startCharPtr = tempQueryParse.GetCurrentPosition(); //qtss_printf("QueryURI::ParseQueryString start Position = '%s'\n",startCharPtr); while (tempQueryParse.GetDataRemaining() > 0) { tempQueryParse.ConsumeUntil(NULL, sWhiteQuoteOrEOL); // stop on whitespace '"' stopCharPtr = tempQueryParse.GetCurrentPosition(); if (*stopCharPtr == '"') // if quote read to next quote { tempQueryParse.ConsumeLength(NULL, 1); tempQueryParse.ConsumeUntil(NULL, '"'); tempQueryParse.ConsumeLength(NULL, 1); //qtss_printf("QueryURI::ParseQueryString is quote GetCurrentPosition = '%s' len = %"_U32BITARG_"\n",stopCharPtr, strlen(stopCharPtr)); } else { //qtss_printf("QueryURI::ParseQueryString white or EOL GetCurrentPosition = '%s' len = %"_U32BITARG_"\n",stopCharPtr, strlen(stopCharPtr)); if (*stopCharPtr == ' ') { tempQueryParse.ConsumeWhitespace(); continue; } break; } } len = (UInt32) ((PointerSizedInt)stopCharPtr - (PointerSizedInt) startCharPtr); if (len < QueryURI::eMaxBufferSize) { if (len > 0) fHasQuery = true; queryStr.Set(fQueryBuffer,len); memcpy(fQueryBuffer, startCharPtr, len ); fURIFieldSPL[eQuery].Set(queryStr.Ptr,queryStr.Len); fURIFieldsPtr[eQuery].fData = &fURIFieldSPL[eQuery]; } //qtss_printf("Query String = '%s' Query len = %"_U32BITARG_" parseLen = %"_U32BITARG_"\n",queryStr.Ptr, queryStr.Len,len); }; void QueryURI::ParseURLString(StringParser *parserPtr,StrPtrLen *urlStreamPtr) { parserPtr->ConsumeWhitespace(); parserPtr->ConsumeUntilWhitespace(urlStreamPtr); fAdminFullURI.Set(fURIBuffer, urlStreamPtr->Len); if (urlStreamPtr->Len < QueryURI::eMaxBufferSize) memcpy(fURIBuffer,urlStreamPtr->Ptr,urlStreamPtr->Len); // make a local copy in fAdminFullURI //qtss_printf("QueryURI::ParseURLString fURIBuffer =%s len = %"_U32BITARG_"\n", fURIBuffer,urlStreamPtr->Len); StringParser tempURLParse(&fAdminFullURI);// point to local copy tempURLParse.ConsumeUntil(&fURIFieldSPL[eURL],'?'); // pull out URL fURIFieldsPtr[eURL].fData = &fURIFieldSPL[eURL]; //qtss_printf("QueryURI::ParseURLString fURIFieldsPtr[eURL]="); PRINT_STR(fURIFieldsPtr[eURL].fData); }; void QueryURI::URLParse(StrPtrLen *inStream) { if (inStream != NULL) { char * decodedRequest = NEW char[inStream->Len + 1]; Assert(decodedRequest != NULL); decodedRequest[inStream->Len] = 0; OSCharArrayDeleter decodedRequestDeleter(decodedRequest); StringParser tempParser(inStream); StrPtrLen URLToParse; SInt32 URLoffset = 0; if (inStream->Len > 0) { // skip past the HTTP command for the StringTranslator::DecodeURL but keep it in our decoded Request buffer tempParser.ConsumeWhitespace(); tempParser.ConsumeWord(NULL); tempParser.ConsumeWhitespace(); URLToParse.Set(tempParser.GetCurrentPosition(),tempParser.GetDataRemaining()); // this should be a '/' and is required by the DecodeURL routine URLoffset = tempParser.GetDataParsedLen(); memcpy(decodedRequest, inStream->Ptr, URLoffset); } SInt32 decodedLen = StringTranslator::DecodeURL(URLToParse.Ptr, URLToParse.Len, &decodedRequest[URLoffset], inStream->Len); StrPtrLen decodedRequestStr(decodedRequest,decodedLen); StringParser parser(&decodedRequestStr); StrPtrLen startFields; StrPtrLen adminURI; StrPtrLen streamURL; do // once { if (decodedRequestStr.Len < 1) { //qtss_printf("no string to parse \n"); break; } if (decodedRequestStr.Len > QueryURI::eMaxBufferSize -1) { //qtss_printf("URL string bigger than Buffer size=%"_U32BITARG_"\n",decodedRequestStr.Len); break; } StrPtrLen httpRequest; parser.ConsumeWord(&httpRequest); static StrPtrLen sPost("POST"); static StrPtrLen sGet("GET"); if ( false == httpRequest.Equal(sPost) && false == httpRequest.Equal(sGet) ) //bail if not a GET or POST { //qtss_printf("not a POST or GET \n"); break; } ParseURLString(&parser,&streamURL); ParseQueryString(&parser,&streamURL); if (fURIFieldSPL[eURL].Len > 0) { StrPtrLen tempStr; StringParser URIParser(fURIFieldsPtr[eURL].fData); // parser now pointing to internal buffer root of URL if(!URIParser.Expect('/')) { //qtss_printf("no starting slash\n"); break; } URIParser.ConsumeWord(&tempStr); if ( !(tempStr.Len != 0 && tempStr.Equal(StrPtrLen(fURIFieldsPtr[eModuleID].fFieldName,fURIFieldsPtr[eModuleID].fFieldLen) )) )//check "modules" request { //qtss_printf("no %s in URL\n",fURIFieldsPtr[eModuleID].fFieldName); break; } fURIFieldSPL[eModuleID] = tempStr; fURIFieldsPtr[eModuleID].fData = &fURIFieldSPL[eModuleID]; if(!URIParser.Expect('/')) { //qtss_printf("no trailing slash for modules\n"); break; } URIParser.ConsumeWord(&tempStr); if ( !(tempStr.Len != 0 && tempStr.Equal(StrPtrLen(fURIFieldsPtr[eRootID].fFieldName,fURIFieldsPtr[eRootID].fFieldLen) )) )//check "modules" request { //qtss_printf("no %s in URL\n", fURIFieldsPtr[eRootID].fFieldName); break; } fIsAdminQuery = true; // ok it is for us fURIFieldSPL[eRootID] = tempStr; fURIFieldsPtr[eRootID].fData = &fURIFieldSPL[eRootID]; } if (fURIFieldSPL[eQuery].Len > 0) // has query fields (step past ?) { StringParser queryParser(fURIFieldsPtr[eQuery].fData); StrPtrLen tempStr(fURIFieldSPL[eQuery].Ptr,fURIFieldSPL[eQuery].Len); StrPtrLen tempData; //qtss_printf("queryParser=");PRINT_STR(fURIFieldsPtr[eQuery].fData); while (queryParser.GetDataRemaining() != 0) { tempData.Set(NULL,0); if (queryParser.GetDataRemaining())queryParser.ConsumeWhitespace(); if (queryParser.GetDataRemaining())queryParser.ConsumeUntil(&tempStr,(UInt8*) sNotQueryData); if (tempStr.Len == 0) { //qtss_printf("no query name\n"); if (queryParser.GetDataRemaining())queryParser.ConsumeLength(NULL, 1); continue; } if (queryParser.GetDataRemaining())queryParser.ConsumeWhitespace(); if(!queryParser.Expect('=')) { //qtss_printf("no '=' for query name ");PRINT_STR(&tempStr); if (queryParser.GetDataRemaining())queryParser.ConsumeLength(NULL, 1); continue; } if (queryParser.GetDataRemaining())queryParser.ConsumeWhitespace(); char testQuote = queryParser.PeekFast(); if (testQuote == '"') { if (queryParser.GetDataRemaining())queryParser.ConsumeLength(NULL, 1); if (queryParser.GetDataRemaining())queryParser.ConsumeUntil(&tempData, '"'); if (queryParser.GetDataRemaining())queryParser.ConsumeLength(NULL, 1); } else { if (queryParser.GetDataRemaining())queryParser.ConsumeUntil(&tempData,(UInt8*) sNotQueryData); } if (tempData.Len == 0) { if (queryParser.GetDataRemaining())queryParser.Expect('+'); if (queryParser.GetDataRemaining())queryParser.ConsumeWhitespace(); //qtss_printf("no query data for ");PRINT_STR(&tempStr); continue; } if (queryParser.GetDataRemaining())queryParser.ConsumeWhitespace(); if (queryParser.GetDataRemaining())queryParser.Expect('+'); if (queryParser.GetDataRemaining())queryParser.ConsumeWhitespace(); //qtss_printf("set data =%s\n", tempData.Ptr); StrPtrLen definedID; UInt32 fieldID; for (short testField = 0; testField < eNumAttributes; testField++) { definedID.Set(fURIFieldsPtr[testField].fFieldName,fURIFieldsPtr[testField].fFieldLen); fieldID = fURIFieldsPtr[testField].fID; if ( definedID.EqualIgnoreCase(tempStr.Ptr, tempStr.Len) ) // test (fURIFieldsPtr[fieldID].fData == NULL) to make first time setting only { // set the field value always takes the last appearance of the name=value pair if (fieldID >= eFilter1) { UInt32 emptyId = eFilter1 + fNumFilters; if (tempData.Len > 0) { fNumFilters ++; fURIFieldSPL[emptyId].Set(tempData.Ptr,tempData.Len); fURIFieldsPtr[emptyId].fData = &fURIFieldSPL[emptyId]; } } else { fURIFieldSPL[fieldID].Set(tempData.Ptr,tempData.Len); fURIFieldsPtr[testField].fData = &fURIFieldSPL[fieldID]; } } } } } } while (false); /* for (int count = 0; fURIFieldsPtr[count].fID != -1 ; count++) { //qtss_printf("QueryURI::URLParse %s=",fURIFieldsPtr[count].fFieldName); PRINT_STR(fURIFieldsPtr[count].fData); } */ } }