Mercurial > hg > nginx
annotate src/http/modules/ngx_http_xslt_filter_module.c @ 2156:0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 05 Aug 2008 19:05:15 +0000 |
parents | 4f48a2765da0 |
children | 18e85d78fb0c |
rev | line source |
---|---|
2139 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 #include <libxml/parser.h> | |
12 #include <libxml/tree.h> | |
13 #include <libxslt/xslt.h> | |
14 #include <libxslt/xsltInternals.h> | |
15 #include <libxslt/transform.h> | |
16 #include <libxslt/xsltutils.h> | |
17 | |
18 | |
19 #ifndef NGX_HTTP_XSLT_REUSE_DTD | |
20 #define NGX_HTTP_XSLT_REUSE_DTD 1 | |
21 #endif | |
22 | |
23 | |
24 typedef struct { | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
25 u_char *name; |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
26 void *data; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
27 } ngx_http_xslt_file_t; |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
28 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
29 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
30 typedef struct { |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
31 ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
32 ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
33 } ngx_http_xslt_filter_main_conf_t; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
34 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
35 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
36 typedef struct { |
2139 | 37 ngx_array_t *lengths; |
38 ngx_array_t *values; | |
39 } ngx_http_xslt_param_t; | |
40 | |
41 | |
42 typedef struct { | |
43 xsltStylesheetPtr stylesheet; | |
44 ngx_array_t params; /* ngx_http_xslt_param_t */ | |
45 } ngx_http_xslt_sheet_t; | |
46 | |
47 | |
48 typedef struct { | |
49 xmlDtdPtr dtd; | |
2153
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
50 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ |
2148 | 51 ngx_hash_t types; |
52 ngx_array_t *types_keys; | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
53 } ngx_http_xslt_filter_loc_conf_t; |
2139 | 54 |
55 | |
56 typedef struct { | |
57 xmlDocPtr doc; | |
58 xmlParserCtxtPtr ctxt; | |
59 xmlSAXHandler *sax; | |
60 ngx_http_request_t *request; | |
61 ngx_array_t params; | |
2153
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
62 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
63 ngx_uint_t done; /* unsigned done:1; */ |
2139 | 64 } ngx_http_xslt_filter_ctx_t; |
65 | |
66 | |
67 static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r, | |
68 ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b); | |
69 static ngx_int_t ngx_http_xslt_filter_internal_error(ngx_http_request_t *r); | |
70 static ngx_int_t ngx_http_xslt_add_chunk(ngx_http_request_t *r, | |
71 ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b); | |
72 | |
73 | |
74 static void ngx_http_xslt_sax_start_document(void *data); | |
75 static void ngx_http_xslt_sax_end_document(void *data); | |
76 static void ngx_http_xslt_sax_internal_subset(void *data, const xmlChar *name, | |
77 const xmlChar *externalId, const xmlChar *systemId); | |
78 static void ngx_http_xslt_sax_external_subset(void *data, const xmlChar *name, | |
79 const xmlChar *externalId, const xmlChar *systemId); | |
80 static void ngx_http_xslt_sax_entity_decl(void *data, const xmlChar *name, | |
81 int type, const xmlChar *publicId, const xmlChar *systemId, | |
82 xmlChar *content); | |
83 static void ngx_http_xslt_sax_attribute_decl(void *data, const xmlChar *elem, | |
84 const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, | |
85 xmlEnumerationPtr tree); | |
86 static void ngx_http_xslt_sax_element_decl(void *data, const xmlChar * name, | |
87 int type, xmlElementContentPtr content); | |
88 static void ngx_http_xslt_sax_notation_decl(void *data, const xmlChar *name, | |
89 const xmlChar *publicId, const xmlChar *systemId); | |
90 static void ngx_http_xslt_sax_unparsed_entity_decl(void *data, | |
91 const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, | |
92 const xmlChar *notationName); | |
93 static void ngx_http_xslt_sax_start_element(void *data, | |
94 const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, | |
95 int nb_namespaces, const xmlChar **namespaces, int nb_attributes, | |
96 int nb_defaulted, const xmlChar **attributes); | |
97 static void ngx_http_xslt_sax_end_element(void *data, | |
98 const xmlChar * localname ATTRIBUTE_UNUSED, | |
99 const xmlChar * prefix ATTRIBUTE_UNUSED, | |
100 const xmlChar * URI ATTRIBUTE_UNUSED); | |
101 static void ngx_http_xslt_sax_characters(void *data, const xmlChar *p, int len); | |
102 static void ngx_http_xslt_sax_cdata_block(void *data, const xmlChar *p, | |
103 int len); | |
104 static xmlEntityPtr ngx_http_xslt_sax_get_entity(void *data, | |
105 const xmlChar *name); | |
106 static xmlEntityPtr ngx_http_xslt_sax_get_parameter_entity(void *data, | |
107 const xmlChar *name); | |
108 static xmlParserInputPtr ngx_http_xslt_sax_resolve_entity(void *data, | |
109 const xmlChar *publicId, const xmlChar *systemId); | |
110 static void ngx_http_xslt_sax_reference(void *data, const xmlChar *name); | |
111 static void ngx_http_xslt_sax_comment(void *data, const xmlChar *value); | |
112 static void ngx_http_xslt_sax_processing_instruction(void *data, | |
113 const xmlChar *target, const xmlChar *pidata); | |
114 static int ngx_http_xslt_sax_is_standalone(void *data); | |
115 static int ngx_http_xslt_sax_has_internal_subset(void *data); | |
116 static int ngx_http_xslt_sax_has_external_subset(void *data); | |
117 static void ngx_cdecl ngx_http_xslt_sax_error(void *data, const char *msg, ...); | |
118 | |
119 | |
120 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, | |
121 ngx_http_xslt_filter_ctx_t *ctx); | |
122 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, | |
123 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); | |
2153
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
124 static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s); |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
125 static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s); |
2139 | 126 static void ngx_http_xslt_cleanup(void *data); |
127 | |
128 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, | |
129 void *conf); | |
130 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, | |
131 void *conf); | |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
132 static void ngx_http_xslt_cleanup_dtd(void *data); |
2139 | 133 static void ngx_http_xslt_cleanup_stylesheet(void *data); |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
134 static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf); |
2139 | 135 static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf); |
136 static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, | |
137 void *child); | |
138 static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf); | |
139 | |
140 | |
141 ngx_str_t ngx_http_xslt_default_types[] = { | |
142 ngx_string("text/xml"), | |
143 ngx_null_string | |
144 }; | |
145 | |
146 | |
147 static ngx_command_t ngx_http_xslt_filter_commands[] = { | |
148 | |
149 { ngx_string("xml_entities"), | |
2150
50cede290146
fix xslt module context levels
Igor Sysoev <igor@sysoev.ru>
parents:
2148
diff
changeset
|
150 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
2139 | 151 ngx_http_xslt_entities, |
152 NGX_HTTP_LOC_CONF_OFFSET, | |
153 0, | |
154 NULL }, | |
155 | |
156 { ngx_string("xslt_stylesheet"), | |
2151
c8331f70d799
xslt_stylesheet should be valid for location only
Igor Sysoev <igor@sysoev.ru>
parents:
2150
diff
changeset
|
157 NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
2139 | 158 ngx_http_xslt_stylesheet, |
159 NGX_HTTP_LOC_CONF_OFFSET, | |
160 0, | |
161 NULL }, | |
162 | |
163 { ngx_string("xslt_types"), | |
2150
50cede290146
fix xslt module context levels
Igor Sysoev <igor@sysoev.ru>
parents:
2148
diff
changeset
|
164 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
2139 | 165 ngx_http_types_slot, |
166 NGX_HTTP_LOC_CONF_OFFSET, | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
167 offsetof(ngx_http_xslt_filter_loc_conf_t, types_keys), |
2139 | 168 &ngx_http_xslt_default_types[0] }, |
169 | |
170 ngx_null_command | |
171 }; | |
172 | |
173 | |
174 static ngx_http_module_t ngx_http_xslt_filter_module_ctx = { | |
175 NULL, /* preconfiguration */ | |
176 ngx_http_xslt_filter_init, /* postconfiguration */ | |
177 | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
178 ngx_http_xslt_filter_create_main_conf, /* create main configuration */ |
2139 | 179 NULL, /* init main configuration */ |
180 | |
181 NULL, /* create server configuration */ | |
182 NULL, /* merge server configuration */ | |
183 | |
184 ngx_http_xslt_filter_create_conf, /* create location configuration */ | |
185 ngx_http_xslt_filter_merge_conf /* merge location configuration */ | |
186 }; | |
187 | |
188 | |
189 ngx_module_t ngx_http_xslt_filter_module = { | |
190 NGX_MODULE_V1, | |
191 &ngx_http_xslt_filter_module_ctx, /* module context */ | |
192 ngx_http_xslt_filter_commands, /* module directives */ | |
193 NGX_HTTP_MODULE, /* module type */ | |
194 NULL, /* init master */ | |
195 NULL, /* init module */ | |
196 NULL, /* init process */ | |
197 NULL, /* init thread */ | |
198 NULL, /* exit thread */ | |
199 NULL, /* exit process */ | |
200 NULL, /* exit master */ | |
201 NGX_MODULE_V1_PADDING | |
202 }; | |
203 | |
204 | |
205 static ngx_http_output_header_filter_pt ngx_http_next_header_filter; | |
206 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; | |
207 | |
208 | |
209 static ngx_int_t | |
210 ngx_http_xslt_header_filter(ngx_http_request_t *r) | |
211 { | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
212 ngx_http_xslt_filter_ctx_t *ctx; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
213 ngx_http_xslt_filter_loc_conf_t *conf; |
2139 | 214 |
215 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
216 "xslt filter header"); | |
217 | |
218 if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { | |
219 return ngx_http_next_header_filter(r); | |
220 } | |
221 | |
222 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); | |
223 | |
224 if (conf->sheets.nelts == 0 | |
2148 | 225 || ngx_http_test_content_type(r, &conf->types) == NULL) |
2139 | 226 { |
227 return ngx_http_next_header_filter(r); | |
228 } | |
229 | |
230 ctx = ngx_http_get_module_ctx(r, ngx_http_xslt_filter_module); | |
231 | |
232 if (ctx) { | |
233 return ngx_http_next_header_filter(r); | |
234 } | |
235 | |
236 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_xslt_filter_ctx_t)); | |
237 if (ctx == NULL) { | |
238 return NGX_ERROR; | |
239 } | |
240 | |
241 ngx_http_set_ctx(r, ctx, ngx_http_xslt_filter_module); | |
242 | |
243 r->main_filter_need_in_memory = 1; | |
244 | |
245 return NGX_OK; | |
246 } | |
247 | |
248 | |
249 static ngx_int_t | |
250 ngx_http_xslt_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
251 { | |
252 ngx_chain_t *cl; | |
253 ngx_http_xslt_filter_ctx_t *ctx; | |
254 | |
255 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
256 "xslt filter body"); | |
257 | |
258 if (in == NULL) { | |
259 return ngx_http_next_body_filter(r, in); | |
260 } | |
261 | |
262 ctx = ngx_http_get_module_ctx(r, ngx_http_xslt_filter_module); | |
263 | |
264 if (ctx == NULL || ctx->done) { | |
265 return ngx_http_next_body_filter(r, in); | |
266 } | |
267 | |
268 for (cl = in; cl; cl = cl->next) { | |
269 | |
270 if (ngx_http_xslt_add_chunk(r, ctx, cl->buf) != NGX_OK) { | |
271 | |
272 if (ctx->ctxt->myDoc){ | |
273 | |
274 #if (NGX_HTTP_XSLT_REUSE_DTD) | |
275 ctx->ctxt->myDoc->extSubset = NULL; | |
276 #endif | |
277 xmlFreeDoc(ctx->ctxt->myDoc); | |
278 } | |
279 | |
280 xmlFreeParserCtxt(ctx->ctxt); | |
281 | |
282 return ngx_http_xslt_send(r, ctx, NULL); | |
283 } | |
284 | |
285 if (cl->buf->last_buf) { | |
286 | |
287 ctx->doc = ctx->ctxt->myDoc; | |
288 | |
289 #if (NGX_HTTP_XSLT_REUSE_DTD) | |
290 ctx->doc->extSubset = NULL; | |
291 #endif | |
292 | |
293 xmlFreeParserCtxt(ctx->ctxt); | |
294 | |
295 if (ctx->ctxt->wellFormed) { | |
296 return ngx_http_xslt_send(r, ctx, | |
297 ngx_http_xslt_apply_stylesheet(r, ctx)); | |
298 } | |
299 | |
300 xmlFreeDoc(ctx->doc); | |
301 | |
302 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
303 "not well formed XML document"); | |
304 | |
305 return ngx_http_xslt_send(r, ctx, NULL); | |
306 } | |
307 } | |
308 | |
309 return NGX_OK; | |
310 } | |
311 | |
312 | |
313 static ngx_int_t | |
314 ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, | |
315 ngx_buf_t *b) | |
316 { | |
317 ngx_int_t rc; | |
318 ngx_chain_t out; | |
319 ngx_pool_cleanup_t *cln; | |
320 | |
321 ctx->done = 1; | |
322 | |
323 if (b == NULL) { | |
324 return ngx_http_xslt_filter_internal_error(r); | |
325 } | |
326 | |
327 cln = ngx_pool_cleanup_add(r->pool, 0); | |
328 | |
329 if (cln == NULL) { | |
330 ngx_free(b->pos); | |
331 return ngx_http_special_response_handler(r, | |
332 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
333 } | |
334 | |
335 r->headers_out.content_length_n = b->last - b->pos; | |
336 | |
337 if (r->headers_out.content_length) { | |
338 r->headers_out.content_length->hash = 0; | |
339 r->headers_out.content_length = NULL; | |
340 } | |
341 | |
342 r->allow_ranges = 1; | |
343 | |
344 rc = ngx_http_next_header_filter(r); | |
345 | |
346 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
347 ngx_free(b->pos); | |
348 return rc; | |
349 } | |
350 | |
351 cln->handler = ngx_http_xslt_cleanup; | |
352 cln->data = b->pos; | |
353 | |
354 out.buf = b; | |
355 out.next = NULL; | |
356 | |
357 return ngx_http_next_body_filter(r, &out); | |
358 } | |
359 | |
360 | |
361 static ngx_int_t | |
362 ngx_http_xslt_filter_internal_error(ngx_http_request_t *r) | |
363 { | |
364 ngx_int_t rc; | |
365 | |
366 /* clear the modules contexts */ | |
367 ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module); | |
368 | |
369 rc = ngx_http_special_response_handler(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
370 | |
371 /* NGX_ERROR resets any pending data */ | |
372 | |
373 return (rc == NGX_OK) ? NGX_ERROR : rc; | |
374 } | |
375 | |
376 | |
377 static ngx_int_t | |
378 ngx_http_xslt_add_chunk(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, | |
379 ngx_buf_t *b) | |
380 { | |
381 int err; | |
382 xmlSAXHandler *sax; | |
383 xmlParserCtxtPtr ctxt; | |
384 | |
385 if (ctx->ctxt == NULL) { | |
386 | |
387 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL); | |
388 if (ctxt == NULL) { | |
389 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
390 "xmlCreatePushParserCtxt() failed"); | |
391 return NGX_ERROR; | |
392 } | |
393 | |
394 ctx->sax = ngx_palloc(r->pool, sizeof(xmlSAXHandler)); | |
395 if (ctx->sax == NULL) { | |
396 return NGX_ERROR; | |
397 } | |
398 | |
399 sax = ctxt->sax; | |
400 | |
401 ngx_memcpy(ctx->sax, sax, sizeof(xmlSAXHandler)); | |
402 | |
403 sax->startDocument = ngx_http_xslt_sax_start_document; | |
404 sax->endDocument = ngx_http_xslt_sax_end_document; | |
405 | |
406 sax->internalSubset = ngx_http_xslt_sax_internal_subset; | |
407 sax->externalSubset = ngx_http_xslt_sax_external_subset; | |
408 sax->entityDecl = ngx_http_xslt_sax_entity_decl; | |
409 sax->attributeDecl = ngx_http_xslt_sax_attribute_decl; | |
410 sax->elementDecl = ngx_http_xslt_sax_element_decl; | |
411 sax->notationDecl = ngx_http_xslt_sax_notation_decl; | |
412 sax->unparsedEntityDecl = ngx_http_xslt_sax_unparsed_entity_decl; | |
413 sax->setDocumentLocator = NULL; | |
414 | |
415 sax->startElementNs = ngx_http_xslt_sax_start_element; | |
416 sax->endElementNs = ngx_http_xslt_sax_end_element; | |
417 | |
418 sax->characters = ngx_http_xslt_sax_characters; | |
419 sax->ignorableWhitespace = ngx_http_xslt_sax_characters; | |
420 sax->cdataBlock = ngx_http_xslt_sax_cdata_block; | |
421 sax->getEntity = ngx_http_xslt_sax_get_entity; | |
422 sax->resolveEntity = ngx_http_xslt_sax_resolve_entity; | |
423 sax->getParameterEntity = ngx_http_xslt_sax_get_parameter_entity; | |
424 sax->reference = ngx_http_xslt_sax_reference; | |
425 sax->comment = ngx_http_xslt_sax_comment; | |
426 sax->processingInstruction = ngx_http_xslt_sax_processing_instruction; | |
427 | |
428 sax->isStandalone = ngx_http_xslt_sax_is_standalone; | |
429 sax->hasInternalSubset = ngx_http_xslt_sax_has_internal_subset; | |
430 sax->hasExternalSubset = ngx_http_xslt_sax_has_external_subset; | |
431 | |
432 sax->warning = NULL; | |
433 sax->error = ngx_http_xslt_sax_error; | |
434 sax->fatalError = ngx_http_xslt_sax_error; | |
435 | |
436 ctxt->userData = ctx; | |
437 | |
438 ctxt->replaceEntities = 1; | |
439 ctxt->loadsubset = 1; | |
440 | |
441 ctx->ctxt = ctxt; | |
442 ctx->request = r; | |
443 } | |
444 | |
445 err = xmlParseChunk(ctx->ctxt, (char *) b->pos, | |
446 (int) (b->last - b->pos), b->last_buf); | |
447 | |
448 if (err == 0) { | |
449 b->pos = b->last; | |
450 return NGX_OK; | |
451 } | |
452 | |
453 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
454 "xmlParseChunk() failed, error:%d", err); | |
455 | |
456 return NGX_ERROR; | |
457 } | |
458 | |
459 | |
460 static void | |
461 ngx_http_xslt_sax_start_document(void *data) | |
462 { | |
463 ngx_http_xslt_filter_ctx_t *ctx = data; | |
464 | |
465 ctx->sax->startDocument(ctx->ctxt); | |
466 } | |
467 | |
468 | |
469 static void | |
470 ngx_http_xslt_sax_end_document(void *data) | |
471 { | |
472 ngx_http_xslt_filter_ctx_t *ctx = data; | |
473 | |
474 ctx->sax->endDocument(ctx->ctxt); | |
475 } | |
476 | |
477 | |
478 static void | |
479 ngx_http_xslt_sax_internal_subset(void *data, const xmlChar *name, | |
480 const xmlChar *externalId, const xmlChar *systemId) | |
481 { | |
482 ngx_http_xslt_filter_ctx_t *ctx = data; | |
483 | |
484 ctx->sax->internalSubset(ctx->ctxt, name, externalId, systemId); | |
485 } | |
486 | |
487 | |
488 static void | |
489 ngx_http_xslt_sax_external_subset(void *data, const xmlChar *name, | |
490 const xmlChar *externalId, const xmlChar *systemId) | |
491 { | |
492 ngx_http_xslt_filter_ctx_t *ctx = data; | |
493 | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
494 xmlDocPtr doc; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
495 xmlDtdPtr dtd; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
496 ngx_http_request_t *r; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
497 ngx_http_xslt_filter_loc_conf_t *conf; |
2139 | 498 |
499 r = ctx->request; | |
500 | |
501 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); | |
502 | |
503 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
504 "xslt filter extSubset: \"%s\" \"%s\" \"%s\"", | |
505 name ? name : (xmlChar *) "", | |
506 externalId ? externalId : (xmlChar *) "", | |
507 systemId ? systemId : (xmlChar *) ""); | |
508 | |
509 doc = ctx->ctxt->myDoc; | |
510 | |
511 #if (NGX_HTTP_XSLT_REUSE_DTD) | |
512 | |
513 dtd = conf->dtd; | |
514 | |
515 #else | |
516 | |
517 dtd = xmlCopyDtd(conf->dtd); | |
518 if (dtd == NULL) { | |
519 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
520 "xmlCopyDtd() failed"); | |
521 return; | |
522 } | |
523 | |
524 if (doc->children == NULL) { | |
525 xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd); | |
526 | |
527 } else { | |
528 xmlAddPrevSibling(doc->children, (xmlNodePtr) dtd); | |
529 } | |
530 | |
531 #endif | |
532 | |
533 doc->extSubset = dtd; | |
534 } | |
535 | |
536 | |
537 static void | |
538 ngx_http_xslt_sax_entity_decl(void *data, const xmlChar *name, int type, | |
539 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) | |
540 { | |
541 ngx_http_xslt_filter_ctx_t *ctx = data; | |
542 | |
543 ctx->sax->entityDecl(ctx->ctxt, name, type, publicId, systemId, content); | |
544 } | |
545 | |
546 | |
547 static void | |
548 ngx_http_xslt_sax_attribute_decl(void *data, const xmlChar *elem, | |
549 const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, | |
550 xmlEnumerationPtr tree) | |
551 { | |
552 ngx_http_xslt_filter_ctx_t *ctx = data; | |
553 | |
554 ctx->sax->attributeDecl(ctx->ctxt, elem, fullname, type, def, defaultValue, | |
555 tree); | |
556 } | |
557 | |
558 | |
559 static void | |
560 ngx_http_xslt_sax_element_decl(void *data, const xmlChar * name, int type, | |
561 xmlElementContentPtr content) | |
562 { | |
563 ngx_http_xslt_filter_ctx_t *ctx = data; | |
564 | |
565 ctx->sax->elementDecl(ctx->ctxt, name, type, content); | |
566 } | |
567 | |
568 | |
569 static void | |
570 ngx_http_xslt_sax_notation_decl(void *data, const xmlChar *name, | |
571 const xmlChar *publicId, const xmlChar *systemId) | |
572 { | |
573 ngx_http_xslt_filter_ctx_t *ctx = data; | |
574 | |
575 ctx->sax->notationDecl(ctx->ctxt, name, publicId, systemId); | |
576 } | |
577 | |
578 | |
579 static void | |
580 ngx_http_xslt_sax_unparsed_entity_decl(void *data, const xmlChar *name, | |
581 const xmlChar *publicId, const xmlChar *systemId, | |
582 const xmlChar *notationName) | |
583 { | |
584 ngx_http_xslt_filter_ctx_t *ctx = data; | |
585 | |
586 ctx->sax->unparsedEntityDecl(ctx->ctxt, name, publicId, systemId, | |
587 notationName); | |
588 } | |
589 | |
590 | |
591 static void | |
592 ngx_http_xslt_sax_start_element(void *data, const xmlChar *localname, | |
593 const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, | |
594 const xmlChar **namespaces, int nb_attributes, int nb_defaulted, | |
595 const xmlChar **attributes) | |
596 { | |
597 ngx_http_xslt_filter_ctx_t *ctx = data; | |
598 | |
599 ctx->sax->startElementNs(ctx->ctxt, localname, prefix, URI, nb_namespaces, | |
600 namespaces, nb_attributes, nb_defaulted, attributes); | |
601 } | |
602 | |
603 | |
604 static void | |
605 ngx_http_xslt_sax_end_element(void *data, | |
606 const xmlChar * localname ATTRIBUTE_UNUSED, | |
607 const xmlChar * prefix ATTRIBUTE_UNUSED, | |
608 const xmlChar * URI ATTRIBUTE_UNUSED) | |
609 { | |
610 ngx_http_xslt_filter_ctx_t *ctx = data; | |
611 | |
612 ctx->sax->endElementNs(ctx->ctxt, localname, prefix, URI); | |
613 } | |
614 | |
615 | |
616 static void | |
617 ngx_http_xslt_sax_characters(void *data, const xmlChar *p, int len) | |
618 { | |
619 ngx_http_xslt_filter_ctx_t *ctx = data; | |
620 | |
621 ctx->sax->characters(ctx->ctxt, p, len); | |
622 } | |
623 | |
624 | |
625 static void | |
626 ngx_http_xslt_sax_cdata_block(void *data, const xmlChar *p, int len) | |
627 { | |
628 ngx_http_xslt_filter_ctx_t *ctx = data; | |
629 | |
630 ctx->sax->cdataBlock(ctx->ctxt, p, len); | |
631 } | |
632 | |
633 | |
634 static xmlEntityPtr | |
635 ngx_http_xslt_sax_get_entity(void *data, const xmlChar *name) | |
636 { | |
637 ngx_http_xslt_filter_ctx_t *ctx = data; | |
638 | |
639 return ctx->sax->getEntity(ctx->ctxt, name); | |
640 } | |
641 | |
642 | |
643 static xmlEntityPtr | |
644 ngx_http_xslt_sax_get_parameter_entity(void *data, const xmlChar *name) | |
645 { | |
646 ngx_http_xslt_filter_ctx_t *ctx = data; | |
647 | |
648 return ctx->sax->getParameterEntity(ctx->ctxt, name); | |
649 } | |
650 | |
651 | |
652 static xmlParserInputPtr | |
653 ngx_http_xslt_sax_resolve_entity(void *data, const xmlChar *publicId, | |
654 const xmlChar *systemId) | |
655 { | |
656 ngx_http_xslt_filter_ctx_t *ctx = data; | |
657 | |
658 return ctx->sax->resolveEntity(ctx->ctxt, publicId, systemId); | |
659 } | |
660 | |
661 | |
662 static void | |
663 ngx_http_xslt_sax_reference(void *data, const xmlChar *name) | |
664 { | |
665 ngx_http_xslt_filter_ctx_t *ctx = data; | |
666 | |
667 ctx->sax->reference(ctx->ctxt, name); | |
668 } | |
669 | |
670 | |
671 static void | |
672 ngx_http_xslt_sax_comment(void *data, const xmlChar *value) | |
673 { | |
674 ngx_http_xslt_filter_ctx_t *ctx = data; | |
675 | |
676 ctx->sax->comment(ctx->ctxt, value); | |
677 } | |
678 | |
679 | |
680 static void | |
681 ngx_http_xslt_sax_processing_instruction(void *data, const xmlChar *target, | |
682 const xmlChar *pidata) | |
683 { | |
684 ngx_http_xslt_filter_ctx_t *ctx = data; | |
685 | |
686 ctx->sax->processingInstruction(ctx->ctxt, target, pidata); | |
687 } | |
688 | |
689 | |
690 static int | |
691 ngx_http_xslt_sax_is_standalone(void *data) | |
692 { | |
693 ngx_http_xslt_filter_ctx_t *ctx = data; | |
694 | |
695 return ctx->sax->isStandalone(ctx->ctxt); | |
696 } | |
697 | |
698 | |
699 static int | |
700 ngx_http_xslt_sax_has_internal_subset(void *data) | |
701 { | |
702 ngx_http_xslt_filter_ctx_t *ctx = data; | |
703 | |
704 return ctx->sax->hasInternalSubset(ctx->ctxt); | |
705 } | |
706 | |
707 | |
708 static int | |
709 ngx_http_xslt_sax_has_external_subset(void *data) | |
710 { | |
711 ngx_http_xslt_filter_ctx_t *ctx = data; | |
712 | |
713 return ctx->sax->hasExternalSubset(ctx->ctxt); | |
714 } | |
715 | |
716 | |
717 static void ngx_cdecl | |
718 ngx_http_xslt_sax_error(void *data, const char *msg, ...) | |
719 { | |
720 ngx_http_xslt_filter_ctx_t *ctx = data; | |
721 | |
722 size_t n; | |
723 va_list args; | |
724 u_char buf[NGX_MAX_ERROR_STR]; | |
725 | |
726 buf[0] = '\0'; | |
727 | |
728 va_start(args, msg); | |
729 n = (size_t) vsnprintf((char *) buf, NGX_MAX_ERROR_STR, msg, args); | |
730 va_end(args); | |
731 | |
732 while (--n && (buf[n] == CR || buf[n] == LF)) { /* void */ } | |
733 | |
734 ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, | |
735 "libxml2 error: \"%*s\"", n, buf); | |
736 } | |
737 | |
738 | |
739 static ngx_buf_t * | |
740 ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, | |
741 ngx_http_xslt_filter_ctx_t *ctx) | |
742 { | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
743 int len, rc, doc_type; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
744 u_char *type, *encoding; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
745 ngx_buf_t *b; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
746 ngx_uint_t i; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
747 xmlChar *buf; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
748 xmlDocPtr doc, res; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
749 ngx_http_xslt_sheet_t *sheet; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
750 ngx_http_xslt_filter_loc_conf_t *conf; |
2139 | 751 |
752 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module); | |
753 sheet = conf->sheets.elts; | |
754 doc = ctx->doc; | |
755 | |
756 /* preallocate array for 4 params */ | |
757 | |
758 if (ngx_array_init(&ctx->params, r->pool, 4 * 2 + 1, sizeof(char *)) | |
759 != NGX_OK) | |
760 { | |
761 xmlFreeDoc(doc); | |
762 return NULL; | |
763 } | |
764 | |
765 for (i = 0; i < conf->sheets.nelts; i++) { | |
766 | |
767 if (ngx_http_xslt_params(r, ctx, &sheet[i].params) != NGX_OK) { | |
768 xmlFreeDoc(doc); | |
769 return NULL; | |
770 } | |
771 | |
772 res = xsltApplyStylesheet(sheet[i].stylesheet, doc, ctx->params.elts); | |
773 | |
774 xmlFreeDoc(doc); | |
775 | |
776 if (res == NULL) { | |
777 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
778 "xsltApplyStylesheet() failed"); | |
779 return NULL; | |
780 } | |
781 | |
782 doc = res; | |
783 | |
784 /* reset array elements */ | |
785 ctx->params.nelts = 0; | |
786 } | |
787 | |
2153
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
788 /* there must be at least one stylesheet */ |
2139 | 789 |
2153
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
790 type = ngx_http_xslt_content_type(sheet[i - 1].stylesheet); |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
791 encoding = ngx_http_xslt_encoding(sheet[i - 1].stylesheet); |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
792 doc_type = doc->type; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
793 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
794 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
795 "xslt filter type: %d t:%s e:%s", |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
796 doc_type, type ? type : (u_char *) "(null)", |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
797 encoding ? encoding : (u_char *) "(null)"); |
2139 | 798 |
799 rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet); | |
800 | |
801 xmlFreeDoc(doc); | |
802 | |
803 if (rc != 0) { | |
804 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
805 "xsltSaveResultToString() failed"); | |
806 return NULL; | |
807 } | |
808 | |
809 if (len == 0) { | |
810 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
811 "xsltSaveResultToString() returned zero-length result"); | |
812 return NULL; | |
813 } | |
814 | |
815 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); | |
816 if (b == NULL) { | |
817 ngx_free(buf); | |
818 return NULL; | |
819 } | |
820 | |
821 b->pos = buf; | |
822 b->last = buf + len; | |
823 b->memory = 1; | |
824 b->last_buf = 1; | |
825 | |
2153
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
826 if (type) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
827 len = ngx_strlen(type); |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
828 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
829 r->headers_out.content_type_len = len; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
830 r->headers_out.content_type.len = len; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
831 r->headers_out.content_type.data = type; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
832 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
833 } else if (doc_type == XML_HTML_DOCUMENT_NODE) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
834 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
835 r->headers_out.content_type_len = sizeof("text/html") - 1; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
836 r->headers_out.content_type.len = sizeof("text/html") - 1; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
837 r->headers_out.content_type.data = (u_char *) "text/html"; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
838 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
839 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
840 if (encoding) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
841 r->headers_out.charset.len = ngx_strlen(encoding); |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
842 r->headers_out.charset.data = encoding; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
843 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
844 |
2139 | 845 return b; |
846 } | |
847 | |
848 | |
849 static ngx_int_t | |
850 ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, | |
851 ngx_array_t *params) | |
852 { | |
853 u_char *p, *last, *value, *dst, *src, **s; | |
854 size_t len; | |
855 ngx_uint_t i; | |
856 ngx_str_t string; | |
857 ngx_http_xslt_param_t *param; | |
858 | |
859 param = params->elts; | |
860 | |
861 for (i = 0; i < params->nelts; i++) { | |
862 | |
863 if (ngx_http_script_run(r, &string, param[i].lengths->elts, 1, | |
864 param[i].values->elts) | |
865 == NULL) | |
866 { | |
867 return NGX_ERROR; | |
868 } | |
869 | |
870 last = string.data + string.len - 1; | |
871 *last = '\0'; | |
872 | |
873 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
874 "xslt filter param: \"%s\"", string.data); | |
875 | |
876 p = string.data; | |
877 | |
878 while (p && *p) { | |
879 | |
880 value = p; | |
881 p = (u_char *) ngx_strchr(p, '='); | |
882 if (p == NULL) { | |
883 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
884 "invalid libxslt parameter \"%s\"", value); | |
885 return NGX_ERROR; | |
886 } | |
887 *p++ = '\0'; | |
888 | |
889 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
890 "xslt filter param name: \"%s\"", value); | |
891 | |
892 s = ngx_array_push(&ctx->params); | |
893 if (s == NULL) { | |
894 return NGX_ERROR; | |
895 } | |
896 | |
897 *s = value; | |
898 | |
899 value = p; | |
900 p = (u_char *) ngx_strchr(p, ':'); | |
901 | |
902 if (p) { | |
903 len = p - value; | |
904 *p++ = '\0'; | |
905 | |
906 } else { | |
907 len = last - value; | |
908 } | |
909 | |
910 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
911 "xslt filter param value: \"%s\"", value); | |
912 | |
913 dst = value; | |
914 src = value; | |
915 | |
916 ngx_unescape_uri(&dst, &src, len, 0); | |
917 | |
918 *dst = '\0'; | |
919 | |
920 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
921 "xslt filter param unescaped: \"%s\"", value); | |
922 | |
923 s = ngx_array_push(&ctx->params); | |
924 if (s == NULL) { | |
925 return NGX_ERROR; | |
926 } | |
927 | |
928 *s = value; | |
929 } | |
930 } | |
931 | |
932 s = ngx_array_push(&ctx->params); | |
933 if (s == NULL) { | |
934 return NGX_ERROR; | |
935 } | |
936 | |
937 *s = NULL; | |
938 | |
939 return NGX_OK; | |
940 } | |
941 | |
942 | |
2153
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
943 static u_char * |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
944 ngx_http_xslt_content_type(xsltStylesheetPtr s) |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
945 { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
946 u_char *type; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
947 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
948 if (s->mediaType) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
949 return s->mediaType; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
950 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
951 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
952 for (s = s->imports; s; s = s->next) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
953 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
954 type = ngx_http_xslt_content_type(s); |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
955 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
956 if (type) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
957 return type; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
958 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
959 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
960 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
961 return NULL; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
962 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
963 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
964 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
965 static u_char * |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
966 ngx_http_xslt_encoding(xsltStylesheetPtr s) |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
967 { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
968 u_char *encoding; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
969 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
970 if (s->encoding) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
971 return s->encoding; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
972 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
973 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
974 for (s = s->imports; s; s = s->next) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
975 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
976 encoding = ngx_http_xslt_encoding(s); |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
977 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
978 if (encoding) { |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
979 return encoding; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
980 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
981 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
982 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
983 return NULL; |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
984 } |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
985 |
6476e445d6ce
xsl:output's media-type and encoding support
Igor Sysoev <igor@sysoev.ru>
parents:
2152
diff
changeset
|
986 |
2139 | 987 static void |
988 ngx_http_xslt_cleanup(void *data) | |
989 { | |
990 ngx_free(data); | |
991 } | |
992 | |
993 | |
994 static char * | |
995 ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
996 { | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
997 ngx_http_xslt_filter_loc_conf_t *xlcf = conf; |
2139 | 998 |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
999 ngx_str_t *value; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1000 ngx_uint_t i; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1001 ngx_pool_cleanup_t *cln; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1002 ngx_http_xslt_file_t *file; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1003 ngx_http_xslt_filter_main_conf_t *xmcf; |
2139 | 1004 |
1005 if (xlcf->dtd) { | |
1006 return "is duplicate"; | |
1007 } | |
1008 | |
1009 value = cf->args->elts; | |
1010 | |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1011 xmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_xslt_filter_module); |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1012 |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1013 file = xmcf->dtd_files.elts; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1014 for (i = 0; i < xmcf->dtd_files.nelts; i++) { |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1015 if (ngx_strcmp(file[i].name, &value[1].data) == 0) { |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1016 xlcf->dtd = file[i].data; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1017 return NGX_CONF_OK; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1018 } |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1019 } |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1020 |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1021 cln = ngx_pool_cleanup_add(cf->pool, 0); |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1022 if (cln == NULL) { |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1023 return NGX_CONF_ERROR; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1024 } |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1025 |
2139 | 1026 xlcf->dtd = xmlParseDTD(NULL, (xmlChar *) value[1].data); |
1027 | |
1028 if (xlcf->dtd == NULL) { | |
1029 ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "xmlParseDTD() failed"); | |
1030 return NGX_CONF_ERROR; | |
1031 } | |
1032 | |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1033 cln->handler = ngx_http_xslt_cleanup_dtd; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1034 cln->data = xlcf->dtd; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1035 |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1036 file = ngx_array_push(&xmcf->dtd_files); |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1037 if (file == NULL) { |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1038 return NGX_CONF_ERROR; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1039 } |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1040 |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1041 file->name = value[1].data; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1042 file->data = xlcf->dtd; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1043 |
2139 | 1044 return NGX_CONF_OK; |
1045 } | |
1046 | |
1047 | |
1048 | |
1049 static char * | |
1050 ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1051 { | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1052 ngx_http_xslt_filter_loc_conf_t *xlcf = conf; |
2139 | 1053 |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1054 ngx_str_t *value; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1055 ngx_uint_t i, n; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1056 ngx_pool_cleanup_t *cln; |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1057 ngx_http_xslt_file_t *file; |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1058 ngx_http_xslt_sheet_t *sheet; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1059 ngx_http_xslt_param_t *param; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1060 ngx_http_script_compile_t sc; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1061 ngx_http_xslt_filter_main_conf_t *xmcf; |
2139 | 1062 |
1063 value = cf->args->elts; | |
1064 | |
1065 if (xlcf->sheets.elts == NULL) { | |
1066 if (ngx_array_init(&xlcf->sheets, cf->pool, 1, | |
1067 sizeof(ngx_http_xslt_sheet_t)) | |
1068 != NGX_OK) | |
1069 { | |
1070 return NGX_CONF_ERROR; | |
1071 } | |
1072 } | |
1073 | |
1074 sheet = ngx_array_push(&xlcf->sheets); | |
1075 if (sheet == NULL) { | |
1076 return NGX_CONF_ERROR; | |
1077 } | |
1078 | |
1079 ngx_memzero(sheet, sizeof(ngx_http_xslt_sheet_t)); | |
1080 | |
1081 if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) { | |
1082 return NGX_CONF_ERROR; | |
1083 } | |
1084 | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1085 xmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_xslt_filter_module); |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1086 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1087 file = xmcf->sheet_files.elts; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1088 for (i = 0; i < xmcf->sheet_files.nelts; i++) { |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1089 if (ngx_strcmp(file[i].name, &value[1].data) == 0) { |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1090 sheet->stylesheet = file[i].data; |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1091 goto found; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1092 } |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1093 } |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1094 |
2139 | 1095 cln = ngx_pool_cleanup_add(cf->pool, 0); |
1096 if (cln == NULL) { | |
1097 return NGX_CONF_ERROR; | |
1098 } | |
1099 | |
1100 sheet->stylesheet = xsltParseStylesheetFile(value[1].data); | |
1101 if (sheet->stylesheet == NULL) { | |
1102 ngx_conf_log_error(NGX_LOG_ERR, cf, 0, | |
1103 "xsltParseStylesheetFile(\"%s\") failed", | |
1104 value[1].data); | |
1105 return NGX_CONF_ERROR; | |
1106 } | |
1107 | |
1108 cln->handler = ngx_http_xslt_cleanup_stylesheet; | |
1109 cln->data = sheet->stylesheet; | |
1110 | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1111 file = ngx_array_push(&xmcf->sheet_files); |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1112 if (file == NULL) { |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1113 return NGX_CONF_ERROR; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1114 } |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1115 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1116 file->name = value[1].data; |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1117 file->data = sheet->stylesheet; |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1118 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1119 found: |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1120 |
2139 | 1121 n = cf->args->nelts; |
1122 | |
1123 if (n == 2) { | |
1124 return NGX_CONF_OK; | |
1125 } | |
1126 | |
1127 if (ngx_array_init(&sheet->params, cf->pool, n - 2, | |
1128 sizeof(ngx_http_xslt_param_t)) | |
1129 != NGX_OK) | |
1130 { | |
1131 return NGX_CONF_ERROR; | |
1132 } | |
1133 | |
1134 for (i = 2; i < n; i++) { | |
1135 | |
1136 param = ngx_array_push(&sheet->params); | |
1137 if (param == NULL) { | |
1138 return NGX_CONF_ERROR; | |
1139 } | |
1140 | |
1141 param->lengths = NULL; | |
1142 param->values = NULL; | |
1143 | |
1144 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1145 | |
1146 sc.cf = cf; | |
1147 sc.source = &value[i]; | |
1148 sc.lengths = ¶m->lengths; | |
1149 sc.values = ¶m->values; | |
1150 sc.variables = ngx_http_script_variables_count(&value[i]); | |
1151 sc.complete_lengths = 1; | |
1152 sc.complete_values = 1; | |
1153 | |
1154 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1155 return NGX_CONF_ERROR; | |
1156 } | |
1157 } | |
1158 | |
1159 return NGX_CONF_OK; | |
1160 } | |
1161 | |
1162 | |
1163 static void | |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1164 ngx_http_xslt_cleanup_dtd(void *data) |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1165 { |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1166 xmlFreeDtd(data); |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1167 } |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1168 |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1169 |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1170 static void |
2139 | 1171 ngx_http_xslt_cleanup_stylesheet(void *data) |
1172 { | |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1173 xsltFreeStylesheet(data); |
2139 | 1174 } |
1175 | |
1176 | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1177 static void * |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1178 ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf) |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1179 { |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1180 ngx_http_xslt_filter_main_conf_t *conf; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1181 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1182 conf = ngx_palloc(cf->pool, sizeof(ngx_http_xslt_filter_main_conf_t)); |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1183 if (conf == NULL) { |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1184 return NGX_CONF_ERROR; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1185 } |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1186 |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1187 if (ngx_array_init(&conf->dtd_files, cf->pool, 1, |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1188 sizeof(ngx_http_xslt_file_t)) |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1189 != NGX_OK) |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1190 { |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1191 return NULL; |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1192 } |
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1193 |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1194 if (ngx_array_init(&conf->sheet_files, cf->pool, 1, |
2156
0c6d0bd60579
reuse compiled DTD hash in different locations, add DTD cleanup
Igor Sysoev <igor@sysoev.ru>
parents:
2154
diff
changeset
|
1195 sizeof(ngx_http_xslt_file_t)) |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1196 != NGX_OK) |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1197 { |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1198 return NULL; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1199 } |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1200 |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1201 return conf; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1202 } |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1203 |
2139 | 1204 |
1205 static void * | |
1206 ngx_http_xslt_filter_create_conf(ngx_conf_t *cf) | |
1207 { | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1208 ngx_http_xslt_filter_loc_conf_t *conf; |
2139 | 1209 |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1210 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_xslt_filter_loc_conf_t)); |
2139 | 1211 if (conf == NULL) { |
1212 return NGX_CONF_ERROR; | |
1213 } | |
1214 | |
1215 /* | |
1216 * set by ngx_pcalloc(): | |
1217 * | |
2148 | 1218 * conf->dtd = NULL; |
1219 * conf->sheets = { NULL }; | |
1220 * conf->types = { NULL }; | |
1221 * conf->types_keys = NULL; | |
2139 | 1222 */ |
1223 | |
1224 return conf; | |
1225 } | |
1226 | |
1227 | |
1228 static char * | |
1229 ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
1230 { | |
2154
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1231 ngx_http_xslt_filter_loc_conf_t *prev = parent; |
4f48a2765da0
reuse compiled XSLT tree in different locations
Igor Sysoev <igor@sysoev.ru>
parents:
2153
diff
changeset
|
1232 ngx_http_xslt_filter_loc_conf_t *conf = child; |
2139 | 1233 |
1234 if (conf->dtd == NULL) { | |
1235 conf->dtd = prev->dtd; | |
1236 } | |
1237 | |
1238 if (conf->sheets.nelts == 0) { | |
1239 conf->sheets = prev->sheets; | |
1240 } | |
1241 | |
2148 | 1242 if (ngx_http_merge_types(cf, conf->types_keys, &conf->types, |
1243 prev->types_keys, &prev->types, | |
1244 ngx_http_xslt_default_types) | |
2139 | 1245 != NGX_OK) |
1246 { | |
1247 return NGX_CONF_ERROR; | |
1248 } | |
1249 | |
1250 return NGX_CONF_OK; | |
1251 } | |
1252 | |
1253 | |
1254 static ngx_int_t | |
1255 ngx_http_xslt_filter_init(ngx_conf_t *cf) | |
1256 { | |
1257 xmlInitParser(); | |
1258 | |
1259 ngx_http_next_header_filter = ngx_http_top_header_filter; | |
1260 ngx_http_top_header_filter = ngx_http_xslt_header_filter; | |
1261 | |
1262 ngx_http_next_body_filter = ngx_http_top_body_filter; | |
1263 ngx_http_top_body_filter = ngx_http_xslt_body_filter; | |
1264 | |
1265 return NGX_OK; | |
1266 } | |
1267 | |
1268 | |
1269 static void | |
1270 ngx_http_xslt_filter_exit(ngx_cycle_t *cycle) | |
1271 { | |
1272 xsltCleanupGlobals(); | |
1273 xmlCleanupParser(); | |
1274 } |