[nginx] svn commit: r4555 - trunk/src/http/modules

mdounin at mdounin.ru mdounin at mdounin.ru
Thu Mar 22 10:44:01 UTC 2012


Author: mdounin
Date: 2012-03-22 10:44:00 +0000 (Thu, 22 Mar 2012)
New Revision: 4555
URL: http://trac.nginx.org/nginx/changeset/4555/nginx

Log:
Added xslt_param and xslt_string_param directives.

Based on patch by Samuel Behan.


Modified:
   trunk/src/http/modules/ngx_http_xslt_filter_module.c

Modified: trunk/src/http/modules/ngx_http_xslt_filter_module.c
===================================================================
--- trunk/src/http/modules/ngx_http_xslt_filter_module.c	2012-03-22 10:43:33 UTC (rev 4554)
+++ trunk/src/http/modules/ngx_http_xslt_filter_module.c	2012-03-22 10:44:00 UTC (rev 4555)
@@ -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 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 @@
     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 @@
       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 @@
 
     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 @@
 
 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, &param[i], &string) != NGX_OK) {
+        if (ngx_http_complex_value(r, &param[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 @@
         }
     }
 
-    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_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 @@
     }
 
     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 @@
             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 = &param->value;
         ccv.zero = 1;
 
         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
@@ -866,6 +954,48 @@
 }
 
 
+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 = &param->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 @@
      *     conf->sheets = { NULL };
      *     conf->types = { NULL };
      *     conf->types_keys = NULL;
+     *     conf->params = NULL;
      */
 
     return conf;
@@ -945,6 +1076,10 @@
         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