bool _ExtractHeaderValuePair (const char *inStartLinePtr, const char *inEndLinePtr, XBOX::VString& outHeader, XBOX::VString& outValue)
{
	if (NULL == inStartLinePtr)
		return false;

	const char *colonPtr = strchr (inStartLinePtr, ':');

	if (NULL != colonPtr)
	{
		outHeader.FromBlock (inStartLinePtr, colonPtr - inStartLinePtr, XBOX::VTC_DefaultTextExport);
		if (!outHeader.IsEmpty())
		{
			++colonPtr; // skip colon
			while (isspace (*colonPtr))
				++colonPtr;

			outValue.FromBlock (colonPtr, (inEndLinePtr - colonPtr), XBOX::VTC_DefaultTextExport);

			if (((inEndLinePtr - colonPtr) > 0) && outValue.IsEmpty())	// YT 01-Feb-2012 - ACI0075472 - Something was going wrong at conversion... Let's try in UTF-8
				outValue.FromBlock (colonPtr, (inEndLinePtr - colonPtr), XBOX::VTC_UTF_8);
		}

		return !(outHeader.IsEmpty());
	}

	return false;
}
static
void BuildFolderPath (const XBOX::VFilePath& inBaseFolder, const XBOX::VString& inPath, XBOX::VFilePath& outPath)
{
	if (inPath.IsEmpty())
	{
		outPath.FromFilePath (inBaseFolder);
	}
	else
	{
		XBOX::VString	pathString (inPath);
		
		if ((pathString[0] == CHAR_SOLIDUS) // POSIX Path ?
#if VERSIONWIN
			|| ((pathString.GetLength() > 2) && (pathString[1] == CHAR_COLON) && (pathString[2] == CHAR_SOLIDUS)) // POSIX path like c:/blahblah/
#endif
		)
		{
			if (!pathString.IsEmpty() && (pathString[pathString.GetLength()-1] != CHAR_SOLIDUS))
				pathString.AppendUniChar (CHAR_SOLIDUS);
			
			outPath.FromFullPath (pathString, XBOX::FPS_POSIX);
		}
		else if ((pathString[0] != CHAR_FULL_STOP) && (pathString.FindUniChar (XBOX::FOLDER_SEPARATOR) > 0))
		{
			if (!pathString.IsEmpty() && (pathString[pathString.GetLength()-1] != XBOX::FOLDER_SEPARATOR))
				pathString.AppendUniChar (XBOX::FOLDER_SEPARATOR);
			
			outPath.FromFullPath (pathString, XBOX::FPS_SYSTEM);
		}
		else
		{
			XBOX::VFilePath baseFolder (inBaseFolder);
			
			if ((pathString[0] == CHAR_FULL_STOP) && (pathString[1] == CHAR_SOLIDUS))
				pathString.Remove (1, 2);
			
			while ((pathString[0] == CHAR_FULL_STOP) && (pathString[1] == CHAR_FULL_STOP) && (pathString[2] == CHAR_SOLIDUS))
			{
				pathString.Remove (1, 3);
				baseFolder = baseFolder.ToParent();
			}
			
			pathString.ExchangeAll (CHAR_SOLIDUS, XBOX::FOLDER_SEPARATOR);
			
			if (!pathString.IsEmpty() && (pathString[pathString.GetLength()-1] != XBOX::FOLDER_SEPARATOR))
				pathString.AppendUniChar (XBOX::FOLDER_SEPARATOR);
			
			outPath.FromRelativePath (baseFolder, pathString);
		}
	}
}
void VHTTPServerLog::_WriteUsername (const XBOX::VString& inUserName, XBOX::VString& ioStream)
{
	if (!inUserName.IsEmpty())
	{
		bool			wasCtrl = false;
		XBOX::VString	userName;

		for (XBOX::VIndex pos = 0; pos < inUserName.GetLength(); ++pos)
		{
			// When user name contains CHAR_SPACE, replace it by CHAR_LOW_LINE '_'
			if ((inUserName[pos] <= CHAR_SPACE) && (inUserName[pos] > 0))
			{
				if (!wasCtrl)
					userName.AppendUniChar (CHAR_LOW_LINE);
				wasCtrl = (inUserName[pos] != CHAR_SPACE);
			}
			else
			{
				userName.AppendUniChar (inUserName[pos]);
				wasCtrl = false;
			}
		}

		ioStream.AppendString (userName);
	}
	else
	{
		ioStream.AppendUniChar (CHAR_HYPHEN_MINUS);
	}
}
예제 #4
0
    bool HttpRequest::SetRequestHeader(const XBOX::VString& inKey, const XBOX::VString& inValue)
    {
        if(!fHandle || inKey.IsEmpty())
            return false;

        fReqHdrs.SetHeader(inKey, inValue);

        return true;
    }
XBOX::VError VHTTPServerProject::AddVirtualFolder (const XBOX::VString& inLocationPath, const XBOX::VString& inIndexFileName, const XBOX::VString& inMatchingKeyWord)
{
	if (inLocationPath.IsEmpty() || inMatchingKeyWord.IsEmpty())
		return XBOX::VE_INVALID_PARAMETER;

	XBOX::VError		error = XBOX::VE_MEMORY_FULL;
	VVirtualFolder *	virtualFolder = fHTTPServer->RetainVirtualFolder (inLocationPath, inIndexFileName, inMatchingKeyWord);

	if (NULL!= virtualFolder)
	{
		XBOX::VTaskLock lock (&fVirtualHostsLock);

		error = XBOX::VE_OK;
		if (fVirtualHosts.empty())
		{
			// sc 16/02/2012 create a virtual host if needed
			VVirtualHost *virtualHost = new VVirtualHost (this);
			if (testAssert(virtualHost != NULL))
			{
				fVirtualHosts.push_back (virtualHost);
				error = fHTTPServer->AddVirtualHost (virtualHost);
			}
			else
			{
				error = XBOX::VE_MEMORY_FULL;
			}
		}

		if (error == XBOX::VE_OK)
		{
			for (std::vector<VVirtualHost *>::const_iterator it = fVirtualHosts.begin(); (it != fVirtualHosts.end()) && (error == XBOX::VE_OK); ++it)
			{
				error = (*it)->AddVirtualFolder (virtualFolder);
			}
		}
		
		XBOX::ReleaseRefCountable (&virtualFolder);
	}

	return error;
}
XBOX::VError VVirtualHostManager::AddVirtualHost (const VVirtualHost *inVirtualHost)
{
	XBOX::VError error = XBOX::VE_INVALID_PARAMETER;

	if (NULL != inVirtualHost)
	{
		XBOX::VString	pattern;
		VVirtualHost *	virtualHost = const_cast<VVirtualHost *>(inVirtualHost);

		pattern.FromString (virtualHost->GetHostPattern());
		if (!pattern.IsEmpty())
		{
			/* Severals project can use the same hostPattern but they can NOT have the same projectPattern */
			error = _AddVirtualHost (fHostPatternsMap, virtualHost, pattern);
		}

#if HTTP_SERVER_USE_PROJECT_PATTERNS
		pattern.FromString (virtualHost->GetURLPattern());
		if (!pattern.IsEmpty())
		{
			if (!_VirtualHostAlreadyExist (fURLPatternsMap, pattern))
			{
				error = _AddVirtualHost (fURLPatternsMap, virtualHost, pattern);
			}
			else
			{
				error = VE_HTTP_SERVER_VIRTUAL_HOST_ALREADY_EXIST;
			}
		}
#endif
		
		if (error == VE_OK)
		{
			fVirtualHosts.push_back (virtualHost);
		}
	}

	return error;
} 
USING_TOOLBOX_NAMESPACE


VError SetHTTPResponseString( IHTTPResponse* inResponse, const VString& inString, const VString* inContentType)
{
	if (inResponse == NULL)
		return VE_INVALID_PARAMETER;
	
	StStringConverter<char> buffer( inString, VTC_UTF_8);

	inResponse->GetResponseBody().OpenWriting();
	inResponse->GetResponseBody().PutData( buffer.GetCPointer(), buffer.GetLength());
	inResponse->GetResponseBody().CloseWriting();

	VError err = inResponse->GetResponseBody().GetLastError();
	if (err == VE_OK)
	{
		inResponse->SetExpiresHeader( GMT_NOW);
		inResponse->AddResponseHeader( HEADER_PRAGMA, CVSTR ("no-cache"));
		if (inContentType != NULL)
		{
			inResponse->AddResponseHeader( HEADER_CONTENT_TYPE, *inContentType);
		}
		/* We send a String encoded using UTF-8, so set the correct header value */
		XBOX::CharSet	charSet = XBOX::VTC_UNKNOWN;
		XBOX::VString	contentType;
		inResponse->GetContentTypeHeader (contentType, &charSet);
		if (contentType.IsEmpty() || charSet !=  VTC_UTF_8)
		{
			inResponse->SetContentTypeHeader (contentType.IsEmpty() ? CVSTR ("text/html"): contentType, VTC_UTF_8);
		}
#if HTTP_SERVER_VERBOSE_MODE
		inResponse->AddResponseHeader( HEADER_X_POWERED_BY, "RIA Server");
#endif
		inResponse->SetContentLengthHeader( buffer.GetLength());
		inResponse->AllowCompression (false);
	}
	return err;
}
void MakeHostString (const XBOX::VString& inHost, PortNumber inPort, XBOX::VString& outHostString)
{
	outHostString.Clear();

	if (!inHost.IsEmpty())
		outHostString.AppendString (inHost);

	if (inPort != DEFAULT_LISTENING_PORT)
	{
		outHostString.AppendUniChar (CHAR_COLON);
		outHostString.AppendLong (inPort);
	}
}
bool VHTTPResponse::_UpdateRequestURL (const XBOX::VString& inProjectPattern)
{
	// URL Start with project pattern ?
	if (!inProjectPattern.IsEmpty())
	{
		_RemoveProjectPatternFromURL (inProjectPattern, fRequest->fURL);
		_RemoveProjectPatternFromURL (inProjectPattern, fRequest->fURLPath);
		_RemoveProjectPatternFromURL (inProjectPattern, fRequest->fRawURL);

		return true;
	}

	return false;
}
bool VVirtualHostManager::_VirtualHostAlreadyExist (const VVirtualHostMap& inMap, const XBOX::VString& inPattern)
{
	if (inPattern.IsEmpty())
		return false;

	VVirtualHost *	matchingHost = NULL;
	XBOX::VTaskLock	lock (&fLock);

	VVirtualHostMap::const_iterator it = std::find_if (inMap.begin(), inMap.end(), EqualVRegexMatcherFunctor<VVirtualHostRefPtr> (inPattern));
	if (it != inMap.end())
		matchingHost = it->second;

	return (NULL != matchingHost);
}
static
bool _RemoveProjectPatternFromURL (const XBOX::VString& inProjectPattern, XBOX::VString& ioURL)
{
	if (inProjectPattern.IsEmpty())
		return false;

	XBOX::VString url (ioURL);
	sLONG pos = HTTPServerTools::FindASCIIVString (url, inProjectPattern);
	if (pos == 2) // Takes the starting CHAR_SOLIDUS into account
	{
		url.GetSubString (pos + inProjectPattern.GetLength(), url.GetLength() - inProjectPattern.GetLength() - 1, ioURL);
		return true;
	}

	return false;;
}
예제 #12
0
BEGIN_TOOLBOX_NAMESPACE
USING_TOOLBOX_NAMESPACE


VMIMEWriter::VMIMEWriter (const XBOX::VString& inBoundary)
: fMIMEMessage()
{
	if (inBoundary.IsEmpty())
	{
		XBOX::VUUID		uuid (true);
		uuid.GetString (fMIMEMessage.fBoundary);
	}
	else
	{
		fMIMEMessage.fBoundary.FromString (inBoundary);
	}
}
XBOX::VError VHTTPServerProject::_BuildRegexMatcher (const XBOX::VString& inPatternString, XBOX::VRegexMatcher **outMatcher)
{
	if (NULL == outMatcher)
		return XBOX::VE_INVALID_PARAMETER;

	XBOX::VString	patternString (inPatternString);
	XBOX::VError	error = XBOX::VE_OK;
	sLONG			pos = 0;

	if (!HTTPServerTools::BeginsWithASCIICString (patternString.GetCPointer(), "(?i)"))
		patternString.Insert (CVSTR ("(?i)"), 1);

	if (HTTPServerTools::EndsWithASCIICString (patternString, "/") &&
		!HTTPServerTools::EndsWithASCIICString (patternString, "$"))
		patternString.AppendString (CVSTR (".*"));

	XBOX::VString string;

	if ((pos = patternString.FindUniChar (CHAR_CIRCUMFLEX_ACCENT)) == 0)
	{
		string.FromCString ("^");
		pos = HTTPServerTools::FindASCIICString (patternString, "(?i)") + 4;
	}
	else
	{
		++pos;
	}

#if HTTP_SERVER_USE_PROJECT_PATTERNS
	if (!fSettings->GetProjectPattern().IsEmpty())
	{
		string.AppendCString ("(/");
		string.AppendString (fSettings->GetProjectPattern());
		string.AppendCString ("|)");
	}
#endif

	patternString.Insert (string, pos);

	if (!patternString.IsEmpty())
		*outMatcher = XBOX::VRegexMatcher::Create (patternString, &error);

	return error;
}
예제 #14
0
void VMIMEMessage::_ReadUrl (const XBOX::VString& inString)
{
	if (!inString.IsEmpty())
	{
		const UniChar *stringPtr = inString.GetCPointer();
		UniChar ch = *stringPtr;

		while (ch != '\0')
		{
			XBOX::VString	name;
			XBOX::VString	value;

			while (ch != '\0' && ch != CHAR_EQUALS_SIGN && ch != CHAR_AMPERSAND)
			{
				if (ch == CHAR_PLUS_SIGN) ch = CHAR_SPACE;
				name.AppendUniChar (ch);
				ch = *(++stringPtr);
			}

			if (ch == CHAR_EQUALS_SIGN)
			{
				ch = *(++stringPtr);
				while (ch != '\0' && ch != CHAR_AMPERSAND)
				{
					if (ch == CHAR_PLUS_SIGN) ch = CHAR_SPACE;
					value.AppendUniChar (ch);
					ch = *(++stringPtr);
				}
			}

			XBOX::VString decodedName (name);
			XBOX::VString decodedValue (value);
			XBOX::VURL::Decode (decodedName);
			XBOX::VURL::Decode (decodedValue);

			XBOX::StStringConverter<char> buffer (decodedValue, XBOX::VTC_UTF_8);
			_AddValuePair (decodedName, CONST_TEXT_PLAIN_UTF_8, (void *)buffer.GetCPointer(), buffer.GetLength());

			if (ch == CHAR_AMPERSAND) ch = *(++stringPtr);
		}
	}
}
예제 #15
0
void VCacheLog::LogComment( const XBOX::VString& inComment )
{
	if(!inComment.IsEmpty())
	{
		if (fLogFile != NULL)
		{
			VTaskLock lock(&s_mutex);
			if (fLogFile != NULL)
			{
				_UpdateStartFlag(true);
				_AddEntry(eCLEntryKind_Comment);
				_UpdateStartFlag(false);

				fLogFile->AppendFormattedString("\r%s\r", fConverter.ConvertString(inComment));

				_AddEntryEnd(eCLEntryKind_Comment, true);
			}
		}
	}
}
예제 #16
0
void VJSStorageClass::_key (VJSParms_callStaticFunction &ioParms, VJSStorageObject *inStorageObject)
{
	xbox_assert(inStorageObject != NULL);

	sLONG	index;

	if (ioParms.CountParams() && ioParms.IsNumberParam(1) && ioParms.GetLongParam(1, &index)) {

		XBOX::VString	key;

		inStorageObject->GetKeyFromIndex(index, &key);
		if (!key.IsEmpty())

			ioParms.ReturnString(key);

		else

			ioParms.ReturnNullValue();	// Index is out of bound.

	} else

		ioParms.ReturnNullValue();
}
XBOX::VError XMLHttpRequest::Send(const XBOX::VString& inData, XBOX::VError* outImplErr)
{
    if(fReadyState!=OPENED)
        return VE_XHRQ_INVALID_STATE_ERROR;

    if(!fCWImpl || !fCWImpl->fReq)
        return VE_XHRQ_IMPL_FAIL_ERROR;

    fErrorFlag=false;

    if(!fProxy.IsEmpty())
        fCWImpl->fReq->SetProxy(fProxy, fPort);

    if(/*(fCWImpl->fMethod==CW::HttpRequest::POST || fCWImpl->fMethod==CW::HttpRequest::PUT) && */!inData.IsEmpty())
    {
        fCWImpl->fReq->SetData(inData);
    }

    //if(fCWImpl->fMethod==CW::HttpRequest::GET || fCWImpl->fMethod==CW::HttpRequest::POST || fCWImpl->fMethod==CW::HttpRequest::HEAD || fCWImpl->fMethod==CW::HttpRequest::PUT)
    //{
    //parametrer la req de facon appropriee
    //}

    if(!fUser.IsEmpty())
    {
        //parametrer la req de facon appropriee

        if(!fPasswd.IsEmpty())
        {
            //parametrer la req de facon appropriee
        }
    }

    bool res=fCWImpl->fReq->Perform(outImplErr);

    if(res)
    {
        fReadyState=HEADERS_RECEIVED;

        if(fChangeHandler)
            fChangeHandler->Execute();

        fReadyState=LOADING;

        if(fChangeHandler)
            fChangeHandler->Execute();
    }

    fReadyState=DONE;

    if(fChangeHandler)
        fChangeHandler->Execute();

    if(!res)
        return VE_XHRQ_SEND_ERROR;

    return XBOX::VE_OK;
}
XBOX::VError VHTTPMessage::ReadFromStream (XBOX::VStream& inStream, const XBOX::VString& inBoundary)
{
#define	MAX_BUFFER_LENGTH	32768

	const char			HTTP_CR = '\r';
	const char			HTTP_LF = '\n';
	const char			HTTP_CRLF [] = { HTTP_CR, HTTP_LF, 0 };
	const char			HTTP_CRLFCRLF [] = { HTTP_CR, HTTP_LF, HTTP_CR, HTTP_LF, 0 };

	XBOX::VError		streamError = XBOX::VE_OK;
	HTTPParsingState	parsingState;
	XBOX::VError		parsingError = XBOX::VE_OK;
	XBOX::VSize			bufferSize = MAX_BUFFER_LENGTH;
	char *				buffer = (char *)XBOX::vMalloc (bufferSize, 0);
	XBOX::VSize			bufferOffset = 0;
	XBOX::VSize			unreadBytes = 0;
	sLONG				lineLen = 0;
	XBOX::VString		header;
	XBOX::VString		value;
	char *				startLinePtr = NULL;
	char *				endLinePtr = NULL;
	char *				endHeaderPtr = NULL;
	sLONG				endLineSize = sizeof (HTTP_CRLF) - 1;
	sLONG				contentLength = 0;
	void *				bodyContentBuffer = NULL;
	XBOX::VSize			bodyContentSize = 0;
	const sLONG			MAX_REQUEST_ENTITY_SIZE = XBOX::MaxLongInt;
	XBOX::VString		boundaryEnd;
	char *				boundary = NULL;
	bool				stopReadingStream = false;

	if (!inBoundary.IsEmpty())
	{
		boundaryEnd.AppendString ("--");
		boundaryEnd.AppendString (inBoundary);
		boundary = new char[boundaryEnd.GetLength() + 1];
		if (NULL != boundary)
			boundaryEnd.ToCString (boundary, boundaryEnd.GetLength() + 1);
	}

	if (NULL == buffer)
		return XBOX::VE_MEMORY_FULL;

	parsingState = PS_ReadingHeaders;

	XBOX::StErrorContextInstaller errorContext (XBOX::VE_STREAM_EOF, XBOX::VE_OK);

	bool isAlreadyReading = inStream.IsReading();

	if (!isAlreadyReading)
		streamError = inStream.OpenReading();

	while ((XBOX::VE_OK == streamError) && !stopReadingStream)
	{
		if (0 == unreadBytes)
			bufferOffset = 0;

		bufferSize = MAX_BUFFER_LENGTH - bufferOffset;

		streamError = inStream.GetData (buffer + bufferOffset, &bufferSize);

		unreadBytes = (bufferSize + bufferOffset);
		bufferOffset = 0;

		while ((unreadBytes > 0) && (XBOX::VE_OK == parsingError))
		{
			if (parsingState <= PS_ReadingHeaders)
			{
				startLinePtr = buffer + bufferOffset;
				endLinePtr = strstr (startLinePtr, HTTP_CRLF);

				if ((NULL != endLinePtr) && (NULL == endHeaderPtr))
					endHeaderPtr = strstr (startLinePtr, HTTP_CRLFCRLF);
			}

			/* Start to parse the Status-Line */
			switch (parsingState)
			{
			case PS_ReadingHeaders:
				{
					if (NULL != endLinePtr)
					{
						if (startLinePtr != (endHeaderPtr + endLineSize))
						{
							if (_ExtractHeaderValuePair (startLinePtr, endLinePtr, header, value))
							{
								GetHeaders().SetHeaderValue (header, value, false);
							}
						}

						else /*if (startLinePtr == endHeaderPtr)*/
						{
							parsingState = PS_ReadingBody;
							XBOX::VString contentLengthString;
							if (GetHeaders().GetHeaderValue (STRING_HEADER_CONTENT_LENGTH, contentLengthString))
								contentLength = HTTPTools::GetLongFromString (contentLengthString);
						}
					}
					break;
				}

			case PS_ReadingBody:
				{
					if (!boundaryEnd.IsEmpty())
					{
						if (NULL != boundary)
						{
							char *endBoundaryPtr = memstr (buffer + bufferOffset, unreadBytes, boundary, strlen (boundary));
							if (NULL != endBoundaryPtr)
							{
								XBOX::VSize nbBytesToCopy  = (endBoundaryPtr - (buffer + bufferOffset));
								inStream.UngetData (endBoundaryPtr, unreadBytes - nbBytesToCopy);
								unreadBytes = nbBytesToCopy;
								if (NULL != memstr (endBoundaryPtr - 2, 2, HTTP_CRLF, 2))
									unreadBytes -= 2;	// Skip CRLF after boundary part
								stopReadingStream = true;
							}
						}
					}

					if (NULL == bodyContentBuffer)
					{
						// There's no Content-Length field in header
						if (0 == contentLength)
						{
							bodyContentBuffer = XBOX::vMalloc (bufferSize, 0);
							bodyContentSize = 0;
						}
						// There's one Content-Length, just check it match limits
						else if ((contentLength > 0) && (contentLength < MAX_REQUEST_ENTITY_SIZE))
						{
							bodyContentBuffer = XBOX::vMalloc (contentLength, 0);
							bodyContentSize = 0;
						}
					}

					if ((NULL != bodyContentBuffer) && (bodyContentSize + unreadBytes < MAX_REQUEST_ENTITY_SIZE))
					{
						XBOX::VSize nbBytesToCopy = unreadBytes;
						if (bodyContentSize + nbBytesToCopy > contentLength)
							bodyContentBuffer = XBOX::vRealloc (bodyContentBuffer, bodyContentSize + nbBytesToCopy);

						memcpy ((char *)(bodyContentBuffer) + bodyContentSize, buffer + bufferOffset, unreadBytes);
						bodyContentSize += unreadBytes;
						bufferOffset = unreadBytes = 0;
					}
					else
					{
						parsingError = XBOX::VE_MEMORY_FULL;

						if (NULL != bodyContentBuffer)
						{
							XBOX::vFree (bodyContentBuffer);
							bodyContentBuffer = NULL;
						}
					}
					break;
				}
			}

			if (XBOX::VE_OK != parsingError)
				break;

			if (NULL != endLinePtr)
			{
				lineLen = (endLinePtr - startLinePtr) + endLineSize; // to skip CRLF;
				bufferOffset += lineLen;
				unreadBytes -= lineLen;
				endLinePtr = NULL;
			}
			else
			{
				if (bufferOffset > 0)
				{
					memmove (buffer, buffer + bufferOffset, unreadBytes);
					buffer[unreadBytes] = 0;
				}
				bufferOffset = unreadBytes;
				break;
			}
		}

		if (XBOX::VE_OK != parsingError)
			break;
	}

	if (!isAlreadyReading)
		inStream.CloseReading();

	if (XBOX::VE_STREAM_EOF == streamError)
		streamError = XBOX::VE_OK;

	if (!parsingError && !streamError)
	{
		if (NULL != bodyContentBuffer)
		{
#if VERSIONDEBUG
			if ((contentLength > 0) && (bodyContentSize != contentLength))
				assert (false);
#endif
			GetBody().SetDataPtr (bodyContentBuffer, bodyContentSize);

			XBOX::VString	contentType;
			XBOX::CharSet	charSet = XBOX::VTC_UNKNOWN;

			/* Set VStream charset according to content-type header other else set default charset to UTF-8 */
			if ((!GetHeaders().GetContentType (contentType, &charSet)) || (XBOX::VTC_UNKNOWN == charSet))
				charSet = XBOX::VTC_UTF_8;
			GetBody().SetCharSet (charSet);
		}

		parsingState = PS_ParsingFinished;
	}
	else
	{
		if (NULL != bodyContentBuffer)
			XBOX::vFree (bodyContentBuffer);
	}

	delete [] boundary;
	boundary = NULL;

	XBOX::vFree (buffer);
	buffer = NULL;

	return streamError;

#undef MAX_BUFFER_LENGTH
}
// Environment block == null-terminated block of null-terminated strings of the form: name=value\0
wchar_t * XWinProcessLauncher::_CreateEnvironmentVariablesBlock(const EnvVarNamesAndValuesMap &inVarToUse)
{
	wchar_t *		initialEnvStrings	= NULL;
	VMemoryBuffer<>	allStrings;
	wchar_t *		theEnvVarBlock		= NULL;

	// Initial environment variables

	initialEnvStrings = ::GetEnvironmentStringsW();
	if(initialEnvStrings != NULL)
	{
		wchar_t	*currentStr = initialEnvStrings;
		size_t	fullStrSize;

		while (*currentStr)
		{
			fullStrSize = ::wcslen(currentStr) + 1;
			allStrings.PutData(allStrings.GetDataSize(), currentStr, fullStrSize * sizeof(wchar_t));
			currentStr += fullStrSize;
		}
	}

	// Prepare our envir. variables
	if(!inVarToUse.empty())
	{
		XBOX::VString							oneEnvVarAndValue;
		EnvVarNamesAndValuesMap::const_iterator	envVarIterator;

		// Calculate final buffer size (concatenate name=value and add the 0 terminattion)
		 
		for (envVarIterator = inVarToUse.begin(); envVarIterator != inVarToUse.end(); envVarIterator++)
		{
			oneEnvVarAndValue = envVarIterator->first;
			if(!oneEnvVarAndValue.IsEmpty())
			{
				oneEnvVarAndValue += "=";
				oneEnvVarAndValue += envVarIterator->second;

				const wchar_t *	varValueCStr = oneEnvVarAndValue.GetCPointer();	// Null terminated UniCode string.

				if(testAssert(varValueCStr != NULL))
				{
					allStrings.PutData(allStrings.GetDataSize(), varValueCStr, (oneEnvVarAndValue.GetLength() + 1) * sizeof(wchar_t));				
				}
			}						
		}
	} //if(!inVarToUse.empty())

	if(allStrings.GetDataSize() > 0)
	{
		wchar_t	theZero = 0;

		allStrings.PutData(allStrings.GetDataSize(), &theZero, sizeof(wchar_t));

		theEnvVarBlock = new wchar_t[allStrings.GetDataSize()];
		if(testAssert(theEnvVarBlock))
			allStrings.GetData(0, theEnvVarBlock, allStrings.GetDataSize());
	}
	
	if(initialEnvStrings != NULL)
		::FreeEnvironmentStringsW(initialEnvStrings);

	return theEnvVarBlock;
}
XBOX::VError VVirtualFolder::GetFilePathFromURL (const XBOX::VString& inURL, XBOX::VString& outLocationPath)
{
	if (!fLocalFolder)
	{
		XBOX::VString URL (inURL);
		sLONG pos = HTTPServerTools::FindASCIIVString (URL, fName);

		if (pos > 0)
			URL.Remove (1, pos + fName.GetLength() - 1);

		if ((URL.GetLength() == 1) && (URL.GetUniChar (1) == CHAR_SOLIDUS) && (!fIndexFileName.IsEmpty()))
			URL.AppendString (fIndexFileName);
		
		outLocationPath.FromString (fLocationPath);
		if (outLocationPath.GetUniChar (outLocationPath.GetLength()) == CHAR_SOLIDUS)
			outLocationPath.Truncate (outLocationPath.GetLength() - 1);
		outLocationPath.AppendString (URL);

		return VE_HTTP_PROTOCOL_FOUND;
	}

	XBOX::VError	error = XBOX::VE_FILE_NOT_FOUND;
	XBOX::VFilePath	path (fFolder->GetPath());
	XBOX::VString	pathString (inURL);
	XBOX::VString	folder;
	XBOX::VString	docName;

	if ((pathString.GetLength() == 1) && (pathString.GetUniChar (1) == CHAR_SOLIDUS))
	{
		docName.FromString (fIndexFileName);
	}
	else
	{
		bool	notDone = true;
		sLONG	folderLen = 0;
		sLONG	pos = 0;
		sLONG	curPos = 0;

		// YT 16-Nov-2011 - ACI0073914
		if (pathString.FindUniChar (CHAR_COLON) > 0) // ':'
			pathString.ExchangeAll (CHAR_COLON, CHAR_SOLIDUS);

		if (pathString.FindUniChar (CHAR_REVERSE_SOLIDUS) > 0) // '\'
			pathString.ExchangeAll (CHAR_REVERSE_SOLIDUS, CHAR_SOLIDUS);

		while (notDone)
		{
			if ((pos = pathString.FindUniChar (CHAR_SOLIDUS, curPos + 1)) > 0)	// '/'
			{
				HTTPServerTools::GetSubString (pathString, curPos, pos - 2, folder);
				folderLen = folder.GetLength();
				if (folderLen > 0)
				{
					/* If URL first folder equals Virtual Folder Name or Project Pattern... Do nothing... */
					if ((curPos == 1) && !fName.IsEmpty() && HTTPServerTools::EqualASCIIVString (fName, folder))
						;
					/* YT 24-Feb-2011 - ACI0069901 - Project Pattern is already removed from URL in VHTTPResponse::_UpdateRequestURL()
					else if ((curPos == 1) && !fProjectPattern.IsEmpty() && HTTPServerTools::EqualASCIIVString (fProjectPattern, folder))
					{
						pathString.SubString (curPos + fProjectPattern.GetLength() + 1, pathString.GetLength() - fProjectPattern.GetLength() + 1); // YT 24-Nov-2010 - ACI0068942 - Remove Project Pattern from URL...
						folderLen = 0;
						curPos = -1;
					}
					*/
					else if ((folderLen == 2) && (folder[0] == CHAR_FULL_STOP) && (folder[1] == CHAR_FULL_STOP)) // ".."
						path = path.ToParent();
					else if  ((folderLen == 1) && (folder[0] == CHAR_FULL_STOP)) // "."
						;	// unchanged
					else
						path = path.ToSubFolder (folder);

					curPos += (folderLen + 1);
				}
				else
					curPos += 1;
			}
			else
				notDone = false;

			if (curPos >= pathString.GetLength())
				break;
		}
		
		if (curPos < pathString.GetLength())
			HTTPServerTools::GetSubString (pathString, curPos, pathString.GetLength() - 1, docName);
	}

	/* if URL does not include a filename, try using the index file name set in prefs */
	if (docName.IsEmpty())
		docName.FromString (fIndexFileName);

	path = path.ToSubFile (docName);

	/*
		at this stage path should contain a full path pointing to the wanted file
		check that this is inside the web folder (if it's a web connection)
	*/
	// SECURITY CHECK - change it with great care
	if (path.GetPath().BeginsWith (fFolder->GetPath().GetPath()))
	{
		outLocationPath.FromString (path.GetPath());
		error = VE_OK;
	}
	else
	{
		// UNDER ATTACK !!!
		path.Clear();
		error = VE_HTTP_PROTOCOL_FORBIDDEN;
	}

	return error;
}
XBOX::VError VHTTPServerProjectSettings::LoadFromBag (const XBOX::VValueBag *inBag)
{
	if (NULL == inBag)
		return XBOX::VE_INVALID_PARAMETER;

#if 0 /*VERSIONDEBUG*/
	XBOX::VString xmlString ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
	inBag->DumpXML (xmlString, CVSTR ("settings"), true);
#endif

	/* Project settings */
	const XBOX::VValueBag *projectSettings = RetainSettings (inBag, RIASettingsKeys::Project::kXmlElement);
	if (projectSettings)
	{
		XBOX::VString ipString = RIASettingsKeys::Project::listen.Get (projectSettings);
#if WITH_DEPRECATED_IPV4_API
		fListeningAddress = ServerNetTools::GetIPAddress (ipString);
#else
		fListeningAddress.FromString (ipString);
#endif		
		fHostName = RIASettingsKeys::Project::hostName.Get (projectSettings);
#if HTTP_SERVER_USE_PROJECT_PATTERNS
		fProjectPattern = RIASettingsKeys::Project::pattern.Get (projectSettings);
#endif

#if WITH_DEPRECATED_IPV4_API
		if ((fListeningAddress != 0) && (fListeningAddress != LOCALHOST_ADDRESS))
#else
		if ((fListeningAddress != XBOX::VNetAddress::GetAnyIP()) && (fListeningAddress != XBOX::VNetAddress::GetLoopbackIP()))
#endif		
		{
#if WITH_DEPRECATED_IPV4_API
			std::vector<IP4> ipv4Addresses;
			if (ServerNetTools::GetLocalIPv4Addresses (ipv4Addresses) > 0)
			{
				if (!FindValueInVector (ipv4Addresses, fListeningAddress))
					fListeningAddress = 0; // Listening on all IP addresses
			}
#else
			XBOX::VectorOfVString	localIPAddresses;

			if (HTTPServerTools::GetLocalIPAddresses (localIPAddresses) > 0)
			{
				if (!FindValueInVector (localIPAddresses, fListeningAddress))
					fListeningAddress.FromString (XBOX::VNetAddress::GetAnyIP()); // Listening on all IP addresses
			}
#endif			
		}

		XBOX::VString authType;
		RIASettingsKeys::Project::realm.Get (projectSettings, fRealm);
		RIASettingsKeys::Project::authType.Get (projectSettings, authType);
		fAuthType = HTTPServerTools::GetAuthenticationMethodFromName (authType);

		XBOX::QuickReleaseRefCountable (projectSettings);
	}


	/*  HTTP Settings */
	const XBOX::VValueBag *httpSettings = RetainSettings (inBag, RIASettingsKeys::HTTP::kXmlElement);
	if (httpSettings)
	{
		fPort = RIASettingsKeys::HTTP::port.Get (httpSettings);
		fAllowSSL = RIASettingsKeys::HTTP::allowSSL.Get (httpSettings);
		fSSLMandatory = RIASettingsKeys::HTTP::SSLMandatory.Get (httpSettings);
		fSSLPort = RIASettingsKeys::HTTP::SSLPort.Get (httpSettings);

		if (fSSLMandatory && !fAllowSSL)
			fAllowSSL = true;

		if (fAllowSSL)
		{
			XBOX::VString certificatePath = RIASettingsKeys::HTTP::SSLCertificatePath.Get (httpSettings);
			BuildFolderPath (fProjectFolderPath, certificatePath, fSSLCertificatesFolderPath);
		}

		XBOX::VString charSetString = RIASettingsKeys::HTTP::standardSet.Get (httpSettings);
		XBOX::CharSet charSet = VTextConverters::Get()->GetCharSetFromName (charSetString);
		fDefaultCharSet = (charSet != XBOX::VTC_UNKNOWN) ? charSet : XBOX::VTC_UTF_8;

		/* cache settings */
		fEnableCache = RIASettingsKeys::HTTP::useCache.Get (httpSettings);
		fCacheMaxSize = RIASettingsKeys::HTTP::pageCacheSize.Get (httpSettings) * 1024;			// expressed in Kilo-Bytes in settings file
		fCachedObjectMaxSize = RIASettingsKeys::HTTP::cachedObjectMaxSize.Get (httpSettings);	// expressed in Bytes in settings file

		/* compression settings */
		fEnableCompression = RIASettingsKeys::HTTP::allowCompression.Get (httpSettings);
		fCompressionMinThreshold = RIASettingsKeys::HTTP::compressionMinThreshold.Get (httpSettings);
		fCompressionMaxThreshold = RIASettingsKeys::HTTP::compressionMaxThreshold.Get (httpSettings);

		/* Keep-Alive settings */
		fEnableKeepAlive = RIASettingsKeys::HTTP::acceptKeepAliveConnections.Get (httpSettings);
/* Temporary disable theses settings loading... because of a bug with long timeout values (sic...)
		fKeepAliveTimeout = RIASettingsKeys::HTTP::maximumTimeout.Get (httpSettings);
		fKeepAliveMaxConnections = RIASettingsKeys::HTTP::maximumRequestsByConnection.Get (httpSettings);
*/

		/* Log settings */
		fLogFormat = HTTPServerTools::GetLogFormatFromName (RIASettingsKeys::HTTP::logFormat.Get (httpSettings));
		SetLogRotationMode (LRC_ROTATE_ON_FILE_SIZE);
		SetLogMaxSize (RIASettingsKeys::HTTP::logMaxSize.Get (httpSettings));
		XBOX::VString logFolderPathString = RIASettingsKeys::HTTP::logPath.Get (httpSettings);
		BuildFolderPath (fProjectFolderPath, logFolderPathString, fLogFolderPath);
		fLogFileName = RIASettingsKeys::HTTP::logFileName.Get (httpSettings);

		const XBOX::VBagArray *logTokens = RetainMultipleSettings (httpSettings, RIASettingsKeys::HTTP::Log::kXmlElement);
		if (NULL != logTokens)
		{
			XBOX::VIndex count = logTokens->GetCount();

			if (count > 0)
			{
				XBOX::VString tokenName;
				XBOX::VTaskLock lock (&fLogTokensVectorLock);

				fLogTokensVector.clear();
				for (XBOX::VIndex i = 1; i <= count; ++i)
				{
					const XBOX::VValueBag *bag = logTokens->GetNth (i);
					if (NULL != bag)
					{
						bag->GetString (RIASettingsKeys::HTTP::Log::field, tokenName);
						if (!tokenName.IsEmpty())
						{
							EHTTPServerLogToken token = HTTPServerTools::GetLogTokenFromName (tokenName);
							if (token != LOG_TOKEN_NONE)
								AppendUniqueValueToVector (fLogTokensVector, token);
						}
					}
				}
			}

			XBOX::QuickReleaseRefCountable (logTokens);
		}

		XBOX::QuickReleaseRefCountable (httpSettings);
	}

	/* Web App settings */
	const XBOX::VValueBag *webAppSettings = RetainSettings (inBag, RIASettingsKeys::WebApp::kXmlElement);
	if (webAppSettings)
	{
		XBOX::VString webFolderPath;
		webFolderPath = RIASettingsKeys::WebApp::documentRoot.Get (webAppSettings);
		BuildFolderPath (fProjectFolderPath, webFolderPath, fWebFolderPath);
		fIndexPageName = RIASettingsKeys::WebApp::directoryIndex.Get (webAppSettings);

		XBOX::QuickReleaseRefCountable (webAppSettings);
	}

	/* Resources settings */
	LoadResourcesSettingsFromBag( *inBag);

	/* Virtual Folders settings */
	LoadVirtualFoldersSettingsFromBag( *inBag);

	Tell_SettingsChanged();

	return XBOX::VE_OK;
}
XBOX::VError VHTTPResponse::SendResponse()
{
	XBOX::VError error = XBOX::VE_OK;

	if (fIsChunked)
	{
		// First send buffered data that was not already sent...
		if (XBOX::VE_OK == (error = _SendResponseBody()))
		{
			// Then send special ending line for chunked encoding
			error = _WriteChunkSize (0);
		}
	}
	else
	{
		XBOX::VString contentType;
		XBOX::VString contentEncoding;

		GetHeaders().GetContentType (contentType);
		
		if (GetHeaders().GetHeaderValue (HEADER_CONTENT_ENCODING, contentEncoding) && !contentEncoding.IsEmpty())
		{
			if (HTTPProtocol::NegotiateEncodingMethod (contentEncoding) != COMPRESSION_UNKNOWN)
				fCanCompressBody = false;
		}

		if (HTTP_UNDEFINED == fResponseStatusCode)
			fResponseStatusCode = HTTP_OK;

		VVirtualHost *virtualHost = dynamic_cast<VVirtualHost *>(GetVirtualHost());

		if (NULL != virtualHost)
		{
			// Compress HTTP Message body when applicable
#if HTTP_SERVER_GLOBAL_SETTINGS
			bool compressionEnabled = fHTTPServer->GetSettings()->GetEnableCompression();
#else
			bool compressionEnabled = virtualHost->GetSettings()->GetEnableCompression();
#endif
			if (fCanCompressBody && compressionEnabled)
			{
				sLONG size = (sLONG)GetBody().GetSize();
#if HTTP_SERVER_GLOBAL_SETTINGS
				sLONG minThreshold = (fMinCompressionThreshold == -1) ? fHTTPServer->GetSettings()->GetCompressionMinThreshold() : fMinCompressionThreshold;
				sLONG maxThreshold = (fMaxCompressionThreshold == -1) ? fHTTPServer->GetSettings()->GetCompressionMaxThreshold() : fMaxCompressionThreshold;
#else
				sLONG minThreshold = (fMinCompressionThreshold == -1) ? virtualHost->GetSettings()->GetCompressionMinThreshold() : fMinCompressionThreshold;
				sLONG maxThreshold = (fMaxCompressionThreshold == -1) ? virtualHost->GetSettings()->GetCompressionMaxThreshold() : fMaxCompressionThreshold;
#endif
				if ((size > minThreshold) && (size <= maxThreshold))
				{
					if (!contentType.IsEmpty() && (VMimeTypeManager::IsMimeTypeCompressible (contentType)))
					{
						error = _CompressData();
					}
				}
			}
		}

		// Put HTTP Message body in cache when applicable
		if ((NULL != virtualHost) && fCanCacheBody && (fResponseStatusCode == HTTP_OK))
		{
#if HTTP_SERVER_GLOBAL_CACHE
			VCacheManager *	cacheManager = virtualHost->GetProject()->GetHTTPServer()->GetCacheManager();
#else
			VCacheManager *	cacheManager = virtualHost->GetCacheManager();
#endif
			XBOX::VFilePath	filePath;
			XBOX::VString	locationPath;
			XBOX::VTime		lastModified;
			XBOX::VString	lastModifiedString;
			XBOX::VError	fileError = XBOX::VE_OK;
			bool			staticFile = false;

			if (XBOX::VE_OK == (fileError = virtualHost->GetFilePathFromURL (fRequest->GetURL(), locationPath)))
			{
				filePath.FromFullPath (locationPath);
				if (filePath.IsFile() && (XBOX::VE_OK == HTTPServerTools::GetFileInfos (filePath, &lastModified)))
				{
					staticFile = true;
					HTTPProtocol::MakeRFC822GMTDateString (lastModified, lastModifiedString);
				}
			}

			if ((XBOX::VE_OK == fileError) && (NULL != cacheManager) && cacheManager->GetEnableDataCache())
			{
				uLONG	bufferSize = (uLONG)GetBody().GetSize();
				if (bufferSize <= cacheManager->GetCachedObjectMaxSize())
				{
					void *			buffer = GetBody().GetDataPtr();
					XBOX::VTime		lastChecked;
					VCachedObject *	cachedObject = NULL;

					XBOX::VTime::Now (lastChecked);

					bool ok = cacheManager->AddPageToCache (fRequest->GetURL(),
															virtualHost->GetUUIDString(),
															contentType,
															buffer,
															bufferSize,
															filePath,
															lastChecked,
															lastModified,
															staticFile,
															fCompressionMode,
															&cachedObject);

					if (ok)
					{
						if (NULL != cachedObject)
						{
							XBOX::VTime expirationDate;
							sLONG maxAge = cachedObject->GetMaxAge();

							if (maxAge > 0)
							{
								XBOX::VString	string;

								string.FromCString ("max-age=");
								string.AppendLong (maxAge);
								AddResponseHeader (STRING_HEADER_CACHE_CONTROL, string);
								AddResponseHeader (STRING_HEADER_AGE, cachedObject->GetAge());
								if (cachedObject->GetExpirationDate (expirationDate))
									AddResponseHeader (STRING_HEADER_EXPIRES, expirationDate);
							}
							else if (cachedObject->GetExpirationDate (expirationDate) && IsVTimeValid (expirationDate))
							{
								AddResponseHeader (STRING_HEADER_EXPIRES, expirationDate);
							}

							XBOX::QuickReleaseRefCountable (cachedObject);
						}
					}
				}
			}

			if (!lastModifiedString.IsEmpty())
				AddResponseHeader (STRING_HEADER_LAST_MODIFIED, lastModifiedString);
		}

		if (HTTP_OK == fResponseStatusCode)
		{
			if (NULL != fFileToSend)
			{
				if (fFileToSend->Exists())
				{
					sLONG8	fileSize = 0;
					
					fFileToSend->GetSize (&fileSize);
					this->SetContentLengthHeader (fileSize); // YT 18-Jul-2011 - ACI0072287

					if (XBOX::VE_OK == (error = _SendResponseHeader()))
					{
						const sLONG CHUNK_BUFFER_SIZE = 0xFFFF;
						char *	chunkBuffer = (char *)XBOX::vMalloc (CHUNK_BUFFER_SIZE, 0);
						if (testAssert (NULL != chunkBuffer))
						{
							XBOX::VFileDesc *fileDesc = NULL;
							if ((XBOX::VE_OK == fFileToSend->Open (XBOX::FA_READ, &fileDesc, XBOX::FO_SequentialScan)) && (NULL != fileDesc))
							{
								uLONG			chunkSize = 0;
								XBOX::VSize		readBytes = 0;
								XBOX::VError	fileError = XBOX::VE_OK;
								sLONG8			unreadSize = 0;

								unreadSize = fileSize;
								fileDesc->SetPos (0, true);

								while ((XBOX::VE_OK == fileError) && (unreadSize > 0))
								{
									chunkSize = (unreadSize > CHUNK_BUFFER_SIZE) ? CHUNK_BUFFER_SIZE : unreadSize;
									fileError = fileDesc->GetDataAtPos (chunkBuffer, chunkSize, 0, &readBytes);
									unreadSize -= (sLONG8)readBytes;

									if ((XBOX::VE_OK == fileError) || (XBOX::VE_STREAM_EOF == fileError))
									{
										error = _WriteToSocket (chunkBuffer, &chunkSize);
										if (XBOX::VE_OK != error)
											break;
									}
								}

								delete fileDesc;
								fileDesc = NULL;
							}
							else
							{
								error = _SendResponseWithStatusCode (HTTP_INTERNAL_SERVER_ERROR);
							}

							XBOX::vFree (chunkBuffer);
							chunkBuffer = NULL;
						}
						else
						{
							error = _SendResponseWithStatusCode (HTTP_INTERNAL_SERVER_ERROR);
						}
					}
				}
				else
				{
					error = _SendResponseWithStatusCode (HTTP_NOT_FOUND);
				}

				XBOX::ReleaseRefCountable (&fFileToSend);
			}
			else if (GetBody().GetDataSize() >= 0)
			{
				if (XBOX::VE_OK == (error = _SendResponseHeader()))
				{
					if (NULL != GetBody().GetDataPtr())
						error = _SendResponseBody();
				}
			}
			else
			{
				error = _SendResponseWithStatusCode (HTTP_INTERNAL_SERVER_ERROR);
			}
		}
		else
		{
			error = _SendResponseWithStatusCode (fResponseStatusCode);
		}
	}

	return error;
}
void XPosixProcessLauncher::_BuildArrayEnvironmentVariables(const EnvVarNamesAndValuesMap &inVarToUse, char **&outArrayEnv)
{
/*	An environment variable array for Unix is a pointer to a null-terminated array of character pointers to null-terminated strings
	Each element is formated "var_name=var_value", ie "PHP_FCGI_CHILDREN=1"
*/
	// Dispose the previous array of arguments if not NULL
	_Free2DCharArray(outArrayEnv);
	
	if(inVarToUse.empty())
		return;
	
	// Don't handle empty names
	sLONG		nbNonEmptyNames = 0;
	
	EnvVarNamesAndValuesMap::const_iterator	envVarIterator = inVarToUse.begin();
	while(envVarIterator != inVarToUse.end())
	{
		if(!envVarIterator->first.IsEmpty())
			++nbNonEmptyNames;
		
		++envVarIterator;
	}
	
	if(nbNonEmptyNames == 0)
		return;
	
	size_t outArrayEnvLength = (nbNonEmptyNames + 1) * sizeof(char *);// +1 for last NULL element
	outArrayEnv = (char **)gMemory->NewPtrClear(outArrayEnvLength, 0);
	if(outArrayEnv == NULL)
	{
		assert(false);
		return;
	}
		
	XBOX::VString	oneEnvVarAndValue;
	
	nbNonEmptyNames = 0;
	
	envVarIterator = inVarToUse.begin();
	while(envVarIterator != inVarToUse.end())
	{
		oneEnvVarAndValue = envVarIterator->first;
		if(!oneEnvVarAndValue.IsEmpty())
		{
			oneEnvVarAndValue += "=";
			oneEnvVarAndValue += envVarIterator->second;
			
			char *oneFinalEntry = _CreateCString(oneEnvVarAndValue);
			if(testAssert(oneFinalEntry != NULL))
			{
				++nbNonEmptyNames;
				outArrayEnv[nbNonEmptyNames - 1] = oneFinalEntry;
			}
			else
			{
				break;
			}
		}
		
		++envVarIterator;
	}
	outArrayEnv[nbNonEmptyNames] = NULL;
}
XBOX::VError VHTTPServerLog::_WriteCLF_DLF (const IHTTPResponse& inHTTPResponse)
{
	XBOX::VString	string;
	XBOX::VTime		time;

	// GMT time
	time.FromSystemTime();

	// Client IP address
	HTTPServerTools::MakeIPv4String (inHTTPResponse.GetIPv4(), string);
	fRequestsBuffer.AppendString (string);
	fRequestsBuffer.AppendUniChar (CHAR_SPACE);
	
	// RFC931
	fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
	fRequestsBuffer.AppendUniChar (CHAR_SPACE);
	
	// AuthUser
	XBOX::VString userName;
	inHTTPResponse.GetRequest().GetAuthenticationInfos()->GetUserName (userName);
	
	if (userName.IsEmpty())
		fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
	else
		fRequestsBuffer.AppendString (userName);
	fRequestsBuffer.AppendUniChar (CHAR_SPACE);

	// Date & Time
	string.Clear();
	_MakeDateString (time, string);

	fRequestsBuffer.AppendUniChar (CHAR_LEFT_SQUARE_BRACKET);
	fRequestsBuffer.AppendString (string);
	fRequestsBuffer.AppendUniChar (CHAR_RIGHT_SQUARE_BRACKET);
	fRequestsBuffer.AppendUniChar (CHAR_SPACE);

	// HTTP Request
	fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
	fRequestsBuffer.AppendString (inHTTPResponse.GetRequest().GetRequestLine());
	fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
	fRequestsBuffer.AppendUniChar (CHAR_SPACE);
	
	// HTTP Status
	string.Clear();
	string.FromLong ((sLONG)inHTTPResponse.GetResponseStatusCode());
	fRequestsBuffer.AppendString (string);
	fRequestsBuffer.AppendUniChar (CHAR_SPACE);

	// HTTP Content Length
	string.Clear();
	if (!inHTTPResponse.GetResponseHeader (STRING_HEADER_CONTENT_LENGTH, string) || string.IsEmpty())
		string.FromLong(0);
	fRequestsBuffer.AppendString (string);
	
	// We add the last fields for the DLF log format
	if (fSettings.GetLogFormat() == LOG_FORMAT_DLF)
	{	
		// HTTP Referrer
		string.Clear();
		fRequestsBuffer.AppendUniChar (CHAR_SPACE);
		inHTTPResponse.GetRequest().GetHTTPHeaders().GetHeaderValue (STRING_HEADER_REFERER, string);
		fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
		fRequestsBuffer.AppendString (string);
		fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
		fRequestsBuffer.AppendUniChar (CHAR_SPACE);
		
		// HTTP User-Agent
		string.Clear();
		inHTTPResponse.GetRequest().GetHTTPHeaders().GetHeaderValue (STRING_HEADER_USER_AGENT, string);
		fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
		fRequestsBuffer.AppendString (string);
		fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
	}

	fRequestsBuffer.AppendUniChar (HTTP_LF);

	return XBOX::VE_OK;
}
XBOX::VError VHTTPServerLog::_WriteWLF_ELF (const IHTTPResponse& inHTTPResponse)
{
	XBOX::VString				string;
	XBOX::VString				ipAddress;
	const VectorOfLogToken		tokens = fSettings.GetLogTokens();
	const EHTTPServerLogFormat	format = fSettings.GetLogFormat();

	for (VectorOfLogToken::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
	{
		switch (*it)
		{
			case LOG_TOKEN_DATE:
				string.Clear();
				if (format == LOG_FORMAT_ELF)
				{
					_GetCurrentFormatedDate (string, false);
				}
				else
				{
					_GetCurrentFormatedDate (string, true, HTTP_SOLIDUS);
				}

				if (!string.IsEmpty())
				{
					fRequestsBuffer.AppendString (string);					
				}
				else
				{
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				}
				break;

			case LOG_TOKEN_TIME:
				string.Clear();
				if (format == LOG_FORMAT_WLF)
					_GetCurrentFormatedTime (string, true);				
				else
					_GetCurrentFormatedTime (string, false);
				fRequestsBuffer.AppendString (string);	
				break;

			case LOG_TOKEN_STATUS:
				string.FromLong ((sLONG)inHTTPResponse.GetResponseStatusCode());
				fRequestsBuffer.AppendString (string);
				break;

			case LOG_TOKEN_ELF_S_IP:
				string.Clear();
				HTTPServerTools::MakeIPv4String (inHTTPResponse.GetIPv4(), string);
				fRequestsBuffer.AppendString (string);
				break;

			case LOG_TOKEN_HOST_NAME:	//	= C_DNS .....
			case LOG_TOKEN_ELF_C_DNS:	//	DNS lookup : tres couteux en perf : remplacé par l'IP du client (les analyseurs de log font le DNS lookup)...
			case LOG_TOKEN_ELF_C_IP:	//	Client IP Address 192.0.1.3
				string.Clear();
				HTTPServerTools::MakeIPv4String (inHTTPResponse.GetIPv4(), string);
				fRequestsBuffer.AppendString (string);
				break;

			case LOG_TOKEN_METHOD:	// The HTTP method : GET HEAD POST. If Unknown, we just copy it
				string.Clear();
				HTTPProtocol::MakeHTTPMethodString (inHTTPResponse.GetRequest().GetRequestMethod(), string);
				fRequestsBuffer.AppendString (string);
				break;

			case LOG_TOKEN_BYTES_SENT:	//WLF : Bytes sent to the client : = HTTP Content Length
				string.Clear();
				if (inHTTPResponse.GetResponseHeader (STRING_HEADER_CONTENT_LENGTH, string) && !string.IsEmpty())
					fRequestsBuffer.AppendString (string);
				else
					fRequestsBuffer.AppendUniChar (CHAR_DIGIT_ZERO);
				break;

			case LOG_TOKEN_AGENT:	// The identity of the browser software or other client. Mozilla/4.04_(Macintosh;_U;_PPC)
				string.Clear();
				if (inHTTPResponse.GetRequest().GetHTTPHeaders().GetHeaderValue (STRING_HEADER_USER_AGENT, string) && !string.IsEmpty())
				{
					string.Exchange (CHAR_SPACE, CHAR_LOW_LINE);
					fRequestsBuffer.AppendString (string);
				}
				else
				{
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				}
				break;

			case LOG_TOKEN_CS_USER_AGENT:	// HTTP request's "User-Agent" header field. "Mozilla/4.04 (Macintosh; U; PPC)"
				string.Clear();
				inHTTPResponse.GetRequest().GetHTTPHeaders().GetHeaderValue (STRING_HEADER_USER_AGENT, string);
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				fRequestsBuffer.AppendString (string);
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				break;

			case LOG_TOKEN_USER:	//The User Name if there was a Web User entry for a realm.
				string.Clear();
				inHTTPResponse.GetRequest().GetAuthenticationInfos()->GetUserName (string);
				_WriteUsername (string, fRequestsBuffer);
				break;

			case LOG_TOKEN_REFERER: //HTTP request's "Referer" header field, sending  the URL that referred to the current page. www.google.com
				string.Clear();
				inHTTPResponse.GetRequest().GetHTTPHeaders().GetHeaderValue (STRING_HEADER_REFERER, string);
				if (!string.IsEmpty())
					fRequestsBuffer.AppendString (string);
				else
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				break;

			case LOG_TOKEN_CS_REFERER:	//HTTP request's "Referer" header field, sending  the URL that referred to the current page.  www.google.com
				string.Clear();
				inHTTPResponse.GetRequest().GetHTTPHeaders().GetHeaderValue (STRING_HEADER_REFERER, string);
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				fRequestsBuffer.AppendString (string);
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				break;

			case LOG_TOKEN_ELF_CS_HOST: // = LOG_TOKEN_HOSTFIELD. The "HOST" field of the HTTP request
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				fRequestsBuffer.AppendString (inHTTPResponse.GetRequest().GetHost());
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				break;

			case LOG_TOKEN_ELF_URI:
				string.FromString (inHTTPResponse.GetRequest().GetURL());
				if (!string.IsEmpty())
					fRequestsBuffer.AppendString (string);
				else
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				break;

			case LOG_TOKEN_URL:
			case LOG_TOKEN_ELF_CS_URI_STEM:	//	Path portion of the HTTP request. "/status/stat.html"
				string.FromString (inHTTPResponse.GetRequest().GetURLPath());
				if (!string.IsEmpty())
					fRequestsBuffer.AppendString (string);
				else
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				break;

			case LOG_TOKEN_SEARCH_ARGS:	//	The search arguments to the URL (text after a question  mark)
				string.FromString (inHTTPResponse.GetRequest().GetURLQuery());
				fRequestsBuffer.AppendString (string);
				break;

			case LOG_TOKEN_ELF_CS_URI_QUERY:	// 	Search argument portion of the HTTP request. "first=last&last=first"
				string.FromString (inHTTPResponse.GetRequest().GetURLQuery());
				if (!string.IsEmpty())
					fRequestsBuffer.AppendString (string);
				else
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				break;

			case LOG_TOKEN_CONNECTION_ID:	// A number that is unique for each connection for this invocation of the server. Typically socket number.
			{
				sLONG rawSocket = inHTTPResponse.GetRawSocket();
				if (rawSocket > 0)
				{
					fRequestsBuffer.AppendLong (rawSocket);
				}
				else
				{
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				}
				break;
			}
			case LOG_TOKEN_ELF_CS_COOKIE:	// The "cookie" information sent in this request "Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 20-Jan-05 23:12:40 GMT"
				string.Clear();
				inHTTPResponse.GetRequest().GetHTTPHeaders().GetHeaderValue (STRING_HEADER_COOKIE, string);
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				fRequestsBuffer.AppendString (string);
				fRequestsBuffer.AppendUniChar (CHAR_QUOTATION_MARK);
				break;

			case LOG_TOKEN_TRANSFER_TIME:	// Time-Taken in millisecond like IIS
			{
				uLONG timeTaken = (XBOX::VSystem::GetCurrentTime() - inHTTPResponse.GetStartRequestTime());
				fRequestsBuffer.AppendLong (timeTaken);
				break;
			}
			case LOG_TOKEN_WLF_BYTES_RECEIVED:
			{
				sLONG8 bytesReceived = inHTTPResponse.GetRequest().GetRequestBody().GetDataSize();
				if (bytesReceived > 0)
				{
					fRequestsBuffer.AppendLong8 (bytesReceived);
				}
				else
				{
					fRequestsBuffer.AppendUniChar (CHAR_DIGIT_ZERO);
				}
				break;
			}

			case LOG_TOKEN_PATH_ARGS: //The path arguments to the URL for a CGI (the text after a dollar sign)
			{
				sLONG			posChar = 0;
				XBOX::VString	pathArgString;
				
				string.FromString (inHTTPResponse.GetRequest().GetURL());

				if (!string.IsEmpty() && (posChar = string.FindUniChar (CHAR_DOLLAR_SIGN)) > 0)
				{
					// Let's delete all the stuff before '$'
					string.GetSubString (posChar + 1, string.GetLength() - posChar, pathArgString);

					// We delete the query arguments after the ? : we only want the string after the '$'
					if ((posChar = pathArgString.FindUniChar (CHAR_QUESTION_MARK)) > 0)
						pathArgString.SubString (1, posChar - 1);
				}

				if (!pathArgString.IsEmpty())
				{
					fRequestsBuffer.AppendString (pathArgString);
				}
				else
				{
					fRequestsBuffer.AppendUniChar (CHAR_HYPHEN_MINUS);
				}
				break;
			}

			default:	// this should never happen.
				assert (false);
				fRequestsBuffer.AppendCString ("UNKNOWN_FIELD"); 
				break;
		}

		VectorOfLogToken::const_iterator nextToken = it;
		if (++nextToken != tokens.end())
			fRequestsBuffer.AppendUniChar (CHAR_SPACE);
	}

	fRequestsBuffer.AppendUniChar (HTTP_LF);

	return XBOX::VE_OK;
}
// Environment block == null-terminated block of null-terminated strings of the form: name=value\0
char * XWinProcessLauncher::_CreateEnvironmentVariablesBlock(const EnvVarNamesAndValuesMap &inVarToUse)
{
	char	*initialEnvStrings = NULL;
	VMemoryBuffer<>		allStrings;
	char * theEnvVarBlock = NULL;

	// Initial environment variables
	initialEnvStrings = ::GetEnvironmentStrings();
	if(initialEnvStrings != NULL)
	{
		char *currentStr = initialEnvStrings;
		size_t	fullStrSize;
		while(*currentStr)
		{
			fullStrSize = strlen(currentStr) + 1;
			allStrings.PutData(allStrings.GetDataSize(), currentStr, fullStrSize);
			currentStr += fullStrSize;
		}
	}

	// Prepare our envir. variables
	if(!inVarToUse.empty())
	{
		XBOX::VString	oneEnvVarAndValue;
	// Calculate final buffer size (concatenate name=value and add the 0 terminattion)
		EnvVarNamesAndValuesMap::const_iterator	envVarIterator = inVarToUse.begin();
		while(envVarIterator != inVarToUse.end())
		{
			oneEnvVarAndValue = envVarIterator->first;
			if(!oneEnvVarAndValue.IsEmpty())
			{
				oneEnvVarAndValue += "=";
				oneEnvVarAndValue += envVarIterator->second;

				char *varValueCStr = _CreateCString(oneEnvVarAndValue);
				if(testAssert(varValueCStr != NULL))
				{
					allStrings.PutData(allStrings.GetDataSize(), varValueCStr, strlen(varValueCStr) + 1);
					delete [] varValueCStr;
				}
			}			
			++envVarIterator;
		}
	} //if(!inVarToUse.empty())

	if(allStrings.GetDataSize() > 0)
	{
		char	theZero = 0;
		allStrings.PutData(allStrings.GetDataSize(), &theZero, 1);

		theEnvVarBlock = new char[allStrings.GetDataSize()];
		if(testAssert(theEnvVarBlock))
			allStrings.GetData(0, theEnvVarBlock, allStrings.GetDataSize());
	}
	
	if(initialEnvStrings != NULL)
		::FreeEnvironmentStrings(initialEnvStrings);
	
	return theEnvVarBlock;

}