240bc0655680714a07e16e7b540ac54e44903c4c
[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_module);
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_module);
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_module);
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_module);
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         cfg->pre_xsl = NULL;
53         cfg->post_xsl = NULL;
54         return (void*) cfg;
55 }
56
57
58 /* Child Init handler  ----------------------------------------------------------- */
59 static void mod_xmltools_child_init(apr_pool_t *p, server_rec *s) {
60 }
61
62
63 /* Request handler  -------------------------------------------------------------- */
64 static int mod_xmltools_handler (request_rec* r) {
65
66         /* make sure we're needed first thing*/
67         if (strcmp(r->handler, MODULE_NAME )) 
68                 return DECLINED;
69
70         mod_xmltools_config *cfg = ap_get_module_config(r->server->module_config, &mod_xmltools_module);
71         char* locale_dir = cfg->locale_dir;
72         char* default_locale = cfg->default_locale;
73         xsltStylesheetPtr pre_xsl = cfg->pre_xsl;
74         xsltStylesheetPtr post_xsl = cfg->post_xsl;
75
76         /* we accept get/post requests */
77         r->allowed |= (AP_METHOD_BIT << M_GET);
78         r->allowed |= (AP_METHOD_BIT << M_POST);
79
80         ap_set_content_type(r, "text/html; charset=utf-8");
81
82         string_array* params = apacheParseParms(r);
83
84         char* file = r->filename;
85         char* dtdfile = get_dtd_lang_file(params, default_locale, locale_dir );
86
87         xmlDocPtr doc;
88
89         /* be explicit */
90         xmlSubstituteEntitiesDefault(0);
91
92         /* parse the doc */
93         if( (doc = xmlParseFile(file)) == NULL) {
94                 fprintf(stderr, "\n ^-- Error parsing XML file %s\n", file);
95                 fflush(stderr);
96                 return HTTP_INTERNAL_SERVER_ERROR;
97         }
98
99         fflush(stderr);
100
101
102         if(pre_xsl) {
103                 xmlDocPtr newdoc;
104                 newdoc = xsltApplyStylesheet(pre_xsl, doc, NULL );
105                 if(newdoc == NULL) {
106                         fprintf(stderr, "Error applying PreXSL stylesheet\n");
107                         fflush(stderr);
108                 }
109                 xmlFreeDoc(doc);
110                 doc = newdoc;
111         }
112
113         fflush(stderr);
114
115         /* process xincludes */
116         if( xmlXIncludeProcess(doc) < 0 ) {
117                 fprintf(stderr, "\n ^-- Error processing XIncludes for file %s\n", file);
118                 fflush(stderr);
119                 return HTTP_INTERNAL_SERVER_ERROR;
120         }
121
122         /* replace the DTD */
123         if(xmlReplaceDtd(doc, dtdfile) < 0) {
124                 fprintf(stderr, "Error replacing DTD file with file %s\n", dtdfile);
125                 fflush(stderr);
126                 return HTTP_INTERNAL_SERVER_ERROR;
127         }
128
129
130         /* force DTD entity replacement */
131         doc = xmlProcessDtdEntities(doc);
132
133         if(post_xsl) {
134                 xmlDocPtr newdoc;
135                 newdoc = xsltApplyStylesheet(post_xsl, doc, NULL );
136                 if(newdoc == NULL) {
137                         fprintf(stderr, "Error applying PostXSL stylesheet\n");
138                         fflush(stderr);
139                 }
140                 xmlFreeDoc(doc);
141                 doc = newdoc;
142         }
143
144         /* stringify */
145         char* xml = xmlDocToString(doc, 0);
146
147         /* print the doc */
148         ap_rputs(xml, r);
149
150         /* deallocate */
151         free(dtdfile);
152         free(xml);
153         xmlFreeDoc(doc);
154         xmlCleanupCharEncodingHandlers();
155         xmlCleanupParser();
156         
157         return OK;
158
159 }
160
161
162 /* register callbacks */
163 static void mod_xmltools_register_hooks (apr_pool_t *p) {
164         ap_hook_handler(mod_xmltools_handler, NULL, NULL, APR_HOOK_MIDDLE);
165         ap_hook_child_init(mod_xmltools_child_init,NULL,NULL,APR_HOOK_MIDDLE);
166 }
167
168
169 /* finally, flesh the module */
170 module AP_MODULE_DECLARE_DATA mod_xmltools_module = {
171         STANDARD20_MODULE_STUFF,
172         NULL,
173         NULL,
174         mod_xmltools_create_config,
175         NULL,
176         mod_xmltools_cmds,
177         mod_xmltools_register_hooks,
178 };
179
180
181
182 /* UTILITY FUNCTIONS ----------------------------------------------------- */
183 char* get_dtd_lang_file(string_array* params, char* default_locale, char* locale_dir) {
184
185         /* if no locale is provided via URL, we use the default */
186         char* locale = apacheGetFirstParamValue(params, PARAM_LOCALE);
187         if(!locale) locale = default_locale;
188         if(!locale) return NULL;
189
190         int len = strlen(LANG_DTD) + strlen(locale) + strlen(locale_dir) + 1;
191         char dtdfile[len];
192         bzero(dtdfile, len);
193
194         if(locale)
195                 sprintf(dtdfile, "%s/%s/%s",  locale_dir, locale, LANG_DTD );
196
197         return strdup(dtdfile);
198 }
199
200