/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * mod_request.c --- HTTP routines to set aside or process request bodies.
 */

#include "apr.h"
#include "apr_strings.h"
#include "apr_buckets.h"
#include "apr_lib.h"

#include "ap_config.h"
#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"           /* For errors detected in basic auth common
                                 * support code... */
#include "http_request.h"

#include "mod_request.h"

/* Handles for core filters */
static ap_filter_rec_t *keep_body_input_filter_handle;
static ap_filter_rec_t *kept_body_input_filter_handle;

static apr_status_t bail_out_on_error(apr_bucket_brigade *bb,
                                      ap_filter_t *f,
                                      int http_error)
{
    apr_bucket *e;

    apr_brigade_cleanup(bb);
    e = ap_bucket_error_create(http_error,
                               NULL, f->r->pool,
                               f->c->bucket_alloc);
    APR_BRIGADE_INSERT_TAIL(bb, e);
    e = apr_bucket_eos_create(f->c->bucket_alloc);
    APR_BRIGADE_INSERT_TAIL(bb, e);
    return ap_pass_brigade(f->r->output_filters, bb);
}

typedef struct keep_body_filter_ctx {
    apr_off_t remaining;
    apr_off_t keep_body;
} keep_body_ctx_t;

/**
 * This is the KEEP_BODY_INPUT filter for HTTP requests, for times when the
 * body should be set aside for future use by other modules.
 */
static apr_status_t keep_body_filter(ap_filter_t *f, apr_bucket_brigade *b,
                                     ap_input_mode_t mode,
                                     apr_read_type_e block,
                                     apr_off_t readbytes)
{
    apr_bucket *e;
    keep_body_ctx_t *ctx = f->ctx;
    apr_status_t rv;
    apr_bucket *bucket;
    apr_off_t len = 0;


    if (!ctx) {
        const char *lenp;
        char *endstr = NULL;
        request_dir_conf *dconf = ap_get_module_config(f->r->per_dir_config,
                                                       &request_module);

        /* must we step out of the way? */
        if (!dconf->keep_body || f->r->kept_body) {
            ap_remove_input_filter(f);
            return ap_get_brigade(f->next, b, mode, block, readbytes);
        }

        f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));

        /* fail fast if the content length exceeds keep body */
        lenp = apr_table_get(f->r->headers_in, "Content-Length");
        if (lenp) {

            /* Protects against over/underflow, non-digit chars in the
             * string (excluding leading space) (the endstr checks)
             * and a negative number. */
            if (apr_strtoff(&ctx->remaining, lenp, &endstr, 10)
                || endstr == lenp || *endstr || ctx->remaining < 0) {

                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01411)
                              "Invalid Content-Length");

                ap_remove_input_filter(f);
                return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
            }

            /* If we have a limit in effect and we know the C-L ahead of
             * time, stop it here if it is invalid.
             */
            if (dconf->keep_body < ctx->remaining) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01412)
                          "Requested content-length of %" APR_OFF_T_FMT
                          " is larger than the configured limit"
                          " of %" APR_OFF_T_FMT, ctx->remaining, dconf->keep_body);
                ap_remove_input_filter(f);
                return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
            }

        }

        f->r->kept_body = apr_brigade_create(f->r->pool, f->r->connection->bucket_alloc);
        ctx->remaining = dconf->keep_body;

    }

    /* get the brigade from upstream, and read it in to get its length */
    rv = ap_get_brigade(f->next, b, mode, block, readbytes);
    if (rv == APR_SUCCESS) {
        rv = apr_brigade_length(b, 1, &len);
    }

    /* does the length take us over the limit? */
    if (APR_SUCCESS == rv && len > ctx->remaining) {
        if (f->r->kept_body) {
            apr_brigade_cleanup(f->r->kept_body);
            f->r->kept_body = NULL;
        }
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01413)
                      "Requested content-length of %" APR_OFF_T_FMT
                      " is larger than the configured limit"
                      " of %" APR_OFF_T_FMT, len, ctx->keep_body);
        return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
    }
    ctx->remaining -= len;

    /* pass any errors downstream */
    if (rv != APR_SUCCESS) {
        if (f->r->kept_body) {
            apr_brigade_cleanup(f->r->kept_body);
            f->r->kept_body = NULL;
        }
        return rv;
    }

    /* all is well, set aside the buckets */
    for (bucket = APR_BRIGADE_FIRST(b);
         bucket != APR_BRIGADE_SENTINEL(b);
         bucket = APR_BUCKET_NEXT(bucket))
    {
        apr_bucket_copy(bucket, &e);
        APR_BRIGADE_INSERT_TAIL(f->r->kept_body, e);
    }

    return APR_SUCCESS;
}


typedef struct kept_body_filter_ctx {
    apr_off_t offset;
    apr_off_t remaining;
} kept_body_ctx_t;

/**
 * Initialisation of filter to handle a kept body on subrequests.
 *
 * If a body is to be reinserted into a subrequest, any chunking will have
 * been removed from the body during storage. We need to change the request
 * from Transfer-Encoding: chunked to an explicit Content-Length.
 */
static int kept_body_filter_init(ap_filter_t *f)
{
    apr_off_t length = 0;
    request_rec *r = f->r;
    apr_bucket_brigade *kept_body = r->kept_body;

    if (kept_body) {
        apr_table_unset(r->headers_in, "Transfer-Encoding");
        apr_brigade_length(kept_body, 1, &length);
        apr_table_setn(r->headers_in, "Content-Length", apr_off_t_toa(r->pool, length));
    }

    return OK;
}

/**
 * Filter to handle a kept body on subrequests.
 *
 * If a body has been previously kept by the request, and if a subrequest wants
 * to re-insert the body into the request, this input filter makes it happen.
 */
static apr_status_t kept_body_filter(ap_filter_t *f, apr_bucket_brigade *b,
                                     ap_input_mode_t mode,
                                     apr_read_type_e block,
                                     apr_off_t readbytes)
{
    request_rec *r = f->r;
    apr_bucket_brigade *kept_body = r->kept_body;
    kept_body_ctx_t *ctx = f->ctx;
    apr_bucket *ec, *e2;
    apr_status_t rv;

    /* just get out of the way of things we don't want. */
    if (!kept_body || (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE)) {
        return ap_get_brigade(f->next, b, mode, block, readbytes);
    }

    /* set up the context if it does not already exist */
    if (!ctx) {
        f->ctx = ctx = apr_palloc(f->r->pool, sizeof(*ctx));
        ctx->offset = 0;
        apr_brigade_length(kept_body, 1, &ctx->remaining);
    }

    /* kept_body is finished, send next filter */
    if (ctx->remaining <= 0) {
        return ap_get_brigade(f->next, b, mode, block, readbytes);
    }

    /* send all of the kept_body, but no more */
    if (readbytes > ctx->remaining) {
        readbytes = ctx->remaining;
    }

    /* send part of the kept_body */
    if ((rv = apr_brigade_partition(kept_body, ctx->offset, &ec)) != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01414)
                      "apr_brigade_partition() failed on kept_body at %" APR_OFF_T_FMT, ctx->offset);
        return rv;
    }
    if ((rv = apr_brigade_partition(kept_body, ctx->offset + readbytes, &e2)) != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01415)
                      "apr_brigade_partition() failed on kept_body at %" APR_OFF_T_FMT, ctx->offset + readbytes);
        return rv;
    }

    do {
        apr_bucket *foo;
        const char *str;
        apr_size_t len;

        if (apr_bucket_copy(ec, &foo) != APR_SUCCESS) {
            /* As above; this should not fail since the bucket has
             * a known length, but just to be sure, this takes
             * care of uncopyable buckets that do somehow manage
             * to slip through.  */
            /* XXX: check for failure? */
            apr_bucket_read(ec, &str, &len, APR_BLOCK_READ);
            apr_bucket_copy(ec, &foo);
        }
        APR_BRIGADE_INSERT_TAIL(b, foo);
        ec = APR_BUCKET_NEXT(ec);
    } while (ec != e2);

    ctx->remaining -= readbytes;
    ctx->offset += readbytes;
    return APR_SUCCESS;

}

/**
 * Check whether this filter is not already present.
 */
static int request_is_filter_present(request_rec * r, ap_filter_rec_t *fn)
{
    ap_filter_t * f = r->input_filters;
    while (f) {
        if (f->frec == fn) {
            return 1;
        }
        f = f->next;
    }
    return 0;
}

/**
 * Insert filter hook.
 *
 * Add the KEEP_BODY filter to the request, if the admin wants to keep
 * the body using the KeptBodySize directive.
 *
 * As a precaution, any pre-existing instances of either the kept_body or
 * keep_body filters will be removed before the filter is added.
 *
 * @param r The request
 */
static void ap_request_insert_filter(request_rec * r)
{
    request_dir_conf *conf = ap_get_module_config(r->per_dir_config,
                                                  &request_module);

    if (r->kept_body) {
        if (!request_is_filter_present(r, kept_body_input_filter_handle)) {
            ap_add_input_filter_handle(kept_body_input_filter_handle,
                                       NULL, r, r->connection);
        }
    }
    else if (conf->keep_body) {
        if (!request_is_filter_present(r, kept_body_input_filter_handle)) {
            ap_add_input_filter_handle(keep_body_input_filter_handle,
                                       NULL, r, r->connection);
        }
    }

}

/**
 * Remove the kept_body and keep body filters from this specific request.
 */
static void ap_request_remove_filter(request_rec * r)
{
    ap_filter_t * f = r->input_filters;
    while (f) {
        if (f->frec->filter_func.in_func == kept_body_filter ||
                f->frec->filter_func.in_func == keep_body_filter) {
            ap_remove_input_filter(f);
        }
        f = f->next;
    }
}

static void *create_request_dir_config(apr_pool_t *p, char *dummy)
{
    request_dir_conf *new =
        (request_dir_conf *) apr_pcalloc(p, sizeof(request_dir_conf));

    new->keep_body_set = 0; /* unset */
    new->keep_body = 0; /* don't by default */

    return (void *) new;
}

static void *merge_request_dir_config(apr_pool_t *p, void *basev, void *addv)
{
    request_dir_conf *new = (request_dir_conf *) apr_pcalloc(p, sizeof(request_dir_conf));
    request_dir_conf *add = (request_dir_conf *) addv;
    request_dir_conf *base = (request_dir_conf *) basev;

    new->keep_body = (add->keep_body_set == 0) ? base->keep_body : add->keep_body;
    new->keep_body_set = add->keep_body_set || base->keep_body_set;

    return new;
}

static const char *set_kept_body_size(cmd_parms *cmd, void *dconf,
                                      const char *arg)
{
    request_dir_conf *conf = dconf;
    char *end = NULL;

    if (APR_SUCCESS != apr_strtoff(&(conf->keep_body), arg, &end, 10)
            || conf->keep_body < 0 || *end) {
        return "KeptBodySize must be a valid size in bytes, or zero.";
    }
    conf->keep_body_set = 1;

    return NULL;
}

static const command_rec request_cmds[] = {
    AP_INIT_TAKE1("KeptBodySize", set_kept_body_size, NULL, ACCESS_CONF,
                  "Maximum size of request bodies kept aside for use by filters"),
    { NULL }
};

static void register_hooks(apr_pool_t *p)
{
    keep_body_input_filter_handle =
        ap_register_input_filter(KEEP_BODY_FILTER, keep_body_filter,
                                 NULL, AP_FTYPE_RESOURCE);
    kept_body_input_filter_handle =
        ap_register_input_filter(KEPT_BODY_FILTER, kept_body_filter,
                                 kept_body_filter_init, AP_FTYPE_RESOURCE);
    ap_hook_insert_filter(ap_request_insert_filter, NULL, NULL, APR_HOOK_LAST);
    APR_REGISTER_OPTIONAL_FN(ap_request_insert_filter);
    APR_REGISTER_OPTIONAL_FN(ap_request_remove_filter);
}

AP_DECLARE_MODULE(request) = {
    STANDARD20_MODULE_STUFF,
    create_request_dir_config, /* create per-directory config structure */
    merge_request_dir_config,  /* merge per-directory config structures */
    NULL,                      /* create per-server config structure */
    NULL,                      /* merge per-server config structures */
    request_cmds,              /* command apr_table_t */
    register_hooks             /* register hooks */
};
