Changes with Apache 2.3.14
+ *) core: Add more logging to ap_scan_script_header_err* functions. Add
+ ap_scan_script_header_err*_ex functions that take a module index for
+ logging.
+ mod_cgi, mod_cgid, mod_proxy_fcgi, mod_proxy_scgi, mod_isapi: Use the
+ new functions in order to make logging configurable per-module.
+ [Stefan Fritsch]
+
*) mod_dir: Add DirectoryIndexRedirect to send an external redirect to
the proper index. [Eric Covener]
* add ap_start_lingering_close(),
* add conn_state_e:CONN_STATE_LINGER_NORMAL and CONN_STATE_LINGER_SHORT
* 20110619.1 (2.3.13-dev) add ap_str_toupper()
- * 20110702.0 (2.3.13-dev) make ap_expr_parse_cmd() macro wrapper for new
+ * 20110702.0 (2.3.14-dev) make ap_expr_parse_cmd() macro wrapper for new
* ap_expr_parse_cmd_mi() function, add ap_expr_str_*() functions,
* rename AP_EXPR_FLAGS_* -> AP_EXPR_FLAG_*
+ * 20110702.1 (2.3.14-dev) Add ap_scan_script_header_err*_ex functions
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20110702
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
*/
AP_DECLARE(int) ap_scan_script_header_err(request_rec *r, apr_file_t *f, char *buffer);
+/**
+ * Read headers output from a script, ensuring that the output is valid. If
+ * the output is valid, then the headers are added to the headers out of the
+ * current request
+ * @param r The current request
+ * @param f The file to read from
+ * @param buffer Empty when calling the function. On output, if there was an
+ * error, the string that cause the error is stored here.
+ * @param module_index The module index to be used for logging
+ * @return HTTP_OK on success, HTTP_INTERNAL_SERVER_ERROR otherwise
+ */
+AP_DECLARE(int) ap_scan_script_header_err_ex(request_rec *r, apr_file_t *f,
+ char *buffer, int module_index);
+
+
/**
* Read headers output from a script, ensuring that the output is valid. If
* the output is valid, then the headers are added to the headers out of the
apr_bucket_brigade *bb,
char *buffer);
+/**
+ * Read headers output from a script, ensuring that the output is valid. If
+ * the output is valid, then the headers are added to the headers out of the
+ * current request
+ * @param r The current request
+ * @param bb The brigade from which to read
+ * @param buffer Empty when calling the function. On output, if there was an
+ * error, the string that cause the error is stored here.
+ * @param module_index The module index to be used for logging
+ * @return HTTP_OK on success, HTTP_INTERNAL_SERVER_ERROR otherwise
+ */
+AP_DECLARE(int) ap_scan_script_header_err_brigade_ex(request_rec *r,
+ apr_bucket_brigade *bb,
+ char *buffer,
+ int module_index);
+
/**
* Read headers strings from a script, ensuring that the output is valid. If
* the output is valid, then the headers are added to the headers out of the
int *termarg, ...)
ap_func_attr_sentinel;
+/**
+ * Read headers strings from a script, ensuring that the output is valid. If
+ * the output is valid, then the headers are added to the headers out of the
+ * current request
+ * @param r The current request
+ * @param buffer Empty when calling the function. On output, if there was an
+ * error, the string that cause the error is stored here.
+ * @param module_index The module index to be used for logging
+ * @param termch Pointer to the last character parsed.
+ * @param termarg Pointer to an int to capture the last argument parsed.
+ *
+ * The varargs are string arguments to parse consecutively for headers,
+ * with a NULL argument to terminate the list.
+ *
+ * @return HTTP_OK on success, HTTP_INTERNAL_SERVER_ERROR otherwise
+ */
+AP_DECLARE_NONSTD(int) ap_scan_script_header_err_strs_ex(request_rec *r,
+ char *buffer,
+ int module_index,
+ const char **termch,
+ int *termarg, ...)
+ ap_func_attr_sentinel;
+
+
/**
* Read headers output from a script, ensuring that the output is valid. If
* the output is valid, then the headers are added to the headers out of the
int (*getsfunc) (char *, int, void *),
void *getsfunc_data);
+/**
+ * Read headers output from a script, ensuring that the output is valid. If
+ * the output is valid, then the headers are added to the headers out of the
+ * current request
+ * @param r The current request
+ * @param buffer Empty when calling the function. On output, if there was an
+ * error, the string that cause the error is stored here.
+ * @param getsfunc Function to read the headers from. This function should
+ act like gets()
+ * @param getsfunc_data The place to read from
+ * @param module_index The module index to be used for logging
+ * @return HTTP_OK on success, HTTP_INTERNAL_SERVER_ERROR otherwise
+ */
+AP_DECLARE(int) ap_scan_script_header_err_core_ex(request_rec *r, char *buffer,
+ int (*getsfunc) (char *, int, void *),
+ void *getsfunc_data, int module_index);
+
+
/**
* Parse query args for the request and store in a new table allocated
* from the request pool.
old_status = cid->r->status;
if (stat) {
- res = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg,
- stat, head, NULL);
+ res = ap_scan_script_header_err_strs_ex(cid->r, NULL,
+ APLOG_MODULE_INDEX, &termch, &termarg, stat, head, NULL);
}
else {
- res = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg,
- head, NULL);
+ res = ap_scan_script_header_err_strs_ex(cid->r, NULL,
+ APLOG_MODULE_INDEX, &termch, &termarg, head, NULL);
}
/* Set our status. */
return HTTP_FORBIDDEN;
}
- ap_scan_script_header_err(r, f, NULL);
+ ap_scan_script_header_err_ex(r, f, NULL, APLOG_MODULE_INDEX);
location = apr_table_get(r->headers_out, "Location");
if (location && location[0] == '/' &&
char sbuf[MAX_STRING_LEN];
int ret;
- if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) {
+ if ((ret = ap_scan_script_header_err_brigade_ex(r, bb, sbuf,
+ APLOG_MODULE_INDEX)))
+ {
ret = log_script(r, conf, ret, dbuf, sbuf, bb, script_err);
/*
b = apr_bucket_eos_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
- if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) {
+ if ((ret = ap_scan_script_header_err_brigade_ex(r, bb, sbuf,
+ APLOG_MODULE_INDEX)))
+ {
ret = log_script(r, conf, ret, dbuf, sbuf, bb, NULL);
/*
int status;
seen_end_of_headers = 1;
- status = ap_scan_script_header_err_brigade(r, ob,
- NULL);
+ status = ap_scan_script_header_err_brigade_ex(r, ob,
+ NULL, APLOG_MODULE_INDEX);
/* suck in all the rest */
if (status != OK) {
apr_bucket *tmp_b;
b = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
- status = ap_scan_script_header_err_brigade(r, bb, NULL);
+ status = ap_scan_script_header_err_brigade_ex(r, bb, NULL,
+ APLOG_MODULE_INDEX);
if (status != OK) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: " PROXY_FUNCTION ": error reading response "
}
#define HTTP_UNSET (-HTTP_OK)
+#define SCRIPT_LOG_MARK __FILE__,__LINE__,module_index
-AP_DECLARE(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
+AP_DECLARE(int) ap_scan_script_header_err_core_ex(request_rec *r, char *buffer,
int (*getsfunc) (char *, int, void *),
- void *getsfunc_data)
+ void *getsfunc_data,
+ int module_index)
{
char x[MAX_STRING_LEN];
char *w, *l;
int cgi_status = HTTP_UNSET;
apr_table_t *merge;
apr_table_t *cookie_table;
+ int trace_log = APLOG_R_MODULE_IS_LEVEL(r, module_index, APLOG_TRACE1);
+ int first_header = 1;
if (buffer) {
*buffer = '\0';
int rv = (*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data);
if (rv == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
- "Premature end of script headers: %s",
+ const char *msg = "Premature end of script headers";
+ if (first_header)
+ msg = "End of script output before headers";
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
+ "%s: %s", msg,
apr_filepath_name_get(r->filename));
return HTTP_INTERNAL_SERVER_ERROR;
}
else if (rv == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
"Script timed out before returning headers: %s",
apr_filepath_name_get(r->filename));
return HTTP_GATEWAY_TIME_OUT;
return cond_status;
}
+ if (trace_log) {
+ if (first_header)
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_TRACE4, 0, r,
+ "Headers from script '%s':",
+ apr_filepath_name_get(r->filename));
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_TRACE4, 0, r, " %s", w);
+ }
+
/* if we see a bogus header don't ignore it. Shout and scream */
#if APR_CHARSET_EBCDIC
++maybeASCII;
}
if (maybeASCII > maybeEBCDIC) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ ap_log_error(SCRIPT_LOG_MARK, APLOG_ERR, 0, r->server,
"CGI Interface Error: Script headers apparently ASCII: (CGI = %s)",
r->filename);
inbytes_left = outbytes_left = cp - w;
}
}
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
- "malformed header from script: %s; Bad header: %.30s",
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
+ "malformed header from script '%s': Bad header: %.30s",
apr_filepath_name_get(r->filename), w);
return HTTP_INTERNAL_SERVER_ERROR;
}
*/
else if (!strcasecmp(w, "Status")) {
r->status = cgi_status = atoi(l);
+ if (!ap_is_HTTP_VALID_RESPONSE(cgi_status))
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
+ "Invalid status line from script '%s': %s",
+ apr_filepath_name_get(r->filename), w);
+ else
+ ap_log_rerror(SCRIPT_LOG_MARK, APLOG_TRACE1, 0, r,
+ "Status line from script '%s': %s",
+ apr_filepath_name_get(r->filename), w);
r->status_line = apr_pstrdup(r->pool, l);
}
else if (!strcasecmp(w, "Location")) {
else {
apr_table_add(merge, w, l);
}
+ first_header = 0;
}
/* never reached - we leave this function within the while loop above */
return OK;
}
+AP_DECLARE(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
+ int (*getsfunc) (char *, int, void *),
+ void *getsfunc_data)
+{
+ return ap_scan_script_header_err_core_ex(r, buffer, getsfunc,
+ getsfunc_data,
+ APLOG_MODULE_INDEX);
+}
+
static int getsfunc_FILE(char *buf, int len, void *f)
{
return apr_file_gets(buf, len, (apr_file_t *) f) == APR_SUCCESS;
AP_DECLARE(int) ap_scan_script_header_err(request_rec *r, apr_file_t *f,
char *buffer)
{
- return ap_scan_script_header_err_core(r, buffer, getsfunc_FILE, f);
+ return ap_scan_script_header_err_core_ex(r, buffer, getsfunc_FILE, f,
+ APLOG_MODULE_INDEX);
+}
+
+AP_DECLARE(int) ap_scan_script_header_err_ex(request_rec *r, apr_file_t *f,
+ char *buffer, int module_index)
+{
+ return ap_scan_script_header_err_core_ex(r, buffer, getsfunc_FILE, f,
+ module_index);
}
+
static int getsfunc_BRIGADE(char *buf, int len, void *arg)
{
apr_bucket_brigade *bb = (apr_bucket_brigade *)arg;
apr_bucket_brigade *bb,
char *buffer)
{
- return ap_scan_script_header_err_core(r, buffer, getsfunc_BRIGADE, bb);
+ return ap_scan_script_header_err_core_ex(r, buffer, getsfunc_BRIGADE, bb,
+ APLOG_MODULE_INDEX);
+}
+
+AP_DECLARE(int) ap_scan_script_header_err_brigade_ex(request_rec *r,
+ apr_bucket_brigade *bb,
+ char *buffer,
+ int module_index)
+{
+ return ap_scan_script_header_err_core_ex(r, buffer, getsfunc_BRIGADE, bb,
+ module_index);
}
+
struct vastrs {
va_list args;
int arg;
* character is returned to **arg, **data. (The first optional arg is
* counted as 0.)
*/
+AP_DECLARE_NONSTD(int) ap_scan_script_header_err_strs_ex(request_rec *r,
+ char *buffer,
+ int module_index,
+ const char **termch,
+ int *termarg, ...)
+{
+ struct vastrs strs;
+ int res;
+
+ va_start(strs.args, termarg);
+ strs.arg = 0;
+ strs.curpos = va_arg(strs.args, char*);
+ res = ap_scan_script_header_err_core_ex(r, buffer, getsfunc_STRING,
+ (void *) &strs, module_index);
+ if (termch)
+ *termch = strs.curpos;
+ if (termarg)
+ *termarg = strs.arg;
+ va_end(strs.args);
+ return res;
+}
+
AP_DECLARE_NONSTD(int) ap_scan_script_header_err_strs(request_rec *r,
char *buffer,
const char **termch,
va_start(strs.args, termarg);
strs.arg = 0;
strs.curpos = va_arg(strs.args, char*);
- res = ap_scan_script_header_err_core(r, buffer, getsfunc_STRING, (void *) &strs);
+ res = ap_scan_script_header_err_core_ex(r, buffer, getsfunc_STRING,
+ (void *) &strs, APLOG_MODULE_INDEX);
if (termch)
*termch = strs.curpos;
if (termarg)
return res;
}
-
static void
argstr_to_table(char *str, apr_table_t *parms)
{