Example #1
0
inline Bool16 HasAuthentication(StringParser *theFullRequestPtr, StrPtrLen* namePtr, StrPtrLen* passwordPtr, StrPtrLen* outAuthTypePtr)
{
//  Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Bool16 hasAuthentication = false;
    StrPtrLen   strPtr; 
    StrPtrLen   authType;
    StrPtrLen   authString;
    while (theFullRequestPtr->GetDataRemaining() > 0)
    {
        theFullRequestPtr->ConsumeWhitespace();     
        theFullRequestPtr->ConsumeUntilWhitespace(&strPtr);
        if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("Authorization:")) ) 
            continue;   
                
        theFullRequestPtr->ConsumeWhitespace();     
        theFullRequestPtr->ConsumeUntilWhitespace(&authType);
        if ( authType.Len == 0 ) 
            continue;

        theFullRequestPtr->ConsumeWhitespace();                 
        theFullRequestPtr->ConsumeUntil(&authString, StringParser::sEOLMask);
        if ( authString.Len == 0 ) 
            continue;

        if (outAuthTypePtr != NULL)
            outAuthTypePtr->Set(authType.Ptr, authType.Len);

        if (authType.Equal(StrPtrLen("Basic") ) )
        {
            (void) ParseAuthNameAndPassword(&authString,namePtr, passwordPtr);
            if (namePtr->Len == 0) 
                continue;

            hasAuthentication = true;
            break;
        }
        else if (authType.Equal(sAuthRef) )
        {
            namePtr->Set(NULL,0);
            passwordPtr->Set(authString.Ptr, authString.Len);
            hasAuthentication = true;
            break;
        }
        
        
    };
    
    return hasAuthentication;
}
Example #2
0
Bool16 IsAuthentic(QTSS_Filter_Params* inParams,StringParser *fullRequestPtr)
{
    Bool16 isAuthentic = false;

    if (!sAuthenticationEnabled) // no authentication
    {
        isAuthentic = true;
    }
    else // must authenticate
    {
        StrPtrLen theClientIPAddressStr;
        (void) QTSS_GetValuePtr(inParams->inRTSPSession, qtssRTSPSesRemoteAddrStr, 0, (void**)&theClientIPAddressStr.Ptr, &theClientIPAddressStr.Len);
        Bool16 isLocal =  IPComponentStr(&theClientIPAddressStr).IsLocal(); 
        
        StrPtrLen authenticateName;
        StrPtrLen authenticatePassword;
        StrPtrLen authType;
        Bool16 hasAuthentication = HasAuthentication(fullRequestPtr,&authenticateName,&authenticatePassword, &authType);               
        if (hasAuthentication) 
        {
            if (authType.Equal(sAuthRef))
            {    
                if (isLocal)
                    isAuthentic = OSXAuthenticate(&authenticatePassword);
            }
            else
                isAuthentic = Authenticate(inParams->inRTSPRequest, &authenticateName,&authenticatePassword);
       }
    }
//    if (isAuthentic)
//        isAuthentic = AuthorizeAdminRequest(inParams->inRTSPRequest);
    (void) QTSS_SetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&isAuthentic, sizeof(isAuthentic));

    return isAuthentic;
}
Example #3
0
void    QTSServerPrefs::UpdateAuthScheme()
{
    static StrPtrLen sNoAuthScheme("none");
    static StrPtrLen sBasicAuthScheme("basic");
    static StrPtrLen sDigestAuthScheme("digest");
    
    // Get the auth scheme attribute
    StrPtrLen* theAuthScheme = this->GetValue(qtssPrefsAuthenticationScheme);
    
    if (theAuthScheme->Equal(sNoAuthScheme))
        fAuthScheme = qtssAuthNone;
    else if (theAuthScheme->Equal(sBasicAuthScheme))
        fAuthScheme = qtssAuthBasic;
    else if (theAuthScheme->Equal(sDigestAuthScheme))
        fAuthScheme = qtssAuthDigest;
}
Example #4
0
QTSS_Error HTTPRequest::ParseRequestLine(StringParser* parser)
{
    // Get the method - If the method is not one of the defined methods
    // then it doesn't return an error but sets fMethod to httpIllegalMethod
    StrPtrLen theParsedData;
    parser->ConsumeWord(&theParsedData);
    fMethod = HTTPProtocol::GetMethod(&theParsedData);

	//还有可能是HTTP Response类型
	if((fMethod == httpIllegalMethod) && theParsedData.Equal("HTTP"))
	{
		parser->ConsumeUntilWhitespace();//过滤掉HTTP/1.1
		parser->ConsumeUntilDigit(NULL);
		UInt32 statusCode = parser->ConsumeInteger(NULL);
		if( statusCode != 0 )
		{
			fHTTPType = httpResponseType;

			parser->ConsumeWhitespace();
			parser->ConsumeUntilWhitespace(NULL);
			// Go past the end of line
			if (!parser->ExpectEOL())
			{
				fStatusCode = httpBadRequest;
				return QTSS_BadArgument;     // Request line is not properly formatted!
			}
			return QTSS_NoErr;
		}
	} 
    // Consume whitespace
    parser->ConsumeWhitespace();
 

    // Parse the URI - If it fails returns an error after setting 
    // the fStatusCode to the appropriate error code
    QTSS_Error err = ParseURI(parser);
    if (err != QTSS_NoErr)
            return err;
  
    // Consume whitespace
    parser->ConsumeWhitespace();
  
    // If there is a version, consume the version string
    StrPtrLen versionStr;
    parser->ConsumeUntil(&versionStr, StringParser::sEOLMask);
    // Check the version
    if (versionStr.Len > 0)
            fVersion = HTTPProtocol::GetVersion(&versionStr);
  
    // Go past the end of line
    if (!parser->ExpectEOL())
    {
        fStatusCode = httpBadRequest;
        return QTSS_BadArgument;     // Request line is not properly formatted!
    }

    return QTSS_NoErr;
}
Example #5
0
inline Bool16 IsAdminRequest(StringParser *theFullRequestPtr)
{
    Bool16 handleRequest = false;
    if (theFullRequestPtr != NULL) do
    {
        StrPtrLen   strPtr;
        theFullRequestPtr->ConsumeWord(&strPtr);
        if ( !strPtr.Equal(StrPtrLen("GET")) ) break;   //it's a "Get" request
        
        theFullRequestPtr->ConsumeWhitespace();
        if ( !theFullRequestPtr->Expect('/') ) break;   
                
        theFullRequestPtr->ConsumeWord(&strPtr);
        if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("modules") )    ) break;
        if (!theFullRequestPtr->Expect('/') ) break;
            
        theFullRequestPtr->ConsumeWord(&strPtr);
        if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("admin") ) ) break;
        handleRequest = true;
        
    } while (false);

    return handleRequest;
}
Example #6
0
// Parse out the URL from the HTTP GET line.
Bool16 ParseURL(StrPtrLen& theRequest, char* outURL, UInt16 maxlen)
{
    StringParser reqParse(&theRequest);
    StrPtrLen strPtr;
    
    ::memset(outURL, 0, maxlen);
    reqParse.ConsumeWord(&strPtr);

    if ( !strPtr.Equal(StrPtrLen("GET")) )
    {
        return false;
    }
    reqParse.ConsumeWhitespace();
    reqParse.ConsumeUntilWhitespace(&strPtr);
    if (strPtr.Len == 0)
        return false;
    else if ((UInt16)strPtr.Len > maxlen-1)
        strPtr.Len = maxlen-1;
    ::memcpy(outURL, strPtr.Ptr, strPtr.Len);

    return true;
}
Example #7
0
QTSS_ModulePrefsObject QTSSModuleUtils::GetModuleObjectByName(const StrPtrLen& inModuleName)
{
    QTSS_ModuleObject theModule = NULL;
    UInt32 theLen = sizeof(theModule);
    
    for (int x = 0; QTSS_GetValue(sServer, qtssSvrModuleObjects, x, &theModule, &theLen) == QTSS_NoErr; x++)
    {
        Assert(theModule != NULL);
        Assert(theLen == sizeof(theModule));
        
        StrPtrLen theName;
        QTSS_Error theErr = QTSS_GetValuePtr(theModule, qtssModName, 0, (void**)(void*)&theName.Ptr, &theName.Len);
        Assert(theErr == QTSS_NoErr);
        
        if (inModuleName.Equal(theName))
            return theModule;
            
#if DEBUG
        theModule = NULL;
        theLen = sizeof(theModule);
#endif
    }
    return NULL;
}
Example #8
0
void SDPSourceInfo::Parse(char* sdpData, UInt32 sdpLen)
{
    //
    // There are some situations in which Parse can be called twice.
    // If that happens, just return and don't do anything the second time.
    if (fSDPData.Ptr != NULL)
        return;
        
    Assert(fStreamArray == NULL);
    
    char *sdpDataCopy = new char[sdpLen];
    Assert(sdpDataCopy != NULL);
    
    memcpy(sdpDataCopy,sdpData, sdpLen);
    fSDPData.Set(sdpDataCopy, sdpLen);

    // If there is no trackID information in this SDP, we make the track IDs start
    // at 1 -> N
    UInt32 currentTrack = 1;
    
    bool hasGlobalStreamInfo = false;
    StreamInfo theGlobalStreamInfo; //needed if there is one c= header independent of
                                    //individual streams

    StrPtrLen sdpLine;
    StringParser trackCounter(&fSDPData);
    StringParser sdpParser(&fSDPData);
    UInt32 theStreamIndex = 0;

    //walk through the SDP, counting up the number of tracks
    // Repeat until there's no more data in the SDP
    while (trackCounter.GetDataRemaining() > 0)
    {
        //each 'm' line in the SDP file corresponds to another track.
        trackCounter.GetThruEOL(&sdpLine);
        if ((sdpLine.Len > 0) && (sdpLine.Ptr[0] == 'm'))
            fNumStreams++;  
    }

    //We should scale the # of StreamInfos to the # of trax, but we can't because
    //of an annoying compiler bug...
    
    fStreamArray = new StreamInfo[fNumStreams];
	::memset(fStreamArray, 0, sizeof(StreamInfo) * fNumStreams);

    // set the default destination as our default IP address and set the default ttl
    theGlobalStreamInfo.fDestIPAddr = INADDR_ANY;
    theGlobalStreamInfo.fTimeToLive = kDefaultTTL;
        
    //Set bufferdelay to default of 3
    theGlobalStreamInfo.fBufferDelay = (Float32) eDefaultBufferDelay;
    
    //Now actually get all the data on all the streams
    while (sdpParser.GetDataRemaining() > 0)
    {
        sdpParser.GetThruEOL(&sdpLine);
        if (sdpLine.Len == 0)
            continue;//skip over any blank lines

        switch (*sdpLine.Ptr)
        {
            case 't':
            {
                StringParser mParser(&sdpLine);
                                
                mParser.ConsumeUntil(NULL, StringParser::sDigitMask);
                UInt32 ntpStart = mParser.ConsumeInteger(NULL);
                
                mParser.ConsumeUntil(NULL, StringParser::sDigitMask);               
                UInt32 ntpEnd = mParser.ConsumeInteger(NULL);
                
                SetActiveNTPTimes(ntpStart,ntpEnd);
            }
            break;
            
            case 'm':
            {
                if (hasGlobalStreamInfo)
                {
                    fStreamArray[theStreamIndex].fDestIPAddr = theGlobalStreamInfo.fDestIPAddr;
                    fStreamArray[theStreamIndex].fTimeToLive = theGlobalStreamInfo.fTimeToLive;
                }
                fStreamArray[theStreamIndex].fTrackID = currentTrack;
                currentTrack++;
                
                StringParser mParser(&sdpLine);
                
                //find out what type of track this is
                mParser.ConsumeLength(NULL, 2);//go past 'm='
                StrPtrLen theStreamType;
                mParser.ConsumeWord(&theStreamType);
                if (theStreamType.Equal(sVideoStr))
                    fStreamArray[theStreamIndex].fPayloadType = qtssVideoPayloadType;
                else if (theStreamType.Equal(sAudioStr))
                    fStreamArray[theStreamIndex].fPayloadType = qtssAudioPayloadType;
                    
                //find the port for this stream
                mParser.ConsumeUntil(NULL, StringParser::sDigitMask);
                SInt32 tempPort = mParser.ConsumeInteger(NULL);
                if ((tempPort > 0) && (tempPort < 65536))
                    fStreamArray[theStreamIndex].fPort = (UInt16) tempPort;
                    
                // find out whether this is TCP or UDP
                mParser.ConsumeWhitespace();
                StrPtrLen transportID;
                mParser.ConsumeWord(&transportID);
                
                static const StrPtrLen kTCPTransportStr("RTP/AVP/TCP");
                if (transportID.Equal(kTCPTransportStr))
                    fStreamArray[theStreamIndex].fIsTCP = true;
                    
                theStreamIndex++;
            }
            break;
            case 'a':
            {
                StringParser aParser(&sdpLine);

                aParser.ConsumeLength(NULL, 2);//go past 'a='

                StrPtrLen aLineType;

                aParser.ConsumeWord(&aLineType);



                if (aLineType.Equal(sBroadcastControlStr))

                {   // found a control line for the broadcast (delete at time or delete at end of broadcast/server startup) 

                    // qtss_printf("found =%s\n",sBroadcastControlStr);

                    aParser.ConsumeUntil(NULL,StringParser::sWordMask);

                    StrPtrLen sessionControlType;

                    aParser.ConsumeWord(&sessionControlType);

                    if (sessionControlType.Equal(sAutoDisconnect))
                    {
                       fSessionControlType = kRTSPSessionControl; 
                    }       
                    else if (sessionControlType.Equal(sAutoDisconnectTime))
                    {
                       fSessionControlType = kSDPTimeControl; 
                    }       
                    

                }

                //if we haven't even hit an 'm' line yet, just ignore all 'a' lines
                if (theStreamIndex == 0)
                    break;
                    
                if (aLineType.Equal(sRtpMapStr))
                {
                    //mark the codec type if this line has a codec name on it. If we already
                    //have a codec type for this track, just ignore this line
                    if ((fStreamArray[theStreamIndex - 1].fPayloadName.Len == 0) &&
                        (aParser.GetThru(NULL, ' ')))
                    {
                        StrPtrLen payloadNameFromParser;
                        (void)aParser.GetThruEOL(&payloadNameFromParser);
						char* temp = payloadNameFromParser.GetAsCString();
//                                                qtss_printf("payloadNameFromParser (%x) = %s\n", temp, temp);
                        (fStreamArray[theStreamIndex - 1].fPayloadName).Set(temp, payloadNameFromParser.Len);
//                                                qtss_printf("%s\n", fStreamArray[theStreamIndex - 1].fPayloadName.Ptr);
                    }
                }
                else if (aLineType.Equal(sControlStr))
                {           
					// Modify By EasyDarwin
					//if ((fStreamArray[theStreamIndex - 1].fTrackName.Len == 0) &&
     //                   (aParser.GetThru(NULL, ' ')))
					{
						StrPtrLen trackNameFromParser;
						aParser.ConsumeUntil(NULL,':');
						aParser.ConsumeLength(NULL,1);
						aParser.GetThruEOL(&trackNameFromParser);

						char* temp = trackNameFromParser.GetAsCString();
//                                                qtss_printf("trackNameFromParser (%x) = %s\n", temp, temp);
						(fStreamArray[theStreamIndex - 1].fTrackName).Set(temp, trackNameFromParser.Len);
//                                                qtss_printf("%s\n", fStreamArray[theStreamIndex - 1].fTrackName.Ptr);
					
						StringParser tParser(&trackNameFromParser);
						tParser.ConsumeUntil(NULL, '=');
						tParser.ConsumeUntil(NULL, StringParser::sDigitMask);
						fStreamArray[theStreamIndex - 1].fTrackID = tParser.ConsumeInteger(NULL);
					}
                }
                else if (aLineType.Equal(sBufferDelayStr))
                {   // if a BufferDelay is found then set all of the streams to the same buffer delay (it's global)
                    aParser.ConsumeUntil(NULL, StringParser::sDigitMask);
                    theGlobalStreamInfo.fBufferDelay = aParser.ConsumeFloat();
                }

            }
            break;
            case 'c':
            {
                //get the IP address off this header
                StringParser cParser(&sdpLine);
                cParser.ConsumeLength(NULL, 9);//strip off "c=in ip4 "
                UInt32 tempIPAddr = SDPSourceInfo::GetIPAddr(&cParser, '/');
                                
                //grab the ttl
                SInt32 tempTtl = kDefaultTTL;
                if (cParser.GetThru(NULL, '/'))
                {
                    tempTtl = cParser.ConsumeInteger(NULL);
                    Assert(tempTtl >= 0);
                    Assert(tempTtl < 65536);
                }

                if (theStreamIndex > 0)
                {
                    //if this c= line is part of a stream, it overrides the
                    //global stream information
                    fStreamArray[theStreamIndex - 1].fDestIPAddr = tempIPAddr;
                    fStreamArray[theStreamIndex - 1].fTimeToLive = (UInt16) tempTtl;
                } else {
                    theGlobalStreamInfo.fDestIPAddr = tempIPAddr;
                    theGlobalStreamInfo.fTimeToLive = (UInt16) tempTtl;
                    hasGlobalStreamInfo = true;
                }
            }
        }
    }       
    
    // Add the default buffer delay
    Float32 bufferDelay = (Float32) eDefaultBufferDelay;
    if (theGlobalStreamInfo.fBufferDelay != (Float32) eDefaultBufferDelay)
        bufferDelay = theGlobalStreamInfo.fBufferDelay;
    
    UInt32 count = 0;
    while (count < fNumStreams)
    {   fStreamArray[count].fBufferDelay = bufferDelay;
        count ++;
    }
        
}
Example #9
0
void AccessChecker::GetAccessFileInfo(const  char* inQTAccessDir)
{
	Assert( fAccessFile != NULL);

	const int kBufLen = 2048;
	char buf[kBufLen];
	StrPtrLen bufLine;
	::qtss_printf("QTSSDemoODAuthModule: File Info\n");
	while ( std::fgets(buf, kBufLen, fAccessFile) != NULL )
	{
		bufLine.Set(buf, strlen(buf));
		StringParser bufParser(&bufLine);

		//skip over leading whitespace
		bufParser.ConsumeUntil(NULL, StringParser::sWhitespaceMask);

		//skip over comments and blank lines...

		if ( (bufParser.GetDataRemaining() == 0) || (bufParser[0] == '#') || (bufParser[0] == '\0') )
			continue;

		StrPtrLen word;
		bufParser.ConsumeWord(&word);
		bufParser.ConsumeWhitespace();

		if ( word.Equal("AuthName") ) //realm name
		{
			bufParser.GetThruEOL(&word);
			fRealmHeader = word.Ptr;
		}
		else if ( word.Equal("AuthUserFile" ) ) //users name
		{
			char filePath[kBufLen];
			bufParser.GetThruEOL(&word); 
			if (word.Ptr[0] == '/') //absolute path
			{
				std::memcpy(filePath, word.Ptr, word.Len);
				filePath[word.Len] = '\0';
			}
			else
			{
				std::snprintf(filePath, sizeof(filePath), "%s/%s", inQTAccessDir, word.Ptr);
			}
			fUsersFile = std::fopen(filePath, "r");
		}
		else if ( word.Equal("AuthGroupFile") ) //groups name
		{
			char filePath[kBufLen];
			bufParser.GetThruEOL(&word); 
			if (word.Ptr[0] == '/') //absolute path
			{
				std::memcpy(filePath, word.Ptr, word.Len);
				filePath[word.Len] = '\0';
			}
			else
			{
				std::snprintf(filePath, sizeof(filePath), "%s/%s", inQTAccessDir, word.Ptr);
			}
			fGroupsFile = std::fopen(filePath, "r");
		}
	}

	if (fUsersFile == NULL)
	{
		fUsersFile = std::fopen(fUsersFilePath.c_str(), "r");
	}

	if (fGroupsFile == NULL)
	{
		fGroupsFile = std::fopen(fGroupsFilePath.c_str(), "r");
	}
}
Example #10
0
bool AccessChecker::CheckUserAccess(const char* inUsername)
{
	::qtss_printf("In QTSSDemoODAuthModule: Check User Access - start\n");

	const int kBufLen = 2048;
	char buf[kBufLen];
	StrPtrLen bufLine;

	if ( fAccessFile == NULL )
		return false;

	std::rewind(fAccessFile);
	while ( std::fgets(buf, kBufLen, fAccessFile) != NULL )
	{
		bufLine.Set(buf, strlen(buf));
		StringParser bufParser(&bufLine);

		//skip over leading whitespace
		bufParser.ConsumeUntil(NULL, StringParser::sWhitespaceMask);

		//skip over comments and blank lines...
		if ((bufParser.GetDataRemaining() == 0) || (bufParser[0] == '#') || (bufParser[0] == '\0') )
			continue;

		StrPtrLen word;
		bufParser.ConsumeWord(&word);
		if ( word.Equal("require") )
		{
			bufParser.ConsumeWhitespace();
			bufParser.ConsumeWord(&word);

			if ( word.Equal("user") )
			{
				while (word.Len != 0)
				{
					bufParser.ConsumeWhitespace();
					bufParser.ConsumeWord(&word);

					if (word.Equal(inUsername)) 
					{
						 ::qtss_printf("QTSSDemoODAuthModule in CheckUserAccess() : user %s found\n", inUsername);
						return true;
					}
				}
			}
			else if (word.Equal("valid-user"))
			{   
				::qtss_printf("QTSSDemoODAuthModule in CheckUserAccess(): valid-user\n");
				return true;
			}
			else if ( word.Equal("group") )
			{
				while (word.Len != 0)
				{
					bufParser.ConsumeWhitespace();
					bufParser.ConsumeWord(&word);
					if ( this->CheckGroupMembership(inUsername, word.GetAsCString()) )
					{
						::qtss_printf("QTSSDemoODAuthModule in CheckUserAccess(): user is part of %s group\n", word.GetAsCString());
						return true;
					}
				}
			}
		}
	}

	return false;
}
Example #11
0
// allocates memory for outUsersFilePath and outGroupsFilePath - remember to delete
// returns the auth scheme
QTSS_AuthScheme QTAccessFile::FindUsersAndGroupsFilesAndAuthScheme(char* inAccessFilePath, QTSS_ActionFlags inAction, char** outUsersFilePath, char** outGroupsFilePath)
{
    QTSS_AuthScheme authScheme = qtssAuthNone;
    QTSS_ActionFlags currentFlags = qtssActionFlagsRead;
    
    if (inAccessFilePath == NULL)
    return authScheme;
        
    *outUsersFilePath = NULL;
    *outGroupsFilePath = NULL;
    //Assert(outUsersFilePath == NULL);
    //Assert(outGroupsFilePath == NULL);
    
    StrPtrLen accessFileBuf;
    (void)QTSSModuleUtils::ReadEntireFile(inAccessFilePath, &accessFileBuf);
    OSCharArrayDeleter accessFileBufDeleter(accessFileBuf.Ptr);
    
    StringParser accessFileParser(&accessFileBuf);
    StrPtrLen line;
    StrPtrLen word;
    
    while( accessFileParser.GetDataRemaining() != 0 ) 
    {
        accessFileParser.GetThruEOL(&line);     // Read each line   
        StringParser lineParser(&line);
        lineParser.ConsumeWhitespace();         //skip over leading whitespace
        if (lineParser.GetDataRemaining() == 0)     // must be an empty line
            continue;

        char firstChar = lineParser.PeekFast();
        if ( (firstChar == '#') || (firstChar == '\0') )
            continue;               //skip over comments and blank lines...
        
        lineParser.ConsumeUntilWhitespace(&word);
               
        if ( word.Equal("<Limit") ) // a limit line
        {
            currentFlags = qtssActionFlagsNoFlags; // clear to no access
            lineParser.ConsumeWhitespace();
            lineParser.ConsumeUntil( &word, sWhitespaceAndGreaterThanMask); // the flag <limit Read> or <limit Read >
            while (word.Len != 0) // compare each word in the line
            {   
                if (word.Equal("WRITE")  ) 
                {   
                    currentFlags |= inAction & qtssActionFlagsWrite; // accept following lines if inFlags has write
                }
                    
                if (word.Equal("READ") ) 
                {   
                    currentFlags |= inAction & qtssActionFlagsRead; // accept following lines if inFlags has read
                }
                            
                lineParser.ConsumeWhitespace();
                lineParser.ConsumeUntil(&word, sWhitespaceAndGreaterThanMask);
            }
            continue; //done with limit line
        }
        
        if ( word.Equal("</Limit>") )
            currentFlags = qtssActionFlagsRead; // set the current access state to the default of read access
        
        if (0 == (currentFlags & inAction))
            continue; // ignore lines because inFlags doesn't match the current access state
            
        if (word.Equal("AuthUserFile") )
        {
            lineParser.ConsumeWhitespace();
            lineParser.GetThruEOL(&word);
            StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.
    
            if(*outUsersFilePath != NULL)       // we are encountering the AuthUserFile keyword twice!
                delete[] *outUsersFilePath; // The last one found takes precedence...delete the previous path
            
            *outUsersFilePath = word.GetAsCString();
            continue;
        }
        
        if (word.Equal("AuthGroupFile") )
        {
            lineParser.ConsumeWhitespace();
            lineParser.GetThruEOL(&word);
            StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.

            if(*outGroupsFilePath != NULL)      // we are encountering the AuthGroupFile keyword twice!
                delete[] *outGroupsFilePath;    // The last one found takes precedence...delete the previous path       
            
            *outGroupsFilePath = word.GetAsCString();
            
            continue;
        }
        
        if (word.Equal("AuthScheme") )
        {
            lineParser.ConsumeWhitespace();
            lineParser.GetThruEOL(&word);
            StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.

            if (word.Equal("basic"))
                authScheme = qtssAuthBasic;
            else if (word.Equal("digest"))
                authScheme = qtssAuthDigest;
                
            continue;
        }
    }
    
    return authScheme;
}
Example #12
0
Bool16 QTAccessFile::AccessAllowed  (   char *userName, char**groupArray, UInt32 numGroups, StrPtrLen *accessFileBufPtr,
                                        QTSS_ActionFlags inFlags,StrPtrLen* ioRealmNameStr, Bool16 *outAllowAnyUserPtr, void *extraDataPtr
                                    )
{       
    if (NULL == accessFileBufPtr || NULL == accessFileBufPtr->Ptr || 0 == accessFileBufPtr->Len)
        return true; // nothing to check
        
    if (ioRealmNameStr != NULL && ioRealmNameStr->Ptr != NULL && ioRealmNameStr->Len > 0)
        ioRealmNameStr->Ptr[0] = 0;
        
    StringParser            accessFileParser(accessFileBufPtr);
    QTSS_ActionFlags        currentFlags = qtssActionFlagsRead; 
    StrPtrLen               line;
    StrPtrLen               word;
    Bool16                  haveUserName = false;
    Bool16                  haveRealmResultBuffer = false;
    Bool16                  haveGroups = false;
    
    *outAllowAnyUserPtr = false;
        
    haveUserName = HaveUser(userName, extraDataPtr);
  
    haveGroups = HaveGroups(groupArray, numGroups, extraDataPtr);

    haveRealmResultBuffer =  HaveRealm(userName, ioRealmNameStr, extraDataPtr );
  
    while( accessFileParser.GetDataRemaining() != 0 ) 
    {
        accessFileParser.GetThruEOL(&line);  // Read each line  
        StringParser lineParser(&line);
        lineParser.ConsumeWhitespace();//skip over leading whitespace
        if (lineParser.GetDataRemaining() == 0) // must be an empty line
            continue;

        char firstChar = lineParser.PeekFast();
        if ( (firstChar == '#') || (firstChar == '\0') )
            continue; //skip over comments and blank lines...
        
        lineParser.ConsumeUntilWhitespace(&word);
        if ( word.Equal("<Limit") ) // a limit line
        {
            currentFlags = qtssActionFlagsNoFlags; // clear to no access
            lineParser.ConsumeWhitespace();
            lineParser.ConsumeUntil( &word, sWhitespaceAndGreaterThanMask); // the flag <limit Read> or <limit Read >
            while (word.Len != 0) // compare each word in the line
            {   
                if (word.Equal("WRITE")  ) 
                {   currentFlags |= inFlags & qtssActionFlagsWrite; // accept following lines if inFlags has write
                }
                
                if (word.Equal("READ") ) 
                {   currentFlags |= inFlags & qtssActionFlagsRead; // accept following lines if inFlags has read
                }
                lineParser.ConsumeWhitespace();
                lineParser.ConsumeUntil(&word, sWhitespaceAndGreaterThanMask);
            }
            continue; //done with limit line
        }
        if ( word.Equal("</Limit>") )
            currentFlags = qtssActionFlagsRead; // set the current access state to the default of read access
        
        if (0 == (currentFlags & inFlags))
            continue; // ignore lines because inFlags doesn't match the current access state
            
        if (haveRealmResultBuffer && word.Equal("AuthName") ) //realm name
        {   
            lineParser.ConsumeWhitespace();
            lineParser.GetThruEOL(&word);
            StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.
            
            GetRealm(&word, ioRealmNameStr, userName, extraDataPtr );

            // we don't change the buffer len ioRealmNameStr->Len because we might have another AuthName tag to copy
            continue; // done with AuthName (realm)
        }
        
        
        if (word.Equal("require") )
        {
            lineParser.ConsumeWhitespace();
            lineParser.ConsumeUntilWhitespace(&word);       

            if (haveUserName && word.Equal("valid-user") ) 
            {   return true; 
            }
            
            if ( word.Equal("any-user")  ) 
            {   
                *outAllowAnyUserPtr = true;
                return true; 
            }
    
            if (!haveUserName)
                continue;
                
            if (word.Equal("user") )
            {   
                lineParser.ConsumeWhitespace();
                lineParser.ConsumeUntilWhitespace(&word);   
                    
                while (word.Len != 0) // compare each word in the line
                {   
                    if (TestUser(&word, userName, extraDataPtr ))
                        return true;

                    lineParser.ConsumeWhitespace();
                    lineParser.ConsumeUntilWhitespace(&word);       
                }
                continue; // done with "require user" line
            }
            
            if (haveGroups && word.Equal("group")) // check if we have groups for the user
            {
                lineParser.ConsumeWhitespace();
                lineParser.ConsumeUntilWhitespace(&word);       
                
                while (word.Len != 0) // compare each word in the line
                {   
                    if (TestGroup(&word, userName, groupArray, numGroups, extraDataPtr) )
                        return true;

                    lineParser.ConsumeWhitespace();
                    lineParser.ConsumeUntilWhitespace(&word);
                }
                continue; // done with "require group" line
            }
            
            if (TestExtraData(&word, &lineParser, extraDataPtr))
                return true;
                
                    
            continue; // done with unparsed "require" line
        }
        
    }
    
    return false; // user or group not found
}
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams)
{
#if HTTP_FILE_DEBUGGING
    qtss_printf("FilterRequest\n");
#endif

    static Bool16 sFalse = false;

    QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;
    
    // Initial state.   
    StrPtrLen theFullRequest;
    StrPtrLen reqMethod;
    StrPtrLen reqStr;
    StrPtrLen httpVersion;
    
    (void)QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);
    StringParser fullRequest(&theFullRequest);

    // Parsing the HTTP request
    fullRequest.ConsumeWord(&reqMethod);
    if ( !(reqMethod.Equal(StrPtrLen("GET")) || reqMethod.Equal(StrPtrLen("HEAD"))) )
        // It's not a "Get" or a "Head" request 
        return QTSS_NoErr;
     
    fullRequest.ConsumeWhitespace();
    if ( !fullRequest.Expect('/') )
        // Improperly formed request
        return QTSS_NoErr;
            
    fullRequest.ConsumeUntil(&reqStr, StringParser::sEOLWhitespaceMask);
    if( reqStr.Len == 0 )
        //if a file or directory name is not given, return
        return QTSS_NoErr;
        
    if ( !reqStr.Equal(StrPtrLen("Popular.smil")) )
        return QTSS_NoErr;
    
    // If it's a "Head" request send the Head response header back and just return
    if ( reqMethod.Equal(StrPtrLen("HEAD")) )
    {
        QTSS_Write(theRequest, sResponseHeader, ::strlen(sResponseHeader), NULL, 0);    
        return QTSS_NoErr;
    }

    // Create a buffer to store data.
    char theFileBuffer[8192];
    char contentLength[256];
        
    // Before sending any response, set keep alive to off for this connection
    // Regardless of what the client sends, the server always closes the connection after sending the file
    (void)QTSS_SetValue(theRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));
    
#if HTTP_FILE_DEBUGGING
    qtss_printf("Creating a smil file\n");   
#endif
    // Create a ref movie buffer for the single file. It is of the form:
    //  rtsptext\r
    //  rtsp://servername/filepath
    char smilFileBuf[8192] = {0};

    GenerateHotHitSMIL(smilFileBuf);
                
    qtss_sprintf(contentLength, "%lu", strlen(smilFileBuf));
    // Allocate memory for theFileBuffer
    // Write the HTTP header prefix into the buffer
    ::strcpy(theFileBuffer, sRespHeaderPrefix.Ptr);
    ::strcat(theFileBuffer, sContentLengthHeaderTag.Ptr);
    // Write the remaining part of the HTTP header into the file buffer
    ::strcat(theFileBuffer, contentLength);
    ::strcat(theFileBuffer, sContentTypeHeaderTag.Ptr);
    ::strcat(theFileBuffer, sSmilMimeType.Ptr);
    ::strcat(theFileBuffer, "\r\n\r\n");
    
    // Write the smil file created above to the file buffer
    ::strcat(theFileBuffer, smilFileBuf);
    
    // Write the contents of the file buffer to the request stream and return
    QTSS_Write(theRequest, theFileBuffer, strlen(theFileBuffer), NULL, 0);
    
#if HTTP_FILE_DEBUGGING
    qtss_printf("Wrote the smil file to the request stream. Successful!\n"); 
#endif

    return QTSS_NoErr;
}
Example #14
0
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams)
{
    UInt8 sParamStopMask[] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-9      //stop unless a '\t', ' ', or '&'
        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, 0, 0, 0, 0, 0, 0, 1, 0, //30-39   
        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, 1             //250-255
    };


    //check to see if we should handle this request. Invokation is triggered
    //by a "GET /" request
    
    QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;
    
    StrPtrLen theFullRequest;
    (void)QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);

    StringParser fullRequest(&theFullRequest);
    
    StrPtrLen   strPtr;
    StrPtrLen   paramName;
    StrPtrLen   fieldsList;
    
    fullRequest.ConsumeWord(&strPtr);
    if ( strPtr.Equal(StrPtrLen("GET")) )   //it's a "Get" request
    {
        fullRequest.ConsumeWhitespace();
        if ( fullRequest.Expect('/') )
        {
            UInt32  refreshInterval = 0;
            Bool16  displayHelp = false;
            
            
            OSCharArrayDeleter theWebStatsURL(GetPrefAsString(sPrefs, sDefaultURLPrefName));
            StrPtrLen theWebStatsURLPtr(theWebStatsURL.GetObject());
            
            // If there isn't any web stats URL, we can just return at this point
            if (theWebStatsURLPtr.Len == 0)
                return QTSS_NoErr;
                
            fullRequest.ConsumeUntil(&strPtr, StringParser::sEOLWhitespaceQueryMask);
            if ( strPtr.Len != 0 && strPtr.Equal(theWebStatsURLPtr) )   //it's a "stats" request
            {
                if ( fullRequest.Expect('?') )
                {
                    do {
                        fullRequest.ConsumeWord(&paramName);
                        
                        if( paramName.Len != 0)
                        {
                            
                            if ( paramName.Equal(StrPtrLen("refresh",strlen("refresh"))) )
                            {
                                if (fullRequest.Expect('='))
                                    refreshInterval  = fullRequest.ConsumeInteger(NULL);
                            }
                            else if ( paramName.Equal(StrPtrLen("help",strlen("help"))) )
                            {
                                displayHelp = true;
                            }
                            else if ( paramName.Equal(StrPtrLen("fields",strlen("fields"))) )
                            {
                                if (fullRequest.Expect('='))
                                    fullRequest.ConsumeUntil(&fieldsList, (UInt8*)sParamStopMask);
                                
                            }
                        }
                    } while ( paramName.Len != 0 && fullRequest.Expect('&') );
                }
                
                // Before sending a response, set keep alive to off for this connection
                (void)QTSS_SetValue(theRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));
                SendStats(inParams->inRTSPRequest, refreshInterval, displayHelp, (fieldsList.Len != 0) ? &fieldsList : NULL);
            }
        }
    }
    return QTSS_NoErr;
}
Example #15
0
char* SDPSourceInfo::GetLocalSDP(UInt32* newSDPLen)
{
    Assert(fSDPData.Ptr != NULL);

    bool appendCLine = true;
    UInt32 trackIndex = 0;
    
    char *localSDP = new char[fSDPData.Len * 2];
    OSCharArrayDeleter charArrayPathDeleter(localSDP);
    StringFormatter localSDPFormatter(localSDP, fSDPData.Len * 2);

    StrPtrLen sdpLine;
    StringParser sdpParser(&fSDPData);
    char trackIndexBuffer[50];
    
    // Only generate our own trackIDs if this file doesn't have 'em.
    // Our assumption here is that either the file has them, or it doesn't.
    // A file with some trackIDs, and some not, won't work.
    bool hasControlLine = false;

    while (sdpParser.GetDataRemaining() > 0)
    {
        //stop when we reach an empty line.
        sdpParser.GetThruEOL(&sdpLine);
        if (sdpLine.Len == 0)
            continue;
            
        switch (*sdpLine.Ptr)
        {
            case 'c':
                break;//ignore connection information
            case 'm':
            {
                //append new connection information right before the first 'm'
                if (appendCLine)
                {
                    localSDPFormatter.Put(sCLine);
                    localSDPFormatter.PutEOL();
                   
                    if (!hasControlLine)
                    { 
                      localSDPFormatter.Put(sControlLine);
                      localSDPFormatter.PutEOL();
                    }
                    
                    appendCLine = false;
                }
                //the last "a=" for each m should be the control a=
                if ((trackIndex > 0) && (!hasControlLine))
                {
                    qtss_sprintf(trackIndexBuffer, "a=control:trackID=%" _S32BITARG_ "\r\n",trackIndex);
                    localSDPFormatter.Put(trackIndexBuffer, ::strlen(trackIndexBuffer));
                }
                //now write the 'm' line, but strip off the port information
                StringParser mParser(&sdpLine);
                StrPtrLen mPrefix;
                mParser.ConsumeUntil(&mPrefix, StringParser::sDigitMask);
                localSDPFormatter.Put(mPrefix);
                localSDPFormatter.Put("0", 1);
                (void)mParser.ConsumeInteger(NULL);
                localSDPFormatter.Put(mParser.GetCurrentPosition(), mParser.GetDataRemaining());
                localSDPFormatter.PutEOL();
                trackIndex++;
                break;
            }
            case 'a':
            {
                StringParser aParser(&sdpLine);
                aParser.ConsumeLength(NULL, 2);//go past 'a='
                StrPtrLen aLineType;
                aParser.ConsumeWord(&aLineType);
                if (aLineType.Equal(sControlStr))
                {
                    aParser.ConsumeUntil(NULL, '=');
                    aParser.ConsumeUntil(NULL, StringParser::sDigitMask);
                    
                   StrPtrLen aDigitType;                
                   (void)aParser.ConsumeInteger(&aDigitType);
                    if (aDigitType.Len > 0)
                    {
                      localSDPFormatter.Put("a=control:trackID=", 18);
                      localSDPFormatter.Put(aDigitType);
                      localSDPFormatter.PutEOL();
                      hasControlLine = true;
                      break;
                    }
                }
               
                localSDPFormatter.Put(sdpLine);
                localSDPFormatter.PutEOL();
                break;
            }
            default:
            {
                localSDPFormatter.Put(sdpLine);
                localSDPFormatter.PutEOL();
            }
        }
    }
    
    if ((trackIndex > 0) && (!hasControlLine))
    {
        qtss_sprintf(trackIndexBuffer, "a=control:trackID=%" _S32BITARG_ "\r\n",trackIndex);
        localSDPFormatter.Put(trackIndexBuffer, ::strlen(trackIndexBuffer));
    }
    *newSDPLen = (UInt32)localSDPFormatter.GetCurrentOffset();
    
    StrPtrLen theSDPStr(localSDP, *newSDPLen);//localSDP is not 0 terminated so initialize theSDPStr with the len.
    SDPContainer rawSDPContainer; 
    (void) rawSDPContainer.SetSDPBuffer( &theSDPStr );    
    SDPLineSorter sortedSDP(&rawSDPContainer);

    return sortedSDP.GetSortedSDPCopy(); // return a new copy of the sorted SDP
}
Example #16
0
void SendStats(QTSS_StreamRef inStream, UInt32  refreshInterval, Bool16 displayHelp, StrPtrLen* fieldList)
{
    struct FieldIndex {
        char*   fieldName;
        int fieldIndex;
    };
    
    const FieldIndex kFieldIndexes[] = {
                                    {"title", 1},
                                    {"dnsname", 2},
                                    {"curtime", 3},
                                    {"", 4},
                                    {"serververs", 5},
                                    {"serverbornon", 6},
                                    {"serverstatus", 7},
                                    {"", 8},
                                    {"", 9},
                                    {"", 10},
                                    {"", 11},
                                    {"", 12},
                                    {"", 13},
                                    {"currtp", 14},
                                    {"currtsp", 15},
                                    {"currtsphttp", 16},
                                    {"curthru", 17},
                                    {"curpkts", 18},
                                    {"totbytes", 19},
                                    {"totconns", 20},
                                    {"", 21},
                                    {"connlimit", 22},
                                    {"thrulimit", 23},
                                    {"moviedir", 24},
                                    {"rtspip", 25},
                                    {"rtspport", 26},
                                    {"rtsptimeout", 27},
                                    {"rtptimeout", 28},
                                    {"secstobuffer", 29},
                                    {"", 30},
                                    {"accesslog", 31},
                                    {"accesslogdir",32},
                                    {"accesslogname", 33},
                                    {"accessrollsize", 34},
                                    {"accessrollinterval", 35},
                                    {"", 36},
                                    {"errorlog", 37},
                                    {"errorlogdir", 38},
                                    {"errorlogname", 39},
                                    {"errorrollsize", 40},
                                    {"errorrollinterval", 41},
                                    {"errorloglevel", 42},
                                    {"", 43},
                                    {"assertbreak", 44},
                                    {"autostart", 45},
                                    {"totbytesupdateinterval", 46},
                                    {"reflectordelay", 47},
                                    {"reflectorbucketsize", 48},
                                    {"historyinterval", 49},
                                    {"outoffiledesc", 50},
                                    {"numudpsockets", 51},
                                    {"apiversion", 52},
                                    {"numreliableudpbuffers", 53},
                                    {"reliableudpwastedbytes", 54},
                                    {"numtaskthreads", 55}
    };
    const int kMaxFieldNum = 55;
    static char* kEmptyStr = "?";
    char* thePrefStr = kEmptyStr;

    char buffer[1024];

    (void)QTSS_Write(inStream, sResponseHeader, ::strlen(sResponseHeader), NULL, 0);

    if (refreshInterval > 0)
    {
        qtss_sprintf(buffer, "<META HTTP-EQUIV=Refresh CONTENT=%"_U32BITARG_">\n", refreshInterval);
        (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
    }
        
    //qtss_sprintf(buffer, "<body text=\"#000000\" bgcolor=\"#C0C0C0\" link=\"#0000FF\" vlink=\"#551A8B\" alink=\"#0000FF\">\n");
    //(void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
    
    char *theHTML =  "<HTML><BODY>\n";
    
    (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0);
    
    if (displayHelp)
    {
    
    #ifndef __MacOSX__
        static StrPtrLen sHelpLine1("<P><b>Streaming Server Statistics Help</b></P>\n");
    #else
        static StrPtrLen sHelpLine1("<P><b>QuickTime Streaming Server Statistics Help</b></P>\n");
    #endif

        static StrPtrLen sHelpLine2("<P>Example:</P>\n");
        static StrPtrLen sHelpLine3("<BLOCKQUOTE><P>http://server/statsURL?help&amp;refresh=15&amp;fields=curtime,cpuload </P>\n");

        static StrPtrLen sHelpLine4("\"?\" means that there are options being attached to the stats request.<BR>\n");
        static StrPtrLen sHelpLine5("\"&amp;\" separates multiple stats options<BR>\n<BR>\n");

        static StrPtrLen sHelpLine6("<P>The three possible parameters to stats are:</P>\n");
        static StrPtrLen sHelpLine7("<P>\"help\"  -- shows the help information you're reading right now.</P>\n");
        static StrPtrLen sHelpLine8("<P>\"refresh=&#91;n&#93;\"  -- tells the browser to automatically update the page every &#91;n&#93; seconds.</P>\n");
        static StrPtrLen sHelpLine9("<P>\"fields=&#91;fieldList&#93;\"  -- show only the fields specified in comma delimited &#91;fieldList&#93;</P>\n");
        static StrPtrLen sHelpLine10("<BLOCKQUOTE>The following fields are available for use with the \"fields\" option:</P><BLOCKQUOTE><DL>\n");
        
        (void)QTSS_Write(inStream, sHelpLine1.Ptr, sHelpLine1.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine2.Ptr, sHelpLine2.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine3.Ptr, sHelpLine3.Len, NULL, 0);

        (void)QTSS_Write(inStream, sHelpLine4.Ptr, sHelpLine4.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine5.Ptr, sHelpLine5.Len, NULL, 0);

        (void)QTSS_Write(inStream, sHelpLine6.Ptr, sHelpLine6.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine7.Ptr, sHelpLine7.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine8.Ptr, sHelpLine8.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine9.Ptr, sHelpLine9.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine10.Ptr, sHelpLine10.Len, NULL, 0);      
    
        for (short i = 0; i < kMaxFieldNum; i++)
        {
                qtss_sprintf(buffer, "<DT><I>%s</I></DT>\n", kFieldIndexes[i].fieldName);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
        }
        
        static StrPtrLen sHelpLine11("</DL></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE><BR><P><HR>");
        (void)QTSS_Write(inStream, sHelpLine11.Ptr, sHelpLine11.Len, NULL, 0);      
    }

    StringParser fieldNamesParser(fieldList);
    StrPtrLen fieldName;
    int fieldNum = 0;
    do
    {
    
            
        if (fieldList != NULL)
        {
            fieldNum = 0;
            
            fieldNamesParser.ConsumeWord(&fieldName);
            
            for (short i = 0; i < kMaxFieldNum; i++)
            {
                if ( fieldName.Equal(StrPtrLen(kFieldIndexes[i].fieldName, ::strlen(kFieldIndexes[i].fieldName))) )
                {
                    fieldNum = kFieldIndexes[i].fieldIndex;
                    break;
                }
            }
        }
        else
        {
            fieldNum++;
            if ( fieldNum > kMaxFieldNum )
                fieldNum = 0;
        }

        UInt32 theLen = 0;
        
        switch (fieldNum)
        {
            case 1:
            {
#if __MacOSX__
                    static StrPtrLen sStatsLine1("<TITLE>QuickTime Streaming Server Stats</TITLE><BR>\n");
                    (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0);      
#else
                    static StrPtrLen sStatsLine1("<TITLE>Streaming Server Stats</TITLE><BR>\n");
                    (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0);      
#endif
                    
#if __MacOSX__
                    static StrPtrLen sStatsLine2("<center><h1>QuickTime Streaming Server Statistics</h1></center>\n");
                    (void)QTSS_Write(inStream, sStatsLine2.Ptr, sStatsLine2.Len, NULL, 0);      
#else
                    static StrPtrLen sStatsLine2("<center><h1>Streaming Server Statistics</h1></center>\n");
                    (void)QTSS_Write(inStream, sStatsLine2.Ptr, sStatsLine2.Len, NULL, 0);      
#endif
            }
            break;
        
            case 2:
            {
                StrPtrLen theDNS;
                (void)QTSS_GetValuePtr(sServer, qtssSvrDefaultDNSName, 0, (void**)&theDNS.Ptr, &theDNS.Len);
                
                if ( theDNS.Ptr == NULL )
                {   // no DNS, try for the IP address only.
                    (void)QTSS_GetValuePtr(sServer, qtssSvrDefaultIPAddr, 0, (void**)&theDNS.Ptr, &theDNS.Len);
                    
                }
                
                if ( theDNS.Ptr != NULL )
                {
                    qtss_sprintf(buffer, "<b>DNS Name (default): </b> %s<BR>\n", theDNS.Ptr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
            
            case 3:
            {
                char uptimebuffer[1024];
                time_t curTime = ::time(NULL); 
                qtss_sprintf(uptimebuffer, "<b>Current Time: </b> %s<BR>\n", qtss_ctime(&curTime, buffer, sizeof(buffer)));
                (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0);    
                
                time_t upTime = curTime - sStartupTime;
                #define kDaySeconds  (24 * 60 * 60)
                #define kHourSeconds  (60 * 60)
                #define kMinuteSeconds 60

                UInt32 upTimeDays = upTime / kDaySeconds;
                UInt32 upTimeHours = (upTime % kDaySeconds) / kHourSeconds;
                UInt32 upTimeMinutes = (upTime % kHourSeconds) / kMinuteSeconds;
                UInt32 upTimeSeconds = (upTime % kMinuteSeconds);
                qtss_snprintf(uptimebuffer,sizeof(uptimebuffer), "<b>Up Time Total Seconds: </b> %"_U32BITARG_"<BR>\n", upTime);
                uptimebuffer[sizeof(uptimebuffer) -1] = 0;
                (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0);    
                       
                qtss_snprintf(uptimebuffer,sizeof(uptimebuffer), "<b>Up Time: </b> %"_U32BITARG_" days %"_U32BITARG_" hours %"_U32BITARG_" minutes %"_U32BITARG_" seconds <BR>\n", upTimeDays, upTimeHours,upTimeMinutes, upTimeSeconds);
                uptimebuffer[sizeof(uptimebuffer) -1] = 0;
                (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0);    
            }
            break;
            
            case 4:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 5:
            {
                StrPtrLen theVersion;
                (void)QTSS_GetValuePtr(sServer, qtssSvrRTSPServerHeader, 0, (void**)&theVersion.Ptr, &theVersion.Len);
                Assert(theVersion.Ptr != NULL);
                if (theVersion.Len > 7) //Skip the "Server:" text
                   theVersion.Ptr += 7;
                qtss_sprintf(buffer, "<b>Server Version: </b>%s<BR>\n", theVersion.Ptr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 6:
            {
                StrPtrLen theBuildDate;
                (void)QTSS_GetValuePtr(sServer, qtssSvrServerBuildDate, 0, (void**)&theBuildDate.Ptr, &theBuildDate.Len);
                Assert(theBuildDate.Ptr != NULL);
                qtss_sprintf(buffer, "<b>Server Build Date: </b> %s<BR>\n", theBuildDate.Ptr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 7:
            {
                char statusBuffer[1024];
                const char* states[]    = { "Starting Up",
                                            "Running",
                                            "Refusing Connections",
                                            "Fatal Error",
                                            "Shutting Down"
                                          };
                QTSS_ServerState theState = qtssRunningState;
                theLen = sizeof(theState);
                (void)QTSS_GetValue(sServer, qtssSvrState, 0, &theState, &theLen);

                if (theState == qtssRunningState)
                {	qtss_snprintf(statusBuffer, sizeof(statusBuffer), "<b>Status: </b> %s since %s<BR>", states[theState], qtss_ctime(&sStartupTime,buffer,sizeof(buffer)));
                }
                else
                    qtss_snprintf(statusBuffer,sizeof(statusBuffer), "<b>Status: </b> %s<BR>", states[theState]);
                (void)QTSS_Write(inStream, statusBuffer, ::strlen(statusBuffer), NULL, 0);      
            }
            break;
            
            case 8:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 9:
            {
                
                //NOOP
            }
            break;
            
            case 10:
            {
                
                //NOOP
            }
            break;
    
            case 11:
            {
                
                //NOOP
            }
            break;
    
            case 12:
            {       
            /*  
                struct vm_statistics vmStats = {};
                if (vm_statistics (current_task (), &vmStats) != KERN_SUCCESS)
                    memset (&stats, '\0', sizeof (vmStats)) ;
            */
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
            
            case 13:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
                
            //**********************************



    
            case 14:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurConn, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current RTP Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 15:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTSPCurrentSessionCount, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current RTSP Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 16:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTSPHTTPCurrentSessionCount, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current RTSP over HTTP Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 17:
            {
                UInt32 curBandwidth = 0;
                theLen = sizeof(curBandwidth);
                (void)QTSS_GetValue(sServer, qtssRTPSvrCurBandwidth, 0, &curBandwidth, &theLen);

                qtss_sprintf(buffer, "<b>Current Throughput: </b> %"_U32BITARG_" kbits<BR>\n", curBandwidth/1024);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 18:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurPackets, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current Packets Per Second: </b> %s <BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 19:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalBytes, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Total Bytes Served: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 20:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalConn, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Total Connections: </b> %s<BR>", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
            
            case 21:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            //**************************************
            case 22:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumConnections, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Maximum Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 23:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumBandwidth, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Maximum Throughput: </b> %s Kbits<BR>\n",thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 24:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMovieFolder, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Movie Folder Path: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 25:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPIPAddr, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>RTSP IP Address: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 26:
            {
                static StrPtrLen sRTSPPortsStart("<b>RTSP Ports: </b> ");
                (void)QTSS_Write(inStream, sRTSPPortsStart.Ptr, sRTSPPortsStart.Len, NULL, 0);      

                StrPtrLen thePort;
                for (UInt32 theIndex = 0; true; theIndex++)
                {
                    QTSS_Error theErr = QTSS_GetValuePtr(sServer, qtssSvrRTSPPorts, theIndex, (void**)&thePort.Ptr, &thePort.Len);
                    if (theErr != QTSS_NoErr)
                        break;

                    Assert(thePort.Ptr != NULL);
                    char temp[20];
                    qtss_sprintf(temp, "%u ", *(UInt16*)thePort.Ptr);
                    (void)QTSS_Write(inStream, temp, ::strlen(temp), NULL, 0);      
                }
                
                static StrPtrLen sRTSPPortsEnd("<BR>\n");
                (void)QTSS_Write(inStream, sRTSPPortsEnd.Ptr, sRTSPPortsEnd.Len, NULL, 0);      
            }
            break;
    
            case 27:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPTimeout, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>RTP Timeout: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 28:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTPTimeout, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>RTP Timeout: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 29:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 30:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 31:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logging");
                    qtss_sprintf(buffer, "<b>Access Logging: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 32:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_dir");
                    qtss_sprintf(buffer, "<b>Access Log Directory: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 33:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_name");
                    qtss_sprintf(buffer, "<b>Access Log Name: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 34:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_size");
                    qtss_sprintf(buffer, "<b>Access Log Roll Size: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 35:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_interval");
                    qtss_sprintf(buffer, "<b>Access Log Roll Interval (days): </b> %s<BR>", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
            
            case 36:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 37:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogEnabled, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Logging: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 38:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogDir, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Directory: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 39:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogName, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Name: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 40:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaxErrorLogSize, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Roll Size: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 41:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorRollInterval, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Roll Interval (days): </b> %s<BR>\n",thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 42:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogVerbosity, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Verbosity: </b> %s<BR>", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
            
            case 43:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 44:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsBreakOnAssert, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Break On Assert: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 45:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsAutoRestart, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>AutoStart: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 46:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsTotalBytesUpdate, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Total Bytes Update Interval: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 47:
            {
                if (sReflectorPrefs != NULL)
                {
                    thePrefStr = GetPrefAsString(sReflectorPrefs, "reflector_delay");
                    qtss_sprintf(buffer, "<b>Reflector Delay Time: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 48:
            {
                if (sReflectorPrefs != NULL)
                {
                    thePrefStr = GetPrefAsString(sReflectorPrefs, "reflector_bucket_size");
                    qtss_sprintf(buffer, "<b>Reflector Bucket Size: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 49:
            {
                if ( sSvrControlPrefs != NULL)
                {
                    thePrefStr = GetPrefAsString(sSvrControlPrefs, "history_update_interval");
                    qtss_sprintf(buffer, "<b>History Update Interval: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }       
            }
            break;
    
            case 50:
            {
                Bool16 isOutOfDescriptors = false;
                theLen = sizeof(isOutOfDescriptors);
                (void)QTSS_GetValue(sServer, qtssSvrIsOutOfDescriptors, 0, &isOutOfDescriptors, &theLen);

                qtss_sprintf(buffer, "<b>Out of file descriptors: </b> %d<BR>\n", isOutOfDescriptors);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 51:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrNumUDPSockets, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Number of UDP sockets: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 52:
            {
                UInt32 apiVersion = 0;
                UInt32 size = sizeof(UInt32);
                (void)QTSS_GetValue(sServer, qtssServerAPIVersion, 0, &apiVersion, &size);
                qtss_sprintf(buffer, "<b>API version: </b> %d.%d<BR>\n", (int)( (UInt32) (apiVersion & (UInt32) 0xFFFF0000L) >> 16), (int)(apiVersion &(UInt32) 0x0000FFFFL));
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;

            case 53:
            {
                UInt32 reliableUDPBuffers = 0;
                UInt32 blahSize = sizeof(reliableUDPBuffers);
                (void)QTSS_GetValue(sServer, qtssSvrNumReliableUDPBuffers, 0, &reliableUDPBuffers, &blahSize);
                qtss_sprintf(buffer, "<b>Num Reliable UDP Retransmit Buffers: </b> %"_U32BITARG_"<BR>\n", reliableUDPBuffers);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;

            case 54:
            {
                UInt32 wastedBufSpace = 0;
                UInt32 blahSize2 = sizeof(wastedBufSpace);
                (void)QTSS_GetValue(sServer, qtssSvrReliableUDPWastageInBytes, 0, &wastedBufSpace, &blahSize2);
                qtss_sprintf(buffer, "<b>Amount of buffer space being wasted in UDP Retrans buffers: </b> %"_U32BITARG_"<BR>\n", wastedBufSpace);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
            
            case 55:
            {
                (void)QTSS_GetValueAsString(sServer, qtssSvrNumThreads, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Number of Task Threads: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
             
            
    
            default:        
                break;
    
                
        } //switch fieldNum
            
            
        if (fieldList != NULL && !fieldNamesParser.Expect(','))
            fieldNum = 0;
            
        if (thePrefStr != kEmptyStr)
            delete [] thePrefStr; 
            
        thePrefStr = kEmptyStr;
            
    } while (fieldNum != 0);
    
    theHTML = "</BODY></HTML>\n";
    (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0);        
}
Example #17
0
bool XMLTag::ParseTag(StringParser* parser, DTDVerifier* verifier, char* errorBuffer, int errorBufferSize)
{
    while (true)
    {
        if (!parser->GetThru(NULL, '<'))
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer, errorBufferSize, "Couldn't find a valid tag");
            return false;   // couldn't find beginning of tag
        }
            
        char c = parser->PeekFast();
        if (c == '/')
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer, errorBufferSize, "End tag with no begin tag on line %d", parser->GetCurrentLineNumber());
            return false;   // we shouldn't be seeing a close tag here
        }
            
        if ((c != '!') && (c != '?'))
            break;  // this should be the beginning of a regular tag
            
        ConsumeIfComment(parser);
        // otherwise this is a processing instruction or a c-data, so look for the next tag
    }
    
    int tagStartLine = parser->GetCurrentLineNumber();
    
    StrPtrLen temp;
    parser->ConsumeUntil(&temp, sNonNameMask);
    if (temp.Len == 0)
    {
        if (errorBuffer != NULL)
        {
            if (parser->GetDataRemaining() == 0)
                qtss_snprintf(errorBuffer, errorBufferSize, "Unexpected end of file on line %d", parser->GetCurrentLineNumber());
            else
                qtss_snprintf(errorBuffer,  errorBufferSize,"Unexpected character (%c) on line %d", parser->PeekFast(), parser->GetCurrentLineNumber());
        }
        return false;   // bad file
    }
        
    fTag = temp.GetAsCString();
    
    parser->ConsumeWhitespace();
    while ((parser->PeekFast() != '>') && (parser->PeekFast() != '/'))
    {
        // we must have an attribute value for this tag
        XMLAttribute* attr = new XMLAttribute;
        fAttributes.EnQueue(&attr->fElem);
        parser->ConsumeUntil(&temp, sNonNameMask);
        if (temp.Len == 0)
        {
            if (errorBuffer != NULL)
            {
                if (parser->GetDataRemaining() == 0)
                    qtss_snprintf(errorBuffer,  errorBufferSize, "Unexpected end of file on line %d", parser->GetCurrentLineNumber());
                else
                    qtss_snprintf(errorBuffer,  errorBufferSize,"Unexpected character (%c) on line %d", parser->PeekFast(), parser->GetCurrentLineNumber());
            }
            return false;   // bad file
        }

        attr->fAttrName = temp.GetAsCString();

        if (!parser->Expect('='))
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer,  errorBufferSize,"Missing '=' after attribute %s on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
        if (!parser->Expect('"'))
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer,  errorBufferSize,"Attribute %s value not in quotes on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
            
        parser->ConsumeUntil(&temp, '"');
        attr->fAttrValue = temp.GetAsCString();
        if (!parser->Expect('"'))
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer, errorBufferSize, "Attribute %s value not in quotes on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
        
        if (verifier && !verifier->IsValidAttributeName(fTag, attr->fAttrName))
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer, errorBufferSize, "Attribute %s not allowed in tag %s on line %d", attr->fAttrName, fTag, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }

        if (verifier && !verifier->IsValidAttributeValue(fTag, attr->fAttrName, attr->fAttrValue))
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer,  errorBufferSize,"Bad value for attribute %s on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }

        parser->ConsumeWhitespace();
    }
    
    if (parser->PeekFast() == '/')
    {
        // this is an empty element tag, i.e. no contents or end tag (e.g <TAG attr="value" />
        parser->Expect('/');
        if (!parser->Expect('>'))
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer,  errorBufferSize,"'>' must follow '/' on line %d", parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
        
        return true;    // we're done with this tag
    }
    
    if (!parser->Expect('>'))
    {
        if (errorBuffer != NULL)
            qtss_snprintf(errorBuffer,  errorBufferSize,"Bad format for tag <%s> on line %d", fTag, parser->GetCurrentLineNumber());
        return false;   // bad attribute specification
    }
    
    while(true)
    {
        parser->ConsumeUntil(&temp, '<');   // this is either value or whitespace
        if (parser->GetDataRemaining() < 4)
        {
            if (errorBuffer != NULL)
                qtss_snprintf(errorBuffer, errorBufferSize, "Reached end of file without end for tag <%s> declared on line %d", fTag, tagStartLine);
            return false;
        }
        if ((*parser)[1] == '/')
        {
            // we'll only assign a value if there were no embedded tags
            if (fEmbeddedTags.GetLength() == 0 && (!verifier || verifier->CanHaveValue(fTag)))
                fValue = temp.GetAsCString();
            else
            {
                // otherwise this needs to have been just whitespace
                StringParser tempParser(&temp);
                tempParser.ConsumeWhitespace();
                if (tempParser.GetDataRemaining() > 0)
                {
                    if (errorBuffer)
                    {
                        if (fEmbeddedTags.GetLength() > 0)
                            qtss_snprintf(errorBuffer,  errorBufferSize,"Unexpected text outside of tag on line %d", tagStartLine);
                        else
                            qtss_snprintf(errorBuffer, errorBufferSize, "Tag <%s> on line %d not allowed to have data", fTag, tagStartLine);
                    }
                }
            }
            break;  // we're all done with this tag
        }
        
        if (((*parser)[1] != '!') && ((*parser)[1] != '?'))
        {
            // this must be the beginning of an embedded tag
            XMLTag* tag = NEW XMLTag();
            fEmbeddedTags.EnQueue(&tag->fElem);
            if (!tag->ParseTag(parser, verifier, errorBuffer, errorBufferSize))
                return false;
                
            if (verifier && !verifier->IsValidSubtag(fTag, tag->GetTagName()))
            {
                if (errorBuffer != NULL)
                    qtss_snprintf(errorBuffer, errorBufferSize, "Tag %s not allowed in tag %s on line %d", tag->GetTagName(), fTag, parser->GetCurrentLineNumber());
                return false;   // bad attribute specification
            }
        }
        else
        {
            parser->ConsumeLength(NULL, 1); // skip '<'
            ConsumeIfComment(parser);
        }
    }

    parser->ConsumeLength(NULL, 2); // skip '</'
    parser->ConsumeUntil(&temp, sNonNameMask);
    if (!temp.Equal(fTag))
    {
        char* newTag = temp.GetAsCString();
        if (errorBuffer != NULL)
            qtss_snprintf(errorBuffer,  errorBufferSize,"End tag </%s> on line %d doesn't match tag <%s> declared on line %d", newTag, parser->GetCurrentLineNumber(),fTag, tagStartLine);
        delete newTag;
        return false;   // bad attribute specification
    }
    
    if (!parser->GetThru(NULL, '>'))
    {
        if (errorBuffer != NULL)
            qtss_snprintf(errorBuffer,  errorBufferSize,"Couldn't find end of tag <%s> declared on line %d", fTag, tagStartLine);
        return false;   // bad attribute specification
    }
    
    return true;
}
Example #18
0
void UserAgentParser::Parse(StrPtrLen *inStream)
{
	StrPtrLen tempID;
	StrPtrLen tempData;
	StringParser parser(inStream);
	StrPtrLen startFields;


	memset(&fFieldData, 0, sizeof(fFieldData));

	parser.ConsumeUntil(&startFields, '('); // search for '(' if not found does nothing

	// parse through everything between the '(' and ')'.
	while (startFields.Len != 0)
	{
		//stop when we reach an empty line.
		tempID.Set(NULL, 0);
		tempData.Set(NULL, 0);

		parser.ConsumeLength(NULL, 1); // step past '(' or ';' if not found or at end of line does nothing
		parser.ConsumeWhitespace(); // search for non-white space if not found does nothing
		parser.ConsumeUntil(&tempID, sEOLWhitespaceEqualMask); // search for end of id (whitespace or =)if not found does nothing
		if (tempID.Len == 0) break;

		parser.ConsumeUntil(NULL, '='); // find the '='
		parser.ConsumeLength(NULL, 1); // step past if not found or at end of line does nothing
		parser.ConsumeUntil(&tempData, sEOLSemicolonCloseParenMask); // search for end of data if not found does nothing
		if (tempData.Len == 0) break;

		StrPtrLen   testID;
		UInt32      fieldID;
		for (short testField = 0; testField < UserAgentParser::eNumAttributes; testField++)
		{
			testID.Set(sFieldIDs[testField].fFieldName, sFieldIDs[testField].fLen);
			fieldID = sFieldIDs[testField].fID;
			if ((fFieldData[fieldID].fFound == false) && testID.Equal(tempID))
			{
				fFieldData[fieldID].fData = tempData;
				fFieldData[fieldID].fFound = true;
			}
		}

	}
	// If we parsed the OS field but not the OSVer field then check and see if
	// the OS field contains the OS version. If it does copy it from there.
	// (e.g. 'os=Mac%209.2.2' or 'os=Windows%20NT%204.0'.)
	if (fFieldData[eOs].fFound && !fFieldData[eOsver].fFound)
	{
		UInt16 len = (UInt16)fFieldData[eOs].fData.Len;
		char* cp = (char*)fFieldData[eOs].fData.Ptr;
		// skip up to the blank space if it exists.
		// (i.e. the blank is URL encoded as '%20')
		while (*cp != '%')
		{
			len--;
			if (*cp == '\0' || len == 0)
			{
				// no blank space...so we're all done.
				return;
			}
			cp++;
		}
		// skip over the blank space.
		cp += 3; len -= 3;
		// the remaining string is the OS version.
		fFieldData[eOsver].fData.Set(cp, len);
		fFieldData[eOsver].fFound = true;
		// and truncate the version from the OS field.
		fFieldData[eOs].fData.Len -= len + 3;
	}
}