1 /* $Id: yaz-proxy-config.cpp,v 1.1 2004-03-29 22:46:51 adam Exp $
2 Copyright (c) 1998-2004, Index Data.
4 This file is part of the yaz-proxy.
6 Zebra is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
11 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with Zebra; see the file LICENSE.proxy. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 #include <yaz++/proxy/proxy.h>
26 Yaz_ProxyConfig::Yaz_ProxyConfig()
35 Yaz_ProxyConfig::~Yaz_ProxyConfig()
38 if (!m_copy && m_docPtr)
43 int Yaz_ProxyConfig::read_xml(const char *fname)
46 xmlDocPtr ndoc = xmlParseFile(fname);
50 yaz_log(LOG_WARN, "Config file %s not found or parse error", fname);
53 xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc);
54 if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE ||
55 strcmp((const char *) proxyPtr->name, "proxy"))
57 yaz_log(LOG_WARN, "No proxy element in %s", fname);
61 m_proxyPtr = proxyPtr;
63 // OK: release previous and make it the current one.
74 const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr)
76 for(ptr = ptr->children; ptr; ptr = ptr->next)
77 if (ptr->type == XML_TEXT_NODE)
79 xmlChar *t = ptr->content;
84 return (const char *) t;
92 void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr,
97 for (ptr = ptr->children; ptr; ptr = ptr->next)
99 if (ptr->type == XML_ELEMENT_NODE
100 && !strcmp((const char *) ptr->name, "bandwidth"))
102 const char *t = get_text(ptr);
106 if (ptr->type == XML_ELEMENT_NODE
107 && !strcmp((const char *) ptr->name, "retrieve"))
109 const char *t = get_text(ptr);
111 *limit_req = atoi(t);
113 if (ptr->type == XML_ELEMENT_NODE
114 && !strcmp((const char *) ptr->name, "pdu"))
116 const char *t = get_text(ptr);
118 *limit_pdu = atoi(t);
125 void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
130 int *target_idletime,
131 int *client_idletime,
132 int *keepalive_limit_bw,
133 int *keepalive_limit_pdu,
135 const char **cql2rpn)
140 for (; ptr; ptr = ptr->next)
142 if (ptr->type == XML_ELEMENT_NODE
143 && !strcmp((const char *) ptr->name, "preinit"))
145 const char *v = get_text(ptr);
146 *pre_init = v ? atoi(v) : 1;
148 if (ptr->type == XML_ELEMENT_NODE
149 && !strcmp((const char *) ptr->name, "url"))
151 const char *t = get_text(ptr);
152 if (t && no_url < MAX_ZURL_PLEX)
158 if (ptr->type == XML_ELEMENT_NODE
159 && !strcmp((const char *) ptr->name, "keepalive"))
162 *keepalive_limit_bw = 500000;
163 *keepalive_limit_pdu = 1000;
164 return_limit(ptr, keepalive_limit_bw, keepalive_limit_pdu,
167 if (ptr->type == XML_ELEMENT_NODE
168 && !strcmp((const char *) ptr->name, "limit"))
169 return_limit(ptr, limit_bw, limit_pdu, limit_req);
170 if (ptr->type == XML_ELEMENT_NODE
171 && !strcmp((const char *) ptr->name, "target-timeout"))
173 const char *t = get_text(ptr);
176 *target_idletime = atoi(t);
177 if (*target_idletime < 0)
178 *target_idletime = 0;
181 if (ptr->type == XML_ELEMENT_NODE
182 && !strcmp((const char *) ptr->name, "client-timeout"))
184 const char *t = get_text(ptr);
187 *client_idletime = atoi(t);
188 if (*client_idletime < 0)
189 *client_idletime = 0;
192 if (ptr->type == XML_ELEMENT_NODE
193 && !strcmp((const char *) ptr->name, "cql2rpn"))
195 const char *t = get_text(ptr);
203 int Yaz_ProxyConfig::atoi_l(const char **cp)
206 while (**cp && isdigit(**cp))
208 v = v*10 + (**cp - '0');
214 int Yaz_ProxyConfig::match_list(int v, const char *m)
218 while(*m && isspace(*m))
229 if (v >= l && v <= h)
238 int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptrl,
239 Z_AttributeList *attrs,
243 for (i = 0; i<attrs->num_attributes; i++)
245 Z_AttributeElement *el = attrs->attributes[i];
247 if (!el->attributeType)
249 int type = *el->attributeType;
252 if (el->which == Z_AttributeValue_numeric && el->value.numeric)
253 value = el->value.numeric;
256 for(ptr = ptrl->children; ptr; ptr = ptr->next)
258 if (ptr->type == XML_ELEMENT_NODE &&
259 !strcmp((const char *) ptr->name, "attribute"))
261 const char *match_type = 0;
262 const char *match_value = 0;
263 const char *match_error = 0;
264 struct _xmlAttr *attr;
265 for (attr = ptr->properties; attr; attr = attr->next)
267 if (!strcmp((const char *) attr->name, "type") &&
268 attr->children && attr->children->type == XML_TEXT_NODE)
269 match_type = (const char *) attr->children->content;
270 if (!strcmp((const char *) attr->name, "value") &&
271 attr->children && attr->children->type == XML_TEXT_NODE)
272 match_value = (const char *) attr->children->content;
273 if (!strcmp((const char *) attr->name, "error") &&
274 attr->children && attr->children->type == XML_TEXT_NODE)
275 match_error = (const char *) attr->children->content;
277 if (match_type && match_value)
279 char addinfo_str[20];
280 if (!match_list(type, match_type))
284 if (!strcmp(match_type, "*"))
285 sprintf (addinfo_str, "%d", type);
288 if (!match_list(*value, match_value))
290 sprintf (addinfo_str, "%d", *value);
298 *addinfo = odr_strdup(odr, addinfo_str);
299 return atoi(match_error);
311 int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr,
315 if (q->which == Z_RPNStructure_complex)
317 int e = check_type_1_structure(odr, ptr, q->u.complex->s1, addinfo);
320 e = check_type_1_structure(odr, ptr, q->u.complex->s2, addinfo);
323 else if (q->which == Z_RPNStructure_simple)
325 if (q->u.simple->which == Z_Operand_APT)
327 return check_type_1_attributes(
328 odr, ptr, q->u.simple->u.attributesPlusTerm->attributes,
337 int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
340 // possibly check for Bib-1
341 return check_type_1_structure(odr, ptr, query->RPNStructure, addinfo);
345 int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query,
351 ptr = find_target_node(name, 0);
354 if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
355 return check_type_1(odr, ptr, query->u.type_1, addinfo);
362 int Yaz_ProxyConfig::check_schema(xmlNodePtr ptr, Z_RecordComposition *comp,
363 const char *schema_identifier)
366 int default_match = 1;
367 if (comp && comp->which == Z_RecordComp_simple &&
368 comp->u.simple && comp->u.simple->which == Z_ElementSetNames_generic)
370 esn = comp->u.simple->u.generic;
372 // if no ESN/schema was given accept..
375 // check if schema identifier match
376 if (schema_identifier && !strcmp(esn, schema_identifier))
378 // Check each name element
379 for (; ptr; ptr = ptr->next)
381 if (ptr->type == XML_ELEMENT_NODE
382 && !strcmp((const char *) ptr->name, "name"))
384 xmlNodePtr tptr = ptr->children;
386 for (; tptr; tptr = tptr->next)
387 if (tptr->type == XML_TEXT_NODE && tptr->content)
389 xmlChar *t = tptr->content;
390 while (*t && isspace(*t))
393 while (esn[i] && esn[i] == t[i])
395 if (!esn[i] && (!t[i] || isspace(t[i])))
400 return default_match;
404 int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name,
405 Odr_oid *syntax, Z_RecordComposition *comp,
407 char **stylesheet, char **schema)
420 int syntax_has_matched = 0;
423 ptr = find_target_node(name, 0);
426 for(ptr = ptr->children; ptr; ptr = ptr->next)
428 if (ptr->type == XML_ELEMENT_NODE &&
429 !strcmp((const char *) ptr->name, "syntax"))
431 int match = 0; // if we match record syntax
432 const char *match_type = 0;
433 const char *match_error = 0;
434 const char *match_marcxml = 0;
435 const char *match_stylesheet = 0;
436 const char *match_identifier = 0;
437 struct _xmlAttr *attr;
438 for (attr = ptr->properties; attr; attr = attr->next)
440 if (!strcmp((const char *) attr->name, "type") &&
441 attr->children && attr->children->type == XML_TEXT_NODE)
442 match_type = (const char *) attr->children->content;
443 if (!strcmp((const char *) attr->name, "error") &&
444 attr->children && attr->children->type == XML_TEXT_NODE)
445 match_error = (const char *) attr->children->content;
446 if (!strcmp((const char *) attr->name, "marcxml") &&
447 attr->children && attr->children->type == XML_TEXT_NODE)
448 match_marcxml = (const char *) attr->children->content;
449 if (!strcmp((const char *) attr->name, "stylesheet") &&
450 attr->children && attr->children->type == XML_TEXT_NODE)
451 match_stylesheet = (const char *) attr->children->content;
452 if (!strcmp((const char *) attr->name, "identifier") &&
453 attr->children && attr->children->type == XML_TEXT_NODE)
454 match_identifier = (const char *) attr->children->content;
458 if (!strcmp(match_type, "*"))
460 else if (!strcmp(match_type, "none"))
467 int match_oid[OID_SIZE];
468 oid_name_to_oid(CLASS_RECSYN, match_type, match_oid);
469 if (oid_oidcmp(match_oid, syntax) == 0)
476 syntax_has_matched = 1;
477 match = check_schema(ptr->children, comp, match_identifier);
481 if (stylesheet && match_stylesheet)
484 *stylesheet = xstrdup(match_stylesheet);
486 if (schema && match_identifier)
489 *schema = xstrdup(match_identifier);
497 if (syntax_has_matched) // if syntax OK, bad schema/ESN
501 char dotoid_str[100];
502 oid_to_dotstring(syntax, dotoid_str);
503 *addinfo = odr_strdup(odr, dotoid_str);
505 return atoi(match_error);
516 xmlNodePtr Yaz_ProxyConfig::find_target_db(xmlNodePtr ptr, const char *db)
523 for (dptr = ptr->children; dptr; dptr = dptr->next)
524 if (dptr->type == XML_ELEMENT_NODE &&
525 !strcmp((const char *) dptr->name, "database"))
527 struct _xmlAttr *attr;
528 for (attr = dptr->properties; attr; attr = attr->next)
529 if (!strcmp((const char *) attr->name, "name"))
532 && attr->children->type==XML_TEXT_NODE
533 && attr->children->content
534 && (!strcmp((const char *) attr->children->content, db)
535 || !strcmp((const char *) attr->children->content,
543 xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name, const char *db)
548 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
550 if (ptr->type == XML_ELEMENT_NODE &&
551 !strcmp((const char *) ptr->name, "target"))
556 // <target default="1"> ?
557 struct _xmlAttr *attr;
558 for (attr = ptr->properties; attr; attr = attr->next)
559 if (!strcmp((const char *) attr->name, "default") &&
560 attr->children && attr->children->type == XML_TEXT_NODE)
562 xmlChar *t = attr->children->content;
565 return find_target_db(ptr, db);
571 // <target name="name"> ?
572 struct _xmlAttr *attr;
573 for (attr = ptr->properties; attr; attr = attr->next)
574 if (!strcmp((const char *) attr->name, "name"))
577 && attr->children->type==XML_TEXT_NODE
578 && attr->children->content
579 && (!strcmp((const char *) attr->children->content,
581 || !strcmp((const char *) attr->children->content,
584 return find_target_db(ptr, db);
594 int Yaz_ProxyConfig::get_target_no(int no,
600 int *target_idletime,
601 int *client_idletime,
603 int *keepalive_limit_bw,
604 int *keepalive_limit_pdu,
606 const char **cql2rpn)
613 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
614 if (ptr->type == XML_ELEMENT_NODE &&
615 !strcmp((const char *) ptr->name, "target"))
619 struct _xmlAttr *attr;
620 for (attr = ptr->properties; attr; attr = attr->next)
621 if (!strcmp((const char *) attr->name, "name"))
624 && attr->children->type==XML_TEXT_NODE
625 && attr->children->content)
626 *name = (const char *) attr->children->content;
628 return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
629 target_idletime, client_idletime,
630 keepalive_limit_bw, keepalive_limit_pdu,
640 int Yaz_ProxyConfig::mycmp(const char *hay, const char *item, size_t len)
642 if (len == strlen(item) && memcmp(hay, item, len) == 0)
647 void Yaz_ProxyConfig::get_generic_info(int *log_mask,
654 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
656 if (ptr->type == XML_ELEMENT_NODE
657 && !strcmp((const char *) ptr->name, "log"))
659 const char *v = get_text(ptr);
664 while (*cp && *cp != ',' && !isspace(*cp))
667 if (mycmp(v, "client-apdu", len))
668 *log_mask |= PROXY_LOG_APDU_CLIENT;
669 if (mycmp(v, "server-apdu", len))
670 *log_mask |= PROXY_LOG_APDU_SERVER;
671 if (mycmp(v, "client-requests", len))
672 *log_mask |= PROXY_LOG_REQ_CLIENT;
673 if (mycmp(v, "server-requests", len))
674 *log_mask |= PROXY_LOG_REQ_SERVER;
676 *log_mask |= atoi(v);
679 while (*cp && isspace(*cp))
684 if (ptr->type == XML_ELEMENT_NODE &&
685 !strcmp((const char *) ptr->name, "max-clients"))
687 const char *t = get_text(ptr);
690 *max_clients = atoi(t);
691 if (*max_clients < 1)
699 char *Yaz_ProxyConfig::get_explain(ODR odr, const char *name, const char *db,
703 xmlNodePtr ptr = find_target_node(name, db);
707 for (; ptr; ptr = ptr->next)
708 if (ptr->type == XML_ELEMENT_NODE &&
709 !strcmp((const char *) ptr->name, "explain"))
711 xmlNodePtr ptr1 = ptr->children;
714 for (; ptr1; ptr1 = ptr1->next)
715 if (ptr1->type == XML_ELEMENT_NODE &&
716 !strcmp((const char *) ptr1->name, "serverInfo"))
720 for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next)
721 if (ptr1->type == XML_ELEMENT_NODE &&
722 !strcmp((const char *) ptr1->name, "database"))
727 for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next)
728 if (ptr1->type == XML_TEXT_NODE &&
730 !strcmp((const char *) ptr1->content, db))
735 xmlNodePtr ptr2 = xmlCopyNode(ptr, 1);
737 xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0");
739 xmlDocSetRootElement(doc, ptr2);
742 xmlDocDumpMemory(doc, &buf_out, len);
743 char *content = (char*) odr_malloc(odr, *len);
744 memcpy(content, buf_out, *len);
755 void Yaz_ProxyConfig::get_target_info(const char *name,
760 int *target_idletime,
761 int *client_idletime,
763 int *keepalive_limit_bw,
764 int *keepalive_limit_pdu,
766 const char **cql2rpn)
777 for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
779 if (ptr->type == XML_ELEMENT_NODE &&
780 !strcmp((const char *) ptr->name, "max-clients"))
782 const char *t = get_text(ptr);
785 *max_clients = atoi(t);
786 if (*max_clients < 1)
791 ptr = find_target_node(name, 0);
799 return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
800 target_idletime, client_idletime,
801 keepalive_limit_bw, keepalive_limit_pdu,