27 #include <libxml/parser.h>
28 #include <libxml/tree.h>
30 #include <yaz/yaz-util.h>
32 #include <yaz/snprintf.h>
33 #include <yaz/tpath.h>
34 #include <yaz/xml_include.h>
36 #include <sys/types.h>
63 xsltStylesheetPtr
xsp;
69 const char *service_id)
72 NMEM
nmem = nmem_create();
75 service = nmem_malloc(nmem,
sizeof(
struct conf_service));
95 service->
id = service_id ? nmem_strdup(nmem, service_id) : 0;
146 NMEM nmem = service->
nmem;
149 || field_id < 0 || !(field_id < service->num_metadata))
153 assert(nmem && md && name);
155 md->
name = nmem_strdup(nmem, name);
168 md->
rank = nmem_strdup_null(nmem, rank);
171 md->
facetrule = nmem_strdup_null(nmem, facetrule);
172 md->
limitmap = nmem_strdup_null(nmem, limitmap);
173 md->
limitcluster = nmem_strdup_null(nmem, limitcluster);
184 NMEM nmem = service->
nmem;
187 || field_id < 0 || !(field_id < service->num_sortkeys))
192 assert(nmem && sk && name);
194 sk->
name = nmem_strdup(nmem, name);
208 if (!strcmp(name, (service->
metadata[i]).name))
222 if (!strcmp(name, (service->
sortkeys[i]).name))
230 !yaz_is_abspath(src))
232 wrbuf_printf(w,
"%s/%s", wrbuf_cstr(config->
confdir), src);
247 yaz_mutex_destroy(&service->
mutex);
248 nmem_destroy(service->
nmem);
255 yaz_log(YLOG_LOG,
"service_incref. p=%p cnt=%d", service,
261 int *md_node,
int *sk_node)
269 int sortkey_offset = 0;
270 xmlChar *xml_name = 0;
271 xmlChar *xml_brief = 0;
272 xmlChar *xml_sortkey = 0;
273 xmlChar *xml_merge = 0;
274 xmlChar *xml_type = 0;
275 xmlChar *xml_termlist = 0;
276 xmlChar *xml_rank = 0;
277 xmlChar *xml_setting = 0;
278 xmlChar *xml_mergekey = 0;
279 xmlChar *xml_limitmap = 0;
280 xmlChar *xml_limitcluster = 0;
281 xmlChar *xml_icu_chain = 0;
283 struct _xmlAttr *attr;
287 for (attr = n->properties; attr; attr = attr->next)
289 if (!xmlStrcmp(attr->name, BAD_CAST
"name") &&
290 attr->children && attr->children->type == XML_TEXT_NODE)
291 xml_name = attr->children->content;
292 else if (!xmlStrcmp(attr->name, BAD_CAST
"brief") &&
293 attr->children && attr->children->type == XML_TEXT_NODE)
294 xml_brief = attr->children->content;
295 else if (!xmlStrcmp(attr->name, BAD_CAST
"sortkey") &&
296 attr->children && attr->children->type == XML_TEXT_NODE)
297 xml_sortkey = attr->children->content;
298 else if (!xmlStrcmp(attr->name, BAD_CAST
"merge") &&
299 attr->children && attr->children->type == XML_TEXT_NODE)
300 xml_merge = attr->children->content;
301 else if (!xmlStrcmp(attr->name, BAD_CAST
"type") &&
302 attr->children && attr->children->type == XML_TEXT_NODE)
303 xml_type = attr->children->content;
304 else if (!xmlStrcmp(attr->name, BAD_CAST
"termlist") &&
305 attr->children && attr->children->type == XML_TEXT_NODE)
306 xml_termlist = attr->children->content;
307 else if (!xmlStrcmp(attr->name, BAD_CAST
"rank") &&
308 attr->children && attr->children->type == XML_TEXT_NODE)
309 xml_rank = attr->children->content;
310 else if (!xmlStrcmp(attr->name, BAD_CAST
"setting") &&
311 attr->children && attr->children->type == XML_TEXT_NODE)
312 xml_setting = attr->children->content;
313 else if (!xmlStrcmp(attr->name, BAD_CAST
"mergekey") &&
314 attr->children && attr->children->type == XML_TEXT_NODE)
315 xml_mergekey = attr->children->content;
316 else if (!xmlStrcmp(attr->name, BAD_CAST
"facetrule") &&
317 attr->children && attr->children->type == XML_TEXT_NODE)
318 xml_icu_chain = attr->children->content;
319 else if (!xmlStrcmp(attr->name, BAD_CAST
"limitmap") &&
320 attr->children && attr->children->type == XML_TEXT_NODE)
321 xml_limitmap = attr->children->content;
322 else if (!xmlStrcmp(attr->name, BAD_CAST
"limitcluster") &&
323 attr->children && attr->children->type == XML_TEXT_NODE)
324 xml_limitcluster = attr->children->content;
327 yaz_log(YLOG_FATAL,
"Unknown metadata attribute '%s'", attr->name);
335 yaz_log(YLOG_FATAL,
"Must specify name in metadata element");
340 if (!strcmp((
const char *) xml_brief,
"yes"))
342 else if (strcmp((
const char *) xml_brief,
"no"))
344 yaz_log(YLOG_FATAL,
"metadata/brief must be yes or no");
351 if (!strcmp((
const char *) xml_termlist,
"yes"))
353 else if (strcmp((
const char *) xml_termlist,
"no"))
355 yaz_log(YLOG_FATAL,
"metadata/termlist must be yes or no");
362 if (!strcmp((
const char *) xml_type,
"generic"))
364 else if (!strcmp((
const char *) xml_type,
"year"))
366 else if (!strcmp((
const char *) xml_type,
"date"))
371 "Unknown value for metadata/type: %s", xml_type);
378 if (!strcmp((
const char *) xml_merge,
"no"))
380 else if (!strcmp((
const char *) xml_merge,
"unique"))
382 else if (!strcmp((
const char *) xml_merge,
"longest"))
384 else if (!strcmp((
const char *) xml_merge,
"range"))
386 else if (!strcmp((
const char *) xml_merge,
"all"))
388 else if (!strcmp((
const char *) xml_merge,
"first"))
393 "Unknown value for metadata/merge: %s", xml_merge);
400 if (!strcmp((
const char *) xml_setting,
"no"))
402 else if (!strcmp((
const char *) xml_setting,
"postproc"))
404 else if (!strcmp((
const char *) xml_setting,
"parameter"))
409 "Unknown value for medadata/setting: %s", xml_setting);
415 if (xml_sortkey && strcmp((
const char *) xml_sortkey,
"no"))
421 "Can't specify sortkey on a non-merged field");
424 if (!strcmp((
const char *) xml_sortkey,
"numeric"))
426 else if (!strcmp((
const char *) xml_sortkey,
"skiparticle"))
431 "Unknown sortkey in metadata element: %s",
435 sortkey_offset = *sk_node;
438 (
const char *) xml_name, sk_type);
446 if (!strcmp((
const char *) xml_mergekey,
"required"))
448 else if (!strcmp((
const char *) xml_mergekey,
"optional"))
450 else if (!strcmp((
const char *) xml_mergekey,
"no"))
454 yaz_log(YLOG_FATAL,
"Unknown value for mergekey: %s", xml_mergekey);
461 (
const char *) xml_name,
462 type, merge, setting,
464 (
const char *) xml_rank, sortkey_offset,
466 (
const char *) xml_icu_chain,
467 (
const char *) xml_limitmap,
468 (
const char *) xml_limitcluster);
475 const char *service_id)
484 int got_settings = 0;
487 for (n = node->children; n; n = n->next)
488 if (n->type == XML_ELEMENT_NODE && !strcmp((
const char *)
489 n->name,
"metadata"))
491 xmlChar *sortkey = xmlGetProp(n, (xmlChar *)
"sortkey");
493 if (sortkey && strcmp((
const char *) sortkey,
"no"))
498 service =
service_init(server, num_metadata, num_sortkeys, service_id);
500 for (n = node->children; n; n = n->next)
502 if (n->type != XML_ELEMENT_NODE)
504 if (!strcmp((
const char *) n->name,
"timeout"))
506 xmlChar *src = xmlGetProp(n, (xmlChar *)
"session");
513 yaz_log(YLOG_FATAL,
"session timeout out of range");
517 src = xmlGetProp(n, (xmlChar *)
"z3950_operation");
524 yaz_log(YLOG_FATAL,
"Z39.50 operation timeout out of range");
528 src = xmlGetProp(n, (xmlChar *)
"z3950_session");
535 yaz_log(YLOG_FATAL,
"Z39.50 session timeout out of range");
540 else if (!strcmp((
const char *) n->name,
"ccldirective"))
546 name = (
char *) xmlGetProp(n, (xmlChar *)
"name");
549 yaz_log(YLOG_FATAL,
"ccldirective: missing @name");
552 value = (
char *) xmlGetProp(n, (xmlChar *)
"value");
556 yaz_log(YLOG_FATAL,
"ccldirective: missing @value");
559 ccl_qual_add_special(service->
ccl_bibset, name, value);
563 else if (!strcmp((
const char *) n->name,
"settings"))
565 else if (!strcmp((
const char *) n->name,
"icu_chain"))
571 yaz_log(YLOG_FATAL,
"ICU chain definition error");
575 else if (!strcmp((
const char *) n->name,
"relevance")
576 || !strcmp((
const char *) n->name,
"sort")
577 || !strcmp((
const char *) n->name,
"mergekey")
578 || !strcmp((
const char *) n->name,
"facet"))
584 n->children, (
const char *) n->name))
586 yaz_log(YLOG_FATAL,
"ICU chain definition error");
590 else if (!strcmp((
const char *) n->name, (
const char *)
"metadata"))
595 else if (!strcmp((
const char *) n->name, (
const char *)
"xslt"))
600 else if (!strcmp((
const char *) n->name, (
const char *)
"set"))
602 xmlChar *
name= xmlGetProp(n, (xmlChar *)
"name");
603 xmlChar *value = xmlGetProp(n, (xmlChar *)
"value");
605 yaz_log(YLOG_DEBUG,
"service set: %s=%s (Not implemented)", (
char *) name, (
char *) value);
609 else if (!strcmp((
const char *) n->name,
"rank"))
611 char *
rank_cluster = (
char *) xmlGetProp(n, (xmlChar *)
"cluster");
612 char *
rank_debug = (
char *) xmlGetProp(n, (xmlChar *)
"debug");
613 char *
rank_follow = (
char *) xmlGetProp(n, (xmlChar *)
"follow");
614 char *
rank_lead = (
char *) xmlGetProp(n, (xmlChar *)
"lead");
615 char *
rank_length= (
char *) xmlGetProp(n, (xmlChar *)
"length");
618 if (!strcmp(rank_cluster,
"yes"))
620 else if (!strcmp(rank_cluster,
"no"))
624 yaz_log(YLOG_FATAL,
"service: rank@cluster boolean");
636 yaz_log(YLOG_FATAL,
"service: rank@debug boolean");
658 yaz_log(YLOG_FATAL,
"service: rank@length linear|log|none");
668 else if (!strcmp((
const char *) n->name,
"sort-default"))
670 char *
default_sort = (
char *) xmlGetProp(n, (xmlChar *)
"field");
672 if (default_sort && strcmp(default_sort,
"")) {
673 service->default_sort = nmem_strdup(service->nmem, default_sort);
674 yaz_log(YLOG_LOG,
"service %s: default sort order configured to: %s",
675 service_id ? service_id :
"unnamed", default_sort);
679 yaz_log(YLOG_FATAL,
"default sort order is invalid: %s", default_sort);
682 xmlFree(default_sort);
686 yaz_log(YLOG_FATAL,
"Bad element: %s", n->name);
695 for (pass = 1; pass <= 2; pass++)
697 for (n = node->children; n; n = n->next)
699 if (n->type != XML_ELEMENT_NODE)
701 if (!strcmp((
const char *) n->name,
"settings"))
704 xmlChar *src = xmlGetProp(n, (xmlChar *)
"src");
707 WRBUF w = wrbuf_alloc();
743 yaz_log(YLOG_WARN,
"server '%s' has no settings", s->
id ? s->
id :
"unnamed");
772 assert(service->
mutex == 0);
779 NMEM nmem, xmlNode *node)
783 xmlChar *
server_id = xmlGetProp(node, (xmlChar *)
"id");
801 server->
server_id = nmem_strdup(nmem, (
const char *)server_id);
806 for (n = node->children; n; n = n->next)
808 if (n->type != XML_ELEMENT_NODE)
810 if (!strcmp((
const char *) n->name,
"listen"))
812 xmlChar *
port = xmlGetProp(n, (xmlChar *)
"port");
813 xmlChar *
host = xmlGetProp(n, (xmlChar *)
"host");
815 server->
port = atoi((
const char *) port);
817 server->
host = nmem_strdup(nmem, (
const char *) host);
821 else if (!strcmp((
const char *) n->name,
"proxy"))
823 xmlChar *
port = xmlGetProp(n, (xmlChar *)
"port");
824 xmlChar *
host = xmlGetProp(n, (xmlChar *)
"host");
825 xmlChar *
myurl = xmlGetProp(n, (xmlChar *)
"myurl");
827 server->
proxy_port = atoi((
const char *) port);
829 server->
proxy_host = nmem_strdup(nmem, (
const char *) host);
831 server->
myurl = nmem_strdup(nmem, (
const char *) myurl);
836 else if (!strcmp((
const char *) n->name,
"settings"))
838 xmlChar *src = xmlGetProp(n, (xmlChar *)
"src");
842 yaz_log(YLOG_FATAL,
"Missing src attribute for settings");
848 yaz_log(YLOG_FATAL,
"Can't repeat 'settings'");
857 else if (!strcmp((
const char *) n->name,
"icu_chain"))
863 yaz_log(YLOG_FATAL,
"ICU chain definition error");
867 else if (!strcmp((
const char *) n->name,
"relevance")
868 || !strcmp((
const char *) n->name,
"sort")
869 || !strcmp((
const char *) n->name,
"mergekey")
870 || !strcmp((
const char *) n->name,
"facet"))
875 n->children, (
const char *) n->name))
877 yaz_log(YLOG_FATAL,
"ICU chain definition error");
881 else if (!strcmp((
const char *) n->name,
"service"))
883 char *service_id = (
char *)
884 xmlGetProp(n, (xmlChar *)
"id");
887 for (; *sp; sp = &(*sp)->
next)
888 if ((*sp)->id && service_id &&
889 0 == strcmp((*sp)->id, service_id))
891 yaz_log(YLOG_FATAL,
"Duplicate service: %s", service_id);
894 else if (!(*sp)->id && !service_id)
896 yaz_log(YLOG_FATAL,
"Duplicate unnamed service");
917 yaz_log(YLOG_FATAL,
"Bad element: %s", n->name);
932 WRBUF w = wrbuf_alloc();
939 const char *service_id)
942 for (; s; s = s->
next)
943 if (s->
id && service_id && 0 == strcmp(s->
id, service_id))
945 else if (!s->
id && !service_id)
955 wrbuf_puts(w,
" <services>\n");
956 for (; s; s = s->
next)
958 wrbuf_puts(w,
" <service");
961 wrbuf_puts(w,
" id=\"");
962 wrbuf_xmlputs(w, s->
id);
969 wrbuf_puts(w,
" </services>\n");
976 for (n = root->children; n; n = n->next)
978 if (n->type != XML_ELEMENT_NODE)
980 if (!strcmp((
const char *) n->name,
"server"))
988 else if (!strcmp((
const char *) n->name,
"threads"))
990 xmlChar *number = xmlGetProp(n, (xmlChar *)
"number");
993 config->
no_threads = atoi((
const char *) number);
997 else if (!strcmp((
const char *) n->name,
"targetprofiles"))
999 yaz_log(YLOG_FATAL,
"targetprofiles unsupported here. Must be part of service");
1005 yaz_log(YLOG_FATAL,
"Bad element: %s", n->name);
1014 xmlDoc *doc = xmlParseFile(fname);
1018 NMEM
nmem = nmem_create();
1021 xmlSubstituteEntitiesDefault(1);
1022 xmlLoadExtDtdDefaultValue = 1;
1025 yaz_log(YLOG_FATAL,
"Failed to read %s", fname);
1036 config->
confdir = wrbuf_alloc();
1037 if ((p = strrchr(fname,
1045 int len = p - fname;
1046 wrbuf_write(config->
confdir, fname, len);
1048 wrbuf_puts(config->
confdir,
"");
1050 n = xmlDocGetRootElement(doc);
1051 r = yaz_xml_include_simple(n, wrbuf_cstr(config->
confdir));
1056 yaz_log(YLOG_LOG,
"Configuration %s after include processing",
1058 #if LIBXML_VERSION >= 20600
1059 xmlDocFormatDump(yaz_log_file(), doc, 0);
1061 xmlDocDump(yaz_log_file(), doc);
1086 yaz_log(YLOG_LOG,
"server_destroy server=%p", server);
1103 wrbuf_destroy(config->
confdir);
1104 nmem_destroy(config->
nmem);
1123 for (;s ; s = s->
next)
1125 assert(s->
mutex == 0);
1134 const char *listener_override,
1135 const char *record_fname)
1142 WRBUF w = wrbuf_alloc();
1146 if (listener_override)
1148 wrbuf_puts(w, listener_override);
1149 listener_override = 0;
1154 wrbuf_puts(w, ser->
host);
1159 wrbuf_printf(w,
"%d", ser->
port);
1162 r =
http_init(wrbuf_cstr(w), ser, record_fname);