Klaus Demo nginx / 1aa5fbb
Added xslt_param and xslt_string_param directives. Based on patch by Samuel Behan. Maxim Dounin 10 years ago
1 changed file(s) with 172 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
1313 #include <libxslt/xslt.h>
1414 #include <libxslt/xsltInternals.h>
1515 #include <libxslt/transform.h>
16 #include <libxslt/variables.h>
1617 #include <libxslt/xsltutils.h>
1718
1819 #if (NGX_HAVE_EXSLT)
2627
2728
2829 typedef struct {
29 u_char *name;
30 void *data;
30 u_char *name;
31 void *data;
3132 } ngx_http_xslt_file_t;
3233
3334
3435 typedef struct {
35 ngx_array_t dtd_files; /* ngx_http_xslt_file_t */
36 ngx_array_t sheet_files; /* ngx_http_xslt_file_t */
36 ngx_array_t dtd_files; /* ngx_http_xslt_file_t */
37 ngx_array_t sheet_files; /* ngx_http_xslt_file_t */
3738 } ngx_http_xslt_filter_main_conf_t;
3839
3940
4041 typedef struct {
41 xsltStylesheetPtr stylesheet;
42 ngx_array_t params; /* ngx_http_complex_value_t */
42 u_char *name;
43 ngx_http_complex_value_t value;
44 ngx_uint_t quote; /* unsigned quote:1; */
45 } ngx_http_xslt_param_t;
46
47
48 typedef struct {
49 xsltStylesheetPtr stylesheet;
50 ngx_array_t params; /* ngx_http_xslt_param_t */
4351 } ngx_http_xslt_sheet_t;
4452
4553
4654 typedef struct {
47 xmlDtdPtr dtd;
48 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */
49 ngx_hash_t types;
50 ngx_array_t *types_keys;
55 xmlDtdPtr dtd;
56 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */
57 ngx_hash_t types;
58 ngx_array_t *types_keys;
59 ngx_array_t *params; /* ngx_http_xslt_param_t */
5160 } ngx_http_xslt_filter_loc_conf_t;
5261
5362
5463 typedef struct {
55 xmlDocPtr doc;
56 xmlParserCtxtPtr ctxt;
57 ngx_http_request_t *request;
58 ngx_array_t params;
59
60 ngx_uint_t done; /* unsigned done:1; */
64 xmlDocPtr doc;
65 xmlParserCtxtPtr ctxt;
66 xsltTransformContextPtr transform;
67 ngx_http_request_t *request;
68 ngx_array_t params;
69
70 ngx_uint_t done; /* unsigned done:1; */
6171 } ngx_http_xslt_filter_ctx_t;
6272
6373
7585 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r,
7686 ngx_http_xslt_filter_ctx_t *ctx);
7787 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r,
78 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params);
88 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params, ngx_uint_t final);
7989 static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s);
8090 static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s);
8191 static void ngx_http_xslt_cleanup(void *data);
8393 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd,
8494 void *conf);
8595 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd,
96 void *conf);
97 static char *ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd,
8698 void *conf);
8799 static void ngx_http_xslt_cleanup_dtd(void *data);
88100 static void ngx_http_xslt_cleanup_stylesheet(void *data);
115127 NGX_HTTP_LOC_CONF_OFFSET,
116128 0,
117129 NULL },
130
131 { ngx_string("xslt_param"),
132 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
133 ngx_http_xslt_param,
134 NGX_HTTP_LOC_CONF_OFFSET,
135 0,
136 NULL },
137
138 { ngx_string("xslt_string_param"),
139 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
140 ngx_http_xslt_param,
141 NGX_HTTP_LOC_CONF_OFFSET,
142 0,
143 (void *) 1 },
118144
119145 { ngx_string("xslt_types"),
120146 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
468494
469495 for (i = 0; i < conf->sheets.nelts; i++) {
470496
471 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) {
472499 xmlFreeDoc(doc);
473500 return NULL;
474501 }
475502
476 res = xsltApplyStylesheet(sheet[i].stylesheet, doc, ctx->params.elts);
477
503 if (conf->params
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);
478522 xmlFreeDoc(doc);
479523
480524 if (res == NULL) {
564608
565609 static ngx_int_t
566610 ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
567 ngx_array_t *params)
568 {
569 u_char *p, *last, *value, *dst, *src, **s;
570 size_t len;
571 ngx_uint_t i;
572 ngx_str_t string;
573 ngx_http_complex_value_t *param;
611 ngx_array_t *params, ngx_uint_t final)
612 {
613 u_char *p, *last, *value, *dst, *src, **s;
614 size_t len;
615 ngx_uint_t i;
616 ngx_str_t string;
617 ngx_http_xslt_param_t *param;
574618
575619 param = params->elts;
576620
577621 for (i = 0; i < params->nelts; i++) {
578622
579 if (ngx_http_complex_value(r, &param[i], &string) != NGX_OK) {
623 if (ngx_http_complex_value(r, &param[i].value, &string) != NGX_OK) {
580624 return NGX_ERROR;
581625 }
582626
583627 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
584628 "xslt filter param: \"%s\"", string.data);
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 */
585670
586671 p = string.data;
587672 last = string.data + string.len;
640725 }
641726 }
642727
643 s = ngx_array_push(&ctx->params);
644 if (s == NULL) {
645 return NGX_ERROR;
646 }
647
648 *s = NULL;
728 if (final) {
729 s = ngx_array_push(&ctx->params);
730 if (s == NULL) {
731 return NGX_ERROR;
732 }
733
734 *s = NULL;
735 }
649736
650737 return NGX_OK;
651738 }
767854 ngx_pool_cleanup_t *cln;
768855 ngx_http_xslt_file_t *file;
769856 ngx_http_xslt_sheet_t *sheet;
770 ngx_http_complex_value_t *param;
857 ngx_http_xslt_param_t *param;
771858 ngx_http_compile_complex_value_t ccv;
772859 ngx_http_xslt_filter_main_conf_t *xmcf;
773860
836923 }
837924
838925 if (ngx_array_init(&sheet->params, cf->pool, n - 2,
839 sizeof(ngx_http_complex_value_t))
926 sizeof(ngx_http_xslt_param_t))
840927 != NGX_OK)
841928 {
842929 return NGX_CONF_ERROR;
849936 return NGX_CONF_ERROR;
850937 }
851938
939 ngx_memzero(param, sizeof(ngx_http_xslt_param_t));
852940 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
853941
854942 ccv.cf = cf;
855943 ccv.value = &value[i];
856 ccv.complex_value = param;
944 ccv.complex_value = &param->value;
857945 ccv.zero = 1;
858946
859947 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
860948 return NGX_CONF_ERROR;
861949 }
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 = &param->value;
988 ccv.zero = 1;
989
990 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
991 return NGX_CONF_ERROR;
862992 }
863993
864994 return NGX_CONF_OK;
9241054 * conf->sheets = { NULL };
9251055 * conf->types = { NULL };
9261056 * conf->types_keys = NULL;
1057 * conf->params = NULL;
9271058 */
9281059
9291060 return conf;
9421073
9431074 if (conf->sheets.nelts == 0) {
9441075 conf->sheets = prev->sheets;
1076 }
1077
1078 if (conf->params == NULL) {
1079 conf->params = prev->params;
9451080 }
9461081
9471082 if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,