/* 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 "mod_perl.h"

MP_INLINE int modperl_cgi_header_parse(request_rec *r, char *buffer,
                                       apr_size_t *len, const char **body)
{
    int status;
    int termarg;
    const char *location;
    const char *tmp;
    apr_size_t tlen, newln;

    if (!buffer) {
        return DECLINED;
    }

    /* ap_scan_script_header_err_strs won't handle correctly binary
     * data following the headers, e.g. when the terminating /\n\r?\n/
     * is followed by \0\0 which is a part of the response
     * body. Therefore we need to separate the headers from the body
     * and not rely on ap_scan_script_header_err_strs to do that for
     * us.
     */
    tmp = buffer;
    newln = 0;
    tlen = *len;
    while (tlen--) {
        /* that strange mix of CR and \n (and not LF) copied from
         * util_script.c:ap_scan_script_header_err_core
         */
        if (*tmp != CR && *tmp != '\n') {
            newln = 0;
        }
        if (*tmp == '\n') {
            newln++;
        }
        tmp++;
        if (newln == 2) {
            break;
        }
    }

    if (tmp - buffer >= *len) {
        *body = NULL; /* no body along with headers */
        *len = 0;
    }
    else {
        *body = tmp;
        *len = *len - (tmp - buffer);
    }

    status = ap_scan_script_header_err_strs(r, NULL, NULL,
                                            &termarg, buffer, NULL);

    /* code below from mod_cgi.c */
    location = apr_table_get(r->headers_out, "Location");

    if (location && (location[0] == '/') && (r->status == 200)) {
        r->method = apr_pstrdup(r->pool, "GET");
        r->method_number = M_GET;

        /* We already read the message body (if any), so don't allow
         * the redirected request to think it has one.  We can ignore
         * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
         */
        apr_table_unset(r->headers_in, "Content-Length");

        ap_internal_redirect_handler(location, r);

        return OK;
    }
    else if (location && (r->status == 200)) {
        MP_dRCFG;

        /* Note that if a script wants to produce its own Redirect
         * body, it now has to explicitly *say* "Status: 302"
         */

        /* XXX: this is a hack.
         * filter return value doesn't seem to impact anything.
         */
        rcfg->status = HTTP_MOVED_TEMPORARILY;

        return HTTP_MOVED_TEMPORARILY;
    }

    return status;
}

/*
 * Local Variables:
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * End:
 */
