Mercurial > hg > nginx-vendor-1-0
comparison src/http/modules/ngx_http_xslt_filter_module.c @ 394:05981f639d21 NGINX_0_7_9
nginx 0.7.9
*) Change: now ngx_http_charset_module works by default with following
MIME types: text/html, text/css, text/xml, text/plain,
text/vnd.wap.wml, application/x-javascript, and application/rss+xml.
*) Feature: the "charset_types" and "addition_types" directives.
*) Feature: now the "gzip_types", "ssi_types", and "sub_filter_types"
directives use hash.
*) Feature: the ngx_cpp_test_module.
*) Feature: the "expires" directive supports daily time.
*) Feature: the ngx_http_xslt_module improvements and bug fixing.
Thanks to Denis F. Latypoff and Maxim Dounin.
*) Bugfix: the "log_not_found" directive did not work for index files
tests.
*) Bugfix: HTTPS connections might hang, if kqueue, epoll, rtsig, or
eventport methods were used; the bug had appeared in 0.7.7.
*) Bugfix: if the "server_name", "valid_referers", and "map" directives
used an "*.domain.tld" wildcard and exact name "domain.tld" was not
set, then the exact name was matched by the wildcard; the bugs had
appeared in 0.3.18.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 12 Aug 2008 00:00:00 +0400 |
parents | 34fb3a573548 |
children | 6ebbca3d5ed7 |
comparison
equal
deleted
inserted
replaced
393:040b8c84d040 | 394:05981f639d21 |
---|---|
20 #define NGX_HTTP_XSLT_REUSE_DTD 1 | 20 #define NGX_HTTP_XSLT_REUSE_DTD 1 |
21 #endif | 21 #endif |
22 | 22 |
23 | 23 |
24 typedef struct { | 24 typedef struct { |
25 u_char *name; | |
26 void *data; | |
27 } ngx_http_xslt_file_t; | |
28 | |
29 | |
30 typedef struct { | |
31 ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ | |
32 ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ | |
33 } ngx_http_xslt_filter_main_conf_t; | |
34 | |
35 | |
36 typedef struct { | |
25 ngx_array_t *lengths; | 37 ngx_array_t *lengths; |
26 ngx_array_t *values; | 38 ngx_array_t *values; |
27 } ngx_http_xslt_param_t; | 39 } ngx_http_xslt_param_t; |
28 | 40 |
29 | 41 |
33 } ngx_http_xslt_sheet_t; | 45 } ngx_http_xslt_sheet_t; |
34 | 46 |
35 | 47 |
36 typedef struct { | 48 typedef struct { |
37 xmlDtdPtr dtd; | 49 xmlDtdPtr dtd; |
38 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ | 50 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ |
39 ngx_hash_t types_hash; | 51 ngx_hash_t types; |
40 ngx_array_t *keys; | 52 ngx_array_t *types_keys; |
41 } ngx_http_xslt_filter_conf_t; | 53 } ngx_http_xslt_filter_loc_conf_t; |
42 | 54 |
43 | 55 |
44 typedef struct { | 56 typedef struct { |
45 xmlDocPtr doc; | 57 xmlDocPtr doc; |
46 xmlParserCtxtPtr ctxt; | 58 xmlParserCtxtPtr ctxt; |
47 xmlSAXHandler *sax; | 59 xmlSAXHandler *sax; |
48 ngx_http_request_t *request; | 60 ngx_http_request_t *request; |
49 ngx_array_t params; | 61 ngx_array_t params; |
50 unsigned done:1; | 62 |
51 unsigned html:1; | 63 ngx_uint_t done; /* unsigned done:1; */ |
52 } ngx_http_xslt_filter_ctx_t; | 64 } ngx_http_xslt_filter_ctx_t; |
53 | 65 |
54 | 66 |
55 static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r, | 67 static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r, |
56 ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b); | 68 ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b); |
107 | 119 |
108 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, | 120 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, |
109 ngx_http_xslt_filter_ctx_t *ctx); | 121 ngx_http_xslt_filter_ctx_t *ctx); |
110 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, | 122 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, |
111 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); | 123 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); |
124 static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s); | |
125 static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s); | |
112 static void ngx_http_xslt_cleanup(void *data); | 126 static void ngx_http_xslt_cleanup(void *data); |
113 | 127 |
114 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, | 128 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, |
115 void *conf); | 129 void *conf); |
116 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, | 130 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, |
117 void *conf); | 131 void *conf); |
132 static void ngx_http_xslt_cleanup_dtd(void *data); | |
118 static void ngx_http_xslt_cleanup_stylesheet(void *data); | 133 static void ngx_http_xslt_cleanup_stylesheet(void *data); |
134 static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf); | |
119 static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf); | 135 static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf); |
120 static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, | 136 static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, |
121 void *child); | 137 void *child); |
122 static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf); | 138 static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf); |
123 | 139 |
129 | 145 |
130 | 146 |
131 static ngx_command_t ngx_http_xslt_filter_commands[] = { | 147 static ngx_command_t ngx_http_xslt_filter_commands[] = { |
132 | 148 |
133 { ngx_string("xml_entities"), | 149 { ngx_string("xml_entities"), |
134 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, | 150 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
135 ngx_http_xslt_entities, | 151 ngx_http_xslt_entities, |
136 NGX_HTTP_LOC_CONF_OFFSET, | 152 NGX_HTTP_LOC_CONF_OFFSET, |
137 0, | 153 0, |
138 NULL }, | 154 NULL }, |
139 | 155 |
140 { ngx_string("xslt_stylesheet"), | 156 { ngx_string("xslt_stylesheet"), |
141 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_1MORE, | 157 NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
142 ngx_http_xslt_stylesheet, | 158 ngx_http_xslt_stylesheet, |
143 NGX_HTTP_LOC_CONF_OFFSET, | 159 NGX_HTTP_LOC_CONF_OFFSET, |
144 0, | 160 0, |
145 NULL }, | 161 NULL }, |
146 | 162 |
147 { ngx_string("xslt_types"), | 163 { ngx_string("xslt_types"), |
148 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_1MORE, | 164 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
149 ngx_http_types_slot, | 165 ngx_http_types_slot, |
150 NGX_HTTP_LOC_CONF_OFFSET, | 166 NGX_HTTP_LOC_CONF_OFFSET, |
151 offsetof(ngx_http_xslt_filter_conf_t, keys), | 167 offsetof(ngx_http_xslt_filter_loc_conf_t, types_keys), |
152 &ngx_http_xslt_default_types[0] }, | 168 &ngx_http_xslt_default_types[0] }, |
153 | 169 |
154 ngx_null_command | 170 ngx_null_command |
155 }; | 171 }; |
156 | 172 |
157 | 173 |
158 static ngx_http_module_t ngx_http_xslt_filter_module_ctx = { | 174 static ngx_http_module_t ngx_http_xslt_filter_module_ctx = { |
159 NULL, /* preconfiguration */ | 175 NULL, /* preconfiguration */ |
160 ngx_http_xslt_filter_init, /* postconfiguration */ | 176 ngx_http_xslt_filter_init, /* postconfiguration */ |
161 | 177 |
162 NULL, /* create main configuration */ | 178 ngx_http_xslt_filter_create_main_conf, /* create main configuration */ |
163 NULL, /* init main configuration */ | 179 NULL, /* init main configuration */ |
164 | 180 |
165 NULL, /* create server configuration */ | 181 NULL, /* create server configuration */ |
166 NULL, /* merge server configuration */ | 182 NULL, /* merge server configuration */ |
167 | 183 |
191 | 207 |
192 | 208 |
193 static ngx_int_t | 209 static ngx_int_t |
194 ngx_http_xslt_header_filter(ngx_http_request_t *r) | 210 ngx_http_xslt_header_filter(ngx_http_request_t *r) |
195 { | 211 { |
196 ngx_http_xslt_filter_ctx_t *ctx; | 212 ngx_http_xslt_filter_ctx_t *ctx; |
197 ngx_http_xslt_filter_conf_t *conf; | 213 ngx_http_xslt_filter_loc_conf_t *conf; |
198 | 214 |
199 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 215 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
200 "xslt filter header"); | 216 "xslt filter header"); |
201 | 217 |
202 if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { | 218 if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { |
204 } | 220 } |
205 | 221 |
206 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); | 222 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); |
207 | 223 |
208 if (conf->sheets.nelts == 0 | 224 if (conf->sheets.nelts == 0 |
209 || ngx_http_test_content_type(r, &conf->types_hash) == NULL) | 225 || ngx_http_test_content_type(r, &conf->types) == NULL) |
210 { | 226 { |
211 return ngx_http_next_header_filter(r); | 227 return ngx_http_next_header_filter(r); |
212 } | 228 } |
213 | 229 |
214 ctx = ngx_http_get_module_ctx(r, ngx_http_xslt_filter_module); | 230 ctx = ngx_http_get_module_ctx(r, ngx_http_xslt_filter_module); |
314 ngx_free(b->pos); | 330 ngx_free(b->pos); |
315 return ngx_http_special_response_handler(r, | 331 return ngx_http_special_response_handler(r, |
316 NGX_HTTP_INTERNAL_SERVER_ERROR); | 332 NGX_HTTP_INTERNAL_SERVER_ERROR); |
317 } | 333 } |
318 | 334 |
319 if (ctx->html) { | 335 if (r == r->main) { |
320 r->headers_out.content_type_len = sizeof("text/html") - 1; | 336 r->headers_out.content_length_n = b->last - b->pos; |
321 r->headers_out.content_type.len = sizeof("text/html") - 1; | 337 |
322 r->headers_out.content_type.data = (u_char *) "text/html"; | 338 if (r->headers_out.content_length) { |
323 } | 339 r->headers_out.content_length->hash = 0; |
324 | 340 r->headers_out.content_length = NULL; |
325 r->headers_out.content_length_n = b->last - b->pos; | 341 } |
326 | 342 |
327 if (r->headers_out.content_length) { | 343 ngx_http_clear_last_modified(r); |
328 r->headers_out.content_length->hash = 0; | 344 } |
329 r->headers_out.content_length = NULL; | |
330 } | |
331 | |
332 r->allow_ranges = 1; | |
333 | 345 |
334 rc = ngx_http_next_header_filter(r); | 346 rc = ngx_http_next_header_filter(r); |
335 | 347 |
336 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | 348 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { |
337 ngx_free(b->pos); | 349 ngx_free(b->pos); |
479 ngx_http_xslt_sax_external_subset(void *data, const xmlChar *name, | 491 ngx_http_xslt_sax_external_subset(void *data, const xmlChar *name, |
480 const xmlChar *externalId, const xmlChar *systemId) | 492 const xmlChar *externalId, const xmlChar *systemId) |
481 { | 493 { |
482 ngx_http_xslt_filter_ctx_t *ctx = data; | 494 ngx_http_xslt_filter_ctx_t *ctx = data; |
483 | 495 |
484 xmlDocPtr doc; | 496 xmlDocPtr doc; |
485 xmlDtdPtr dtd; | 497 xmlDtdPtr dtd; |
486 ngx_http_request_t *r; | 498 ngx_http_request_t *r; |
487 ngx_http_xslt_filter_conf_t *conf; | 499 ngx_http_xslt_filter_loc_conf_t *conf; |
488 | 500 |
489 r = ctx->request; | 501 r = ctx->request; |
490 | 502 |
491 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); | 503 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); |
492 | 504 |
509 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 521 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
510 "xmlCopyDtd() failed"); | 522 "xmlCopyDtd() failed"); |
511 return; | 523 return; |
512 } | 524 } |
513 | 525 |
514 dtd->name = xmlStrdup(name); | |
515 | |
516 if (doc->children == NULL) { | 526 if (doc->children == NULL) { |
517 xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd); | 527 xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd); |
518 | 528 |
519 } else { | 529 } else { |
520 xmlAddPrevSibling(doc->children, (xmlNodePtr) dtd); | 530 xmlAddPrevSibling(doc->children, (xmlNodePtr) dtd); |
730 | 740 |
731 static ngx_buf_t * | 741 static ngx_buf_t * |
732 ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, | 742 ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, |
733 ngx_http_xslt_filter_ctx_t *ctx) | 743 ngx_http_xslt_filter_ctx_t *ctx) |
734 { | 744 { |
735 int len, rc; | 745 int len, rc, doc_type; |
736 ngx_buf_t *b; | 746 u_char *type, *encoding; |
737 ngx_uint_t i; | 747 ngx_buf_t *b; |
738 xmlChar *buf; | 748 ngx_uint_t i; |
739 xmlDocPtr doc, res; | 749 xmlChar *buf; |
740 ngx_http_xslt_sheet_t *sheet; | 750 xmlDocPtr doc, res; |
741 ngx_http_xslt_filter_conf_t *conf; | 751 ngx_http_xslt_sheet_t *sheet; |
752 ngx_http_xslt_filter_loc_conf_t *conf; | |
742 | 753 |
743 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); | 754 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); |
744 sheet = conf->sheets.elts; | 755 sheet = conf->sheets.elts; |
745 doc = ctx->doc; | 756 doc = ctx->doc; |
746 | 757 |
774 | 785 |
775 /* reset array elements */ | 786 /* reset array elements */ |
776 ctx->params.nelts = 0; | 787 ctx->params.nelts = 0; |
777 } | 788 } |
778 | 789 |
779 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 790 /* there must be at least one stylesheet */ |
780 "xslt filter doc type: %d", doc->type); | 791 |
781 | 792 if (r == r->main) { |
782 ctx->html = (doc->type == XML_HTML_DOCUMENT_NODE) ? 1 : 0; | 793 type = ngx_http_xslt_content_type(sheet[i - 1].stylesheet); |
794 | |
795 } else { | |
796 type = NULL; | |
797 } | |
798 | |
799 encoding = ngx_http_xslt_encoding(sheet[i - 1].stylesheet); | |
800 doc_type = doc->type; | |
801 | |
802 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
803 "xslt filter type: %d t:%s e:%s", | |
804 doc_type, type ? type : (u_char *) "(null)", | |
805 encoding ? encoding : (u_char *) "(null)"); | |
783 | 806 |
784 rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet); | 807 rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet); |
785 | 808 |
786 xmlFreeDoc(doc); | 809 xmlFreeDoc(doc); |
787 | 810 |
805 | 828 |
806 b->pos = buf; | 829 b->pos = buf; |
807 b->last = buf + len; | 830 b->last = buf + len; |
808 b->memory = 1; | 831 b->memory = 1; |
809 b->last_buf = 1; | 832 b->last_buf = 1; |
833 | |
834 if (encoding) { | |
835 r->headers_out.charset.len = ngx_strlen(encoding); | |
836 r->headers_out.charset.data = encoding; | |
837 } | |
838 | |
839 if (r != r->main) { | |
840 return b; | |
841 } | |
842 | |
843 if (type) { | |
844 len = ngx_strlen(type); | |
845 | |
846 r->headers_out.content_type_len = len; | |
847 r->headers_out.content_type.len = len; | |
848 r->headers_out.content_type.data = type; | |
849 | |
850 } else if (doc_type == XML_HTML_DOCUMENT_NODE) { | |
851 | |
852 r->headers_out.content_type_len = sizeof("text/html") - 1; | |
853 r->headers_out.content_type.len = sizeof("text/html") - 1; | |
854 r->headers_out.content_type.data = (u_char *) "text/html"; | |
855 } | |
810 | 856 |
811 return b; | 857 return b; |
812 } | 858 } |
813 | 859 |
814 | 860 |
904 | 950 |
905 return NGX_OK; | 951 return NGX_OK; |
906 } | 952 } |
907 | 953 |
908 | 954 |
955 static u_char * | |
956 ngx_http_xslt_content_type(xsltStylesheetPtr s) | |
957 { | |
958 u_char *type; | |
959 | |
960 if (s->mediaType) { | |
961 return s->mediaType; | |
962 } | |
963 | |
964 for (s = s->imports; s; s = s->next) { | |
965 | |
966 type = ngx_http_xslt_content_type(s); | |
967 | |
968 if (type) { | |
969 return type; | |
970 } | |
971 } | |
972 | |
973 return NULL; | |
974 } | |
975 | |
976 | |
977 static u_char * | |
978 ngx_http_xslt_encoding(xsltStylesheetPtr s) | |
979 { | |
980 u_char *encoding; | |
981 | |
982 if (s->encoding) { | |
983 return s->encoding; | |
984 } | |
985 | |
986 for (s = s->imports; s; s = s->next) { | |
987 | |
988 encoding = ngx_http_xslt_encoding(s); | |
989 | |
990 if (encoding) { | |
991 return encoding; | |
992 } | |
993 } | |
994 | |
995 return NULL; | |
996 } | |
997 | |
998 | |
909 static void | 999 static void |
910 ngx_http_xslt_cleanup(void *data) | 1000 ngx_http_xslt_cleanup(void *data) |
911 { | 1001 { |
912 ngx_free(data); | 1002 ngx_free(data); |
913 } | 1003 } |
914 | 1004 |
915 | 1005 |
916 static char * | 1006 static char * |
917 ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1007 ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
918 { | 1008 { |
919 ngx_http_xslt_filter_conf_t *xlcf = conf; | 1009 ngx_http_xslt_filter_loc_conf_t *xlcf = conf; |
920 | 1010 |
921 ngx_str_t *value; | 1011 ngx_str_t *value; |
1012 ngx_uint_t i; | |
1013 ngx_pool_cleanup_t *cln; | |
1014 ngx_http_xslt_file_t *file; | |
1015 ngx_http_xslt_filter_main_conf_t *xmcf; | |
922 | 1016 |
923 if (xlcf->dtd) { | 1017 if (xlcf->dtd) { |
924 return "is duplicate"; | 1018 return "is duplicate"; |
925 } | 1019 } |
926 | 1020 |
927 value = cf->args->elts; | 1021 value = cf->args->elts; |
1022 | |
1023 xmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_xslt_filter_module); | |
1024 | |
1025 file = xmcf->dtd_files.elts; | |
1026 for (i = 0; i < xmcf->dtd_files.nelts; i++) { | |
1027 if (ngx_strcmp(file[i].name, &value[1].data) == 0) { | |
1028 xlcf->dtd = file[i].data; | |
1029 return NGX_CONF_OK; | |
1030 } | |
1031 } | |
1032 | |
1033 cln = ngx_pool_cleanup_add(cf->pool, 0); | |
1034 if (cln == NULL) { | |
1035 return NGX_CONF_ERROR; | |
1036 } | |
928 | 1037 |
929 xlcf->dtd = xmlParseDTD(NULL, (xmlChar *) value[1].data); | 1038 xlcf->dtd = xmlParseDTD(NULL, (xmlChar *) value[1].data); |
930 | 1039 |
931 if (xlcf->dtd == NULL) { | 1040 if (xlcf->dtd == NULL) { |
932 ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "xmlParseDTD() failed"); | 1041 ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "xmlParseDTD() failed"); |
933 return NGX_CONF_ERROR; | 1042 return NGX_CONF_ERROR; |
934 } | 1043 } |
935 | 1044 |
1045 cln->handler = ngx_http_xslt_cleanup_dtd; | |
1046 cln->data = xlcf->dtd; | |
1047 | |
1048 file = ngx_array_push(&xmcf->dtd_files); | |
1049 if (file == NULL) { | |
1050 return NGX_CONF_ERROR; | |
1051 } | |
1052 | |
1053 file->name = value[1].data; | |
1054 file->data = xlcf->dtd; | |
1055 | |
936 return NGX_CONF_OK; | 1056 return NGX_CONF_OK; |
937 } | 1057 } |
938 | 1058 |
939 | 1059 |
940 | 1060 |
941 static char * | 1061 static char * |
942 ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1062 ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
943 { | 1063 { |
944 ngx_http_xslt_filter_conf_t *xlcf = conf; | 1064 ngx_http_xslt_filter_loc_conf_t *xlcf = conf; |
945 | 1065 |
946 ngx_str_t *value; | 1066 ngx_str_t *value; |
947 ngx_uint_t i, n; | 1067 ngx_uint_t i, n; |
948 ngx_pool_cleanup_t *cln; | 1068 ngx_pool_cleanup_t *cln; |
949 ngx_http_xslt_sheet_t *sheet; | 1069 ngx_http_xslt_file_t *file; |
950 ngx_http_xslt_param_t *param; | 1070 ngx_http_xslt_sheet_t *sheet; |
951 ngx_http_script_compile_t sc; | 1071 ngx_http_xslt_param_t *param; |
1072 ngx_http_script_compile_t sc; | |
1073 ngx_http_xslt_filter_main_conf_t *xmcf; | |
952 | 1074 |
953 value = cf->args->elts; | 1075 value = cf->args->elts; |
954 | 1076 |
955 if (xlcf->sheets.elts == NULL) { | 1077 if (xlcf->sheets.elts == NULL) { |
956 if (ngx_array_init(&xlcf->sheets, cf->pool, 1, | 1078 if (ngx_array_init(&xlcf->sheets, cf->pool, 1, |
970 | 1092 |
971 if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) { | 1093 if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) { |
972 return NGX_CONF_ERROR; | 1094 return NGX_CONF_ERROR; |
973 } | 1095 } |
974 | 1096 |
1097 xmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_xslt_filter_module); | |
1098 | |
1099 file = xmcf->sheet_files.elts; | |
1100 for (i = 0; i < xmcf->sheet_files.nelts; i++) { | |
1101 if (ngx_strcmp(file[i].name, &value[1].data) == 0) { | |
1102 sheet->stylesheet = file[i].data; | |
1103 goto found; | |
1104 } | |
1105 } | |
1106 | |
975 cln = ngx_pool_cleanup_add(cf->pool, 0); | 1107 cln = ngx_pool_cleanup_add(cf->pool, 0); |
976 if (cln == NULL) { | 1108 if (cln == NULL) { |
977 return NGX_CONF_ERROR; | 1109 return NGX_CONF_ERROR; |
978 } | 1110 } |
979 | 1111 |
985 return NGX_CONF_ERROR; | 1117 return NGX_CONF_ERROR; |
986 } | 1118 } |
987 | 1119 |
988 cln->handler = ngx_http_xslt_cleanup_stylesheet; | 1120 cln->handler = ngx_http_xslt_cleanup_stylesheet; |
989 cln->data = sheet->stylesheet; | 1121 cln->data = sheet->stylesheet; |
1122 | |
1123 file = ngx_array_push(&xmcf->sheet_files); | |
1124 if (file == NULL) { | |
1125 return NGX_CONF_ERROR; | |
1126 } | |
1127 | |
1128 file->name = value[1].data; | |
1129 file->data = sheet->stylesheet; | |
1130 | |
1131 found: | |
990 | 1132 |
991 n = cf->args->nelts; | 1133 n = cf->args->nelts; |
992 | 1134 |
993 if (n == 2) { | 1135 if (n == 2) { |
994 return NGX_CONF_OK; | 1136 return NGX_CONF_OK; |
1029 return NGX_CONF_OK; | 1171 return NGX_CONF_OK; |
1030 } | 1172 } |
1031 | 1173 |
1032 | 1174 |
1033 static void | 1175 static void |
1176 ngx_http_xslt_cleanup_dtd(void *data) | |
1177 { | |
1178 xmlFreeDtd(data); | |
1179 } | |
1180 | |
1181 | |
1182 static void | |
1034 ngx_http_xslt_cleanup_stylesheet(void *data) | 1183 ngx_http_xslt_cleanup_stylesheet(void *data) |
1035 { | 1184 { |
1036 xsltStylesheetPtr stylesheet = data; | 1185 xsltFreeStylesheet(data); |
1037 | 1186 } |
1038 xsltFreeStylesheet(stylesheet); | 1187 |
1039 } | 1188 |
1040 | 1189 static void * |
1190 ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf) | |
1191 { | |
1192 ngx_http_xslt_filter_main_conf_t *conf; | |
1193 | |
1194 conf = ngx_palloc(cf->pool, sizeof(ngx_http_xslt_filter_main_conf_t)); | |
1195 if (conf == NULL) { | |
1196 return NGX_CONF_ERROR; | |
1197 } | |
1198 | |
1199 if (ngx_array_init(&conf->dtd_files, cf->pool, 1, | |
1200 sizeof(ngx_http_xslt_file_t)) | |
1201 != NGX_OK) | |
1202 { | |
1203 return NULL; | |
1204 } | |
1205 | |
1206 if (ngx_array_init(&conf->sheet_files, cf->pool, 1, | |
1207 sizeof(ngx_http_xslt_file_t)) | |
1208 != NGX_OK) | |
1209 { | |
1210 return NULL; | |
1211 } | |
1212 | |
1213 return conf; | |
1214 } | |
1041 | 1215 |
1042 | 1216 |
1043 static void * | 1217 static void * |
1044 ngx_http_xslt_filter_create_conf(ngx_conf_t *cf) | 1218 ngx_http_xslt_filter_create_conf(ngx_conf_t *cf) |
1045 { | 1219 { |
1046 ngx_http_xslt_filter_conf_t *conf; | 1220 ngx_http_xslt_filter_loc_conf_t *conf; |
1047 | 1221 |
1048 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_xslt_filter_conf_t)); | 1222 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_xslt_filter_loc_conf_t)); |
1049 if (conf == NULL) { | 1223 if (conf == NULL) { |
1050 return NGX_CONF_ERROR; | 1224 return NGX_CONF_ERROR; |
1051 } | 1225 } |
1052 | 1226 |
1053 /* | 1227 /* |
1054 * set by ngx_pcalloc(): | 1228 * set by ngx_pcalloc(): |
1055 * | 1229 * |
1056 * conf->dtd | 1230 * conf->dtd = NULL; |
1057 * conf->sheets | 1231 * conf->sheets = { NULL }; |
1232 * conf->types = { NULL }; | |
1233 * conf->types_keys = NULL; | |
1058 */ | 1234 */ |
1059 | 1235 |
1060 return conf; | 1236 return conf; |
1061 } | 1237 } |
1062 | 1238 |
1063 | 1239 |
1064 static char * | 1240 static char * |
1065 ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child) | 1241 ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
1066 { | 1242 { |
1067 ngx_http_xslt_filter_conf_t *prev = parent; | 1243 ngx_http_xslt_filter_loc_conf_t *prev = parent; |
1068 ngx_http_xslt_filter_conf_t *conf = child; | 1244 ngx_http_xslt_filter_loc_conf_t *conf = child; |
1069 | 1245 |
1070 if (conf->dtd == NULL) { | 1246 if (conf->dtd == NULL) { |
1071 conf->dtd = prev->dtd; | 1247 conf->dtd = prev->dtd; |
1072 } | 1248 } |
1073 | 1249 |
1074 if (conf->sheets.nelts == 0) { | 1250 if (conf->sheets.nelts == 0) { |
1075 conf->sheets = prev->sheets; | 1251 conf->sheets = prev->sheets; |
1076 } | 1252 } |
1077 | 1253 |
1078 if (ngx_http_merge_types(cf, conf->keys, &conf->types_hash, prev->keys, | 1254 if (ngx_http_merge_types(cf, conf->types_keys, &conf->types, |
1079 &prev->types_hash, ngx_http_xslt_default_types) | 1255 prev->types_keys, &prev->types, |
1256 ngx_http_xslt_default_types) | |
1080 != NGX_OK) | 1257 != NGX_OK) |
1081 { | 1258 { |
1082 return NGX_CONF_ERROR; | 1259 return NGX_CONF_ERROR; |
1083 } | 1260 } |
1084 | 1261 |