X-Git-Url: http://git.indexdata.com/?p=yazproxy-moved-to-github.git;a=blobdiff_plain;f=src%2Fyaz-proxy-config.cpp;h=76259cf3b96288810fcab98fbf28f8c9448f1e53;hp=9e0fbf875a96d388554713d8106825237fd6571f;hb=2faeba3f61ac423a9c71222e9a15377724d8f0fa;hpb=2f1a9a4b28ae43c9da9e0740f84048065b2d3bf6 diff --git a/src/yaz-proxy-config.cpp b/src/yaz-proxy-config.cpp index 9e0fbf8..76259cf 100644 --- a/src/yaz-proxy-config.cpp +++ b/src/yaz-proxy-config.cpp @@ -1,45 +1,233 @@ -/* $Id: yaz-proxy-config.cpp,v 1.1 2004-04-11 11:36:47 adam Exp $ - Copyright (c) 1998-2004, Index Data. +/* $Id: yaz-proxy-config.cpp,v 1.19 2005-05-18 20:15:22 adam Exp $ + Copyright (c) 1998-2005, Index Data. This file is part of the yaz-proxy. -Zebra is free software; you can redistribute it and/or modify it under +YAZ proxy is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. -Zebra is distributed in the hope that it will be useful, but WITHOUT ANY +YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Zebra; see the file LICENSE.proxy. If not, write to the +along with YAZ proxy; see the file LICENSE. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include + +#if HAVE_DLFCN_H +#include +#endif + #include -#include +#include "proxyp.h" -Yaz_ProxyConfig::Yaz_ProxyConfig() + +class Yaz_ProxyModule { +private: + void *m_dl_handle; /* dlopen/close handle */ + Yaz_ProxyModule_entry *m_entry; + Yaz_ProxyModule *m_next; + void *m_user_handle; /* user handle */ +public: + Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent, + Yaz_ProxyModule *next); + ~Yaz_ProxyModule(); + + Yaz_ProxyModule *get_next() { return m_next; }; + int is_module(const char *name); + int authenticate(const char *target_name, void *element_ptr, + const char *user, const char *group, const char *password); +}; + +int Yaz_ProxyModule::is_module(const char *type) +{ + if (!type || !strcmp(m_entry->module_name, type)) + return 1; + return 0; +} + +Yaz_ProxyModule::Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent, + Yaz_ProxyModule *next) +{ + m_dl_handle = dl_handle; + m_entry = ent; + m_next = next; + m_user_handle = 0; + if (m_entry->int_version == 0) + { + struct Yaz_ProxyModule_int0 *int0 = + reinterpret_cast(m_entry->fl); + if (int0->init) + m_user_handle = (*int0->init)(); + } +} + +Yaz_ProxyModule::~Yaz_ProxyModule() +{ + if (m_entry->int_version == 0) + { + struct Yaz_ProxyModule_int0 *int0 = + reinterpret_cast(m_entry->fl); + if (int0->destroy) + (*int0->destroy)(m_user_handle); + } +#if HAVE_DLFCN_H + dlclose(m_dl_handle); +#endif +} + +int Yaz_ProxyModule::authenticate(const char *name, + void *element_ptr, + const char *user, const char *group, + const char *password) +{ + if (m_entry->int_version == 0) + { + struct Yaz_ProxyModule_int0 *int0 = + reinterpret_cast(m_entry->fl); + + if (!int0->authenticate) + return YAZPROXY_RET_NOT_ME; + return (*int0->authenticate)(m_user_handle, name, element_ptr, + user, group, password); + } + return YAZPROXY_RET_NOT_ME; +} + +class Yaz_ProxyConfigP { + friend class Yaz_ProxyConfig; + + Yaz_ProxyModule *m_modules; + + int mycmp(const char *hay, const char *item, size_t len); + int match_list(int v, const char *m); + int atoi_l(const char **cp); +#if HAVE_XSLT + void load_modules(void); + void unload_modules(void); + int check_schema(xmlNodePtr ptr, Z_RecordComposition *comp, + const char *schema_identifier); + xmlDocPtr m_docPtr; + xmlNodePtr m_proxyPtr; + void return_target_info(xmlNodePtr ptr, const char **url, + int *limit_bw, int *limit_pdu, int *limit_req, + int *target_idletime, int *client_idletime, + int *keepalive_limit_bw, int *keepalive_limit_pdu, + int *pre_init, const char **cql2rpn, + const char **negotiation_charset, + const char **negotiation_lang, + const char **target_charset); + void return_limit(xmlNodePtr ptr, + int *limit_bw, int *limit_pdu, int *limit_req); + int check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query, + char **addinfo); + xmlNodePtr find_target_node(const char *name, const char *db); + xmlNodePtr find_target_db(xmlNodePtr ptr, const char *db); + const char *get_text(xmlNodePtr ptr); + int check_type_1_attributes(ODR odr, xmlNodePtr ptr, + Z_AttributeList *attrs, + char **addinfo); + int check_type_1_structure(ODR odr, xmlNodePtr ptr, Z_RPNStructure *q, + char **addinfo); + int get_explain_ptr(const char *host, const char *db, + xmlNodePtr *ptr_target, xmlNodePtr *ptr_explain); +#endif + Yaz_ProxyConfigP(); + ~Yaz_ProxyConfigP(); +}; + +Yaz_ProxyConfigP::Yaz_ProxyConfigP() { - m_copy = 0; #if HAVE_XSLT m_docPtr = 0; m_proxyPtr = 0; #endif + m_modules = 0; } -Yaz_ProxyConfig::~Yaz_ProxyConfig() +Yaz_ProxyConfigP::~Yaz_ProxyConfigP() { #if HAVE_XSLT - if (!m_copy && m_docPtr) + if (m_docPtr) xmlFreeDoc(m_docPtr); #endif } +Yaz_ProxyConfig::Yaz_ProxyConfig() +{ + m_cp = new Yaz_ProxyConfigP; +} + +Yaz_ProxyConfig::~Yaz_ProxyConfig() +{ + delete m_cp; +} + +#if HAVE_XSLT +void Yaz_ProxyConfigP::unload_modules() +{ + Yaz_ProxyModule *m = m_modules; + while (m) + { + Yaz_ProxyModule *m_next = m->get_next(); + delete m; + m = m_next; + } + m_modules = 0; +} +#endif + +#if HAVE_XSLT +void Yaz_ProxyConfigP::load_modules() +{ + if (!m_proxyPtr) + return; + xmlNodePtr ptr; + for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next) + { + const char *fname; + if (ptr->type == XML_ELEMENT_NODE + && !strcmp((const char *) ptr->name, "module") + && (fname = get_text(ptr))) + { +#if HAVE_DLFCN_H + void *dl_handle = dlopen(fname, RTLD_NOW|RTLD_GLOBAL); + if (dl_handle) + { + Yaz_ProxyModule_entry *fl_ptr = 0; + fl_ptr = reinterpret_cast + (dlsym(dl_handle, "yazproxy_module")); + if (fl_ptr) + { + Yaz_ProxyModule *m = new Yaz_ProxyModule(dl_handle, + fl_ptr, + m_modules); + m_modules = m; + yaz_log(YLOG_LOG, "Loading %s OK", fname); + } + else + { + yaz_log(YLOG_WARN, "Loading %s FAIL: missing yazproxy_module symbol", fname); + dlclose(dl_handle); + } + } + else + yaz_log(YLOG_WARN, "Loading %s FAIL: dlopen failed", fname); +#else + yaz_log(YLOG_WARN, "Loading &s FAIL: dl unsupported", fname); +#endif + } + } +} +#endif + int Yaz_ProxyConfig::read_xml(const char *fname) { #if HAVE_XSLT @@ -47,23 +235,30 @@ int Yaz_ProxyConfig::read_xml(const char *fname) if (!ndoc) { - yaz_log(LOG_WARN, "Config file %s not found or parse error", fname); + yaz_log(YLOG_WARN, "Config file %s not found or parse error", fname); return -1; // no good } + int noSubstitutions = xmlXIncludeProcess(ndoc); + if (noSubstitutions == -1) + yaz_log(YLOG_WARN, "XInclude processing failed on config %s", fname); + xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc); if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE || strcmp((const char *) proxyPtr->name, "proxy")) { - yaz_log(LOG_WARN, "No proxy element in %s", fname); + yaz_log(YLOG_WARN, "No proxy element in %s", fname); xmlFreeDoc(ndoc); return -1; } - m_proxyPtr = proxyPtr; + m_cp->m_proxyPtr = proxyPtr; // OK: release previous and make it the current one. - if (m_docPtr) - xmlFreeDoc(m_docPtr); - m_docPtr = ndoc; + if (m_cp->m_docPtr) + xmlFreeDoc(m_cp->m_docPtr); + m_cp->m_docPtr = ndoc; + + m_cp->unload_modules(); + m_cp->load_modules(); return 0; #else return -2; @@ -71,7 +266,7 @@ int Yaz_ProxyConfig::read_xml(const char *fname) } #if HAVE_XSLT -const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr) +const char *Yaz_ProxyConfigP::get_text(xmlNodePtr ptr) { for(ptr = ptr->children; ptr; ptr = ptr->next) if (ptr->type == XML_TEXT_NODE) @@ -89,7 +284,7 @@ const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr) #endif #if HAVE_XSLT -void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr, +void Yaz_ProxyConfigP::return_limit(xmlNodePtr ptr, int *limit_bw, int *limit_pdu, int *limit_req) @@ -122,17 +317,20 @@ void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr, #endif #if HAVE_XSLT -void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr, - const char **url, - int *limit_bw, - int *limit_pdu, - int *limit_req, - int *target_idletime, - int *client_idletime, - int *keepalive_limit_bw, - int *keepalive_limit_pdu, - int *pre_init, - const char **cql2rpn) +void Yaz_ProxyConfigP::return_target_info(xmlNodePtr ptr, + const char **url, + int *limit_bw, + int *limit_pdu, + int *limit_req, + int *target_idletime, + int *client_idletime, + int *keepalive_limit_bw, + int *keepalive_limit_pdu, + int *pre_init, + const char **cql2rpn, + const char **negotiation_charset, + const char **negotiation_lang, + const char **target_charset) { *pre_init = 0; int no_url = 0; @@ -196,11 +394,32 @@ void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr, if (t) *cql2rpn = t; } + if (ptr->type == XML_ELEMENT_NODE + && !strcmp((const char *) ptr->name, "target-charset")) + { + const char *t = get_text(ptr); + if (t && target_charset) + *target_charset = t; + } + if (ptr->type == XML_ELEMENT_NODE + && !strcmp((const char *) ptr->name, "negotiation-charset")) + { + const char *t = get_text(ptr); + if (t) + *negotiation_charset = t; + } + if (ptr->type == XML_ELEMENT_NODE + && !strcmp((const char *) ptr->name, "negotiation-lang")) + { + const char *t = get_text(ptr); + if (t) + *negotiation_lang = t; + } } } #endif -int Yaz_ProxyConfig::atoi_l(const char **cp) +int Yaz_ProxyConfigP::atoi_l(const char **cp) { int v = 0; while (**cp && isdigit(**cp)) @@ -211,33 +430,33 @@ int Yaz_ProxyConfig::atoi_l(const char **cp) return v; } -int Yaz_ProxyConfig::match_list(int v, const char *m) +int Yaz_ProxyConfigP::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) + 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 (*m == ',') + m++; + } + return 0; } #if HAVE_XSLT -int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptrl, - Z_AttributeList *attrs, - char **addinfo) +int Yaz_ProxyConfigP::check_type_1_attributes(ODR odr, xmlNodePtr ptrl, + Z_AttributeList *attrs, + char **addinfo) { int i; for (i = 0; inum_attributes; i++) @@ -308,9 +527,9 @@ int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptrl, #endif #if HAVE_XSLT -int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr, - Z_RPNStructure *q, - char **addinfo) +int Yaz_ProxyConfigP::check_type_1_structure(ODR odr, xmlNodePtr ptr, + Z_RPNStructure *q, + char **addinfo) { if (q->which == Z_RPNStructure_complex) { @@ -334,8 +553,8 @@ int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr, #endif #if HAVE_XSLT -int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query, - char **addinfo) +int Yaz_ProxyConfigP::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); @@ -348,19 +567,19 @@ int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query, #if HAVE_XSLT xmlNodePtr ptr; - ptr = find_target_node(name, 0); + ptr = m_cp->find_target_node(name, 0); if (ptr) { if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101) - return check_type_1(odr, ptr, query->u.type_1, addinfo); + return m_cp->check_type_1(odr, ptr, query->u.type_1, addinfo); } #endif return 0; } #if HAVE_XSLT -int Yaz_ProxyConfig::check_schema(xmlNodePtr ptr, Z_RecordComposition *comp, - const char *schema_identifier) +int Yaz_ProxyConfigP::check_schema(xmlNodePtr ptr, Z_RecordComposition *comp, + const char *schema_identifier) { char *esn = 0; int default_match = 1; @@ -401,10 +620,154 @@ int Yaz_ProxyConfig::check_schema(xmlNodePtr ptr, Z_RecordComposition *comp, } #endif +const char *Yaz_ProxyConfig::check_mime_type(const char *path) +{ + struct { + const char *mask; + const char *type; + } types[] = { + {".xml", "text/xml"}, + {".xsl", "text/xml"}, + {".tkl", "text/xml"}, + {".xsd", "text/xml"}, + {".html", "text/html"}, + {".jpg", "image/jpeg"}, + {".png", "image/png"}, + {".gif", "image/gif"}, + {0, "text/plain"}, + {0, 0}, + }; + int i; + size_t plen = strlen (path); + for (i = 0; types[i].type; i++) + if (types[i].mask == 0) + return types[i].type; + else + { + size_t mlen = strlen(types[i].mask); + if (plen > mlen && !memcmp(path+plen-mlen, types[i].mask, mlen)) + return types[i].type; + } + return "application/octet-stream"; +} + + +void Yaz_ProxyConfig::target_authentication(const char *name, + ODR odr, Z_InitRequest *req) +{ +#if HAVE_XSLT + xmlNodePtr ptr = m_cp->find_target_node(name, 0); + if (!ptr) + return ; + + for (ptr = ptr->children; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "target-authentication")) + { + struct _xmlAttr *attr; + const char *type = "open"; + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!strcmp((const char *) attr->name, "type") && + attr->children && attr->children->type == XML_TEXT_NODE) + type = (const char *) attr->children->content; + } + const char *t = m_cp->get_text(ptr); + if (!t || !strcmp(type, "none")) + req->idAuthentication = 0; + else if (!strcmp(type, "anonymous")) + { + req->idAuthentication = + (Z_IdAuthentication *) + odr_malloc (odr, sizeof(*req->idAuthentication)); + req->idAuthentication->which = + Z_IdAuthentication_anonymous; + req->idAuthentication->u.anonymous = odr_nullval(); + } + else if (!strcmp(type, "open")) + { + req->idAuthentication = + (Z_IdAuthentication *) + odr_malloc (odr, sizeof(*req->idAuthentication)); + req->idAuthentication->which = + Z_IdAuthentication_open; + req->idAuthentication->u.open = odr_strdup (odr, t); + } + else if (!strcmp(type, "idPass")) + { + char user[64], group[64], password[64]; + *group = '\0'; + *password = '\0'; + *user = '\0'; + sscanf(t, "%63[^:]:%63[^:]:%63s", user, group, password); + + req->idAuthentication = + (Z_IdAuthentication *) + odr_malloc (odr, sizeof(*req->idAuthentication)); + req->idAuthentication->which = + Z_IdAuthentication_idPass; + req->idAuthentication->u.idPass = + (Z_IdPass*) odr_malloc(odr, sizeof(Z_IdPass)); + req->idAuthentication->u.idPass->userId = + *user ? odr_strdup(odr, user) : 0; + req->idAuthentication->u.idPass->groupId = + *group ? odr_strdup(odr, group) : 0; + req->idAuthentication->u.idPass->password = + *password ? odr_strdup(odr, password) : 0; + } + } +#endif +} + +int Yaz_ProxyConfig::client_authentication(const char *name, + const char *user, + const char *group, + const char *password) +{ + int ret = YAZPROXY_RET_NOT_ME; +#if HAVE_XSLT + xmlNodePtr ptr; + ptr = m_cp->find_target_node(name, 0); + if (!ptr) + return 1; + for (ptr = ptr->children; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "client-authentication")) + { + struct _xmlAttr *attr; + const char *module_name = 0; + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!strcmp((const char *) attr->name, "module") && + attr->children && attr->children->type == XML_TEXT_NODE) + module_name = (const char *) attr->children->content; + } + Yaz_ProxyModule *m = m_cp->m_modules; + for (; m; m = m->get_next()) + { + if (m->is_module(module_name)) + { + ret = m->authenticate(name, ptr, user, group, password); + if (ret != YAZPROXY_RET_NOT_ME) + break; + } + } + } +#endif + if (ret == YAZPROXY_RET_PERM) + return 0; + return 1; +} + int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, Odr_oid *syntax, Z_RecordComposition *comp, char **addinfo, - char **stylesheet, char **schema) + char **stylesheet, char **schema, + char **backend_type, + char **backend_charset, + char **usemarcon_ini_stage1, + char **usemarcon_ini_stage2 + ) { if (stylesheet) { @@ -416,11 +779,31 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, xfree (*schema); *schema = 0; } + if (backend_type) + { + xfree (*backend_type); + *backend_type = 0; + } + if (backend_charset) + { + xfree (*backend_charset); + *backend_charset = 0; + } + if (usemarcon_ini_stage1) + { + xfree (*usemarcon_ini_stage1); + *usemarcon_ini_stage1 = 0; + } + if (usemarcon_ini_stage2) + { + xfree (*usemarcon_ini_stage2); + *usemarcon_ini_stage2 = 0; + } #if HAVE_XSLT int syntax_has_matched = 0; xmlNodePtr ptr; - ptr = find_target_node(name, 0); + ptr = m_cp->find_target_node(name, 0); if (!ptr) return 0; for(ptr = ptr->children; ptr; ptr = ptr->next) @@ -434,6 +817,10 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, const char *match_marcxml = 0; const char *match_stylesheet = 0; const char *match_identifier = 0; + const char *match_backend_type = 0; + const char *match_backend_charset = 0; + const char *match_usemarcon_ini_stage1 = 0; + const char *match_usemarcon_ini_stage2 = 0; struct _xmlAttr *attr; for (attr = ptr->properties; attr; attr = attr->next) { @@ -452,6 +839,22 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, if (!strcmp((const char *) attr->name, "identifier") && attr->children && attr->children->type == XML_TEXT_NODE) match_identifier = (const char *) attr->children->content; + if (!strcmp((const char *) attr->name, "backendtype") && + attr->children && attr->children->type == XML_TEXT_NODE) + match_backend_type = (const char *) + attr->children->content; + if (!strcmp((const char *) attr->name, "backendcharset") && + attr->children && attr->children->type == XML_TEXT_NODE) + match_backend_charset = (const char *) + attr->children->content; + if (!strcmp((const char *) attr->name, "usemarconstage1") && + attr->children && attr->children->type == XML_TEXT_NODE) + match_usemarcon_ini_stage1 = (const char *) + attr->children->content; + if (!strcmp((const char *) attr->name, "usemarconstage2") && + attr->children && attr->children->type == XML_TEXT_NODE) + match_usemarcon_ini_stage2 = (const char *) + attr->children->content; } if (match_type) { @@ -474,7 +877,8 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, { if (!match_error) syntax_has_matched = 1; - match = check_schema(ptr->children, comp, match_identifier); + match = m_cp->check_schema(ptr->children, comp, + match_identifier); } if (match) { @@ -488,6 +892,26 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, xfree(*schema); *schema = xstrdup(match_identifier); } + if (backend_type && match_backend_type) + { + xfree(*backend_type); + *backend_type = xstrdup(match_backend_type); + } + if (backend_charset && match_backend_charset) + { + xfree(*backend_charset); + *backend_charset = xstrdup(match_backend_charset); + } + if (usemarcon_ini_stage1 && match_usemarcon_ini_stage1) + { + xfree(*usemarcon_ini_stage1); + *usemarcon_ini_stage1 = xstrdup(match_usemarcon_ini_stage1); + } + if (usemarcon_ini_stage1 && match_usemarcon_ini_stage2) + { + xfree(*usemarcon_ini_stage2); + *usemarcon_ini_stage2 = xstrdup(match_usemarcon_ini_stage2); + } if (match_marcxml) { return -1; @@ -513,7 +937,7 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, } #if HAVE_XSLT -xmlNodePtr Yaz_ProxyConfig::find_target_db(xmlNodePtr ptr, const char *db) +xmlNodePtr Yaz_ProxyConfigP::find_target_db(xmlNodePtr ptr, const char *db) { xmlNodePtr dptr; if (!db) @@ -540,7 +964,7 @@ xmlNodePtr Yaz_ProxyConfig::find_target_db(xmlNodePtr ptr, const char *db) return ptr; } -xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name, const char *db) +xmlNodePtr Yaz_ProxyConfigP::find_target_node(const char *name, const char *db) { xmlNodePtr ptr; if (!m_proxyPtr) @@ -603,14 +1027,18 @@ int Yaz_ProxyConfig::get_target_no(int no, int *keepalive_limit_bw, int *keepalive_limit_pdu, int *pre_init, - const char **cql2rpn) + const char **cql2rpn, + const char **authentication, + const char **negotiation_charset, + const char **negotiation_lang, + const char **target_charset) { #if HAVE_XSLT xmlNodePtr ptr; - if (!m_proxyPtr) + if (!m_cp->m_proxyPtr) return 0; int i = 0; - for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next) + for (ptr = m_cp->m_proxyPtr->children; ptr; ptr = ptr->next) if (ptr->type == XML_ELEMENT_NODE && !strcmp((const char *) ptr->name, "target")) { @@ -625,10 +1053,13 @@ int Yaz_ProxyConfig::get_target_no(int no, && attr->children->content) *name = (const char *) attr->children->content; } - return_target_info(ptr, url, limit_bw, limit_pdu, limit_req, - target_idletime, client_idletime, - keepalive_limit_bw, keepalive_limit_pdu, - pre_init, cql2rpn); + m_cp->return_target_info( + ptr, url, + limit_bw, limit_pdu, limit_req, + target_idletime, client_idletime, + keepalive_limit_bw, keepalive_limit_pdu, + pre_init, cql2rpn, + negotiation_charset, negotiation_lang, target_charset); return 1; } i++; @@ -637,7 +1068,7 @@ int Yaz_ProxyConfig::get_target_no(int no, return 0; } -int Yaz_ProxyConfig::mycmp(const char *hay, const char *item, size_t len) +int Yaz_ProxyConfigP::mycmp(const char *hay, const char *item, size_t len) { if (len == strlen(item) && memcmp(hay, item, len) == 0) return 1; @@ -649,14 +1080,14 @@ void Yaz_ProxyConfig::get_generic_info(int *log_mask, { #if HAVE_XSLT xmlNodePtr ptr; - if (!m_proxyPtr) + if (!m_cp->m_proxyPtr) return; - for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next) + for (ptr = m_cp->m_proxyPtr->children; ptr; ptr = ptr->next) { if (ptr->type == XML_ELEMENT_NODE && !strcmp((const char *) ptr->name, "log")) { - const char *v = get_text(ptr); + const char *v = m_cp->get_text(ptr); *log_mask = 0; while (v && *v) { @@ -664,13 +1095,13 @@ void Yaz_ProxyConfig::get_generic_info(int *log_mask, while (*cp && *cp != ',' && !isspace(*cp)) cp++; size_t len = cp - v; - if (mycmp(v, "client-apdu", len)) + if (m_cp->mycmp(v, "client-apdu", len)) *log_mask |= PROXY_LOG_APDU_CLIENT; - if (mycmp(v, "server-apdu", len)) + if (m_cp->mycmp(v, "server-apdu", len)) *log_mask |= PROXY_LOG_APDU_SERVER; - if (mycmp(v, "client-requests", len)) + if (m_cp->mycmp(v, "client-requests", len)) *log_mask |= PROXY_LOG_REQ_CLIENT; - if (mycmp(v, "server-requests", len)) + if (m_cp->mycmp(v, "server-requests", len)) *log_mask |= PROXY_LOG_REQ_SERVER; if (isdigit(*v)) *log_mask |= atoi(v); @@ -684,7 +1115,7 @@ void Yaz_ProxyConfig::get_generic_info(int *log_mask, if (ptr->type == XML_ELEMENT_NODE && !strcmp((const char *) ptr->name, "max-clients")) { - const char *t = get_text(ptr); + const char *t = m_cp->get_text(ptr); if (t) { *max_clients = atoi(t); @@ -696,57 +1127,119 @@ void Yaz_ProxyConfig::get_generic_info(int *log_mask, #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) +int Yaz_ProxyConfigP::get_explain_ptr(const char *host, const char *db, + xmlNodePtr *ptr_target, + xmlNodePtr *ptr_explain) +{ + xmlNodePtr ptr; + if (!m_proxyPtr) + return 0; + if (!db) + return 0; + for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next) { - ptr = ptr->children; - for (; ptr; ptr = ptr->next) - if (ptr->type == XML_ELEMENT_NODE && - !strcmp((const char *) ptr->name, "explain")) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "target")) + { + *ptr_target = ptr; + xmlNodePtr ptr = (*ptr_target)->children; + for (; ptr; ptr = ptr->next) { - xmlNodePtr ptr1 = ptr->children; - if (db) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "explain")) { - for (; ptr1; ptr1 = ptr1->next) - if (ptr1->type == XML_ELEMENT_NODE && - !strcmp((const char *) ptr1->name, "serverInfo")) + *ptr_explain = ptr; + xmlNodePtr ptr = (*ptr_explain)->children; + + for (; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "serverInfo")) break; - if (!ptr1) + if (!ptr) continue; - for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next) - if (ptr1->type == XML_ELEMENT_NODE && - !strcmp((const char *) ptr1->name, "database")) + for (ptr = ptr->children; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "database")) break; - if (!ptr1) + if (!ptr) continue; - for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next) - if (ptr1->type == XML_TEXT_NODE && - ptr1->content && - !strcmp((const char *) ptr1->content, db)) + for (ptr = ptr->children; ptr; ptr = ptr->next) + if (ptr->type == XML_TEXT_NODE && + ptr->content && + !strcmp((const char *) ptr->content, db)) break; - if (!ptr1) + if (!ptr) continue; + return 1; } - xmlNodePtr ptr2 = xmlCopyNode(ptr, 1); + } + } + } + return 0; +} +#endif - 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; +const char *Yaz_ProxyConfig::get_explain_name(const char *db, + const char **backend_db) +{ +#if HAVE_XSLT + xmlNodePtr ptr_target, ptr_explain; + if (m_cp->get_explain_ptr(0, db, &ptr_target, &ptr_explain) + && ptr_target) + { + struct _xmlAttr *attr; + const char *name = 0; + + for (attr = ptr_target->properties; attr; attr = attr->next) + if (!strcmp((const char *) attr->name, "name") + && attr->children + && attr->children->type==XML_TEXT_NODE + && attr->children->content + && attr->children->content[0]) + { + name = (const char *)attr->children->content; + break; } + if (name) + { + for (attr = ptr_target->properties; attr; attr = attr->next) + if (!strcmp((const char *) attr->name, "database")) + { + if (attr->children + && attr->children->type==XML_TEXT_NODE + && attr->children->content) + *backend_db = (const char *) attr->children->content; + } + return name; + } + } +#endif + return 0; +} + +char *Yaz_ProxyConfig::get_explain_doc(ODR odr, const char *name, + const char *db, int *len) +{ +#if HAVE_XSLT + xmlNodePtr ptr_target, ptr_explain; + if (m_cp->get_explain_ptr(0 /* host */, db, &ptr_target, &ptr_explain)) + { + xmlNodePtr ptr2 = xmlCopyNode(ptr_explain, 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 return 0; @@ -763,23 +1256,26 @@ void Yaz_ProxyConfig::get_target_info(const char *name, int *keepalive_limit_bw, int *keepalive_limit_pdu, int *pre_init, - const char **cql2rpn) + const char **cql2rpn, + const char **negotiation_charset, + const char **negotiation_lang, + const char **target_charset) { #if HAVE_XSLT xmlNodePtr ptr; - if (!m_proxyPtr) + if (!m_cp->m_proxyPtr) { url[0] = name; url[1] = 0; return; } url[0] = 0; - for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next) + for (ptr = m_cp->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); + const char *t = m_cp->get_text(ptr); if (t) { *max_clients = atoi(t); @@ -788,7 +1284,7 @@ void Yaz_ProxyConfig::get_target_info(const char *name, } } } - ptr = find_target_node(name, 0); + ptr = m_cp->find_target_node(name, 0); if (ptr) { if (name) @@ -796,10 +1292,12 @@ void Yaz_ProxyConfig::get_target_info(const char *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, - pre_init, cql2rpn); + m_cp->return_target_info(ptr, url, limit_bw, limit_pdu, limit_req, + target_idletime, client_idletime, + keepalive_limit_bw, keepalive_limit_pdu, + pre_init, cql2rpn, + negotiation_charset, negotiation_lang, + target_charset); } #else *url = name;