void VJSRequireClass::_getCurrentPath (VJSParms_callStaticFunction &ioParms, void *)
{
	VJSGlobalObject	*globalObject	= ioParms.GetContext().GetGlobalObjectPrivateInstance();
	
	xbox_assert(globalObject != NULL);

	XBOX::VFilePath	*path	= (XBOX::VFilePath *) globalObject->GetSpecific(VJSContext::kURLSpecificKey);
	
	xbox_assert(path != NULL);

	XBOX::VFilePath	parent;

	if (!path->GetParent(parent)) {

		ioParms.ReturnString("/");

	} else {

		XBOX::VString	posixPath;

		parent.GetPosixPath(posixPath);

		ioParms.ReturnString(posixPath);

	}
}
XBOX::VError VJSModuleState::LoadScript (const XBOX::VString &inURLString, XBOX::VURL *outURL, XBOX::VString *outScript)
{
	xbox_assert(outURL != NULL && outScript != NULL);

	outURL->FromFilePath(inURLString, eURL_POSIX_STYLE, CVSTR("file://"));

	XBOX::VError	error;
	XBOX::VFilePath	path;
					
	if (outURL->GetFilePath(path) && path.IsFile()) {

		XBOX::VFile			file(path);			
		XBOX::VFileStream	stream(&file);
				
		if ((error = stream.OpenReading()) == XBOX::VE_OK
		&& (error = stream.GuessCharSetFromLeadingBytes(XBOX::VTC_DefaultTextExport)) == XBOX::VE_OK) {

			stream.SetCarriageReturnMode(XBOX::eCRM_NATIVE);
			error = stream.GetText(*outScript);

		}
		stream.CloseReading();	// Ignore closing error, if any.

	} else

		error = XBOX::VE_JVSC_SCRIPT_NOT_FOUND;

	return error;
}
void VVirtualFolderSetting::LoadFromBag (const XBOX::VValueBag& inValueBag, const XBOX::VFilePath& inProjectFolderPath)
{
	inValueBag.GetString (RIASettingsKeys::VirtualFolders::name, fName);
	inValueBag.GetString (RIASettingsKeys::VirtualFolders::location, fLocation);
	inValueBag.GetString (RIASettingsKeys::VirtualFolders::index, fIndex);

	if (HTTPServerTools::BeginsWithASCIICString (fLocation, "http://") ||
		HTTPServerTools::BeginsWithASCIICString (fLocation, "https://"))
	{
		fUseRedirect = true;
	}
	else
	{
		XBOX::VFilePath path;
		BuildFolderPath (inProjectFolderPath, fLocation, path);
		if (path.IsFolder())
		{
			path.GetPath (fLocation);
		}
		else
		{
			XBOX::VFilePath	folder;
			XBOX::VString	string;

			path.GetFolder (folder);
			path.GetFileName (string);
			folder.ToSubFolder (string);
			folder.GetPath (fLocation);
		}
	}
}
void VHTTPServerLog::_GetLogFilePath (XBOX::VFilePath& outFilepath)
{
	XBOX::VFilePath logFolderPath (fSettings.GetLogPath());

	if (logFolderPath.IsValid() && logFolderPath.IsFolder())
	{
		XBOX::VFolder folder (fSettings.GetLogPath());

		if (!folder.Exists())
			folder.CreateRecursive();
	}

	outFilepath.FromFilePath (fSettings.GetLogPath());
	outFilepath.SetFileName (fSettings.GetLogFileName());
}
void VHTTPServerProject::_AddVirtualFoldersFromSettings (VVirtualHost *ioVirtualHost)
{
	if (fSettings->GetUseWALibVirtualFolder())
	{
		XBOX::VRefPtr<VFolder>	wakandaServerFolder;
#if VERSIONWIN
		wakandaServerFolder.Adopt (XBOX::VProcess::Get()->RetainFolder (XBOX::VProcess::eFS_Executable));
#else
		XBOX::VFilePath path (VProcess::Get()->GetExecutableFolderPath());

#if VERSION_LINUX
		//jmo - Check that : It should break on Mac !
		XBOX::VFolder *folder = new VFolder (path);
#else
		XBOX::VFolder *folder = new VFolder (path.ToParent());
#endif
		wakandaServerFolder.Adopt (folder);
#endif

		if (NULL != wakandaServerFolder)
		{
			XBOX::VString	indexFileName;
			XBOX::VString	keyword (CVSTR ("walib"));
			XBOX::VFilePath	waLibPath (wakandaServerFolder->GetPath());
			VVirtualFolder *virtualFolder = NULL;

			waLibPath.ToSubFolder (keyword);
			virtualFolder = fHTTPServer->RetainVirtualFolder (waLibPath.GetPath(), indexFileName, keyword);
			if (NULL != virtualFolder)
				ioVirtualHost->AddVirtualFolder (virtualFolder);

			XBOX::ReleaseRefCountable (&virtualFolder);

			// Temp for WAK3 - Support "webComponents" VirtualFolder
			// TODO: Use .waResources settings later
			XBOX::VFilePath	webComponentsPath (wakandaServerFolder->GetPath());
			webComponentsPath.ToSubFolder (CVSTR ("resources")).ToSubFolder (CVSTR ("Web Components"));
			virtualFolder = fHTTPServer->RetainVirtualFolder (webComponentsPath.GetPath(), indexFileName, CVSTR ("webComponents"));
			if (NULL != virtualFolder)
				ioVirtualHost->AddVirtualFolder (virtualFolder);

			XBOX::ReleaseRefCountable (&virtualFolder);
		}

		// Load Virtual Folders from settings
		const VVirtualFolderSettingsVector&	virtualFolderSettings = fSettings->GetVirtualFoldersVector();
		for (VVirtualFolderSettingsVector::const_iterator it = virtualFolderSettings.begin(); it != virtualFolderSettings.end(); ++it)
		{
			VVirtualFolder *virtualFolder = fHTTPServer->RetainVirtualFolder ((*it)->GetLocation(), (*it)->GetIndex(), (*it)->GetName());
			if (NULL != virtualFolder)
				ioVirtualHost->AddVirtualFolder (virtualFolder);

			XBOX::ReleaseRefCountable (&virtualFolder);
		}
	}
}
예제 #6
0
JS4D::ObjectRef JS4D::VFilePathToObjectAsFileOrFolder( ContextRef inContext, const XBOX::VFilePath& inPath, ValueRef *outException)
{
	ObjectRef value;
	if (inPath.IsFolder())
	{
		VFolder *folder = new VFolder( inPath);
		value = VFolderToObject( inContext, folder, outException);
		ReleaseRefCountable( &folder);
	}
	else if (inPath.IsFile())
	{
		VFile *file = new VFile( inPath);
		value = VFileToObject( inContext, file, outException);
		ReleaseRefCountable( &file);
	}
	else
	{
		value = JSValueToObject( inContext, JSValueMakeNull( inContext), outException);	// exception instead ?
	}
	return value;
}
/* private */
void VVirtualFolder::_NormalizeFolder()
{
	assert (NULL != fFolder);

	if (!fFolder->Exists())
		fFolder->CreateRecursive();

	if (fFolder->Exists())
	{
		XBOX::VFilePath folderPath (fFolder->GetPath());
		XBOX::VFilePath indexPath;

		indexPath = folderPath.ToSubFile (fIndexFileName);

		if (indexPath.IsFile())
		{
			XBOX::VFile indexFile (indexPath);

			if (!indexFile.Exists())
			{
				XBOX::VFolder *componentFolder = VHTTPServer::RetainComponentFolder (kBF_RESOURCES_FOLDER);

				if (NULL != componentFolder)
				{
					XBOX::VFilePath		defaultIndexPath = componentFolder->GetPath();
					XBOX::DialectCode	dialectCode = XBOX::VIntlMgr::GetDefaultMgr()->GetCurrentDialectCode();
					XBOX::VString		languageCode;
					XBOX::VString		fileName;

					XBOX::VIntlMgr::GetDefaultMgr()->GetISO6391LanguageCode (dialectCode, languageCode);

					fileName.AppendCString ("index_");
					fileName.AppendString (languageCode);
					fileName.AppendCString (".html");

					defaultIndexPath.ToSubFolder (CVSTR ("Default Page")).ToSubFile (fileName);

					if (defaultIndexPath.IsFile())
					{
						XBOX::VFile defaultIndexFile (defaultIndexPath);

						if (defaultIndexFile.Exists())
							indexFile.CopyFrom (defaultIndexFile);
					}

					XBOX::QuickReleaseRefCountable (componentFolder);
				}
			}
		}
	}
}
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);
		}
	}
}
XBOX::VError VHTTPServerLog::_RotateFile()
{
	XBOX::VError	error = XBOX::VE_OK;
	XBOX::VFilePath	logFilePath;
	XBOX::VTime		curTime;

	curTime.FromSystemTime();

	_GetLogFilePath (logFilePath);

	if (fLogFileAccessLock.Lock())
	{
		if (NULL == fLogFile)
			fLogFile = new XBOX::VFile (logFilePath);

		if (fLogFile->Exists())
		{
			// the backup fileName will look like "HTTPServer_DAAAAMMJJT00000000.waLog" => "HTTPServer_D20100122T113307.waLog"
			// I used this format to have the files sorted by time thanks to their name

			XBOX::VString	newFileName;
			XBOX::VString	dateTimeString;

			GetFormatedDateTimeString (curTime, dateTimeString);

			fLogFile->GetNameWithoutExtension (newFileName);
			newFileName.AppendUniChar (CHAR_LOW_LINE);
			newFileName.AppendString (dateTimeString);
			newFileName.AppendUniChar (CHAR_FULL_STOP);
			newFileName.AppendString (fSettings.GetLogFileNameExtension());

			if (fSettings.GetArchivesFolderName().IsEmpty())
			{
				error = fLogFile->Rename (newFileName);
			}
			else
			{
				XBOX::VFilePath	destinationFilePath;

				fLogFile->GetPath (destinationFilePath);
				destinationFilePath.ToParent().ToSubFolder (fSettings.GetArchivesFolderName());

				if (destinationFilePath.IsFolder())
				{
					XBOX::VFolder *	destinationFolder = new XBOX::VFolder (destinationFilePath);
					if (NULL != destinationFolder)
					{
						if (!destinationFolder->Exists())
							error = destinationFolder->CreateRecursive();
						XBOX::ReleaseRefCountable (&destinationFolder);

						if (XBOX::VE_OK == error)
						{
							destinationFilePath.SetFileName (newFileName);

							error = fLogFile->Move (destinationFilePath, NULL, XBOX::FCP_Overwrite);
						}
					}
					else
					{
						error = XBOX::VE_MEMORY_FULL;
					}
				}
			}

			XBOX::ReleaseRefCountable (&fLogFile);
		}

		//Creating the log file
		if ((XBOX::VE_OK == error) && (NULL == fLogFile))
		{
			fLogFile = new XBOX::VFile (logFilePath);
			if (NULL != fLogFile)
			{
				error = fLogFile->Create();

				// Set correct dates & times (used later to determine the next backup time)
				if (XBOX::VE_OK == error)
					error = fLogFile->SetTimeAttributes (&curTime, &curTime, &curTime);
				fLogFileSize = 0;
				
				fLastFileRotationTime.FromTime (curTime);
				_CalculateNextFileRotationTime();
			}
			else
			{
				error = VE_CANNOT_CREATE_LOG_FILE;
			}
		}
		else
		{
			error = VE_CANNOT_OPEN_LOG_FILE;
		}

		fNeedSplit = false;
		fLogFileAccessLock.Unlock();
	}

	return error;
}
XBOX::VError VHTTPServerLog::_Flush()
{
	XBOX::VFilePath	logFilePath;
	XBOX::VError	error = XBOX::VE_OK;

	_GetLogFilePath (logFilePath);

	if (!logFilePath.IsValid())
		return XBOX::VE_FILE_NOT_FOUND;

	if (fLogFileAccessLock.Lock())
	{
		if (NULL == fLogFile)
			fLogFile = new XBOX::VFile (logFilePath);

		if (testAssert (NULL != fLogFile))
		{
			XBOX::VFileDesc *fileDesc = NULL;

			error = fLogFile->Open (XBOX::FA_READ_WRITE, &fileDesc, XBOX::FO_CreateIfNotFound);

			if ((XBOX::VE_OK == error) && (NULL != fileDesc))
			{
				sLONG8 logFileSize = fileDesc->GetSize();

				if ((CHAR_NUMBER_SIGN != fRequestsBuffer.GetUniChar (1)) && (0 == logFileSize))
				{
					XBOX::VString fileHeader;
					_WriteFileHeader (fileHeader);

					XBOX::StStringConverter<char> buffer (fileHeader, XBOX::VTC_DefaultTextExport);
					fileDesc->SetPos (fileDesc->GetSize());
					error = fileDesc->PutDataAtPos (buffer.GetCPointer(), buffer.GetSize());
					fileDesc->Flush();
				}

				if (fLogBufferAccessLock.Lock())
				{
					// Flushing the buffer
					XBOX::StStringConverter<char> buffer (fRequestsBuffer, XBOX::VTC_DefaultTextExport);
					fileDesc->SetPos (fileDesc->GetSize());
					error = fileDesc->PutDataAtPos (buffer.GetCPointer(), buffer.GetSize());

					fRequestsBuffer.Clear();
					fRequestsInBuffer = 0;

					fLogBufferAccessLock.Unlock();
				}

				error = fileDesc->Flush();
				fLogFileSize = fileDesc->GetSize();
				delete fileDesc;
				fileDesc = NULL;
			}
			else
			{
				error = VE_CANNOT_OPEN_LOG_FILE;
			}
		}
		else
		{
			error = VE_CANNOT_CREATE_LOG_FILE;
		}

		fLogFileAccessLock.Unlock();

		_CalculateNextFileRotationTime();
	}

	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;
}
void VHTTPServerProjectSettings::SetWebFolderPath (const XBOX::VFilePath& inValue)
{
	BuildFolderPath (fProjectFolderPath, inValue.GetPath(), fWebFolderPath);

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