/*
 * 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, request_rec * r,
                  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);

    /* Initialize begin request header and body */
    if (!init_header(FCGI_BEGIN_REQUEST, 1, sizeof(FCGI_BeginRequestBody),
                     0, begin_request_header)) {
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
                      "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(request_rec * r, 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);

    /* 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_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
                      "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;
}
