~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/http/modules/ngx_http_sub_filter_module.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
10
11
 
11
12
 
12
13
typedef struct {
13
 
    ngx_str_t      match;
14
 
    ngx_str_t      sub;
15
 
 
16
 
    ngx_array_t   *types;     /* array of ngx_str_t */
17
 
 
18
 
    ngx_array_t   *sub_lengths;
19
 
    ngx_array_t   *sub_values;
20
 
 
21
 
    ngx_flag_t     once;
 
14
    ngx_str_t                  match;
 
15
    ngx_http_complex_value_t   value;
 
16
 
 
17
    ngx_hash_t                 types;
 
18
 
 
19
    ngx_flag_t                 once;
 
20
 
 
21
    ngx_array_t               *types_keys;
22
22
} ngx_http_sub_loc_conf_t;
23
23
 
24
24
 
29
29
 
30
30
 
31
31
typedef struct {
32
 
    ngx_str_t      match;
33
 
 
34
 
    ngx_uint_t     once;   /* unsigned  once:1 */
35
 
 
36
 
    ngx_buf_t     *buf;
37
 
 
38
 
    u_char        *pos;
39
 
    u_char        *copy_start;
40
 
    u_char        *copy_end;
41
 
 
42
 
    ngx_chain_t   *in;
43
 
    ngx_chain_t   *out;
44
 
    ngx_chain_t  **last_out;
45
 
    ngx_chain_t   *busy;
46
 
    ngx_chain_t   *free;
47
 
 
48
 
    ngx_str_t      sub;
49
 
 
50
 
    ngx_uint_t     state;
51
 
    size_t         saved;
52
 
    size_t         looked;
 
32
    ngx_str_t                  match;
 
33
    ngx_str_t                  saved;
 
34
    ngx_str_t                  looked;
 
35
 
 
36
    ngx_uint_t                 once;   /* unsigned  once:1 */
 
37
 
 
38
    ngx_buf_t                 *buf;
 
39
 
 
40
    u_char                    *pos;
 
41
    u_char                    *copy_start;
 
42
    u_char                    *copy_end;
 
43
 
 
44
    ngx_chain_t               *in;
 
45
    ngx_chain_t               *out;
 
46
    ngx_chain_t              **last_out;
 
47
    ngx_chain_t               *busy;
 
48
    ngx_chain_t               *free;
 
49
 
 
50
    ngx_str_t                  sub;
 
51
 
 
52
    ngx_uint_t                 state;
53
53
} ngx_http_sub_ctx_t;
54
54
 
55
55
 
60
60
 
61
61
static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd,
62
62
    void *conf);
63
 
static char *ngx_http_sub_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
64
63
static void *ngx_http_sub_create_conf(ngx_conf_t *cf);
65
64
static char *ngx_http_sub_merge_conf(ngx_conf_t *cf,
66
65
    void *parent, void *child);
78
77
 
79
78
    { ngx_string("sub_filter_types"),
80
79
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
81
 
      ngx_http_sub_types,
 
80
      ngx_http_types_slot,
82
81
      NGX_HTTP_LOC_CONF_OFFSET,
83
 
      0,
84
 
      NULL },
 
82
      offsetof(ngx_http_sub_loc_conf_t, types_keys),
 
83
      &ngx_http_html_default_types[0] },
85
84
 
86
85
    { ngx_string("sub_filter_once"),
87
86
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
132
131
static ngx_int_t
133
132
ngx_http_sub_header_filter(ngx_http_request_t *r)
134
133
{
135
 
    ngx_str_t                *type;
136
 
    ngx_uint_t                i;
137
134
    ngx_http_sub_ctx_t        *ctx;
138
135
    ngx_http_sub_loc_conf_t  *slcf;
139
136
 
140
137
    slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
141
138
 
142
139
    if (slcf->match.len == 0
143
 
        || r->headers_out.content_type.len == 0
144
 
        || r->headers_out.content_length_n == 0)
 
140
        || r->headers_out.content_length_n == 0
 
141
        || ngx_http_test_content_type(r, &slcf->types) == NULL)
145
142
    {
146
143
        return ngx_http_next_header_filter(r);
147
144
    }
148
145
 
149
 
    type = slcf->types->elts;
150
 
    for (i = 0; i < slcf->types->nelts; i++) {
151
 
        if (r->headers_out.content_type.len >= type[i].len
152
 
            && ngx_strncasecmp(r->headers_out.content_type.data,
153
 
                               type[i].data, type[i].len) == 0)
154
 
        {
155
 
            goto found;
156
 
        }
157
 
    }
158
 
 
159
 
    return ngx_http_next_header_filter(r);
160
 
 
161
 
found:
162
 
 
163
146
    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_ctx_t));
164
147
    if (ctx == NULL) {
165
148
        return NGX_ERROR;
166
149
    }
167
150
 
 
151
    ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len);
 
152
    if (ctx->saved.data == NULL) {
 
153
        return NGX_ERROR;
 
154
    }
 
155
 
 
156
    ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len);
 
157
    if (ctx->looked.data == NULL) {
 
158
        return NGX_ERROR;
 
159
    }
 
160
 
168
161
    ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
169
162
 
170
163
    ctx->match = slcf->match;
171
164
    ctx->last_out = &ctx->out;
172
 
    ctx->sub = slcf->sub;
173
165
 
174
166
    r->filter_need_in_memory = 1;
175
167
 
176
168
    if (r == r->main) {
177
169
        ngx_http_clear_content_length(r);
178
170
        ngx_http_clear_last_modified(r);
 
171
        ngx_http_clear_etag(r);
179
172
    }
180
173
 
181
174
    return ngx_http_next_header_filter(r);
219
212
    /* add the incoming chain to the chain ctx->in */
220
213
 
221
214
    if (in) {
222
 
        if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
 
215
        if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
223
216
            return NGX_ERROR;
224
217
        }
225
218
    }
229
222
 
230
223
    while (ctx->in || ctx->buf) {
231
224
 
232
 
        if (ctx->buf == NULL ){
 
225
        if (ctx->buf == NULL) {
233
226
            ctx->buf = ctx->in->buf;
234
227
            ctx->in = ctx->in->next;
235
228
            ctx->pos = ctx->buf->pos;
245
238
        while (ctx->pos < ctx->buf->last) {
246
239
 
247
240
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
248
 
                           "saved: %d state: %d", ctx->saved, ctx->state);
 
241
                           "saved: \"%V\" state: %d", &ctx->saved, ctx->state);
249
242
 
250
243
            rc = ngx_http_sub_parse(r, ctx);
251
244
 
252
245
            ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
253
 
                           "parse: %d, looked: %d %p-%p",
254
 
                           rc, ctx->looked, ctx->copy_start, ctx->copy_end);
 
246
                           "parse: %d, looked: \"%V\" %p-%p",
 
247
                           rc, &ctx->looked, ctx->copy_start, ctx->copy_end);
255
248
 
256
249
            if (rc == NGX_ERROR) {
257
250
                return rc;
260
253
            if (ctx->copy_start != ctx->copy_end) {
261
254
 
262
255
                ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
263
 
                               "saved: %d", ctx->saved);
 
256
                               "saved: \"%V\"", &ctx->saved);
264
257
 
265
 
                if (ctx->saved) {
 
258
                if (ctx->saved.len) {
266
259
 
267
260
                    if (ctx->free) {
268
261
                        cl = ctx->free;
284
277
                        cl->buf = b;
285
278
                    }
286
279
 
 
280
                    b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
 
281
                    if (b->pos == NULL) {
 
282
                        return NGX_ERROR;
 
283
                    }
 
284
 
 
285
                    ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
 
286
                    b->last = b->pos + ctx->saved.len;
287
287
                    b->memory = 1;
288
 
                    b->pos = ctx->match.data;
289
 
                    b->last = ctx->match.data + ctx->saved;
290
288
 
291
289
                    *ctx->last_out = cl;
292
290
                    ctx->last_out = &cl->next;
293
291
 
294
 
                    ctx->saved = 0;
 
292
                    ctx->saved.len = 0;
295
293
                }
296
294
 
297
295
                if (ctx->free) {
361
359
 
362
360
            if (ctx->sub.data == NULL) {
363
361
 
364
 
                if (ngx_http_script_run(r, &ctx->sub, slcf->sub_lengths->elts,
365
 
                                        0, slcf->sub_values->elts)
366
 
                    == NULL)
 
362
                if (ngx_http_complex_value(r, &slcf->value, &ctx->sub)
 
363
                    != NGX_OK)
367
364
                {
368
365
                    return NGX_ERROR;
369
366
                }
425
422
 
426
423
        ctx->buf = NULL;
427
424
 
428
 
        ctx->saved = ctx->looked;
 
425
        ctx->saved.len = ctx->looked.len;
 
426
        ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len);
429
427
    }
430
428
 
431
429
    if (ctx->out == NULL && ctx->busy == NULL) {
480
478
            break;
481
479
        }
482
480
 
483
 
#if (NGX_HAVE_WRITE_ZEROCOPY)
484
 
        if (b->zerocopy_busy) {
485
 
            break;
486
 
        }
487
 
#endif
488
 
 
489
481
        if (b->shadow) {
490
482
            b->shadow->pos = b->shadow->last;
491
483
        }
522
514
        ctx->copy_start = ctx->pos;
523
515
        ctx->copy_end = ctx->buf->last;
524
516
        ctx->pos = ctx->buf->last;
525
 
        ctx->looked = 0;
 
517
        ctx->looked.len = 0;
526
518
 
527
519
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once");
528
520
 
530
522
    }
531
523
 
532
524
    state = ctx->state;
533
 
    looked = ctx->looked;
 
525
    looked = ctx->looked.len;
534
526
    last = ctx->buf->last;
535
527
    copy_end = ctx->copy_end;
536
528
 
548
540
            for ( ;; ) {
549
541
                if (ch == match) {
550
542
                    copy_end = p;
 
543
                    ctx->looked.data[0] = *p;
551
544
                    looked = 1;
552
545
                    state = sub_match_state;
553
546
 
564
557
 
565
558
            ctx->state = state;
566
559
            ctx->pos = p;
567
 
            ctx->looked = looked;
 
560
            ctx->looked.len = looked;
568
561
            ctx->copy_end = p;
569
562
 
570
563
            if (ctx->copy_start == NULL) {
581
574
        /* state == sub_match_state */
582
575
 
583
576
        if (ch == ctx->match.data[looked]) {
 
577
            ctx->looked.data[looked] = *p;
584
578
            looked++;
585
579
 
586
580
            if (looked == ctx->match.len) {
587
581
                if ((size_t) (p - ctx->pos) < looked) {
588
 
                    ctx->saved = 0;
 
582
                    ctx->saved.len = 0;
589
583
                }
590
584
 
591
585
                ctx->state = sub_start_state;
592
586
                ctx->pos = p + 1;
593
 
                ctx->looked = 0;
 
587
                ctx->looked.len = 0;
594
588
                ctx->copy_end = copy_end;
595
589
 
596
590
                if (ctx->copy_start == NULL && copy_end) {
602
596
 
603
597
        } else if (ch == ctx->match.data[0]) {
604
598
            copy_end = p;
 
599
            ctx->looked.data[0] = *p;
605
600
            looked = 1;
606
601
 
607
602
        } else {
613
608
 
614
609
    ctx->state = state;
615
610
    ctx->pos = p;
616
 
    ctx->looked = looked;
 
611
    ctx->looked.len = looked;
617
612
 
618
613
    ctx->copy_end = (state == sub_start_state) ? p : copy_end;
619
614
 
630
625
{
631
626
    ngx_http_sub_loc_conf_t *slcf = conf;
632
627
 
633
 
    ngx_str_t                  *value;
634
 
    ngx_int_t                   n;
635
 
    ngx_uint_t                  i;
636
 
    ngx_http_script_compile_t   sc;
 
628
    ngx_str_t                         *value;
 
629
    ngx_http_compile_complex_value_t   ccv;
637
630
 
638
 
    if (slcf->match.len) {
 
631
    if (slcf->match.data) {
639
632
        return "is duplicate";
640
633
    }
641
634
 
642
635
    value = cf->args->elts;
643
636
 
 
637
    ngx_strlow(value[1].data, value[1].data, value[1].len);
 
638
 
644
639
    slcf->match = value[1];
645
640
 
646
 
    for (i = 0; i < value[1].len; i++) {
647
 
        value[1].data[i] = ngx_tolower(value[1].data[i]);
648
 
    }
649
 
 
650
 
    n = ngx_http_script_variables_count(&value[2]);
651
 
 
652
 
    if (n == 0) {
653
 
        slcf->sub = value[2];
654
 
        return NGX_CONF_OK;
655
 
    }
656
 
 
657
 
    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
658
 
 
659
 
    sc.cf = cf;
660
 
    sc.source = &value[2];
661
 
    sc.lengths = &slcf->sub_lengths;
662
 
    sc.values = &slcf->sub_values;
663
 
    sc.variables = n;
664
 
    sc.complete_lengths = 1;
665
 
    sc.complete_values = 1;
666
 
 
667
 
    if (ngx_http_script_compile(&sc) != NGX_OK) {
 
641
    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
642
 
 
643
    ccv.cf = cf;
 
644
    ccv.value = &value[2];
 
645
    ccv.complex_value = &slcf->value;
 
646
 
 
647
    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
668
648
        return NGX_CONF_ERROR;
669
649
    }
670
650
 
672
652
}
673
653
 
674
654
 
675
 
static char *
676
 
ngx_http_sub_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
677
 
{
678
 
    ngx_http_sub_loc_conf_t *slcf = conf;
679
 
 
680
 
    ngx_str_t   *value, *type;
681
 
    ngx_uint_t   i;
682
 
 
683
 
    if (slcf->types == NULL) {
684
 
        slcf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
685
 
        if (slcf->types == NULL) {
686
 
            return NGX_CONF_ERROR;
687
 
        }
688
 
 
689
 
        type = ngx_array_push(slcf->types);
690
 
        if (type == NULL) {
691
 
            return NGX_CONF_ERROR;
692
 
        }
693
 
 
694
 
        type->len = sizeof("text/html") - 1;
695
 
        type->data = (u_char *) "text/html";
696
 
    }
697
 
 
698
 
    value = cf->args->elts;
699
 
 
700
 
    for (i = 1; i < cf->args->nelts; i++) {
701
 
 
702
 
        if (ngx_strcmp(value[i].data, "text/html") == 0) {
703
 
            continue;
704
 
        }
705
 
 
706
 
        type = ngx_array_push(slcf->types);
707
 
        if (type == NULL) {
708
 
            return NGX_CONF_ERROR;
709
 
        }
710
 
 
711
 
        type->len = value[i].len;
712
 
 
713
 
        type->data = ngx_palloc(cf->pool, type->len + 1);
714
 
        if (type->data == NULL) {
715
 
            return NGX_CONF_ERROR;
716
 
        }
717
 
 
718
 
        ngx_cpystrn(type->data, value[i].data, type->len + 1);
719
 
    }
720
 
 
721
 
    return NGX_CONF_OK;
722
 
}
723
 
 
724
 
 
725
655
static void *
726
656
ngx_http_sub_create_conf(ngx_conf_t *cf)
727
657
{
729
659
 
730
660
    slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sub_loc_conf_t));
731
661
    if (slcf == NULL) {
732
 
        return NGX_CONF_ERROR;
 
662
        return NULL;
733
663
    }
734
664
 
735
665
    /*
736
666
     * set by ngx_pcalloc():
737
667
     *
738
 
     *     conf->match.len = 0;
739
 
     *     conf->match.data = NULL;
740
 
     *     conf->sub.len = 0;
741
 
     *     conf->sub.data = NULL;
 
668
     *     conf->match = { 0, NULL };
 
669
     *     conf->sub = { 0, NULL };
742
670
     *     conf->sub_lengths = NULL;
743
671
     *     conf->sub_values = NULL;
744
 
     *     conf->types = NULL;
 
672
     *     conf->types = { NULL };
 
673
     *     conf->types_keys = NULL;
745
674
     */
746
675
 
747
676
    slcf->once = NGX_CONF_UNSET;
756
685
    ngx_http_sub_loc_conf_t *prev = parent;
757
686
    ngx_http_sub_loc_conf_t *conf = child;
758
687
 
759
 
    ngx_str_t  *type;
760
 
 
761
688
    ngx_conf_merge_value(conf->once, prev->once, 1);
762
689
    ngx_conf_merge_str_value(conf->match, prev->match, "");
763
690
 
764
 
    if (conf->sub.data == NULL && conf->sub_lengths == NULL) {
765
 
        conf->sub = prev->sub;
766
 
        conf->sub_lengths = prev->sub_lengths;
767
 
        conf->sub_values = prev->sub_values;
 
691
    if (conf->value.value.data == NULL) {
 
692
        conf->value = prev->value;
768
693
    }
769
694
 
770
 
    if (conf->types == NULL) {
771
 
        if (prev->types == NULL) {
772
 
            conf->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
773
 
            if (conf->types == NULL) {
774
 
                return NGX_CONF_ERROR;
775
 
            }
776
 
 
777
 
            type = ngx_array_push(conf->types);
778
 
            if (type == NULL) {
779
 
                return NGX_CONF_ERROR;
780
 
            }
781
 
 
782
 
            type->len = sizeof("text/html") - 1;
783
 
            type->data = (u_char *) "text/html";
784
 
 
785
 
        } else {
786
 
            conf->types = prev->types;
787
 
        }
 
695
    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
 
696
                             &prev->types_keys, &prev->types,
 
697
                             ngx_http_html_default_types)
 
698
        != NGX_OK)
 
699
    {
 
700
        return NGX_CONF_ERROR;
788
701
    }
789
702
 
790
703
    return NGX_CONF_OK;