~ubuntu-branches/ubuntu/quantal/nginx/quantal-updates

« back to all changes in this revision

Viewing changes to debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry, Kartik Mistry
  • Date: 2011-09-26 10:17:04 UTC
  • mfrom: (4.2.38 sid)
  • Revision ID: package-import@ubuntu.com-20110926101704-x8pxngiujrmkxnn3
Tags: 1.1.4-2
[Kartik Mistry]
* debian/modules:
  + Updated nginx-upload-progress module, Thanks to upstream for fixing issue
    that FTBFS nginx on kFreeBSD-* archs.
  + Updated nginx-lua module to latest upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) agentzh */
 
2
 
 
3
#define DDEBUG 0
 
4
 
 
5
#include "ddebug.h"
 
6
 
 
7
#include "ngx_http_headers_more_headers_in.h"
 
8
#include "ngx_http_headers_more_util.h"
 
9
#include <ctype.h>
 
10
 
 
11
/* config time */
 
12
 
 
13
static char *
 
14
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
 
15
        void *conf, ngx_http_headers_more_opcode_t opcode);
 
16
 
 
17
/* request time */
 
18
 
 
19
static ngx_flag_t ngx_http_headers_more_check_type(ngx_http_request_t *r,
 
20
        ngx_array_t *types);
 
21
 
 
22
static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
 
23
    ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
 
24
 
 
25
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
 
26
    ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
 
27
    ngx_table_elt_t **output_header);
 
28
 
 
29
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
 
30
    ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
 
31
 
 
32
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
 
33
    ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
 
34
 
 
35
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
 
36
    ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
 
37
 
 
38
static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
 
39
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
 
40
 
 
41
static ngx_int_t ngx_http_set_host_header(ngx_http_request_t *r,
 
42
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
 
43
 
 
44
 
 
45
static ngx_http_headers_more_set_header_t ngx_http_headers_more_set_handlers[]
 
46
        = {
 
47
 
 
48
    { ngx_string("Host"),
 
49
                 offsetof(ngx_http_headers_in_t, host),
 
50
                 ngx_http_set_host_header },
 
51
 
 
52
    { ngx_string("Connection"),
 
53
                 offsetof(ngx_http_headers_in_t, connection),
 
54
                 ngx_http_set_builtin_header },
 
55
 
 
56
    { ngx_string("If-Modified-Since"),
 
57
                 offsetof(ngx_http_headers_in_t, if_modified_since),
 
58
                 ngx_http_set_builtin_header },
 
59
 
 
60
    { ngx_string("User-Agent"),
 
61
                 offsetof(ngx_http_headers_in_t, user_agent),
 
62
                 ngx_http_set_builtin_header },
 
63
 
 
64
    { ngx_string("Referer"),
 
65
                 offsetof(ngx_http_headers_in_t, referer),
 
66
                 ngx_http_set_builtin_header },
 
67
 
 
68
    { ngx_string("Content-Type"),
 
69
                 offsetof(ngx_http_headers_in_t, content_type),
 
70
                 ngx_http_set_builtin_header },
 
71
 
 
72
    { ngx_string("Range"),
 
73
                 offsetof(ngx_http_headers_in_t, range),
 
74
                 ngx_http_set_builtin_header },
 
75
 
 
76
    { ngx_string("If-Range"),
 
77
                 offsetof(ngx_http_headers_in_t, if_range),
 
78
                 ngx_http_set_builtin_header },
 
79
 
 
80
    { ngx_string("Transfer-Encoding"),
 
81
                 offsetof(ngx_http_headers_in_t, transfer_encoding),
 
82
                 ngx_http_set_builtin_header },
 
83
 
 
84
    { ngx_string("Expect"),
 
85
                 offsetof(ngx_http_headers_in_t, expect),
 
86
                 ngx_http_set_builtin_header },
 
87
 
 
88
    { ngx_string("Authorization"),
 
89
                 offsetof(ngx_http_headers_in_t, authorization),
 
90
                 ngx_http_set_builtin_header },
 
91
 
 
92
    { ngx_string("Keep-Alive"),
 
93
                 offsetof(ngx_http_headers_in_t, keep_alive),
 
94
                 ngx_http_set_builtin_header },
 
95
 
 
96
    { ngx_string("Content-Length"),
 
97
                 offsetof(ngx_http_headers_in_t, content_length),
 
98
                 ngx_http_set_content_length_header },
 
99
 
 
100
    { ngx_null_string, 0, ngx_http_set_header }
 
101
};
 
102
 
 
103
 
 
104
/* request time implementation */
 
105
 
 
106
ngx_int_t
 
107
ngx_http_headers_more_exec_input_cmd(ngx_http_request_t *r,
 
108
        ngx_http_headers_more_cmd_t *cmd)
 
109
{
 
110
    ngx_str_t                                    value;
 
111
    ngx_http_headers_more_header_val_t          *h;
 
112
    ngx_uint_t                                   i;
 
113
 
 
114
    if (!cmd->headers) {
 
115
        return NGX_OK;
 
116
    }
 
117
 
 
118
    if (cmd->types) {
 
119
        if ( ! ngx_http_headers_more_check_type(r, cmd->types) ) {
 
120
            return NGX_OK;
 
121
        }
 
122
    }
 
123
 
 
124
    h = cmd->headers->elts;
 
125
    for (i = 0; i < cmd->headers->nelts; i++) {
 
126
 
 
127
        if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
 
128
            return NGX_ERROR;
 
129
        }
 
130
 
 
131
#if 1
 
132
        /* XXX nginx core's ngx_http_range_parse
 
133
         *     function requires null-terminated
 
134
         *     Range header values. so we have to
 
135
         *     work-around it here */
 
136
 
 
137
        if (h[i].key.len == sizeof("Range") - 1 &&
 
138
                ngx_strncasecmp(h[i].key.data, (u_char *) "Range",
 
139
                    sizeof("Range") - 1) == 0)
 
140
        {
 
141
            u_char                  *p;
 
142
 
 
143
            p = ngx_palloc(r->pool, value.len + 1);
 
144
            if (p == NULL) {
 
145
                return NGX_ERROR;
 
146
            }
 
147
 
 
148
            ngx_memcpy(p, value.data, value.len);
 
149
            p[value.len] = '\0';
 
150
 
 
151
            value.data = p;
 
152
        }
 
153
#endif
 
154
 
 
155
        if (h[i].handler(r, &h[i], &value) != NGX_OK) {
 
156
            return NGX_ERROR;
 
157
        }
 
158
    }
 
159
 
 
160
    return NGX_OK;
 
161
}
 
162
 
 
163
 
 
164
static ngx_int_t
 
165
ngx_http_set_header(ngx_http_request_t *r,
 
166
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
 
167
{
 
168
    return ngx_http_set_header_helper(r, hv, value, NULL);
 
169
}
 
170
 
 
171
 
 
172
static ngx_int_t
 
173
ngx_http_set_header_helper(ngx_http_request_t *r,
 
174
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
 
175
        ngx_table_elt_t **output_header)
 
176
{
 
177
    ngx_table_elt_t             *h;
 
178
    ngx_list_part_t             *part;
 
179
    ngx_uint_t                   i;
 
180
    ngx_uint_t                   rc;
 
181
 
 
182
    dd_enter();
 
183
 
 
184
    part = &r->headers_in.headers.part;
 
185
    h = part->elts;
 
186
 
 
187
    for (i = 0; /* void */; i++) {
 
188
        dd("i: %d, part: %p", (int) i, part);
 
189
 
 
190
        if (i >= part->nelts) {
 
191
            if (part->next == NULL) {
 
192
                break;
 
193
            }
 
194
 
 
195
            part = part->next;
 
196
            h = part->elts;
 
197
            i = 0;
 
198
        }
 
199
 
 
200
        if (h[i].key.len == hv->key.len
 
201
                && ngx_strncasecmp(h[i].key.data,
 
202
                    hv->key.data,
 
203
                    h[i].key.len) == 0)
 
204
        {
 
205
            if (value->len == 0) {
 
206
                h[i].hash = 0;
 
207
 
 
208
                rc = ngx_http_headers_more_rm_header_helper(
 
209
                        &r->headers_in.headers, part, i);
 
210
 
 
211
                if (rc == NGX_OK) {
 
212
                    if (output_header) {
 
213
                        *output_header = NULL;
 
214
                    }
 
215
 
 
216
                    return NGX_OK;
 
217
                }
 
218
            }
 
219
 
 
220
            h[i].value = *value;
 
221
 
 
222
            if (output_header) {
 
223
                *output_header = &h[i];
 
224
                dd("setting existing builtin input header");
 
225
            }
 
226
 
 
227
            return NGX_OK;
 
228
        }
 
229
    }
 
230
 
 
231
    if (value->len == 0 || hv->replace) {
 
232
      return NGX_OK;
 
233
    }
 
234
 
 
235
    h = ngx_list_push(&r->headers_in.headers);
 
236
 
 
237
    if (h == NULL) {
 
238
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
239
    }
 
240
 
 
241
    dd("created new header for %.*s", (int) hv->key.len, hv->key.data);
 
242
 
 
243
    if (value->len == 0) {
 
244
        h->hash = 0;
 
245
    } else {
 
246
        h->hash = hv->hash;
 
247
    }
 
248
 
 
249
    h->key = hv->key;
 
250
    h->value = *value;
 
251
 
 
252
    h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
 
253
    if (h->lowcase_key == NULL) {
 
254
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
255
    }
 
256
 
 
257
    ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
 
258
 
 
259
    if (output_header) {
 
260
        *output_header = h;
 
261
 
 
262
        while (r != r->main) {
 
263
            r->parent->headers_in = r->headers_in;
 
264
            r = r->parent;
 
265
        }
 
266
    }
 
267
 
 
268
    return NGX_OK;
 
269
}
 
270
 
 
271
static ngx_int_t
 
272
ngx_http_set_builtin_header(ngx_http_request_t *r,
 
273
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
 
274
{
 
275
    ngx_table_elt_t             *h, **old;
 
276
    ngx_int_t                    rc;
 
277
 
 
278
    dd("entered set_builtin_header (input)");
 
279
 
 
280
    if (hv->offset) {
 
281
        old = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
 
282
 
 
283
    } else {
 
284
        old = NULL;
 
285
    }
 
286
 
 
287
    dd("old builtin ptr ptr: %p", old);
 
288
    if (old) {
 
289
        dd("old builtin ptr: %p", *old);
 
290
    }
 
291
 
 
292
    if (old == NULL || *old == NULL) {
 
293
        dd("set normal header");
 
294
        return ngx_http_set_header_helper(r, hv, value, old);
 
295
    }
 
296
 
 
297
    h = *old;
 
298
 
 
299
    if (value->len == 0) {
 
300
        h->hash = 0;
 
301
        h->value = *value;
 
302
 
 
303
        rc = ngx_http_headers_more_rm_header(&r->headers_in.headers, h);
 
304
 
 
305
        dd("rm header: %d", (int) rc);
 
306
 
 
307
        if (rc == NGX_OK) {
 
308
            *old = NULL;
 
309
        }
 
310
 
 
311
        return rc;
 
312
    }
 
313
 
 
314
    h->hash = hv->hash;
 
315
    h->value = *value;
 
316
 
 
317
    return NGX_OK;
 
318
}
 
319
 
 
320
static ngx_int_t
 
321
ngx_http_set_host_header(ngx_http_request_t *r,
 
322
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
 
323
{
 
324
    dd("server new value len: %d", (int) value->len);
 
325
 
 
326
    r->headers_in.server = *value;
 
327
 
 
328
    return ngx_http_set_builtin_header(r, hv, value);
 
329
}
 
330
 
 
331
static ngx_int_t
 
332
ngx_http_set_content_length_header(ngx_http_request_t *r,
 
333
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
 
334
{
 
335
    off_t           len;
 
336
 
 
337
    if (value->len == 0) {
 
338
        return ngx_http_clear_content_length_header(r, hv, value);
 
339
    }
 
340
 
 
341
    len = ngx_atosz(value->data, value->len);
 
342
    if (len == NGX_ERROR) {
 
343
        return NGX_ERROR;
 
344
    }
 
345
 
 
346
    dd("reset headers_in.content_length_n to %d", (int)len);
 
347
 
 
348
    r->headers_in.content_length_n = len;
 
349
 
 
350
    return ngx_http_set_builtin_header(r, hv, value);
 
351
}
 
352
 
 
353
static ngx_int_t
 
354
ngx_http_clear_content_length_header(ngx_http_request_t *r,
 
355
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
 
356
{
 
357
    r->headers_in.content_length_n = -1;
 
358
 
 
359
    return ngx_http_clear_builtin_header(r, hv, value);
 
360
}
 
361
 
 
362
static ngx_int_t
 
363
ngx_http_clear_builtin_header(ngx_http_request_t *r,
 
364
        ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
 
365
{
 
366
    value->len = 0;
 
367
    return ngx_http_set_builtin_header(r, hv, value);
 
368
}
 
369
 
 
370
char *
 
371
ngx_http_headers_more_set_input_headers(ngx_conf_t *cf,
 
372
        ngx_command_t *cmd, void *conf)
 
373
{
 
374
    return ngx_http_headers_more_parse_directive(cf, cmd, conf,
 
375
            ngx_http_headers_more_opcode_set);
 
376
}
 
377
 
 
378
char *
 
379
ngx_http_headers_more_clear_input_headers(ngx_conf_t *cf,
 
380
        ngx_command_t *cmd, void *conf)
 
381
{
 
382
    return ngx_http_headers_more_parse_directive(cf, cmd, conf,
 
383
            ngx_http_headers_more_opcode_clear);
 
384
}
 
385
 
 
386
static ngx_flag_t
 
387
ngx_http_headers_more_check_type(ngx_http_request_t *r, ngx_array_t *types)
 
388
{
 
389
    ngx_uint_t          i;
 
390
    ngx_str_t           *t;
 
391
    ngx_str_t           actual_type;
 
392
 
 
393
    if (r->headers_in.content_type == NULL) {
 
394
        return 0;
 
395
    }
 
396
 
 
397
    actual_type = r->headers_in.content_type->value;
 
398
    if (actual_type.len == 0) {
 
399
        return 0;
 
400
    }
 
401
 
 
402
    dd("headers_in->content_type: %.*s",
 
403
            (int) actual_type.len,
 
404
            actual_type.data);
 
405
 
 
406
    t = types->elts;
 
407
    for (i = 0; i < types->nelts; i++) {
 
408
        dd("...comparing with type [%.*s]", (int) t[i].len, t[i].data);
 
409
 
 
410
        if (actual_type.len == t[i].len
 
411
                && ngx_strncmp(actual_type.data,
 
412
                    t[i].data, t[i].len) == 0)
 
413
        {
 
414
            return 1;
 
415
        }
 
416
    }
 
417
 
 
418
    return 0;
 
419
}
 
420
 
 
421
/* config time implementation */
 
422
 
 
423
static char *
 
424
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
 
425
        void *conf, ngx_http_headers_more_opcode_t opcode)
 
426
{
 
427
    ngx_http_headers_more_loc_conf_t   *hcf = conf;
 
428
 
 
429
    ngx_uint_t                          i;
 
430
    ngx_http_headers_more_cmd_t         *cmd;
 
431
    ngx_str_t                           *arg;
 
432
    ngx_flag_t                          ignore_next_arg;
 
433
    ngx_str_t                           *cmd_name;
 
434
    ngx_int_t                           rc;
 
435
    ngx_flag_t                          replace = 0;
 
436
    ngx_http_headers_more_header_val_t  *h;
 
437
 
 
438
    if (hcf->cmds == NULL) {
 
439
        hcf->cmds = ngx_array_create(cf->pool, 1,
 
440
                        sizeof(ngx_http_headers_more_cmd_t));
 
441
 
 
442
        if (hcf->cmds == NULL) {
 
443
            return NGX_CONF_ERROR;
 
444
        }
 
445
    }
 
446
 
 
447
    cmd = ngx_array_push(hcf->cmds);
 
448
 
 
449
    if (cmd == NULL) {
 
450
        return NGX_CONF_ERROR;
 
451
    }
 
452
 
 
453
    cmd->headers = ngx_array_create(cf->pool, 1,
 
454
                            sizeof(ngx_http_headers_more_header_val_t));
 
455
 
 
456
    if (cmd->headers == NULL) {
 
457
        return NGX_CONF_ERROR;
 
458
    }
 
459
 
 
460
    cmd->types = ngx_array_create(cf->pool, 1,
 
461
                            sizeof(ngx_str_t));
 
462
    if (cmd->types == NULL) {
 
463
        return NGX_CONF_ERROR;
 
464
    }
 
465
 
 
466
    cmd->statuses = NULL;
 
467
 
 
468
    arg = cf->args->elts;
 
469
 
 
470
    cmd_name = &arg[0];
 
471
 
 
472
    ignore_next_arg = 0;
 
473
 
 
474
    for (i = 1; i < cf->args->nelts; i++) {
 
475
        if (ignore_next_arg) {
 
476
            ignore_next_arg = 0;
 
477
            continue;
 
478
        }
 
479
 
 
480
        if (arg[i].len == 0) {
 
481
            continue;
 
482
        }
 
483
 
 
484
        if (arg[i].data[0] != '-') {
 
485
            rc = ngx_http_headers_more_parse_header(cf, cmd_name,
 
486
                    &arg[i], cmd->headers, opcode,
 
487
                    ngx_http_headers_more_set_handlers);
 
488
 
 
489
            if (rc != NGX_OK) {
 
490
                return NGX_CONF_ERROR;
 
491
            }
 
492
 
 
493
            continue;
 
494
        }
 
495
 
 
496
        if (arg[i].len == 2) {
 
497
            if (arg[i].data[1] == 't') {
 
498
                if (i == cf->args->nelts - 1) {
 
499
                    ngx_log_error(NGX_LOG_ERR, cf->log, 0,
 
500
                          "%V: option -t takes an argument.",
 
501
                          cmd_name);
 
502
 
 
503
                    return NGX_CONF_ERROR;
 
504
                }
 
505
 
 
506
                rc = ngx_http_headers_more_parse_types(cf->log, cmd_name,
 
507
                        &arg[i + 1], cmd->types);
 
508
 
 
509
                if (rc != NGX_OK) {
 
510
                    return NGX_CONF_ERROR;
 
511
                }
 
512
 
 
513
                ignore_next_arg = 1;
 
514
 
 
515
                continue;
 
516
            } else if (arg[i].data[1] == 'r') {
 
517
              dd("Found replace flag");
 
518
              replace = 1;
 
519
              continue;
 
520
            }
 
521
        }
 
522
 
 
523
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
 
524
              "%V: invalid option name: \"%V\"",
 
525
              cmd_name, &arg[i]);
 
526
 
 
527
        return NGX_CONF_ERROR;
 
528
    }
 
529
 
 
530
    dd("Found %d types, and %d headers",
 
531
            (int) cmd->types->nelts,
 
532
            (int) cmd->headers->nelts);
 
533
 
 
534
    if (cmd->headers->nelts == 0) {
 
535
        ngx_pfree(cf->pool, cmd->headers);
 
536
        cmd->headers = NULL;
 
537
    } else {
 
538
        h = cmd->headers->elts;
 
539
        for (i = 0; i < cmd->headers->nelts; i++) {
 
540
            h[i].replace = replace;
 
541
        }
 
542
    }
 
543
 
 
544
    if (cmd->types->nelts == 0) {
 
545
        ngx_pfree(cf->pool, cmd->types);
 
546
        cmd->types = NULL;
 
547
    }
 
548
 
 
549
    cmd->is_input = 1;
 
550
 
 
551
    ngx_http_headers_more_handler_used = 1;
 
552
 
 
553
    return NGX_CONF_OK;
 
554
}
 
555