Darwin-Streaming-Server/APIModules/QTSSAdminModule/AdminQuery.cpp
Darren VanBuren 849723c9cf Add even more of the source
This should be about everything needed to build so far?
2017-03-07 17:14:16 -08:00

849 lines
30 KiB
C++

/*
*
* @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 <unistd.h> /* for getopt() et al */
#endif
#include <time.h>
#include <stdio.h> /* for //qtss_printf */
#include <stdlib.h> /* 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);
}
*/
}
}