1 /* $Id: config.c,v 1.17 2007-03-20 07:27:51 adam Exp $ */
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>
15 #include <yaz/yaz-util.h>
18 #define CONFIG_NOEXTERNS
22 static char confdir[256] = ".";
24 struct conf_config *config = 0;
26 /* Code to parse configuration file */
27 /* ==================================================== */
29 static struct conf_service *parse_service(xmlNode *node)
32 struct conf_service *r = nmem_malloc(nmem, sizeof(struct conf_service));
36 r->num_sortkeys = r->num_metadata = 0;
37 // Allocate array of conf metadata and sortkey tructs, if necessary
38 for (n = node->children; n; n = n->next)
39 if (n->type == XML_ELEMENT_NODE && !strcmp((const char *)
42 xmlChar *sortkey = xmlGetProp(n, (xmlChar *) "sortkey");
44 if (sortkey && strcmp((const char *) sortkey, "no"))
49 r->metadata = nmem_malloc(nmem, sizeof(struct conf_metadata) * r->num_metadata);
53 r->sortkeys = nmem_malloc(nmem, sizeof(struct conf_sortkey) * r->num_sortkeys);
57 for (n = node->children; n; n = n->next)
59 if (n->type != XML_ELEMENT_NODE)
61 if (!strcmp(n->name, (const char *) "metadata"))
63 struct conf_metadata *md = &r->metadata[md_node];
64 xmlChar *name = xmlGetProp(n, "name");
65 xmlChar *brief = xmlGetProp(n, "brief");
66 xmlChar *sortkey = xmlGetProp(n, "sortkey");
67 xmlChar *merge = xmlGetProp(n, "merge");
68 xmlChar *type = xmlGetProp(n, "type");
69 xmlChar *termlist = xmlGetProp(n, "termlist");
70 xmlChar *rank = xmlGetProp(n, "rank");
74 yaz_log(YLOG_FATAL, "Must specify name in metadata element");
77 md->name = nmem_strdup(nmem, name);
80 if (!strcmp(brief, "yes"))
82 else if (strcmp(brief, "no"))
84 yaz_log(YLOG_FATAL, "metadata/brief must be yes or no");
93 if (!strcmp(termlist, "yes"))
95 else if (strcmp(termlist, "no"))
97 yaz_log(YLOG_FATAL, "metadata/termlist must be yes or no");
105 md->rank = atoi(rank);
111 if (!strcmp(type, "generic"))
112 md->type = Metadata_type_generic;
113 else if (!strcmp(type, "year"))
114 md->type = Metadata_type_year;
117 yaz_log(YLOG_FATAL, "Unknown value for metadata/type: %s", type);
122 md->type = Metadata_type_generic;
126 if (!strcmp(merge, "no"))
127 md->merge = Metadata_merge_no;
128 else if (!strcmp(merge, "unique"))
129 md->merge = Metadata_merge_unique;
130 else if (!strcmp(merge, "longest"))
131 md->merge = Metadata_merge_longest;
132 else if (!strcmp(merge, "range"))
133 md->merge = Metadata_merge_range;
134 else if (!strcmp(merge, "all"))
135 md->merge = Metadata_merge_all;
138 yaz_log(YLOG_FATAL, "Unknown value for metadata/merge: %s", merge);
143 md->merge = Metadata_merge_no;
145 if (sortkey && strcmp(sortkey, "no"))
147 struct conf_sortkey *sk = &r->sortkeys[sk_node];
148 if (md->merge == Metadata_merge_no)
150 yaz_log(YLOG_FATAL, "Can't specify sortkey on a non-merged field");
153 if (!strcmp(sortkey, "numeric"))
154 sk->type = Metadata_sortkey_numeric;
155 else if (!strcmp(sortkey, "skiparticle"))
156 sk->type = Metadata_sortkey_skiparticle;
159 yaz_log(YLOG_FATAL, "Unknown sortkey in metadata element: %s", sortkey);
163 md->sortkey_offset = sk_node;
167 md->sortkey_offset = -1;
179 yaz_log(YLOG_FATAL, "Bad element: %s", n->name);
186 static struct conf_server *parse_server(xmlNode *node)
189 struct conf_server *r = nmem_malloc(nmem, sizeof(struct conf_server));
199 for (n = node->children; n; n = n->next)
201 if (n->type != XML_ELEMENT_NODE)
203 if (!strcmp(n->name, "listen"))
205 xmlChar *port = xmlGetProp(n, "port");
206 xmlChar *host = xmlGetProp(n, "host");
208 r->port = atoi(port);
210 r->host = nmem_strdup(nmem, host);
214 else if (!strcmp(n->name, "proxy"))
216 xmlChar *port = xmlGetProp(n, "port");
217 xmlChar *host = xmlGetProp(n, "host");
218 xmlChar *myurl = xmlGetProp(n, "myurl");
220 r->proxy_port = atoi(port);
222 r->proxy_host = nmem_strdup(nmem, host);
224 r->myurl = nmem_strdup(nmem, myurl);
227 yaz_log(YLOG_FATAL, "Must specify @myurl for proxy");
234 else if (!strcmp(n->name, "service"))
236 struct conf_service *s = parse_service(n);
243 yaz_log(YLOG_FATAL, "Bad element: %s", n->name);
250 static xsltStylesheet *load_stylesheet(const char *fname)
253 sprintf(path, "%s/%s", confdir, fname);
254 return xsltParseStylesheetFile(path);
257 static void setup_marc(struct conf_retrievalprofile *r)
260 r->yaz_marc = yaz_marc_create();
261 if (!(cm = yaz_iconv_open("utf-8", r->native_encoding)))
263 yaz_log(YLOG_WARN, "Unable to support mapping from %s", r->native_encoding);
266 yaz_marc_iconv(r->yaz_marc, cm);
269 static struct conf_retrievalprofile *parse_retrievalprofile(xmlNode *node)
271 struct conf_retrievalprofile *r = nmem_malloc(nmem, sizeof(struct conf_retrievalprofile));
273 struct conf_retrievalmap **rm = &r->maplist;
275 r->requestsyntax = 0;
276 r->native_syntax = Nativesyn_xml;
277 r->native_format = Nativeform_na;
278 r->native_encoding = 0;
279 r->native_mapto = Nativemapto_na;
284 for (n = node->children; n; n = n->next)
286 if (n->type != XML_ELEMENT_NODE)
288 if (!strcmp(n->name, "requestsyntax"))
290 xmlChar *content = xmlNodeGetContent(n);
292 r->requestsyntax = nmem_strdup(nmem, content);
294 else if (!strcmp(n->name, "nativesyntax"))
296 xmlChar *name = xmlGetProp(n, "name");
297 xmlChar *format = xmlGetProp(n, "format");
298 xmlChar *encoding = xmlGetProp(n, "encoding");
299 xmlChar *mapto = xmlGetProp(n, "mapto");
302 yaz_log(YLOG_WARN, "Missing name in 'nativesyntax' element");
306 r->native_encoding = encoding;
307 if (!strcmp(name, "iso2709"))
309 r->native_syntax = Nativesyn_iso2709;
310 // Set a few defaults, too
311 r->native_format = Nativeform_marc21;
312 r->native_mapto = Nativemapto_marcxml;
313 if (!r->native_encoding)
314 r->native_encoding = "marc-8";
317 else if (!strcmp(name, "xml"))
318 r->native_syntax = Nativesyn_xml;
321 yaz_log(YLOG_WARN, "Unknown native syntax name %s", name);
326 if (!strcmp(format, "marc21") || !strcmp(format, "usmarc"))
327 r->native_format = Nativeform_marc21;
330 yaz_log(YLOG_WARN, "Unknown native format name %s", format);
336 if (!strcmp(mapto, "marcxml"))
337 r->native_mapto = Nativemapto_marcxml;
338 else if (!strcmp(mapto, "marcxchange"))
339 r->native_mapto = Nativemapto_marcxchange;
342 yaz_log(YLOG_WARN, "Unknown mapto target %s", format);
351 else if (!strcmp(n->name, "map"))
353 struct conf_retrievalmap *m = nmem_malloc(nmem, sizeof(struct conf_retrievalmap));
354 xmlChar *type = xmlGetProp(n, "type");
355 xmlChar *charset = xmlGetProp(n, "charset");
356 xmlChar *format = xmlGetProp(n, "format");
357 xmlChar *stylesheet = xmlGetProp(n, "stylesheet");
358 memset(m, 0, sizeof(*m));
361 if (!strcmp(type, "xslt"))
365 yaz_log(YLOG_WARN, "Unknown map type: %s", type);
370 m->charset = nmem_strdup(nmem, charset);
372 m->format = nmem_strdup(nmem, format);
375 if (!(m->stylesheet = load_stylesheet(stylesheet)))
387 yaz_log(YLOG_FATAL, "Bad element in retrievalprofile: %s", n->name);
395 static struct conf_targetprofiles *parse_targetprofiles(xmlNode *node)
397 struct conf_targetprofiles *r = nmem_malloc(nmem, sizeof(*r));
398 xmlChar *type = xmlGetProp(node, "type");
399 xmlChar *src = xmlGetProp(node, "src");
401 memset(r, 0, sizeof(*r));
405 if (!strcmp(type, "local"))
406 r->type = Targetprofiles_local;
409 yaz_log(YLOG_FATAL, "Unknown targetprofile type");
415 yaz_log(YLOG_FATAL, "Must specify type for targetprofile");
420 r->src = nmem_strdup(nmem, src);
423 yaz_log(YLOG_FATAL, "Must specify src in targetprofile");
431 static struct conf_config *parse_config(xmlNode *root)
434 struct conf_config *r = nmem_malloc(nmem, sizeof(struct conf_config));
435 struct conf_retrievalprofile **rp = &r->retrievalprofiles;
438 r->queryprofiles = 0;
439 r->retrievalprofiles = 0;
440 r->targetprofiles = 0;
442 for (n = root->children; n; n = n->next)
444 if (n->type != XML_ELEMENT_NODE)
446 if (!strcmp(n->name, "server"))
448 struct conf_server *tmp = parse_server(n);
451 tmp->next = r->servers;
454 else if (!strcmp(n->name, "queryprofile"))
457 else if (!strcmp(n->name, "retrievalprofile"))
459 if (!(*rp = parse_retrievalprofile(n)))
463 else if (!strcmp(n->name, "targetprofiles"))
465 // It would be fun to be able to fix this sometime
466 if (r->targetprofiles)
468 yaz_log(YLOG_FATAL, "Can't repeat targetprofiles");
471 if (!(r->targetprofiles = parse_targetprofiles(n)))
476 yaz_log(YLOG_FATAL, "Bad element: %s", n->name);
483 int read_config(const char *fname)
485 xmlDoc *doc = xmlParseFile(fname);
488 if (!nmem) // Initialize
490 nmem = nmem_create();
491 xmlSubstituteEntitiesDefault(1);
492 xmlLoadExtDtdDefaultValue = 1;
496 yaz_log(YLOG_FATAL, "Failed to read %s", fname);
499 if ((p = strrchr(fname, '/')))
502 strncpy(confdir, fname, len);
505 config = parse_config(xmlDocGetRootElement(doc));
518 * indent-tabs-mode: nil
520 * vim: shiftwidth=4 tabstop=8 expandtab