apachetools is some generic apache module helper functions
authorerickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Thu, 4 Aug 2005 22:13:11 +0000 (22:13 +0000)
committererickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Thu, 4 Aug 2005 22:13:11 +0000 (22:13 +0000)
xmltools are some generic xml helper functions
mod_xmltools is the beginning of our XML monster for
processing DTDs, xincludes, and potentially xslt's

git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@464 9efc2488-bf62-4759-914b-345cdb29e865

src/apachemods/Makefile [new file with mode: 0644]
src/apachemods/apachetools.c [new file with mode: 0644]
src/apachemods/apachetools.h [new file with mode: 0644]
src/apachemods/mod_xmltools.c [new file with mode: 0644]
src/apachemods/xmltools.c [new file with mode: 0644]
src/apachemods/xmltools.h [new file with mode: 0644]

diff --git a/src/apachemods/Makefile b/src/apachemods/Makefile
new file mode 100644 (file)
index 0000000..1932c7e
--- /dev/null
@@ -0,0 +1,27 @@
+LD_OPTS        += -lxml2 -lc_utils
+
+all: mod_xmltools.so
+
+mod_xmltools.so: apachetools.o  xmltools.o
+       $(CC) -c $(CC_OPTS) mod_xmltools.c 
+       $(CC) $(LD_OPTS) -shared -W1 apachetools.o xmltools.o mod_xmltools.o -o $@
+
+apachetools.o: apachetools.c apachetools.h
+       $(CC) -c $(CC_OPTS)  apachetools.c -o $@
+
+xmltools.o:    xmltools.c xmltools.h   
+       $(CC) -c $(CC_OPTS) xmltools.c -o $@
+
+
+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 "-----------------------------------------------";
+       @sleep 3;
+
+clean:
+       /bin/rm -f *.o xmltools
diff --git a/src/apachemods/apachetools.c b/src/apachemods/apachetools.c
new file mode 100644 (file)
index 0000000..2891d15
--- /dev/null
@@ -0,0 +1,113 @@
+#include "apachetools.h"
+
+string_array* apacheParseParms(request_rec* r) {
+
+       if( r == NULL ) return NULL;
+
+       char* arg = r->args;                    /* url query string */
+       apr_pool_t *p = r->pool;        /* memory pool */
+       string_array* sarray                    = init_string_array(12); /* method parameters */
+
+       growing_buffer* buffer          = NULL; /* POST data */
+       growing_buffer* tmp_buf         = NULL; /* temp buffer */
+
+       char* key                                               = NULL; /* query item name */
+       char* val                                               = NULL; /* query item value */
+
+
+       /* gather the post args and append them to the url query string */
+       if( !strcmp(r->method,"POST") ) {
+
+               ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
+
+               if(ap_should_client_block(r)) {
+
+                       char body[1025];
+                       memset(body,0,1025);
+                       buffer = buffer_init(1025);
+       
+                       while(ap_get_client_block(r, body, 1024)) {
+                               buffer_add( buffer, body );
+                               memset(body,0,1025);
+                       }
+       
+                       if(arg && arg[0]) {
+
+                               tmp_buf = buffer_init(1024);
+                               buffer_add(tmp_buf,arg);
+                               buffer_add(tmp_buf,buffer->buf);
+                               arg = (char*) apr_pstrdup(p, tmp_buf->buf);
+                               buffer_free(tmp_buf);
+
+                       } else {
+                               arg = (char*) apr_pstrdup(p, buffer->buf);
+                       }
+
+                       buffer_free(buffer);
+               }
+       } 
+
+
+       if( ! arg || !arg[0] ) { /* we received no request */
+               return NULL;
+       }
+
+
+       while( arg && (val = ap_getword(p, (const char**) &arg, '&'))) {
+
+               key = ap_getword(r->pool, (const char**) &val, '=');
+               if(!key || !key[0])
+                       break;
+
+               ap_unescape_url((char*)key);
+               ap_unescape_url((char*)val);
+
+               string_array_add(sarray, key);
+               string_array_add(sarray, val);
+
+       }
+
+       return sarray;
+
+}
+
+
+
+string_array* apacheGetParamKeys(string_array* params) {
+       if(params == NULL) return NULL; 
+       string_array* sarray    = init_string_array(12); 
+       int i;
+       for( i = 0; i < params->size; i++ ) 
+               string_array_add(sarray, string_array_get_string(params, i++)); 
+       return sarray;
+}
+
+string_array* apacheGetParamValues(string_array* params, char* key) {
+
+       if(params == NULL || key == NULL) return NULL;  
+       string_array* sarray    = init_string_array(12); 
+
+       int i;
+       for( i = 0; i < params->size; i++ ) {
+               char* nkey = string_array_get_string(params, i++);      
+               if(key && !strcmp(nkey, key)) 
+                       string_array_add(sarray, string_array_get_string(params, i));   
+       }
+       return sarray;
+}
+
+
+char* apacheGetFirstParamValue(string_array* params, char* key) {
+       if(params == NULL || key == NULL) return NULL;  
+
+       int i;
+       for( i = 0; i < params->size; i++ ) {
+               char* nkey = string_array_get_string(params, i++);      
+               if(key && !strcmp(nkey, key)) 
+                       return strdup(string_array_get_string(params, i));
+       }
+
+       return NULL;
+}
+
+       
diff --git a/src/apachemods/apachetools.h b/src/apachemods/apachetools.h
new file mode 100644 (file)
index 0000000..d082c57
--- /dev/null
@@ -0,0 +1,37 @@
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "apr_compat.h"
+#include "apr_strings.h"
+
+#include "string_array.h"
+#include "utils.h"
+
+#ifndef APACHE_TOOLS_H
+#define APACHE_TOOLS_H
+
+
+/* parses apache URL params (GET and POST).  
+       Returns a string_array of the form [ key, val, key, val, ...]
+       Returns NULL if there are no params */
+string_array* apacheParseParms(request_rec* r);
+
+/* provide the params string array, and this will generate a 
+       string of array of param keys 
+       the returned string_array most be freed by the caller
+       */
+string_array* apacheGetParamKeys(string_array* params);
+
+/* provide the params string array and a key name, and 
+       this will provide the value found for that key 
+       the returned string_array most be freed by the caller
+       */
+string_array* apacheGetParamValues(string_array* params, char* key);
+
+/* returns the first value found for the given param.  
+       char* must be freed by the caller */
+char* apacheGetFirstParamValue(string_array* params, char* key);
+
+
+#endif
diff --git a/src/apachemods/mod_xmltools.c b/src/apachemods/mod_xmltools.c
new file mode 100644 (file)
index 0000000..41caeb6
--- /dev/null
@@ -0,0 +1,116 @@
+#include "apachetools.h"
+#include "xmltools.h"
+
+#define MODULE_NAME            "mod_xmltools" /* 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 */
+
+/* these should be config directives */
+#define LOCALE_DIR             "/home/erickson/sandbox/apachemods/locale"              /* The root directory where the local files are stored */
+#define DEFAULT_LOCALE "en-US"                 /* If no locale data is provided */
+
+
+/* Child Init */
+static void mod_xmltools_child_init(apr_pool_t *p, server_rec *s) {
+}
+
+/* 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 
+       */
+
+static char* get_dtd_lang_file(string_array* params) {
+
+       char* localedir = apacheGetFirstParamValue(params, PARAM_LOCALE);
+       if(!localedir) localedir = strdup(DEFAULT_LOCALE);
+
+       int len = strlen(LANG_DTD) + strlen(localedir) + strlen(LOCALE_DIR) + 1;
+       char dtdfile[len];
+       bzero(dtdfile, len);
+
+       if(localedir)
+               sprintf(dtdfile, "%s/%s/%s",  LOCALE_DIR, localedir, LANG_DTD );
+
+       return strdup(dtdfile);
+}
+
+static int mod_xmltools_handler (request_rec* r) {
+
+       /* make sure we're needed first thing*/
+       if (strcmp(r->handler, MODULE_NAME )) 
+               return DECLINED;
+
+       /* 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");
+
+       string_array* params = apacheParseParms(r);
+
+       char* file = r->filename;
+       char* dtdfile = get_dtd_lang_file(params);
+
+       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;
+       }
+
+       /* 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);
+
+       /* stringify */
+       char* xml = xmlDocToString(doc, 0);
+
+       /* print the doc */
+       ap_rputs(xml, r);
+
+       /* deallocate */
+       free(dtdfile);
+       free(xml);
+       xmlFreeDoc(doc);
+       xmlCleanupCharEncodingHandlers();
+       xmlCleanupParser();
+       
+       return OK;
+
+}
+
+
+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);
+}
+
+module AP_MODULE_DECLARE_DATA mod_xmltools = {
+       STANDARD20_MODULE_STUFF,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       mod_xmltools_register_hooks,
+};
+
diff --git a/src/apachemods/xmltools.c b/src/apachemods/xmltools.c
new file mode 100644 (file)
index 0000000..fb92b89
--- /dev/null
@@ -0,0 +1,130 @@
+#include "xmltools.h"
+
+#define TEXT_DTD "test2.dtd"
+
+
+
+/*
+int main( int argc, char* argv[] ) {
+
+       char* file = argv[1];
+       char* localedir = argv[2];
+
+       int len = strlen(TEXT_DTD) + strlen(localedir) + 1;
+       char dtdfile[len];
+       bzero(dtdfile, len);
+
+       if(localedir)
+               sprintf(dtdfile, "%s/%s",  localedir, TEXT_DTD );
+
+
+       if(access(dtdfile, R_OK)) {
+               fprintf(stderr, "Unable to open DTD file %s\n", dtdfile);
+               fflush(stderr);
+               return HTTP_INTERNAL_SERVER_ERROR;
+       }
+
+
+       xmlDocPtr doc;
+
+       xmlSubstituteEntitiesDefault(0);
+
+
+       if( (doc = xmlParseFile(file)) == NULL) {
+               fprintf(stderr, "\n ^-- Error parsing XML file %s\n", file);
+               fflush(stderr);
+               return HTTP_INTERNAL_SERVER_ERROR;
+       }
+
+       if( xmlXIncludeProcess(doc) < 0 ) {
+               fprintf(stderr, "\n ^-- Error processing XIncludes for file %s\n", file);
+               fflush(stderr);
+               return HTTP_INTERNAL_SERVER_ERROR;
+       }
+
+       xmlReplaceDtd(doc, dtdfile);
+
+       doc = xmlProcessDtdEntities(doc);
+
+       char* xml = xmlDocToString(doc, 0);
+
+       printf("\n%s\n", xml);
+
+       free(xml);
+       xmlFreeDoc(doc);
+       xmlCleanupCharEncodingHandlers();
+       xmlCleanupParser();
+
+       return 0;
+
+}
+*/
+
+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;
+       }
+
+       fprintf(stderr, "2\n");
+       fflush(stderr);
+
+       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) {
+
+       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;
+
+       }
+
+}
diff --git a/src/apachemods/xmltools.h b/src/apachemods/xmltools.h
new file mode 100644 (file)
index 0000000..b5baeed
--- /dev/null
@@ -0,0 +1,39 @@
+
+/* 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>
+
+#include "apachetools.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
+
+