LDLIBS += -lxml2 -lopensrf -lxslt
-all: mod_xmltools.so mod_ils_rest_gateway.so
+all: mod_xmlbuilder.so mod_ils_rest_gateway.so
-install: mod_xmltools-install mod_ils_rest_gateway-install libfieldmapper-install
+install: mod_xmlbuilder-install mod_ils_rest_gateway-install libfieldmapper-install
-mod_xmltools.o: mod_xmltools.c mod_xmltools.h
+mod_xmlbuilder.o: mod_xmlbuilder.h mod_xmlbuilder.c
apachetools.o: apachetools.c apachetools.h
-xmltools.o: xmltools.c xmltools.h
json_xml.o: json_xml.c json_xml.h
fieldmapper_lookup.o: fieldmapper_lookup.c fieldmapper_lookup.h
ils_rest_gateway.o: mod_rest_gateway.c mod_rest_gateway.h
# ------------------------------------------------------
-mod_xmltools.so: mod_xmltools.o apachetools.o xmltools.o
+mod_xmlbuilder.so: mod_xmlbuilder.o apachetools.o
@echo $@
- $(CC) $(LDFLAGS) $(LDLIBS) -shared -W1 apachetools.o xmltools.o mod_xmltools.o -o $@
+ $(CC) $(LDFLAGS) $(LDLIBS) -shared -W1 apachetools.o mod_xmlbuilder.o -o $@
libfieldmapper.so: fieldmapper_lookup.o
@echo $@
echo "-----------------------------------------------";
echo ""
-mod_xmltools-install:
- $(APXS2) -i -a -n mod_xmltools mod_xmltools.so
- echo "-----------------------------------------------";
- echo -e "* Important * : Change httpd.conf from this: \n \
- LoadModule mod_xmltools_module modules/mod_xmltools.so \n \
- to this: \n \
- LoadModule mod_xmltools modules/mod_xmltools.so"
- echo -e "Supported configuration options:\
- \nXMLToolsDefaultLocale <locale>\
- \nXMLToolsLocaleDir <web-locale-dir>\
- \nXMLToolsPreXSL <pre_xsl_file>\
- \nXMLToolsPostXSL <post_xsl_file>"
- echo "-----------------------------------------------";
- echo ""
+mod_xmlbuilder-install:
+ $(APXS2) -i -a -n xmlbuilder mod_xmlbuilder.so
+
clean:
echo $@
- /bin/rm -f *.o xmltools mod_xmltools.so libfieldmapper.so mod_ils_rest_gateway.so
+ /bin/rm -f *.o mod_xmlbuilder.so libfieldmapper.so mod_ils_rest_gateway.so
/bin/rm -f fieldmapper_lookup.c
return NULL;
}
-
+
+int apacheDebug( char* msg, ... ) {
+ VA_LIST_TO_STRING(msg);
+ fprintf(stderr, "%s\n", VA_BUF);
+ fflush(stderr);
+ return 0;
+}
+
+
+int apacheError( char* msg, ... ) {
+ VA_LIST_TO_STRING(msg);
+ fprintf(stderr, "%s\n", VA_BUF);
+ fflush(stderr);
+ return HTTP_INTERNAL_SERVER_ERROR;
+}
+
+
#include "http_protocol.h"
#include "apr_compat.h"
#include "apr_strings.h"
+#include "apr_reslist.h"
+
#include "string_array.h"
#include "utils.h"
+#include "opensrf/utils.h"
#ifndef APACHE_TOOLS_H
#define APACHE_TOOLS_H
char* must be freed by the caller */
char* apacheGetFirstParamValue(string_array* params, char* key);
+/* Writes msg to stderr, flushes stderr, and returns 0 */
+int apacheDebug( char* msg, ... );
+
+/* Writes to stderr, flushe stderr, and returns HTTP_INTERNAL_SERVER_ERROR;
+ */
+int apacheError( char* msg, ... );
+
#endif
--- /dev/null
+#include "mod_xmlbuilder.h"
+
+char* __xmlBuilderDynamicLocale = NULL;
+
+
+/* set the base DTD directory */
+static const char* xmlBuilderSetBaseDir(cmd_parms *params, void *cfg, const char *arg) {
+ xmlBuilderConfig* config = ap_get_module_config(
+ params->server->module_config, &xmlbuilder_module );
+ config->baseDir = (char*) arg;
+ return NULL;
+}
+
+static const char* xmlBuilderSetDefaultLocale(
+ cmd_parms* params, void* cfg, const char* arg ) {
+ xmlBuilderConfig* config = ap_get_module_config(
+ params->server->module_config, &xmlbuilder_module );
+ config->defaultLocale = (char*) arg;
+ return NULL;
+}
+
+static const char* xmlBuilderSetDefaultDtd(
+ cmd_parms* params, void* cfg, const char* arg ) {
+ xmlBuilderConfig* config = ap_get_module_config(
+ params->server->module_config, &xmlbuilder_module );
+ config->defaultDtd = (char*) arg;
+ return NULL;
+}
+
+
+static const char* xmlBuilderSetLocaleParam(
+ cmd_parms* params, void* cfg, const char* arg ) {
+ xmlBuilderConfig* config = ap_get_module_config(
+ params->server->module_config, &xmlbuilder_module );
+ config->localeParam = (char*) arg;
+ return NULL;
+}
+
+
+static const char* xmlBuilderSetPostXSL(
+ cmd_parms* params, void* cfg, const char* arg ) {
+ xmlBuilderConfig* config = ap_get_module_config(
+ params->server->module_config, &xmlbuilder_module );
+ config->postXSL = xsltParseStylesheetFile((xmlChar*) arg);
+ if( config->postXSL == NULL )
+ apacheDebug("Unable to parse postXSL stylesheet: %s. No postXSL will be performed", arg);
+ return NULL;
+}
+
+static const command_rec xmlBuilderCommands[] = {
+ AP_INIT_TAKE1( MODXMLB_CONFIG_LOCALE,
+ xmlBuilderSetDefaultLocale, NULL, ACCESS_CONF, "Default Locale"),
+ AP_INIT_TAKE1( MODXMLB_CONFIG_BASE_DIR,
+ xmlBuilderSetBaseDir, NULL, ACCESS_CONF, "Base Directory"),
+ AP_INIT_TAKE1( MODXMLB_CONFIG_POST_XSL,
+ xmlBuilderSetPostXSL, NULL, ACCESS_CONF, "Post XSL"),
+ AP_INIT_TAKE1( MODXMLB_CONFIG_DEFAULT_DTD,
+ xmlBuilderSetDefaultDtd, NULL, ACCESS_CONF, "Default DTD"),
+ AP_INIT_TAKE1( MODXMLB_CONFIG_LOCALE_PARAM,
+ xmlBuilderSetLocaleParam, NULL, ACCESS_CONF, "Default DTD"),
+ {NULL}
+};
+
+static void* xmlBuilderCreateConfig( apr_pool_t* p, server_rec* s ) {
+ xmlBuilderConfig* config =
+ (xmlBuilderConfig*) apr_palloc( p, sizeof(xmlBuilderConfig) );
+ config->baseDir = MODXMLB_DEFAULT_BASE_DIR;
+ config->defaultLocale = MODXMLB_DEFAULT_LOCALE;
+ config->defaultDtd = NULL;
+ config->postXSL = NULL;
+ config->localeParam = MODXMLB_DEFAULT_LOCALE_PARAM;
+ return (void*) config;
+}
+
+
+/* Child Init handler ----------------------------------------------------------- */
+static void xmlBuilderChildInit( apr_pool_t *p, server_rec *s ) {
+}
+
+static int xmlBuilderHandler( request_rec* r ) {
+
+ if( strcmp(r->handler, MODULE_NAME ) ) return DECLINED;
+
+ xmlBuilderConfig* config = ap_get_module_config(
+ r->server->module_config, &xmlbuilder_module );
+
+ r->allowed |= (AP_METHOD_BIT << M_GET);
+ r->allowed |= (AP_METHOD_BIT << M_POST);
+ ap_set_content_type(r, "text/html; charset=utf-8");
+
+ string_array* params = apacheParseParms(r);
+ char* locale = apacheGetFirstParamValue(params, config->localeParam);
+ if(locale) __xmlBuilderDynamicLocale = locale;
+ char* XMLFile = r->filename;
+
+ apacheDebug("Processing file %s", XMLFile);
+ xmlDocPtr doc = xmlBuilderProcessFile( XMLFile, config );
+ if(!doc) return apacheError( "Unable to parse XML file %s", XMLFile );
+
+ /* apply the post XSL */
+ if(config->postXSL) {
+ xmlDocPtr newdoc;
+ newdoc = xsltApplyStylesheet(config->postXSL, doc, NULL );
+
+ if(newdoc == NULL) {
+ apacheDebug("Error applying postXSL... skipping.");
+ } else {
+ xmlFreeDoc(doc);
+ doc = newdoc;
+ }
+ }
+
+ char* docXML = xmlDocToString( doc, 1 );
+ ap_rputs(docXML, r);
+ free(docXML);
+ xmlFreeDoc( doc );
+ doc = NULL;
+ xmlCleanupCharEncodingHandlers();
+ xmlCleanupParser();
+
+ return OK;
+}
+
+
+/* frees the collected DTD's */
+static void __xmlBuilderFreeDtdHash( char* key, void* item ) {
+ if(!item) return;
+ xmlFreeDtd( item );
+}
+
+
+xmlDocPtr xmlBuilderProcessFile( char* filename, xmlBuilderConfig* config ) {
+ if(!filename) {
+ apacheError( "No XML file provided" ); return NULL; }
+
+ xmlBuilderContext context;
+ context.config = config;
+ context.doc = xmlNewDoc( BAD_CAST "1.0" );
+ context.dtdHash = osrfNewHash();
+ context.entHash = osrfNewHash();
+ context.nodeList = osrfNewList();
+ context.xmlError = 0;
+ context.xmlFile = filename;
+ context.dtdHash->freeItem = &__xmlBuilderFreeDtdHash;
+
+ /* pre-parse the default dtd if defined */
+ if( config->defaultDtd )
+ xmlBuilderAddDtd( config->defaultDtd, &context );
+
+ xmlParserCtxtPtr parserCtx;
+
+ parserCtx = xmlCreatePushParserCtxt(xmlBuilderSaxHandler, &context, "", 0, NULL);
+ xmlCtxtReadFile( parserCtx, filename, NULL, XML_PARSE_RECOVER );
+
+ xmlFreeParserCtxt( parserCtx );
+ osrfListFree(context.nodeList);
+ osrfHashFree(context.entHash);
+ osrfHashFree(context.dtdHash);
+ return context.doc;
+}
+
+
+void xmlBuilderStartElement( void* context, const xmlChar *name, const xmlChar **atts ) {
+ apacheDebug( "Starting element: %s", name );
+ xmlBuilderContext* ctx = (xmlBuilderContext*) context;
+
+ xmlNodePtr node = NULL;
+
+ /* process xincludes as a sub-doc */
+ if( !strcmp( name, "xi:include" ) ) {
+
+ char* href = strdup(xmlSaxAttr( atts, "href" ));
+ if(href) {
+
+ /* find the relative path for the xinclude */
+ if(href[0] != '/') {
+ int len = strlen(ctx->xmlFile) + strlen(href) + 1;
+ char buf[len];
+ bzero(buf, len);
+ strcpy( buf, ctx->xmlFile );
+ int i;
+ for( i = strlen(buf); i != 0; i-- ) {
+ if( buf[i] == '/' ) break;
+ buf[i] = '\0';
+ }
+ strcat( buf, href );
+ free(href);
+ href = strdup(buf);
+ }
+
+
+ apacheDebug( "Processing xinclude %s", href );
+ xmlDocPtr subDoc = xmlBuilderProcessFile( href, ctx->config );
+ node = xmlDocGetRootElement( subDoc );
+ }
+
+ if(!node) {
+ apacheError("Unable to parse xinclude: %s", href );
+ return;
+ }
+
+ } else {
+ node = xmlNewNode(NULL, name);
+ xmlAddAttrs( node, atts );
+ }
+
+
+ xmlNodePtr parent = osrfListGetIndex(
+ ctx->nodeList, ctx->nodeList->size - 1 );
+
+ if( parent ) xmlAddChild( parent, node );
+ else xmlDocSetRootElement(ctx->doc, node);
+
+ osrfListPush( ctx->nodeList, node );
+}
+
+void xmlBuilderEndElement( void* context, const xmlChar* name ) {
+ xmlBuilderContext* ctx = (xmlBuilderContext*) context;
+ osrfListPop( ctx->nodeList );
+}
+
+
+void xmlBuilderHandleCharacter(void* context, const xmlChar *ch, int len) {
+ xmlBuilderContext* ctx = (xmlBuilderContext*) context;
+ xmlNodePtr node = osrfListGetIndex(
+ ctx->nodeList, ctx->nodeList->size - 1 );
+
+ if(node) {
+ xmlNodePtr txt = xmlNewTextLen(ch, len);
+ xmlAddChild( node, txt );
+ }
+
+}
+
+
+void xmlBuilderParseError( void* context, const char* msg, ... ) {
+ xmlBuilderContext* ctx = (xmlBuilderContext*) context;
+ VA_LIST_TO_STRING(msg);
+ apacheDebug( "Parser Error Occurred: %s", VA_BUF);
+ ctx->xmlError = 1;
+}
+
+
+xmlEntityPtr xmlBuilderGetEntity( void* context, const xmlChar* name ) {
+ xmlBuilderContext* ctx = (xmlBuilderContext*) context;
+ return osrfHashGet( ctx->entHash, name );
+}
+
+
+void xmlBuilderExtSubset( void* blob,
+ const xmlChar* name, const xmlChar* extId, const xmlChar* sysId ) {
+
+ xmlBuilderContext* context = (xmlBuilderContext*) blob;
+ if( context->config->defaultDtd ) return; /* only use the default if defined */
+ xmlBuilderAddDtd( sysId, context );
+}
+
+
+
+void xmlBuilderAddDtd( const char* sysId, xmlBuilderContext* context ) {
+
+ if(!sysId) return;
+ if( osrfHashGet( context->dtdHash, sysId ) ) return; /* already parsed this hash */
+
+ /* use the dynamic locale if defined... default locale instead */
+ char* locale;
+ if(__xmlBuilderDynamicLocale) locale = __xmlBuilderDynamicLocale;
+ else locale = context->config->defaultLocale;
+
+ /* determine the path to the DTD file and load it */
+ int len = strlen(context->config->baseDir) + strlen(locale) + strlen(sysId) + 4;
+ char buf[len]; bzero(buf,len);
+ snprintf( buf, len, "%s/%s/%s", context->config->baseDir, locale, sysId );
+
+ apacheDebug("Parsing DTD file %s", buf);
+ xmlDtdPtr dtd = xmlParseDTD(NULL, buf);
+
+
+ /* cycle through entities and push them into the entity hash */
+ xmlNodePtr node = dtd->children;
+ while( node ) {
+ if( node->type == XML_ENTITY_DECL ) { /* shove the entities into the hash */
+ xmlEntityPtr ent = (xmlEntityPtr) node;
+ osrfHashSet( context->entHash, ent, (char*) ent->name );
+ }
+ node = node->next;
+ }
+
+ /* cache the DTD so we can free it later */
+ osrfHashSet( context->dtdHash, dtd, sysId );
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/* register callbacks */
+static void xmlBuilderRegisterHooks (apr_pool_t *p) {
+ ap_hook_handler(xmlBuilderHandler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init(xmlBuilderChildInit,NULL,NULL,APR_HOOK_MIDDLE);
+}
+
+
+/* finally, flesh the module */
+module AP_MODULE_DECLARE_DATA xmlbuilder_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL,
+ NULL,
+ xmlBuilderCreateConfig,
+ NULL,
+ xmlBuilderCommands,
+ xmlBuilderRegisterHooks,
+};
+
+
+
+
+
+
+/*
+char* get_dtd_lang_file(string_array* params, char* default_locale, char* locale_dir) {
+
+ char* locale = apacheGetFirstParamValue(params, PARAM_LOCALE);
+ if(!locale) locale = default_locale;
+ if(!locale) return NULL;
+
+ int len = strlen(LANG_DTD) + strlen(locale) + strlen(locale_dir) + 1;
+ char dtdfile[len];
+ bzero(dtdfile, len);
+
+ if(locale)
+ sprintf(dtdfile, "%s/%s/%s", locale_dir, locale, LANG_DTD );
+
+ return strdup(dtdfile);
+}
+*/
+
+
--- /dev/null
+#include "apachetools.h"
+#include "opensrf/xml_utils.h"
+#include "opensrf/osrf_hash.h"
+#include "opensrf/osrf_list.h"
+#include <libxslt/xslt.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+#define MODULE_NAME "xmlbuilder_module" /* our module name */
+
+/* ------------------------------------------------------------------------------ */
+/* Apache config items. These are defaults which are only used if they are not
+ overriden by the Apache config or URL where appropriate */
+/* ------------------------------------------------------------------------------ */
+/* The default directory where the DTD files are stored */
+#define MODXMLB_DEFAULT_LOCALE_PARAM "locale"
+#define MODXMLB_DEFAULT_BASE_DIR "/openils/var/web/locale"
+#define MODXMLB_DEFAULT_LOCALE "en-US"
+#define MODXMLB_DEFAULT_DTD NULL /* if defined, use this DTD only */
+/* ------------------------------------------------------------------------------ */
+
+#define MODXMLB_CONFIG_LOCALE "XMLBuilderDefaultLocale"
+#define MODXMLB_CONFIG_BASE_DIR "XMLBuilderBaseDir"
+#define MODXMLB_CONFIG_POST_XSL "XMLBuilderPostXSL"
+#define MODXMLB_CONFIG_DEFAULT_DTD "XMLBuilderDefaultDTD"
+#define MODXMLB_CONFIG_LOCALE_PARAM "XMLBuilderLocaleParam"
+
+
+
+/* This module */
+module AP_MODULE_DECLARE_DATA xmlbuilder_module;
+
+
+/* our config structure */
+typedef struct {
+
+ char* baseDir; /* directory on disk where the DTD files live */
+ char* defaultLocale; /* locale dir from config or default */
+ char* defaultDtd; /* if defined, we load this DTD only */
+ char* localeParam; /* the CGI param used to choose the locale dir dynamically */
+ xsltStylesheetPtr postXSL; /* if defined, run this XSL after parsing */
+
+} xmlBuilderConfig;
+
+typedef struct {
+ xmlBuilderConfig* config;
+ xmlDocPtr doc;
+ osrfHash* entHash;
+ osrfHash* dtdHash;
+ osrfList* nodeList;
+ int xmlError;
+ char* xmlFile;
+} xmlBuilderContext;
+
+
+
+xmlDocPtr xmlBuilderProcessFile( char* XMLFile, xmlBuilderConfig* config );
+
+void xmlBuilderAddDtd( const char* sysId, xmlBuilderContext* context );
+
+
+/* SAX Callbacks */
+void xmlBuilderStartElement( void* blob, const xmlChar *name, const xmlChar **atts );
+void xmlBuilderEndElement( void* blob, const xmlChar* name );
+void xmlBuilderHandleCharacter(void* blob, const xmlChar *ch, int len);
+void xmlBuilderParseError( void* blob, const char* msg, ... );
+xmlEntityPtr xmlBuilderGetEntity( void* blob, const xmlChar* name );
+void xmlBuilderExtSubset( void* blob, const xmlChar* name, const xmlChar* extId, const xmlChar* sysId );
+
+static xmlSAXHandler xmlBuilderSaxHandlerStruct = {
+ NULL, /* internalSubset */
+ NULL, /* isStandalone */
+ NULL, /* hasInternalSubset */
+ NULL, /* hasExternalSubset */
+ NULL, /* resolveEntity */
+ xmlBuilderGetEntity, /* getEntity */
+ NULL, /* entityDecl */
+ NULL, /* notationDecl */
+ NULL, /* attributeDecl */
+ NULL, /* elementDecl */
+ NULL, /* unparsedEntityDecl */
+ NULL, /* setDocumentLocator */
+ NULL, /* startDocument */
+ NULL, /* endDocument */
+ xmlBuilderStartElement, /* startElement */
+ xmlBuilderEndElement, /* endElement */
+ NULL, /* reference */
+ xmlBuilderHandleCharacter, /* characters */
+ NULL, /* ignorableWhitespace */
+ NULL, /* processingInstruction */
+ NULL, /* comment */
+ xmlBuilderParseError, /* xmlParserWarning */
+ xmlBuilderParseError, /* xmlParserError */
+ NULL, /* xmlParserFatalError : unused */
+ NULL, /* getParameterEntity */
+ NULL, /* cdataBlock; */
+ xmlBuilderExtSubset, /* externalSubset; */
+ 1,
+ NULL,
+ NULL, /* startElementNs */
+ NULL, /* endElementNs */
+ NULL /* xmlStructuredErrorFunc */
+};
+static const xmlSAXHandlerPtr xmlBuilderSaxHandler = &xmlBuilderSaxHandlerStruct;
+
+
+++ /dev/null
-#include "mod_xmltools.h"
-
-
-/* Configuration handlers -------------------------------------------------------- */
-static const char* mod_xmltools_set_locale_dir(cmd_parms *parms, void *config, const char *arg) {
- mod_xmltools_config *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools_module);
- cfg->locale_dir = (char*) arg;
- return NULL;
-}
-
-static const char* mod_xmltools_set_default_locale(cmd_parms *parms, void *config, const char *arg) {
- mod_xmltools_config *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools_module);
- cfg->default_locale = (char*) arg;
- return NULL;
-}
-
-static const char* mod_xmltools_set_pre_xsl(cmd_parms *parms, void *config, const char *arg) {
- mod_xmltools_config *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools_module);
- cfg->pre_xsl = xsltParseStylesheetFile( (xmlChar*) arg );
- if(cfg->pre_xsl == NULL) {
- fprintf(stderr, "Unable to parse PreXSL stylesheet %s\n", (char*) arg );
- fflush(stderr);
- }
- return NULL;
-}
-
-static const char* mod_xmltools_set_post_xsl(cmd_parms *parms, void *config, const char *arg) {
- mod_xmltools_config *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools_module);
- cfg->post_xsl = xsltParseStylesheetFile( (xmlChar*) arg );
- if(cfg->post_xsl == NULL) {
- fprintf(stderr, "Unable to parse PostXSL stylesheet %s\n", (char*) arg );
- fflush(stderr);
- }
- return NULL;
-}
-
-/* tell apache about our commands */
-static const command_rec mod_xmltools_cmds[] = {
- AP_INIT_TAKE1( CONFIG_LOCALE, mod_xmltools_set_default_locale, NULL, RSRC_CONF, "default locale"),
- AP_INIT_TAKE1( CONFIG_LOCALE_DIR, mod_xmltools_set_locale_dir, NULL, RSRC_CONF, "locale directory"),
- AP_INIT_TAKE1( CONFIG_PRE_XSL, mod_xmltools_set_pre_xsl, NULL, RSRC_CONF, "pre xsl"),
- AP_INIT_TAKE1( CONFIG_POST_XSL, mod_xmltools_set_post_xsl, NULL, RSRC_CONF, "post xsl"),
- {NULL}
-};
-
-/* build the config object */
-static void* mod_xmltools_create_config( apr_pool_t* p, server_rec* s) {
- mod_xmltools_config* cfg =
- (mod_xmltools_config*) apr_palloc(p, sizeof(mod_xmltools_config));
- cfg->default_locale = DEFAULT_LOCALE;
- cfg->locale_dir = DEFAULT_LOCALE_DIR;
- cfg->pre_xsl = NULL;
- cfg->post_xsl = NULL;
- return (void*) cfg;
-}
-
-
-/* Child Init handler ----------------------------------------------------------- */
-static void mod_xmltools_child_init(apr_pool_t *p, server_rec *s) {
-}
-
-
-/* Request handler -------------------------------------------------------------- */
-static int mod_xmltools_handler (request_rec* r) {
-
- /* make sure we're needed first thing*/
- if (strcmp(r->handler, MODULE_NAME ))
- return DECLINED;
-
- mod_xmltools_config *cfg = ap_get_module_config(r->server->module_config, &mod_xmltools_module);
- char* locale_dir = cfg->locale_dir;
- char* default_locale = cfg->default_locale;
- xsltStylesheetPtr pre_xsl = cfg->pre_xsl;
- xsltStylesheetPtr post_xsl = cfg->post_xsl;
-
- /* we accept get/post requests */
- r->allowed |= (AP_METHOD_BIT << M_GET);
- r->allowed |= (AP_METHOD_BIT << M_POST);
-
- ap_set_content_type(r, "text/html; charset=utf-8");
-
- string_array* params = apacheParseParms(r);
-
- char* file = r->filename;
- char* dtdfile = get_dtd_lang_file(params, default_locale, locale_dir );
-
- xmlDocPtr doc;
-
- /* be explicit */
- xmlSubstituteEntitiesDefault(0);
-
- /* parse the doc */
- if( (doc = xmlParseFile(file)) == NULL) {
- fprintf(stderr, "\n ^-- Error parsing XML file %s\n", file);
- fflush(stderr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- fflush(stderr);
-
-
- if(pre_xsl) {
- xmlDocPtr newdoc;
- newdoc = xsltApplyStylesheet(pre_xsl, doc, NULL );
- if(newdoc == NULL) {
- fprintf(stderr, "Error applying PreXSL stylesheet\n");
- fflush(stderr);
- }
- xmlFreeDoc(doc);
- doc = newdoc;
- }
-
- fflush(stderr);
-
- /* process xincludes */
- if( xmlXIncludeProcess(doc) < 0 ) {
- fprintf(stderr, "\n ^-- Error processing XIncludes for file %s\n", file);
- fflush(stderr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* replace the DTD */
- if(xmlReplaceDtd(doc, dtdfile) < 0) {
- fprintf(stderr, "Error replacing DTD file with file %s\n", dtdfile);
- fflush(stderr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-
- /* force DTD entity replacement */
- doc = xmlProcessDtdEntities(doc);
-
- if(post_xsl) {
- xmlDocPtr newdoc;
- newdoc = xsltApplyStylesheet(post_xsl, doc, NULL );
- if(newdoc == NULL) {
- fprintf(stderr, "Error applying PostXSL stylesheet\n");
- fflush(stderr);
- }
- xmlFreeDoc(doc);
- doc = newdoc;
- }
-
- /* stringify */
- char* xml = xmlDocToString(doc, 0);
-
- /* print the doc */
- ap_rputs(xml, r);
-
- /* deallocate */
- free(dtdfile);
- free(xml);
- xmlFreeDoc(doc);
- xmlCleanupCharEncodingHandlers();
- xmlCleanupParser();
-
- return OK;
-
-}
-
-
-/* register callbacks */
-static void mod_xmltools_register_hooks (apr_pool_t *p) {
- ap_hook_handler(mod_xmltools_handler, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_child_init(mod_xmltools_child_init,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-
-/* finally, flesh the module */
-module AP_MODULE_DECLARE_DATA mod_xmltools_module = {
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- mod_xmltools_create_config,
- NULL,
- mod_xmltools_cmds,
- mod_xmltools_register_hooks,
-};
-
-
-
-/* UTILITY FUNCTIONS ----------------------------------------------------- */
-char* get_dtd_lang_file(string_array* params, char* default_locale, char* locale_dir) {
-
- /* if no locale is provided via URL, we use the default */
- char* locale = apacheGetFirstParamValue(params, PARAM_LOCALE);
- if(!locale) locale = default_locale;
- if(!locale) return NULL;
-
- int len = strlen(LANG_DTD) + strlen(locale) + strlen(locale_dir) + 1;
- char dtdfile[len];
- bzero(dtdfile, len);
-
- if(locale)
- sprintf(dtdfile, "%s/%s/%s", locale_dir, locale, LANG_DTD );
-
- return strdup(dtdfile);
-}
-
-
+++ /dev/null
-#include "apachetools.h"
-#include "xmltools.h"
-#include <libxslt/xslt.h>
-#include <libxslt/transform.h>
-#include <libxslt/xsltutils.h>
-
-#define MODULE_NAME "mod_xmltools_module" /* our module name */
-#define PARAM_LOCALE "locale" /* the URL param for the local directory */
-#define LANG_DTD "lang.dtd" /* the DTD for the test entities */
-
-
-/* ------------------------------------------------------------------------------ */
-/* Apache config items. These are defaults which are only used if they are not
- overriden by the Apache config or URL where appropriate */
-/* ------------------------------------------------------------------------------ */
-/* The default directory where the local files are stored */
-#define DEFAULT_LOCALE_DIR "/openils/var/locale"
-#define DEFAULT_LOCALE "en-US"
-/* ------------------------------------------------------------------------------ */
-
-#define CONFIG_LOCALE "XMLToolsDefaultLocale"
-#define CONFIG_LOCALE_DIR "XMLToolsLocaleDir"
-#define CONFIG_PRE_XSL "XMLToolsPreXSL"
-#define CONFIG_POST_XSL "XMLToolsPostXSL"
-
-
-
-/* This module */
-module AP_MODULE_DECLARE_DATA mod_xmltools_module;
-
-
-/* our config structure */
-typedef struct {
-
- char* locale_dir; /* directory on disk where the locale directories live */
- char* default_locale;
-
- xsltStylesheetPtr pre_xsl;
- xsltStylesheetPtr post_xsl;
-
-} mod_xmltools_config;
-
-
-
-/* allocates a char* to hold the name of the DTD language file
- Prints to stderr and returns NULL if there was an error loading the file
- default_locale comes from the apache config and is used only if no
- locale is provided via URL
- locale_dir also comes from the apache config.
- */
-char* get_dtd_lang_file(string_array* params, char* default_locale, char* locale_dir);
+++ /dev/null
-#include "xmltools.h"
-
-
-#ifdef XMLTOOLS_DEBUG // standalone debugging
-
-int main(int argc, char* argv[]) {
-
- char* file = argv[1];
- char* dtdfile = argv[2];
-
-
- printf("\n%s\n", xmlDocToString(xmlParseEntity(file), 1));
-
- xmlDocPtr doc;
-
- xmlSubstituteEntitiesDefault(1);
- xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
- doc = xmlCtxtReadFile(ctxt, file, NULL, XML_PARSE_NOENT | XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING );
- if(doc != NULL)
- fprintf(stderr, "What we have so far:\n%s\n", xmlDocToString(doc, 1));
- else {
- fprintf(stderr, "NO Doc\n");
- return 0;
- }
-
- /* parse the doc */
- /*
- if( (doc = xmlParseFile(file)) == NULL) {
- fprintf(stderr, "\n ^-- Error parsing XML file %s\n", file);
- fflush(stderr);
- return 99;
- }
- */
-
- /* process xincludes */
- if( xmlXIncludeProcessFlags(doc, XML_PARSE_NOENT) < 0 ) {
- fprintf(stderr, "\n ^-- Error processing XIncludes for file %s\n", file);
- if(doc != NULL)
- fprintf(stderr, "What we have so far:\n%s\n", xmlDocToString(doc, 1));
- fflush(stderr);
- return 99;
- }
-
-
-
- /* replace the DTD */
- /*
- if(xmlReplaceDtd(doc, dtdfile) < 0) {
- fprintf(stderr, "Error replacing DTD file with file %s\n", dtdfile);
- fflush(stderr);
- return 99;
- }
- */
-
- //
- xmlAddDocEntity(doc, "test", XML_INTERNAL_GENERAL_ENTITY, NULL, NULL, "Here is my test");
-
- xmlSubstituteEntitiesDefault(1);
- printf("---------------------------------\n%s\n", xmlDocToString(doc,1));
- exit(99);
- //
-
- /* force DTD entity replacement */
- doc = xmlProcessDtdEntities(doc);
-
- /* stringify */
- char* xml = xmlDocToString(doc, 0);
-
- fprintf(stderr, "%s\n", xml);
-
- /* deallocate */
- free(xml);
- xmlFreeDoc(doc);
- xmlCleanupCharEncodingHandlers();
- xmlCleanupParser();
-
-
-}
-
-#endif
-
-xmlDocPtr xmlProcessDtdEntities(xmlDocPtr doc) {
- char* xml = xmlDocToString(doc, 1);
- xmlFreeDoc(doc);
- xmlSubstituteEntitiesDefault(1);
- xmlDocPtr d = xmlParseMemory(xml, strlen(xml));
- free(xml);
- return d;
-}
-
-
-int xmlReplaceDtd(xmlDocPtr doc, char* dtdfile) {
-
- if(!doc || !dtdfile) return 0;
-
- /* remove the original DTD */
- if(doc->children && doc->children->type == XML_DTD_NODE) {
- xmlNodePtr p = doc->children;
- xmlUnlinkNode(p);
- xmlFreeNode(p);
- }
-
-
- xmlDtdPtr dtd = xmlParseDTD(NULL, dtdfile);
-
- if(!dtd) {
- fprintf(stderr, "Error parsing DTD file %s\n", dtdfile);
- fflush(stderr);
- return -1;
- }
-
- dtd->name = xmlStrdup((xmlChar*)"x");
- doc->extSubset = dtd;
- dtd->doc = doc;
- dtd->parent = doc;
- xmlNodePtr x = doc->children;
- doc->children = (xmlNodePtr)dtd;
- dtd->next = x;
-
- return 1;
-}
-
-char* xmlDocToString(xmlDocPtr doc, int full) {
-
- if(!doc) return NULL;
-
- char* xml;
-
- if(full) {
-
- xmlChar* xmlbuf;
- int size;
- xmlDocDumpMemory(doc, &xmlbuf, &size);
- xml = strdup((char*) (xmlbuf));
- xmlFree(xmlbuf);
- return xml;
-
- } else {
-
- xmlBufferPtr xmlbuf = xmlBufferCreate();
- xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
- xml = strdup((char*) (xmlBufferContent(xmlbuf)));
- xmlBufferFree(xmlbuf);
- return xml;
-
- }
-}
-
-
+++ /dev/null
-
-/* general headers */
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-
-/* libxml2 headers */
-#include <libxml/parser.h>
-#include <libxml/globals.h>
-#include <libxml/xinclude.h>
-#include <libxml/xmlwriter.h>
-#include <libxml/xmlreader.h>
-
-
-#ifndef XMLTOOLS_H
-#define XMLTOOLS_H
-
-
-/* turns a doc into a string. string must be deallocated.
- if 'full', then the entire doc is stringified, otherwise
- the root node (on down) is stringified */
-char* xmlDocToString(xmlDocPtr doc, int full);
-
-int xmlReplaceDtd(xmlDocPtr doc, char* dtdfile);
-
-/* Inline DTD Entity replacement.
- creates a new doc with the entities replaced, frees the
- doc provided and returns a new one.
- Do this and you'll be OK:
- doc = xmlProcessDtdEntities(doc);
- */
-xmlDocPtr xmlProcessDtdEntities(xmlDocPtr doc);
-
-
-#endif
-
-