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=c05724e53182c6a720d04e3f19eea8cab8004c23;hb=2faeba3f61ac423a9c71222e9a15377724d8f0fa;hpb=b33db4435e63a69fc8aafa1e3a163743b79b6990 diff --git a/src/yaz-proxy-config.cpp b/src/yaz-proxy-config.cpp index c05724e..76259cf 100644 --- a/src/yaz-proxy-config.cpp +++ b/src/yaz-proxy-config.cpp @@ -1,5 +1,5 @@ -/* $Id: yaz-proxy-config.cpp,v 1.9 2004-11-09 14:24:22 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. @@ -20,26 +20,98 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA */ #include + +#if HAVE_DLFCN_H +#include +#endif + #include -#include +#include "proxyp.h" -#if HAVE_XSLT -#include -#include -#include -#include -#include + +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; - int m_copy; + 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; @@ -49,7 +121,9 @@ class Yaz_ProxyConfigP { int *target_idletime, int *client_idletime, int *keepalive_limit_bw, int *keepalive_limit_pdu, int *pre_init, const char **cql2rpn, - const char **authentication); + 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, @@ -65,27 +139,95 @@ class Yaz_ProxyConfigP { int get_explain_ptr(const char *host, const char *db, xmlNodePtr *ptr_target, xmlNodePtr *ptr_explain); #endif + Yaz_ProxyConfigP(); + ~Yaz_ProxyConfigP(); }; -Yaz_ProxyConfig::Yaz_ProxyConfig() +Yaz_ProxyConfigP::Yaz_ProxyConfigP() { - m_cp = new Yaz_ProxyConfigP; - m_cp->m_copy = 0; #if HAVE_XSLT - m_cp->m_docPtr = 0; - m_cp->m_proxyPtr = 0; + m_docPtr = 0; + m_proxyPtr = 0; #endif + m_modules = 0; } -Yaz_ProxyConfig::~Yaz_ProxyConfig() +Yaz_ProxyConfigP::~Yaz_ProxyConfigP() { #if HAVE_XSLT - if (!m_cp->m_copy && m_cp->m_docPtr) - xmlFreeDoc(m_cp->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 @@ -93,18 +235,18 @@ 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(LOG_WARN, "XInclude processing failed on config %s", fname); + 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; } @@ -114,6 +256,9 @@ int Yaz_ProxyConfig::read_xml(const char *fname) 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; @@ -183,7 +328,9 @@ void Yaz_ProxyConfigP::return_target_info(xmlNodePtr ptr, int *keepalive_limit_pdu, int *pre_init, const char **cql2rpn, - const char **authentication) + const char **negotiation_charset, + const char **negotiation_lang, + const char **target_charset) { *pre_init = 0; int no_url = 0; @@ -248,11 +395,25 @@ void Yaz_ProxyConfigP::return_target_info(xmlNodePtr ptr, *cql2rpn = t; } if (ptr->type == XML_ELEMENT_NODE - && !strcmp((const char *) ptr->name, "authentication")) + && !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) - *authentication = t; + *negotiation_lang = t; } } } @@ -367,8 +528,8 @@ int Yaz_ProxyConfigP::check_type_1_attributes(ODR odr, xmlNodePtr ptrl, #if HAVE_XSLT int Yaz_ProxyConfigP::check_type_1_structure(ODR odr, xmlNodePtr ptr, - Z_RPNStructure *q, - char **addinfo) + Z_RPNStructure *q, + char **addinfo) { if (q->which == Z_RPNStructure_complex) { @@ -459,12 +620,154 @@ int Yaz_ProxyConfigP::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 **backend_type, - char **backend_charset) + char **backend_charset, + char **usemarcon_ini_stage1, + char **usemarcon_ini_stage2 + ) { if (stylesheet) { @@ -486,6 +789,16 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, 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; @@ -506,6 +819,8 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, 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) { @@ -532,6 +847,14 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, 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) { @@ -579,6 +902,16 @@ int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name, 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; @@ -695,7 +1028,10 @@ int Yaz_ProxyConfig::get_target_no(int no, int *keepalive_limit_pdu, int *pre_init, const char **cql2rpn, - const char **authentication) + const char **authentication, + const char **negotiation_charset, + const char **negotiation_lang, + const char **target_charset) { #if HAVE_XSLT xmlNodePtr ptr; @@ -722,7 +1058,8 @@ int Yaz_ProxyConfig::get_target_no(int no, limit_bw, limit_pdu, limit_req, target_idletime, client_idletime, keepalive_limit_bw, keepalive_limit_pdu, - pre_init, cql2rpn, authentication); + pre_init, cql2rpn, + negotiation_charset, negotiation_lang, target_charset); return 1; } i++; @@ -920,7 +1257,9 @@ void Yaz_ProxyConfig::get_target_info(const char *name, int *keepalive_limit_pdu, int *pre_init, const char **cql2rpn, - const char **authentication) + const char **negotiation_charset, + const char **negotiation_lang, + const char **target_charset) { #if HAVE_XSLT xmlNodePtr ptr; @@ -956,7 +1295,9 @@ void Yaz_ProxyConfig::get_target_info(const char *name, 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, authentication); + pre_init, cql2rpn, + negotiation_charset, negotiation_lang, + target_charset); } #else *url = name;