Automaked pazpar2. Bug #799. Preprocessor defines are put in cconfig.h and
[pazpar2-moved-to-github.git] / src / config.c
1 /* $Id: config.c,v 1.4 2007-01-08 12:43:41 adam Exp $ */
2
3 #include <string.h>
4
5 #include <libxml/parser.h>
6 #include <libxml/tree.h>
7 #include <libxslt/xslt.h>
8 #include <libxslt/transform.h>
9 #include <libxslt/xsltutils.h>
10
11 #if HAVE_CONFIG_H
12 #include <cconfig.h>
13 #endif
14
15 #include <yaz/yaz-util.h>
16 #include <yaz/nmem.h>
17
18 #define CONFIG_NOEXTERNS
19 #include "config.h"
20
21 static NMEM nmem = 0;
22 static char confdir[256] = ".";
23
24 struct conf_config *config = 0;
25
26 /* Code to parse configuration file */
27 /* ==================================================== */
28
29 static struct conf_service *parse_service(xmlNode *node)
30 {
31     xmlNode *n;
32     struct conf_service *r = nmem_malloc(nmem, sizeof(struct conf_service));
33
34     r->termlists = 0;
35
36     for (n = node->children; n; n = n->next)
37     {
38         if (n->type != XML_ELEMENT_NODE)
39             continue;
40         if (!strcmp(n->name, "termlist"))
41         {
42             struct conf_termlist *tl = nmem_malloc(nmem, sizeof(struct conf_termlist));
43             xmlChar *name = xmlGetProp(n, "name");
44             if (!name)
45             {
46                 yaz_log(YLOG_WARN, "Missing name attribute in termlist");
47                 continue;
48             }
49             tl->name = nmem_strdup(nmem, name);
50             tl->next = r->termlists;
51             r->termlists = tl;
52         }
53         else
54         {
55             yaz_log(YLOG_FATAL, "Bad element: %s", n->name);
56             return 0;
57         }
58     }
59     return r;
60 }
61
62 static struct conf_server *parse_server(xmlNode *node)
63 {
64     xmlNode *n;
65     struct conf_server *r = nmem_malloc(nmem, sizeof(struct conf_server));
66
67     r->host = 0;
68     r->port = 0;
69     r->proxy_host = 0;
70     r->proxy_port = 0;
71     r->service = 0;
72     r->next = 0;
73
74     for (n = node->children; n; n = n->next)
75     {
76         if (n->type != XML_ELEMENT_NODE)
77             continue;
78         if (!strcmp(n->name, "listen"))
79         {
80             xmlChar *port = xmlGetProp(n, "port");
81             xmlChar *host = xmlGetProp(n, "host");
82             if (port)
83                 r->port = atoi(port);
84             if (host)
85                 r->host = nmem_strdup(nmem, host);
86         }
87         else if (!strcmp(n->name, "proxy"))
88         {
89             xmlChar *port = xmlGetProp(n, "port");
90             xmlChar *host = xmlGetProp(n, "host");
91             if (port)
92                 r->proxy_port = atoi(port);
93             if (host)
94                 r->proxy_host = nmem_strdup(nmem, host);
95         }
96         else if (!strcmp(n->name, "service"))
97         {
98             struct conf_service *s = parse_service(n);
99             if (!s)
100                 return 0;
101             r->service = s;
102         }
103         else
104         {
105             yaz_log(YLOG_FATAL, "Bad element: %s", n->name);
106             return 0;
107         }
108     }
109     return r;
110 }
111
112 static xsltStylesheet *load_stylesheet(const char *fname)
113 {
114     char path[256];
115     sprintf(path, "%s/%s", confdir, fname);
116     return xsltParseStylesheetFile(path);
117 }
118
119 static void setup_marc(struct conf_retrievalprofile *r)
120 {
121     yaz_iconv_t cm;
122     r->yaz_marc = yaz_marc_create();
123     if (!(cm = yaz_iconv_open("utf-8", r->native_encoding)))
124     {
125         yaz_log(YLOG_WARN, "Unable to support mapping from %s", r->native_encoding);
126         return;
127     }
128     yaz_marc_iconv(r->yaz_marc, cm);
129 }
130
131 static struct conf_retrievalprofile *parse_retrievalprofile(xmlNode *node)
132 {
133     struct conf_retrievalprofile *r = nmem_malloc(nmem, sizeof(struct conf_retrievalprofile));
134     xmlNode *n;
135     struct conf_retrievalmap **rm = &r->maplist;
136
137     r->requestsyntax = 0;
138     r->native_syntax = Nativesyn_xml;
139     r->native_format = Nativeform_na;
140     r->native_encoding = 0;
141     r->native_mapto = Nativemapto_na;
142     r->yaz_marc = 0;
143     r->maplist = 0;
144     r->next = 0;
145
146     for (n = node->children; n; n = n->next)
147     {
148         if (n->type != XML_ELEMENT_NODE)
149             continue;
150         if (!strcmp(n->name, "requestsyntax"))
151         {
152             xmlChar *content = xmlNodeGetContent(n);
153             if (content)
154                 r->requestsyntax = nmem_strdup(nmem, content);
155         }
156         else if (!strcmp(n->name, "nativesyntax"))
157         {
158             xmlChar *name = xmlGetProp(n, "name");
159             xmlChar *format = xmlGetProp(n, "format");
160             xmlChar *encoding = xmlGetProp(n, "encoding");
161             xmlChar *mapto = xmlGetProp(n, "mapto");
162             if (!name)
163             {
164                 yaz_log(YLOG_WARN, "Missing name in 'nativesyntax' element");
165                 return 0;
166             }
167             if (!strcmp(name, "iso2709"))
168             {
169                 r->native_syntax = Nativesyn_iso2709;
170                 // Set a few defaults, too
171                 r->native_format = Nativeform_marc21;
172                 r->native_mapto = Nativemapto_marcxml;
173                 r->native_encoding = "marc-8";
174                 setup_marc(r);
175             }
176             else if (!strcmp(name, "xml"))
177                 r->native_syntax = Nativesyn_xml;
178             else
179             {
180                 yaz_log(YLOG_WARN, "Unknown native syntax name %s", name);
181                 return 0;
182             }
183             if (format)
184             {
185                 if (!strcmp(format, "marc21") || !strcmp(format, "usmarc"))
186                     r->native_format = Nativeform_marc21;
187                 else
188                 {
189                     yaz_log(YLOG_WARN, "Unknown native format name %s", format);
190                     return 0;
191                 }
192             }
193             if (encoding)
194                 r->native_encoding = encoding;
195             if (mapto)
196             {
197                 if (!strcmp(mapto, "marcxml"))
198                     r->native_mapto = Nativemapto_marcxml;
199                 else if (!strcmp(mapto, "marcxchange"))
200                     r->native_mapto = Nativemapto_marcxchange;
201                 else
202                 {
203                     yaz_log(YLOG_WARN, "Unknown mapto target %s", format);
204                     return 0;
205                 }
206             }
207         }
208         else if (!strcmp(n->name, "map"))
209         {
210             struct conf_retrievalmap *m = nmem_malloc(nmem, sizeof(struct conf_retrievalmap));
211             xmlChar *type = xmlGetProp(n, "type");
212             xmlChar *charset = xmlGetProp(n, "charset");
213             xmlChar *format = xmlGetProp(n, "format");
214             xmlChar *stylesheet = xmlGetProp(n, "stylesheet");
215             bzero(m, sizeof(*m));
216             if (type)
217             {
218                 if (!strcmp(type, "xslt"))
219                     m->type = Map_xslt;
220                 else
221                 {
222                     yaz_log(YLOG_WARN, "Unknown map type: %s", type);
223                     return 0;
224                 }
225             }
226             if (charset)
227                 m->charset = nmem_strdup(nmem, charset);
228             if (format)
229                 m->format = nmem_strdup(nmem, format);
230             if (stylesheet)
231             {
232                 if (!(m->stylesheet = load_stylesheet(stylesheet)))
233                     return 0;
234             }
235             *rm = m;
236             rm = &m->next;
237         }
238         else
239         {
240             yaz_log(YLOG_FATAL, "Bad element in retrievalprofile: %s", n->name);
241             return 0;
242         }
243     }
244
245     return r;
246 }
247
248 static struct conf_config *parse_config(xmlNode *root)
249 {
250     xmlNode *n;
251     struct conf_config *r = nmem_malloc(nmem, sizeof(struct conf_config));
252     struct conf_retrievalprofile **rp = &r->retrievalprofiles;
253
254     r->servers = 0;
255     r->queryprofiles = 0;
256     r->retrievalprofiles = 0;
257
258     for (n = root->children; n; n = n->next)
259     {
260         if (n->type != XML_ELEMENT_NODE)
261             continue;
262         if (!strcmp(n->name, "server"))
263         {
264             struct conf_server *tmp = parse_server(n);
265             if (!tmp)
266                 return 0;
267             tmp->next = r->servers;
268             r->servers = tmp;
269         }
270         else if (!strcmp(n->name, "queryprofile"))
271         {
272         }
273         else if (!strcmp(n->name, "retrievalprofile"))
274         {
275             if (!(*rp = parse_retrievalprofile(n)))
276                 return 0;
277             rp = &(*rp)->next;
278         }
279         else
280         {
281             yaz_log(YLOG_FATAL, "Bad element: %s", n->name);
282             return 0;
283         }
284     }
285     return r;
286 }
287
288 int read_config(const char *fname)
289 {
290     xmlDoc *doc = xmlReadFile(fname, NULL, 0);
291     const char *p;
292
293     if (!nmem)  // Initialize
294     {
295         nmem = nmem_create();
296         xmlSubstituteEntitiesDefault(1);
297         xmlLoadExtDtdDefaultValue = 1;
298     }
299     if (!doc)
300     {
301         yaz_log(YLOG_FATAL, "Failed to read %s", fname);
302         exit(1);
303     }
304     if ((p = rindex(fname, '/')))
305     {
306         int len = p - fname;
307         strncpy(confdir, fname, len);
308         confdir[len] = '\0';
309     }
310     config = parse_config(xmlDocGetRootElement(doc));
311     xmlFreeDoc(doc);
312
313     if (config)
314         return 1;
315     else
316         return 0;
317 }
318
319
320 /*
321  * Local variables:
322  * c-basic-offset: 4
323  * indent-tabs-mode: nil
324  * End:
325  * vim: shiftwidth=4 tabstop=8 expandtab
326  */