Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_xslt_filter_module.c @ 668:9fbf3ad94cbf NGINX_1_1_18
nginx 1.1.18
*) Change: keepalive connections are no longer disabled for Safari by
default.
*) Feature: the $connection_requests variable.
*) Feature: $tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd and
$tcpinfo_rcv_space variables.
*) Feature: the "worker_cpu_affinity" directive now works on FreeBSD.
*) Feature: the "xslt_param" and "xslt_string_param" directives.
Thanks to Samuel Behan.
*) Bugfix: in configure tests.
Thanks to Piotr Sikora.
*) Bugfix: in the ngx_http_xslt_filter_module.
*) Bugfix: nginx could not be built on Debian GNU/Hurd.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 28 Mar 2012 00:00:00 +0400 |
parents | d0f7a625f27c |
children | bfa81a0490a2 |
comparison
equal
deleted
inserted
replaced
667:e0eabdb2bad1 | 668:9fbf3ad94cbf |
---|---|
12 #include <libxml/parser.h> | 12 #include <libxml/parser.h> |
13 #include <libxml/tree.h> | 13 #include <libxml/tree.h> |
14 #include <libxslt/xslt.h> | 14 #include <libxslt/xslt.h> |
15 #include <libxslt/xsltInternals.h> | 15 #include <libxslt/xsltInternals.h> |
16 #include <libxslt/transform.h> | 16 #include <libxslt/transform.h> |
17 #include <libxslt/variables.h> | |
17 #include <libxslt/xsltutils.h> | 18 #include <libxslt/xsltutils.h> |
18 | 19 |
19 #if (NGX_HAVE_EXSLT) | 20 #if (NGX_HAVE_EXSLT) |
20 #include <libexslt/exslt.h> | 21 #include <libexslt/exslt.h> |
21 #endif | 22 #endif |
25 #define NGX_HTTP_XSLT_REUSE_DTD 1 | 26 #define NGX_HTTP_XSLT_REUSE_DTD 1 |
26 #endif | 27 #endif |
27 | 28 |
28 | 29 |
29 typedef struct { | 30 typedef struct { |
30 u_char *name; | 31 u_char *name; |
31 void *data; | 32 void *data; |
32 } ngx_http_xslt_file_t; | 33 } ngx_http_xslt_file_t; |
33 | 34 |
34 | 35 |
35 typedef struct { | 36 typedef struct { |
36 ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ | 37 ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ |
37 ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ | 38 ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ |
38 } ngx_http_xslt_filter_main_conf_t; | 39 } ngx_http_xslt_filter_main_conf_t; |
39 | 40 |
40 | 41 |
41 typedef struct { | 42 typedef struct { |
42 xsltStylesheetPtr stylesheet; | 43 u_char *name; |
43 ngx_array_t params; /* ngx_http_complex_value_t */ | 44 ngx_http_complex_value_t value; |
45 ngx_uint_t quote; /* unsigned quote:1; */ | |
46 } ngx_http_xslt_param_t; | |
47 | |
48 | |
49 typedef struct { | |
50 xsltStylesheetPtr stylesheet; | |
51 ngx_array_t params; /* ngx_http_xslt_param_t */ | |
44 } ngx_http_xslt_sheet_t; | 52 } ngx_http_xslt_sheet_t; |
45 | 53 |
46 | 54 |
47 typedef struct { | 55 typedef struct { |
48 xmlDtdPtr dtd; | 56 xmlDtdPtr dtd; |
49 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ | 57 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ |
50 ngx_hash_t types; | 58 ngx_hash_t types; |
51 ngx_array_t *types_keys; | 59 ngx_array_t *types_keys; |
60 ngx_array_t *params; /* ngx_http_xslt_param_t */ | |
52 } ngx_http_xslt_filter_loc_conf_t; | 61 } ngx_http_xslt_filter_loc_conf_t; |
53 | 62 |
54 | 63 |
55 typedef struct { | 64 typedef struct { |
56 xmlDocPtr doc; | 65 xmlDocPtr doc; |
57 xmlParserCtxtPtr ctxt; | 66 xmlParserCtxtPtr ctxt; |
58 ngx_http_request_t *request; | 67 xsltTransformContextPtr transform; |
59 ngx_array_t params; | 68 ngx_http_request_t *request; |
60 | 69 ngx_array_t params; |
61 ngx_uint_t done; /* unsigned done:1; */ | 70 |
71 ngx_uint_t done; /* unsigned done:1; */ | |
62 } ngx_http_xslt_filter_ctx_t; | 72 } ngx_http_xslt_filter_ctx_t; |
63 | 73 |
64 | 74 |
65 static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r, | 75 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); | 76 ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b); |
74 | 84 |
75 | 85 |
76 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, | 86 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, |
77 ngx_http_xslt_filter_ctx_t *ctx); | 87 ngx_http_xslt_filter_ctx_t *ctx); |
78 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, | 88 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, |
79 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); | 89 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params, ngx_uint_t final); |
80 static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s); | 90 static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s); |
81 static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s); | 91 static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s); |
82 static void ngx_http_xslt_cleanup(void *data); | 92 static void ngx_http_xslt_cleanup(void *data); |
83 | 93 |
84 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, | 94 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, |
85 void *conf); | 95 void *conf); |
86 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, | 96 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, |
97 void *conf); | |
98 static char *ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, | |
87 void *conf); | 99 void *conf); |
88 static void ngx_http_xslt_cleanup_dtd(void *data); | 100 static void ngx_http_xslt_cleanup_dtd(void *data); |
89 static void ngx_http_xslt_cleanup_stylesheet(void *data); | 101 static void ngx_http_xslt_cleanup_stylesheet(void *data); |
90 static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf); | 102 static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf); |
91 static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf); | 103 static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf); |
114 NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | 126 NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
115 ngx_http_xslt_stylesheet, | 127 ngx_http_xslt_stylesheet, |
116 NGX_HTTP_LOC_CONF_OFFSET, | 128 NGX_HTTP_LOC_CONF_OFFSET, |
117 0, | 129 0, |
118 NULL }, | 130 NULL }, |
131 | |
132 { ngx_string("xslt_param"), | |
133 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, | |
134 ngx_http_xslt_param, | |
135 NGX_HTTP_LOC_CONF_OFFSET, | |
136 0, | |
137 NULL }, | |
138 | |
139 { ngx_string("xslt_string_param"), | |
140 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, | |
141 ngx_http_xslt_param, | |
142 NGX_HTTP_LOC_CONF_OFFSET, | |
143 0, | |
144 (void *) 1 }, | |
119 | 145 |
120 { ngx_string("xslt_types"), | 146 { ngx_string("xslt_types"), |
121 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | 147 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
122 ngx_http_types_slot, | 148 ngx_http_types_slot, |
123 NGX_HTTP_LOC_CONF_OFFSET, | 149 NGX_HTTP_LOC_CONF_OFFSET, |
334 if (ctxt == NULL) { | 360 if (ctxt == NULL) { |
335 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 361 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
336 "xmlCreatePushParserCtxt() failed"); | 362 "xmlCreatePushParserCtxt() failed"); |
337 return NGX_ERROR; | 363 return NGX_ERROR; |
338 } | 364 } |
365 xmlCtxtUseOptions(ctxt, XML_PARSE_NOENT|XML_PARSE_DTDLOAD | |
366 |XML_PARSE_NOWARNING); | |
339 | 367 |
340 ctxt->sax->externalSubset = ngx_http_xslt_sax_external_subset; | 368 ctxt->sax->externalSubset = ngx_http_xslt_sax_external_subset; |
341 ctxt->sax->setDocumentLocator = NULL; | 369 ctxt->sax->setDocumentLocator = NULL; |
342 ctxt->sax->warning = NULL; | |
343 ctxt->sax->error = ngx_http_xslt_sax_error; | 370 ctxt->sax->error = ngx_http_xslt_sax_error; |
344 ctxt->sax->fatalError = ngx_http_xslt_sax_error; | 371 ctxt->sax->fatalError = ngx_http_xslt_sax_error; |
345 ctxt->sax->_private = ctx; | 372 ctxt->sax->_private = ctx; |
346 ctxt->replaceEntities = 1; | |
347 ctxt->loadsubset = 1; | |
348 | 373 |
349 ctx->ctxt = ctxt; | 374 ctx->ctxt = ctxt; |
350 ctx->request = r; | 375 ctx->request = r; |
351 } | 376 } |
352 | 377 |
467 return NULL; | 492 return NULL; |
468 } | 493 } |
469 | 494 |
470 for (i = 0; i < conf->sheets.nelts; i++) { | 495 for (i = 0; i < conf->sheets.nelts; i++) { |
471 | 496 |
472 if (ngx_http_xslt_params(r, ctx, &sheet[i].params) != NGX_OK) { | 497 ctx->transform = xsltNewTransformContext(sheet[i].stylesheet, doc); |
498 if (ctx->transform == NULL) { | |
473 xmlFreeDoc(doc); | 499 xmlFreeDoc(doc); |
474 return NULL; | 500 return NULL; |
475 } | 501 } |
476 | 502 |
477 res = xsltApplyStylesheet(sheet[i].stylesheet, doc, ctx->params.elts); | 503 if (conf->params |
478 | 504 && ngx_http_xslt_params(r, ctx, conf->params, 0) != NGX_OK) |
505 { | |
506 xsltFreeTransformContext(ctx->transform); | |
507 xmlFreeDoc(doc); | |
508 return NULL; | |
509 } | |
510 | |
511 if (ngx_http_xslt_params(r, ctx, &sheet[i].params, 1) != NGX_OK) { | |
512 xsltFreeTransformContext(ctx->transform); | |
513 xmlFreeDoc(doc); | |
514 return NULL; | |
515 } | |
516 | |
517 res = xsltApplyStylesheetUser(sheet[i].stylesheet, doc, | |
518 ctx->params.elts, NULL, NULL, | |
519 ctx->transform); | |
520 | |
521 xsltFreeTransformContext(ctx->transform); | |
479 xmlFreeDoc(doc); | 522 xmlFreeDoc(doc); |
480 | 523 |
481 if (res == NULL) { | 524 if (res == NULL) { |
482 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 525 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
483 "xsltApplyStylesheet() failed"); | 526 "xsltApplyStylesheet() failed"); |
563 } | 606 } |
564 | 607 |
565 | 608 |
566 static ngx_int_t | 609 static ngx_int_t |
567 ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, | 610 ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, |
568 ngx_array_t *params) | 611 ngx_array_t *params, ngx_uint_t final) |
569 { | 612 { |
570 u_char *p, *last, *value, *dst, *src, **s; | 613 u_char *p, *last, *value, *dst, *src, **s; |
571 size_t len; | 614 size_t len; |
572 ngx_uint_t i; | 615 ngx_uint_t i; |
573 ngx_str_t string; | 616 ngx_str_t string; |
574 ngx_http_complex_value_t *param; | 617 ngx_http_xslt_param_t *param; |
575 | 618 |
576 param = params->elts; | 619 param = params->elts; |
577 | 620 |
578 for (i = 0; i < params->nelts; i++) { | 621 for (i = 0; i < params->nelts; i++) { |
579 | 622 |
580 if (ngx_http_complex_value(r, ¶m[i], &string) != NGX_OK) { | 623 if (ngx_http_complex_value(r, ¶m[i].value, &string) != NGX_OK) { |
581 return NGX_ERROR; | 624 return NGX_ERROR; |
582 } | 625 } |
583 | 626 |
584 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 627 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
585 "xslt filter param: \"%s\"", string.data); | 628 "xslt filter param: \"%s\"", string.data); |
586 | 629 |
630 if (param[i].name) { | |
631 | |
632 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
633 "xslt filter param name: \"%s\"", param[i].name); | |
634 | |
635 if (param[i].quote) { | |
636 if (xsltQuoteOneUserParam(ctx->transform, param[i].name, | |
637 string.data) | |
638 != 0) | |
639 { | |
640 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
641 "xsltQuoteOneUserParam(\"%s\", \"%s\") failed", | |
642 param[i].name, string.data); | |
643 return NGX_ERROR; | |
644 } | |
645 | |
646 continue; | |
647 } | |
648 | |
649 s = ngx_array_push(&ctx->params); | |
650 if (s == NULL) { | |
651 return NGX_ERROR; | |
652 } | |
653 | |
654 *s = param[i].name; | |
655 | |
656 s = ngx_array_push(&ctx->params); | |
657 if (s == NULL) { | |
658 return NGX_ERROR; | |
659 } | |
660 | |
661 *s = string.data; | |
662 | |
663 continue; | |
664 } | |
665 | |
666 /* | |
667 * parse param1=value1:param2=value2 syntax as used by parameters | |
668 * specified in xslt_stylesheet directives | |
669 */ | |
670 | |
587 p = string.data; | 671 p = string.data; |
588 last = string.data + string.len - 1; | 672 last = string.data + string.len; |
589 | 673 |
590 while (p && *p) { | 674 while (p && *p) { |
591 | 675 |
592 value = p; | 676 value = p; |
593 p = (u_char *) ngx_strchr(p, '='); | 677 p = (u_char *) ngx_strchr(p, '='); |
639 | 723 |
640 *s = value; | 724 *s = value; |
641 } | 725 } |
642 } | 726 } |
643 | 727 |
644 s = ngx_array_push(&ctx->params); | 728 if (final) { |
645 if (s == NULL) { | 729 s = ngx_array_push(&ctx->params); |
646 return NGX_ERROR; | 730 if (s == NULL) { |
647 } | 731 return NGX_ERROR; |
648 | 732 } |
649 *s = NULL; | 733 |
734 *s = NULL; | |
735 } | |
650 | 736 |
651 return NGX_OK; | 737 return NGX_OK; |
652 } | 738 } |
653 | 739 |
654 | 740 |
766 ngx_str_t *value; | 852 ngx_str_t *value; |
767 ngx_uint_t i, n; | 853 ngx_uint_t i, n; |
768 ngx_pool_cleanup_t *cln; | 854 ngx_pool_cleanup_t *cln; |
769 ngx_http_xslt_file_t *file; | 855 ngx_http_xslt_file_t *file; |
770 ngx_http_xslt_sheet_t *sheet; | 856 ngx_http_xslt_sheet_t *sheet; |
771 ngx_http_complex_value_t *param; | 857 ngx_http_xslt_param_t *param; |
772 ngx_http_compile_complex_value_t ccv; | 858 ngx_http_compile_complex_value_t ccv; |
773 ngx_http_xslt_filter_main_conf_t *xmcf; | 859 ngx_http_xslt_filter_main_conf_t *xmcf; |
774 | 860 |
775 value = cf->args->elts; | 861 value = cf->args->elts; |
776 | 862 |
835 if (n == 2) { | 921 if (n == 2) { |
836 return NGX_CONF_OK; | 922 return NGX_CONF_OK; |
837 } | 923 } |
838 | 924 |
839 if (ngx_array_init(&sheet->params, cf->pool, n - 2, | 925 if (ngx_array_init(&sheet->params, cf->pool, n - 2, |
840 sizeof(ngx_http_complex_value_t)) | 926 sizeof(ngx_http_xslt_param_t)) |
841 != NGX_OK) | 927 != NGX_OK) |
842 { | 928 { |
843 return NGX_CONF_ERROR; | 929 return NGX_CONF_ERROR; |
844 } | 930 } |
845 | 931 |
848 param = ngx_array_push(&sheet->params); | 934 param = ngx_array_push(&sheet->params); |
849 if (param == NULL) { | 935 if (param == NULL) { |
850 return NGX_CONF_ERROR; | 936 return NGX_CONF_ERROR; |
851 } | 937 } |
852 | 938 |
939 ngx_memzero(param, sizeof(ngx_http_xslt_param_t)); | |
853 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | 940 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
854 | 941 |
855 ccv.cf = cf; | 942 ccv.cf = cf; |
856 ccv.value = &value[i]; | 943 ccv.value = &value[i]; |
857 ccv.complex_value = param; | 944 ccv.complex_value = ¶m->value; |
858 ccv.zero = 1; | 945 ccv.zero = 1; |
859 | 946 |
860 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | 947 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
861 return NGX_CONF_ERROR; | 948 return NGX_CONF_ERROR; |
862 } | 949 } |
950 } | |
951 | |
952 return NGX_CONF_OK; | |
953 } | |
954 | |
955 | |
956 static char * | |
957 ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
958 { | |
959 ngx_http_xslt_filter_loc_conf_t *xlcf = conf; | |
960 | |
961 ngx_http_xslt_param_t *param; | |
962 ngx_http_compile_complex_value_t ccv; | |
963 ngx_str_t *value; | |
964 | |
965 value = cf->args->elts; | |
966 | |
967 if (xlcf->params == NULL) { | |
968 xlcf->params = ngx_array_create(cf->pool, 2, | |
969 sizeof(ngx_http_xslt_param_t)); | |
970 if (xlcf->params == NULL) { | |
971 return NGX_CONF_ERROR; | |
972 } | |
973 } | |
974 | |
975 param = ngx_array_push(xlcf->params); | |
976 if (param == NULL) { | |
977 return NGX_CONF_ERROR; | |
978 } | |
979 | |
980 param->name = value[1].data; | |
981 param->quote = (cmd->post == NULL) ? 0 : 1; | |
982 | |
983 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
984 | |
985 ccv.cf = cf; | |
986 ccv.value = &value[2]; | |
987 ccv.complex_value = ¶m->value; | |
988 ccv.zero = 1; | |
989 | |
990 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
991 return NGX_CONF_ERROR; | |
863 } | 992 } |
864 | 993 |
865 return NGX_CONF_OK; | 994 return NGX_CONF_OK; |
866 } | 995 } |
867 | 996 |
923 * | 1052 * |
924 * conf->dtd = NULL; | 1053 * conf->dtd = NULL; |
925 * conf->sheets = { NULL }; | 1054 * conf->sheets = { NULL }; |
926 * conf->types = { NULL }; | 1055 * conf->types = { NULL }; |
927 * conf->types_keys = NULL; | 1056 * conf->types_keys = NULL; |
1057 * conf->params = NULL; | |
928 */ | 1058 */ |
929 | 1059 |
930 return conf; | 1060 return conf; |
931 } | 1061 } |
932 | 1062 |
941 conf->dtd = prev->dtd; | 1071 conf->dtd = prev->dtd; |
942 } | 1072 } |
943 | 1073 |
944 if (conf->sheets.nelts == 0) { | 1074 if (conf->sheets.nelts == 0) { |
945 conf->sheets = prev->sheets; | 1075 conf->sheets = prev->sheets; |
1076 } | |
1077 | |
1078 if (conf->params == NULL) { | |
1079 conf->params = prev->params; | |
946 } | 1080 } |
947 | 1081 |
948 if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, | 1082 if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, |
949 &prev->types_keys, &prev->types, | 1083 &prev->types_keys, &prev->types, |
950 ngx_http_xslt_default_types) | 1084 ngx_http_xslt_default_types) |