Beispiel #1
0
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);
    }
Beispiel #2
0
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;

}
Beispiel #3
0
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;
    
}
Beispiel #4
0
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;
}
Beispiel #5
0
/* 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);
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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 ;
}
Beispiel #13
0
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);
}
Beispiel #14
0
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);
}
Beispiel #15
0
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);    
}
Beispiel #16
0
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);
}
Beispiel #17
0
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;
}
Beispiel #18
0
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);
}
Beispiel #19
0
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);
}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
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);
}
Beispiel #23
0
// 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;
}
Beispiel #24
0
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);
}
Beispiel #25
0
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;
}
Beispiel #26
0
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;
}
Beispiel #27
0
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);
}
Beispiel #29
0
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);
}
Beispiel #30
0
/* 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;	
}