/*
 * 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 "httpd.h"
#include "apr_strings.h"
#include "apr_portable.h"
#include "apr_pools.h"
#include "fcgid_global.h"
#include "fcgid_protocol.h"

static size_t init_environment(char *buf, char **envp)
{
    char *spliter;
    int namelen, valuelen;
    char *cur_buf = buf;
    size_t buffer_size = 0;

    for (; *envp != NULL; envp++) {
        spliter = strchr(*envp, '=');
        if (spliter == NULL)
            continue;

        namelen = spliter - *envp;
        valuelen = strlen(spliter + 1);

        /* Put name length to buffer */
        if (namelen < 0x80) {
            if (!buf)
                buffer_size++;
            else
                *cur_buf++ = (unsigned char) namelen;
        } else {
            if (!buf)
                buffer_size += 4;
            else {
                *cur_buf++ = (unsigned char) ((namelen >> 24) | 0x80);
                *cur_buf++ = (unsigned char) (namelen >> 16);
                *cur_buf++ = (unsigned char) (namelen >> 8);
                *cur_buf++ = (unsigned char) namelen;
            }
        }

        /* Put value length to buffer */
        if (valuelen < 0x80) {
            if (!buf)
                buffer_size++;
            else
                *cur_buf++ = (unsigned char) valuelen;
        } else {
            if (!buf)
                buffer_size += 4;
            else {
                *cur_buf++ = (unsigned char) ((valuelen >> 24) | 0x80);
                *cur_buf++ = (unsigned char) (valuelen >> 16);
                *cur_buf++ = (unsigned char) (valuelen >> 8);
                *cur_buf++ = (unsigned char) valuelen;
            }
        }

        /* Now the name and body buffer */
        if (!buf) {
            buffer_size += namelen;
            buffer_size += valuelen;
        } else {
            memcpy(cur_buf, *envp, namelen);
            cur_buf += namelen;
            memcpy(cur_buf, spliter + 1, valuelen);
            cur_buf += valuelen;
        }
    }
    return buffer_size;
}

static void
init_begin_request_body(int role,
                        FCGI_BeginRequestBody * begin_request_body)
{
    begin_request_body->roleB1 = (unsigned char) (((role >> 8) & 0xff));
    begin_request_body->roleB0 = (unsigned char) (role & 0xff);
    begin_request_body->flags = 0;
    memset(begin_request_body->reserved, 0,
           sizeof(begin_request_body->reserved));
}

int
init_header(int type, int requestId, apr_size_t contentLength,
            apr_size_t paddingLength, FCGI_Header * header)
{
    if (contentLength > 65535 || paddingLength > 255)
        return 0;
    header->version = FCGI_VERSION_1;
    header->type = (unsigned char) type;
    header->requestIdB1 = (unsigned char) ((requestId >> 8) & 0xff);
    header->requestIdB0 = (unsigned char) (requestId & 0xff);
    header->contentLengthB1 =
        (unsigned char) ((contentLength >> 8) & 0xff);
    header->contentLengthB0 = (unsigned char) ((contentLength) & 0xff);
    header->paddingLength = (unsigned char) paddingLength;
    header->reserved = 0;
    return 1;
}

int
build_begin_block(int role, server_rec * main_server,
                  apr_bucket_alloc_t * alloc,
                  apr_bucket_brigade * request_brigade)
{
    /* Alloc memory for begin request header & body */
    FCGI_Header *begin_request_header =
        apr_bucket_alloc(sizeof(FCGI_Header), alloc);
    FCGI_BeginRequestBody *begin_request_body =
        apr_bucket_alloc(sizeof(FCGI_BeginRequestBody), alloc);
    apr_bucket *bucket_header =
        apr_bucket_heap_create((const char *) begin_request_header,
                               sizeof(*begin_request_header),
                               apr_bucket_free,
                               alloc);
    apr_bucket *bucket_body =
        apr_bucket_heap_create((const char *) begin_request_body,
                               sizeof(*begin_request_body),
                               apr_bucket_free,
                               alloc);

    /* Sanity check */
    if (!begin_request_header || !begin_request_body
        || !bucket_header || !bucket_body) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     main_server,
                     "mod_fcgid: can't alloc memeory for begin request");
        return 0;
    }

    /* Initialize begin request header and body */
    if (!init_header(FCGI_BEGIN_REQUEST, 1, sizeof(FCGI_BeginRequestBody),
                     0, begin_request_header)) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     main_server,
                     "mod_fcgid: can't init begin request header");
        return 0;
    }
    init_begin_request_body(role, begin_request_body);

    /* Append the header and body to request brigade */
    APR_BRIGADE_INSERT_TAIL(request_brigade, bucket_header);
    APR_BRIGADE_INSERT_TAIL(request_brigade, bucket_body);

    return 1;
}

int
build_env_block(server_rec * main_server, char **envp,
                apr_bucket_alloc_t * alloc,
                apr_bucket_brigade * request_brigade)
{
    /* Get the size of the destination buffer */
    apr_size_t bufsize = init_environment(NULL, envp);

    /* Alloc memory for environment header and body */
    FCGI_Header *env_request_header =
        apr_bucket_alloc(sizeof(FCGI_Header), alloc);
    FCGI_Header *env_empty_header =
        apr_bucket_alloc(sizeof(FCGI_Header), alloc);
    char *buf = apr_bucket_alloc(bufsize, alloc);
    apr_bucket *bucket_header = apr_bucket_heap_create((const char *)
                                                       env_request_header,
                                                       sizeof
                                                       (*env_request_header),
                                                       apr_bucket_free,
                                                       alloc);
    apr_bucket *bucket_body = apr_bucket_heap_create(buf, bufsize,
                                                     apr_bucket_free,
                                                     alloc);
    apr_bucket *bucket_empty_header = apr_bucket_heap_create((const char *)
                                                             env_empty_header,
                                                             sizeof
                                                             (*env_empty_header),
                                                             apr_bucket_free,
                                                             alloc);

    if (!env_request_header || !buf || !env_empty_header || !bucket_header
        || !bucket_body || !bucket_empty_header) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     main_server,
                     "mod_fcgid: can't alloc memory for envion");
        return 0;
    }

    /* Initialize header and body */
    if (!init_header(FCGI_PARAMS, 1, bufsize, 0, env_request_header)
        || !init_header(FCGI_PARAMS, 1, 0, 0, env_empty_header)) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     main_server,
                     "mod_fcgid: can't init env request header");
        return 0;
    }
    init_environment(buf, envp);

    /* Append the header and body to request brigade */
    APR_BRIGADE_INSERT_TAIL(request_brigade, bucket_header);
    APR_BRIGADE_INSERT_TAIL(request_brigade, bucket_body);
    APR_BRIGADE_INSERT_TAIL(request_brigade, bucket_empty_header);

    return 1;
}
