void TrimUniChar (XBOX::VString& ioString, const UniChar inCharToTrim)
{
	if (ioString.GetLength() > 0)
	{
		sLONG			length = ioString.GetLength();
		UniChar *		data = (UniChar *)ioString.GetCPointer();
		XBOX::VIndex	leadingChars = 0;
		XBOX::VIndex	endingChars = 0;

		for (UniChar *p = data, *end = (data + length); (p != end) && (*p == inCharToTrim); p++, leadingChars++);
		for (UniChar *p = (data + length - 1), *start = (data - 1); (p != start) && (*p == inCharToTrim); p--, endingChars++);

		if ((0 != leadingChars) || (0 != endingChars))
		{
			if ((leadingChars + endingChars) >= length)
			{
				ioString.Clear();
			}
			else
			{
				ioString.SubString (leadingChars + 1, length - leadingChars - endingChars);
			}
		}
	}
}
void VJSTextStream::_Read (VJSParms_callStaticFunction &ioParms, VJSTextStreamState *inStreamState)
{
	if (inStreamState == NULL)

		XBOX::vThrowError(XBOX::VE_JVSC_INVALID_STATE, L"TextStream.read()");

	else if (ioParms.CountParams() == 1 && ioParms.IsStringParam(1)) {

		XBOX::VString	delimiter;

		if (!ioParms.GetStringParam(1, delimiter) || delimiter.GetLength() > 1)

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_STRING, "1");
			
		else {

			XBOX::VString	result;
			bool			hasBeenFound;

			hasBeenFound = inStreamState->_ReadUntilDelimiter(delimiter, &result);
			inStreamState->fPosition += result.GetLength();
			if (hasBeenFound)

				inStreamState->fPosition++;	// Delimiter is not included.

			ioParms.ReturnString(result);
		
		}

	} else {

		// numberCharacters is the number of actual characters to read, not the number of bytes.
				
		sLONG	numberCharacters;

		numberCharacters = 0;
		if (ioParms.CountParams() >= 1 && (!ioParms.GetLongParam(1, &numberCharacters) || numberCharacters < 0))

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");
			
		else {

			XBOX::VString	result;
		
			inStreamState->_ReadCharacters(numberCharacters, &result);
			inStreamState->fPosition += result.GetLength();
			ioParms.ReturnString(result);

		}

	}
}
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 ToXMLCompatibleText(const XBOX::VString& inText, XBOX::VString& outText)
{
	outText = inText;
	sLONG len = inText.GetLength();
	outText.Exchange( CVSTR("&"), CVSTR("&amp;"), 1, len);
	len = outText.GetLength();
	outText.Exchange( CVSTR("<"), CVSTR("&lt;"), 1, len);
	len = outText.GetLength();
	outText.Exchange( CVSTR(">"), CVSTR("&gt;"), 1, len);	
	outText.ConvertCarriageReturns(XBOX::eCRM_CR);
	len = outText.GetLength();
	outText.Exchange( CVSTR("\r"), CVSTR("<BR/>"), 1, len);
	len = outText.GetLength();
	outText.Exchange( CVSTR("\13"), CVSTR("<BR/>"), 1, len);//[MI] le 28/12/2010 ACI0069253
}
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);
	}
}
void GetIPv4FromString (const XBOX::VString& inIPv4String, IP4& outIPv4)
{
	sLONG	hostNameSize = inIPv4String.GetLength() + 1;
	char *	hostName = new char[hostNameSize];

	outIPv4 = INADDR_NONE;
	if (NULL != hostName)
	{
		struct hostent *	remoteHost = NULL;
		struct in_addr		addr = {0};

		inIPv4String.ToCString (hostName, hostNameSize);

		if (isalpha (hostName[0]))	// host address is a name
		{
			remoteHost = gethostbyname (hostName);
		}
		else
		{
			addr.s_addr = inet_addr (hostName);
			if (addr.s_addr != INADDR_NONE)
				remoteHost = gethostbyaddr ((char *) &addr, 4, AF_INET);
		}

		if (NULL != remoteHost)
			outIPv4 = *((sLONG *)remoteHost->h_addr_list[0]);

		delete [] hostName;
	}
}
sLONG GetLongFromString (const XBOX::VString& inString)		
{
	bool	isneg = false;		

	XBOX::VIndex sepPos = HTTPServerTools::FindASCIIVString (inString, XBOX::VIntlMgr::GetDefaultMgr()->GetDecimalSeparator());
	if (sepPos <= 0)
		sepPos = inString.GetLength();

	const UniChar* bb = inString.GetCPointer();
	sLONG result = 0;
	for (XBOX::VIndex i = 0; i < sepPos; ++i)
	{
		if ((0 == result) && (bb[i] == CHAR_HYPHEN_MINUS))
			isneg = true;
		if ((bb[i] < CHAR_DIGIT_ZERO) || (bb[i] > CHAR_DIGIT_NINE))
			continue;
		result *= 10;
		result += bb[i] - CHAR_DIGIT_ZERO;
	}

	if (isneg)
		result = -result;
	
	return result;
}
bool EndsWithASCIICString (const XBOX::VString& inText, const char *inPattern, bool isCaseSensitive)
{
	sLONG textSize = inText.GetLength();
	sLONG patternSize = (sLONG)strlen (inPattern);

	return (_FindASCIICString (inText.GetCPointer() + (textSize - patternSize), textSize, inPattern, patternSize, isCaseSensitive) == 1);
}
IHTTPRequestHandler *VHTTPServerProject::RetainMatchingHTTPRequestHandler (const XBOX::VString& inURL)
{
	IHTTPRequestHandler *resultHandler = NULL;
	XBOX::VTaskLock		lock (&fRegexCacheLock);
	XBOX::VString		urlString (inURL);
/*
	// URL Start with project pattern ?
	if (!fSettings->GetProjectPattern().IsEmpty())
	{
		sLONG pos = HTTPServerTools::FindASCIIVString (urlString, fSettings->GetProjectPattern());
		if (pos == 2) // Takes the starting CHAR_SOLIDUS into account
			inURL.GetSubString (pos + fSettings->GetProjectPattern().GetLength(), inURL.GetLength() - fSettings->GetProjectPattern().GetLength() - 1, urlString);
	}
*/

	resultHandler = RetainProcessingHandler<IHTTPRequestHandler> (fRegexCache, urlString, false);

	/* YT 18-Jan-2012 - ACI0075015, ACI0074936 & ACI0074300
		When no requestHandler match and the URL ends by SOLIDUS '/', try to find a requestHandler matching the URL + 
		the index page name (typically for 4D: /index.shtml have to be handled by a specific requestHandler)
	*/
	if ((NULL == resultHandler) && (urlString.GetUniChar (urlString.GetLength()) == CHAR_SOLIDUS))
	{
		urlString.AppendString (fSettings->GetIndexPageName());

		resultHandler = RetainProcessingHandler<IHTTPRequestHandler> (fRegexCache, urlString, false);
	}

	return resultHandler;
}
void GetSubString (const XBOX::VString& inString, sLONG inFirst, sLONG inLast, XBOX::VString& outString)
{
	if (testAssert ((inFirst >= 0) && (inLast < inString.GetLength())))
		outString.FromBlock (inString.GetCPointer() + inFirst, (inLast - inFirst + 1) * sizeof(UniChar), XBOX::VTC_UTF_16);
	else
		outString.Clear();
}
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;;
}
	bool HttpRequest::SetUserInfos(const XBOX::VString& inUser, const XBOX::VString& inPasswd, bool inAllowBasic)
	{
		if(!fHandle)
            return false;
		
		XBOX::VString userInfos;
		userInfos.AppendString(inUser).AppendCString(":").AppendString(inPasswd);
	
		int maxlen=2*userInfos.GetLength()+1;  //We convert utf16 to utf8, it should be large enough.
        char* buf=new char[maxlen];
		
        if(!buf)
            return false;
		
		int len=userInfos.ToBlock(buf, maxlen, XBOX::VTC_UTF_8, true, false);
		
		curl_easy_setopt(fHandle, CURLOPT_USERPWD, buf);
		
		delete buf;
		
		if(inAllowBasic)
			curl_easy_setopt(fHandle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST);
		else	
			curl_easy_setopt(fHandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
		
		return true;
	}
Example #13
0
void VJSMessagePort::SetCallbackName (VJSWorker *inWorker, const XBOX::VString &inCallbackName)
{
    xbox_assert(inWorker != NULL && (inWorker == fOutsideWorker || inWorker == fInsideWorker));
    xbox_assert((inWorker == fOutsideWorker && !fOutsideClosingFlag) || (inWorker == fInsideWorker && !fInsideClosingFlag));
    xbox_assert(inCallbackName.GetLength());

    if (inWorker == fOutsideWorker)

        fOutsideCallbackName = inCallbackName;

    else

        fInsideCallbackName = inCallbackName;
}
    std::string StdStringFromAsciiVString(const XBOX::VString inStr)
    {
        int len=inStr.GetLength();
        char* buf=new char[len];

        if(!buf)
            return std::string();

        inStr.ToBlock(buf, len, XBOX::VTC_US_ASCII, false, false);

        std::string outStr(buf, len);
        delete[] buf;

        return outStr;
    }
void ParseHostString (const XBOX::VString& inHostString, XBOX::VString& outIPv4String, PortNumber& outPort)
{
	XBOX::VIndex pos = inHostString.FindUniChar (CHAR_COLON);

	if (pos > 0)
	{
		XBOX::VString	portString;
		inHostString.GetSubString (1, pos - 1, outIPv4String);
		inHostString.GetSubString (pos + 1, inHostString.GetLength() - pos, portString);

		outPort = portString.GetLong();
	}
	else
	{
		outIPv4String.FromString (inHostString);
		outPort = DEFAULT_LISTENING_PORT;
	}
}
    bool HttpRequest::SetData(const XBOX::VString& inData, XBOX::CharSet inCS)
    {
        int maxlen=2*inData.GetLength();  //We convert utf16 to utf8, it should be large enough.
        char* buf=new char[maxlen];

        if(!buf)
            return false;

        //int len=inData.ToBlock(buf, maxlen, XBOX::VTC_UTF_8, false, false);

        inCS=(inCS!=XBOX::VTC_UNKNOWN ? inCS : XBOX::VTC_US_ASCII); 
        int len=inData.ToBlock(buf, maxlen, inCS, false, false);

        int count=fData.AddRawPtr(buf, len);

        delete(buf);

        fReqHdrs.FixContentThings();

		curl_easy_setopt(fHandle, CURLOPT_POSTFIELDSIZE, count);

        return len==count;
    }
void VJSTextStream::_Write (VJSParms_callStaticFunction &ioParms, VJSTextStreamState *inStreamState)
{
	if (inStreamState == NULL && !inStreamState->fStream->IsWriting()) 

		XBOX::vThrowError(XBOX::VE_JVSC_INVALID_STATE, L"TextStream.write()");

	else {

		XBOX::VString	string;
 
		if (ioParms.CountParams() != 1 || !ioParms.IsStringParam(1) || !ioParms.GetStringParam(1, string))
	
			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");

		else {
	
			inStreamState->fStream->PutText(string);
			inStreamState->fPosition += string.GetLength();

		}

	}
}
XBOX::VError SendValueBagResponse (IHTTPResponse& ioResponse, const XBOX::VValueBag& inBag, const XBOX::VString& inBagName)
{
	XBOX::VError		error = XBOX::VE_OK;
	const XBOX::VString	stringURL = ioResponse.GetRequest().GetURLQuery();
	HTTPRequestMethod	method = ioResponse.GetRequest().GetRequestMethod();
	XBOX::VString		resultString;
	bool				isJSON = true;
	bool				prettyFormatting = false;
	bool				isValidRequest = ((method == HTTP_GET) || (method == HTTP_HEAD));

	if (isValidRequest)
	{
		sLONG			posFormat = 0, posPretty = 0;
		const UniChar *	stringPtr = stringURL.GetCPointer();
		const sLONG		stringLen = stringURL.GetLength();

		if ((posFormat = HTTPServerTools::FindASCIICString (stringPtr, "format=")) > 0)
		{
			posFormat += 6;

			sLONG startPos = 0;
			sLONG endPos = HTTPServerTools::FindASCIICString (stringPtr + posFormat, "&");
			if (endPos <= 0)
				endPos = stringLen;
			else
				endPos += (posFormat - 1);

			if (((startPos = HTTPServerTools::FindASCIICString (stringPtr + posFormat, "xml")) > 0) && (startPos < endPos))
				isJSON = false;
			else if(((startPos = HTTPServerTools::FindASCIICString (stringPtr + posFormat, "json")) > 0) && (startPos < endPos))
				isJSON = true;
			else
				isValidRequest = false;
		}

		if ((posPretty = HTTPServerTools::FindASCIICString (stringPtr, "pretty=")) > 0)
		{
			XBOX::VString prettyString;

			posPretty += 6;
			sLONG endPos = HTTPServerTools::FindASCIICString (stringPtr + posPretty, "&");
			if (endPos <= 0)
				endPos = stringLen;
			else
				endPos += (posPretty - 1);

			if (endPos > posPretty)
			{
				GetSubString (stringURL, posPretty, endPos - 1, prettyString);
				prettyFormatting = (HTTPServerTools::EqualASCIICString (prettyString, "yes"));
			}
			else
				isValidRequest = false;
		}
	}

	if (isValidRequest)
	{
		if (isJSON)
		{
			inBag.GetJSONString (resultString, prettyFormatting ? JSON_PrettyFormatting : JSON_Default);
		}
		else
		{
			resultString.FromCString ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
			inBag.DumpXML (resultString,  inBagName, prettyFormatting);
		}

		XBOX::StStringConverter<char> buffer (resultString, XBOX::VTC_UTF_8);

		error = ioResponse.SetResponseBody (buffer.GetCPointer(), buffer.GetLength());

		ioResponse.SetExpiresHeader (GMT_NOW);
		ioResponse.AddResponseHeader (STRING_HEADER_PRAGMA, STRING_HEADER_VALUE_NO_CACHE);
		ioResponse.AddResponseHeader (STRING_HEADER_CONTENT_TYPE, (isJSON) ? STRING_CONTENT_TYPE_JSON : STRING_CONTENT_TYPE_XML);

		ioResponse.SetContentLengthHeader (buffer.GetLength());
		ioResponse.AllowCompression (true);
	}
	else
	{
		error = ioResponse.ReplyWithStatusCode (HTTP_BAD_REQUEST);
	}

	return error;
}
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;
}
// 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;
}
bool VJSTextStreamState::_ReadUntilDelimiter (const XBOX::VString &inDelimiter, XBOX::VString *outResult)
{
	bool	isFound	= false;

	sLONG	numberCharactersLeft;
	
	numberCharactersLeft = fBuffer.GetLength() - fIndex;
	outResult->Clear();

	if (!inDelimiter.GetLength()) {

		for ( ; ; ) {

			if (!numberCharactersLeft) {

				fBuffer.Clear();
				fIndex = 0;

				XBOX::VError	error;

				if ((error = fStream->GetText(fBuffer, kREAD_SLICE_SIZE)) != XBOX::VE_OK && error != XBOX::VE_STREAM_EOF) 
					
					break;				// Error!
				
				if (!(numberCharactersLeft = fBuffer.GetLength()))
						
					break;				// End-of-file.

			}

			const UniChar	*p, *q;

			for (p = q = fBuffer.GetCPointer() + fIndex; *q != 0 && *q != '\r' && *q != '\n'; q++)

				;

			if (*q) {

				outResult->AppendUniChars(p, q - p);

				fIndex = 1 + (q - fBuffer.GetCPointer());
				if (fIndex == fBuffer.GetLength()) {

					fBuffer.Clear();
					fIndex = 0;

				}
				isFound = true;
				break;

			} else {

				outResult->AppendUniChars(p, fBuffer.GetLength() - fIndex);
				numberCharactersLeft = 0;

			}

		}

	} else {

		UniChar	delimiter;
		
		delimiter = inDelimiter[0];
		for ( ; ; ) {

			if (!numberCharactersLeft) {
				
				fBuffer.Clear();
				fIndex = 0;

				XBOX::VError	error;

				if ((error = fStream->GetText(fBuffer, kREAD_SLICE_SIZE)) != XBOX::VE_OK && error != XBOX::VE_STREAM_EOF) 
					
					break;				// Error!
				
				if (!(numberCharactersLeft = fBuffer.GetLength()))
						
					break;				// End-of-file.

			}

			VIndex	index;

			if ((index = fBuffer.FindUniChar(delimiter, fIndex + 1))) {

				// Remember that fIndex starts at zero and index at one.

				outResult->AppendUniChars(fBuffer.GetCPointer() + fIndex, index - (fIndex + 1));
				if (index == fBuffer.GetLength()) {

					fBuffer.Clear();
					fIndex = 0;

				} else 

					fIndex = index;	// fIndex now indexes next character!

				isFound = true;
				break;

			} else {

				outResult->AppendUniChars(fBuffer.GetCPointer() + fIndex, fBuffer.GetLength() - fIndex);
				numberCharactersLeft = 0;

			}
	
		}

	}

	return isFound;
}
void VJSNetServerClass::_listen (XBOX::VJSParms_callStaticFunction &ioParms, VJSNetServerObject *inServer)
{
	xbox_assert(inServer != NULL);

	XBOX::VString	address;
	sLONG			port;

	if (!ioParms.CountParams()) {

		XBOX::vThrowError(XBOX::VE_JVSC_EXPECTING_PARAMETER, "net.Server.listen()");
		return;

	}

	if (!ioParms.IsNumberParam(1) || !ioParms.GetLongParam(1, &port)) {
		
		XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");
		return;

	}

	XBOX::VString	hostname;
	XBOX::VJSObject	callback(ioParms.GetContext());
	bool			hasCallback;

	hostname = "";
	hasCallback = false;
	if (ioParms.CountParams() >= 2) {

		if (ioParms.IsStringParam(2)) {
			
			if (!ioParms.GetStringParam(2, hostname)) {

				XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_STRING, "2");
				return;

			}

		} else if (ioParms.IsObjectParam(2) && ioParms.GetParamFunc(2, callback)) {

			hasCallback = true;

		} else {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_FUNCTION, "2");
			return;

		}

	} 

	if (ioParms.CountParams() == 3 ) {
	
		if ((hasCallback || !ioParms.IsObjectParam(3) || !ioParms.GetParamFunc(3, callback))) {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_FUNCTION, "3");
			return;

		} else

			hasCallback = true;

	}

	// We are already listening, stop previous listener.

	if (inServer->fConnectionListener != NULL)

		inServer->Close();

	// Set up listener.
	
	if ((inServer->fConnectionListener = new XBOX::VTCPConnectionListener())== NULL) {

		XBOX::vThrowError(XBOX::VE_MEMORY_FULL);
		return;

	} 

	if (inServer->fIsSSL)

		inServer->fConnectionListener->SetSSLKeyAndCertificate(inServer->fCertificate, inServer->fKey);

	VJSNetSocketObject::sMutex.Lock();

	if (VJSNetSocketObject::sSelectIOPool == NULL)

		VJSNetSocketObject::sSelectIOPool = new XBOX::VTCPSelectIOPool();

	VJSNetSocketObject::sMutex.Unlock();

	inServer->fConnectionListener->AddSelectIOPool(VJSNetSocketObject::sSelectIOPool);

	VJSWorker	*worker;

	worker = VJSWorker::RetainWorker(ioParms.GetContext());

	VJSConnectionHandlerFactory	*connectionHandlerFactory;
	
	if ((connectionHandlerFactory = new VJSConnectionHandlerFactory(worker, inServer, inServer->fIsSSL)) == NULL) {

		XBOX::vThrowError(XBOX::VE_MEMORY_FULL);
		XBOX::ReleaseRefCountable<VJSWorker>(&worker);
		return;

	}

#if WITH_DEPRECATED_IPV4_API
	
	sLONG	resolvedAddress;

	if (hostname.GetLength()) {

		address = hostname;
		resolvedAddress = XBOX::ServerNetTools::ResolveAddress(hostname);

	} else {

		address = "0.0.0.0";

		std::vector<IP4>	localIPs;

		if (XBOX::ServerNetTools::GetLocalIPv4Addresses(localIPs))

			resolvedAddress = localIPs[0];

		else

			resolvedAddress = 0;	// Should be same as above.

	}

	connectionHandlerFactory->SetIP(resolvedAddress);

#else

	XBOX::VNetAddressList	addrList;
	bool				isIPv6;

	if (hostname.GetLength()) {

		XBOX::VNetAddress	addr(hostname, port);

		isIPv6 = addr.IsV6();
		addrList.FromDnsQuery(hostname, port);
		
	} else {

		addrList.FromLocalInterfaces();
		isIPv6 = false;

	}

	// Always take first matching type address.

	XBOX::VNetAddressList::const_iterator	it;

	for (it = addrList.begin(); it != addrList.end(); it++)

		if ((*it).IsV6() == isIPv6)

			break;

	address = (*it).GetIP();
		
	connectionHandlerFactory->SetIP(address);

#endif	

	connectionHandlerFactory->AddNewPort(port);

	XBOX::VError	error;

	error = inServer->fConnectionListener->AddConnectionHandlerFactory(connectionHandlerFactory);
	connectionHandlerFactory->Release();	// AddConnectionHandlerFactory() has done a retain().

	if (error != XBOX::VE_OK 
	|| (error = inServer->fConnectionListener->StartListening()) != XBOX::VE_OK) 
		
		XBOX::vThrowError(error);

	else {

		inServer->fAddress = address;
		inServer->fPort = port;
			
		if (hasCallback) 
			
			inServer->AddListener("listening", callback, false);
		
		worker->QueueEvent(VJSNetEvent::Create(inServer, "listening"));

	}
	XBOX::ReleaseRefCountable<VJSWorker>(&worker);
}
/*
	static
*/
DialectCode	VComponentManager::GetLocalizationLanguage(VFolder * inLocalizationResourcesFolder,bool inGotoResourceFolder)
{
	DialectCode sResult = XBOX::DC_NONE;	// sc 19/05/2008 was XBOX::DC_ENGLISH_US
	VFolder * localizationResourcesFolder = NULL;
	
	if(testAssert(inLocalizationResourcesFolder != NULL && inLocalizationResourcesFolder->Exists()))
	{
		if (inGotoResourceFolder)
		{
			XBOX::VFilePath componentOrPluginFolderPath = inLocalizationResourcesFolder->GetPath();
			componentOrPluginFolderPath.ToSubFolder(CVSTR("Contents")).ToSubFolder(CVSTR("Resources"));
			localizationResourcesFolder = new XBOX::VFolder(componentOrPluginFolderPath);
		}
		else
		{
			localizationResourcesFolder = inLocalizationResourcesFolder;
			localizationResourcesFolder->Retain();
		}

		bool englishFolderDetected = false;
		XBOX::DialectCode dialectCode = XBOX::DC_NONE;
		
		//Detect what is the favorite language of the OS/App
#if VERSIONWIN
		LCID lcid = ::GetUserDefaultLCID();
		XBOX::DialectCode currentDialectCode = (XBOX::DialectCode)LANGIDFROMLCID(lcid);

#elif VERSION_LINUX

		//jmo - Be coherent with code in VIntlMgr.cpp
		XBOX::DialectCode currentDialectCode=XBOX::DC_ENGLISH_US;   // Postponed Linux Implementation !
		
#else

		CFBundleRef	bundle = ::CFBundleGetMainBundle();
		XBOX::DialectCode currentDialectCode = XBOX::DC_ENGLISH_US;
		if ( bundle != nil ){
			CFArrayRef array_ref = ::CFBundleCopyBundleLocalizations(bundle);			
			if (array_ref != nil){
				CFArrayRef usedLanguages = ::CFBundleCopyPreferredLocalizationsFromArray(array_ref);
				CFStringRef cfPrimaryLanguage = (CFStringRef)CFArrayGetValueAtIndex(usedLanguages, 0);
				XBOX::VString xboxPrimaryLanguage;
				xboxPrimaryLanguage.MAC_FromCFString(cfPrimaryLanguage);
				::CFRelease(usedLanguages);
				if(!XBOX::VIntlMgr::GetDialectCodeWithISOLanguageName(xboxPrimaryLanguage, currentDialectCode))
					if(!XBOX::VIntlMgr::GetDialectCodeWithRFC3066BisLanguageCode(xboxPrimaryLanguage, currentDialectCode))
						currentDialectCode = XBOX::DC_ENGLISH_US;
				CFRelease(array_ref);
			}
		}
#endif
		//Try to see if we have this language. If not, take english
		for ( XBOX::VFolderIterator folderIter( localizationResourcesFolder ); folderIter.IsValid() && currentDialectCode != dialectCode ; ++folderIter )
		{
			XBOX::VString folderName;
			folderIter->GetName(folderName);
			uLONG posStr = folderName.Find(CVSTR(".lproj"), 1, false);
			if ( posStr > 0 )
			{
				folderName.Remove(posStr, folderName.GetLength() - posStr + 1);
				if( XBOX::VIntlMgr::GetDialectCodeWithRFC3066BisLanguageCode(folderName, dialectCode ) || XBOX::VIntlMgr::GetDialectCodeWithISOLanguageName(folderName, dialectCode)){
					if(dialectCode == XBOX::DC_ENGLISH_US)
						englishFolderDetected = true;
					
					if(currentDialectCode == dialectCode)
						sResult = dialectCode;
				}
			}
		}
		
		if ( sResult == XBOX::DC_NONE ){
			if ( englishFolderDetected ) 
				sResult = XBOX::DC_ENGLISH_US;
			else 
				sResult = dialectCode;
		}
		
		ReleaseRefCountable(&localizationResourcesFolder);
	}
	
	return sResult;
}
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;
}
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
}