#include "postgres.h"
#include "executor/spi.h"
#include "fmgr.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/xml.h"
Go to the source code of this file.
Functions | |
Datum | xslt_process (PG_FUNCTION_ARGS) |
PG_FUNCTION_INFO_V1 (xslt_process) |
PG_FUNCTION_INFO_V1 | ( | xslt_process | ) |
Datum xslt_process | ( | PG_FUNCTION_ARGS | ) |
Definition at line 52 of file xslt_proc.c.
References cstring_to_text_with_len(), ereport, errcode(), errmsg(), ERROR, NULL, palloc(), PG_CATCH, PG_END_TRY, PG_GETARG_TEXT_P, PG_RE_THROW, PG_RETURN_NULL, PG_RETURN_TEXT_P, PG_TRY, pg_xml_done(), PG_XML_STRICTNESS_LEGACY, pgxml_parser_init(), VARDATA, VARHDRSZ, VARSIZE, and xml_ereport().
{ #ifdef USE_LIBXSLT text *doct = PG_GETARG_TEXT_P(0); text *ssheet = PG_GETARG_TEXT_P(1); text *result; text *paramstr; const char **params; PgXmlErrorContext *xmlerrcxt; volatile xsltStylesheetPtr stylesheet = NULL; volatile xmlDocPtr doctree = NULL; volatile xmlDocPtr restree = NULL; volatile xsltSecurityPrefsPtr xslt_sec_prefs = NULL; volatile xsltTransformContextPtr xslt_ctxt = NULL; volatile int resstat = -1; xmlChar *resstr = NULL; int reslen = 0; if (fcinfo->nargs == 3) { paramstr = PG_GETARG_TEXT_P(2); params = parse_params(paramstr); } else { /* No parameters */ params = (const char **) palloc(sizeof(char *)); params[0] = NULL; } /* Setup parser */ xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY); PG_TRY(); { xmlDocPtr ssdoc; bool xslt_sec_prefs_error; /* Parse document */ doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ); if (doctree == NULL) xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "error parsing XML document"); /* Same for stylesheet */ ssdoc = xmlParseMemory((char *) VARDATA(ssheet), VARSIZE(ssheet) - VARHDRSZ); if (ssdoc == NULL) xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "error parsing stylesheet as XML document"); /* After this call we need not free ssdoc separately */ stylesheet = xsltParseStylesheetDoc(ssdoc); if (stylesheet == NULL) xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "failed to parse stylesheet"); xslt_ctxt = xsltNewTransformContext(stylesheet, doctree); xslt_sec_prefs_error = false; if ((xslt_sec_prefs = xsltNewSecurityPrefs()) == NULL) xslt_sec_prefs_error = true; if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid) != 0) xslt_sec_prefs_error = true; if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid) != 0) xslt_sec_prefs_error = true; if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid) != 0) xslt_sec_prefs_error = true; if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid) != 0) xslt_sec_prefs_error = true; if (xsltSetSecurityPrefs(xslt_sec_prefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid) != 0) xslt_sec_prefs_error = true; if (xsltSetCtxtSecurityPrefs(xslt_sec_prefs, xslt_ctxt) != 0) xslt_sec_prefs_error = true; if (xslt_sec_prefs_error) ereport(ERROR, (errmsg("could not set libxslt security preferences"))); restree = xsltApplyStylesheetUser(stylesheet, doctree, params, NULL, NULL, xslt_ctxt); if (restree == NULL) xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "failed to apply stylesheet"); resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet); } PG_CATCH(); { if (stylesheet != NULL) xsltFreeStylesheet(stylesheet); if (restree != NULL) xmlFreeDoc(restree); if (doctree != NULL) xmlFreeDoc(doctree); if (xslt_sec_prefs != NULL) xsltFreeSecurityPrefs(xslt_sec_prefs); if (xslt_ctxt != NULL) xsltFreeTransformContext(xslt_ctxt); xsltCleanupGlobals(); pg_xml_done(xmlerrcxt, true); PG_RE_THROW(); } PG_END_TRY(); xsltFreeStylesheet(stylesheet); xmlFreeDoc(restree); xmlFreeDoc(doctree); xsltFreeSecurityPrefs(xslt_sec_prefs); xsltFreeTransformContext(xslt_ctxt); xsltCleanupGlobals(); pg_xml_done(xmlerrcxt, false); /* XXX this is pretty dubious, really ought to throw error instead */ if (resstat < 0) PG_RETURN_NULL(); result = cstring_to_text_with_len((char *) resstr, reslen); if (resstr) xmlFree(resstr); PG_RETURN_TEXT_P(result); #else /* !USE_LIBXSLT */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("xslt_process() is not available without libxslt"))); PG_RETURN_NULL(); #endif /* USE_LIBXSLT */ }