completed xslt plugin

This commit is contained in:
Unbit
2013-03-19 17:53:12 +01:00
parent ef0316fc2e
commit 3f8e6a8cc8
5 changed files with 1573 additions and 1410 deletions
+151 -3
View File
@@ -26,6 +26,17 @@ struct uwsgi_xslt_config {
uint16_t content_type_len;
} uxslt;
struct uwsgi_router_xslt_conf {
char *doc;
uint16_t doc_len;
char *stylesheet;
uint16_t stylesheet_len;
char *params;
uint16_t params_len;
char *content_type;
uint16_t content_type_len;
};
struct uwsgi_option uwsgi_xslt_options[] = {
{"xslt-docroot", required_argument, 0, "add a document_root for xslt processing", uwsgi_opt_add_string_list, &uxslt.docroot, 0},
{"xslt-ext", required_argument, 0, "search for xslt stylesheets with the specified extension", uwsgi_opt_add_string_list, &uxslt.ext, 0},
@@ -35,7 +46,34 @@ struct uwsgi_option uwsgi_xslt_options[] = {
{NULL, 0, 0, NULL, NULL, NULL, 0},
};
static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char **params, int *rlen) {
static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *rlen) {
char **vparams = NULL;
char *tmp_params;
uint16_t count = 0;
if (params) {
// first count the number of items
size_t i;
size_t params_len = strlen(params);
for(i=0;i<params_len;i++) {
if (params[i] == '=') {
count++;
}
}
vparams = uwsgi_calloc( sizeof(char *) * ((count * 2) + 1));
tmp_params = uwsgi_str(params);
char *p = strtok(tmp_params, "&");
int pos = 0;
while(p) {
char *equal = strchr(p, '=');
if (equal) {
*equal = 0;
vparams[pos] = p; pos++;
vparams[pos] = uwsgi_concat3("\"", equal+1, "\""); pos++;
}
p = strtok(NULL, "&");
}
}
// we reset them every time to avoid collision with other xml engines
xmlSubstituteEntitiesDefault(1);
@@ -43,19 +81,34 @@ static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char **params, int
xmlDocPtr doc = xmlParseFile(xmlfile);
if (!doc) {
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
return NULL;
}
xsltStylesheetPtr ss = xsltParseStylesheetFile((const xmlChar *) xsltfile);
if (!ss) {
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
return NULL;
}
xmlDocPtr res = xsltApplyStylesheet(ss, doc, (const char **) params);
xmlDocPtr res = xsltApplyStylesheet(ss, doc, (const char **) vparams);
if (!res) {
xsltFreeStylesheet(ss);
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
return NULL;
}
@@ -64,6 +117,11 @@ static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char **params, int
xsltFreeStylesheet(ss);
xmlFreeDoc(res);
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
if (ret < 0) return NULL;
return (char *) output;
}
@@ -78,6 +136,8 @@ static int uwsgi_request_xslt(struct wsgi_request *wsgi_req) {
size_t filename_len = 0;
char stylesheet[PATH_MAX+1];
size_t stylesheet_len = 0;
char *params = NULL;
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
@@ -215,8 +275,12 @@ static int uwsgi_request_xslt(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
apply:
if (wsgi_req->query_string_len > 0) {
params = uwsgi_concat2n(wsgi_req->query_string, wsgi_req->query_string_len, "", 0);
}
// we have both the file and the stylesheet, let's run the engine
output = uwsgi_xslt_apply(filename, stylesheet, NULL, &output_rlen);
output = uwsgi_xslt_apply(filename, stylesheet, params, &output_rlen);
if (params) free(params);
if (!output) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
@@ -249,10 +313,94 @@ static void uwsgi_xslt_log(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static int uwsgi_routing_func_xslt(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_xslt_conf *urxc = (struct uwsgi_router_xslt_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_doc = NULL;
struct uwsgi_buffer *ub_stylesheet = NULL;
struct uwsgi_buffer *ub_params = NULL;
struct uwsgi_buffer *ub_content_type = NULL;
ub_doc = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->doc, urxc->doc_len);
if (!ub_doc) goto end;
ub_stylesheet = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->stylesheet, urxc->stylesheet_len);
if (!ub_stylesheet) goto end;
if (urxc->params) {
ub_params = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->params, urxc->params_len);
if (!ub_params) goto end;
}
if (urxc->content_type) {
ub_content_type = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->content_type, urxc->content_type_len);
if (!ub_content_type) goto end;
}
int rlen;
char *output = uwsgi_xslt_apply( ub_doc->buf, ub_stylesheet->buf, ub_params ? ub_params->buf : NULL, &rlen);
if (!output) goto end;
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
if (uwsgi_response_add_content_length(wsgi_req, rlen)) goto end;
if (uwsgi_response_add_content_type(wsgi_req, urxc->content_type, urxc->content_type_len)) goto end;
uwsgi_response_write_body_do(wsgi_req, output, rlen);
xmlFree(output);
end:
if (ub_doc) uwsgi_buffer_destroy(ub_doc);
if (ub_stylesheet) uwsgi_buffer_destroy(ub_stylesheet);
if (ub_params) uwsgi_buffer_destroy(ub_params);
if (ub_content_type) uwsgi_buffer_destroy(ub_content_type);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_xslt(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_xslt;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_xslt_conf *urxc = uwsgi_calloc(sizeof(struct uwsgi_router_xslt_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"doc", &urxc->doc,
"stylesheet", &urxc->stylesheet,
"content_type", &urxc->content_type,
"params", &urxc->params,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urxc->doc && !urxc->stylesheet) {
uwsgi_log("invalid route syntax: you need to specify a doc and a stylesheet\n");
exit(1);
}
urxc->doc_len = strlen(urxc->doc);
urxc->stylesheet_len = strlen(urxc->stylesheet);
if (urxc->params) urxc->params_len = strlen(urxc->params);
if (!urxc->content_type) urxc->content_type = "text/html";
urxc->content_type_len = strlen(urxc->content_type);
ur->data2 = urxc;
return 0;
}
static void router_xslt_register() {
uwsgi_register_router("xslt", uwsgi_router_xslt);
}
struct uwsgi_plugin xslt_plugin = {
.name = "xslt",
.modifier1 = 23,
.options = uwsgi_xslt_options,
.request = uwsgi_request_xslt,
.after_request = uwsgi_xslt_log,
.on_load = router_xslt_register,
};
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!-- Edited by XMLSpy® -->
<catalog>
<cd>
<title>Quintessence</title>
<artist>Borknagar</artist>
</cd>
<cd>
<title>Torn Beyond Reason</title>
<artist>Woods Of Desolation</artist>
</cd>
<cd>
<title>Autumn Aurora</title>
<artist>Drudkh</artist>
</cd>
<cd>
<title>Om</title>
<artist>Negura Bunget</artist>
</cd>
<cd>
<title>Frostnacht</title>
<artist>Helrunar</artist>
</cd>
</catalog>
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Blackmetal albums</h2>
<table border="1">
<tr bgcolor="black">
<th style="color:white">Title</th>
<th style="color:white">Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
<td>-<xsl:value-of select="$foobar"/>-</td>
<td><xsl:value-of select="$agent"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
http-socket = :9090
plugin = xslt
xml_storage = t/xslt
route = /(.*)$ xslt:doc=%(xml_storage)/$1.xml,stylesheet=%(xml_storage)/$1.xml.xslt,content_type=text/html,params=foobar=test&agent=${HTTP_USER_AGENT}
+1368 -1407
View File
File diff suppressed because it is too large Load Diff