/* 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; }