X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_zoom.cpp;h=2062b1c0ce5621b57314403680fc9fbfabef1646;hb=ed11bc4976b4ab91eb399455f5c2f4940d136eca;hp=95a444bd68bcae04a233b0509c7c35bb58966d1e;hpb=73f37c91c144b070020df2f27472c09b62367acf;p=metaproxy-moved-to-github.git diff --git a/src/filter_zoom.cpp b/src/filter_zoom.cpp index 95a444b..2062b1c 100644 --- a/src/filter_zoom.cpp +++ b/src/filter_zoom.cpp @@ -1,5 +1,5 @@ /* This file is part of Metaproxy. - Copyright (C) 2005-2012 Index Data + Copyright (C) Index Data Metaproxy 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 @@ -51,6 +51,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include namespace mp = metaproxy_1; namespace yf = mp::filter; @@ -60,6 +61,7 @@ namespace metaproxy_1 { class Zoom::Searchable : boost::noncopyable { public: std::string authentication; + std::string authenticationMode; std::string cfAuth; std::string cfProxy; std::string cfSubDB; @@ -107,10 +109,11 @@ namespace metaproxy_1 { void connect(std::string zurl, int *error, char **addinfo, ODR odr); void search(ZOOM_query q, Odr_int *hits, - int *error, char **addinfo, ODR odr); + int *error, char **addinfo, Z_FacetList **fl, ODR odr); void present(Odr_int start, Odr_int number, ZOOM_record *recs, int *error, char **addinfo, ODR odr); void set_option(const char *name, const char *value); + void set_option(const char *name, const char *value, size_t l); void set_option(const char *name, std::string value); const char *get_option(const char *name); void get_zoom_error(int *error, char **addinfo, ODR odr); @@ -125,7 +128,6 @@ namespace metaproxy_1 { BackendPtr m_backend; void handle_package(mp::Package &package); void handle_search(mp::Package &package); - void auth(mp::Package &package, Z_InitRequest *req, int *error, char **addinfo, ODR odr); @@ -227,6 +229,7 @@ namespace metaproxy_1 { CCL_bibset bibset; std::string element_transform; std::string element_raw; + std::string element_passthru; std::string proxy; xsltStylesheetPtr explain_xsp; xsltStylesheetPtr record_xsp; @@ -369,15 +372,84 @@ void yf::Zoom::Backend::connect(std::string zurl, } void yf::Zoom::Backend::search(ZOOM_query q, Odr_int *hits, - int *error, char **addinfo, ODR odr) + int *error, char **addinfo, Z_FacetList **flp, + ODR odr) { ZOOM_resultset_destroy(m_resultset); + m_resultset = 0; + if (*flp) + { + WRBUF w = wrbuf_alloc(); + yaz_facet_list_to_wrbuf(w, *flp); + set_option("facets", wrbuf_cstr(w)); + wrbuf_destroy(w); + } m_resultset = ZOOM_connection_search(m_connection, q); get_zoom_error(error, addinfo, odr); if (*error == 0) *hits = ZOOM_resultset_size(m_resultset); else *hits = 0; + *flp = 0; + size_t num_facets = ZOOM_resultset_facets_size(m_resultset); + if (num_facets > 0) + { + size_t i; + Z_FacetList *fl = (Z_FacetList *) odr_malloc(odr, sizeof(*fl)); + fl->elements = (Z_FacetField **) + odr_malloc(odr, num_facets * sizeof(*fl->elements)); + for (i = 0; i < num_facets; i++) + { + ZOOM_facet_field ff = + ZOOM_resultset_get_facet_field_by_index(m_resultset, i); + if (!ff) + break; + Z_AttributeList *al = (Z_AttributeList *) + odr_malloc(odr, sizeof(*al)); + al->num_attributes = 1; + al->attributes = (Z_AttributeElement **) + odr_malloc(odr, sizeof(*al->attributes)); + Z_AttributeElement *ae = al->attributes[0] = (Z_AttributeElement *) + odr_malloc(odr, sizeof(**al->attributes)); + ae->attributeSet = 0; + ae->attributeType = odr_intdup(odr, 1); + ae->which = Z_AttributeValue_complex; + ae->value.complex = (Z_ComplexAttribute *) + odr_malloc(odr, sizeof(*ae->value.complex)); + ae->value.complex->num_list = 1; + ae->value.complex->list = (Z_StringOrNumeric **) + odr_malloc(odr, sizeof(**ae->value.complex->list)); + ae->value.complex->list[0] = (Z_StringOrNumeric *) + odr_malloc(odr, sizeof(**ae->value.complex->list)); + ae->value.complex->list[0]->which = Z_StringOrNumeric_string; + ae->value.complex->list[0]->u.string = + odr_strdup(odr, ZOOM_facet_field_name(ff)); + ae->value.complex->num_semanticAction = 0; + ae->value.complex->semanticAction = 0; + + int num_terms = ZOOM_facet_field_term_count(ff); + fl->elements[i] = (Z_FacetField *) + odr_malloc(odr, sizeof(Z_FacetField)); + fl->elements[i]->attributes = al; + fl->elements[i]->num_terms = num_terms; + fl->elements[i]->terms = (Z_FacetTerm **) + odr_malloc(odr, num_terms * sizeof(Z_FacetTerm *)); + int j; + for (j = 0; j < num_terms; j++) + { + int freq; + const char *a_term = ZOOM_facet_field_get_term(ff, j, &freq); + Z_FacetTerm *ft = (Z_FacetTerm *) odr_malloc(odr, sizeof(*ft)); + ft->term = z_Term_create(odr, Z_Term_general, a_term, + strlen(a_term)); + ft->count = odr_intdup(odr, freq); + + fl->elements[i]->terms[j] = ft; + } + } + fl->num = i; + *flp = fl; + } } void yf::Zoom::Backend::present(Odr_int start, Odr_int number, @@ -388,6 +460,12 @@ void yf::Zoom::Backend::present(Odr_int start, Odr_int number, get_zoom_error(error, addinfo, odr); } + +void yf::Zoom::Backend::set_option(const char *name, const char *value, size_t l) +{ + ZOOM_connection_option_setl(m_connection, name, value, l); +} + void yf::Zoom::Backend::set_option(const char *name, const char *value) { ZOOM_connection_option_set(m_connection, name, value); @@ -473,7 +551,8 @@ void yf::Zoom::Impl::release_frontend(mp::Package &package) } yf::Zoom::Impl::Impl() : - apdu_log(false), element_transform("pz2") , element_raw("raw"), + apdu_log(false), element_transform("pz2") , element_raw("raw") , + element_passthru("F"), zoom_timeout("40"), proxy_timeout(1) { bibset = ccl_qual_mk(); @@ -506,6 +585,11 @@ yf::Zoom::SearchablePtr yf::Zoom::Impl::parse_torus_record(const xmlNode *ptr) s->authentication = mp::xml::get_text(ptr); } else if (!strcmp((const char *) ptr->name, + "authenticationMode")) + { + s->authenticationMode = mp::xml::get_text(ptr); + } + else if (!strcmp((const char *) ptr->name, "cfAuth")) { s->cfAuth = mp::xml::get_text(ptr); @@ -700,6 +784,8 @@ void yf::Zoom::Impl::configure(const xmlNode *ptr, bool test_only, element_transform = mp::xml::get_text(attr->children); else if (!strcmp((const char *) attr->name, "element_raw")) element_raw = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "element_passthru")) + element_passthru = mp::xml::get_text(attr->children); else if (!strcmp((const char *) attr->name, "proxy")) proxy = mp::xml::get_text(attr->children); else if (!strcmp((const char *) attr->name, "explain_xsl")) @@ -940,8 +1026,8 @@ bool yf::Zoom::Frontend::create_content_session(mp::Package &package, "unable to open content config %s", m_p->content_config_file.c_str()); *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; - *addinfo = (char *) odr_malloc(odr, 60 + tmp_file.length()); - sprintf(*addinfo, "unable to open content config %s", + *addinfo = (char *) odr_malloc(odr, 70 + tmp_file.length()); + sprintf(*addinfo, "zoom: unable to open content config %s", m_p->content_config_file.c_str()); return false; } @@ -965,7 +1051,7 @@ bool yf::Zoom::Frontend::create_content_session(mp::Package &package, package.log("zoom", YLOG_WARN, "bad tmp_file %s", tmp_file.c_str()); *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; *addinfo = (char *) odr_malloc(odr, 60 + tmp_file.length()); - sprintf(*addinfo, "bad format of content tmp_file: %s", + sprintf(*addinfo, "zoom: bad format of content tmp_file: %s", tmp_file.c_str()); xfree(fname); return false; @@ -983,8 +1069,8 @@ bool yf::Zoom::Frontend::create_content_session(mp::Package &package, { package.log("zoom", YLOG_WARN|YLOG_ERRNO, "create %s", fname); *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; - *addinfo = (char *) odr_malloc(odr, 40 + strlen(fname)); - sprintf(*addinfo, "Could not create %s", fname); + *addinfo = (char *) odr_malloc(odr, 50 + strlen(fname)); + sprintf(*addinfo, "zoom: could not create %s", fname); xfree(fname); return false; } @@ -1132,7 +1218,7 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( BackendPtr notfound; char *msg = (char*) odr_malloc(odr, strlen(name) + 30); *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; - sprintf(msg, "Bad database argument: %s", name); + sprintf(msg, "zoom: bad database argument: %s", name); *addinfo = msg; return notfound; } @@ -1242,8 +1328,8 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( if (!xsp_doc) { *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; - *addinfo = (char *) odr_malloc(odr, 40); - sprintf(*addinfo, "xmlParseMemory failed"); + *addinfo = odr_strdup(odr, "zoom: xmlParseMemory failed " + "for literalTransform XSL"); BackendPtr b; return b; } @@ -1251,7 +1337,9 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( if (!xsp) { *error = YAZ_BIB1_DATABASE_DOES_NOT_EXIST; - *addinfo = odr_strdup(odr, "xsltParseStylesheetDoc failed"); + *addinfo = + odr_strdup(odr,"zoom: xsltParseStylesheetDoc failed " + "for literalTransform XSL"); BackendPtr b; xmlFreeDoc(xsp_doc); return b; @@ -1277,7 +1365,7 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; *addinfo = (char *) odr_malloc(odr, 40 + sptr->transform_xsl_fname.length()); - sprintf(*addinfo, "File could not be read: %s", + sprintf(*addinfo, "zoom: could not open file %s", sptr->transform_xsl_fname.c_str()); BackendPtr b; return b; @@ -1286,16 +1374,19 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( if (!xsp_doc) { *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; - *addinfo = (char *) odr_malloc(odr, 40 + fname.length()); - sprintf(*addinfo, "xmlParseFile failed. File: %s", fname.c_str()); + *addinfo = (char *) odr_malloc(odr, 50 + fname.length()); + sprintf(*addinfo, "zoom: xmlParseFile failed for file %s", + fname.c_str()); BackendPtr b; return b; } xsp = xsltParseStylesheetDoc(xsp_doc); if (!xsp) { - *error = YAZ_BIB1_DATABASE_DOES_NOT_EXIST; - *addinfo = odr_strdup(odr, "xsltParseStylesheetDoc failed"); + *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; + *addinfo = (char *) odr_malloc(odr, 50 + fname.length()); + sprintf(*addinfo, "zoom: xsltParseStylesheetDoc failed " + "for file %s", fname.c_str()); BackendPtr b; xmlFreeDoc(xsp_doc); return b; @@ -1317,7 +1408,7 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( if (!cqlt) { *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; - *addinfo = odr_strdup(odr, "Missing/invalid cql2rpn file"); + *addinfo = odr_strdup(odr, "zoom: missing/invalid cql2rpn file"); BackendPtr b; xsltFreeStylesheet(xsp); return b; @@ -1336,8 +1427,7 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( if (sptr->query_encoding.length()) b->set_option("rpnCharset", sptr->query_encoding); - if (sptr->extraArgs.length()) - b->set_option("extraArgs", sptr->extraArgs); + std::string extraArgs = sptr->extraArgs; b->set_option("timeout", m_p->zoom_timeout.c_str()); @@ -1390,6 +1480,9 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( out_names[no_out_args] = "subdatabase"; out_values[no_out_args++] = odr_strdup(odr, sptr->cfSubDB.c_str()); } + if (!param_nocproxy && b->sptr->contentConnector.length()) + param_nocproxy = "1"; + if (param_nocproxy) { out_names[no_out_args] = "nocproxy"; @@ -1398,32 +1491,46 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( } else { - size_t found = authentication.find('/'); - - if (sptr->sru.length() && found != std::string::npos) + const char *auth = authentication.c_str(); + const char *cp1 = strchr(auth, ' '); + if (!cp1 && sptr->sru.length()) + cp1 = strchr(auth, '/'); + if (!cp1) { - b->set_option("user", authentication.substr(0, found)); - b->set_option("password", authentication.substr(found+1)); + /* Z39.50 user/password style, or no password for SRU */ + b->set_option("user", auth); } else - b->set_option("user", authentication); + { + /* now consider group as well */ + const char *cp2 = strchr(cp1 + 1, ' '); + b->set_option("user", auth, cp1 - auth); + if (!cp2) + b->set_option("password", cp1 + 1); + else + { + b->set_option("group", cp1 + 1, cp2 - cp1 - 1); + b->set_option("password", cp2 + 1); + } + } + if (sptr->authenticationMode.length()) + b->set_option("authenticationMode", sptr->authenticationMode); if (proxy.length()) b->set_option("proxy", proxy); } - std::string url; + if (extraArgs.length()) + b->set_option("extraArgs", extraArgs); + + std::string url(sptr->target); if (sptr->sru.length()) { - url = "http://" + sptr->target; b->set_option("sru", sptr->sru); - + if (url.find("://") == std::string::npos) + url = "http://" + url; if (sptr->sru_version.length()) b->set_option("sru_version", sptr->sru_version); } - else - { - url = sptr->target; - } if (no_out_args) { char *x_args = 0; @@ -1503,9 +1610,15 @@ void yf::Zoom::Frontend::prepare_elements(BackendPtr b, if (enable_pz2_retrieval) { - element_set_name = 0; - if (b->sptr->element_set.length()) - element_set_name = b->sptr->element_set.c_str(); + if (element_set_name && !strcmp(element_set_name, + m_p->element_passthru.c_str())) + ; + else + { + element_set_name = 0; + if (b->sptr->element_set.length()) + element_set_name = b->sptr->element_set.c_str(); + } } b->set_option("elementSetName", element_set_name); @@ -2254,6 +2367,14 @@ next_proxy: ZOOM_query q = ZOOM_query_create(); ZOOM_query_sortby2(q, b->sptr->sortStrategy.c_str(), sortkeys.c_str()); + Z_FacetList *fl = 0; + + // Facets for request.. And later for reponse + if (!fl) + fl = yaz_oi_get_facetlist(&sr->otherInfo); + if (!fl) + fl = yaz_oi_get_facetlist(&sr->additionalSearchInfo); + if (b->get_option("sru")) { int status = 0; @@ -2277,14 +2398,14 @@ next_proxy: { ZOOM_query_cql(q, wrbuf_cstr(wrb)); package.log("zoom", YLOG_LOG, "CQL: %s", wrbuf_cstr(wrb)); - b->search(q, &hits, &error, &addinfo, odr); + b->search(q, &hits, &error, &addinfo, &fl, odr); } ZOOM_query_destroy(q); if (status) { error = YAZ_BIB1_MALFORMED_QUERY; - const char *addinfo = "can not convert from RPN to CQL/SOLR"; + const char *addinfo = "can not convert from RPN to CQL/Solr"; log_diagnostic(package, error, addinfo); apdu_res = odr.create_searchResponse(apdu_req, error, addinfo); package.response() = apdu_res; @@ -2295,7 +2416,7 @@ next_proxy: { ZOOM_query_prefix(q, wrbuf_cstr(pqf_wrbuf)); package.log("zoom", YLOG_LOG, "search PQF: %s", wrbuf_cstr(pqf_wrbuf)); - b->search(q, &hits, &error, &addinfo, odr); + b->search(q, &hits, &error, &addinfo, &fl, odr); ZOOM_query_destroy(q); } @@ -2327,6 +2448,9 @@ next_proxy: odr_intdup(odr, number_of_records_returned); } apdu_res->u.searchResponse->resultCount = odr_intdup(odr, hits); + if (fl) + yaz_oi_set_facetlist(&apdu_res->u.searchResponse->additionalSearchInfo, + odr, fl); package.response() = apdu_res; } @@ -2491,8 +2615,13 @@ void yf::Zoom::Frontend::auth(mp::Package &package, Z_InitRequest *req, } } - std::string ip = package.origin().get_address(); - yaz_log(YLOG_LOG, "IP=%s", ip.c_str()); + Z_OtherInformation **oi = &req->otherInfo; + const char *ip = + yaz_oi_get_string_oid(oi, yaz_oid_userinfo_client_ip, 1, 0); + if (!ip) + ip = package.origin().get_address().c_str(); + + yaz_log(YLOG_LOG, "IP=%s", ip); std::string torus_query; int failure_code; @@ -2505,13 +2634,8 @@ void yf::Zoom::Frontend::auth(mp::Package &package, Z_InitRequest *req, } else { - const char *ip_cstr = ip.c_str(); - const char *cp = strchr(ip_cstr, ':'); - if (cp) - ip_cstr = cp + 1; - torus_query = "ip encloses/net.ipaddress \""; - torus_query += escape_cql_term(std::string(ip_cstr)); + torus_query += escape_cql_term(std::string(ip)); torus_query += "\""; failure_code = YAZ_BIB1_INIT_AC_BLOCKED_NETWORK_ADDRESS; } @@ -2524,8 +2648,8 @@ void yf::Zoom::Frontend::auth(mp::Package &package, Z_InitRequest *req, { // something fundamental broken in lookup. *error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR; - *addinfo = odr_strdup(odr, "Torus server unavailable or " - "incorrectly configured"); + *addinfo = odr_strdup(odr, "zoom: torus server unavailable or " + "incorrectly configured."); return; } const xmlNode *ptr = xmlDocGetRootElement(doc);