// Main execution loop. This loop executes correctly when run both as a // standard Cgi app and when running as a FastCgi process. This loop is // single threaded. Multiple FastCgi processes are started to handle // concurrent incoming requests. int main () { #ifdef _WIN32 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #ifdef _DEBUG // to debug memory leaks, set a breakpoint here and set iBlock // to the block allocation you want to break on long iBlock = -1; _CrtSetBreakAlloc(iBlock); #endif #endif bool bFirstTime = true; int nRequests = 1; INT32 dbgPause = 0; CgiPostParser postParser; MG_TRY() // If Web Tier generates an exception which is not caught // by the HTTP handler execute, we should exit to reduce // the likelihood of a hung agent lying around. if (bFirstTime) { bFirstTime = false; #ifdef _WIN32 // Set stdin and stdout to binary mode _setmode(0, _O_BINARY); _setmode(1, _O_BINARY); #else //TODO: Does this need to be done under Linux? #endif //Debugging code //EchoTest(); //break; Initialize(); #ifdef _DEBUG MgConfiguration* cfg = MgConfiguration::GetInstance(); cfg->GetIntValue(MgConfigProperties::AgentPropertiesSection, MgConfigProperties::AgentDebugPause, dbgPause, MgConfigProperties::DefaultAgentDebugPause); #endif DumpMessage("Initialized process %d",getpid()); } DumpMessage("Process %d servicing request #%d",getpid(), nRequests); // Construct self Url. It is embedded into the output stream // of some requests (like GetMap). Use a fully qualified URL. char* serverName = getenv(MapAgentStrings::ServerName); char* serverPort = getenv(MapAgentStrings::ServerPort); char* scriptName = getenv(MapAgentStrings::ScriptName); char* remoteAddr = getenv(MapAgentStrings::RemoteAddr); char* httpClientIp = getenv(MapAgentStrings::HttpClientIp); char* httpXFF = getenv(MapAgentStrings::HttpXForwardedFor); char* secure = getenv(MapAgentStrings::Secure); string url = secure != NULL && (!_stricmp(secure, "on") || !_stricmp(secure, "true")) ? MapAgentStrings::Https : MapAgentStrings::Http; // NOXLATE if (NULL != serverName && NULL != serverPort && NULL != scriptName) { url.append(serverName); url += ':'; url.append(serverPort); url.append(scriptName); } STRING wUrl = MgUtil::MultiByteToWideChar(url); Ptr<MgHttpRequest> request = new MgHttpRequest(wUrl); Ptr<MgHttpRequestParam> params = request->GetRequestParam(); // Temporarily moved here to allow debugging post. #ifdef _DEBUG if(dbgPause > 0) { DumpMessage("Delaying request %d seconds", dbgPause); #ifdef _WIN32 Sleep(dbgPause * 1000L); #else struct timespec delay = { (time_t)dbgPause, 0 }; nanosleep(&delay, NULL); #endif } #endif // Parse inputs GET/POST char* query = getenv(MapAgentStrings::QueryString); char* requestMethod = getenv(MapAgentStrings::RequestMethod); if (NULL != requestMethod && NULL != strstr(requestMethod, "POST")) { // Must be a POST request postParser.Parse(params); } else if (NULL != query && strlen(query) > 0) { DumpMessage2("Query string present"); DumpMessage2(query); // If we have a QUERY_STRING then we are a GET request MapAgentGetParser::Parse(query, params); } // check for CLIENTIP, if it's not there (and it shouldn't be), // add it in using httpClientIp. httpXFF or remoteAddr STRING clientIp = L""; if (!params->ContainsParameter(L"CLIENTIP")) // NOXLATE { if (NULL != httpClientIp && strlen(httpClientIp) > 0 && _stricmp(httpClientIp, MapAgentStrings::Unknown) != 0) { clientIp = MgUtil::MultiByteToWideChar(httpClientIp); params->AddParameter(L"CLIENTIP", clientIp); // NOXLATE } else if (NULL != httpXFF && strlen(httpXFF) > 0 && _stricmp(httpXFF, MapAgentStrings::Unknown) != 0) { clientIp = MgUtil::MultiByteToWideChar(httpXFF); params->AddParameter(L"CLIENTIP", clientIp); // NOXLATE } else if (NULL != remoteAddr && strlen(remoteAddr) > 0) { clientIp = MgUtil::MultiByteToWideChar(remoteAddr); params->AddParameter(L"CLIENTIP", clientIp); // NOXLATE } } // Check for HTTP Basic Auth header char* auth = getenv(MapAgentStrings::HttpAuth); bool gotAuth = ParseAuth(auth, params); if (!gotAuth) { // And check for a REMOTE_USER remapped header auth = getenv(MapAgentStrings::HttpRemoteUser); gotAuth = ParseAuth(auth, params); } // Log request information string postData = ""; if (requestMethod && _stricmp(requestMethod, "POST") == 0) // NOXLATE { // Get the post xml data postData = params->GetXmlPostData(); } STRING client = params->GetParameterValue(MgHttpResourceStrings::reqClientAgent); string strRequestMethod= std::string(requestMethod); string strQuery = std::string(query); LogRequest(client, clientIp, url, strRequestMethod, postData, strQuery); Ptr<MgPropertyCollection> paramList = params->GetParameters()->GetPropertyCollection(); if (paramList != NULL) { //Check to be sure that we have some kind of credentials before continuing. Either //username/password or sessionid. bool bValid = paramList->Contains(MgHttpResourceStrings::reqSession); // Strike two: no session? how about a username? if (!bValid) bValid = paramList->Contains(MgHttpResourceStrings::reqUsername); // Strike three: no username either? How about if it's an XML POST if (!bValid) bValid = params->GetXmlPostData().length() != 0; // Certain operations do not require authentication STRING operation = params->GetParameterValue(L"OPERATION"); if((_wcsicmp(operation.c_str(), L"GETSITESTATUS") == 0)) { bValid = true; } if (!bValid) { // Invalid authentication information is not fatal, we should continue. CgiResponseHandler::RequestAuth(); // clean up any temporary files we created MapAgentCommon::DeleteTempFiles(params); return 0; } Ptr<MgHttpResponse> response = request->Execute(); // NOTE: temporary files are deleted when we execute the request CgiResponseHandler::SendResponse(response); } MG_CATCH(L"FastCgiAgent.main"); if (mgException != NULL) { CgiResponseHandler::SendError(mgException); } DumpMessage("Process %d serviced request #%d",getpid(), nRequests++); MgUninitializeWebTier(); DumpMessage("Exiting process %d",getpid()); return 0; }