comparison src/http/modules/ngx_http_charset_filter_module.c @ 78:9db7e0b5b27f NGINX_0_1_39

nginx 0.1.39 *) The changes in the ngx_http_charset_module: the "default_charset" directive was canceled; the "charset" directive sets the response charset; the "source_charset" directive sets the source charset only. *) Bugfix: the backend "WWW-Authenticate" header line did not transferred while the 401 response code redirecting. *) Bugfix: the ngx_http_proxy_module and ngx_http_fastcgi_module may close a connection before anything was transferred to a client; bug appeared in 0.1.38. *) Workaround: the Linux glibc crypt_r() initialization bug. *) Bugfix: the ngx_http_ssi_module did not support the relative URI in the "include virtual" command. *) Bugfix: if the backend response had the "Location" header line and nginx should not rewrite this line, then the 500 code response body was transferred; bug appeared in 0.1.29. *) Bugfix: some directives of the ngx_http_proxy_module and ngx_http_fastcgi_module were not inherited from the server to the location level; bug appeared in 0.1.29. *) Bugfix: the ngx_http_ssl_module did not support the certificate chain. *) Bugfix: the ngx_http_autoindex_module did not show correctly the long file names; bug appeared in 0.1.38. *) Bugfixes in IMAP/POP3 proxy in interaction with a backend at the login state.
author Igor Sysoev <http://sysoev.ru>
date Thu, 14 Jul 2005 00:00:00 +0400
parents 77969b24f355
children 71c46860eb55
comparison
equal deleted inserted replaced
77:e6b3de2dc637 78:9db7e0b5b27f
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_http.h> 9 #include <ngx_http.h>
10 10
11 11
12 #define NGX_HTTP_NO_CHARSET -2
13
14
12 typedef struct { 15 typedef struct {
13 char **tables; 16 char **tables;
14 ngx_str_t name; 17 ngx_str_t name;
15 18
16 unsigned server:1; 19 ngx_uint_t utf8; /* unsigned utf8:1; */
17 unsigned utf8:1;
18 } ngx_http_charset_t; 20 } ngx_http_charset_t;
21
22
23 typedef struct {
24 ngx_int_t src;
25 ngx_int_t dst;
26 } ngx_http_charset_recode_t;
19 27
20 28
21 typedef struct { 29 typedef struct {
22 ngx_int_t src; 30 ngx_int_t src;
23 ngx_int_t dst; 31 ngx_int_t dst;
27 35
28 36
29 typedef struct { 37 typedef struct {
30 ngx_array_t charsets; /* ngx_http_charset_t */ 38 ngx_array_t charsets; /* ngx_http_charset_t */
31 ngx_array_t tables; /* ngx_http_charset_tables_t */ 39 ngx_array_t tables; /* ngx_http_charset_tables_t */
40 ngx_array_t recodes; /* ngx_http_charset_recode_t */
32 } ngx_http_charset_main_conf_t; 41 } ngx_http_charset_main_conf_t;
33 42
34 43
35 typedef struct { 44 typedef struct {
36 ngx_flag_t enable; 45 ngx_int_t charset;
37
38 ngx_int_t default_charset;
39 ngx_int_t source_charset; 46 ngx_int_t source_charset;
40 } ngx_http_charset_loc_conf_t; 47 } ngx_http_charset_loc_conf_t;
41 48
42 49
43 typedef struct { 50 typedef struct {
44 ngx_int_t server; 51 ngx_int_t server;
45 ngx_int_t client; 52 ngx_int_t client;
46 } ngx_http_charset_ctx_t; 53 } ngx_http_charset_ctx_t;
47 54
48 55
49 static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table); 56 static ngx_uint_t ngx_http_charset_recode(ngx_buf_t *b, char *table);
50 57
51 static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd, 58 static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
52 void *conf); 59 void *conf);
53 static char *ngx_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); 60 static char *ngx_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
54 61
57 static ngx_int_t ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name); 64 static ngx_int_t ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name);
58 65
59 static ngx_int_t ngx_http_charset_filter_init(ngx_cycle_t *cycle); 66 static ngx_int_t ngx_http_charset_filter_init(ngx_cycle_t *cycle);
60 67
61 static void *ngx_http_charset_create_main_conf(ngx_conf_t *cf); 68 static void *ngx_http_charset_create_main_conf(ngx_conf_t *cf);
62 static char *ngx_http_charset_init_main_conf(ngx_conf_t *cf, void *conf);
63 static void *ngx_http_charset_create_loc_conf(ngx_conf_t *cf); 69 static void *ngx_http_charset_create_loc_conf(ngx_conf_t *cf);
64 static char *ngx_http_charset_merge_loc_conf(ngx_conf_t *cf, 70 static char *ngx_http_charset_merge_loc_conf(ngx_conf_t *cf,
65 void *parent, void *child); 71 void *parent, void *child);
72 static ngx_int_t ngx_http_charset_postconfiguration(ngx_conf_t *cf);
66 73
67 74
68 static ngx_command_t ngx_http_charset_filter_commands[] = { 75 static ngx_command_t ngx_http_charset_filter_commands[] = {
76
77 { ngx_string("charset"),
78 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
79 |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
80 ngx_http_set_charset_slot,
81 NGX_HTTP_LOC_CONF_OFFSET,
82 offsetof(ngx_http_charset_loc_conf_t, charset),
83 NULL },
84
85 { ngx_string("source_charset"),
86 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
87 |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
88 ngx_http_set_charset_slot,
89 NGX_HTTP_LOC_CONF_OFFSET,
90 offsetof(ngx_http_charset_loc_conf_t, source_charset),
91 NULL },
69 92
70 { ngx_string("charset_map"), 93 { ngx_string("charset_map"),
71 NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2, 94 NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
72 ngx_charset_map_block, 95 ngx_charset_map_block,
73 NGX_HTTP_MAIN_CONF_OFFSET, 96 NGX_HTTP_MAIN_CONF_OFFSET,
74 0, 97 0,
75 NULL }, 98 NULL },
76 99
77 { ngx_string("default_charset"),
78 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
79 ngx_http_set_charset_slot,
80 NGX_HTTP_LOC_CONF_OFFSET,
81 offsetof(ngx_http_charset_loc_conf_t, default_charset),
82 NULL },
83
84 { ngx_string("source_charset"),
85 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
86 ngx_http_set_charset_slot,
87 NGX_HTTP_LOC_CONF_OFFSET,
88 offsetof(ngx_http_charset_loc_conf_t, source_charset),
89 NULL },
90
91 { ngx_string("charset"),
92 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
93 ngx_conf_set_flag_slot,
94 NGX_HTTP_LOC_CONF_OFFSET,
95 offsetof(ngx_http_charset_loc_conf_t, enable),
96 NULL },
97
98 ngx_null_command 100 ngx_null_command
99 }; 101 };
100 102
101 103
102 static ngx_http_module_t ngx_http_charset_filter_module_ctx = { 104 static ngx_http_module_t ngx_http_charset_filter_module_ctx = {
103 NULL, /* preconfiguration */ 105 NULL, /* preconfiguration */
104 NULL, /* postconfiguration */ 106 ngx_http_charset_postconfiguration, /* postconfiguration */
105 107
106 ngx_http_charset_create_main_conf, /* create main configuration */ 108 ngx_http_charset_create_main_conf, /* create main configuration */
107 ngx_http_charset_init_main_conf, /* init main configuration */ 109 NULL, /* init main configuration */
108 110
109 NULL, /* create server configuration */ 111 NULL, /* create server configuration */
110 NULL, /* merge server configuration */ 112 NULL, /* merge server configuration */
111 113
112 ngx_http_charset_create_loc_conf, /* create location configuration */ 114 ngx_http_charset_create_loc_conf, /* create location configuration */
137 ngx_http_charset_main_conf_t *mcf; 139 ngx_http_charset_main_conf_t *mcf;
138 140
139 mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module); 141 mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
140 lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module); 142 lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
141 143
142 if (lcf->enable == 0) { 144 if (lcf->charset == NGX_HTTP_NO_CHARSET) {
143 return ngx_http_next_header_filter(r); 145 return ngx_http_next_header_filter(r);
144 } 146 }
145 147
146 if (r->headers_out.content_type.len == 0) { 148 if (r->headers_out.content_type.len == 0) {
147 return ngx_http_next_header_filter(r); 149 return ngx_http_next_header_filter(r);
174 if (r->headers_out.charset.len) { 176 if (r->headers_out.charset.len) {
175 return ngx_http_next_header_filter(r); 177 return ngx_http_next_header_filter(r);
176 } 178 }
177 179
178 charsets = mcf->charsets.elts; 180 charsets = mcf->charsets.elts;
179 r->headers_out.charset = charsets[lcf->default_charset].name; 181 r->headers_out.charset = charsets[lcf->charset].name;
180 r->utf8 = charsets[lcf->default_charset].utf8; 182 r->utf8 = charsets[lcf->charset].utf8;
181 183
182 if (lcf->default_charset == lcf->source_charset) { 184 if (lcf->source_charset == NGX_CONF_UNSET
185 || lcf->source_charset == lcf->charset)
186 {
183 return ngx_http_next_header_filter(r); 187 return ngx_http_next_header_filter(r);
184 } 188 }
185 189
186 190
187 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t)); 191 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t));
216 220
217 mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module); 221 mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
218 lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module); 222 lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
219 223
220 charsets = mcf->charsets.elts; 224 charsets = mcf->charsets.elts;
221 table = charsets[lcf->source_charset].tables[lcf->default_charset]; 225 table = charsets[lcf->source_charset].tables[lcf->charset];
222 226
223 for (cl = in; cl; cl = cl->next) { 227 for (cl = in; cl; cl = cl->next) {
224 ngx_charset_recode(cl->buf, table); 228 ngx_http_charset_recode(cl->buf, table);
225 } 229 }
226 230
227 return ngx_http_next_body_filter(r, in); 231 return ngx_http_next_body_filter(r, in);
228 } 232 }
229 233
230 234
231 static ngx_uint_t 235 static ngx_uint_t
232 ngx_charset_recode(ngx_buf_t *b, char *table) 236 ngx_http_charset_recode(ngx_buf_t *b, char *table)
233 { 237 {
234 u_char *p; 238 u_char *p;
235 ngx_uint_t change; 239 ngx_uint_t change;
236 240
237 change = 0; 241 change = 0;
383 { 387 {
384 char *p = conf; 388 char *p = conf;
385 389
386 ngx_int_t *cp; 390 ngx_int_t *cp;
387 ngx_str_t *value; 391 ngx_str_t *value;
388 ngx_http_charset_t *charset;
389 ngx_http_charset_main_conf_t *mcf; 392 ngx_http_charset_main_conf_t *mcf;
390 393
391 cp = (ngx_int_t *) (p + cmd->offset); 394 cp = (ngx_int_t *) (p + cmd->offset);
392 395
393 if (*cp != NGX_CONF_UNSET) { 396 if (*cp != NGX_CONF_UNSET) {
394 return "is duplicate"; 397 return "is duplicate";
395 } 398 }
396 399
400 value = cf->args->elts;
401
402 if (cmd->offset == offsetof(ngx_http_charset_loc_conf_t, charset)
403 && ngx_strcmp(value[1].data, "off") == 0)
404 {
405 *cp = NGX_HTTP_NO_CHARSET;
406 return NGX_CONF_OK;
407 }
408
397 mcf = ngx_http_conf_get_module_main_conf(cf, 409 mcf = ngx_http_conf_get_module_main_conf(cf,
398 ngx_http_charset_filter_module); 410 ngx_http_charset_filter_module);
399 411
400 value = cf->args->elts;
401
402 *cp = ngx_http_add_charset(&mcf->charsets, &value[1]); 412 *cp = ngx_http_add_charset(&mcf->charsets, &value[1]);
403 if (*cp == NGX_ERROR) { 413 if (*cp == NGX_ERROR) {
404 return NGX_CONF_ERROR; 414 return NGX_CONF_ERROR;
405 }
406
407 if (cmd->offset == offsetof(ngx_http_charset_loc_conf_t, source_charset)) {
408 charset = mcf->charsets.elts;
409 charset[*cp].server = 1;
410 } 415 }
411 416
412 return NGX_CONF_OK; 417 return NGX_CONF_OK;
413 } 418 }
414 419
439 return NGX_ERROR; 444 return NGX_ERROR;
440 } 445 }
441 446
442 c->tables = NULL; 447 c->tables = NULL;
443 c->name = *name; 448 c->name = *name;
444 c->server = 0;
445 449
446 if (ngx_strcasecmp(name->data, "utf-8") == 0) { 450 if (ngx_strcasecmp(name->data, "utf-8") == 0) {
447 c->utf8 = 1; 451 c->utf8 = 1;
448 } 452 }
449 453
473 if (mcf == NULL) { 477 if (mcf == NULL) {
474 return NGX_CONF_ERROR; 478 return NGX_CONF_ERROR;
475 } 479 }
476 480
477 if (ngx_array_init(&mcf->charsets, cf->pool, 2, sizeof(ngx_http_charset_t)) 481 if (ngx_array_init(&mcf->charsets, cf->pool, 2, sizeof(ngx_http_charset_t))
478 == NGX_ERROR) 482 == NGX_ERROR)
479 { 483 {
480 return NGX_CONF_ERROR; 484 return NGX_CONF_ERROR;
481 } 485 }
482 486
483 if (ngx_array_init(&mcf->tables, cf->pool, 4, 487 if (ngx_array_init(&mcf->tables, cf->pool, 1,
484 sizeof(ngx_http_charset_tables_t)) == NGX_ERROR) 488 sizeof(ngx_http_charset_tables_t)) == NGX_ERROR)
485 { 489 {
486 return NGX_CONF_ERROR; 490 return NGX_CONF_ERROR;
487 } 491 }
488 492
493 if (ngx_array_init(&mcf->recodes, cf->pool, 2,
494 sizeof(ngx_http_charset_recode_t)) == NGX_ERROR)
495 {
496 return NGX_CONF_ERROR;
497 }
498
489 return mcf; 499 return mcf;
490 } 500 }
491 501
492 502
503 static void *
504 ngx_http_charset_create_loc_conf(ngx_conf_t *cf)
505 {
506 ngx_http_charset_loc_conf_t *lcf;
507
508 lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_loc_conf_t));
509 if (lcf == NULL) {
510 return NGX_CONF_ERROR;
511 }
512
513 lcf->charset = NGX_CONF_UNSET;
514 lcf->source_charset = NGX_CONF_UNSET;
515
516 return lcf;
517 }
518
519
493 static char * 520 static char *
494 ngx_http_charset_init_main_conf(ngx_conf_t *cf, void *conf) 521 ngx_http_charset_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
495 { 522 {
496 ngx_http_charset_main_conf_t *mcf = conf; 523 ngx_http_charset_loc_conf_t *prev = parent;
497 524 ngx_http_charset_loc_conf_t *conf = child;
498 ngx_uint_t i, n; 525
499 ngx_http_charset_t *charset; 526 ngx_uint_t i;
500 ngx_http_charset_tables_t *tables; 527 ngx_http_charset_recode_t *recode;
501 528 ngx_http_charset_main_conf_t *mcf;
529
530 ngx_conf_merge_value(conf->charset, prev->charset, NGX_HTTP_NO_CHARSET);
531
532 if (conf->source_charset == NGX_CONF_UNSET) {
533 conf->source_charset = prev->source_charset;
534 }
535
536 if (conf->charset == NGX_HTTP_NO_CHARSET
537 || conf->source_charset == NGX_CONF_UNSET
538 || conf->charset == conf->source_charset)
539 {
540 return NGX_CONF_OK;
541 }
542
543 mcf = ngx_http_conf_get_module_main_conf(cf,
544 ngx_http_charset_filter_module);
545 recode = mcf->recodes.elts;
546 for (i = 0; i < mcf->recodes.nelts; i++) {
547 if (conf->source_charset == recode[i].src
548 && conf->charset == recode[i].dst)
549 {
550 return NGX_CONF_OK;
551 }
552 }
553
554 recode = ngx_array_push(&mcf->recodes);
555 if (recode == NULL) {
556 return NGX_CONF_ERROR;
557 }
558
559 recode->src = conf->source_charset;
560 recode->dst = conf->charset;
561
562 return NGX_CONF_OK;
563 }
564
565
566 static ngx_int_t
567 ngx_http_charset_postconfiguration(ngx_conf_t *cf)
568 {
569 ngx_int_t c;
570 ngx_uint_t i, t;
571 ngx_http_charset_t *charset;
572 ngx_http_charset_recode_t *recode;
573 ngx_http_charset_tables_t *tables;
574 ngx_http_charset_main_conf_t *mcf;
575
576 mcf = ngx_http_conf_get_module_main_conf(cf,
577 ngx_http_charset_filter_module);
578
579 recode = mcf->recodes.elts;
502 tables = mcf->tables.elts; 580 tables = mcf->tables.elts;
503 charset = mcf->charsets.elts; 581 charset = mcf->charsets.elts;
504 582
505 for (i = 0; i < mcf->charsets.nelts; i++) { 583 for (i = 0; i < mcf->recodes.nelts; i++) {
506 if (!charset[i].server) { 584
507 continue; 585 c = recode[i].src;
508 } 586
509 587 charset[c].tables = ngx_pcalloc(cf->pool,
510 charset[i].tables = ngx_pcalloc(cf->pool,
511 sizeof(char *) * mcf->charsets.nelts); 588 sizeof(char *) * mcf->charsets.nelts);
512 if (charset[i].tables == NULL) { 589 if (charset[c].tables == NULL) {
513 return NGX_CONF_ERROR; 590 return NGX_ERROR;
514 } 591 }
515 592
516 for (n = 0; n < mcf->tables.nelts; n++) { 593 for (t = 0; t < mcf->tables.nelts; t++) {
517 if ((ngx_int_t) i == tables[n].src) { 594
518 charset[i].tables[tables[n].dst] = tables[n].src2dst; 595 if (c == tables[t].src && recode[i].dst == tables[t].dst) {
519 continue; 596 charset[c].tables[tables[t].dst] = tables[t].src2dst;
597 goto next;
520 } 598 }
521 599
522 if ((ngx_int_t) i == tables[n].dst) { 600 if (c == tables[t].dst && recode[i].dst == tables[t].src) {
523 charset[i].tables[tables[n].src] = tables[n].dst2src; 601 charset[c].tables[tables[t].src] = tables[t].dst2src;
602 goto next;
524 } 603 }
525 } 604 }
526 } 605
527 606 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
528 for (i = 0; i < mcf->charsets.nelts; i++) { 607 " no \"charset_map\" between the charsets "
529 if (!charset[i].server) { 608 "\"%V\" and \"%V\"",
530 continue; 609 &charset[c].name, &charset[recode[i].dst].name);
531 } 610 return NGX_ERROR;
532 611
533 for (n = 0; n < mcf->charsets.nelts; n++) { 612 next:
534 if (i == n) { 613 continue;
535 continue; 614 }
536 } 615
537 616 return NGX_OK;
538 if (charset[i].tables[n]) { 617 }
539 continue;
540 }
541
542 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
543 " no \"charset_map\" between the charsets "
544 "\"%V\" and \"%V\"",
545 &charset[i].name, &charset[n].name);
546 return NGX_CONF_ERROR;
547 }
548 }
549
550 return NGX_CONF_OK;
551 }
552
553
554 static void *
555 ngx_http_charset_create_loc_conf(ngx_conf_t *cf)
556 {
557 ngx_http_charset_loc_conf_t *lcf;
558
559 lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_loc_conf_t));
560 if (lcf == NULL) {
561 return NGX_CONF_ERROR;
562 }
563
564 lcf->enable = NGX_CONF_UNSET;
565 lcf->default_charset = NGX_CONF_UNSET;
566 lcf->source_charset = NGX_CONF_UNSET;
567
568 return lcf;
569 }
570
571
572 static char *
573 ngx_http_charset_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
574 {
575 ngx_http_charset_loc_conf_t *prev = parent;
576 ngx_http_charset_loc_conf_t *conf = child;
577
578 ngx_conf_merge_value(conf->enable, prev->enable, 0);
579
580 if (conf->default_charset == NGX_CONF_UNSET) {
581 conf->default_charset = prev->default_charset;
582 }
583
584 if (conf->source_charset == NGX_CONF_UNSET) {
585 conf->source_charset = prev->source_charset;
586 }
587
588 if (conf->default_charset == NGX_CONF_UNSET
589 && conf->source_charset != NGX_CONF_UNSET)
590 {
591 conf->default_charset = conf->source_charset;
592 }
593
594 if (conf->source_charset == NGX_CONF_UNSET
595 && conf->default_charset != NGX_CONF_UNSET)
596 {
597 conf->source_charset = conf->default_charset;
598 }
599
600 if (conf->enable
601 && (conf->default_charset == NGX_CONF_UNSET
602 || conf->source_charset == NGX_CONF_UNSET))
603 {
604 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
605 "the \"source_charset\" or \"default_charset\" "
606 "must be specified when \"charset\" is on");
607 return NGX_CONF_ERROR;
608 }
609
610 return NGX_CONF_OK;
611 }