aa7f843c466fdb9a503278bee04662a1170cddc7
[working/Evergreen.git] / Open-ILS / src / apachemods / mod_xmltools.c
1 #include "mod_xmltools.h"
2
3
4 /* Configuration handlers -------------------------------------------------------- */
5 static const char* mod_xmltools_set_locale_dir(cmd_parms *parms, void *config, const char *arg) {
6         mod_xmltools_config  *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools);
7         cfg->locale_dir = (char*) arg;
8         return NULL;
9 }
10
11 static const char* mod_xmltools_set_default_locale(cmd_parms *parms, void *config, const char *arg) {
12         mod_xmltools_config *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools);
13         cfg->default_locale = (char*) arg;
14         return NULL;
15 }
16
17 static const char* mod_xmltools_set_pre_xsl(cmd_parms *parms, void *config, const char *arg) {
18         mod_xmltools_config *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools);
19         cfg->pre_xsl = xsltParseStylesheetFile( (xmlChar*) arg );
20         if(cfg->pre_xsl == NULL) {
21                 fprintf(stderr, "Unable to parse PreXSL stylesheet %s\n", (char*) arg );
22                 fflush(stderr);
23         }
24         return NULL;
25 }
26
27 static const char* mod_xmltools_set_post_xsl(cmd_parms *parms, void *config, const char *arg) {
28         mod_xmltools_config *cfg = ap_get_module_config(parms->server->module_config, &mod_xmltools);
29         cfg->post_xsl = xsltParseStylesheetFile( (xmlChar*) arg );
30         if(cfg->post_xsl == NULL) {
31                 fprintf(stderr, "Unable to parse PostXSL stylesheet %s\n", (char*) arg );
32                 fflush(stderr);
33         }
34         return NULL;
35 }
36
37 /* tell apache about our commands */
38 static const command_rec mod_xmltools_cmds[] = {
39         AP_INIT_TAKE1( CONFIG_LOCALE, mod_xmltools_set_default_locale, NULL, RSRC_CONF, "default locale"),
40         AP_INIT_TAKE1( CONFIG_LOCALE_DIR, mod_xmltools_set_locale_dir, NULL, RSRC_CONF, "locale directory"),
41         AP_INIT_TAKE1( CONFIG_PRE_XSL, mod_xmltools_set_pre_xsl, NULL, RSRC_CONF, "pre xsl"),
42         AP_INIT_TAKE1( CONFIG_POST_XSL, mod_xmltools_set_post_xsl, NULL, RSRC_CONF, "post xsl"),
43         {NULL}
44 };
45
46 /* build the config object */
47 static void* mod_xmltools_create_config( apr_pool_t* p, server_rec* s) {
48         mod_xmltools_config* cfg = 
49                 (mod_xmltools_config*) apr_palloc(p, sizeof(mod_xmltools_config));
50         cfg->default_locale = DEFAULT_LOCALE;
51         cfg->locale_dir = DEFAULT_LOCALE_DIR;
52         return (void*) cfg;
53 }
54
55
56 /* Child Init handler  ----------------------------------------------------------- */
57 static void mod_xmltools_child_init(apr_pool_t *p, server_rec *s) {
58 }
59
60
61 /* Request handler  -------------------------------------------------------------- */
62 static int mod_xmltools_handler (request_rec* r) {
63
64         /* make sure we're needed first thing*/
65         if (strcmp(r->handler, MODULE_NAME )) 
66                 return DECLINED;
67
68         mod_xmltools_config *cfg = ap_get_module_config(r->server->module_config, &mod_xmltools);
69         char* locale_dir = cfg->locale_dir;
70         char* default_locale = cfg->default_locale;
71         xsltStylesheetPtr pre_xsl = cfg->pre_xsl;
72         xsltStylesheetPtr post_xsl = cfg->post_xsl;
73
74         /* we accept get/post requests */
75         r->allowed |= (AP_METHOD_BIT << M_GET);
76         r->allowed |= (AP_METHOD_BIT << M_POST);
77
78         ap_set_content_type(r, "text/html");
79
80         string_array* params = apacheParseParms(r);
81
82         char* file = r->filename;
83         char* dtdfile = get_dtd_lang_file(params, default_locale, locale_dir );
84
85         xmlDocPtr doc;
86
87         /* be explicit */
88         xmlSubstituteEntitiesDefault(0);
89
90         /* parse the doc */
91         if( (doc = xmlParseFile(file)) == NULL) {
92                 fprintf(stderr, "\n ^-- Error parsing XML file %s\n", file);
93                 fflush(stderr);
94                 return HTTP_INTERNAL_SERVER_ERROR;
95         }
96
97         fflush(stderr);
98
99         if(pre_xsl) {
100                 xmlDocPtr newdoc;
101                 newdoc = xsltApplyStylesheet(pre_xsl, doc, NULL );
102                 if(newdoc == NULL) {
103                         fprintf(stderr, "Error applying PreXSL stylesheet\n");
104                         fflush(stderr);
105                 }
106                 xmlFreeDoc(doc);
107                 doc = newdoc;
108         }
109
110         /* process xincludes */
111         if( xmlXIncludeProcess(doc) < 0 ) {
112                 fprintf(stderr, "\n ^-- Error processing XIncludes for file %s\n", file);
113                 fflush(stderr);
114                 return HTTP_INTERNAL_SERVER_ERROR;
115         }
116
117         fflush(stderr);
118
119         /* replace the DTD */
120         if(xmlReplaceDtd(doc, dtdfile) < 0) {
121                 fprintf(stderr, "Error replacing DTD file with file %s\n", dtdfile);
122                 fflush(stderr);
123                 return HTTP_INTERNAL_SERVER_ERROR;
124         }
125
126
127         /* force DTD entity replacement */
128         doc = xmlProcessDtdEntities(doc);
129
130         if(post_xsl) {
131                 xmlDocPtr newdoc;
132                 newdoc = xsltApplyStylesheet(post_xsl, doc, NULL );
133                 if(newdoc == NULL) {
134                         fprintf(stderr, "Error applying PostXSL stylesheet\n");
135                         fflush(stderr);
136                 }
137                 xmlFreeDoc(doc);
138                 doc = newdoc;
139         }
140
141         /* stringify */
142         char* xml = xmlDocToString(doc, 0);
143
144         /* print the doc */
145         ap_rputs(xml, r);
146
147         /* deallocate */
148         free(dtdfile);
149         free(xml);
150         xmlFreeDoc(doc);
151         xmlCleanupCharEncodingHandlers();
152         xmlCleanupParser();
153         
154         return OK;
155
156 }
157
158
159 /* register callbacks */
160 static void mod_xmltools_register_hooks (apr_pool_t *p) {
161         ap_hook_handler(mod_xmltools_handler, NULL, NULL, APR_HOOK_MIDDLE);
162         ap_hook_child_init(mod_xmltools_child_init,NULL,NULL,APR_HOOK_MIDDLE);
163 }
164
165
166 /* finally, flesh the module */
167 module AP_MODULE_DECLARE_DATA mod_xmltools = {
168         STANDARD20_MODULE_STUFF,
169         NULL,
170         NULL,
171         mod_xmltools_create_config,
172         NULL,
173         mod_xmltools_cmds,
174         mod_xmltools_register_hooks,
175 };
176
177
178
179 /* UTILITY FUNCTIONS ----------------------------------------------------- */
180 char* get_dtd_lang_file(string_array* params, char* default_locale, char* locale_dir) {
181
182         /* if no locale is provided via URL, we use the default */
183         char* locale = apacheGetFirstParamValue(params, PARAM_LOCALE);
184         if(!locale) locale = default_locale;
185         if(!locale) return NULL;
186
187         int len = strlen(LANG_DTD) + strlen(locale) + strlen(locale_dir) + 1;
188         char dtdfile[len];
189         bzero(dtdfile, len);
190
191         if(locale)
192                 sprintf(dtdfile, "%s/%s/%s",  locale_dir, locale, LANG_DTD );
193
194         return strdup(dtdfile);
195 }
196
197