Browse Source

Patch by Aaron Bannert <aaron@clove.org> and Cliff Woolley <jwoolley@virginia.edu>.

experimental/new_ui_api
Sebastian Bergmann 24 years ago
parent
commit
38af983c80
  1. 3
      sapi/apache2filter/php_apache.h
  2. 151
      sapi/apache2filter/sapi_apache2.c

3
sapi/apache2filter/php_apache.h

@ -21,7 +21,6 @@
typedef struct php_struct {
int state;
apr_bucket_brigade *bb;
ap_filter_t *f;
/* Length of post_data buffer */
int post_len;
@ -29,6 +28,8 @@ typedef struct php_struct {
int post_idx;
/* Buffer for request body filter */
char *post_data;
/* Whether or not we've processed PHP in the output filters yet. */
int request_processed;
} php_struct;
int php_apache_register_module(void);

151
sapi/apache2filter/sapi_apache2.c

@ -50,26 +50,29 @@ php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
apr_bucket_brigade *bb;
apr_bucket_alloc_t *ba;
php_struct *ctx;
uint now;
ctx = SG(server_context);
if (str_length == 0) return 0;
ba = ctx->f->r->connection->bucket_alloc;
ba = ctx->f->c->bucket_alloc;
bb = apr_brigade_create(ctx->f->r->pool, ba);
while (str_length > 0) {
now = MIN(str_length, 4096);
b = apr_bucket_transient_create(str, now, ba);
APR_BRIGADE_INSERT_TAIL(bb, b);
str += now;
str_length -= now;
}
b = apr_bucket_transient_create(str, str_length, ba);
APR_BRIGADE_INSERT_TAIL(bb, b);
/* 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);
if (ap_pass_brigade(ctx->f->next, bb) != APR_SUCCESS) {
php_handle_aborted_connection();
}
return str_length;
return 0; /* we wrote everything, we promise! */
}
static int
@ -234,13 +237,6 @@ static sapi_module_struct apache2_sapi_module = {
AP_MODULE_DECLARE_DATA module php4_module;
#define INIT_CTX \
if (ctx == NULL) { \
/* Initialize filter context */ \
SG(server_context) = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx)); \
ctx->bb = apr_brigade_create(f->c->pool, f->c->bucket_alloc); \
}
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)
{
@ -258,7 +254,10 @@ static int php_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
ctx = SG(server_context);
INIT_CTX;
if (ctx == NULL) {
/* Initialize filter context */
SG(server_context) = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
}
if ((rv = ap_get_brigade(f->next, bb, mode, block, readbytes)) != APR_SUCCESS) {
return rv;
@ -331,79 +330,67 @@ static int php_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
ap_add_common_vars(f->r);
ap_add_cgi_vars(f->r);
ctx = SG(server_context);
INIT_CTX;
ctx->f = f;
/* states:
* 0: request startup
* 1: collecting data
* 2: script execution and request shutdown
*/
if (ctx->state == 0) {
apply_config(conf);
ctx->state++;
php_apache_request_ctor(f, ctx TSRMLS_CC);
if (f->ctx == NULL) {
/* Initialize filter context */
f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
ctx->f = f;
}
/* moves all buckets from bb to ctx->bb */
ap_save_brigade(f, &ctx->bb, &bb, f->r->pool);
if (ctx->request_processed) {
return ap_pass_brigade(f->next, bb);
}
/* If we have received all data from the previous filters,
* we "flatten" the buckets by creating a single string buffer.
*/
if (ctx->state == 1 && APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(ctx->bb))) {
APR_BRIGADE_FOREACH(b, bb) {
zend_file_handle zfd;
apr_bucket *eos;
/* We want to execute only one script per request.
* A bug in Apache or other filters could cause us
* to reenter php_filter during script execution, so
* we protect ourselves here.
*/
ctx->state = 2;
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) {
php_handle_aborted_connection();
}
}
/* Handle phpinfo/phpcredits/built-in images */
if (!php_handle_special_queries(TSRMLS_C)) {
SG(server_context) = ctx;
apply_config(conf);
php_apache_request_ctor(f, ctx TSRMLS_CC);
b = APR_BRIGADE_FIRST(ctx->bb);
apr_file_name_get(&path, ((apr_bucket_file *) b->data)->fd);
zfd.type = ZEND_HANDLE_FILENAME;
zfd.filename = (char *) path;
zfd.free_filename = 0;
zfd.opened_path = NULL;
php_execute_script(&zfd TSRMLS_CC);
php_apache_request_dtor(f TSRMLS_CC);
if (APR_BUCKET_IS_FILE(b)) {
const char *path;
apr_file_name_get(&path, ((apr_bucket_file *) b->data)->fd);
zfd.type = ZEND_HANDLE_FILENAME;
zfd.filename = (char *) path;
zfd.free_filename = 0;
zfd.opened_path = NULL;
php_execute_script(&zfd TSRMLS_CC);
} else {
#define PHP_NO_DATA "The PHP Filter did not receive suitable input data"
eos = apr_bucket_transient_create(PHP_NO_DATA, sizeof(PHP_NO_DATA)-1, f->c->bucket_alloc);
APR_BRIGADE_INSERT_HEAD(bb, eos);
}
}
php_apache_request_dtor(f TSRMLS_CC);
ctx->request_processed = 1;
SG(server_context) = 0;
/* Pass EOS bucket to next filter to signal end of request */
eos = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, eos);
return ap_pass_brigade(f->next, bb);
} else
apr_brigade_destroy(bb);
/* Delete the FILE bucket from the brigade. */
apr_bucket_delete(b);
return APR_SUCCESS;
/* We won't handle any more buckets in this brigade, so
* it's ok to break out now. */
break;
}
}
/* Pass whatever is left on the brigade. */
return ap_pass_brigade(f->next, bb);
}
static apr_status_t
@ -496,3 +483,5 @@ AP_MODULE_DECLARE_DATA module php4_module = {
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
Loading…
Cancel
Save