Example #1
0
// 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;
}