#include "apr_strings.h"
#include "apr_thread_proc.h"
#include "apr_buckets.h"
+#include "apr_poll.h"
#define CORE_PRIVATE
#include "util_script.h"
#include "util_filter.h"
+/* needed for get_suexec_identity hook */
+#include "unixd.h"
module AP_MODULE_DECLARE_DATA suphp_module;
Auxiliary functions
*********************/
-static int suphp_bucket_read(apr_bucket *b, char *buf, int len)
-{
- const char *dst_end = buf + len - 1;
- char * dst = buf;
- apr_status_t rv;
- const char *bucket_data;
- apr_size_t bucket_data_len;
- const char *src;
- const char *src_end;
- int count = 0;
-
- if (APR_BUCKET_IS_EOS(b))
- return -1;
-
- rv = apr_bucket_read(b, &bucket_data, &bucket_data_len, APR_BLOCK_READ);
- if (!APR_STATUS_IS_SUCCESS(rv) || (bucket_data_len == 0))
- {
- return 0;
- }
- src = bucket_data;
- src_end = bucket_data + bucket_data_len;
- while ((src < src_end) && (dst < dst_end))
- {
- *dst = *src;
- dst++;
- src++;
- count++;
- }
- *dst = 0;
- return count;
-}
-
-
-static void suphp_log_script_err(request_rec *r, apr_file_t *script_err)
+static apr_status_t suphp_log_script_err(request_rec *r, apr_file_t *script_err)
{
char argsbuffer[HUGE_STRING_LEN];
char *newline;
-
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
- script_err) == APR_SUCCESS) {
+ apr_status_t rv;
+
+ while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+ script_err)) == APR_SUCCESS) {
newline = strchr(argsbuffer, '\n');
if (newline) {
*newline = '\0';
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"%s", argsbuffer);
}
+
+ return rv;
+}
+
+char *suphp_brigade_read(apr_pool_t *p, apr_bucket_brigade *bb, int bytes)
+{
+ char *target_buf;
+ char *next_byte;
+ char *last_byte;
+ apr_bucket *b;
+
+ if (bytes == 0) {
+ return NULL;
+ }
+
+ target_buf = (char *) apr_palloc(p, bytes + 1);
+ next_byte = target_buf;
+ last_byte = target_buf + bytes;
+
+ for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) {
+ char *buf;
+ apr_size_t size;
+ apr_size_t i;
+ if (apr_bucket_read(b, &buf, &size, APR_BLOCK_READ) == APR_SUCCESS) {
+ for (i = 0; i < size; i++) {
+ *next_byte = *buf;
+ next_byte++;
+ buf++;
+ if (next_byte == last_byte) {
+ *next_byte = 0;
+ return target_buf;
+ }
+ }
+ }
+ }
+ next_byte = 0;
+ return target_buf;
}
char *target_group;
#endif
apr_table_t *handlers;
+ char *php_path;
} suphp_conf;
cfg->php_config = NULL;
cfg->engine = SUPHP_ENGINE_UNDEFINED;
+ cfg->php_path = NULL;
cfg->cmode = SUPHP_CONFIG_MODE_DIRECTORY;
#ifdef SUPHP_USE_USERGROUP
suphp_conf *cfg = (suphp_conf *) apr_pcalloc(p, sizeof(suphp_conf));
cfg->engine = SUPHP_ENGINE_UNDEFINED;
+ cfg->php_path = NULL;
cfg->cmode = SUPHP_CONFIG_MODE_SERVER;
+ /* Create table with 0 initial elements */
+ /* This size may be increased for performance reasons */
+ cfg->handlers = apr_table_make(p, 0);
+
return (void *) cfg;
}
merged->engine = child->engine;
else
merged->engine = parent->engine;
-
+
+ if (child->php_path != NULL)
+ merged->php_path = apr_pstrdup(p, child->php_path);
+ else
+ merged->php_path = apr_pstrdup(p, parent->php_path);
+
#ifdef SUPHP_USE_USERGROUP
if (child->target_user)
merged->target_user = apr_pstrdup(p, child->target_user);
merged->target_group = NULL;
#endif
+ merged->handlers = apr_table_overlay(p, child->handlers, parent->handlers);
+
return (void*) merged;
}
static const char *suphp_handle_cmd_add_handler(cmd_parms *cmd, void *mconfig,
- const char *arg)
+ const char *arg)
{
- suphp_conf *cfg = (suphp_conf *) mconfig;
+ suphp_conf *cfg;
+ if (mconfig)
+ cfg = (suphp_conf *) mconfig;
+ else
+ cfg = (suphp_conf *) ap_get_module_config(cmd->server->module_config, &suphp_module);
+
// Mark active handler with '1'
apr_table_set(cfg->handlers, arg, "1");
static const char *suphp_handle_cmd_remove_handler(cmd_parms *cmd,
- void *mconfig,
- const char *arg)
+ void *mconfig,
+ const char *arg)
{
- suphp_conf *cfg = (suphp_conf *) mconfig;
+ suphp_conf *cfg;
+ if (mconfig)
+ cfg = (suphp_conf *) mconfig;
+ else
+ cfg = (suphp_conf *) ap_get_module_config(cmd->server->module_config, &suphp_module);
+
// Mark deactivated handler with '0'
apr_table_set(cfg->handlers, arg, "0");
}
+static const char *suphp_handle_cmd_phppath(cmd_parms *cmd, void* mconfig, const char *arg)
+{
+ server_rec *s = cmd->server;
+ suphp_conf *cfg;
+
+ cfg = (suphp_conf *) ap_get_module_config(s->module_config, &suphp_module);
+
+ cfg->php_path = apr_pstrdup(cmd->pool, arg);
+
+ return NULL;
+}
+
+
static const command_rec suphp_cmds[] =
{
AP_INIT_FLAG("suPHP_Engine", suphp_handle_cmd_engine, NULL, RSRC_CONF | ACCESS_CONF,
#endif
AP_INIT_ITERATE("suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, RSRC_CONF | ACCESS_CONF, "Tells mod_suphp to handle these MIME-types"),
AP_INIT_ITERATE("suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, RSRC_CONF | ACCESS_CONF, "Tells mod_suphp not to handle these MIME-types"),
+ AP_INIT_TAKE1("suPHP_PHPPath", suphp_handle_cmd_phppath, NULL, RSRC_CONF, "Path to the PHP binary used to render source view"),
{NULL}
};
+/*****************************************
+ Code for reading script's stdout/stderr
+ based on mod_cgi's code
+ *****************************************/
+
+#if APR_FILES_AS_SOCKETS
+
+static const apr_bucket_type_t bucket_type_suphp;
+
+struct suphp_bucket_data {
+ apr_pollset_t *pollset;
+ request_rec *r;
+};
+
+static apr_bucket *suphp_bucket_create(request_rec *r, apr_file_t *out, apr_file_t *err, apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+ apr_status_t rv;
+ apr_pollfd_t fd;
+ struct suphp_bucket_data *data = apr_palloc(r->pool, sizeof(*data));
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ b->type = &bucket_type_suphp;
+ b->length = (apr_size_t) (-1);
+ b->start = (-1);
+
+ /* Create the pollset */
+ rv = apr_pollset_create(&data->pollset, 2, r->pool, 0);
+ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
+
+ fd.desc_type = APR_POLL_FILE;
+ fd.reqevents = APR_POLLIN;
+ fd.p = r->pool;
+ fd.desc.f = out; /* script's stdout */
+ fd.client_data = (void *) 1;
+ rv = apr_pollset_add(data->pollset, &fd);
+ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
+
+ fd.desc.f = err; /* script's stderr */
+ fd.client_data = (void *) 2;
+ rv = apr_pollset_add(data->pollset, &fd);
+ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
+
+ data->r = r;
+ b->data = data;
+ return b;
+}
+
+static apr_bucket *suphp_bucket_dup(struct suphp_bucket_data *data, apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ b->type = &bucket_type_suphp;
+ b->length = (apr_size_t) (-1);
+ b->start = (-1);
+ b->data = data;
+ return b;
+}
+
+/* This utility method is needed, because APR's implementation for the
+ pipe bucket cannot handle or special bucket type */
+static apr_status_t suphp_read_fd(apr_bucket *b, apr_file_t *fd, const char **str, apr_size_t *len)
+{
+ char *buf;
+ apr_status_t rv;
+
+ *str = NULL;
+ *len = APR_BUCKET_BUFF_SIZE;
+ buf = apr_bucket_alloc(*len, b->list);
+
+ rv = apr_file_read(fd, buf, len);
+
+ if (*len > 0) {
+ /* Got data */
+ struct suphp_bucket_data *data = b->data;
+ apr_bucket_heap *h;
+
+ /* Change the current bucket to refer to what we read
+ and append the pipe bucket after it */
+ b = apr_bucket_heap_make(b, buf, *len, apr_bucket_free);
+ /* Here, b->data is the new heap bucket data */
+ h = b->data;
+ h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
+ *str = buf;
+ APR_BUCKET_INSERT_AFTER(b, suphp_bucket_dup(data, b->list));
+ } else {
+ /* Got no data */
+ apr_bucket_free(buf);
+ b = apr_bucket_immortal_make(b, "", 0);
+ /* Here, b->data is the reference to the empty string */
+ *str = b->data;
+ }
+ return rv;
+}
+
+/* Poll on stdout and stderr to make sure the process does not block
+ because of a full system (stderr) buffer */
+static apr_status_t suphp_bucket_read(apr_bucket *b, const char **str, apr_size_t *len, apr_read_type_e block) {
+ struct suphp_bucket_data *data = b->data;
+ apr_interval_time_t timeout;
+ apr_status_t rv;
+ int gotdata = 0;
+
+ timeout = (block == APR_NONBLOCK_READ) ? 0 : data->r->server->timeout;
+
+ do {
+ const apr_pollfd_t *results;
+ apr_int32_t num;
+
+ rv = apr_pollset_poll(data->pollset, timeout, &num, &results);
+ if (APR_STATUS_IS_TIMEUP(rv)) {
+ return (timeout == 0) ? APR_EAGAIN : rv;
+ } else if (APR_STATUS_IS_EINTR(rv)) {
+ continue;
+ } else if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r, "Poll failed waiting for suPHP child process");
+ return rv;
+ }
+
+ while (num > 0) {
+ if (results[0].client_data == (void *) 1) {
+ /* handle stdout */
+ rv = suphp_read_fd(b, results[0].desc.f, str, len);
+ if (APR_STATUS_IS_EOF(rv)) {
+ rv = APR_SUCCESS;
+ }
+ gotdata = 1;
+ } else {
+ /* handle stderr */
+ apr_status_t rv2 = suphp_log_script_err(data->r, results[0].desc.f);
+ if (APR_STATUS_IS_EOF(rv2)) {
+ apr_pollset_remove(data->pollset, &results[0]);
+ }
+ }
+ num--;
+ results++;
+ }
+ } while (!gotdata);
+
+ return rv;
+}
+
+static const apr_bucket_type_t bucket_type_suphp = {
+ "SUPHP", 5, APR_BUCKET_DATA,
+ apr_bucket_destroy_noop,
+ suphp_bucket_read,
+ apr_bucket_setaside_notimpl,
+ apr_bucket_split_notimpl,
+ apr_bucket_copy_notimpl
+};
+
+#endif
+
+static void suphp_discard_output(apr_bucket_brigade *bb) {
+ apr_bucket *b;
+ const char *buf;
+ apr_size_t len;
+ apr_status_t rv;
+ for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) {
+ if (APR_BUCKET_IS_EOS(b)) {
+ break;
+ }
+ rv = apr_bucket_read(b, &buf, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+ break;
+ }
+ }
+}
+
/******************
Hooks / handlers
******************/
+static int suphp_script_handler(request_rec *r);
+static int suphp_source_handler(request_rec *r);
+
static int suphp_handler(request_rec *r)
{
+ suphp_conf *sconf, *dconf;
+
+ sconf = ap_get_module_config(r->server->module_config, &suphp_module);
+ dconf = ap_get_module_config(r->per_dir_config, &suphp_module);
+
+ /* only handle request if mod_suphp is active for this handler */
+ /* check only first byte of value (second has to be \0) */
+ if (apr_table_get(dconf->handlers, r->handler) != NULL)
+ {
+ if (*(apr_table_get(dconf->handlers, r->handler)) != '0')
+ {
+ return suphp_script_handler(r);
+ }
+ }
+ else
+ {
+ if ((apr_table_get(sconf->handlers, r->handler) != NULL)
+ && (*(apr_table_get(sconf->handlers, r->handler)) != '0'))
+ {
+ return suphp_script_handler(r);
+ }
+ }
+
+ if (!strcmp(r->handler, "x-httpd-php-source")
+ || !strcmp(r->handler, "application/x-httpd-php-source"))
+ {
+ return suphp_source_handler(r);
+ }
+
+ return DECLINED;
+}
+
+static int suphp_source_handler(request_rec *r)
+{
+ suphp_conf *conf;
+ apr_status_t rv;
+ apr_pool_t *p;
+ apr_file_t *file;
+ apr_proc_t *proc;
+ apr_procattr_t *procattr;
+ char **argv;
+ char **env;
+ apr_bucket_brigade *bb;
+ apr_bucket *b;
+ char *phpexec;
+
+ p = r->main ? r->main->pool : r->pool;
+
+ if (strcmp(r->method, "GET"))
+ {
+ return DECLINED;
+ }
+
+ conf = ap_get_module_config(r->server->module_config, &suphp_module);
+ phpexec = apr_pstrdup(p, conf->php_path);
+ if (phpexec == NULL)
+ {
+ return DECLINED;
+ }
+
+ // Try to open file for reading to see whether is is accessible
+ rv = apr_file_open(&file, apr_pstrdup(p, r->filename), APR_READ, APR_OS_DEFAULT, p);
+ if (rv == APR_SUCCESS)
+ {
+ apr_file_close(file);
+ file = NULL;
+ }
+ else if (rv == EACCES)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "access to %s denied", r->filename);
+ return HTTP_FORBIDDEN;
+ }
+ else if (rv == ENOENT)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "File does not exist: %s", r->filename);
+ return HTTP_NOT_FOUND;
+ }
+ else
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Could not open file: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ env = ap_create_environment(p, r->subprocess_env);
+
+ /* set attributes for new process */
+
+ if (((rv = apr_procattr_create(&procattr, p)) != APR_SUCCESS)
+ || ((rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK)) != APR_SUCCESS)
+ || ((rv = apr_procattr_dir_set(procattr, ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS)
+ || ((apr_procattr_cmdtype_set(procattr, APR_PROGRAM)) != APR_SUCCESS)
+ || ((apr_procattr_error_check_set(procattr, 1)) != APR_SUCCESS)
+ || ((apr_procattr_detach_set(procattr, 0)) != APR_SUCCESS))
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "couldn't set child process attributes: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+
+ /* create new process */
+
+ argv = apr_palloc(p, 4 * sizeof(char *));
+ argv[0] = phpexec;
+ argv[1] = "-s";
+ argv[2] = apr_pstrdup(p, r->filename);
+ argv[3] = NULL;
+
+ env = ap_create_environment(p, r->subprocess_env);
+
+ proc = apr_pcalloc(p, sizeof(*proc));
+ rv = apr_proc_create(proc, phpexec, (const char *const *)argv, (const char *const *)env, procattr, p);
+ if (rv != APR_SUCCESS)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "couldn't create child process: %s for %s", phpexec, r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ apr_pool_note_subprocess(p, proc, APR_KILL_AFTER_TIMEOUT);
+
+ if (!proc->out)
+ return APR_EBADF;
+ apr_file_pipe_timeout_set(proc->out, r->server->timeout);
+
+ if (!proc->in)
+ return APR_EBADF;
+ apr_file_pipe_timeout_set(proc->in, r->server->timeout);
+
+ if (!proc->err)
+ return APR_EBADF;
+ apr_file_pipe_timeout_set(proc->err, r->server->timeout);
+
+ /* discard input */
+
+ bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
+ apr_file_flush(proc->in);
+ apr_file_close(proc->in);
+
+ rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN);
+ if (rv != APR_SUCCESS)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "couldn't get input from filters: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ suphp_discard_output(bb);
+ apr_brigade_cleanup(bb);
+
+ /* get output from script */
+
+#if APR_FILES_AS_SOCKETS
+ apr_file_pipe_timeout_set(proc->out, 0);
+ apr_file_pipe_timeout_set(proc->err, 0);
+ b = suphp_bucket_create(r, proc->out, proc->err, r->connection->bucket_alloc);
+#else
+ b = apr_bucket_pipe_create(proc->out, r->connection->bucket_alloc);
+#endif
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+
+ b = apr_bucket_eos_create(r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+
+ /* send output to browser (through filters) */
+
+ r->content_type = "text/html";
+ rv = ap_pass_brigade(r->output_filters, bb);
+
+ /* write errors to logfile */
+
+ if (rv == APR_SUCCESS && !r->connection->aborted)
+ {
+ suphp_log_script_err(r, proc->err);
+ apr_file_close(proc->err);
+ }
+
+ return OK;
+}
+
+static int suphp_script_handler(request_rec *r)
+{
apr_pool_t *p;
suphp_conf *sconf;
suphp_conf *dconf;
#else
char strbuf[MAX_STRING_LEN];
#endif
+ char *tmpbuf;
int nph = 0;
int eos_reached = 0;
char *auth_user = NULL;
char *auth_pass = NULL;
+
+#ifdef SUPHP_USE_USERGROUP
+ char *ud_user = NULL;
+ char *ud_group = NULL;
+#endif
apr_bucket_brigade *bb;
apr_bucket *b;
dconf = ap_get_module_config(r->per_dir_config, &suphp_module);
core_conf = (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module);
- /* only handle request if mod_suphp is active for this handler */
- /* check only first byte of value (second has to be \0) */
- if ((apr_table_get(dconf->handlers, r->handler) == NULL)
- || (*(apr_table_get(dconf->handlers, r->handler)) == '0'))
- return DECLINED;
-
/* check if suPHP is enabled for this request */
if (((sconf->engine != SUPHP_ENGINE_ON)
if (!(r->finfo.protection & APR_UREAD))
{
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Insufficient permissions: %s", r->filename);
- return HTTP_FORBIDDEN;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Insufficient permissions: %s", r->filename);
+ return HTTP_FORBIDDEN;
}
#ifdef SUPHP_USE_USERGROUP
if ((sconf->target_user == NULL || sconf->target_group == NULL)
&& (dconf->target_user == NULL || dconf->target_group == NULL))
{
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "No user or group set - set suPHP_UserGroup");
- return HTTP_INTERNAL_SERVER_ERROR;
+ /* Check for userdir request */
+ ap_unix_identity_t *userdir_id = NULL;
+ userdir_id = ap_run_get_suexec_identity(r);
+ if (userdir_id != NULL && userdir_id->userdir) {
+ ud_user = apr_psprintf(r->pool, "#%ld", (long) userdir_id->uid);
+ ud_group = apr_psprintf(r->pool, "#%ld", (long) userdir_id->gid);
+ } else {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "No user or group set - set suPHP_UserGroup");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
}
#endif
apr_table_setn(r->subprocess_env, "SUPHP_USER",
apr_pstrdup(r->pool, dconf->target_user));
}
- else
+ else if (sconf->target_user)
{
apr_table_setn(r->subprocess_env, "SUPHP_USER",
apr_pstrdup(r->pool, sconf->target_user));
}
+ else
+ {
+ apr_table_setn(r->subprocess_env, "SUPHP_USER",
+ apr_pstrdup(r->pool, ud_user));
+ }
if (dconf->target_group)
{
apr_table_setn(r->subprocess_env, "SUPHP_GROUP",
apr_pstrdup(r->pool, dconf->target_group));
}
- else
+ else if (sconf->target_group)
{
apr_table_setn(r->subprocess_env, "SUPHP_GROUP",
apr_pstrdup(r->pool, sconf->target_group));
}
+ else
+ {
+ apr_table_setn(r->subprocess_env, "SUPHP_GROUP",
+ apr_pstrdup(r->pool, ud_group));
+ }
#endif
env = ap_create_environment(p, r->subprocess_env);
return rv;
}
- APR_BRIGADE_FOREACH(bucket, bb)
+ for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb); bucket = APR_BUCKET_NEXT(bucket))
{
const char *data;
apr_size_t len;
/* get output from script and check if non-parsed headers are used */
+#if APR_FILES_AS_SOCKETS
+ apr_file_pipe_timeout_set(proc->out, 0);
+ apr_file_pipe_timeout_set(proc->err, 0);
+ b = suphp_bucket_create(r, proc->out, proc->err, r->connection->bucket_alloc);
+#else
b = apr_bucket_pipe_create(proc->out, r->connection->bucket_alloc);
+#endif
+
APR_BRIGADE_INSERT_TAIL(bb, b);
- len = 8;
- if ((suphp_bucket_read(b, strbuf, len) == len)
- && !(strcmp(strbuf, "HTTP/1.0") && strcmp(strbuf, "HTTP/1.1")))
+ b = apr_bucket_eos_create(r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+
+ tmpbuf = suphp_brigade_read(p, bb, 8);
+ if (strlen(tmpbuf) == 8 && !(strncmp(tmpbuf, "HTTP/1.0", 8) && strncmp(tmpbuf, "HTTP/1.1", 8)))
{
nph = 1;
}
- b = apr_bucket_eos_create(r->connection->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(bb, b);
-
- if (proc->out && !nph)
+ if (!nph)
{
- /* normal cgi headers, so we have to create the real headers by hand */
+ /* normal cgi headers, so we have to create the real headers ourselves */
int ret;
const char *location;
-
- ret = ap_scan_script_header_err_brigade(r, bb, strbuf);
- if (ret == HTTP_NOT_MODIFIED)
- {
- return ret;
- }
+
+ ret = ap_scan_script_header_err_brigade(r, bb, strbuf);
+ if (ret == HTTP_NOT_MODIFIED)
+ {
+ return ret;
+ }
else if (ret != APR_SUCCESS)
{
+ suphp_discard_output(bb);
+ apr_brigade_destroy(bb);
suphp_log_script_err(r, proc->err);
/* ap_scan_script_header_err_brigade does logging itself,
{
/* empty brigade (script output) and modify headers */
- const char *buf;
- apr_size_t blen;
- APR_BRIGADE_FOREACH(b, bb)
- {
- if (APR_BUCKET_IS_EOS(b))
- break;
- if (apr_bucket_read(b, &buf, &blen, APR_BLOCK_READ) != APR_SUCCESS)
- break;
- }
+ suphp_discard_output(bb);
apr_brigade_destroy(bb);
suphp_log_script_err(r, proc->err);
r->method = apr_pstrdup(r->pool, "GET");
else if (location && r->status == 200)
{
/* empty brigade (script output) */
- const char *buf;
- apr_size_t blen;
- APR_BRIGADE_FOREACH(b, bb)
- {
- if (APR_BUCKET_IS_EOS(b))
- break;
- if (apr_bucket_read(b, &buf, &blen, APR_BLOCK_READ) != APR_SUCCESS)
- break;
- }
+ suphp_discard_output(bb);
apr_brigade_destroy(bb);
+ suphp_log_script_err(r, proc->err);
return HTTP_MOVED_TEMPORARILY;
}