static int jk_translate()

in native/apache-2.0/mod_jk.c [3829:4045]


static int jk_translate(request_rec * r)
{
    jk_request_conf_t *rconf = apr_palloc(r->pool, sizeof(jk_request_conf_t));
    rconf->jk_handled = JK_FALSE;
    rconf->rule_extensions = NULL;
    rconf->orig_uri = NULL;
    ap_set_module_config(r->request_config, &jk_module, rconf);

    if (!r->proxyreq) {
        jk_log_context_t log_ctx;
        jk_log_context_t *l = &log_ctx;
        jk_server_conf_t *conf =
            (jk_server_conf_t *) ap_get_module_config(r->server->
                                                      module_config,
                                                      &jk_module);
        l->logger = conf->log;
        l->id = "JK_TRANSLATE";

        if (conf) {
            char *clean_uri;
            int rc;
            const char *worker;

            JK_TRACE_ENTER(l);

            rconf->request_id = get_env_string(r, NULL,
                                               conf->request_id_indicator, 1);
            if (rconf->request_id == NULL) {
                rconf->request_id = get_env_string(r, NULL, JK_ENV_REQUEST_ID, 1);
            }
            l->id = rconf->request_id;
            if ((r->handler != NULL) && (!strcmp(r->handler, JK_HANDLER))) {
                /* Somebody already set the handler, probably manual config
                 * or "native" configuration, no need for extra overhead
                 */
                if (JK_IS_DEBUG_LEVEL(l))
                    jk_log(l, JK_LOG_DEBUG,
                           "Manually mapped, no need to call uri_to_worker");
                JK_TRACE_EXIT(l);
                return DECLINED;
            }

            if (apr_table_get(r->subprocess_env, "no-jk")) {
                if (JK_IS_DEBUG_LEVEL(l))
                    jk_log(l, JK_LOG_DEBUG,
                           "Into translate no-jk env var detected for uri=%s, declined",
                           r->uri);

                JK_TRACE_EXIT(l);
                return DECLINED;
            }

            clean_uri = apr_pstrdup(r->pool, r->uri);
            rc = jk_servlet_normalize(clean_uri, l);
            if (rc != 0) {
                JK_TRACE_EXIT(l);
                return HTTP_BAD_REQUEST;
            }

            /* Special case to make sure that apache can serve a directory
               listing if there are no matches for the DirectoryIndex and
               Tomcat webapps are mapped into apache using JkAutoAlias. */
            if (r->main != NULL && r->main->handler != NULL &&
                (conf->alias_dir != NULL) &&
                !strcmp(r->main->handler, DIR_MAGIC_TYPE)) {

                /* Append the request uri to the JkAutoAlias directory and
                   determine if the file exists. */
                apr_finfo_t finfo;
                finfo.filetype = APR_NOFILE;
                /* Map uri to a context static file */
                if (strlen(clean_uri) > 1) {
                    char *context_path = NULL;

                    context_path = apr_pstrcat(r->pool, conf->alias_dir, clean_uri, NULL);
                    if (context_path != NULL) {
                        apr_stat(&finfo, context_path, APR_FINFO_TYPE,
                                 r->pool);
                    }
                }
                if (finfo.filetype != APR_REG) {
                    if (JK_IS_DEBUG_LEVEL(l))
                        jk_log(l, JK_LOG_DEBUG,
                               "JkAutoAlias, no DirectoryIndex file for URI %s",
                               r->uri);
                    JK_TRACE_EXIT(l);
                    return DECLINED;
                }
            }
            if (!conf->uw_map) {
                if (JK_IS_DEBUG_LEVEL(l))
                    jk_log(l, JK_LOG_DEBUG,
                           "missing uri map for %s:%s",
                           conf->s->server_hostname ? conf->s->server_hostname : "_default_",
                           r->uri);
                JK_TRACE_EXIT(l);
                return DECLINED;
            }
            else {
                rule_extension_t *e;
                worker = map_uri_to_worker_ext(conf->uw_map, clean_uri,
                                               NULL, &e, NULL, l);
                if (worker) {
                    rconf->rule_extensions = e;
                    rconf->orig_uri = r->uri;
                    r->uri = clean_uri;
                }
            }

            if (worker) {
                r->handler = apr_pstrdup(r->pool, JK_HANDLER);
                apr_table_setn(r->notes, JK_NOTE_WORKER_NAME, worker);

                /* This could be a sub-request, possibly from mod_dir */
                /* Also add the the HANDLER to the main request */
                if (r->main) {
                    r->main->handler = apr_pstrdup(r->main->pool, JK_HANDLER);
                    apr_table_setn(r->main->notes, JK_NOTE_WORKER_NAME, worker);
                }

                JK_TRACE_EXIT(l);
                return OK;
            }
            else if (conf->alias_dir != NULL) {
                /* Automatically map uri to a context static file */
                if (JK_IS_DEBUG_LEVEL(l))
                    jk_log(l, JK_LOG_DEBUG,
                           "check alias_dir: %s",
                           conf->alias_dir);
                if (strlen(clean_uri) > 1) {
                    /* Get the context directory name */
                    char *context_dir = NULL;
                    char *context_path = NULL;
                    char *child_dir = NULL;
                    char *index = clean_uri;
                    char *suffix = strchr(index + 1, '/');
                    if (suffix != NULL) {
                        int size = (int)(suffix - index);
                        context_dir = apr_pstrndup(r->pool, index, size);
                        /* Get the context child directory name */
                        index = index + size + 1;
                        suffix = strchr(index, '/');
                        if (suffix != NULL) {
                            size = (int)(suffix - index);
                            child_dir = apr_pstrndup(r->pool, index, size);
                        }
                        else {
                            child_dir = index;
                        }
                        /* Deny access to WEB-INF and META-INF directories */
                        if (child_dir != NULL) {
                            if (JK_IS_DEBUG_LEVEL(l))
                                jk_log(l, JK_LOG_DEBUG,
                                       "AutoAlias child_dir: %s",
                                       child_dir);
                            if (!strcasecmp(child_dir, "WEB-INF")
                                || !strcasecmp(child_dir, "META-INF")) {
                                if (JK_IS_DEBUG_LEVEL(l))
                                    jk_log(l, JK_LOG_DEBUG,
                                           "AutoAlias HTTP_NOT_FOUND for URI: %s",
                                           r->uri);
                                JK_TRACE_EXIT(l);
                                return HTTP_NOT_FOUND;
                            }
                        }
                    }
                    else {
                        context_dir = apr_pstrdup(r->pool, index);
                    }

                    context_path = apr_pstrcat(r->pool, conf->alias_dir, context_dir, NULL);
                    if (context_path != NULL) {
                        apr_finfo_t finfo;
                        finfo.filetype = APR_NOFILE;
                        apr_stat(&finfo, context_path, APR_FINFO_TYPE,
                                 r->pool);
                        if (finfo.filetype == APR_DIR) {
                            char *ret = apr_pstrcat(r->pool, conf->alias_dir, clean_uri, NULL);
                            /* Add code to verify real path ap_os_canonical_name */
                            if (ret != NULL) {
                                if (JK_IS_DEBUG_LEVEL(l))
                                    jk_log(l, JK_LOG_DEBUG,
                                           "AutoAlias OK for file: %s",
                                           ret);
                                r->filename = ret;
                                JK_TRACE_EXIT(l);
                                return OK;
                            }
                        }
                        else {
                            /* Deny access to war files in web app directory */
                            int size = (int)strlen(context_dir);
                            if (size > 4
                                && !strcasecmp(context_dir + (size - 4),
                                               ".war")) {
                                if (JK_IS_DEBUG_LEVEL(l))
                                    jk_log(l, JK_LOG_DEBUG,
                                           "AutoAlias HTTP_FORBIDDEN for URI: %s",
                                           r->uri);
                                JK_TRACE_EXIT(l);
                                return HTTP_FORBIDDEN;
                            }
                        }
                    }
                }
            }
            else {
                if (JK_IS_DEBUG_LEVEL(l))
                    jk_log(l, JK_LOG_DEBUG,
                           "no match for %s found",
                           r->uri);
            }
        }
    }

    return DECLINED;
}