#include "apr_strings.h"
#include "ap_config.h"
+#include "apr_buckets.h"
#include "util_filter.h"
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "http_main.h"
#include "util_script.h"
-#include "http_core.h"
+#include "http_core.h"
#include "ap_mpm.h"
#include "php_apache.h"
f = ctx->f;
if (str_length == 0) return 0;
-
+
ba = f->c->bucket_alloc;
bb = apr_brigade_create(ctx->r->pool, ba);
b = apr_bucket_transient_create(str, str_length, ba);
APR_BRIGADE_INSERT_TAIL(bb, b);
-#if 0
- /* Add a Flush bucket to the end of this brigade, so that
- * the transient buckets above are more likely to make it out
- * the end of the filter instead of having to be copied into
- * someone's setaside. */
- b = apr_bucket_flush_create(ba);
- APR_BRIGADE_INSERT_TAIL(bb, b);
-#endif
-
if (ap_pass_brigade(f->next, bb) != APR_SUCCESS || ctx->r->connection->aborted) {
php_handle_aborted_connection();
}
-
+
return str_length; /* we always consume all the data passed to us. */
}
ptr = val;
*val = '\0';
-
+
do {
val++;
} while (*val == ' ');
apr_table_set(ctx->r->headers_out, sapi_header->header, val);
else
apr_table_add(ctx->r->headers_out, sapi_header->header, val);
-
+
*ptr = ':';
return SAPI_HEADER_ADD;
to_read = ctx->post_len - ctx->post_idx;
n = MIN(to_read, count_bytes);
-
+
if (n > 0) {
memcpy(buf, ctx->post_data + ctx->post_idx, n);
ctx->post_idx += n;
{
php_struct *ctx = SG(server_context);
const char *env_var;
-
+
env_var = apr_table_get(ctx->r->subprocess_env, name);
return (char *) env_var;
char *key, *val;
int new_val_len;
UConverter *conv = ZEND_U_CONVERTER(UG(runtime_encoding_conv));
-
+
APR_ARRAY_FOREACH_OPEN(arr, key, val)
if (!val) {
val = "";
php_error(E_WARNING, "Failed to decode _SERVER array entry");
}
APR_ARRAY_FOREACH_CLOSE()
-
+
if (php_register_variable_with_conv(conv, ZEND_STRL("PHP_SELF"), ctx->r->uri,
strlen(ctx->r->uri), track_vars_array, PARSE_SERVER TSRMLS_CC) == FAILURE) {
php_error(E_WARNING, "Failed to decode _SERVER array entry");
* handler seems to act on the first flush bucket, but ignores
* all further flush buckets.
*/
-
+
ba = ctx->r->connection->bucket_alloc;
bb = apr_brigade_create(ctx->r->pool, ba);
b = apr_bucket_flush_create(ba);
TSRMLS_FETCH();
ctx = SG(server_context);
-
+
if (ctx == NULL) { /* we haven't initialized our ctx yet, oh well */
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "%s", msg);
}
static int
php_apache_disable_caching(ap_filter_t *f)
{
- /* Identify PHP scripts as non-cacheable, thus preventing
+ /* Identify PHP scripts as non-cacheable, thus preventing
* Apache from sending a 304 status when the browser sends
* If-Modified-Since header.
*/
f->r->no_local_copy = 1;
-
+
return OK;
}
php_apache_sapi_register_variables,
php_apache_sapi_log_message, /* Log message */
php_apache_sapi_get_request_time, /* Get Request Time */
- NULL, /* Child terminate */
+ NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};
-static int php_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
+static int php_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
{
php_struct *ctx;
}
for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) {
- apr_bucket_read(b, &str, &n, 1);
+ apr_bucket_read(b, &str, &n, APR_NONBLOCK_READ);
if (n > 0) {
old_index = ctx->post_len;
ctx->post_len += n;
SG(sapi_headers).http_response_code = !f->r->status ? HTTP_OK : f->r->status;
SG(request_info).content_type = apr_table_get(f->r->headers_in, "Content-Type");
#undef safe_strdup
-#define safe_strdup(x) ((x)?strdup((x)):NULL)
+#define safe_strdup(x) ((x)?strdup((x)):NULL)
SG(request_info).query_string = safe_strdup(f->r->args);
SG(request_info).request_method = f->r->method;
SG(request_info).proto_num = f->r->proto_num;
content_length = (char *) apr_table_get(f->r->headers_in, "Content-Length");
SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
-
+
apr_table_unset(f->r->headers_out, "Content-Length");
apr_table_unset(f->r->headers_out, "Last-Modified");
apr_table_unset(f->r->headers_out, "Expires");
static void php_apache_request_dtor(ap_filter_t *f TSRMLS_DC)
{
+ php_apr_bucket_brigade *pbb = (php_apr_bucket_brigade *)f->ctx;
+
php_request_shutdown(NULL);
if (SG(request_info).query_string) {
if (SG(request_info).path_translated) {
free(SG(request_info).path_translated);
}
+
+ apr_brigade_destroy(pbb->bb);
}
static int php_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
{
php_struct *ctx;
- apr_bucket *b;
void *conf = ap_get_module_config(f->r->per_dir_config, &php6_module);
char *p = get_php_config(conf, "engine", sizeof("engine"));
+ zend_file_handle zfd;
+ php_apr_bucket_brigade *pbb;
+ apr_bucket *b;
TSRMLS_FETCH();
if (f->r->proxyreq) {
} zend_end_try();
return ap_pass_brigade(f->next, bb);
}
-
+
/* handle situations where user turns the engine off */
if (*p == '0') {
zend_try {
return ap_pass_brigade(f->next, bb);
}
+ if (f->ctx) {
+ pbb = (php_apr_bucket_brigade *)f->ctx;
+ } else {
+ pbb = f->ctx = apr_palloc(f->r->pool, sizeof(*pbb));
+ pbb->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+ }
+
+ if (ap_save_brigade(NULL, &pbb->bb, &bb, f->r->pool) != APR_SUCCESS) {
+ /* Bad */
+ }
+
+ apr_brigade_cleanup(bb);
+
+ /* Check to see if the last bucket in this brigade, it not
+ * we have to wait until then. */
+ if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pbb->bb))) {
+ return 0;
+ }
+
/* Setup the CGI variables if this is the main request.. */
- if (f->r->main == NULL ||
+ if (f->r->main == NULL ||
/* .. or if the sub-request envinronment differs from the main-request. */
f->r->subprocess_env != f->r->main->subprocess_env
) {
ap_add_common_vars(f->r);
ap_add_cgi_vars(f->r);
}
-
+
ctx = SG(server_context);
if (ctx == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
} zend_end_try();
return HTTP_INTERNAL_SERVER_ERROR;
}
- ctx->f = f; /* save whatever filters are after us in the chain. */
+
+ ctx->f = f->next; /* save whatever filters are after us in the chain. */
if (ctx->request_processed) {
zend_try {
return ap_pass_brigade(f->next, bb);
}
- for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) {
- zend_file_handle zfd;
-
- if (!ctx->request_processed && APR_BUCKET_IS_FILE(b)) {
- const char *path;
- apr_bucket_brigade *prebb = bb;
-
- /* Split the brigade into two brigades before and after
- * the file bucket. Leave the "after the FILE" brigade
- * in the original bb, so it gets passed outside of this
- * loop. */
- bb = apr_brigade_split(prebb, b);
-
- /* Pass the "before the FILE" brigade here
- * (if it's non-empty). */
- if (!APR_BRIGADE_EMPTY(prebb)) {
- apr_status_t rv;
- rv = ap_pass_brigade(f->next, prebb);
- /* XXX: destroy the prebb, since we know we're
- * done with it? */
- if (rv != APR_SUCCESS || ctx->r->connection->aborted) {
- php_handle_aborted_connection();
- }
- }
+ apply_config(conf);
+ php_apache_request_ctor(f, ctx TSRMLS_CC);
- apply_config(conf);
- php_apache_request_ctor(f, ctx TSRMLS_CC);
-
- apr_file_name_get(&path, ((apr_bucket_file *) b->data)->fd);
-
- /* Determine if we need to parse the file or show the source */
- if (strncmp(ctx->r->handler, "application/x-httpd-php-source", sizeof("application/x-httpd-php-source"))) {
- zfd.type = ZEND_HANDLE_FILENAME;
- zfd.filename = (char *) path;
- zfd.free_filename = 0;
- zfd.opened_path = NULL;
-
- php_execute_script(&zfd TSRMLS_CC);
-
- apr_table_set(ctx->r->notes, "mod_php_memory_usage",
- apr_psprintf(ctx->r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
- } else {
- zend_syntax_highlighter_ini syntax_highlighter_ini;
-
- php_get_highlight_struct(&syntax_highlighter_ini);
-
- highlight_file((char *)path, &syntax_highlighter_ini TSRMLS_CC);
- }
-
- php_apache_request_dtor(f TSRMLS_CC);
-
- if (!f->r->main) {
- ctx->request_processed = 1;
- }
+ /* It'd be nice if we could highlight based of a zend_file_handle here....
+ * ...but we can't. */
- /* Delete the FILE bucket from the brigade. */
- apr_bucket_delete(b);
+ zfd.type = ZEND_HANDLE_STREAM;
- /* We won't handle any more buckets in this brigade, so
- * it's ok to break out now. */
- break;
- }
+ zfd.handle.stream.handle = pbb;
+ zfd.handle.stream.reader = php_apache_read_stream;
+ zfd.handle.stream.closer = NULL;
+ zfd.handle.stream.fsizer = php_apache_fsizer_stream;
+ zfd.handle.stream.isatty = 0;
+
+ zfd.filename = f->r->filename;
+ zfd.opened_path = NULL;
+ zfd.free_filename = 0;
+
+ php_execute_script(&zfd TSRMLS_CC);
+
+ apr_table_set(ctx->r->notes, "mod_php_memory_usage",
+ apr_psprintf(ctx->r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
+
+ php_apache_request_dtor(f TSRMLS_CC);
+
+ if (!f->r->main) {
+ ctx->request_processed = 1;
}
+ b = apr_bucket_eos_create(f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(pbb->bb, b);
+
/* Pass whatever is left on the brigade. */
- return ap_pass_brigade(f->next, bb);
+ return ap_pass_brigade(f->next, pbb->bb);
}
static apr_status_t
int threaded_mpm;
ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
- if(threaded_mpm) {
+ if (threaded_mpm) {
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 0, "Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.");
return DONE;
}
int content_type_len = strlen("application/x-httpd-php");
if (r->content_type && !strncmp(r->content_type, "application/x-httpd-php", content_type_len-1)) {
- if (r->content_type[content_type_len] == '\0' || !strncmp(r->content_type+content_type_len, "-source", sizeof("-source"))) {
+ if (r->content_type[content_type_len] == '\0' || !strncmp(r->content_type+content_type_len, "-source", sizeof("-source"))) {
php_add_filter(r, r->output_filters);
php_add_filter(r, r->input_filters);
- }
+ }
}
}
ap_register_input_filter("PHP", php_input_filter, php_apache_disable_caching, AP_FTYPE_RESOURCE);
}
+static size_t php_apache_read_stream(void *handle, char *buf, size_t wantlen TSRMLS_DC)
+{
+ php_apr_bucket_brigade *pbb = (php_apr_bucket_brigade *)handle;
+ apr_bucket_brigade *rbb;
+ apr_size_t readlen;
+ apr_bucket *b = NULL;
+
+ rbb = pbb->bb;
+
+ if ((apr_brigade_partition(pbb->bb, wantlen, &b) == APR_SUCCESS) && b){
+ pbb->bb = apr_brigade_split(rbb, b);
+ }
+
+ readlen = wantlen;
+ apr_brigade_flatten(rbb, buf, &readlen);
+ apr_brigade_cleanup(rbb);
+
+ return readlen;
+}
+
+static size_t php_apache_fsizer_stream(void *handle TSRMLS_DC)
+{
+ php_apr_bucket_brigade *pbb = (php_apr_bucket_brigade *)handle;
+ apr_off_t actual = 0;
+
+ if (apr_brigade_length(pbb->bb, 1, &actual) == APR_SUCCESS) {
+ return actual;
+ }
+
+ return 0;
+}
+
AP_MODULE_DECLARE_DATA module php6_module = {
STANDARD20_MODULE_STUFF,
create_php_config, /* create per-directory config structure */