int xslt_transform (xmlDocPtr doc, const char *xslfilename, client_t *client) { int i, ret; xsl_req *x; thread_rwlock_rlock (&xslt_lock); i = xslt_cached (xslfilename, NULL, client->worker->current_time.tv_sec); i = xslt_req_sheet (client, doc, xslfilename, i); x = client->shared_data; switch (i) { case -1: thread_rwlock_unlock (&xslt_lock); xmlFreeDoc (doc); client->shared_data = NULL; ret = client_send_404 (client, "Could not parse XSLT file"); break; case CACHESIZE: // delayed thread_rwlock_unlock (&xslt_lock); return 0; default: // found it and ok to use ret = xslt_send_sheet (client, doc, i); break; } if (x) { free (x->cache.filename); free (x->cache.disposition); free (x); } return ret; }
/* thread to read xsl file and add to the cache */ void *xslt_update (void *arg) { xsl_req *x = arg; client_t *client = x->client; char *fn = x->cache.filename; xsltStylesheetPtr sheet; xmlSetStructuredErrorFunc ("xsl/file", config_xml_parse_failure); xsltSetGenericErrorFunc ("", log_parse_failure); sheet = x->cache.stylesheet = xsltParseStylesheetFile (XMLSTR(fn)); if (sheet) { int i; INFO1 ("loaded stylesheet %s", x->cache.filename); if (sheet->mediaType && strcmp ((char*)sheet->mediaType, "text/html") != 0) { // avoid this lookup for html pages const char _hdr[] = "Content-Disposition: attachment; filename=\"file."; const size_t _hdrlen = sizeof (_hdr); size_t len = _hdrlen + 12; char *filename = malloc (len); // enough for name and extension strcpy (filename, _hdr); fserve_write_mime_ext ((char*)sheet->mediaType, filename + _hdrlen - 1, len - _hdrlen - 4); strcat (filename, "\"\r\n"); x->cache.disposition = filename; } // we now have a sheet, find and update. thread_rwlock_wlock (&xslt_lock); i = xslt_cached (fn, &x->cache, time(NULL)); xslt_send_sheet (client, x->doc, i); } else { WARN1 ("problem reading stylesheet \"%s\"", x->cache.filename); free (fn); xmlFreeDoc (x->doc); free (x->cache.disposition); client->shared_data = NULL; client_send_404 (client, "Could not parse XSLT file"); } thread_spin_lock (&update_lock); xsl_updating--; thread_spin_unlock (&update_lock); free (x); return NULL; }
int xslt_transform (xmlDocPtr doc, const char *xslfilename, client_t *client) { xmlDocPtr res; xsltStylesheetPtr cur; int len, i; char **params = NULL; refbuf_t *content = NULL; client->shared_data = doc; thread_rwlock_rlock (&xslt_lock); i = xslt_cached (xslfilename, client); if (i < 0) { thread_rwlock_unlock (&xslt_lock); if (i == -2) { xmlFreeDoc (doc); client->shared_data = NULL; return client_send_404 (client, "Could not parse XSLT file"); } return 0; } cur = cache[i].stylesheet; client->shared_data = NULL; if (client->parser->queryvars) { // annoying but we need to surround the args with ' when passing them in int i, arg_count = client->parser->queryvars->length * 2; avl_node *node = avl_get_first (client->parser->queryvars); params = calloc (arg_count+1, sizeof (char *)); for (i = 0; node && i < arg_count; node = avl_get_next (node)) { http_var_t *param = (http_var_t *)node->key; char *tmp = util_url_escape (param->value); params[i++] = param->name; // use alloca for now, should really url esc into a supplied buffer params[i] = (char*)alloca (strlen (tmp) + 3); sprintf (params[i++], "\'%s\'", tmp); free (tmp); } params[i] = NULL; } res = xsltApplyStylesheet (cur, doc, (const char **)params); free (params); if (res == NULL || xslt_SaveResultToBuf (&content, &len, res, cur) < 0) { thread_rwlock_unlock (&xslt_lock); xmlFreeDoc (res); xmlFreeDoc (doc); WARN1 ("problem applying stylesheet \"%s\"", xslfilename); return client_send_404 (client, "XSLT problem"); } else { /* the 100 is to allow for the hardcoded headers */ refbuf_t *refbuf = refbuf_new (200); const char *mediatype = NULL; /* lets find out the content type to use */ if (cur->mediaType) mediatype = (char *)cur->mediaType; else { /* check method for the default, a missing method assumes xml */ if (cur->method && xmlStrcmp (cur->method, XMLSTR("html")) == 0) mediatype = "text/html"; else if (cur->method && xmlStrcmp (cur->method, XMLSTR("text")) == 0) mediatype = "text/plain"; else mediatype = "text/xml"; } snprintf (refbuf->data, 200, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n" "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" "Cache-Control: no-store, no-cache, must-revalidate\r\n" "Pragma: no-cache\r\n" "\r\n", mediatype, len); thread_rwlock_unlock (&xslt_lock); client->respcode = 200; client_set_queue (client, NULL); client->refbuf = refbuf; refbuf->len = strlen (refbuf->data); refbuf->next = content; } xmlFreeDoc(res); xmlFreeDoc(doc); return fserve_setup_client (client); }