static DWORD handle_notify_event()

in native/iis/jk_isapi_plugin.c [1710:2002]


static DWORD handle_notify_event(PHTTP_FILTER_CONTEXT pfc,
                                 PHTTP_FILTER_PREPROC_HEADERS pfp)
{
    int rc;
    DWORD rv = SF_STATUS_REQ_NEXT_NOTIFICATION;
    const char *worker = NULL;
    rule_extension_t *extensions;
    int worker_index = -1;
    int port = 0;
    jk_pool_atom_t pbuf[HUGE_POOL_SIZE];
    jk_pool_t pool;

    char *uri_undec  = NULL;
    char *cleanuri  = NULL;
    char *uri = NULL;
    char *host = NULL;
    char *request_id = NULL;
    char *translate = NULL;
    char szHB[HDR_BUFFER_SIZE] = "/";
    char szUB[HDR_BUFFER_SIZE] = "";
    char szRIDB[512] = "";
    char szTB[16] = "";
    char szPB[16] = "";
    char swindex[32] = "";
    char *query;
    DWORD len;
    jk_log_context_t log_ctx;
    jk_log_context_t *l = &log_ctx;

    l->logger = logger;
    l->id = "FILTER";
    if (JK_IS_DEBUG_LEVEL(l))
        jk_log(l, JK_LOG_DEBUG, "Filter started");
    jk_open_pool(&pool, pbuf, sizeof(jk_pool_atom_t) * HUGE_POOL_SIZE);
    /*
     * Just in case somebody set these headers in the request!
     */
    clear_header(pfp, pfc, URI_HEADER_NAME);
    clear_header(pfp, pfc, QUERY_HEADER_NAME);
    clear_header(pfp, pfc, REQUEST_ID_HEADER_NAME);
    clear_header(pfp, pfc, WORKER_HEADER_NAME);
    clear_header(pfp, pfc, WORKER_HEADER_INDEX);
    clear_header(pfp, pfc, TOMCAT_TRANSLATE_HEADER_NAME);

    /*
     * Suppress logging of original uri/query when we don't map a URL
     */
    if (pfc->pFilterContext) {
        isapi_log_data_t *ld = (isapi_log_data_t *)pfc->pFilterContext;
        ld->request_matched = JK_FALSE;
    }
    uri = get_pheader(&pool, pfp, pfc, "url", szUB, sizeof(szUB));
    if (uri == NULL) {
        jk_log(l, JK_LOG_ERROR,
               "error while getting the url");
        return SF_STATUS_REQ_ERROR;
    }
    if (*uri == '\0') {
        /* Empty url */
        return SF_STATUS_REQ_NEXT_NOTIFICATION;
    }
    query = strchr(uri, '?');
    if (query) {
        *query++ = '\0';
        if (*query)
            query = jk_pool_strdup(&pool, query);
        else
            query = NULL;
    }

    /* Duplicate unparsed uri */
    uri_undec = jk_pool_strdup(&pool, uri);

    rc = unescape_url(uri);
    if (rc == BAD_REQUEST) {
        jk_log(l, JK_LOG_ERROR,
               "[%s] contains one or more invalid escape sequences.",
               uri);
        write_error_response(pfc, 400);
        rv = SF_STATUS_REQ_FINISHED;
        goto cleanup;
    }
    if (rc == BAD_PATH) {
        jk_log(l, JK_LOG_EMERG,
               "[%s] contains forbidden escape sequences.",
               uri);
        write_error_response(pfc, 404);
        rv = SF_STATUS_REQ_FINISHED;
        goto cleanup;
    }
    cleanuri = jk_pool_strdup(&pool, uri);
    if (jk_servlet_normalize(cleanuri, l)) {
        write_error_response(pfc, 404);
        rv = SF_STATUS_REQ_FINISHED;
        goto cleanup;
    }
    len = ISIZEOF(szHB) - 1;
    if (pfc->GetServerVariable(pfc, "SERVER_NAME", &szHB[1], &len) && len > 1) {
        len = ISIZEOF(szPB);
        if (pfc->GetServerVariable(pfc, "SERVER_PORT", szPB, &len))
            port = atoi(szPB);
        if (port != 0 && port != 80 && port != 443) {
            host = jk_pool_strcatv(&pool, szHB, ":", szPB, NULL);
        }
        else
            host = szHB;
    }
    worker = map_uri_to_worker_ext(uw_map, cleanuri, host,
                                   &extensions, &worker_index, l);
    /*
     * Check if somebody is feading us with his own TOMCAT data headers.
     * We reject such postings !
     */
    if (worker) {
        char *forwardURI;
        char *rewriteURI;
        isapi_log_data_t *ld;
        BOOL rs;

        /* This is a servlet, should redirect ... */
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "[%s] is a servlet url - should redirect to %s",
                   uri, worker);

        /* get URI we should forward */
        if (uri_select_option == URI_SELECT_OPT_UNPARSED) {
            /* get original unparsed URI */
            forwardURI = uri_undec;
        }
        else if (uri_select_option == URI_SELECT_OPT_ESCAPED) {
            size_t elen  = strlen(uri) * 3 + 1;
            char *escuri = jk_pool_alloc(&pool, elen);
            if (!escape_url(uri, escuri, (int)elen)) {
                jk_log(l, JK_LOG_ERROR,
                       "[%s] re-encoding request exceeds maximum buffer size.",
                       uri);
                write_error_response(pfc, 400);
                rv = SF_STATUS_REQ_FINISHED;
                goto cleanup;
            }
            if (JK_IS_DEBUG_LEVEL(l))
                jk_log(l, JK_LOG_DEBUG,
                       "fowarding escaped URI [%s]",
                       escuri);
            forwardURI = escuri;
        }
        else if (uri_select_option == URI_SELECT_OPT_PROXY) {
            size_t elen  = strlen(uri) * 3 + 1;
            char *escuri = jk_pool_alloc(&pool, elen);
            if (!jk_canonenc(uri, escuri, (int)elen)) {
                jk_log(l, JK_LOG_ERROR,
                       "[%s] re-encoding request exceeds maximum buffer size.",
                       uri);
                write_error_response(pfc, 400);
                rv = SF_STATUS_REQ_FINISHED;
                goto cleanup;
            }
            if (JK_IS_DEBUG_LEVEL(l))
                jk_log(l, JK_LOG_DEBUG,
                       "fowarding escaped URI [%s]",
                       escuri);
            forwardURI = escuri;
        }
        else {
            forwardURI = uri;
        }
        /* Do a simple rewrite .
         * Note that URI can be escaped, so thus the rule has
         * to be in that case.
         *
         * TODO: Add more advanced regexp rewrite.
         */
        rewriteURI = simple_rewrite(&pool, forwardURI);
        if (rewriteURI == NULL)
            rewriteURI = rregex_rewrite(&pool, forwardURI);
        if (rewriteURI) {
            if (JK_IS_DEBUG_LEVEL(l)) {
                jk_log(l, JK_LOG_DEBUG,
                       "rewritten URI [%s]->[%s]",
                       forwardURI, rewriteURI);
            }
            forwardURI = rewriteURI;
        }
        itoa(worker_index, swindex, 10);
        rs = pfp->AddHeader(pfc, URI_HEADER_NAME, forwardURI);
        if (rs && query)
            rs = pfp->AddHeader(pfc, QUERY_HEADER_NAME, query);

        request_id = get_pheader(&pool, pfp, pfc, request_id_header,
                                 szRIDB, sizeof(szRIDB));
        if (request_id  == NULL || *request_id == '\0') {
            char uuid[UUID_BUFFER_SIZE];
            GUID guid;
            HRESULT hr = CoCreateGuid(&guid);
            if (FAILED(hr)) {
                jk_log(l, JK_LOG_WARNING, "Could not create UUID for request id");
                request_id = "NO-ID";
            }
            else {
                _snprintf_s(uuid, sizeof(uuid), _TRUNCATE, UUID_TEMPLATE,
                            guid.Data1, guid.Data2, guid.Data3,
                            guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
                            guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
                request_id = jk_pool_strdup(&pool, uuid);
                l->id = request_id;
                if (JK_IS_DEBUG_LEVEL(l)) {
                    jk_log(l, JK_LOG_DEBUG,
                           "Created request id [%s]", request_id);
                }
            }
        }
        else {
            l->id = request_id;
            if (JK_IS_DEBUG_LEVEL(l)) {
                jk_log(l, JK_LOG_DEBUG,
                       "Received request id [%s]", request_id);
            }
        }

        rs = rs && pfp->AddHeader(pfc, REQUEST_ID_HEADER_NAME, request_id);
        rs = rs && pfp->AddHeader(pfc, WORKER_HEADER_NAME, (LPSTR)worker);
        rs = rs && pfp->AddHeader(pfc, WORKER_HEADER_INDEX, swindex);
        rs = rs && pfp->SetHeader(pfc, "url", extension_uri);

        if (!rs) {
            jk_log(l, JK_LOG_ERROR,
                   "error while adding request headers");
            SetLastError(ERROR_INVALID_PARAMETER);
            rv = SF_STATUS_REQ_ERROR;
            goto cleanup;
        }
        translate = get_pheader(&pool, pfp, pfc, TRANSLATE_HEADER,
                                szTB, sizeof(szTB));
        /* Move Translate: header to a temporary header so
         * that the extension proc will be called.
         * This allows the servlet to handle 'Translate: f'.
         */
        if (translate != NULL && *translate != '\0') {
            if (!pfp->AddHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME, translate)) {
                jk_log(l, JK_LOG_ERROR,
                       "error while adding Tomcat-Translate headers");
                rv = SF_STATUS_REQ_ERROR;
                goto cleanup;
            }
            clear_header(pfp, pfc, TRANSLATE_HEADER);
        }
        ld = (isapi_log_data_t *)pfc->pFilterContext;
        if (ld == NULL) {
            ld = (isapi_log_data_t *)pfc->AllocMem(pfc, sizeof(isapi_log_data_t), 0);
            if (ld == NULL) {
                jk_log(l, JK_LOG_ERROR,
                       "error while allocating memory");
                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                rv = SF_STATUS_REQ_ERROR;
                goto cleanup;
            }
            pfc->pFilterContext = ld;
        }
        memset(ld, 0, sizeof(isapi_log_data_t));
        StringCbCopy(ld->uri, sizeof(ld->uri), forwardURI);
        if (query)
            StringCbCopy(ld->query, sizeof(ld->query), query);
        ld->request_matched = JK_TRUE;
        if (JK_IS_DEBUG_LEVEL(l)) {
            jk_log(l, JK_LOG_DEBUG,
                   "forwarding to : %s", extension_uri);
            jk_log(l, JK_LOG_DEBUG,
                   "forward URI   : %s%s", URI_HEADER_NAME, forwardURI);
            if (query)
                jk_log(l, JK_LOG_DEBUG,
                       "forward query : %s%s", QUERY_HEADER_NAME, query);
            jk_log(l, JK_LOG_DEBUG,
                   "request id: %s%s", REQUEST_ID_HEADER_NAME, request_id);
            jk_log(l, JK_LOG_DEBUG,
                   "forward worker: %s%s", WORKER_HEADER_NAME, worker);
            jk_log(l, JK_LOG_DEBUG,
                   "worker index  : %s%s", WORKER_HEADER_INDEX, swindex);
        }
    }
    else {
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG, "[%s] is not a servlet url", uri_undec);
        if (strip_session) {
            if (jk_strip_session_id(uri_undec, JK_PATH_SESSION_IDENTIFIER, l)) {
                pfp->SetHeader(pfc, "url", uri_undec);
            }
        }
    }
cleanup:
    jk_close_pool(&pool);
    return rv;
}