# HG changeset patch # User Maxim Dounin # Date 1332413040 0 # Node ID 212a0251951b1a769bb3d69d2064cf16b0a4b581 # Parent 3dd8a403faa1801ac5ee78e2d9c768197c28c21e Added xslt_param and xslt_string_param directives. Based on patch by Samuel Behan. diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c --- a/src/http/modules/ngx_http_xslt_filter_module.c +++ b/src/http/modules/ngx_http_xslt_filter_module.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #if (NGX_HAVE_EXSLT) @@ -27,38 +28,47 @@ typedef struct { - u_char *name; - void *data; + u_char *name; + void *data; } ngx_http_xslt_file_t; typedef struct { - ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ - ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ + ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ + ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ } ngx_http_xslt_filter_main_conf_t; typedef struct { - xsltStylesheetPtr stylesheet; - ngx_array_t params; /* ngx_http_complex_value_t */ + u_char *name; + ngx_http_complex_value_t value; + ngx_uint_t quote; /* unsigned quote:1; */ +} ngx_http_xslt_param_t; + + +typedef struct { + xsltStylesheetPtr stylesheet; + ngx_array_t params; /* ngx_http_xslt_param_t */ } ngx_http_xslt_sheet_t; typedef struct { - xmlDtdPtr dtd; - ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ - ngx_hash_t types; - ngx_array_t *types_keys; + xmlDtdPtr dtd; + ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ + ngx_hash_t types; + ngx_array_t *types_keys; + ngx_array_t *params; /* ngx_http_xslt_param_t */ } ngx_http_xslt_filter_loc_conf_t; typedef struct { - xmlDocPtr doc; - xmlParserCtxtPtr ctxt; - ngx_http_request_t *request; - ngx_array_t params; + xmlDocPtr doc; + xmlParserCtxtPtr ctxt; + xsltTransformContextPtr transform; + ngx_http_request_t *request; + ngx_array_t params; - ngx_uint_t done; /* unsigned done:1; */ + ngx_uint_t done; /* unsigned done:1; */ } ngx_http_xslt_filter_ctx_t; @@ -76,7 +86,7 @@ static void ngx_cdecl ngx_http_xslt_sax_ static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx); static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, - ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); + ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params, ngx_uint_t final); static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s); static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s); static void ngx_http_xslt_cleanup(void *data); @@ -85,6 +95,8 @@ static char *ngx_http_xslt_entities(ngx_ void *conf); static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static void ngx_http_xslt_cleanup_dtd(void *data); static void ngx_http_xslt_cleanup_stylesheet(void *data); static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf); @@ -117,6 +129,20 @@ static ngx_command_t ngx_http_xslt_filt 0, NULL }, + { ngx_string("xslt_param"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_http_xslt_param, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("xslt_string_param"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_http_xslt_param, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) 1 }, + { ngx_string("xslt_types"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_http_types_slot, @@ -469,13 +495,31 @@ ngx_http_xslt_apply_stylesheet(ngx_http_ for (i = 0; i < conf->sheets.nelts; i++) { - if (ngx_http_xslt_params(r, ctx, &sheet[i].params) != NGX_OK) { + ctx->transform = xsltNewTransformContext(sheet[i].stylesheet, doc); + if (ctx->transform == NULL) { xmlFreeDoc(doc); return NULL; } - res = xsltApplyStylesheet(sheet[i].stylesheet, doc, ctx->params.elts); + if (conf->params + && ngx_http_xslt_params(r, ctx, conf->params, 0) != NGX_OK) + { + xsltFreeTransformContext(ctx->transform); + xmlFreeDoc(doc); + return NULL; + } + if (ngx_http_xslt_params(r, ctx, &sheet[i].params, 1) != NGX_OK) { + xsltFreeTransformContext(ctx->transform); + xmlFreeDoc(doc); + return NULL; + } + + res = xsltApplyStylesheetUser(sheet[i].stylesheet, doc, + ctx->params.elts, NULL, NULL, + ctx->transform); + + xsltFreeTransformContext(ctx->transform); xmlFreeDoc(doc); if (res == NULL) { @@ -565,25 +609,66 @@ ngx_http_xslt_apply_stylesheet(ngx_http_ static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, - ngx_array_t *params) + ngx_array_t *params, ngx_uint_t final) { - u_char *p, *last, *value, *dst, *src, **s; - size_t len; - ngx_uint_t i; - ngx_str_t string; - ngx_http_complex_value_t *param; + u_char *p, *last, *value, *dst, *src, **s; + size_t len; + ngx_uint_t i; + ngx_str_t string; + ngx_http_xslt_param_t *param; param = params->elts; for (i = 0; i < params->nelts; i++) { - if (ngx_http_complex_value(r, ¶m[i], &string) != NGX_OK) { + if (ngx_http_complex_value(r, ¶m[i].value, &string) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xslt filter param: \"%s\"", string.data); + if (param[i].name) { + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "xslt filter param name: \"%s\"", param[i].name); + + if (param[i].quote) { + if (xsltQuoteOneUserParam(ctx->transform, param[i].name, + string.data) + != 0) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "xsltQuoteOneUserParam(\"%s\", \"%s\") failed", + param[i].name, string.data); + return NGX_ERROR; + } + + continue; + } + + s = ngx_array_push(&ctx->params); + if (s == NULL) { + return NGX_ERROR; + } + + *s = param[i].name; + + s = ngx_array_push(&ctx->params); + if (s == NULL) { + return NGX_ERROR; + } + + *s = string.data; + + continue; + } + + /* + * parse param1=value1:param2=value2 syntax as used by parameters + * specified in xslt_stylesheet directives + */ + p = string.data; last = string.data + string.len; @@ -641,13 +726,15 @@ ngx_http_xslt_params(ngx_http_request_t } } - s = ngx_array_push(&ctx->params); - if (s == NULL) { - return NGX_ERROR; + if (final) { + s = ngx_array_push(&ctx->params); + if (s == NULL) { + return NGX_ERROR; + } + + *s = NULL; } - *s = NULL; - return NGX_OK; } @@ -768,7 +855,7 @@ ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_pool_cleanup_t *cln; ngx_http_xslt_file_t *file; ngx_http_xslt_sheet_t *sheet; - ngx_http_complex_value_t *param; + ngx_http_xslt_param_t *param; ngx_http_compile_complex_value_t ccv; ngx_http_xslt_filter_main_conf_t *xmcf; @@ -837,7 +924,7 @@ found: } if (ngx_array_init(&sheet->params, cf->pool, n - 2, - sizeof(ngx_http_complex_value_t)) + sizeof(ngx_http_xslt_param_t)) != NGX_OK) { return NGX_CONF_ERROR; @@ -850,11 +937,12 @@ found: return NGX_CONF_ERROR; } + ngx_memzero(param, sizeof(ngx_http_xslt_param_t)); ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[i]; - ccv.complex_value = param; + ccv.complex_value = ¶m->value; ccv.zero = 1; if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { @@ -866,6 +954,48 @@ found: } +static char * +ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_xslt_filter_loc_conf_t *xlcf = conf; + + ngx_http_xslt_param_t *param; + ngx_http_compile_complex_value_t ccv; + ngx_str_t *value; + + value = cf->args->elts; + + if (xlcf->params == NULL) { + xlcf->params = ngx_array_create(cf->pool, 2, + sizeof(ngx_http_xslt_param_t)); + if (xlcf->params == NULL) { + return NGX_CONF_ERROR; + } + } + + param = ngx_array_push(xlcf->params); + if (param == NULL) { + return NGX_CONF_ERROR; + } + + param->name = value[1].data; + param->quote = (cmd->post == NULL) ? 0 : 1; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[2]; + ccv.complex_value = ¶m->value; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + static void ngx_http_xslt_cleanup_dtd(void *data) { @@ -925,6 +1055,7 @@ ngx_http_xslt_filter_create_conf(ngx_con * conf->sheets = { NULL }; * conf->types = { NULL }; * conf->types_keys = NULL; + * conf->params = NULL; */ return conf; @@ -945,6 +1076,10 @@ ngx_http_xslt_filter_merge_conf(ngx_conf conf->sheets = prev->sheets; } + if (conf->params == NULL) { + conf->params = prev->params; + } + if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, &prev->types_keys, &prev->types, ngx_http_xslt_default_types)