/*
- * Copyright (c) 1998-2003, Index Data.
+ * Copyright (c) 1998-2004, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-proxy-config.cpp,v 1.12 2003-10-20 18:31:44 adam Exp $
+ * $Id: yaz-proxy-config.cpp,v 1.26 2004-01-29 21:33:39 adam Exp $
*/
#include <ctype.h>
Yaz_ProxyConfig::Yaz_ProxyConfig()
{
m_copy = 0;
-#if HAVE_XML2
+#if HAVE_XSLT
m_docPtr = 0;
m_proxyPtr = 0;
#endif
Yaz_ProxyConfig::~Yaz_ProxyConfig()
{
-#if HAVE_XML2
+#if HAVE_XSLT
if (!m_copy && m_docPtr)
xmlFreeDoc(m_docPtr);
#endif
int Yaz_ProxyConfig::read_xml(const char *fname)
{
-#if HAVE_XML2
+#if HAVE_XSLT
xmlDocPtr ndoc = xmlParseFile(fname);
if (!ndoc)
#endif
}
-#if HAVE_XML2
+#if HAVE_XSLT
const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr)
{
for(ptr = ptr->children; ptr; ptr = ptr->next)
}
#endif
-#if HAVE_XML2
+#if HAVE_XSLT
void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr,
int *limit_bw,
int *limit_pdu,
}
#endif
-#if HAVE_XML2
+#if HAVE_XSLT
void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
const char **url,
int *limit_bw,
int *client_idletime,
int *keepalive_limit_bw,
int *keepalive_limit_pdu,
- int *pre_init)
+ int *pre_init,
+ const char **cql2rpn)
{
*pre_init = 0;
int no_url = 0;
*client_idletime = 0;
}
}
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "cql2rpn"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ *cql2rpn = t;
+ }
}
}
#endif
return 0;
}
-#if HAVE_XML2
-int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptr,
+#if HAVE_XSLT
+int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptrl,
Z_AttributeList *attrs,
char **addinfo)
{
- for(ptr = ptr->children; ptr; ptr = ptr->next)
+ int i;
+ for (i = 0; i<attrs->num_attributes; i++)
{
- if (ptr->type == XML_ELEMENT_NODE &&
- !strcmp((const char *) ptr->name, "attribute"))
+ Z_AttributeElement *el = attrs->attributes[i];
+
+ if (!el->attributeType)
+ continue;
+ int type = *el->attributeType;
+ int *value = 0;
+
+ if (el->which == Z_AttributeValue_numeric && el->value.numeric)
+ value = el->value.numeric;
+
+ xmlNodePtr ptr;
+ for(ptr = ptrl->children; ptr; ptr = ptr->next)
{
- const char *match_type = 0;
- const char *match_value = 0;
- const char *match_error = 0;
- struct _xmlAttr *attr;
- for (attr = ptr->properties; attr; attr = attr->next)
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "attribute"))
{
- if (!strcmp((const char *) attr->name, "type") &&
- attr->children && attr->children->type == XML_TEXT_NODE)
- match_type = (const char *) attr->children->content;
- if (!strcmp((const char *) attr->name, "value") &&
- attr->children && attr->children->type == XML_TEXT_NODE)
- match_value = (const char *) attr->children->content;
- if (!strcmp((const char *) attr->name, "error") &&
- attr->children && attr->children->type == XML_TEXT_NODE)
- match_error = (const char *) attr->children->content;
- }
- int i;
-
- if (match_type && match_value)
- {
- for (i = 0; i<attrs->num_attributes; i++)
+ const char *match_type = 0;
+ const char *match_value = 0;
+ const char *match_error = 0;
+ struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
{
- Z_AttributeElement *el = attrs->attributes[i];
- char value_str[20];
-
- value_str[0] = '\0';
- if (!el->attributeType)
- continue;
- int type = *el->attributeType;
-
+ if (!strcmp((const char *) attr->name, "type") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_type = (const char *) attr->children->content;
+ if (!strcmp((const char *) attr->name, "value") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_value = (const char *) attr->children->content;
+ if (!strcmp((const char *) attr->name, "error") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_error = (const char *) attr->children->content;
+ }
+ if (match_type && match_value)
+ {
+ char addinfo_str[20];
if (!match_list(type, match_type))
continue;
- if (el->which == Z_AttributeValue_numeric &&
- el->value.numeric)
+
+ *addinfo_str = '\0';
+ if (!strcmp(match_type, "*"))
+ sprintf (addinfo_str, "%d", type);
+ else if (value)
{
- if (!match_list(*el->value.numeric, match_value))
+ if (!match_list(*value, match_value))
continue;
- sprintf (value_str, "%d", *el->value.numeric);
+ sprintf (addinfo_str, "%d", *value);
}
else
continue;
+
if (match_error)
{
- if (*value_str)
- *addinfo = odr_strdup(odr, value_str);
+ if (*addinfo_str)
+ *addinfo = odr_strdup(odr, addinfo_str);
return atoi(match_error);
}
- return 0;
+ break;
}
}
}
}
#endif
-#if HAVE_XML2
+#if HAVE_XSLT
int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr,
Z_RPNStructure *q,
char **addinfo)
}
#endif
-#if HAVE_XML2
+#if HAVE_XSLT
int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
char **addinfo)
{
int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query,
char **addinfo)
{
-#if HAVE_XML2
+#if HAVE_XSLT
xmlNodePtr ptr;
- ptr = find_target_node(name);
+ ptr = find_target_node(name, 0);
if (ptr)
{
if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
return 0;
}
+#if HAVE_XSLT
+int Yaz_ProxyConfig::check_schema(xmlNodePtr ptr, Z_RecordComposition *comp,
+ const char *schema_identifier)
+{
+ char *esn = 0;
+ int default_match = 1;
+ if (comp && comp->which == Z_RecordComp_simple &&
+ comp->u.simple && comp->u.simple->which == Z_ElementSetNames_generic)
+ {
+ esn = comp->u.simple->u.generic;
+ }
+ // if no ESN/schema was given accept..
+ if (!esn)
+ return 1;
+ // check if schema identifier match
+ if (schema_identifier && !strcmp(esn, schema_identifier))
+ return 1;
+ // Check each name element
+ for (; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "name"))
+ {
+ xmlNodePtr tptr = ptr->children;
+ default_match = 0;
+ for (; tptr; tptr = tptr->next)
+ if (tptr->type == XML_TEXT_NODE && tptr->content)
+ {
+ xmlChar *t = tptr->content;
+ while (*t && isspace(*t))
+ t++;
+ int i = 0;
+ while (esn[i] && esn[i] == t[i])
+ i++;
+ if (!esn[i] && (!t[i] || isspace(t[i])))
+ return 1;
+ }
+ }
+ }
+ return default_match;
+}
+#endif
+
int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name,
- Odr_oid *syntax, char **addinfo)
+ Odr_oid *syntax, Z_RecordComposition *comp,
+ char **addinfo,
+ char **stylesheet, char **schema)
{
-#if HAVE_XML2
+ if (stylesheet)
+ {
+ xfree (*stylesheet);
+ *stylesheet = 0;
+ }
+ if (schema)
+ {
+ xfree (*schema);
+ *schema = 0;
+ }
+#if HAVE_XSLT
+ int syntax_has_matched = 0;
xmlNodePtr ptr;
- ptr = find_target_node(name);
+ ptr = find_target_node(name, 0);
if (!ptr)
return 0;
for(ptr = ptr->children; ptr; ptr = ptr->next)
const char *match_type = 0;
const char *match_error = 0;
const char *match_marcxml = 0;
+ const char *match_stylesheet = 0;
+ const char *match_identifier = 0;
struct _xmlAttr *attr;
for (attr = ptr->properties; attr; attr = attr->next)
{
if (!strcmp((const char *) attr->name, "marcxml") &&
attr->children && attr->children->type == XML_TEXT_NODE)
match_marcxml = (const char *) attr->children->content;
+ if (!strcmp((const char *) attr->name, "stylesheet") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_stylesheet = (const char *) attr->children->content;
+ if (!strcmp((const char *) attr->name, "identifier") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_identifier = (const char *) attr->children->content;
}
if (match_type)
{
}
if (match)
{
+ if (!match_error)
+ syntax_has_matched = 1;
+ match = check_schema(ptr->children, comp, match_identifier);
+ }
+ if (match)
+ {
+ if (stylesheet && match_stylesheet)
+ {
+ xfree(*stylesheet);
+ *stylesheet = xstrdup(match_stylesheet);
+ }
+ if (schema && match_identifier)
+ {
+ xfree(*schema);
+ *schema = xstrdup(match_identifier);
+ }
if (match_marcxml)
{
return -1;
}
if (match_error)
{
+ if (syntax_has_matched) // if syntax OK, bad schema/ESN
+ return 25;
if (syntax)
{
char dotoid_str[100];
return 0;
}
-#if HAVE_XML2
-xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name)
+#if HAVE_XSLT
+xmlNodePtr Yaz_ProxyConfig::find_target_db(xmlNodePtr ptr, const char *db)
+{
+ xmlNodePtr dptr;
+ if (!db)
+ return ptr;
+ if (!ptr)
+ return 0;
+ for (dptr = ptr->children; dptr; dptr = dptr->next)
+ if (dptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) dptr->name, "database"))
+ {
+ struct _xmlAttr *attr;
+ for (attr = dptr->properties; attr; attr = attr->next)
+ if (!strcmp((const char *) attr->name, "name"))
+ {
+ if (attr->children
+ && attr->children->type==XML_TEXT_NODE
+ && attr->children->content
+ && (!strcmp((const char *) attr->children->content, db)
+ || !strcmp((const char *) attr->children->content,
+ "*")))
+ return dptr;
+ }
+ }
+ return ptr;
+}
+
+xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name, const char *db)
{
xmlNodePtr ptr;
if (!m_proxyPtr)
{
xmlChar *t = attr->children->content;
if (!t || *t == '1')
- return ptr;
+ {
+ return find_target_db(ptr, db);
+ }
}
}
else
|| !strcmp((const char *) attr->children->content,
"*")))
{
- return ptr;
+ return find_target_db(ptr, db);
}
}
}
int *max_clients,
int *keepalive_limit_bw,
int *keepalive_limit_pdu,
- int *pre_init)
+ int *pre_init,
+ const char **cql2rpn)
{
-#if HAVE_XML2
+#if HAVE_XSLT
xmlNodePtr ptr;
if (!m_proxyPtr)
return 0;
return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
target_idletime, client_idletime,
keepalive_limit_bw, keepalive_limit_pdu,
- pre_init);
+ pre_init, cql2rpn);
return 1;
}
i++;
void Yaz_ProxyConfig::get_generic_info(int *log_mask,
int *max_clients)
{
-#if HAVE_XML2
+#if HAVE_XSLT
xmlNodePtr ptr;
if (!m_proxyPtr)
return;
#endif
}
+char *Yaz_ProxyConfig::get_explain(ODR odr, const char *name, const char *db,
+ int *len)
+{
+#if HAVE_XSLT
+ xmlNodePtr ptr = find_target_node(name, db);
+ if (ptr)
+ {
+ ptr = ptr->children;
+ for (; ptr; ptr = ptr->next)
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "explain"))
+ {
+ xmlNodePtr ptr1 = ptr->children;
+ if (db)
+ {
+ for (; ptr1; ptr1 = ptr1->next)
+ if (ptr1->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr1->name, "serverInfo"))
+ break;
+ if (!ptr1)
+ continue;
+ for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next)
+ if (ptr1->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr1->name, "database"))
+ break;
+
+ if (!ptr1)
+ continue;
+ for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next)
+ if (ptr1->type == XML_TEXT_NODE &&
+ ptr1->content &&
+ !strcmp((const char *) ptr1->content, db))
+ break;
+ if (!ptr1)
+ continue;
+ }
+ xmlNodePtr ptr2 = xmlCopyNode(ptr, 1);
+
+ xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0");
+
+ xmlDocSetRootElement(doc, ptr2);
+
+ xmlChar *buf_out;
+ xmlDocDumpMemory(doc, &buf_out, len);
+ char *content = (char*) odr_malloc(odr, *len);
+ memcpy(content, buf_out, *len);
+
+ xmlFree(buf_out);
+ xmlFreeDoc(doc);
+ return content;
+ }
+ }
+#endif
+ yaz_log(LOG_WARN, "No explain node");
+ return 0;
+}
+
void Yaz_ProxyConfig::get_target_info(const char *name,
const char **url,
int *limit_bw,
int *max_clients,
int *keepalive_limit_bw,
int *keepalive_limit_pdu,
- int *pre_init)
+ int *pre_init,
+ const char **cql2rpn)
{
-#if HAVE_XML2
+#if HAVE_XSLT
xmlNodePtr ptr;
if (!m_proxyPtr)
{
}
}
}
- ptr = find_target_node(name);
+ ptr = find_target_node(name, 0);
if (ptr)
{
if (name)
return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
target_idletime, client_idletime,
keepalive_limit_bw, keepalive_limit_pdu,
- pre_init);
+ pre_init, cql2rpn);
}
#else
*url = name;