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 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 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; }
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; }