00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "apr.h"
00018 #include "apr_lib.h"
00019 #include "apr_strings.h"
00020 #include "apr_pools.h"
00021 #include "apr_tables.h"
00022 #include "apr_buckets.h"
00023 #include "apr_errno.h"
00024 #define APR_WANT_MEMFUNC
00025 #define APR_WANT_STRFUNC
00026 #include "apr_want.h"
00027
00028 #if APR_HAVE_SYS_UIO_H
00029 #include <sys/uio.h>
00030 #endif
00031
00032 static apr_status_t brigade_cleanup(void *data)
00033 {
00034 return apr_brigade_cleanup(data);
00035 }
00036
00037 APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data)
00038 {
00039 apr_bucket_brigade *b = data;
00040 apr_bucket *e;
00041
00042
00043
00044
00045
00046 while (!APR_BRIGADE_EMPTY(b)) {
00047 e = APR_BRIGADE_FIRST(b);
00048 apr_bucket_delete(e);
00049 }
00050
00051
00052
00053 return APR_SUCCESS;
00054 }
00055
00056 APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b)
00057 {
00058 apr_pool_cleanup_kill(b->p, b, brigade_cleanup);
00059 return apr_brigade_cleanup(b);
00060 }
00061
00062 APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
00063 apr_bucket_alloc_t *list)
00064 {
00065 apr_bucket_brigade *b;
00066
00067 b = apr_palloc(p, sizeof(*b));
00068 b->p = p;
00069 b->bucket_alloc = list;
00070
00071 APR_RING_INIT(&b->list, apr_bucket, link);
00072
00073 apr_pool_cleanup_register(b->p, b, brigade_cleanup, apr_pool_cleanup_null);
00074 return b;
00075 }
00076
00077 APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
00078 apr_bucket *e)
00079 {
00080 apr_bucket_brigade *a;
00081 apr_bucket *f;
00082
00083 a = apr_brigade_create(b->p, b->bucket_alloc);
00084
00085
00086
00087 if (e != APR_BRIGADE_SENTINEL(b)) {
00088 f = APR_RING_LAST(&b->list);
00089 APR_RING_UNSPLICE(e, f, link);
00090 APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
00091 }
00092
00093 APR_BRIGADE_CHECK_CONSISTENCY(a);
00094 APR_BRIGADE_CHECK_CONSISTENCY(b);
00095
00096 return a;
00097 }
00098
00099 APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
00100 apr_off_t point,
00101 apr_bucket **after_point)
00102 {
00103 apr_bucket *e;
00104 const char *s;
00105 apr_size_t len;
00106 apr_status_t rv;
00107
00108 if (point < 0) {
00109
00110 return APR_EINVAL;
00111 }
00112 if (point == 0) {
00113 *after_point = APR_BRIGADE_FIRST(b);
00114 return APR_SUCCESS;
00115 }
00116
00117 APR_BRIGADE_CHECK_CONSISTENCY(b);
00118
00119 APR_BRIGADE_FOREACH(e, b) {
00120 if ((e->length == (apr_size_t)(-1)) && (point > (apr_size_t)(-1))) {
00121
00122
00123 rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
00124 if (rv != APR_SUCCESS) {
00125 *after_point = e;
00126 return rv;
00127 }
00128 }
00129 if ((point < e->length) || (e->length == (apr_size_t)(-1))) {
00130
00131
00132
00133 if ((rv = apr_bucket_split(e, (apr_size_t)point))
00134 != APR_ENOTIMPL) {
00135 *after_point = APR_BUCKET_NEXT(e);
00136 return rv;
00137 }
00138
00139
00140
00141 rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
00142 if (rv != APR_SUCCESS) {
00143 *after_point = e;
00144 return rv;
00145 }
00146
00147
00148
00149
00150 if (point < e->length) {
00151 rv = apr_bucket_split(e, (apr_size_t)point);
00152 *after_point = APR_BUCKET_NEXT(e);
00153 return rv;
00154 }
00155 }
00156 if (point == e->length) {
00157 *after_point = APR_BUCKET_NEXT(e);
00158 return APR_SUCCESS;
00159 }
00160 point -= e->length;
00161 }
00162 *after_point = APR_BRIGADE_SENTINEL(b);
00163 return APR_INCOMPLETE;
00164 }
00165
00166 APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
00167 int read_all, apr_off_t *length)
00168 {
00169 apr_off_t total = 0;
00170 apr_bucket *bkt;
00171
00172 APR_BRIGADE_FOREACH(bkt, bb) {
00173 if (bkt->length == (apr_size_t)(-1)) {
00174 const char *ignore;
00175 apr_size_t len;
00176 apr_status_t status;
00177
00178 if (!read_all) {
00179 *length = -1;
00180 return APR_SUCCESS;
00181 }
00182
00183 if ((status = apr_bucket_read(bkt, &ignore, &len,
00184 APR_BLOCK_READ)) != APR_SUCCESS) {
00185 return status;
00186 }
00187 }
00188
00189 total += bkt->length;
00190 }
00191
00192 *length = total;
00193 return APR_SUCCESS;
00194 }
00195
00196 APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
00197 char *c, apr_size_t *len)
00198 {
00199 apr_size_t actual = 0;
00200 apr_bucket *b;
00201
00202 APR_BRIGADE_FOREACH(b, bb) {
00203 const char *str;
00204 apr_size_t str_len;
00205 apr_status_t status;
00206
00207 status = apr_bucket_read(b, &str, &str_len, APR_BLOCK_READ);
00208 if (status != APR_SUCCESS) {
00209 return status;
00210 }
00211
00212
00213 if (str_len + actual > *len) {
00214 str_len = *len - actual;
00215 }
00216
00217
00218
00219
00220
00221
00222 memcpy(c, str, str_len);
00223
00224 c += str_len;
00225 actual += str_len;
00226
00227
00228
00229 if (actual >= *len) {
00230 break;
00231 }
00232 }
00233
00234 *len = actual;
00235 return APR_SUCCESS;
00236 }
00237
00238 APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
00239 char **c,
00240 apr_size_t *len,
00241 apr_pool_t *pool)
00242 {
00243 apr_off_t actual;
00244 apr_size_t total;
00245 apr_status_t rv;
00246
00247 apr_brigade_length(bb, 1, &actual);
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 total = (apr_size_t)actual;
00261
00262 *c = apr_palloc(pool, total);
00263
00264 rv = apr_brigade_flatten(bb, *c, &total);
00265
00266 if (rv != APR_SUCCESS) {
00267 return rv;
00268 }
00269
00270 *len = total;
00271 return APR_SUCCESS;
00272 }
00273
00274 APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
00275 apr_bucket_brigade *bbIn,
00276 apr_read_type_e block,
00277 apr_off_t maxbytes)
00278 {
00279 apr_off_t readbytes = 0;
00280
00281 while (!APR_BRIGADE_EMPTY(bbIn)) {
00282 const char *pos;
00283 const char *str;
00284 apr_size_t len;
00285 apr_status_t rv;
00286 apr_bucket *e;
00287
00288 e = APR_BRIGADE_FIRST(bbIn);
00289 rv = apr_bucket_read(e, &str, &len, block);
00290
00291 if (rv != APR_SUCCESS) {
00292 return rv;
00293 }
00294
00295 pos = memchr(str, APR_ASCII_LF, len);
00296
00297 if (pos != NULL) {
00298 apr_bucket_split(e, pos - str + 1);
00299 APR_BUCKET_REMOVE(e);
00300 APR_BRIGADE_INSERT_TAIL(bbOut, e);
00301 return APR_SUCCESS;
00302 }
00303 APR_BUCKET_REMOVE(e);
00304 APR_BRIGADE_INSERT_TAIL(bbOut, e);
00305 readbytes += len;
00306
00307 if (readbytes >= maxbytes) {
00308 break;
00309 }
00310 }
00311
00312 return APR_SUCCESS;
00313 }
00314
00315
00316 APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b,
00317 struct iovec *vec, int *nvec)
00318 {
00319 int left = *nvec;
00320 apr_bucket *e;
00321 struct iovec *orig;
00322 apr_size_t iov_len;
00323 apr_status_t rv;
00324
00325 orig = vec;
00326 APR_BRIGADE_FOREACH(e, b) {
00327 if (left-- == 0)
00328 break;
00329
00330 rv = apr_bucket_read(e, (const char **)&vec->iov_base, &iov_len,
00331 APR_NONBLOCK_READ);
00332 if (rv != APR_SUCCESS)
00333 return rv;
00334 vec->iov_len = iov_len;
00335 ++vec;
00336 }
00337
00338 *nvec = vec - orig;
00339 return APR_SUCCESS;
00340 }
00341
00342 APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b,
00343 apr_brigade_flush flush,
00344 void *ctx,
00345 va_list va)
00346 {
00347 for (;;) {
00348 const char *str = va_arg(va, const char *);
00349 apr_status_t rv;
00350
00351 if (str == NULL)
00352 break;
00353
00354 rv = apr_brigade_write(b, flush, ctx, str, strlen(str));
00355 if (rv != APR_SUCCESS)
00356 return rv;
00357 }
00358
00359 return APR_SUCCESS;
00360 }
00361
00362 APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
00363 apr_brigade_flush flush, void *ctx,
00364 const char c)
00365 {
00366 return apr_brigade_write(b, flush, ctx, &c, 1);
00367 }
00368
00369 APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
00370 apr_brigade_flush flush,
00371 void *ctx,
00372 const char *str, apr_size_t nbyte)
00373 {
00374 apr_bucket *e = APR_BRIGADE_LAST(b);
00375 apr_size_t remaining = APR_BUCKET_BUFF_SIZE;
00376 char *buf = NULL;
00377
00378 if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
00379 apr_bucket_heap *h = e->data;
00380
00381
00382 remaining = h->alloc_len - (e->length + (apr_size_t)e->start);
00383 buf = h->base + e->start + e->length;
00384 }
00385
00386 if (nbyte > remaining) {
00387
00388
00389
00390 if (flush) {
00391 e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
00392 APR_BRIGADE_INSERT_TAIL(b, e);
00393 return flush(b, ctx);
00394 }
00395 else {
00396 e = apr_bucket_heap_create(str, nbyte, NULL, b->bucket_alloc);
00397 APR_BRIGADE_INSERT_TAIL(b, e);
00398 return APR_SUCCESS;
00399 }
00400 }
00401 else if (!buf) {
00402
00403
00404 buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
00405 e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
00406 apr_bucket_free, b->bucket_alloc);
00407 APR_BRIGADE_INSERT_TAIL(b, e);
00408 e->length = 0;
00409
00410
00411
00412
00413
00414 }
00415
00416
00417 memcpy(buf, str, nbyte);
00418 e->length += nbyte;
00419
00420 return APR_SUCCESS;
00421 }
00422
00423 APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
00424 apr_brigade_flush flush,
00425 void *ctx,
00426 const struct iovec *vec,
00427 apr_size_t nvec)
00428 {
00429 apr_bucket *e;
00430 apr_size_t total_len;
00431 apr_size_t i;
00432 char *buf;
00433
00434
00435
00436 total_len = 0;
00437 for (i = 0; i < nvec; i++) {
00438 total_len += vec[i].iov_len;
00439 }
00440
00441
00442
00443
00444 if (total_len > APR_BUCKET_BUFF_SIZE) {
00445 if (flush) {
00446 for (i = 0; i < nvec; i++) {
00447 e = apr_bucket_transient_create(vec[i].iov_base,
00448 vec[i].iov_len,
00449 b->bucket_alloc);
00450 APR_BRIGADE_INSERT_TAIL(b, e);
00451 }
00452 return flush(b, ctx);
00453 }
00454 else {
00455 for (i = 0; i < nvec; i++) {
00456 e = apr_bucket_heap_create((const char *) vec[i].iov_base,
00457 vec[i].iov_len, NULL,
00458 b->bucket_alloc);
00459 APR_BRIGADE_INSERT_TAIL(b, e);
00460 }
00461 return APR_SUCCESS;
00462 }
00463 }
00464
00465 i = 0;
00466
00467
00468
00469
00470 e = APR_BRIGADE_LAST(b);
00471 if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
00472 apr_bucket_heap *h = e->data;
00473 apr_size_t remaining = h->alloc_len -
00474 (e->length + (apr_size_t)e->start);
00475 buf = h->base + e->start + e->length;
00476
00477 if (remaining >= total_len) {
00478
00479
00480
00481 for (; i < nvec; i++) {
00482 apr_size_t len = vec[i].iov_len;
00483 memcpy(buf, (const void *) vec[i].iov_base, len);
00484 buf += len;
00485 }
00486 e->length += total_len;
00487 return APR_SUCCESS;
00488 }
00489 else {
00490
00491
00492
00493
00494
00495 const char *start_buf = buf;
00496 for (; i < nvec; i++) {
00497 apr_size_t len = vec[i].iov_len;
00498 if (len > remaining) {
00499 break;
00500 }
00501 memcpy(buf, (const void *) vec[i].iov_base, len);
00502 buf += len;
00503 remaining -= len;
00504 }
00505 e->length += (buf - start_buf);
00506 total_len -= (buf - start_buf);
00507
00508 if (flush) {
00509 apr_status_t rv = flush(b, ctx);
00510 if (rv != APR_SUCCESS) {
00511 return rv;
00512 }
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522 }
00523 }
00524
00525
00526
00527
00528
00529 buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
00530 e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
00531 apr_bucket_free, b->bucket_alloc);
00532 for (; i < nvec; i++) {
00533 apr_size_t len = vec[i].iov_len;
00534 memcpy(buf, (const void *) vec[i].iov_base, len);
00535 buf += len;
00536 }
00537 e->length = total_len;
00538 APR_BRIGADE_INSERT_TAIL(b, e);
00539
00540 return APR_SUCCESS;
00541 }
00542
00543 APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
00544 apr_brigade_flush flush, void *ctx,
00545 const char *str)
00546 {
00547 apr_size_t len = strlen(str);
00548 apr_bucket *bkt = APR_BRIGADE_LAST(bb);
00549 if (!APR_BRIGADE_EMPTY(bb) && APR_BUCKET_IS_HEAP(bkt)) {
00550
00551
00552
00553
00554 apr_bucket_heap *h = bkt->data;
00555 apr_size_t bytes_avail = h->alloc_len - bkt->length;
00556
00557 if (bytes_avail >= len) {
00558 char *buf = h->base + bkt->start + bkt->length;
00559 memcpy(buf, str, len);
00560 bkt->length += len;
00561 return APR_SUCCESS;
00562 }
00563 }
00564
00565
00566
00567
00568
00569 return apr_brigade_write(bb, flush, ctx, str, len);
00570 }
00571
00572 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,
00573 apr_brigade_flush flush,
00574 void *ctx, ...)
00575 {
00576 va_list va;
00577 apr_status_t rv;
00578
00579 va_start(va, ctx);
00580 rv = apr_brigade_vputstrs(b, flush, ctx, va);
00581 va_end(va);
00582 return rv;
00583 }
00584
00585 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b,
00586 apr_brigade_flush flush,
00587 void *ctx,
00588 const char *fmt, ...)
00589 {
00590 va_list ap;
00591 apr_status_t rv;
00592
00593 va_start(ap, fmt);
00594 rv = apr_brigade_vprintf(b, flush, ctx, fmt, ap);
00595 va_end(ap);
00596 return rv;
00597 }
00598
00599 struct brigade_vprintf_data_t {
00600 apr_vformatter_buff_t vbuff;
00601
00602 apr_bucket_brigade *b;
00603 apr_brigade_flush *flusher;
00604 void *ctx;
00605
00606 char *cbuff;
00607 };
00608
00609 static apr_status_t brigade_flush(apr_vformatter_buff_t *buff)
00610 {
00611
00612
00613
00614
00615
00616
00617 struct brigade_vprintf_data_t *vd = (struct brigade_vprintf_data_t*)buff;
00618 apr_status_t res = APR_SUCCESS;
00619
00620 res = apr_brigade_write(vd->b, *vd->flusher, vd->ctx, vd->cbuff,
00621 APR_BUCKET_BUFF_SIZE);
00622
00623 if(res != APR_SUCCESS) {
00624 return -1;
00625 }
00626
00627 vd->vbuff.curpos = vd->cbuff;
00628 vd->vbuff.endpos = vd->cbuff + APR_BUCKET_BUFF_SIZE;
00629
00630 return res;
00631 }
00632
00633 APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
00634 apr_brigade_flush flush,
00635 void *ctx,
00636 const char *fmt, va_list va)
00637 {
00638
00639 struct brigade_vprintf_data_t vd;
00640 char buf[APR_BUCKET_BUFF_SIZE];
00641 apr_size_t written;
00642
00643 vd.vbuff.curpos = buf;
00644 vd.vbuff.endpos = buf + APR_BUCKET_BUFF_SIZE;
00645 vd.b = b;
00646 vd.flusher = &flush;
00647 vd.ctx = ctx;
00648 vd.cbuff = buf;
00649
00650 written = apr_vformatter(brigade_flush, &vd.vbuff, fmt, va);
00651
00652 if (written == -1) {
00653 return -1;
00654 }
00655
00656
00657 *(vd.vbuff.curpos) = '\0';
00658
00659
00660 return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);
00661 }
00662