Mercurial > hg > nginx
comparison src/http/modules/ngx_http_sub_filter_module.c @ 3839:f706037d7f10 stable-0.7
merge r3676:
fix case of partially matched patterns on buffer border in sub_filter
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 14 Dec 2010 19:32:52 +0000 |
parents | 2efa8d2fcde1 |
children |
comparison
equal
deleted
inserted
replaced
3838:c93b1c05436c | 3839:f706037d7f10 |
---|---|
27 } ngx_http_sub_state_e; | 27 } ngx_http_sub_state_e; |
28 | 28 |
29 | 29 |
30 typedef struct { | 30 typedef struct { |
31 ngx_str_t match; | 31 ngx_str_t match; |
32 ngx_str_t saved; | |
33 ngx_str_t looked; | |
32 | 34 |
33 ngx_uint_t once; /* unsigned once:1 */ | 35 ngx_uint_t once; /* unsigned once:1 */ |
34 | 36 |
35 ngx_buf_t *buf; | 37 ngx_buf_t *buf; |
36 | 38 |
45 ngx_chain_t *free; | 47 ngx_chain_t *free; |
46 | 48 |
47 ngx_str_t sub; | 49 ngx_str_t sub; |
48 | 50 |
49 ngx_uint_t state; | 51 ngx_uint_t state; |
50 size_t saved; | |
51 size_t looked; | |
52 } ngx_http_sub_ctx_t; | 52 } ngx_http_sub_ctx_t; |
53 | 53 |
54 | 54 |
55 static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, | 55 static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, |
56 ngx_http_sub_ctx_t *ctx); | 56 ngx_http_sub_ctx_t *ctx); |
145 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_ctx_t)); | 145 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_ctx_t)); |
146 if (ctx == NULL) { | 146 if (ctx == NULL) { |
147 return NGX_ERROR; | 147 return NGX_ERROR; |
148 } | 148 } |
149 | 149 |
150 ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len); | |
151 if (ctx->saved.data == NULL) { | |
152 return NGX_ERROR; | |
153 } | |
154 | |
155 ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len); | |
156 if (ctx->looked.data == NULL) { | |
157 return NGX_ERROR; | |
158 } | |
159 | |
150 ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); | 160 ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); |
151 | 161 |
152 ctx->match = slcf->match; | 162 ctx->match = slcf->match; |
153 ctx->last_out = &ctx->out; | 163 ctx->last_out = &ctx->out; |
154 | 164 |
224 b = NULL; | 234 b = NULL; |
225 | 235 |
226 while (ctx->pos < ctx->buf->last) { | 236 while (ctx->pos < ctx->buf->last) { |
227 | 237 |
228 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 238 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
229 "saved: %d state: %d", ctx->saved, ctx->state); | 239 "saved: \"%V\" state: %d", &ctx->saved, ctx->state); |
230 | 240 |
231 rc = ngx_http_sub_parse(r, ctx); | 241 rc = ngx_http_sub_parse(r, ctx); |
232 | 242 |
233 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 243 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
234 "parse: %d, looked: %d %p-%p", | 244 "parse: %d, looked: \"%V\" %p-%p", |
235 rc, ctx->looked, ctx->copy_start, ctx->copy_end); | 245 rc, &ctx->looked, ctx->copy_start, ctx->copy_end); |
236 | 246 |
237 if (rc == NGX_ERROR) { | 247 if (rc == NGX_ERROR) { |
238 return rc; | 248 return rc; |
239 } | 249 } |
240 | 250 |
241 if (ctx->copy_start != ctx->copy_end) { | 251 if (ctx->copy_start != ctx->copy_end) { |
242 | 252 |
243 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 253 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
244 "saved: %d", ctx->saved); | 254 "saved: \"%V\"", &ctx->saved); |
245 | 255 |
246 if (ctx->saved) { | 256 if (ctx->saved.len) { |
247 | 257 |
248 if (ctx->free) { | 258 if (ctx->free) { |
249 cl = ctx->free; | 259 cl = ctx->free; |
250 ctx->free = ctx->free->next; | 260 ctx->free = ctx->free->next; |
251 b = cl->buf; | 261 b = cl->buf; |
263 } | 273 } |
264 | 274 |
265 cl->buf = b; | 275 cl->buf = b; |
266 } | 276 } |
267 | 277 |
278 b->pos = ngx_pnalloc(r->pool, ctx->saved.len); | |
279 if (b->pos == NULL) { | |
280 return NGX_ERROR; | |
281 } | |
282 | |
283 ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len); | |
284 b->last = b->pos + ctx->saved.len; | |
268 b->memory = 1; | 285 b->memory = 1; |
269 b->pos = ctx->match.data; | |
270 b->last = ctx->match.data + ctx->saved; | |
271 | 286 |
272 *ctx->last_out = cl; | 287 *ctx->last_out = cl; |
273 ctx->last_out = &cl->next; | 288 ctx->last_out = &cl->next; |
274 | 289 |
275 ctx->saved = 0; | 290 ctx->saved.len = 0; |
276 } | 291 } |
277 | 292 |
278 if (ctx->free) { | 293 if (ctx->free) { |
279 cl = ctx->free; | 294 cl = ctx->free; |
280 ctx->free = ctx->free->next; | 295 ctx->free = ctx->free->next; |
403 b->recycled = ctx->buf->recycled; | 418 b->recycled = ctx->buf->recycled; |
404 } | 419 } |
405 | 420 |
406 ctx->buf = NULL; | 421 ctx->buf = NULL; |
407 | 422 |
408 ctx->saved = ctx->looked; | 423 ctx->saved.len = ctx->looked.len; |
424 ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len); | |
409 } | 425 } |
410 | 426 |
411 if (ctx->out == NULL && ctx->busy == NULL) { | 427 if (ctx->out == NULL && ctx->busy == NULL) { |
412 return NGX_OK; | 428 return NGX_OK; |
413 } | 429 } |
494 | 510 |
495 if (ctx->once) { | 511 if (ctx->once) { |
496 ctx->copy_start = ctx->pos; | 512 ctx->copy_start = ctx->pos; |
497 ctx->copy_end = ctx->buf->last; | 513 ctx->copy_end = ctx->buf->last; |
498 ctx->pos = ctx->buf->last; | 514 ctx->pos = ctx->buf->last; |
499 ctx->looked = 0; | 515 ctx->looked.len = 0; |
500 | 516 |
501 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once"); | 517 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once"); |
502 | 518 |
503 return NGX_AGAIN; | 519 return NGX_AGAIN; |
504 } | 520 } |
505 | 521 |
506 state = ctx->state; | 522 state = ctx->state; |
507 looked = ctx->looked; | 523 looked = ctx->looked.len; |
508 last = ctx->buf->last; | 524 last = ctx->buf->last; |
509 copy_end = ctx->copy_end; | 525 copy_end = ctx->copy_end; |
510 | 526 |
511 for (p = ctx->pos; p < last; p++) { | 527 for (p = ctx->pos; p < last; p++) { |
512 | 528 |
520 match = ctx->match.data[0]; | 536 match = ctx->match.data[0]; |
521 | 537 |
522 for ( ;; ) { | 538 for ( ;; ) { |
523 if (ch == match) { | 539 if (ch == match) { |
524 copy_end = p; | 540 copy_end = p; |
541 ctx->looked.data[0] = *p; | |
525 looked = 1; | 542 looked = 1; |
526 state = sub_match_state; | 543 state = sub_match_state; |
527 | 544 |
528 goto match_started; | 545 goto match_started; |
529 } | 546 } |
536 ch = ngx_tolower(ch); | 553 ch = ngx_tolower(ch); |
537 } | 554 } |
538 | 555 |
539 ctx->state = state; | 556 ctx->state = state; |
540 ctx->pos = p; | 557 ctx->pos = p; |
541 ctx->looked = looked; | 558 ctx->looked.len = looked; |
542 ctx->copy_end = p; | 559 ctx->copy_end = p; |
543 | 560 |
544 if (ctx->copy_start == NULL) { | 561 if (ctx->copy_start == NULL) { |
545 ctx->copy_start = ctx->buf->pos; | 562 ctx->copy_start = ctx->buf->pos; |
546 } | 563 } |
553 } | 570 } |
554 | 571 |
555 /* state == sub_match_state */ | 572 /* state == sub_match_state */ |
556 | 573 |
557 if (ch == ctx->match.data[looked]) { | 574 if (ch == ctx->match.data[looked]) { |
575 ctx->looked.data[looked] = *p; | |
558 looked++; | 576 looked++; |
559 | 577 |
560 if (looked == ctx->match.len) { | 578 if (looked == ctx->match.len) { |
561 if ((size_t) (p - ctx->pos) < looked) { | 579 if ((size_t) (p - ctx->pos) < looked) { |
562 ctx->saved = 0; | 580 ctx->saved.len = 0; |
563 } | 581 } |
564 | 582 |
565 ctx->state = sub_start_state; | 583 ctx->state = sub_start_state; |
566 ctx->pos = p + 1; | 584 ctx->pos = p + 1; |
567 ctx->looked = 0; | 585 ctx->looked.len = 0; |
568 ctx->copy_end = copy_end; | 586 ctx->copy_end = copy_end; |
569 | 587 |
570 if (ctx->copy_start == NULL && copy_end) { | 588 if (ctx->copy_start == NULL && copy_end) { |
571 ctx->copy_start = ctx->buf->pos; | 589 ctx->copy_start = ctx->buf->pos; |
572 } | 590 } |
574 return NGX_OK; | 592 return NGX_OK; |
575 } | 593 } |
576 | 594 |
577 } else if (ch == ctx->match.data[0]) { | 595 } else if (ch == ctx->match.data[0]) { |
578 copy_end = p; | 596 copy_end = p; |
597 ctx->looked.data[0] = *p; | |
579 looked = 1; | 598 looked = 1; |
580 | 599 |
581 } else { | 600 } else { |
582 copy_end = p; | 601 copy_end = p; |
583 looked = 0; | 602 looked = 0; |
585 } | 604 } |
586 } | 605 } |
587 | 606 |
588 ctx->state = state; | 607 ctx->state = state; |
589 ctx->pos = p; | 608 ctx->pos = p; |
590 ctx->looked = looked; | 609 ctx->looked.len = looked; |
591 | 610 |
592 ctx->copy_end = (state == sub_start_state) ? p : copy_end; | 611 ctx->copy_end = (state == sub_start_state) ? p : copy_end; |
593 | 612 |
594 if (ctx->copy_start == NULL && ctx->copy_end) { | 613 if (ctx->copy_start == NULL && ctx->copy_end) { |
595 ctx->copy_start = ctx->buf->pos; | 614 ctx->copy_start = ctx->buf->pos; |