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);
			}
		}
	}
}
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);
}
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();
}
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;
}
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);
		}
	}
}
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;
}
// 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;
}