-: 0:Source:modperl_filter.c -: 0:Object:modperl_filter.bb -: 1:/* Copyright 2001-2004 The Apache Software Foundation -: 2: * -: 3: * Licensed under the Apache License, Version 2.0 (the "License"); -: 4: * you may not use this file except in compliance with the License. -: 5: * You may obtain a copy of the License at -: 6: * -: 7: * http://www.apache.org/licenses/LICENSE-2.0 -: 8: * -: 9: * Unless required by applicable law or agreed to in writing, software -: 10: * distributed under the License is distributed on an "AS IS" BASIS, -: 11: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -: 12: * See the License for the specific language governing permissions and -: 13: * limitations under the License. -: 14: */ -: 15: -: 16:#include "mod_perl.h" -: 17: -: 18:/* helper funcs */ -: 19: -: 20:#define MP_FILTER_NAME_FORMAT " %s\n\n\t" -: 21: -: 22:#define MP_FILTER_NAME(f) \ -: 23: (is_modperl_filter(f) \ -: 24: ? modperl_handler_name(((modperl_filter_ctx_t *)(f)->ctx)->handler) \ -: 25: : (f)->frec->name) -: 26: -: 27:#define MP_FILTER_TYPE(filter) \ -: 28: (is_modperl_filter(filter->f) \ -: 29: ? ((modperl_filter_ctx_t *)(filter)->f->ctx)->handler->attrs & \ -: 30: MP_FILTER_CONNECTION_HANDLER ? "connection" : "request" \ -: 31: : "unknown") -: 32: -: 33:#define MP_FILTER_MODE(filter) \ -: 34: (filter->mode == MP_INPUT_FILTER_MODE ? "input" : "output") -: 35: -: 36:#define MP_FILTER_POOL(f) f->r ? f->r->pool : f->c->pool -: 37: -: 38:/* allocate wbucket memory using malloc and not request pools, since -: 39: * we may need many of these if the filter is invoked multiple -: 40: * times */ -: 41:#define WBUCKET_INIT(wb, p, next_filter) \ -: 42: if (!wb) { \ -: 43: wb = (modperl_wbucket_t *)safemalloc(sizeof(*wb)); \ -: 44: wb->pool = p; \ -: 45: wb->filters = &next_filter; \ -: 46: wb->outcnt = 0; \ -: 47: wb->r = NULL; \ -: 48: wb->header_parse = 0; \ -: 49: } -: 50: -: 51:#define FILTER_FREE(filter) \ -: 52: if (filter->wbucket) { \ -: 53: safefree(filter->wbucket); \ -: 54: } \ -: 55: safefree(filter); -: 56: -: 57:/* this function is for tracing only, it's not optimized for performance */ -: 58:static int is_modperl_filter(ap_filter_t *f) #####: 59:{ #####: 60: const char *name = f->frec->name; -: 61: -: 62: /* frec->name is always lowercased */ #####: 63: if (!strcasecmp(name, MP_FILTER_CONNECTION_INPUT_NAME) || -: 64: !strcasecmp(name, MP_FILTER_CONNECTION_OUTPUT_NAME) || -: 65: !strcasecmp(name, MP_FILTER_REQUEST_INPUT_NAME) || -: 66: !strcasecmp(name, MP_FILTER_REQUEST_OUTPUT_NAME) ) { #####: 67: return 1; -: 68: } -: 69: else { #####: 70: return 0; -: 71: } -: 72:} -: 73: -: 74: -: 75:MP_INLINE static apr_status_t send_input_eos(modperl_filter_t *filter) 8: 76:{ 8: 77: apr_bucket_alloc_t *ba = filter->f->c->bucket_alloc; 8: 78: apr_bucket *b = apr_bucket_eos_create(ba); 8: 79: APR_BRIGADE_INSERT_TAIL(filter->bb_out, b); 8: 80: ((modperl_filter_ctx_t *)filter->f->ctx)->sent_eos = 1; 8: 81: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 82: "write out: EOS bucket\n", MP_FILTER_NAME(filter->f)); 8: 83: return APR_SUCCESS; -: 84:} -: 85: -: 86:MP_INLINE static apr_status_t send_input_flush(modperl_filter_t *filter) #####: 87:{ #####: 88: apr_bucket_alloc_t *ba = filter->f->c->bucket_alloc; #####: 89: apr_bucket *b = apr_bucket_flush_create(ba); #####: 90: APR_BRIGADE_INSERT_TAIL(filter->bb_out, b); #####: 91: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 92: "write out: FLUSH bucket\n", MP_FILTER_NAME(filter->f)); #####: 93: return APR_SUCCESS; -: 94:} -: 95: -: 96:MP_INLINE static apr_status_t send_output_eos(ap_filter_t *f) 18: 97:{ 18: 98: apr_bucket_alloc_t *ba = f->c->bucket_alloc; 18: 99: apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f), 18: 100: ba); 18: 101: apr_bucket *b = apr_bucket_eos_create(ba); 18: 102: APR_BRIGADE_INSERT_TAIL(bb, b); 18: 103: ((modperl_filter_ctx_t *)f->ctx)->sent_eos = 1; 18: 104: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 105: "write out: EOS bucket in separate bb\n", MP_FILTER_NAME(f)); 18: 106: return ap_pass_brigade(f->next, bb); -: 107:} -: 108: -: 109:MP_INLINE static apr_status_t send_output_flush(ap_filter_t *f) 103: 110:{ 103: 111: apr_bucket_alloc_t *ba = f->c->bucket_alloc; 103: 112: apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f), 103: 113: ba); 103: 114: apr_bucket *b = apr_bucket_flush_create(ba); 103: 115: APR_BRIGADE_INSERT_TAIL(bb, b); 103: 116: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 117: "write out: FLUSH bucket in separate bb\n", MP_FILTER_NAME(f)); 103: 118: return ap_pass_brigade(f, bb); -: 119:} -: 120: -: 121:/* simple buffer api */ -: 122: -: 123:MP_INLINE apr_status_t modperl_wbucket_pass(modperl_wbucket_t *wb, -: 124: const char *buf, apr_size_t len, -: 125: int add_flush_bucket) 2665: 126:{ 2665: 127: apr_bucket_alloc_t *ba = (*wb->filters)->c->bucket_alloc; 2665: 128: apr_bucket_brigade *bb; 2665: 129: apr_bucket *bucket; -: 130: -: 131: /* reset the counter to 0 as early as possible and in one place, -: 132: * since this function will always either pass the data out (and -: 133: * it has 'len' already) or return an error. -: 134: */ 2665: 135: wb->outcnt = 0; -: 136: 2665: 137: if (wb->header_parse) { 68: 138: request_rec *r = wb->r; 68: 139: const char *body; 68: 140: int status; -: 141: 68: 142: MP_TRACE_f(MP_FUNC, "\n\n\tparsing headers: %d bytes [%s]\n", len, -: 143: apr_pstrmemdup(wb->pool, buf, len)); -: 144: 68: 145: status = modperl_cgi_header_parse(r, (char *)buf, &len, &body); -: 146: 68: 147: wb->header_parse = 0; /* only once per-request */ -: 148: 68: 149: if (status == HTTP_MOVED_TEMPORARILY) { 3: 150: return APR_SUCCESS; /* XXX: HTTP_MOVED_TEMPORARILY ? */ -: 151: } 65: 152: else if (status != OK) { 1: 153: ap_log_error(APLOG_MARK, APLOG_WARNING, -: 154: 0, r->server, "%s did not send an HTTP header", -: 155: r->uri); 1: 156: r->status = status; -: 157: /* XXX: body == NULL here */ 1: 158: return APR_SUCCESS; -: 159: } 64: 160: else if (!len) { 17: 161: return APR_SUCCESS; -: 162: } -: 163: 47: 164: buf = body; -: 165: } -: 166: 2644: 167: bb = apr_brigade_create(wb->pool, ba); 2644: 168: bucket = apr_bucket_transient_create(buf, len, ba); 2644: 169: APR_BRIGADE_INSERT_TAIL(bb, bucket); -: 170: 2644: 171: if (add_flush_bucket) { -: 172: /* append the flush bucket rather then calling ap_rflush, to -: 173: * prevent a creation of yet another bb, which will cause an -: 174: * extra call for each filter in the chain */ 2413: 175: apr_bucket *bucket = apr_bucket_flush_create(ba); 2413: 176: APR_BRIGADE_INSERT_TAIL(bb, bucket); -: 177: } -: 178: 2644: 179: MP_TRACE_f(MP_FUNC, "\n\n\twrite out: %d bytes\n" -: 180: "\t\tfrom %s\n\t\tto %s filter handler\n", -: 181: len, -: 182: ((wb->r && wb->filters == &wb->r->output_filters) -: 183: ? "response handler" : "current filter handler"), -: 184: MP_FILTER_NAME(*(wb->filters))); -: 185: 2644: 186: return ap_pass_brigade(*(wb->filters), bb); -: 187:} -: 188: -: 189:/* flush data if any, -: 190: * if add_flush_bucket is TRUE -: 191: * if there is data to flush -: 192: * a flush bucket is added to the tail of bb with data -: 193: * else -: 194: * a flush bucket is sent in its own bb -: 195: * else -: 196: * nothing is sent -: 197: */ -: 198:MP_INLINE apr_status_t modperl_wbucket_flush(modperl_wbucket_t *wb, -: 199: int add_flush_bucket) 3434: 200:{ 3434: 201: apr_status_t rv = APR_SUCCESS; -: 202: 3434: 203: if (wb->outcnt) { 2654: 204: rv = modperl_wbucket_pass(wb, wb->outbuf, wb->outcnt, -: 205: add_flush_bucket); -: 206: } 780: 207: else if (add_flush_bucket) { 103: 208: rv = send_output_flush(*(wb->filters)); -: 209: } -: 210: 3434: 211: return rv; -: 212:} -: 213: -: 214:MP_INLINE apr_status_t modperl_wbucket_write(pTHX_ modperl_wbucket_t *wb, -: 215: const char *buf, -: 216: apr_size_t *wlen) 18591: 217:{ 18591: 218: apr_size_t len = *wlen; 18591: 219: *wlen = 0; -: 220: 18591: 221: if ((len + wb->outcnt) > sizeof(wb->outbuf)) { 86: 222: apr_status_t rv; 86: 223: if ((rv = modperl_wbucket_flush(wb, FALSE)) != APR_SUCCESS) { #####: 224: return rv; -: 225: } -: 226: } -: 227: 18591: 228: if (len >= sizeof(wb->outbuf)) { 11: 229: *wlen = len; 11: 230: return modperl_wbucket_pass(wb, buf, len, FALSE); -: 231: } -: 232: else { 18580: 233: memcpy(&wb->outbuf[wb->outcnt], buf, len); 18580: 234: wb->outcnt += len; 18580: 235: *wlen = len; 18580: 236: return APR_SUCCESS; -: 237: } -: 238:} -: 239: -: 240:/* generic filter routines */ -: 241: -: 242:/* all ap_filter_t filter cleanups should go here */ -: 243:static apr_status_t modperl_filter_f_cleanup(void *data) 50: 244:{ 50: 245: ap_filter_t *f = (ap_filter_t *)data; 50: 246: modperl_filter_ctx_t *ctx = (modperl_filter_ctx_t *)(f->ctx); -: 247: -: 248: /* mod_perl filter ctx cleanup */ 50: 249: if (ctx->data){ -: 250:#ifdef USE_ITHREADS 24: 251: dTHXa(ctx->perl); -: 252:#endif 24: 253: if (SvOK(ctx->data) && SvREFCNT(ctx->data)) { 24: 254: SvREFCNT_dec(ctx->data); 24: 255: ctx->data = NULL; -: 256: } 24: 257: ctx->perl = NULL; -: 258: } -: 259: 50: 260: return APR_SUCCESS; -: 261:} -: 262: -: 263:modperl_filter_t *modperl_filter_new(ap_filter_t *f, -: 264: apr_bucket_brigade *bb, -: 265: modperl_filter_mode_e mode, -: 266: ap_input_mode_t input_mode, -: 267: apr_read_type_e block, -: 268: apr_off_t readbytes) 342: 269:{ 342: 270: apr_pool_t *p = MP_FILTER_POOL(f); 342: 271: modperl_filter_t *filter; -: 272: -: 273: /* we can't allocate memory from the pool here, since potentially -: 274: * a filter can be called hundreds of times during the same -: 275: * request/connection resulting in enormous memory demands -: 276: * (sizeof(*filter)*number of invocations) -: 277: */ 342: 278: Newz(0, filter, 1, modperl_filter_t); -: 279: 342: 280: filter->mode = mode; 342: 281: filter->f = f; 342: 282: filter->pool = p; 342: 283: filter->wbucket = NULL; -: 284: 342: 285: if (mode == MP_INPUT_FILTER_MODE) { 144: 286: filter->bb_in = NULL; 144: 287: filter->bb_out = bb; 144: 288: filter->input_mode = input_mode; 144: 289: filter->block = block; 144: 290: filter->readbytes = readbytes; -: 291: } -: 292: else { 198: 293: filter->bb_in = bb; 198: 294: filter->bb_out = NULL; -: 295: } -: 296: 342: 297: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 298: "new: %s %s filter (modperl_filter_t *0x%lx), " -: 299: "f (ap_filter_t *0x%lx)\n", -: 300: MP_FILTER_NAME(f), -: 301: MP_FILTER_TYPE(filter), -: 302: MP_FILTER_MODE(filter), -: 303: (unsigned long)filter, -: 304: (unsigned long)filter->f); -: 305: 342: 306: return filter; -: 307:} -: 308: -: 309:static void modperl_filter_mg_set(pTHX_ SV *obj, modperl_filter_t *filter) 342: 310:{ 342: 311: sv_magic(SvRV(obj), Nullsv, '~', NULL, -1); 342: 312: SvMAGIC(SvRV(obj))->mg_ptr = (char *)filter; -: 313:} -: 314: -: 315:modperl_filter_t *modperl_filter_mg_get(pTHX_ SV *obj) 747: 316:{ 747: 317: MAGIC *mg = mg_find(SvRV(obj), '~'); 747: 318: return mg ? (modperl_filter_t *)mg->mg_ptr : NULL; -: 319:} -: 320: -: 321:/* eval "package Foo; \&init_handler" */ -: 322:int modperl_filter_resolve_init_handler(pTHX_ modperl_handler_t *handler, -: 323: apr_pool_t *p) 12: 324:{ 12: 325: char *init_handler_pv_code = NULL; -: 326: 12: 327: if (handler->mgv_cv) { 12: 328: GV *gv = modperl_mgv_lookup(aTHX_ handler->mgv_cv); 12: 329: if (gv) { 12: 330: CV *cv = modperl_mgv_cv(gv); 12: 331: if (cv && SvMAGICAL(cv)) { 12: 332: MAGIC *mg = mg_find((SV*)(cv), '~'); 12: 333: init_handler_pv_code = mg ? mg->mg_ptr : NULL; -: 334: } -: 335: else { -: 336: /* XXX: should we complain in such a case? */ #####: 337: return 0; -: 338: } -: 339: } -: 340: } -: 341: 12: 342: if (init_handler_pv_code) { 12: 343: char *package_name = 12: 344: modperl_mgv_as_string(aTHX_ handler->mgv_cv, p, 1); -: 345: /* fprintf(stderr, "PACKAGE: %s\n", package_name ); */ -: 346: -: 347: /* eval the code in the parent handler's package's context */ 12: 348: char *code = apr_pstrcat(p, "package ", package_name, ";", 12: 349: init_handler_pv_code, NULL); 12: 350: SV *sv = eval_pv(code, TRUE); -: 351: -: 352: /* fprintf(stderr, "code: %s\n", code); */ 12: 353: modperl_handler_t *init_handler = 12: 354: modperl_handler_new_from_sv(aTHX_ p, sv); -: 355: 12: 356: if (init_handler) { 12: 357: MP_TRACE_h(MP_FUNC, "found init handler %s\n", -: 358: modperl_handler_name(init_handler)); -: 359: 12: 360: if (!init_handler->attrs & MP_FILTER_INIT_HANDLER) { 12: 361: Perl_croak(aTHX_ "handler %s doesn't have " -: 362: "the FilterInitHandler attribute set", -: 363: modperl_handler_name(init_handler)); -: 364: } -: 365: 12: 366: handler->next = init_handler; 12: 367: return 1; -: 368: } -: 369: else { #####: 370: Perl_croak(aTHX_ "failed to eval code: %s", code); -: 371: -: 372: } -: 373: } -: 374: #####: 375: return 1; -: 376:} -: 377: -: 378:static int modperl_run_filter_init(ap_filter_t *f, -: 379: modperl_filter_mode_e mode, -: 380: modperl_handler_t *handler) 3: 381:{ 3: 382: AV *args = Nullav; 3: 383: int status; -: 384: 3: 385: request_rec *r = f->r; 3: 386: conn_rec *c = f->c; 3: 387: server_rec *s = r ? r->server : c->base_server; 3: 388: apr_pool_t *p = r ? r->pool : c->pool; 3: 389: modperl_filter_t *filter = modperl_filter_new(f, NULL, mode, 0, 0, 0); -: 390: 3: 391: MP_dINTERP_SELECT(r, c, s); -: 392: 3: 393: MP_TRACE_h(MP_FUNC, "running filter init handler %s\n", -: 394: modperl_handler_name(handler)); -: 395: 3: 396: modperl_handler_make_args(aTHX_ &args, -: 397: "Apache::Filter", f, -: 398: NULL); -: 399: 3: 400: modperl_filter_mg_set(aTHX_ AvARRAY(args)[0], filter); -: 401: -: 402: /* XXX filter_init return status is propagated back to Apache over -: 403: * in C land, making it possible to use filter_init to return, say, -: 404: * BAD_REQUEST. this implementation, however, ignores the return status -: 405: * even though we're trapping it here - modperl_filter_add_request sees -: 406: * the error and propagates it, but modperl_output_filter_add_request -: 407: * is void so the error is lost */ 3: 408: if ((status = modperl_callback(aTHX_ handler, p, r, s, args)) != OK) { #####: 409: status = modperl_errsv(aTHX_ status, r, s); -: 410: } -: 411: 3: 412: FILTER_FREE(filter); 3: 413: SvREFCNT_dec((SV*)args); -: 414: 3: 415: MP_INTERP_PUTBACK(interp); -: 416: 3: 417: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 418: "return: %d\n", modperl_handler_name(handler), status); -: 419: 3: 420: return status; -: 421:} -: 422: -: 423: -: 424:int modperl_run_filter(modperl_filter_t *filter) 339: 425:{ 339: 426: AV *args = Nullav; 339: 427: int status; 339: 428: modperl_handler_t *handler = 339: 429: ((modperl_filter_ctx_t *)filter->f->ctx)->handler; -: 430: 339: 431: request_rec *r = filter->f->r; 339: 432: conn_rec *c = filter->f->c; 339: 433: server_rec *s = r ? r->server : c->base_server; 339: 434: apr_pool_t *p = r ? r->pool : c->pool; -: 435: 339: 436: MP_dINTERP_SELECT(r, c, s); -: 437: 339: 438: modperl_handler_make_args(aTHX_ &args, -: 439: "Apache::Filter", filter->f, -: 440: "APR::Brigade", -: 441: (filter->mode == MP_INPUT_FILTER_MODE -: 442: ? filter->bb_out -: 443: : filter->bb_in), -: 444: NULL); -: 445: 339: 446: modperl_filter_mg_set(aTHX_ AvARRAY(args)[0], filter); -: 447: 339: 448: if (filter->mode == MP_INPUT_FILTER_MODE) { 142: 449: av_push(args, newSViv(filter->input_mode)); 142: 450: av_push(args, newSViv(filter->block)); 142: 451: av_push(args, newSViv(filter->readbytes)); -: 452: } -: 453: -: 454: /* while filters are VOID handlers, we need to log any errors, -: 455: * because most perl coders will forget to check the return errors -: 456: * from read() and print() calls. and if the caller is not a perl -: 457: * program they won't make any sense of ERRSV or $! -: 458: */ 339: 459: if ((status = modperl_callback(aTHX_ handler, p, r, s, args)) != OK) { 29: 460: status = modperl_errsv(aTHX_ status, r, s); -: 461: } -: 462: 339: 463: SvREFCNT_dec((SV*)args); -: 464: -: 465: /* when the streaming filter is invoked it should be able to send -: 466: * extra data, after the read in a while() loop is finished. -: 467: * Therefore we need to postpone propogating the EOS bucket, up -: 468: * until the filter handler is returned and only then send the EOS -: 469: * bucket if the stream had one. -: 470: */ 339: 471: if (filter->seen_eos) { 26: 472: filter->eos = 1; 26: 473: filter->seen_eos = 0; -: 474: } -: 475: 339: 476: if (filter->mode == MP_INPUT_FILTER_MODE) { 142: 477: if (filter->bb_in) { -: 478: /* in the streaming mode filter->bb_in is populated on the -: 479: * first modperl_input_filter_read, so it must be -: 480: * destroyed at the end of the filter invocation -: 481: */ 20: 482: apr_brigade_destroy(filter->bb_in); 20: 483: filter->bb_in = NULL; -: 484: } 142: 485: MP_FAILURE_CROAK(modperl_input_filter_flush(filter)); -: 486: } -: 487: else { 197: 488: MP_FAILURE_CROAK(modperl_output_filter_flush(filter)); -: 489: } -: 490: 339: 491: MP_INTERP_PUTBACK(interp); -: 492: 339: 493: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 494: "return: %d\n", modperl_handler_name(handler), status); -: 495: 339: 496: return status; -: 497:} -: 498: -: 499: -: 500:/* unrolled APR_BRIGADE_FOREACH loop */ -: 501: -: 502:#define MP_FILTER_EMPTY(filter) \ -: 503:APR_BRIGADE_EMPTY(filter->bb_in) -: 504: -: 505:#define MP_FILTER_SENTINEL(filter) \ -: 506:APR_BRIGADE_SENTINEL(filter->bb_in) -: 507: -: 508:#define MP_FILTER_FIRST(filter) \ -: 509:APR_BRIGADE_FIRST(filter->bb_in) -: 510: -: 511:#define MP_FILTER_NEXT(filter) \ -: 512:APR_BUCKET_NEXT(filter->bucket) -: 513: -: 514:#define MP_FILTER_IS_EOS(filter) \ -: 515:APR_BUCKET_IS_EOS(filter->bucket) -: 516: -: 517:#define MP_FILTER_IS_FLUSH(filter) \ -: 518:APR_BUCKET_IS_FLUSH(filter->bucket) -: 519: -: 520:MP_INLINE static int get_bucket(modperl_filter_t *filter) 378: 521:{ 378: 522: if (!filter->bb_in || MP_FILTER_EMPTY(filter)) { 15: 523: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 524: "read in: bucket brigade is empty\n", -: 525: MP_FILTER_NAME(filter->f)); 15: 526: return 0; -: 527: } -: 528: 363: 529: if (!filter->bucket) { 166: 530: filter->bucket = MP_FILTER_FIRST(filter); -: 531: } 197: 532: else if (filter->bucket != MP_FILTER_SENTINEL(filter)) { 197: 533: filter->bucket = MP_FILTER_NEXT(filter); -: 534: } -: 535: 363: 536: if (filter->bucket == MP_FILTER_SENTINEL(filter)) { 99: 537: filter->bucket = NULL; -: 538: /* can't destroy bb_in since the next read will need a brigade -: 539: * to try to read from */ 99: 540: apr_brigade_cleanup(filter->bb_in); 99: 541: return 0; -: 542: } -: 543: 264: 544: if (MP_FILTER_IS_EOS(filter)) { 25: 545: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 546: "read in: EOS bucket\n", -: 547: MP_FILTER_NAME(filter->f)); -: 548: 25: 549: filter->seen_eos = 1; -: 550: /* there should be only one EOS sent, modperl_filter_read will -: 551: * not come here, since filter->seen_eos is set -: 552: */ 25: 553: return 0; -: 554: } 239: 555: else if (MP_FILTER_IS_FLUSH(filter)) { 122: 556: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 557: "read in: FLUSH bucket\n", -: 558: MP_FILTER_NAME(filter->f)); 122: 559: filter->flush = 1; 122: 560: return 0; -: 561: } -: 562: else { 117: 563: return 1; -: 564: } -: 565:} -: 566: -: 567: -: 568:MP_INLINE static apr_size_t modperl_filter_read(pTHX_ -: 569: modperl_filter_t *filter, -: 570: SV *buffer, -: 571: apr_size_t wanted) 479: 572:{ 479: 573: int num_buckets = 0; 479: 574: apr_size_t len = 0; -: 575: 479: 576: (void)SvUPGRADE(buffer, SVt_PV); 479: 577: SvPOK_only(buffer); 479: 578: SvCUR(buffer) = 0; -: 579: -: 580: /* sometimes the EOS bucket arrives in the same brigade with other -: 581: * buckets, so that particular read() will not return 0 and will -: 582: * be called again if called in the while ($filter->read(...)) -: 583: * loop. In that case we return 0. -: 584: */ 479: 585: if (filter->seen_eos) { 8: 586: return 0; -: 587: } -: 588: -: 589: /*modperl_brigade_dump(filter->bb_in, stderr);*/ -: 590: 471: 591: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 592: "wanted: %d bytes\n", -: 593: MP_FILTER_NAME(filter->f), -: 594: wanted); -: 595: 471: 596: if (filter->remaining) { 203: 597: if (filter->remaining >= wanted) { 161: 598: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 599: "eating and returning %d of " -: 600: "remaining %d leftover bytes\n", -: 601: MP_FILTER_NAME(filter->f), -: 602: wanted, filter->remaining); 161: 603: sv_catpvn(buffer, filter->leftover, wanted); 161: 604: filter->leftover += wanted; 161: 605: filter->remaining -= wanted; 161: 606: return wanted; -: 607: } -: 608: else { 42: 609: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 610: "eating remaining %d leftover bytes\n", -: 611: MP_FILTER_NAME(filter->f), -: 612: filter->remaining); 42: 613: sv_catpvn(buffer, filter->leftover, filter->remaining); 42: 614: len = filter->remaining; 42: 615: filter->remaining = 0; 42: 616: filter->leftover = NULL; -: 617: } -: 618: } -: 619: 378: 620: while (1) { 378: 621: const char *buf; 378: 622: apr_size_t buf_len; -: 623: 378: 624: if (!get_bucket(filter)) { 117: 625: break; -: 626: } -: 627: 117: 628: num_buckets++; -: 629: 117: 630: filter->rc = apr_bucket_read(filter->bucket, &buf, &buf_len, 0); -: 631: 117: 632: if (filter->rc == APR_SUCCESS) { 117: 633: MP_TRACE_f(MP_FUNC, -: 634: MP_FILTER_NAME_FORMAT -: 635: "read in: %s bucket with %d bytes (0x%lx)\n", -: 636: MP_FILTER_NAME(filter->f), -: 637: filter->bucket->type->name, -: 638: buf_len, -: 639: (unsigned long)filter->bucket); -: 640: } -: 641: else { #####: 642: MP_TRACE_f(MP_FUNC, -: 643: MP_FILTER_NAME_FORMAT -: 644: "read in: apr_bucket_read error: %s\n", -: 645: MP_FILTER_NAME(filter->f), -: 646: modperl_apr_strerror(filter->rc)); #####: 647: return len; -: 648: } -: 649: 117: 650: if (buf_len) { 113: 651: if ((SvCUR(buffer) + buf_len) >= wanted) { 49: 652: int nibble = wanted - SvCUR(buffer); 49: 653: sv_catpvn(buffer, buf, nibble); 49: 654: filter->leftover = (char *)buf+nibble; 49: 655: filter->remaining = buf_len - nibble; 49: 656: len += nibble; 49: 657: break; -: 658: } -: 659: else { 64: 660: len += buf_len; 64: 661: sv_catpvn(buffer, buf, buf_len); -: 662: } -: 663: } -: 664: } -: 665: 310: 666: MP_TRACE_f(MP_FUNC, -: 667: MP_FILTER_NAME_FORMAT -: 668: "return: %d bytes from %d bucket%s (%d bytes leftover)\n", -: 669: MP_FILTER_NAME(filter->f), -: 670: len, num_buckets, ((num_buckets == 1) ? "" : "s"), -: 671: filter->remaining); -: 672: 310: 673: return len; -: 674:} -: 675: -: 676:MP_INLINE apr_size_t modperl_input_filter_read(pTHX_ -: 677: modperl_filter_t *filter, -: 678: SV *buffer, -: 679: apr_size_t wanted) 36: 680:{ 36: 681: apr_size_t len = 0; -: 682: 36: 683: if (!filter->bb_in) { -: 684: /* This should be read only once per handler invocation! */ 20: 685: filter->bb_in = apr_brigade_create(filter->pool, -: 686: filter->f->c->bucket_alloc); 20: 687: ap_get_brigade(filter->f->next, filter->bb_in, -: 688: filter->input_mode, filter->block, filter->readbytes); 20: 689: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 690: "retrieving bb: 0x%lx\n", -: 691: MP_FILTER_NAME(filter->f), -: 692: (unsigned long)(filter->bb_in)); -: 693: } -: 694: 36: 695: len = modperl_filter_read(aTHX_ filter, buffer, wanted); -: 696: -: 697:/* if (APR_BRIGADE_EMPTY(filter->bb_in)) { */ -: 698:/* apr_brigade_destroy(filter->bb_in); */ -: 699:/* filter->bb_in = NULL; */ -: 700:/* } */ -: 701: 36: 702: if (filter->flush && len == 0) { -: 703: /* if len > 0 then $filter->write will flush */ #####: 704: modperl_input_filter_flush(filter); -: 705: } -: 706: 36: 707: return len; -: 708:} -: 709: -: 710: -: 711:MP_INLINE apr_size_t modperl_output_filter_read(pTHX_ -: 712: modperl_filter_t *filter, -: 713: SV *buffer, -: 714: apr_size_t wanted) 443: 715:{ 443: 716: apr_size_t len = 0; 443: 717: len = modperl_filter_read(aTHX_ filter, buffer, wanted); -: 718: 443: 719: if (filter->flush && len == 0) { -: 720: /* if len > 0 then $filter->write will flush */ 122: 721: MP_FAILURE_CROAK(modperl_output_filter_flush(filter)); -: 722: } -: 723: 443: 724: return len; -: 725:} -: 726: -: 727: -: 728:MP_INLINE apr_status_t modperl_input_filter_flush(modperl_filter_t *filter) 142: 729:{ 142: 730: if (((modperl_filter_ctx_t *)filter->f->ctx)->sent_eos) { -: 731: /* no data should be sent after EOS has been sent */ #####: 732: return filter->rc; -: 733: } -: 734: 142: 735: if (filter->flush) { #####: 736: filter->rc = send_input_flush(filter); #####: 737: filter->flush = 0; -: 738: } -: 739: 142: 740: if (filter->eos) { 8: 741: filter->rc = send_input_eos(filter); 8: 742: filter->eos = 0; -: 743: } -: 744: 142: 745: return filter->rc; -: 746:} -: 747: -: 748:MP_INLINE apr_status_t modperl_output_filter_flush(modperl_filter_t *filter) 319: 749:{ 319: 750: int add_flush_bucket = FALSE; -: 751: 319: 752: if (((modperl_filter_ctx_t *)filter->f->ctx)->sent_eos) { -: 753: /* no data should be sent after EOS has been sent */ #####: 754: return filter->rc; -: 755: } -: 756: 319: 757: if (filter->flush) { 122: 758: add_flush_bucket = TRUE; 122: 759: filter->flush = 0; -: 760: } -: 761: 319: 762: WBUCKET_INIT(filter->wbucket, filter->pool, filter->f->next); 319: 763: filter->rc = modperl_wbucket_flush(filter->wbucket, add_flush_bucket); 319: 764: if (filter->rc != APR_SUCCESS) { #####: 765: return filter->rc; -: 766: } -: 767: 319: 768: if (filter->eos) { 18: 769: filter->rc = send_output_eos(filter->f); 18: 770: if (filter->bb_in) { 18: 771: apr_brigade_destroy(filter->bb_in); 18: 772: filter->bb_in = NULL; -: 773: } 18: 774: filter->eos = 0; -: 775: } -: 776: 319: 777: return filter->rc; -: 778:} -: 779: -: 780:MP_INLINE apr_status_t modperl_input_filter_write(pTHX_ -: 781: modperl_filter_t *filter, -: 782: const char *buf, -: 783: apr_size_t *len) 20: 784:{ 20: 785: apr_bucket_alloc_t *ba = filter->f->c->bucket_alloc; 20: 786: char *copy = apr_pstrndup(filter->pool, buf, *len); 20: 787: apr_bucket *bucket = apr_bucket_transient_create(copy, *len, ba); -: 788: /* MP_TRACE_f(MP_FUNC, "writing %d bytes: %s\n", *len, copy); */ 20: 789: MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT -: 790: "write out: %d bytes:\n", -: 791: MP_FILTER_NAME(filter->f), -: 792: *len); 20: 793: APR_BRIGADE_INSERT_TAIL(filter->bb_out, bucket); -: 794: /* modperl_brigade_dump(filter->bb_out, stderr); */ 20: 795: return APR_SUCCESS; -: 796:} -: 797: -: 798:MP_INLINE apr_status_t modperl_output_filter_write(pTHX_ -: 799: modperl_filter_t *filter, -: 800: const char *buf, -: 801: apr_size_t *len) 147: 802:{ 147: 803: WBUCKET_INIT(filter->wbucket, filter->pool, filter->f->next); 147: 804: return modperl_wbucket_write(aTHX_ filter->wbucket, buf, len); -: 805:} -: 806: -: 807:apr_status_t modperl_output_filter_handler(ap_filter_t *f, -: 808: apr_bucket_brigade *bb) 197: 809:{ 197: 810: modperl_filter_t *filter; 197: 811: int status; -: 812: 197: 813: if (((modperl_filter_ctx_t *)f->ctx)->sent_eos) { #####: 814: MP_TRACE_f(MP_FUNC, -: 815: MP_FILTER_NAME_FORMAT -: 816: "write_out: EOS was already sent, " -: 817: "passing through the brigade\n", -: 818: MP_FILTER_NAME(f)); #####: 819: return ap_pass_brigade(f->next, bb); -: 820: } -: 821: else { 197: 822: filter = modperl_filter_new(f, bb, MP_OUTPUT_FILTER_MODE, -: 823: 0, 0, 0); 197: 824: status = modperl_run_filter(filter); 197: 825: FILTER_FREE(filter); -: 826: } -: 827: 197: 828: switch (status) { -: 829: case OK: 186: 830: return APR_SUCCESS; -: 831: case DECLINED: 11: 832: return ap_pass_brigade(f->next, bb); -: 833: default: #####: 834: return status; /*XXX*/ -: 835: } -: 836:} -: 837: -: 838:apr_status_t modperl_input_filter_handler(ap_filter_t *f, -: 839: apr_bucket_brigade *bb, -: 840: ap_input_mode_t input_mode, -: 841: apr_read_type_e block, -: 842: apr_off_t readbytes) 147: 843:{ 147: 844: modperl_filter_t *filter; 147: 845: int status; -: 846: 147: 847: if (((modperl_filter_ctx_t *)f->ctx)->sent_eos) { 5: 848: MP_TRACE_f(MP_FUNC, -: 849: MP_FILTER_NAME_FORMAT -: 850: "write out: EOS was already sent, " -: 851: "passing through the brigade\n", -: 852: MP_FILTER_NAME(f)); 5: 853: return ap_get_brigade(f->next, bb, input_mode, block, readbytes); -: 854: } -: 855: else { 142: 856: filter = modperl_filter_new(f, bb, MP_INPUT_FILTER_MODE, -: 857: input_mode, block, readbytes); 142: 858: status = modperl_run_filter(filter); 142: 859: FILTER_FREE(filter); -: 860: } -: 861: 142: 862: switch (status) { -: 863: case OK: 124: 864: return APR_SUCCESS; -: 865: case DECLINED: 12: 866: return ap_get_brigade(f->next, bb, input_mode, block, readbytes); -: 867: default: 6: 868: return status; /*XXX*/ -: 869: } -: 870:} -: 871: -: 872:static int modperl_filter_add_connection(conn_rec *c, -: 873: int idx, -: 874: const char *name, -: 875: modperl_filter_add_t addfunc, -: 876: const char *type) 814: 877:{ 814: 878: modperl_config_dir_t *dcfg = 814: 879: modperl_config_dir_get_defaults(c->base_server); 814: 880: MpAV *av; -: 881: 814: 882: if ((av = dcfg->handlers_per_dir[idx])) { 8: 883: modperl_handler_t **handlers = (modperl_handler_t **)av->elts; 8: 884: int i; 8: 885: ap_filter_t *f; -: 886: 8: 887: for (i=0; inelts; i++) { 8: 888: modperl_filter_ctx_t *ctx; -: 889: 8: 890: if ((handlers[i]->attrs & MP_FILTER_HTTPD_HANDLER)) { #####: 891: addfunc(handlers[i]->name, NULL, NULL, c); #####: 892: MP_TRACE_f(MP_FUNC, -: 893: "a non-mod_perl %s handler %s configured (connection)\n", -: 894: type, handlers[i]->name); #####: 895: continue; -: 896: } -: 897: 8: 898: if (!(handlers[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) { #####: 899: MP_TRACE_f(MP_FUNC, -: 900: "%s is not a FilterConnection handler\n", -: 901: handlers[i]->name); #####: 902: continue; -: 903: } -: 904: 8: 905: ctx = (modperl_filter_ctx_t *)apr_pcalloc(c->pool, sizeof(*ctx)); 8: 906: ctx->handler = handlers[i]; -: 907: 8: 908: f = addfunc(name, (void*)ctx, NULL, c); -: 909: -: 910: /* ap_filter_t filter cleanup */ 8: 911: apr_pool_cleanup_register(c->pool, (void *)f, -: 912: modperl_filter_f_cleanup, -: 913: apr_pool_cleanup_null); -: 914: 8: 915: if (handlers[i]->attrs & MP_FILTER_HAS_INIT_HANDLER && -: 916: handlers[i]->next) { #####: 917: int status = modperl_run_filter_init( -: 918: f, -: 919: (idx == MP_INPUT_FILTER_HANDLER -: 920: ? MP_INPUT_FILTER_MODE : MP_OUTPUT_FILTER_MODE), #####: 921: handlers[i]->next); #####: 922: if (status != OK) { #####: 923: return status; -: 924: } -: 925: } -: 926: 8: 927: MP_TRACE_h(MP_FUNC, "%s handler %s configured (connection)\n", -: 928: type, handlers[i]->name); -: 929: } -: 930: 8: 931: return OK; -: 932: } -: 933: 806: 934: MP_TRACE_h(MP_FUNC, "no %s handlers configured (connection)\n", type); -: 935: 806: 936: return DECLINED; -: 937:} -: 938: -: 939:static int modperl_filter_add_request(request_rec *r, -: 940: int idx, -: 941: const char *name, -: 942: modperl_filter_add_t addfunc, -: 943: const char *type, -: 944: ap_filter_t *filters) 732: 945:{ 732: 946: MP_dDCFG; 732: 947: MpAV *av; -: 948: 732: 949: if ((av = dcfg->handlers_per_dir[idx])) { 43: 950: modperl_handler_t **handlers = (modperl_handler_t **)av->elts; 43: 951: int i; -: 952: 49: 953: for (i=0; inelts; i++) { 54: 954: modperl_filter_ctx_t *ctx; 54: 955: int registered = 0; 54: 956: ap_filter_t *f; -: 957: 54: 958: if ((handlers[i]->attrs & MP_FILTER_HTTPD_HANDLER)) { 6: 959: addfunc(handlers[i]->name, NULL, r, r->connection); 6: 960: MP_TRACE_f(MP_FUNC, -: 961: "a non-mod_perl %s handler %s configured (%s)\n", -: 962: type, handlers[i]->name, r->uri); #####: 963: continue; -: 964: } -: 965: 48: 966: if ((handlers[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) { 11: 967: MP_TRACE_f(MP_FUNC, -: 968: "%s is not a FilterRequest handler\n", -: 969: handlers[i]->name); #####: 970: continue; -: 971: } -: 972: -: 973: /* XXX: I fail to see where this feature is used, since -: 974: * modperl_filter_add_connection doesn't register request -: 975: * filters. may be it'll be still useful when the same -: 976: * filter handler is configured to run more than once? -: 977: * e.g. snooping filter [stas] */ 37: 978: f = filters; 37: 979: while (f) { 37: 980: const char *fname = f->frec->name; -: 981: -: 982: /* XXX: I think this won't work as f->frec->name gets -: 983: * lowercased when added to the chain */ 37: 984: if (*fname == 'M' && strEQ(fname, name)) { #####: 985: modperl_handler_t *ctx_handler = #####: 986: ((modperl_filter_ctx_t *)f->ctx)->handler; -: 987: #####: 988: if (modperl_handler_equal(ctx_handler, handlers[i])) { -: 989: /* skip if modperl_filter_add_connection -: 990: * already registered this handler -: 991: * XXX: set a flag in the modperl_handler_t instead -: 992: */ #####: 993: registered = 1; #####: 994: break; -: 995: } -: 996: } -: 997: 37: 998: f = f->next; -: 999: } -: 1000: 37: 1001: if (registered) { #####: 1002: MP_TRACE_f(MP_FUNC, -: 1003: "%s %s already registered\n", -: 1004: handlers[i]->name, type); #####: 1005: continue; -: 1006: } -: 1007: 37: 1008: ctx = (modperl_filter_ctx_t *)apr_pcalloc(r->pool, sizeof(*ctx)); 37: 1009: ctx->handler = handlers[i]; -: 1010: 37: 1011: f = addfunc(name, (void*)ctx, r, r->connection); -: 1012: -: 1013: /* ap_filter_t filter cleanup */ 37: 1014: apr_pool_cleanup_register(r->pool, (void *)f, -: 1015: modperl_filter_f_cleanup, -: 1016: apr_pool_cleanup_null); -: 1017: 37: 1018: if (handlers[i]->attrs & MP_FILTER_HAS_INIT_HANDLER && -: 1019: handlers[i]->next) { 3: 1020: int status = modperl_run_filter_init( -: 1021: f, -: 1022: (idx == MP_INPUT_FILTER_HANDLER -: 1023: ? MP_INPUT_FILTER_MODE : MP_OUTPUT_FILTER_MODE), 3: 1024: handlers[i]->next); 3: 1025: if (status != OK) { #####: 1026: return status; -: 1027: } -: 1028: } -: 1029: 37: 1030: MP_TRACE_h(MP_FUNC, "%s handler %s configured (%s)\n", -: 1031: type, handlers[i]->name, r->uri); -: 1032: } -: 1033: 43: 1034: return OK; -: 1035: } -: 1036: 689: 1037: MP_TRACE_h(MP_FUNC, "no %s handlers configured (%s)\n", -: 1038: type, r->uri); -: 1039: 689: 1040: return DECLINED; -: 1041:} -: 1042: -: 1043:void modperl_output_filter_add_connection(conn_rec *c) 407: 1044:{ 407: 1045: modperl_filter_add_connection(c, -: 1046: MP_OUTPUT_FILTER_HANDLER, -: 1047: MP_FILTER_CONNECTION_OUTPUT_NAME, -: 1048: ap_add_output_filter, -: 1049: "OutputFilter"); -: 1050:} -: 1051: -: 1052:void modperl_output_filter_add_request(request_rec *r) 366: 1053:{ 366: 1054: modperl_filter_add_request(r, -: 1055: MP_OUTPUT_FILTER_HANDLER, -: 1056: MP_FILTER_REQUEST_OUTPUT_NAME, -: 1057: ap_add_output_filter, -: 1058: "OutputFilter", -: 1059: r->connection->output_filters); -: 1060:} -: 1061: -: 1062:void modperl_input_filter_add_connection(conn_rec *c) 407: 1063:{ 407: 1064: modperl_filter_add_connection(c, -: 1065: MP_INPUT_FILTER_HANDLER, -: 1066: MP_FILTER_CONNECTION_INPUT_NAME, -: 1067: ap_add_input_filter, -: 1068: "InputFilter"); -: 1069:} -: 1070: -: 1071:void modperl_input_filter_add_request(request_rec *r) 366: 1072:{ 366: 1073: modperl_filter_add_request(r, -: 1074: MP_INPUT_FILTER_HANDLER, -: 1075: MP_FILTER_REQUEST_INPUT_NAME, -: 1076: ap_add_input_filter, -: 1077: "InputFilter", -: 1078: r->connection->input_filters); -: 1079:} -: 1080: -: 1081:void modperl_filter_runtime_add(pTHX_ request_rec *r, conn_rec *c, -: 1082: const char *name, -: 1083: modperl_filter_mode_e mode, -: 1084: modperl_filter_add_t addfunc, -: 1085: SV *callback, const char *type) 5: 1086:{ 5: 1087: apr_pool_t *pool = r ? r->pool : c->pool; 5: 1088: modperl_handler_t *handler = 5: 1089: modperl_handler_new_from_sv(aTHX_ pool, callback); -: 1090: 5: 1091: if (handler) { 5: 1092: ap_filter_t *f; 5: 1093: modperl_filter_ctx_t *ctx = 10: 1094: (modperl_filter_ctx_t *)apr_pcalloc(pool, sizeof(*ctx)); -: 1095: 5: 1096: ctx->handler = handler; 5: 1097: f = addfunc(name, (void*)ctx, r, c); -: 1098: -: 1099: /* ap_filter_t filter cleanup */ 5: 1100: apr_pool_cleanup_register(pool, (void *)f, -: 1101: modperl_filter_f_cleanup, -: 1102: apr_pool_cleanup_null); -: 1103: -: 1104: /* has to resolve early so we can check for init functions */ 5: 1105: if (!modperl_mgv_resolve(aTHX_ handler, pool, handler->name, TRUE)) { #####: 1106: Perl_croak(aTHX_ "unable to resolve handler %s\n", -: 1107: modperl_handler_name(handler)); -: 1108: } -: 1109: -: 1110: /* verify that the filter handler is of the right kind */ 5: 1111: if (r == NULL) { -: 1112: /* needs to have the FilterConnectionHandler attribute */ 2: 1113: if (!(handler->attrs & MP_FILTER_CONNECTION_HANDLER)) { #####: 1114: Perl_croak(aTHX_ "Can't add connection filter handler '%s' " -: 1115: "since it doesn't have the " -: 1116: "FilterConnectionHandler attribute set", -: 1117: modperl_handler_name(handler)); -: 1118: } -: 1119: } -: 1120: else { -: 1121: /* needs to have the FilterRequestHandler attribute, but -: 1122: * since by default request filters are not required to -: 1123: * have the FilterRequestHandler attribute, croak only if -: 1124: * some other attribute is set, but not -: 1125: * FilterRequestHandler */ 3: 1126: if (handler->attrs && -: 1127: !(handler->attrs & MP_FILTER_REQUEST_HANDLER)) { #####: 1128: Perl_croak(aTHX_ "Can't add request filter handler '%s' " -: 1129: "since it doesn't have the " -: 1130: "FilterRequestHandler attribute set", -: 1131: modperl_handler_name(handler)); -: 1132: } -: 1133: } -: 1134: 5: 1135: if (handler->attrs & MP_FILTER_HAS_INIT_HANDLER && handler->next) { #####: 1136: int status = modperl_run_filter_init(f, mode, handler->next); #####: 1137: if (status != OK) { -: 1138: /* XXX */ -: 1139: } -: 1140: } -: 1141: 5: 1142: MP_TRACE_h(MP_FUNC, "%s handler %s configured (connection)\n", -: 1143: type, name); -: 1144: #####: 1145: return; -: 1146: } -: 1147: #####: 1148: Perl_croak(aTHX_ "unable to resolve handler 0x%lx\n", -: 1149: (unsigned long)callback); -: 1150:} -: 1151: -: 1152:void modperl_brigade_dump(apr_bucket_brigade *bb, FILE *fp) #####: 1153:{ #####: 1154: apr_bucket *bucket; #####: 1155: int i = 0; -: 1156:#ifndef WIN32 #####: 1157: if (fp == NULL) { #####: 1158: fp = stderr; -: 1159: } -: 1160: #####: 1161: fprintf(fp, "dump of brigade 0x%lx\n", -: 1162: (unsigned long)bb); -: 1163: #####: 1164: for (bucket = APR_BRIGADE_FIRST(bb); -: 1165: bucket != APR_BRIGADE_SENTINEL(bb); -: 1166: bucket = APR_BUCKET_NEXT(bucket)) -: 1167: { #####: 1168: fprintf(fp, " %d: bucket=%s(0x%lx), length=%ld, data=0x%lx\n", -: 1169: i, bucket->type->name, -: 1170: (unsigned long)bucket, -: 1171: (long)bucket->length, -: 1172: (unsigned long)bucket->data); -: 1173: /* fprintf(fp, " : %s\n", (char *)bucket->data); */ -: 1174: #####: 1175: i++; -: 1176: } -: 1177:#endif -: 1178:}