/*
**  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.
*/

#include "apreq_parser.h"
#include "apreq_util.h"
#include "apreq_error.h"


#define PARSER_STATUS_CHECK(PREFIX)   do {         \
    if (ctx->status == PREFIX##_ERROR)             \
        return APREQ_ERROR_GENERAL;                \
    else if (ctx->status == PREFIX##_COMPLETE)     \
        return APR_SUCCESS;                        \
    else if (bb == NULL)                           \
        return APR_INCOMPLETE;                     \
} while (0);



struct url_ctx {
    apr_bucket_brigade *bb;
    apr_size_t          nlen;
    apr_size_t          vlen;
    enum {
        URL_NAME,
        URL_VALUE,
        URL_COMPLETE,
        URL_ERROR
    }                   status;
};


/******************** application/x-www-form-urlencoded ********************/

static apr_status_t split_urlword(apreq_param_t **p, apr_pool_t *pool,
                                  apr_bucket_brigade *bb,
                                  apr_size_t nlen,
                                  apr_size_t vlen)
{
    apreq_param_t *param;
    apreq_value_t *v;
    apr_bucket *e, *f;
    apr_status_t s;
    struct iovec vec[APREQ_DEFAULT_NELTS];
    apr_array_header_t arr;
    apr_size_t mark;
    apreq_charset_t charset;

    if (nlen == 0)
        return APR_EBADARG;

    param = apreq_param_make(pool, NULL, nlen, NULL, vlen);
    if (param == NULL)
        return APR_ENOMEM;
    *(const apreq_value_t **)&v = &param->v;

    arr.pool     = pool;
    arr.elt_size = sizeof(struct iovec);
    arr.nelts    = 0;
    arr.nalloc   = APREQ_DEFAULT_NELTS;
    arr.elts     = (char *)vec;

    ++nlen, ++vlen;
    e = APR_BRIGADE_FIRST(bb);

    while (!APR_BUCKET_IS_EOS(e)) {
        struct iovec *iov = apr_array_push(&arr);
        apr_size_t len;
        s = apr_bucket_read(e, (const char **)&iov->iov_base,
                            &len, APR_BLOCK_READ);
        if (s != APR_SUCCESS)
            return s;

        iov->iov_len = len;
        nlen -= len;

        e = APR_BUCKET_NEXT(e);

        if (nlen == 0) {
            iov->iov_len--;
            break;
        }
    }

    mark = arr.nelts;

    while (!APR_BUCKET_IS_EOS(e)) {
        struct iovec *iov = apr_array_push(&arr);
        apr_size_t len;
        s = apr_bucket_read(e, (const char **)&iov->iov_base,
                            &len, APR_BLOCK_READ);
        if (s != APR_SUCCESS)
            return s;

        iov->iov_len = len;
        vlen -= len;

        e = APR_BUCKET_NEXT(e);

        if (vlen == 0) {
            iov->iov_len--;
            break;
        }

    }

    s = apreq_decodev(v->data, &vlen,
                      (struct iovec *)arr.elts + mark, arr.nelts - mark);
    if (s != APR_SUCCESS)
        return s;

    charset = apreq_charset_divine(v->data, vlen);

    v->name = v->data + vlen + 1;
    v->dlen = vlen;

    s = apreq_decodev(v->name, &nlen, (struct iovec *)arr.elts, mark);
    if (s != APR_SUCCESS)
        return s;

    switch (apreq_charset_divine(v->name, nlen)) {
    case APREQ_CHARSET_UTF8:
        if (charset == APREQ_CHARSET_ASCII)
            charset = APREQ_CHARSET_UTF8;
    case APREQ_CHARSET_ASCII:
        break;

    case APREQ_CHARSET_LATIN1:
        if (charset != APREQ_CHARSET_CP1252)
            charset = APREQ_CHARSET_LATIN1;
        break;
    case APREQ_CHARSET_CP1252:
        charset = APREQ_CHARSET_CP1252;
    }

    v->nlen = nlen;

    while ((f = APR_BRIGADE_FIRST(bb)) != e)
        apr_bucket_delete(f);

    apreq_param_tainted_on(param);
    apreq_param_charset_set(param, charset);
    *p = param;
    return APR_SUCCESS;
}

APREQ_DECLARE_PARSER(apreq_parse_urlencoded)
{
    apr_pool_t *pool = parser->pool;
    apr_bucket *e;
    struct url_ctx *ctx;

    if (parser->ctx == NULL) {
        ctx = apr_pcalloc(pool, sizeof *ctx);
        ctx->bb = apr_brigade_create(pool, parser->bucket_alloc);
        parser->ctx = ctx;
        ctx->status = URL_NAME;
    }
    else
        ctx = parser->ctx;

    PARSER_STATUS_CHECK(URL);
    e = APR_BRIGADE_LAST(ctx->bb);
    APR_BRIGADE_CONCAT(ctx->bb, bb);

 parse_url_brigade:

    for (e  = APR_BUCKET_NEXT(e);
         e != APR_BRIGADE_SENTINEL(ctx->bb);
         e  = APR_BUCKET_NEXT(e))
    {
        apreq_param_t *param;
        apr_size_t off = 0, dlen;
        const char *data;
        apr_status_t s;

        if (APR_BUCKET_IS_EOS(e)) {
            if (ctx->status == URL_NAME) {
                s = APR_SUCCESS;
            }
            else {
                s = split_urlword(&param, pool, ctx->bb, ctx->nlen, ctx->vlen);
                if (parser->hook != NULL && s == APR_SUCCESS)
                    s = apreq_hook_run(parser->hook, param, NULL);

                if (s == APR_SUCCESS) {
                    apreq_value_table_add(&param->v, t);
                    ctx->status = URL_COMPLETE;
                }
                else {
                    ctx->status = URL_ERROR;
                }
            }

            APR_BRIGADE_CONCAT(bb, ctx->bb);
            return s;
        }

        s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ);
        if ( s != APR_SUCCESS ) {
            ctx->status = URL_ERROR;
            return s;
        }

    parse_url_bucket:

        switch (ctx->status) {

        case URL_NAME:
            while (off < dlen) {
                switch (data[off++]) {
                case '=':
                    apr_bucket_split(e, off);
                    dlen -= off;
                    data += off;
                    off = 0;
                    e = APR_BUCKET_NEXT(e);
                    ctx->status = URL_VALUE;
                    goto parse_url_bucket;
                default:
                    ++ctx->nlen;
                }
            }
            break;

        case URL_VALUE:
            while (off < dlen) {

                switch (data[off++]) {
                case '&':
                case ';':
                    apr_bucket_split(e, off);
                    s = split_urlword(&param, pool, ctx->bb,
                                      ctx->nlen, ctx->vlen);
                    if (parser->hook != NULL && s == APR_SUCCESS)
                        s = apreq_hook_run(parser->hook, param, NULL);

                    if (s != APR_SUCCESS) {
                        ctx->status = URL_ERROR;
                        return s;
                    }

                    apreq_value_table_add(&param->v, t);
                    ctx->status = URL_NAME;
                    ctx->nlen = 0;
                    ctx->vlen = 0;
                    e = APR_BRIGADE_SENTINEL(ctx->bb);
                    goto parse_url_brigade;

                default:
                    ++ctx->vlen;
                }
            }
            break;
        default:
            ; /* not reached */
        }
    }
    apreq_brigade_setaside(ctx->bb, pool);
    return APR_INCOMPLETE;
}


