2 * Copyright (c) 1998-2004, Index Data.
3 * See the file LICENSE for details.
5 * $Id: yaz-proxy-config.cpp,v 1.25 2004-01-24 21:31:59 adam Exp $
10 #include <yaz++/proxy.h>
12 Yaz_ProxyConfig::Yaz_ProxyConfig()
21 Yaz_ProxyConfig::~Yaz_ProxyConfig()
24 if (!m_copy && m_docPtr)
29 int Yaz_ProxyConfig::read_xml(const char *fname)
32 xmlDocPtr ndoc = xmlParseFile(fname);
36 yaz_log(LOG_WARN, "Config file %s not found or parse error", fname);
39 xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc);
40 if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE ||
41 strcmp((const char *) proxyPtr->name, "proxy"))
43 yaz_log(LOG_WARN, "No proxy element in %s", fname);
47 m_proxyPtr = proxyPtr;
49 // OK: release previous and make it the current one.
60 const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr)
62 for(ptr = ptr->children; ptr; ptr = ptr->next)
63 if (ptr->type == XML_TEXT_NODE)
65 xmlChar *t = ptr->content;
70 return (const char *) t;
78 void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr,
83 for (ptr = ptr->children; ptr; ptr = ptr->next)
85 if (ptr->type == XML_ELEMENT_NODE
86 && !strcmp((const char *) ptr->name, "bandwidth"))
88 const char *t = get_text(ptr);
92 if (ptr->type == XML_ELEMENT_NODE
93 && !strcmp((const char *) ptr->name, "retrieve"))
95 const char *t = get_text(ptr);
99 if (ptr->type == XML_ELEMENT_NODE
100 && !strcmp((const char *) ptr->name, "pdu"))
102 const char *t = get_text(ptr);
104 *limit_pdu = atoi(t);
111 void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
116 int *target_idletime,
117 int *client_idletime,
118 int *keepalive_limit_bw,
119 int *keepalive_limit_pdu,
121 const char **cql2rpn)
126 for (; ptr; ptr = ptr->next)
128 if (ptr->type == XML_ELEMENT_NODE
129 && !strcmp((const char *) ptr->name, "preinit"))
131 const char *v = get_text(ptr);
132 *pre_init = v ? atoi(v) : 1;
134 if (ptr->type == XML_ELEMENT_NODE
135 && !strcmp((const char *) ptr->name, "url"))
137 const char *t = get_text(ptr);
138 if (t && no_url < MAX_ZURL_PLEX)
144 if (ptr->type == XML_ELEMENT_NODE
145 && !strcmp((const char *) ptr->name, "keepalive"))
148 *keepalive_limit_bw = 500000;
149 *keepalive_limit_pdu = 1000;
150 return_limit(ptr, keepalive_limit_bw, keepalive_limit_pdu,
153 if (ptr->type == XML_ELEMENT_NODE
154 && !strcmp((const char *) ptr->name, "limit"))
155 return_limit(ptr, limit_bw, limit_pdu, limit_req);
156 if (ptr->type == XML_ELEMENT_NODE
157 && !strcmp((const char *) ptr->name, "target-timeout"))
159 const char *t = get_text(ptr);
162 *target_idletime = atoi(t);
163 if (*target_idletime < 0)
164 *target_idletime = 0;
167 if (ptr->type == XML_ELEMENT_NODE
168 && !strcmp((const char *) ptr->name, "client-timeout"))
170 const char *t = get_text(ptr);
173 *client_idletime = atoi(t);
174 if (*client_idletime < 0)
175 *client_idletime = 0;
178 if (ptr->type == XML_ELEMENT_NODE
179 && !strcmp((const char *) ptr->name, "cql2rpn"))
181 const char *t = get_text(ptr);
189 int Yaz_ProxyConfig::atoi_l(const char **cp)
192 while (**cp && isdigit(**cp))
194 v = v*10 + (**cp - '0');
200 int Yaz_ProxyConfig::match_list(int v, const char *m)
204 while(*m && isspace(*m))
215 if (v >= l && v <= h)
224 int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptrl,
225 Z_AttributeList *attrs,
229 for (i = 0; i<attrs->num_attributes; i++)
231 Z_AttributeElement *el = attrs->attributes[i];
233 if (!el->attributeType)
235 int type = *el->attributeType;
238 if (el->which == Z_AttributeValue_numeric && el->value.numeric)
239 value = el->value.numeric;
242 for(ptr = ptrl->children; ptr; ptr = ptr->next)
244 if (ptr->type == XML_ELEMENT_NODE &&
245 !strcmp((const char *) ptr->name, "attribute"))
247 const char *match_type = 0;
248 const char *match_value = 0;
249 const char *match_error = 0;
250 struct _xmlAttr *attr;
251 for (attr = ptr->properties; attr; attr = attr->next)
253 if (!strcmp((const char *) attr->name, "type") &&
254 attr->children && attr->children->type == XML_TEXT_NODE)
255 match_type = (const char *) attr->children->content;
256 if (!strcmp((const char *) attr->name, "value") &&
257 attr->children && attr->children->type == XML_TEXT_NODE)
258 match_value = (const char *) attr->children->content;
259 if (!strcmp((const char *) attr->name, "error") &&
260 attr->children && attr->children->type == XML_TEXT_NODE)
261 match_error = (const char *) attr->children->content;
263 if (match_type && match_value)
265 char addinfo_str[20];
266 if (!match_list(type, match_type))
270 if (!strcmp(match_type, "*"))
271 sprintf (addinfo_str, "%d", type);
274 if (!match_list(*value, match_value))
276 sprintf (addinfo_str, "%d", *value);
284 *addinfo = odr_strdup(odr, addinfo_str);
285 return atoi(match_error);
297 int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr,
301 if (q->which == Z_RPNStructure_complex)
303 int e = check_type_1_structure(odr, ptr, q->u.complex->s1, addinfo);
306 e = check_type_1_structure(odr, ptr, q->u.complex->s2, addinfo);
309 else if (q->which == Z_RPNStructure_simple)
311 if (q->u.simple->which == Z_Operand_APT)
313 return check_type_1_attributes(
314 odr, ptr, q->u.simple->u.attributesPlusTerm->attributes,
323 int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
326 // possibly check for Bib-1
327 return check_type_1_structure(odr, ptr, query->RPNStructure, addinfo);
331 int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query,
337 ptr = find_target_node(name, 0);
340 if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
341 return check_type_1(odr, ptr, query->u.type_1, addinfo);
348 int Yaz_ProxyConfig::check_schema(xmlNodePtr ptr, Z_RecordComposition *comp,
349 const char *schema_identifier)
352 int default_match = 1;
353 if (comp && comp->which == Z_RecordComp_simple &&
354 comp->u.simple && comp->u.simple->which == Z_ElementSetNames_generic)
356 esn = comp->u.simple->u.generic;
358 // if no ESN/schema was given accept..
361 // check if schema identifier match
362 if (schema_identifier && !strcmp(esn, schema_identifier))
364 // Check each name element
365 for (; ptr; ptr = ptr->next)
367 if (ptr->type == XML_ELEMENT_NODE
368 && !strcmp((const char *) ptr->name, "name"))
370 xmlNodePtr tptr = ptr->children;
372 for (; tptr; tptr = tptr->next)
373 if (tptr->type == XML_TEXT_NODE && tptr->content)
375 xmlChar *t = tptr->content;
376 while (*t && isspace(*t))
379 while (esn[i] && esn[i] == t[i])
381 if (!esn[i] && (!t[i] || isspace(t[i])))
386 return default_match;
390 int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name,
391 Odr_oid *syntax, Z_RecordComposition *comp,
393 char **stylesheet, char **schema)
406 int syntax_has_matched = 0;
409 ptr = find_target_node(name, 0);
412 for(ptr = ptr->children; ptr; ptr = ptr->next)
414 if (ptr->type == XML_ELEMENT_NODE &&
415 !strcmp((const char *) ptr->name, "syntax"))
417 int match = 0; // if we match record syntax
418 const char *match_type = 0;
419 const char *match_error = 0;
420 const char *match_marcxml = 0;
421 const char *match_stylesheet = 0;
422 const char *match_identifier = 0;
423 struct _xmlAttr *attr;
424 for (attr = ptr->properties; attr; attr = attr->next)
426 if (!strcmp((const char *) attr->name, "type") &&
427 attr->children && attr->children->type == XML_TEXT_NODE)
428 match_type = (const char *) attr->children->content;
429 if (!strcmp((const char *) attr->name, "error") &&
430 attr->children && attr->children->type == XML_TEXT_NODE)
431 match_error = (const char *) attr->children->content;
432 if (!strcmp((const char *) attr->name, "marcxml") &&
433 attr->children && attr->children->type == XML_TEXT_NODE)
434 match_marcxml = (const char *) attr->children->content;
435 if (!strcmp((const char *) attr->name, "stylesheet") &&
436 attr->children && attr->children->type == XML_TEXT_NODE)
437 match_stylesheet = (const char *) attr->children->content;
438 if (!strcmp((const char *) attr->name, "identifier") &&
439 attr->children && attr->children->type == XML_TEXT_NODE)
440 match_identifier = (const char *) attr->children->content;
444 if (!strcmp(match_type, "*"))
446 else if (!strcmp(match_type, "none"))
453 int match_oid[OID_SIZE];
454 oid_name_to_oid(CLASS_RECSYN, match_type, match_oid);
455 if (oid_oidcmp(match_oid, syntax) == 0)
462 syntax_has_matched = 1;
463 match = check_schema(ptr->children, comp, match_identifier);
467 if (stylesheet && match_stylesheet)
470 *stylesheet = xstrdup(match_stylesheet);
472 if (schema && match_identifier)
475 *schema = xstrdup(match_identifier);
483 if (syntax_has_matched) // if syntax OK, bad schema/ESN
487 char dotoid_str[100];
488 oid_to_dotstring(syntax, dotoid_str);
489 *addinfo = odr_strdup(odr, dotoid_str);
491 return atoi(match_error);
502 xmlNodePtr Yaz_ProxyConfig::find_target_db(xmlNodePtr ptr, const char *db)
509 for (dptr = ptr->children; dptr; dptr = dptr->next)
510 if (dptr->type == XML_ELEMENT_NODE &&
511 !strcmp((const char *) dptr->name, "database"))
513 struct _xmlAttr *attr;
514 for (attr = dptr->properties; attr; attr = attr->next)
515 if (!strcmp((const char *) attr->name, "name"))
518 && attr->children->type==XML_TEXT_NODE
519 && attr->children->content
520 && (!strcmp((const char *) attr->children->content, db)
521 || !strcmp((const char *) attr->children->content,
529 xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name, const char *db)
534 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
536 if (ptr->type == XML_ELEMENT_NODE &&
537 !strcmp((const char *) ptr->name, "target"))
542 // <target default="1"> ?
543 struct _xmlAttr *attr;
544 for (attr = ptr->properties; attr; attr = attr->next)
545 if (!strcmp((const char *) attr->name, "default") &&
546 attr->children && attr->children->type == XML_TEXT_NODE)
548 xmlChar *t = attr->children->content;
551 return find_target_db(ptr, db);
557 // <target name="name"> ?
558 struct _xmlAttr *attr;
559 for (attr = ptr->properties; attr; attr = attr->next)
560 if (!strcmp((const char *) attr->name, "name"))
563 && attr->children->type==XML_TEXT_NODE
564 && attr->children->content
565 && (!strcmp((const char *) attr->children->content,
567 || !strcmp((const char *) attr->children->content,
570 return find_target_db(ptr, db);
580 int Yaz_ProxyConfig::get_target_no(int no,
586 int *target_idletime,
587 int *client_idletime,
589 int *keepalive_limit_bw,
590 int *keepalive_limit_pdu,
592 const char **cql2rpn)
599 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
600 if (ptr->type == XML_ELEMENT_NODE &&
601 !strcmp((const char *) ptr->name, "target"))
605 struct _xmlAttr *attr;
606 for (attr = ptr->properties; attr; attr = attr->next)
607 if (!strcmp((const char *) attr->name, "name"))
610 && attr->children->type==XML_TEXT_NODE
611 && attr->children->content)
612 *name = (const char *) attr->children->content;
614 return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
615 target_idletime, client_idletime,
616 keepalive_limit_bw, keepalive_limit_pdu,
626 int Yaz_ProxyConfig::mycmp(const char *hay, const char *item, size_t len)
628 if (len == strlen(item) && memcmp(hay, item, len) == 0)
633 void Yaz_ProxyConfig::get_generic_info(int *log_mask,
640 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
642 if (ptr->type == XML_ELEMENT_NODE
643 && !strcmp((const char *) ptr->name, "log"))
645 const char *v = get_text(ptr);
650 while (*cp && *cp != ',' && !isspace(*cp))
653 if (mycmp(v, "client-apdu", len))
654 *log_mask |= PROXY_LOG_APDU_CLIENT;
655 if (mycmp(v, "server-apdu", len))
656 *log_mask |= PROXY_LOG_APDU_SERVER;
657 if (mycmp(v, "client-requests", len))
658 *log_mask |= PROXY_LOG_REQ_CLIENT;
659 if (mycmp(v, "server-requests", len))
660 *log_mask |= PROXY_LOG_REQ_SERVER;
662 *log_mask |= atoi(v);
665 while (*cp && isspace(*cp))
670 if (ptr->type == XML_ELEMENT_NODE &&
671 !strcmp((const char *) ptr->name, "max-clients"))
673 const char *t = get_text(ptr);
676 *max_clients = atoi(t);
677 if (*max_clients < 1)
685 char *Yaz_ProxyConfig::get_explain(ODR odr, const char *name, const char *db,
689 xmlNodePtr ptr = find_target_node(name, db);
693 for (; ptr; ptr = ptr->next)
694 if (ptr->type == XML_ELEMENT_NODE &&
695 !strcmp((const char *) ptr->name, "explain"))
697 xmlNodePtr ptr1 = ptr->children;
700 for (; ptr1; ptr1 = ptr1->next)
701 if (ptr1->type == XML_ELEMENT_NODE &&
702 !strcmp((const char *) ptr1->name, "serverInfo"))
706 for (ptr1 = ptr1->children; ptr; ptr1 = ptr1->next)
707 if (ptr1->type == XML_ELEMENT_NODE &&
708 !strcmp((const char *) ptr1->name, "database"))
713 for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next)
714 if (ptr1->type == XML_TEXT_NODE &&
716 !strcmp((const char *) ptr1->content, db))
721 xmlNodePtr ptr2 = xmlCopyNode(ptr, 1);
723 xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0");
725 xmlDocSetRootElement(doc, ptr2);
728 xmlDocDumpMemory(doc, &buf_out, len);
729 char *content = (char*) odr_malloc(odr, *len);
730 memcpy(content, buf_out, *len);
738 yaz_log(LOG_WARN, "No explain node");
742 void Yaz_ProxyConfig::get_target_info(const char *name,
747 int *target_idletime,
748 int *client_idletime,
750 int *keepalive_limit_bw,
751 int *keepalive_limit_pdu,
753 const char **cql2rpn)
764 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
766 if (ptr->type == XML_ELEMENT_NODE &&
767 !strcmp((const char *) ptr->name, "max-clients"))
769 const char *t = get_text(ptr);
772 *max_clients = atoi(t);
773 if (*max_clients < 1)
778 ptr = find_target_node(name, 0);
786 return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
787 target_idletime, client_idletime,
788 keepalive_limit_bw, keepalive_limit_pdu,