USMARC to MARCXML conversion. Check for reconfigure in more places
[yazpp-moved-to-github.git] / src / yaz-proxy-config.cpp
index 61cfb8d..056354b 100644 (file)
@@ -2,9 +2,10 @@
  * Copyright (c) 1998-2003, Index Data.
  * See the file LICENSE for details.
  * 
- * $Id: yaz-proxy-config.cpp,v 1.1 2003-10-01 13:13:51 adam Exp $
+ * $Id: yaz-proxy-config.cpp,v 1.8 2003-10-10 17:58:29 adam Exp $
  */
 
+#include <ctype.h>
 #include <yaz/log.h>
 #include <yaz++/proxy.h>
 
@@ -25,15 +26,6 @@ Yaz_ProxyConfig::~Yaz_ProxyConfig()
 #endif
 }
 
-void Yaz_ProxyConfig::operator=(const Yaz_ProxyConfig &conf)
-{
-#if HAVE_XML2
-    m_docPtr = conf.m_docPtr;
-    m_proxyPtr = conf.m_proxyPtr;
-#endif
-    m_copy = 1;
-}
-
 int Yaz_ProxyConfig::read_xml(const char *fname)
 {
 #if HAVE_XML2
@@ -118,11 +110,15 @@ void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr,
 #if HAVE_XML2
 void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
                                         const char **url,
-                                        int *keepalive,
                                         int *limit_bw,
                                         int *limit_pdu,
-                                        int *limit_req)
+                                        int *limit_req,
+                                        int *target_idletime,
+                                        int *client_idletime,
+                                        int *keepalive_limit_bw,
+                                        int *keepalive_limit_pdu)
 {
+    int no_url = 0;
     ptr = ptr->children;
     for (; ptr; ptr = ptr->next)
     {
@@ -130,39 +126,280 @@ void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
            && !strcmp((const char *) ptr->name, "url"))
        {
            const char *t = get_text(ptr);
-           if (t)
-               *url = t;
+           if (t && no_url < MAX_ZURL_PLEX)
+           {
+               url[no_url++] = t;
+               url[no_url] = 0;
+           }
        }
        if (ptr->type == XML_ELEMENT_NODE 
            && !strcmp((const char *) ptr->name, "keepalive"))
        {
-           const char *t = get_text(ptr);
-           if (!t || *t == '1')
-               *keepalive = 1;
-           else
-               *keepalive = 0;
+           int dummy;
+           *keepalive_limit_bw = 500000;
+           *keepalive_limit_pdu = 1000;
+           return_limit(ptr, keepalive_limit_bw, keepalive_limit_pdu,
+                        &dummy);
        }
        if (ptr->type == XML_ELEMENT_NODE 
            && !strcmp((const char *) ptr->name, "limit"))
            return_limit(ptr, limit_bw, limit_pdu, limit_req);
+       if (ptr->type == XML_ELEMENT_NODE 
+           && !strcmp((const char *) ptr->name, "target-timeout"))
+       {
+           const char *t = get_text(ptr);
+           if (t)
+           {
+               *target_idletime = atoi(t);
+               if (*target_idletime < 0)
+                   *target_idletime = 0;
+           }
+       }
+       if (ptr->type == XML_ELEMENT_NODE 
+           && !strcmp((const char *) ptr->name, "client-timeout"))
+       {
+           const char *t = get_text(ptr);
+           if (t)
+           {
+               *client_idletime = atoi(t);
+               if (*client_idletime < 0)
+                   *client_idletime = 0;
+           }
+       }
     }
 }
 #endif
 
-void Yaz_ProxyConfig::get_target_info(const char *name,
-                                     const char **url,
-                                     int *keepalive,
-                                     int *limit_bw,
-                                     int *limit_pdu,
-                                     int *limit_req)
+int Yaz_ProxyConfig::atoi_l(const char **cp)
+{
+    int v = 0;
+    while (**cp && isdigit(**cp))
+    {
+       v = v*10 + (**cp - '0');
+       (*cp)++;
+    }
+    return v;
+}
+
+int Yaz_ProxyConfig::match_list(int v, const char *m)
+{
+  while(m && *m)
+  {
+      while(*m && isspace(*m))
+         m++;
+      if (*m == '*')
+         return 1;
+      int l = atoi_l(&m);
+      int h = l;
+      if (*m == '-')
+      {
+         ++m;
+         h = atoi_l(&m);
+      }
+      if (v >= l && v <= h)
+         return 1;
+      if (*m == ',')
+         m++;
+  }
+  return 0;
+}
+
+#if HAVE_XML2
+int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptr,
+                                            Z_AttributeList *attrs,
+                                            char **addinfo)
+{
+    for(ptr = ptr->children; ptr; ptr = ptr->next)
+    {
+       if (ptr->type == XML_ELEMENT_NODE &&
+           !strcmp((const char *) ptr->name, "attribute"))
+       {
+           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 (!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++)
+               {
+                   Z_AttributeElement *el = attrs->attributes[i];
+                   char value_str[20];
+                   
+                   value_str[0] = '\0';
+                   if (!el->attributeType)
+                       continue;
+                   int type = *el->attributeType;
+
+                   if (!match_list(type, match_type))
+                       continue;
+                   if (el->which == Z_AttributeValue_numeric && 
+                       el->value.numeric)
+                   {
+                       if (!match_list(*el->value.numeric, match_value))
+                           continue;
+                       sprintf (value_str, "%d", *el->value.numeric);
+                   }
+                   else
+                       continue;
+                   if (match_error)
+                   {
+                       if (*value_str)
+                           *addinfo = odr_strdup(odr, value_str);
+                       return atoi(match_error);
+                   }
+                   return 0;
+               }
+           }
+       }
+    }
+    return 0;
+}
+#endif
+
+#if HAVE_XML2
+int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr,
+                                           Z_RPNStructure *q,
+                                           char **addinfo)
+{
+    int c;
+    if (q->which == Z_RPNStructure_complex)
+    {
+       int e = check_type_1_structure(odr, ptr, q->u.complex->s1, addinfo);
+       if (e)
+           return e;
+       e = check_type_1_structure(odr, ptr, q->u.complex->s2, addinfo);
+       return e;
+    }
+    else if (q->which == Z_RPNStructure_simple)
+    {
+       if (q->u.simple->which == Z_Operand_APT)
+       {
+           return check_type_1_attributes(
+               odr, ptr, q->u.simple->u.attributesPlusTerm->attributes,
+               addinfo);
+       }
+    }
+    return 0;
+}
+#endif
+
+#if HAVE_XML2
+int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
+                                 char **addinfo)
+{
+    // possibly check for Bib-1
+    return check_type_1_structure(odr, ptr, query->RPNStructure, addinfo);
+}
+#endif
+
+int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query,
+                                char **addinfo)
 {
 #if HAVE_XML2
     xmlNodePtr ptr;
-    if (!m_proxyPtr)
+    
+    ptr = find_target_node(name);
+    if (ptr)
     {
-       *url = name;
-       return;
+       if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
+           return check_type_1(odr, ptr, query->u.type_1, addinfo);
+    }
+#endif
+    return 0;
+}
+
+int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name,
+                                 Odr_oid *syntax, char **addinfo)
+{
+#if HAVE_XML2
+    xmlNodePtr ptr;
+    
+    ptr = find_target_node(name);
+    if (!ptr)
+       return 0;
+    for(ptr = ptr->children; ptr; ptr = ptr->next)
+    {
+       if (ptr->type == XML_ELEMENT_NODE &&
+           !strcmp((const char *) ptr->name, "syntax"))
+       {
+           int match = 0;  // if we match record syntax
+           const char *match_type = 0;
+           const char *match_error = 0;
+           const char *match_marcxml = 0;
+           struct _xmlAttr *attr;
+           for (attr = ptr->properties; attr; attr = attr->next)
+           {
+               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, "error") &&
+                   attr->children && attr->children->type == XML_TEXT_NODE)
+                   match_error = (const char *) attr->children->content;
+               if (!strcmp((const char *) attr->name, "marcxml") &&
+                   attr->children && attr->children->type == XML_TEXT_NODE)
+                   match_marcxml = (const char *) attr->children->content;
+           }
+           if (match_type)
+           {
+               if (!strcmp(match_type, "*"))
+                   match = 1;
+               else if (!strcmp(match_type, "none"))
+               {
+                   if (syntax == 0)
+                       match = 1;
+               }
+               else if (syntax)
+               {
+                   int match_oid[OID_SIZE];
+                   oid_name_to_oid(CLASS_RECSYN, match_type, match_oid);
+                   if (oid_oidcmp(match_oid, syntax) == 0)
+                       match = 1;
+               }
+           }
+           if (match)
+           {
+               if (match_marcxml)
+               {
+                   return -1;
+               }
+               if (match_error)
+               {
+                   if (syntax)
+                   {
+                       char dotoid_str[100];
+                       oid_to_dotstring(syntax, dotoid_str);
+                       *addinfo = odr_strdup(odr, dotoid_str);
+                   }
+                   return atoi(match_error);
+               }
+               return 0;
+           }
+       }
     }
+#endif
+    return 0;
+}
+
+#if HAVE_XML2
+xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name)
+{
+    xmlNodePtr ptr;
+    if (!m_proxyPtr)
+       return 0;
     for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
     {
        if (ptr->type == XML_ELEMENT_NODE &&
@@ -179,11 +416,7 @@ void Yaz_ProxyConfig::get_target_info(const char *name,
                    {
                        xmlChar *t = attr->children->content;
                        if (!t || *t == '1')
-                       {
-                           return_target_info(ptr, url, keepalive,
-                                              limit_bw, limit_pdu, limit_req);
-                           return;
-                       }
+                           return ptr;
                    }
            }
            else
@@ -201,15 +434,62 @@ void Yaz_ProxyConfig::get_target_info(const char *name,
                                || !strcmp((const char *) attr->children->content,
                                           "*")))
                        {
-                           *url = name;
-                           return_target_info(ptr, url, keepalive,
-                                              limit_bw, limit_pdu, limit_req);
-                           return;
+                           return ptr;
                        }
                    }
            }
        }
     }
+    return 0;
+}
+#endif
+
+void Yaz_ProxyConfig::get_target_info(const char *name,
+                                     const char **url,
+                                     int *limit_bw,
+                                     int *limit_pdu,
+                                     int *limit_req,
+                                     int *target_idletime,
+                                     int *client_idletime,
+                                     int *max_clients,
+                                     int *keepalive_limit_bw,
+                                     int *keepalive_limit_pdu)
+{
+#if HAVE_XML2
+    xmlNodePtr ptr;
+    if (!m_proxyPtr)
+    {
+       url[0] = name;
+       url[1] = 0;
+       return;
+    }
+    url[0] = 0;
+    for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
+    {
+       if (ptr->type == XML_ELEMENT_NODE &&
+           !strcmp((const char *) ptr->name, "max-clients"))
+       {
+           const char *t = get_text(ptr);
+           if (t)
+           {
+               *max_clients = atoi(t);
+               if (*max_clients  < 1)
+                   *max_clients = 1;
+           }
+       }
+    }
+    ptr = find_target_node(name);
+    if (ptr)
+    {
+       if (name)
+       {
+           url[0] = name;
+           url[1] = 0;
+       }
+       return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
+                          target_idletime, client_idletime,
+                          keepalive_limit_bw, keepalive_limit_pdu);
+    }
 #else
     *url = name;
     return;