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