static apr_status_t read_complete_body(request_rec *r, apr_bucket_brigade *kept_body) { apr_bucket_brigade *tmp_bb; apr_bucket *t_bucket1, *t_bucket2; unsigned short eos_seen = 0; apr_status_t status; tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); while (!eos_seen) { status = ap_get_brigade( r->input_filters, tmp_bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN); /* This means the filter discovered an error. * Furthermore input-filter already handeld the error and sends * something to the output chain. * For example ap_http_filter does this if LimitRequestBody is reached */ if (status == AP_FILTER_ERROR) { apr_brigade_destroy(tmp_bb); return AP_FILTER_ERROR; } /* Cool no need to search for the eos bucket */ if (APR_STATUS_IS_EOF(status)) { apr_brigade_destroy(tmp_bb); return APR_SUCCESS; } if (status != APR_SUCCESS) { apr_brigade_destroy(tmp_bb); return status; } ITER_BRIGADE(t_bucket1, tmp_bb) { apr_bucket_copy(t_bucket1, &t_bucket2); /* If SSL is used TRANSIENT buckets are returned. * However we need this bucket for a longer period than * this function call, hence 'setaside' the bucket. */ if APR_BUCKET_IS_TRANSIENT(t_bucket2) { apr_bucket_setaside(t_bucket2, r->pool); } APR_BRIGADE_INSERT_TAIL(kept_body, t_bucket2); if (!eos_seen && APR_BUCKET_IS_EOS(t_bucket1)) { eos_seen = 1; } } apr_brigade_cleanup(tmp_bb); }
static PyObject *filter_flush(filterobject *self, PyObject *args) { conn_rec *c = self->request_obj->request_rec->connection; /* does the output brigade exist? */ if (!self->bb_out) { self->bb_out = apr_brigade_create(self->f->r->pool, c->bucket_alloc); } APR_BRIGADE_INSERT_TAIL(self->bb_out, apr_bucket_flush_create(c->bucket_alloc)); if (!self->is_input) { Py_BEGIN_ALLOW_THREADS; self->rc = ap_pass_brigade(self->f->next, self->bb_out); apr_brigade_destroy(self->bb_out); Py_END_ALLOW_THREADS; if(self->rc != APR_SUCCESS) { PyErr_SetString(PyExc_IOError, "Flush failed."); return NULL; } } Py_INCREF(Py_None); return Py_None; }
static PyObject *filter_close(filterobject *self, PyObject *args) { conn_rec *c = self->request_obj->request_rec->connection; if (! self->closed) { /* does the output brigade exist? */ if (!self->bb_out) { self->bb_out = apr_brigade_create(self->f->r->pool, c->bucket_alloc); } APR_BRIGADE_INSERT_TAIL(self->bb_out, apr_bucket_eos_create(c->bucket_alloc)); if (! self->is_input) { Py_BEGIN_ALLOW_THREADS; self->rc = ap_pass_brigade(self->f->next, self->bb_out); apr_brigade_destroy(self->bb_out); Py_END_ALLOW_THREADS; self->bb_out = NULL; } self->closed = 1; } Py_INCREF(Py_None); return Py_None; }
int h2_h2_process_conn(conn_rec* c) { h2_ctx *ctx = h2_ctx_get(c, 0); if (ctx) { if (h2_ctx_is_task(c)) { // This should not happend, as we install our own filters // in h2_h2_pre_connection in such cases, so the normal // connection hooks get bypassed. return DECLINED; } else if (!h2_ctx_is_negotiated(c)) { // Let the client/server hellos fly and ALPN call us back. apr_bucket_brigade* temp_brigade = apr_brigade_create( c->pool, c->bucket_alloc); ap_get_brigade(c->input_filters, temp_brigade, AP_MODE_SPECULATIVE, APR_BLOCK_READ, 1); apr_brigade_destroy(temp_brigade); } check_sni_host(c); } ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "h2_h2, connection, start"); if (h2_ctx_is_active(c)) { ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "h2_h2, connection, h2 active"); return h2_conn_main(c); } ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "h2_h2, connection, declined"); return DECLINED; }
/* Regression test for PR 34708, where a file bucket will keep * duplicating itself on being read() when EOF is reached * prematurely. */ static void test_truncfile(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_file_t *f = make_test_file(tc, "testfile.txt", "hello"); apr_bucket *e; const char *buf; apr_size_t len; apr_brigade_insert_file(bb, f, 0, 5, p); apr_file_trunc(f, 0); e = APR_BRIGADE_FIRST(bb); ABTS_ASSERT(tc, "single bucket in brigade", APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb)); apr_bucket_file_enable_mmap(e, 0); ABTS_ASSERT(tc, "read gave APR_EOF", apr_bucket_read(e, &buf, &len, APR_BLOCK_READ) == APR_EOF); ABTS_ASSERT(tc, "read length 0", len == 0); ABTS_ASSERT(tc, "still a single bucket in brigade", APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb)); apr_file_close(f); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
MP_INLINE apr_status_t modperl_output_filter_flush(modperl_filter_t *filter) { int add_flush_bucket = FALSE; if (((modperl_filter_ctx_t *)filter->f->ctx)->sent_eos) { /* no data should be sent after EOS has been sent */ return filter->rc; } if (filter->flush) { add_flush_bucket = TRUE; filter->flush = 0; } WBUCKET_INIT(filter); filter->rc = modperl_wbucket_flush(filter->wbucket, add_flush_bucket); if (filter->rc != APR_SUCCESS) { return filter->rc; } if (filter->eos) { filter->rc = send_output_eos(filter->f); if (filter->bb_in) { apr_brigade_destroy(filter->bb_in); filter->bb_in = NULL; } filter->eos = 0; } return filter->rc; }
static void test_partition(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_bucket *e; e = apr_bucket_immortal_create(hello, strlen(hello), ba); APR_BRIGADE_INSERT_HEAD(bb, e); apr_assert_success(tc, "partition brigade", apr_brigade_partition(bb, 5, &e)); test_bucket_content(tc, APR_BRIGADE_FIRST(bb), "hello", 5); test_bucket_content(tc, APR_BRIGADE_LAST(bb), ", world", 7); ABTS_ASSERT(tc, "partition returns APR_INCOMPLETE", apr_brigade_partition(bb, 8192, &e)); ABTS_ASSERT(tc, "APR_INCOMPLETE partition returned sentinel", e == APR_BRIGADE_SENTINEL(bb)); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
apr_status_t h2_from_h1_destroy(h2_from_h1 *from_h1) { if (from_h1->head) { h2_response_destroy(from_h1->head); from_h1->head = NULL; } if (from_h1->tmp) { apr_brigade_destroy(from_h1->tmp); from_h1->tmp = NULL; } if (from_h1->bb) { apr_brigade_destroy(from_h1->bb); from_h1->bb = NULL; } return APR_SUCCESS; }
static int brigade_destory(lua_State*L) { apr_bucket_brigade *bb = (apr_bucket_brigade *)CHECK_BUCKETBRIGADE_OBJECT(1); apr_status_t rc = apr_brigade_destroy(bb); lua_pushinteger(L,rc); return 1; }
static int php_apache_sapi_read_post(char *buf, uint count_bytes) { apr_size_t len; php_struct *ctx = SG(server_context); apr_bucket_brigade *brigade; apr_bucket *partition; brigade = ctx->post_data; len = count_bytes; switch (apr_brigade_partition(ctx->post_data, count_bytes, &partition)) { case APR_SUCCESS: apr_brigade_flatten(ctx->post_data, buf, &len); brigade = apr_brigade_split(ctx->post_data, partition); apr_brigade_destroy(ctx->post_data); ctx->post_data = brigade; break; case APR_INCOMPLETE: apr_brigade_flatten(ctx->post_data, buf, &len); apr_brigade_cleanup(ctx->post_data); break; } return len; }
static void test_manyfile(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_file_t *f; f = make_test_file(tc, "manyfile.bin", "world" "hello" "brave" " ,\n"); apr_brigade_insert_file(bb, f, 5, 5, p); apr_brigade_insert_file(bb, f, 16, 1, p); apr_brigade_insert_file(bb, f, 15, 1, p); apr_brigade_insert_file(bb, f, 10, 5, p); apr_brigade_insert_file(bb, f, 15, 1, p); apr_brigade_insert_file(bb, f, 0, 5, p); apr_brigade_insert_file(bb, f, 17, 1, p); /* can you tell what it is yet? */ flatten_match(tc, "file seek test", bb, "hello, brave world\n"); apr_file_close(f); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
static apr_status_t tmpfile_filter(ap_filter_t *f, apr_bucket_brigade *bbout, ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes) { apr_bucket_brigade* bbin = apr_brigade_create(f->r->pool, f->r->connection->bucket_alloc); apr_file_t* tmpfile ; char* tmpname = apr_pstrdup(f->r->pool, "/tmp/mod-upload.XXXXXX") ; if ( f->ctx ) { APR_BRIGADE_INSERT_TAIL(bbout, apr_bucket_eos_create(bbout->bucket_alloc)) ; return APR_SUCCESS ; } if ( apr_file_mktemp(&tmpfile, tmpname, KEEPONCLOSE, f->r->pool) != APR_SUCCESS ) { // error ap_remove_input_filter(f) ; } apr_pool_cleanup_register(f->r->pool, tmpfile, (void*)apr_file_close, apr_pool_cleanup_null) ; for ( ; ; ) { apr_bucket* b ; const char* ptr = 0 ; apr_size_t bytes ; #ifdef DEBUG ap_log_rerror(APLOG_MARK,APLOG_DEBUG,0, f->r, "get_brigade") ; #endif ap_get_brigade(f->next, bbin, AP_MODE_READBYTES, APR_BLOCK_READ, BUFLEN) ; for ( b = APR_BRIGADE_FIRST(bbin) ; b != APR_BRIGADE_SENTINEL(bbin) && ! f->ctx ; b = APR_BUCKET_NEXT(b) ) { if ( APR_BUCKET_IS_EOS(b) ) { f->ctx = f ; // just using it as a flag; any nonzero will do apr_file_flush(tmpfile) ; apr_brigade_puts(bbout, ap_filter_flush, f, tmpname) ; APR_BRIGADE_INSERT_TAIL(bbout, apr_bucket_eos_create(bbout->bucket_alloc) ) ; } else if ( apr_bucket_read(b, &ptr, &bytes, APR_BLOCK_READ) == APR_SUCCESS ) { #ifdef DEBUG ap_log_rerror(APLOG_MARK,APLOG_DEBUG,0, f->r, " %d bytes in bucket", bytes) ; #endif apr_file_write(tmpfile, ptr, &bytes) ; } } if ( f->ctx ) break ; else apr_brigade_cleanup(bbin) ; } apr_brigade_destroy(bbin) ; return APR_SUCCESS ; }
static void test_insertfile(abts_case *tc, void *ctx) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb; const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242; apr_off_t count; apr_file_t *f; apr_bucket *e; ABTS_ASSERT(tc, "open test file", apr_file_open(&f, TIF_FNAME, APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE | APR_FOPEN_CREATE | APR_FOPEN_SPARSE, APR_OS_DEFAULT, p) == APR_SUCCESS); if (apr_file_trunc(f, bignum)) { apr_file_close(f); apr_file_remove(TIF_FNAME, p); ABTS_NOT_IMPL(tc, "Skipped: could not create large file"); return; } bb = apr_brigade_create(p, ba); e = apr_brigade_insert_file(bb, f, 0, bignum, p); ABTS_ASSERT(tc, "inserted file was not at end of brigade", e == APR_BRIGADE_LAST(bb)); /* check that the total size of inserted buckets is equal to the * total size of the file. */ count = 0; for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); e = APR_BUCKET_NEXT(e)) { ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1); count += e->length; } ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum); apr_brigade_destroy(bb); /* Truncate the file to zero size before close() so that we don't * actually write out the large file if we are on a non-sparse file * system - like Mac OS X's HFS. Otherwise, pity the poor user who * has to wait for the 8GB file to be written to disk. */ apr_file_trunc(f, 0); apr_file_close(f); apr_bucket_alloc_destroy(ba); apr_file_remove(TIF_FNAME, p); }
static void test_splitline(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bin, *bout; bin = make_simple_brigade(ba, "blah blah blah-", "end of line.\nfoo foo foo"); bout = apr_brigade_create(p, ba); apr_assert_success(tc, "split line", apr_brigade_split_line(bout, bin, APR_BLOCK_READ, 100)); flatten_match(tc, "split line", bout, "blah blah blah-end of line.\n"); flatten_match(tc, "remainder", bin, "foo foo foo"); apr_brigade_destroy(bout); apr_brigade_destroy(bin); apr_bucket_alloc_destroy(ba); }
static void test_flatten(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb; bb = make_simple_brigade(ba, "hello, ", "world"); flatten_match(tc, "flatten brigade", bb, "hello, world"); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
static void test_create(abts_case *tc, void *data) { apr_bucket_alloc_t *ba; apr_bucket_brigade *bb; ba = apr_bucket_alloc_create(p); bb = apr_brigade_create(p, ba); ABTS_ASSERT(tc, "new brigade not NULL", bb != NULL); ABTS_ASSERT(tc, "new brigade is empty", APR_BRIGADE_EMPTY(bb)); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
apr_status_t jxr_append_brigade(request_rec *r, apr_bucket_brigade *dest, apr_bucket_brigade *bb, int *eos_seen) { apr_size_t max_msglen = MAX_PACKET_SIZE - sizeof(Jaxer_Header); apr_status_t rv; while (!APR_BRIGADE_EMPTY(bb)) { apr_size_t readlen; const char *buffer; apr_bucket *e = APR_BRIGADE_FIRST(bb); if (APR_BUCKET_IS_EOS(e) ) { apr_bucket_delete(e); if (eos_seen) *eos_seen = 1; continue; } if (APR_BUCKET_IS_METADATA(e)) { apr_bucket_delete(e); continue; } /* Read the bucket now */ if ((rv = apr_bucket_read(e, &buffer, &readlen, APR_BLOCK_READ)) != APR_SUCCESS) { ap_log_perror(APLOG_MARK, APLOG_INFO, rv, r->pool, "mod_jaxer: can't read data from handler"); return rv; } if (readlen > max_msglen) { apr_bucket_split(e, max_msglen); }else { APR_BUCKET_REMOVE(e); APR_BRIGADE_INSERT_TAIL(dest, e); } } if ((rv=apr_brigade_destroy(bb)) != APR_SUCCESS) { ap_log_perror(APLOG_MARK, APLOG_INFO, rv, r->pool, "mod_jaxer: failed to destroy brigade."); return rv; } return APR_SUCCESS; }
static void test_split(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb, *bb2; apr_bucket *e; bb = make_simple_brigade(ba, "hello, ", "world"); /* split at the "world" bucket */ e = APR_BRIGADE_LAST(bb); bb2 = apr_brigade_split(bb, e); ABTS_ASSERT(tc, "split brigade contains one bucket", count_buckets(bb2) == 1); ABTS_ASSERT(tc, "original brigade contains one bucket", count_buckets(bb) == 1); flatten_match(tc, "match original brigade", bb, "hello, "); flatten_match(tc, "match split brigade", bb2, "world"); apr_brigade_destroy(bb2); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
static void php_apache_request_dtor(ap_filter_t *f) { php_apr_bucket_brigade *pbb = (php_apr_bucket_brigade *)f->ctx; php_request_shutdown(NULL); if (SG(request_info).query_string) { free(SG(request_info).query_string); } if (SG(request_info).request_uri) { free(SG(request_info).request_uri); } if (SG(request_info).path_translated) { free(SG(request_info).path_translated); } apr_brigade_destroy(pbb->bb); }
static int ssl_hook_process_connection(conn_rec* c) { SSLConnRec *sslconn = myConnConfig(c); if (sslconn && !sslconn->disabled) { /* On an active SSL connection, let the input filters initialize * themselves which triggers the handshake, which again triggers * all kinds of useful things such as SNI and ALPN. */ apr_bucket_brigade* temp; temp = apr_brigade_create(c->pool, c->bucket_alloc); ap_get_brigade(c->input_filters, temp, AP_MODE_INIT, APR_BLOCK_READ, 0); apr_brigade_destroy(temp); } return DECLINED; }
char* parse_form_from_POST(request_rec *r, int *in_size_) { char *buf; int in_size; apr_status_t rv; apr_bucket_brigade *bbin; apr_size_t bbin_size; const char *clen = apr_table_get(r->headers_in, "Content-Length"); if (clen != NULL) { in_size = strtol(clen, NULL, 0); if (in_size >= WEBGFFARM_MAX_POST_SIZE) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Content-Length too big. Content-Length: %d bytes; limit: %d", in_size, WEBGFFARM_MAX_POST_SIZE); *in_size_ = 0; return NULL; } } else { in_size = WEBGFFARM_MAX_POST_SIZE; } bbin = apr_brigade_create(r->pool, r->connection->bucket_alloc); rv = ap_get_brigade(r->input_filters, bbin, AP_MODE_READBYTES, APR_BLOCK_READ, in_size); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "[parse_form_from_POST] ap_get_brigade returns some error"); return NULL; } bbin_size = in_size; buf = apr_palloc(r->pool, bbin_size); rv = apr_brigade_flatten(bbin, buf, &bbin_size); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "[parse_form_from_POST] apr_brigade_flatten returns some error"); return NULL; } apr_brigade_destroy(bbin); *in_size_ = bbin_size; if (in_size != bbin_size) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "[parse_form_from_POST] in_size is incorrect(in: %d, out:%d)", in_size, (int) bbin_size); } return buf; }
static void test_simple(abts_case *tc, void *data) { apr_bucket_alloc_t *ba; apr_bucket_brigade *bb; apr_bucket *fb, *tb; ba = apr_bucket_alloc_create(p); bb = apr_brigade_create(p, ba); fb = APR_BRIGADE_FIRST(bb); ABTS_ASSERT(tc, "first bucket of empty brigade is sentinel", fb == APR_BRIGADE_SENTINEL(bb)); fb = apr_bucket_flush_create(ba); APR_BRIGADE_INSERT_HEAD(bb, fb); ABTS_ASSERT(tc, "first bucket of brigade is flush", APR_BRIGADE_FIRST(bb) == fb); ABTS_ASSERT(tc, "bucket after flush is sentinel", APR_BUCKET_NEXT(fb) == APR_BRIGADE_SENTINEL(bb)); tb = apr_bucket_transient_create("aaa", 3, ba); APR_BUCKET_INSERT_BEFORE(fb, tb); ABTS_ASSERT(tc, "bucket before flush now transient", APR_BUCKET_PREV(fb) == tb); ABTS_ASSERT(tc, "bucket after transient is flush", APR_BUCKET_NEXT(tb) == fb); ABTS_ASSERT(tc, "bucket before transient is sentinel", APR_BUCKET_PREV(tb) == APR_BRIGADE_SENTINEL(bb)); apr_brigade_cleanup(bb); ABTS_ASSERT(tc, "cleaned up brigade was empty", APR_BRIGADE_EMPTY(bb)); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
// This input filter handles the job of rewriting the request, it's injected at // runtime by the porter fixup filter. All it does is remove itself from the // filter chain and pass the newly modified content up the filter chain. static apr_status_t porter_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) { porter_upload_request_t *ur = f->ctx; if (!ur) { // Because we add ourselves dynamically, this should never occur. // but handle it anyway. return ap_get_brigade(f->next, bb, mode, block, readbytes); } // Remove ourselves so we don't trigger again. ap_remove_input_filter(f); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)) ; APR_BRIGADE_PREPEND(bb, ur->bucket_brigade); apr_brigade_destroy(ur->bucket_brigade); return APR_SUCCESS; }
static void test_bwrite(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_off_t length; int n; for (n = 0; n < COUNT; n++) { apr_assert_success(tc, "brigade_write", apr_brigade_write(bb, NULL, NULL, THESTR, sizeof THESTR)); } apr_assert_success(tc, "determine brigade length", apr_brigade_length(bb, 1, &length)); ABTS_ASSERT(tc, "brigade has correct length", length == (COUNT * sizeof THESTR)); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
static am_status_t get_request_body(am_request_t *rq) { const char *thisfunc = "get_request_body():"; request_rec *r = (request_rec *) (rq != NULL ? rq->ctx : NULL); apr_bucket_brigade *bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); int eos_found = 0, read_bytes = 0; apr_status_t read_status = 0; am_status_t status = AM_ERROR; char *out = NULL; if (r == NULL || rq == NULL) { return AM_EINVAL; } do { apr_bucket *ob; read_status = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN); if (read_status != APR_SUCCESS) { if (out != NULL) free(out); return AM_ERROR; } ob = APR_BRIGADE_FIRST(bb); while (ob != APR_BRIGADE_SENTINEL(bb)) { const char *data; apr_size_t data_size; if (APR_BUCKET_IS_EOS(ob)) { eos_found = 1; break; } if (APR_BUCKET_IS_FLUSH(ob)) { continue; } /* read data */ apr_bucket_read(ob, &data, &data_size, APR_BLOCK_READ); /* process data */ out = realloc(out, read_bytes + data_size + 1); if (out == NULL) { status = AM_ENOMEM; eos_found = 1; break; } memcpy(out + read_bytes, data, data_size); read_bytes += (int) data_size; out[read_bytes] = 0; ob = APR_BUCKET_NEXT(ob); status = AM_SUCCESS; } apr_brigade_destroy(bb); } while (eos_found == 0); apr_brigade_destroy(bb); rq->post_data = out; rq->post_data_sz = read_bytes; if (status == AM_SUCCESS) { am_log_debug(rq->instance_id, "%s read %d bytes \n%s", thisfunc, read_bytes, LOGEMPTY(out)); /* remove the content length since the body has been read */ r->clength = 0; apr_table_unset(r->headers_in, "Content-Length"); } return status; }
AP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc) { apr_xml_parser *parser; apr_bucket_brigade *brigade; int seen_eos; apr_status_t status; char errbuf[200]; apr_size_t total_read = 0; apr_size_t limit_xml_body = ap_get_limit_xml_body(r); int result = HTTP_BAD_REQUEST; parser = apr_xml_parser_create(r->pool); brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc); seen_eos = 0; total_read = 0; do { apr_bucket *bucket; /* read the body, stuffing it into the parser */ status = ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, READ_BLOCKSIZE); if (status != APR_SUCCESS) { goto read_error; } for (bucket = APR_BRIGADE_FIRST(brigade); bucket != APR_BRIGADE_SENTINEL(brigade); bucket = APR_BUCKET_NEXT(bucket)) { const char *data; apr_size_t len; if (APR_BUCKET_IS_EOS(bucket)) { seen_eos = 1; break; } if (APR_BUCKET_IS_METADATA(bucket)) { continue; } status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ); if (status != APR_SUCCESS) { goto read_error; } total_read += len; if (limit_xml_body && total_read > limit_xml_body) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00539) "XML request body is larger than the configured " "limit of %lu", (unsigned long)limit_xml_body); result = HTTP_REQUEST_ENTITY_TOO_LARGE; goto read_error; } status = apr_xml_parser_feed(parser, data, len); if (status) { goto parser_error; } } apr_brigade_cleanup(brigade); } while (!seen_eos); apr_brigade_destroy(brigade); /* tell the parser that we're done */ status = apr_xml_parser_done(parser, pdoc); if (status) { /* Some parsers are stupid and return an error on blank documents. */ if (!total_read) { *pdoc = NULL; return OK; } ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00540) "XML parser error (at end). status=%d", status); return HTTP_BAD_REQUEST; } #if APR_CHARSET_EBCDIC apr_xml_parser_convert_doc(r->pool, *pdoc, ap_hdrs_from_ascii); #endif return OK; parser_error: (void) apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00541) "XML Parser Error: %s", errbuf); /* FALLTHRU */ read_error: /* make sure the parser is terminated */ (void) apr_xml_parser_done(parser, NULL); apr_brigade_destroy(brigade); /* Apache will supply a default error, plus the error log above. */ return result; }
static int process_echo_connection(conn_rec *c) { apr_bucket_brigade *bb; apr_bucket *b; apr_socket_t *csd = NULL; EchoConfig *pConfig = ap_get_module_config(c->base_server->module_config, &echo_module); if (!pConfig->bEnabled) { return DECLINED; } ap_time_process_request(c->sbh, START_PREQUEST); update_echo_child_status(c->sbh, SERVER_BUSY_READ, c, NULL); bb = apr_brigade_create(c->pool, c->bucket_alloc); for ( ; ; ) { apr_status_t rv; /* Get a single line of input from the client */ if (((rv = ap_get_brigade(c->input_filters, bb, AP_MODE_GETLINE, APR_BLOCK_READ, 0)) != APR_SUCCESS)) { apr_brigade_cleanup(bb); if (!APR_STATUS_IS_EOF(rv) && ! APR_STATUS_IS_TIMEUP(rv)) ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01611) "ProtocolEcho: Failure reading from %s", c->client_ip); break; } /* Something horribly wrong happened. Someone didn't block! */ if (APR_BRIGADE_EMPTY(bb)) { apr_brigade_cleanup(bb); ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01612) "ProtocolEcho: Error - read empty brigade from %s!", c->client_ip); break; } if (!csd) { csd = ap_get_conn_socket(c); apr_socket_timeout_set(csd, c->base_server->keep_alive_timeout); } update_echo_child_status(c->sbh, SERVER_BUSY_WRITE, NULL, bb); /* Make sure the data is flushed to the client */ b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); rv = ap_pass_brigade(c->output_filters, bb); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_INFO, rv, c->base_server, APLOGNO(01613) "ProtocolEcho: Failure writing to %s", c->client_ip); break; } apr_brigade_cleanup(bb); /* Announce our intent to loop */ update_echo_child_status(c->sbh, SERVER_BUSY_KEEPALIVE, NULL, NULL); } apr_brigade_destroy(bb); ap_time_process_request(c->sbh, STOP_PREQUEST); update_echo_child_status(c->sbh, SERVER_CLOSING, c, NULL); return OK; }
AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f, apr_bucket_brigade *bb) { request_rec *r = f->r; conn_rec *c = r->connection; apr_bucket *e; apr_bucket_brigade *bsend; apr_bucket_brigade *tmpbb; apr_off_t range_start; apr_off_t range_end; apr_off_t clength = 0; apr_status_t rv; int found = 0; int num_ranges; char *boundary = NULL; char *bound_head = NULL; apr_array_header_t *indexes; indexes_t *idx; int i; int original_status; int max_ranges = get_max_ranges(r); /* * Iterate through the brigade until reaching EOS or a bucket with * unknown length. */ for (e = APR_BRIGADE_FIRST(bb); (e != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(e) && e->length != (apr_size_t)-1); e = APR_BUCKET_NEXT(e)) { clength += e->length; } /* * Don't attempt to do byte range work if this brigade doesn't * contain an EOS, or if any of the buckets has an unknown length; * this avoids the cases where it is expensive to perform * byteranging (i.e. may require arbitrary amounts of memory). */ if (!APR_BUCKET_IS_EOS(e) || clength <= 0) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } original_status = r->status; num_ranges = ap_set_byterange(r, clength, &indexes); /* We have nothing to do, get out of the way. */ if (num_ranges == 0 || (max_ranges >= 0 && num_ranges > max_ranges)) { r->status = original_status; ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } /* this brigade holds what we will be sending */ bsend = apr_brigade_create(r->pool, c->bucket_alloc); if (num_ranges < 0) return send_416(f, bsend); if (num_ranges > 1) { /* Is ap_make_content_type required here? */ const char *orig_ct = ap_make_content_type(r, r->content_type); boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx", (apr_uint64_t)r->request_time, c->id); ap_set_content_type(r, apr_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/", "byteranges; boundary=", boundary, NULL)); if (strcasecmp(orig_ct, NO_CONTENT_TYPE)) { bound_head = apr_pstrcat(r->pool, CRLF "--", boundary, CRLF "Content-type: ", orig_ct, CRLF "Content-range: bytes ", NULL); } else { /* if we have no type for the content, do our best */ bound_head = apr_pstrcat(r->pool, CRLF "--", boundary, CRLF "Content-range: bytes ", NULL); } ap_xlate_proto_to_ascii(bound_head, strlen(bound_head)); } tmpbb = apr_brigade_create(r->pool, c->bucket_alloc); idx = (indexes_t *)indexes->elts; for (i = 0; i < indexes->nelts; i++, idx++) { range_start = idx->start; range_end = idx->end; rv = copy_brigade_range(bb, tmpbb, range_start, range_end); if (rv != APR_SUCCESS ) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "copy_brigade_range() failed [%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT "]", range_start, range_end, clength); continue; } found = 1; /* * For single range requests, we must produce Content-Range header. * Otherwise, we need to produce the multipart boundaries. */ if (num_ranges == 1) { apr_table_setn(r->headers_out, "Content-Range", apr_psprintf(r->pool, "bytes " BYTERANGE_FMT, range_start, range_end, clength)); } else { char *ts; e = apr_bucket_pool_create(bound_head, strlen(bound_head), r->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF, range_start, range_end, clength); ap_xlate_proto_to_ascii(ts, strlen(ts)); e = apr_bucket_pool_create(ts, strlen(ts), r->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); } APR_BRIGADE_CONCAT(bsend, tmpbb); if (i && !(i & 0x1F)) { /* * Every now and then, pass what we have down the filter chain. * In this case, the content-length filter cannot calculate and * set the content length and we must remove any Content-Length * header already present. */ apr_table_unset(r->headers_out, "Content-Length"); if ((rv = ap_pass_brigade(f->next, bsend)) != APR_SUCCESS) return rv; apr_brigade_cleanup(bsend); } } if (found == 0) { /* bsend is assumed to be empty if we get here. */ return send_416(f, bsend); } if (num_ranges > 1) { char *end; /* add the final boundary */ end = apr_pstrcat(r->pool, CRLF "--", boundary, "--" CRLF, NULL); ap_xlate_proto_to_ascii(end, strlen(end)); e = apr_bucket_pool_create(end, strlen(end), r->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); } e = apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bsend, e); /* we're done with the original content - all of our data is in bsend. */ apr_brigade_cleanup(bb); apr_brigade_destroy(tmpbb); /* send our multipart output */ return ap_pass_brigade(f->next, bsend); }
static void test_splits(abts_case *tc, void *ctx) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb; apr_bucket *e; char *str = "alphabeta"; int n; bb = apr_brigade_create(p, ba); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create(str, 9, ba)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_transient_create(str, 9, ba)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_heap_create(strdup(str), 9, free, ba)); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(apr_pstrdup(p, str), 9, p, ba)); ABTS_ASSERT(tc, "four buckets inserted", count_buckets(bb) == 4); /* now split each of the buckets after byte 5 */ for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) { ABTS_ASSERT(tc, "reached end of brigade", e != APR_BRIGADE_SENTINEL(bb)); ABTS_ASSERT(tc, "split bucket OK", apr_bucket_split(e, 5) == APR_SUCCESS); e = APR_BUCKET_NEXT(e); ABTS_ASSERT(tc, "split OK", e != APR_BRIGADE_SENTINEL(bb)); e = APR_BUCKET_NEXT(e); } ABTS_ASSERT(tc, "four buckets split into eight", count_buckets(bb) == 8); for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) { const char *data; apr_size_t len; apr_assert_success(tc, "read alpha from bucket", apr_bucket_read(e, &data, &len, APR_BLOCK_READ)); ABTS_ASSERT(tc, "read 5 bytes", len == 5); ABTS_STR_NEQUAL(tc, "alpha", data, 5); e = APR_BUCKET_NEXT(e); apr_assert_success(tc, "read beta from bucket", apr_bucket_read(e, &data, &len, APR_BLOCK_READ)); ABTS_ASSERT(tc, "read 4 bytes", len == 4); ABTS_STR_NEQUAL(tc, "beta", data, 5); e = APR_BUCKET_NEXT(e); } /* now delete the "alpha" buckets */ for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) { apr_bucket *f; ABTS_ASSERT(tc, "reached end of brigade", e != APR_BRIGADE_SENTINEL(bb)); f = APR_BUCKET_NEXT(e); apr_bucket_delete(e); e = APR_BUCKET_NEXT(f); } ABTS_ASSERT(tc, "eight buckets reduced to four", count_buckets(bb) == 4); flatten_match(tc, "flatten beta brigade", bb, "beta" "beta" "beta" "beta"); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
/* The handler. Create a new parser and/or filter context where appropriate * and parse the chunks of data received from the brigade */ static int idlChunkHandler( ap_filter_t *f, apr_bucket_brigade *brigade ) { idlChunkContext* ctx = f->ctx; apr_bucket* currentBucket = NULL; apr_pool_t* pool = f->r->pool; const char* data; apr_size_t len; osrfStringArray* params = NULL; mparams = NULL; /* load the per-dir/location config */ idlChunkConfig* config = ap_get_module_config( f->r->per_dir_config, &idlchunk_module ); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "IDLCHUNK Config:\nContent Type = %s, " "Strip PI = %s, Strip Comments = %s, Doctype = %s", config->contentType, (config->stripPI) ? "yes" : "no", (config->stripComments) ? "yes" : "no", config->doctype); /* set the content type based on the config */ ap_set_content_type(f->r, config->contentType); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "Set content type"); params = apacheParseParms(f->r); /* free me */ mparams = apacheGetParamValues( params, "class" ); /* free me */ all = 1; if (mparams && mparams->size > 0) all = 0; //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "Parsed the params, if any"); /* create the XML parser */ int firstrun = 0; if( parser == NULL ) { firstrun = 1; parser = XML_ParserCreate("UTF-8"); XML_SetUserData(parser, f); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, charHandler); if(!config->stripDoctype) XML_SetStartDoctypeDeclHandler( parser, doctypeHandler ); if(!config->stripPI) XML_SetProcessingInstructionHandler(parser, handlePI); if(!config->stripComments) XML_SetCommentHandler(parser, handleComment); } /* create the filter context */ if( ctx == NULL ) { f->ctx = ctx = apr_pcalloc( pool, sizeof(*ctx)); ctx->brigade = apr_brigade_create( pool, f->c->bucket_alloc ); ctx->parser = parser; } if(firstrun) { /* we haven't started writing the data to the stream yet */ /* go ahead and write the doctype out if we have one defined */ if(config->doctype) { ap_log_rerror( APLOG_MARK, APLOG_DEBUG, 0, f->r, "IDLCHUNK DOCTYPE => %s", config->doctype); _fwrite(f, "%s\n", config->doctype); } } /* cycle through the buckets in the brigade */ while (!APR_BRIGADE_EMPTY(brigade)) { /* grab the next bucket */ currentBucket = APR_BRIGADE_FIRST(brigade); /* clean up when we're done */ if (APR_BUCKET_IS_EOS(currentBucket) || APR_BUCKET_IS_FLUSH(currentBucket)) { APR_BUCKET_REMOVE(currentBucket); APR_BRIGADE_INSERT_TAIL(ctx->brigade, currentBucket); ap_pass_brigade(f->next, ctx->brigade); XML_ParserFree(parser); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); parser = NULL; return APR_SUCCESS; } /* read the incoming data */ int s = apr_bucket_read(currentBucket, &data, &len, APR_NONBLOCK_READ); if( s != APR_SUCCESS ) { ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, f->r, "IDLCHUNK error reading data from filter with status %d", s); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); return s; } if (len > 0) { ap_log_rerror( APLOG_MARK, APLOG_DEBUG, 0, f->r, "IDLCHUNK read %d bytes", (int)len); /* push data into the XML push parser */ if ( XML_Parse(ctx->parser, data, len, 0) == XML_STATUS_ERROR ) { char tmp[len+1]; memcpy(tmp, data, len); tmp[len] = '\0'; /* log and die on XML errors */ ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, f->r, "IDLCHUNK XML Parse Error: %s at line %d: parsing %s: data %s", XML_ErrorString(XML_GetErrorCode(ctx->parser)), (int) XML_GetCurrentLineNumber(ctx->parser), f->r->filename, tmp); XML_ParserFree(parser); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); parser = NULL; return HTTP_INTERNAL_SERVER_ERROR; } } /* so a subrequest doesn't re-read this bucket */ apr_bucket_delete(currentBucket); } apr_brigade_destroy(brigade); if (params) osrfStringArrayFree(params); if (mparams) osrfStringArrayFree(mparams); return APR_SUCCESS; }