Blame modules/loggers/mod_log_debug.c

Packit 90a5c9
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 90a5c9
 * contributor license agreements.  See the NOTICE file distributed with
Packit 90a5c9
 * this work for additional information regarding copyright ownership.
Packit 90a5c9
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 90a5c9
 * (the "License"); you may not use this file except in compliance with
Packit 90a5c9
 * the License.  You may obtain a copy of the License at
Packit 90a5c9
 *
Packit 90a5c9
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 90a5c9
 *
Packit 90a5c9
 * Unless required by applicable law or agreed to in writing, software
Packit 90a5c9
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 90a5c9
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 90a5c9
 * See the License for the specific language governing permissions and
Packit 90a5c9
 * limitations under the License.
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
#include "apr_strings.h"
Packit 90a5c9
Packit 90a5c9
#include "httpd.h"
Packit 90a5c9
#include "http_config.h"
Packit 90a5c9
#include "http_log.h"
Packit 90a5c9
#include "http_protocol.h"
Packit 90a5c9
#include "http_request.h"
Packit 90a5c9
#include "ap_expr.h"
Packit 90a5c9
Packit 90a5c9
extern module AP_MODULE_DECLARE_DATA log_debug_module;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    ap_expr_info_t *msg_expr;
Packit 90a5c9
    ap_expr_info_t *condition;
Packit 90a5c9
    const char *hook;
Packit 90a5c9
} msg_entry;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    apr_array_header_t *entries;
Packit 90a5c9
} log_debug_dirconf;
Packit 90a5c9
Packit 90a5c9
static const char *allhooks = "all";
Packit 90a5c9
static const char * const hooks[] = {
Packit 90a5c9
    "log_transaction",      /*  0 */
Packit 90a5c9
    "quick_handler",        /*  1 */
Packit 90a5c9
    "handler",              /*  2 */
Packit 90a5c9
    "translate_name",       /*  3 */
Packit 90a5c9
    "map_to_storage",       /*  4 */
Packit 90a5c9
    "fixups",               /*  5 */
Packit 90a5c9
    "type_checker",         /*  6 */
Packit 90a5c9
    "check_access",         /*  7 */
Packit 90a5c9
    "check_access_ex",      /*  8 */
Packit 90a5c9
    "check_authn",          /*  9 */
Packit 90a5c9
    "check_authz",          /* 10 */
Packit 90a5c9
    "insert_filter",        /* 11 */
Packit 90a5c9
    NULL
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
static void do_debug_log(request_rec *r, const char *hookname)
Packit 90a5c9
{
Packit 90a5c9
    log_debug_dirconf *dconf = ap_get_module_config(r->per_dir_config, &log_debug_module);
Packit 90a5c9
    int i;
Packit 90a5c9
    if (dconf->entries == NULL)
Packit 90a5c9
        return;
Packit 90a5c9
Packit 90a5c9
    for (i = 0; i < dconf->entries->nelts; i++) {
Packit 90a5c9
        const char *msg, *err;
Packit 90a5c9
        msg_entry *entry = APR_ARRAY_IDX(dconf->entries, i, msg_entry *);
Packit 90a5c9
        if (entry->hook != allhooks && entry->hook != hookname)
Packit 90a5c9
            continue;
Packit 90a5c9
        if (entry->condition) {
Packit 90a5c9
            int ret = ap_expr_exec(r, entry->condition, &err;;
Packit 90a5c9
            if (err) {
Packit 90a5c9
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00640)
Packit 90a5c9
                              "Can't evaluate condition: %s", err);
Packit 90a5c9
                continue;
Packit 90a5c9
            }
Packit 90a5c9
            if (!ret)
Packit 90a5c9
                continue;
Packit 90a5c9
        }
Packit 90a5c9
        msg = ap_expr_str_exec(r, entry->msg_expr, &err;;
Packit 90a5c9
        if (err)
Packit 90a5c9
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00641)
Packit 90a5c9
                          "Can't evaluate message expression: %s", err);
Packit 90a5c9
        if (APLOGrdebug(r))
Packit 90a5c9
            /* Intentional no APLOGNO */
Packit 90a5c9
            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
Packit 90a5c9
                           "%s (%s hook, %s:%d)",
Packit 90a5c9
                           msg, hookname, entry->msg_expr->filename,
Packit 90a5c9
                           entry->msg_expr->line_number);
Packit 90a5c9
        else
Packit 90a5c9
            /* Intentional no APLOGNO */
Packit 90a5c9
            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
Packit 90a5c9
                          "%s", msg);
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_log_transaction(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[0]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_quick_handler(request_rec *r, int lookup_uri)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[1]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_handler(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[2]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_translate_name(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[3]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_map_to_storage(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[4]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_fixups(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[5]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_type_checker(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[6]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_check_access(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[7]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_check_access_ex(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[8]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_check_authn(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[9]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static int log_debug_check_authz(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[10]);
Packit 90a5c9
    return DECLINED;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static void log_debug_insert_filter(request_rec *r)
Packit 90a5c9
{
Packit 90a5c9
    do_debug_log(r, hooks[11]);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static void *log_debug_create_dconf(apr_pool_t *p, char *dirspec)
Packit 90a5c9
{
Packit 90a5c9
    log_debug_dirconf *dconf = apr_pcalloc(p, sizeof(log_debug_dirconf));
Packit 90a5c9
    return dconf;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static void *log_debug_merge_dconf(apr_pool_t *p, void *parent_conf, void *new_conf)
Packit 90a5c9
{
Packit 90a5c9
    log_debug_dirconf *merged = apr_pcalloc(p, sizeof(log_debug_dirconf));
Packit 90a5c9
    const log_debug_dirconf *parent = parent_conf;
Packit 90a5c9
    const log_debug_dirconf *new = new_conf;
Packit 90a5c9
Packit 90a5c9
    if (parent->entries == NULL)
Packit 90a5c9
        merged->entries = new->entries;
Packit 90a5c9
    else if (new->entries == NULL)
Packit 90a5c9
        merged->entries = parent->entries;
Packit 90a5c9
    else
Packit 90a5c9
        /* apr_array_append actually creates a new array */
Packit 90a5c9
        merged->entries = apr_array_append(p, parent->entries, new->entries);
Packit 90a5c9
Packit 90a5c9
    return merged;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const char *cmd_log_message(cmd_parms *cmd, void *dconf_, const char *arg1,
Packit 90a5c9
                                   const char *arg2, const char *arg3)
Packit 90a5c9
{
Packit 90a5c9
    msg_entry *entry = apr_pcalloc(cmd->pool, sizeof(msg_entry));
Packit 90a5c9
    log_debug_dirconf *dconf = dconf_;
Packit 90a5c9
    int i, j;
Packit 90a5c9
    const char *err;
Packit 90a5c9
    const char *args[2];
Packit 90a5c9
    args[0] = arg2;
Packit 90a5c9
    args[1] = arg3;
Packit 90a5c9
Packit 90a5c9
    entry->msg_expr = ap_expr_parse_cmd(cmd, arg1, AP_EXPR_FLAG_STRING_RESULT|
Packit 90a5c9
                                                   AP_EXPR_FLAG_DONT_VARY,
Packit 90a5c9
                                        &err, NULL);
Packit 90a5c9
    if (err)
Packit 90a5c9
        return apr_psprintf(cmd->pool,
Packit 90a5c9
                            "Could not parse message expression '%s': %s",
Packit 90a5c9
                            arg1, err);
Packit 90a5c9
Packit 90a5c9
    for (i = 0; i < 2; i++) {
Packit 90a5c9
        if (args[i] == NULL)
Packit 90a5c9
            break;
Packit 90a5c9
Packit 90a5c9
        if (strncasecmp(args[i], "hook=", 5) == 0) {
Packit 90a5c9
            const char *name = args[i] + 5;
Packit 90a5c9
            j = 0;
Packit 90a5c9
            while (hooks[j]) {
Packit 90a5c9
                if (strcasecmp(hooks[j], name) == 0) {
Packit 90a5c9
                    entry->hook = hooks[j];
Packit 90a5c9
                    break;
Packit 90a5c9
                }
Packit 90a5c9
                j++;
Packit 90a5c9
            }
Packit 90a5c9
            if (entry->hook == NULL) {
Packit 90a5c9
                if (strcmp(name, "*") == 0 || strcasecmp(name, allhooks) == 0)
Packit 90a5c9
                    entry->hook = allhooks;
Packit 90a5c9
                else
Packit 90a5c9
                    return apr_psprintf(cmd->pool, "Invalid hook name: %s", name);
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
        else if (strncasecmp(args[i], "expr=", 5) == 0) {
Packit 90a5c9
            const char *expr = args[i] + 5;
Packit 90a5c9
            entry->condition = ap_expr_parse_cmd(cmd, expr,
Packit 90a5c9
                                                 AP_EXPR_FLAG_DONT_VARY,
Packit 90a5c9
                                                 &err, NULL);
Packit 90a5c9
            if (err)
Packit 90a5c9
                return apr_psprintf(cmd->pool,
Packit 90a5c9
                                    "Could not parse expression '%s': %s",
Packit 90a5c9
                                    expr, err);
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            return apr_psprintf(cmd->pool, "Invalid argument %s", args[i]);
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
    if (entry->hook == NULL)
Packit 90a5c9
        entry->hook = hooks[0];
Packit 90a5c9
Packit 90a5c9
    if (!dconf->entries)
Packit 90a5c9
        dconf->entries = apr_array_make(cmd->pool, 4, sizeof(msg_entry *));
Packit 90a5c9
Packit 90a5c9
    APR_ARRAY_PUSH(dconf->entries, msg_entry *) = entry;
Packit 90a5c9
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static const command_rec log_debug_cmds[] =
Packit 90a5c9
{
Packit 90a5c9
    AP_INIT_TAKE123("LogMessage", cmd_log_message, NULL, RSRC_CONF|ACCESS_CONF,
Packit 90a5c9
        "Log a debug message to the error log if this config block is used for "
Packit 90a5c9
        " a request"),
Packit 90a5c9
    {NULL}
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
static void register_hooks(apr_pool_t *p)
Packit 90a5c9
{
Packit 90a5c9
    ap_hook_log_transaction(log_debug_log_transaction, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
    ap_hook_quick_handler(log_debug_quick_handler, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
    ap_hook_handler(log_debug_handler, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
    ap_hook_translate_name(log_debug_translate_name, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
    ap_hook_map_to_storage(log_debug_map_to_storage, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
    ap_hook_fixups(log_debug_fixups, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
    ap_hook_type_checker(log_debug_type_checker, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
    ap_hook_check_access(log_debug_check_access, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_URI);
Packit 90a5c9
    ap_hook_check_access_ex(log_debug_check_access_ex, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_URI);
Packit 90a5c9
    ap_hook_check_authn(log_debug_check_authn, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_URI);
Packit 90a5c9
    ap_hook_check_authz(log_debug_check_authz, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_URI);
Packit 90a5c9
    ap_hook_insert_filter(log_debug_insert_filter, NULL, NULL, APR_HOOK_FIRST);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE_MODULE(log_debug) =
Packit 90a5c9
{
Packit 90a5c9
    STANDARD20_MODULE_STUFF,
Packit 90a5c9
    log_debug_create_dconf,     /* create per-dir config */
Packit 90a5c9
    log_debug_merge_dconf,      /* merge per-dir config */
Packit 90a5c9
    NULL,                       /* server config */
Packit 90a5c9
    NULL,                       /* merge server config */
Packit 90a5c9
    log_debug_cmds,             /* command apr_table_t */
Packit 90a5c9
    register_hooks              /* register hooks */
Packit 90a5c9
};
Packit 90a5c9