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; }
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; } }
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 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::SaveToBag (XBOX::VValueBag *outBag) { if (NULL == outBag) return XBOX::VE_INVALID_PARAMETER; XBOX::VValueBag *projectSettings = new XBOX::VValueBag (); if (projectSettings) { XBOX::VString ipString; XBOX::VString authTypeString; #if WITH_DEPRECATED_IPV4_API ServerNetTools::GetIPAdress (fListeningAddress, ipString); #else ipString.FromString (fListeningAddress); #endif HTTPServerTools::GetAuthenticationMethodName (fAuthType, authTypeString); projectSettings->SetLong (RIASettingsKeys::Project::refCount, GetRefCount()); projectSettings->SetString (RIASettingsKeys::Project::listen, ipString); projectSettings->SetString (RIASettingsKeys::Project::hostName, fHostName); #if HTTP_SERVER_USE_PROJECT_PATTERNS projectSettings->SetString (RIASettingsKeys::Project::pattern, fProjectPattern); #endif projectSettings->SetString (RIASettingsKeys::Project::realm, fRealm); projectSettings->SetString (RIASettingsKeys::Project::authType, authTypeString); outBag->AddElement (RIASettingsKeys::Project::kXmlElement, projectSettings); XBOX::ReleaseRefCountable (&projectSettings); } XBOX::VValueBag *httpSettings = new XBOX::VValueBag (); if (httpSettings) { XBOX::VString posixPath; httpSettings->SetLong (RIASettingsKeys::HTTP::port, fPort); httpSettings->SetBool (RIASettingsKeys::HTTP::allowSSL, fAllowSSL); httpSettings->SetBool (RIASettingsKeys::HTTP::SSLMandatory, fSSLMandatory); httpSettings->SetLong (RIASettingsKeys::HTTP::SSLPort, fSSLPort); if (fSSLCertificatesFolderPath.IsValid()) { fSSLCertificatesFolderPath.GetPosixPath (posixPath); httpSettings->SetString (RIASettingsKeys::HTTP::SSLCertificatePath, posixPath); } XBOX::VString charSetName; VTextConverters::Get()->GetNameFromCharSet (fDefaultCharSet, charSetName); httpSettings->SetString (RIASettingsKeys::HTTP::standardSet, charSetName); /* cache settings */ httpSettings->SetBool (RIASettingsKeys::HTTP::useCache, fEnableCache); httpSettings->SetLong (RIASettingsKeys::HTTP::pageCacheSize, fCacheMaxSize); httpSettings->SetLong (RIASettingsKeys::HTTP::cachedObjectMaxSize, fCachedObjectMaxSize); /* compression settings */ httpSettings->SetBool (RIASettingsKeys::HTTP::allowCompression, fEnableCompression); httpSettings->SetLong (RIASettingsKeys::HTTP::compressionMinThreshold, fCompressionMinThreshold); httpSettings->SetLong (RIASettingsKeys::HTTP::compressionMaxThreshold, fCompressionMaxThreshold); /* Keep-Alive settings */ httpSettings->SetBool (RIASettingsKeys::HTTP::acceptKeepAliveConnections, fEnableKeepAlive); httpSettings->SetLong (RIASettingsKeys::HTTP::maximumTimeout, fKeepAliveTimeout); httpSettings->SetLong (RIASettingsKeys::HTTP::maximumRequestsByConnection, fKeepAliveMaxConnections); /* Log settings */ XBOX::VString logFormatName; HTTPServerTools::GetLogFormatName ((EHTTPServerLogFormat)fLogFormat, logFormatName); posixPath.Clear(); fLogFolderPath.GetPosixPath (posixPath); httpSettings->SetString (RIASettingsKeys::HTTP::logFormat, logFormatName); httpSettings->SetString (RIASettingsKeys::HTTP::logPath, posixPath); httpSettings->SetString (RIASettingsKeys::HTTP::logFileName, fLogFileName); httpSettings->SetLong (RIASettingsKeys::HTTP::logMaxSize, GetLogMaxSize()); /* Log Tokens settings */ XBOX::VBagArray *logTokenSettings = new XBOX::VBagArray (); if (NULL != logTokenSettings) { XBOX::VTaskLock lock (&fLogTokensVectorLock); XBOX::VString tokenName; for (VectorOfLogToken::const_iterator it = fLogTokensVector.begin(); it != fLogTokensVector.end(); ++it) { XBOX::VValueBag *bag = new XBOX::VValueBag (); if (NULL != bag) { HTTPServerTools::GetLogTokenName (*it, tokenName); bag->SetString (RIASettingsKeys::HTTP::Log::field, tokenName); logTokenSettings->AddTail (bag); bag->Release(); } } if (logTokenSettings->GetCount()) httpSettings->SetElements (RIASettingsKeys::HTTP::Log::kXmlElement, logTokenSettings); XBOX::ReleaseRefCountable (&logTokenSettings); } outBag->AddElement (RIASettingsKeys::HTTP::kXmlElement, httpSettings); XBOX::ReleaseRefCountable (&httpSettings); } /* Web App settings */ XBOX::VValueBag *webAppSettings = new XBOX::VValueBag (); if (webAppSettings) { XBOX::VString posixPath; fWebFolderPath.GetPosixPath (posixPath); webAppSettings->SetString (RIASettingsKeys::WebApp::documentRoot, posixPath); webAppSettings->SetString (RIASettingsKeys::WebApp::directoryIndex, fIndexPageName); outBag->AddElement (RIASettingsKeys::WebApp::kXmlElement, webAppSettings); XBOX::ReleaseRefCountable (&webAppSettings); } /* Resources settings */ XBOX::VBagArray *resourcesSettings = new XBOX::VBagArray (); if (resourcesSettings) { XBOX::VTaskLock lock (&fResourcesVectorLock); for (VHTTPResourcesVector::const_iterator it = fResourcesVector.begin(); it != fResourcesVector.end(); ++it) { if (!it->IsNull()) { XBOX::VValueBag *bag = new XBOX::VValueBag (); if (bag) { (*it)->SaveToBag (*bag); resourcesSettings->AddTail (bag); bag->Release(); } } } if (resourcesSettings->GetCount()) outBag->SetElements (RIASettingsKeys::Resources::kXmlElement, resourcesSettings); XBOX::ReleaseRefCountable (&resourcesSettings); } #if 0 /*VERSIONDEBUG*/ XBOX::VString xmlString ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); outBag->DumpXML (xmlString, CVSTR ("settings"), true); #endif return XBOX::VE_OK; }
void VHTTPCookie::FromString (const XBOX::VString& inString) { XBOX::VectorOfVString stringValues; XBOX::VString string; XBOX::VString nameString; XBOX::VString valueString; Clear(); inString.GetSubStrings (CHAR_SEMICOLON, stringValues, false, true); for (VectorOfVString::iterator it = stringValues.begin(); it != stringValues.end(); ++it) { sLONG pos = 0; string.FromString (*it); if ((pos = HTTPTools::FindASCIICString (string, "secure")) == 1) { SetSecure (true); } else if ((pos = HTTPTools::FindASCIICString (string, "httpOnly")) == 1) { SetHttpOnly (true); } else if ((pos = HTTPTools::FindASCIICString (string, "version")) == 1) { SetVersion (1); } else if ((pos = HTTPTools::FindASCIICString (string, "max-age")) == 1) { HTTPTools::ExtractFieldNameValue (string, nameString, valueString); fMaxAge = valueString.GetLong(); } else if ((pos = HTTPTools::FindASCIICString (string, "expires")) == 1) { XBOX::VTime curTime; XBOX::VTime expiresTime; XBOX::VTime::Now (curTime); HTTPTools::ExtractFieldNameValue (string, nameString, valueString); expiresTime.FromRfc822String (valueString); if (expiresTime.GetMilliseconds() > curTime.GetMilliseconds()) fMaxAge = (expiresTime.GetMilliseconds() - curTime.GetMilliseconds()) / 1000; } else if ((pos = HTTPTools::FindASCIICString (string, "path")) == 1) { HTTPTools::ExtractFieldNameValue (string, nameString, fPath); } else if ((pos = HTTPTools::FindASCIICString (string, "domain")) == 1) { HTTPTools::ExtractFieldNameValue (string, nameString, fDomain); } else if ((pos = HTTPTools::FindASCIICString (string, "comment")) == 1) { HTTPTools::ExtractFieldNameValue (string, nameString, fComment); } else if ((pos = HTTPTools::FindASCIICString (string, "="))) { HTTPTools::ExtractFieldNameValue (string, fName, fValue); } } }