[PATCH] add xslt_stylesheet_param directive
Maxim Dounin
mdounin at mdounin.ru
Fri Mar 2 18:52:36 UTC 2012
Hello!
On Sun, Feb 26, 2012 at 04:15:33PM +0100, SamB wrote:
> Hi,
>
> sorry for late response, had no spare time for this. Here is new patch,
> please review it.
> I've modified the string_param-enabled - it seems to better fit my
> usage...
Please check the attached patch. It cleans up some style issues
and slightly changes parameter processing to be more uniform with
parameters from xslt_stylesheet directives.
There is also a tiny patch included which fixes long-standing
off-by-one bug in parsing parameters from xslt_stylesheet
directives.
Tests are here:
http://mdounin.ru/hg/nginx-tests/rev/6bac00bba8d4
Maxim Dounin
-------------- next part --------------
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1330697803 -14400
# Node ID 4df0e70d82dd2555b2aa076197947f744c4aea44
# Parent 88e257b4bd3d61e30d1421ab6f2e417a8baedb96
Fixed off-by-one in xslt parameter parsing.
The problem was introduced in 0.7.44 (r2589) during conversion to complex
values. Previously string.len included space for terminating NUL, but
with complex values it doesn't.
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
@@ -585,7 +585,7 @@ ngx_http_xslt_params(ngx_http_request_t
"xslt filter param: \"%s\"", string.data);
p = string.data;
- last = string.data + string.len - 1;
+ last = string.data + string.len;
while (p && *p) {
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1330707634 -14400
# Node ID ceb911a15613cf81f6a3669c8d39aef596ad36e7
# Parent 4df0e70d82dd2555b2aa076197947f744c4aea44
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 <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
+#include <libxslt/variables.h>
#include <libxslt/xsltutils.h>
#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)
More information about the nginx-devel
mailing list