X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_sru_to_z3950.cpp;h=45abb57813aa73ef7e554de93e15f6a29fb7e1a8;hb=6c0c08aa87abd3698c7a2dab55628cbbe788659c;hp=76c5df8702f9f45e42123465436c1e0245eca59e;hpb=c93d8c8db5ae24e01775060677f8e8e9c2afff34;p=metaproxy-moved-to-github.git diff --git a/src/filter_sru_to_z3950.cpp b/src/filter_sru_to_z3950.cpp index 76c5df8..45abb57 100644 --- a/src/filter_sru_to_z3950.cpp +++ b/src/filter_sru_to_z3950.cpp @@ -1,8 +1,8 @@ -/* $Id: filter_sru_to_z3950.cpp,v 1.15 2006-09-29 08:42:47 marc Exp $ - Copyright (c) 2005-2006, Index Data. +/* $Id: filter_sru_to_z3950.cpp,v 1.34 2007-04-16 21:54:52 adam Exp $ + Copyright (c) 2005-2007, Index Data. See the LICENSE file for details - */ +*/ #include "config.hpp" #include "filter.hpp" @@ -16,13 +16,15 @@ #include #include #include +#include #include #include #include #include - +#include +#include namespace mp = metaproxy_1; namespace mp_util = metaproxy_1::util; @@ -31,73 +33,58 @@ namespace yf = mp::filter; namespace metaproxy_1 { namespace filter { - class SRUtoZ3950::Rep { + class SRUtoZ3950::Impl { + public: + void configure(const xmlNode *xmlnode); + void process(metaproxy_1::Package &package); private: union SRW_query {char * cql; char * xcql; char * pqf;}; typedef const int& SRW_query_type; - public: - void configure(const xmlNode *xmlnode); - void process(metaproxy_1::Package &package) const; + std::map m_database_explain; private: - std::string sru_protocol(const Z_HTTP_Request &http_req) const; - std::string debug_http(const Z_HTTP_Request &http_req) const; - void http_response(mp::Package &package, - const std::string &content, - int http_code = 200) const; - bool build_sru_debug_package(mp::Package &package) const; - bool build_simple_explain(mp::Package &package, - mp::odr &odr_en, - Z_SRW_PDU *sru_pdu_res, - Z_SRW_explainRequest const *er_req) - const; - bool build_sru_response(mp::Package &package, - mp::odr &odr_en, - Z_SOAP *soap, - const Z_SRW_PDU *sru_pdu_res, - char *charset, - const char *stylesheet) const; - Z_SRW_PDU * decode_sru_request(mp::Package &package, - mp::odr &odr_de, - mp::odr &odr_en, - Z_SRW_PDU *sru_pdu_res, - Z_SOAP *&soap, - char *charset, - char *stylesheet) const; - bool check_sru_query_exists(mp::Package &package, - mp::odr &odr_en, - Z_SRW_PDU *sru_pdu_res, - Z_SRW_searchRetrieveRequest - const *sr_req) const; + bool z3950_build_query(mp::odr &odr_en, Z_Query *z_query, const SRW_query &query, SRW_query_type query_type) const; + bool z3950_init_request(mp::Package &package, - const std::string - &database = "Default") const; + mp::odr &odr_en, + Z_SRW_PDU *sru_pdu_res, + const std::string + &database = "Default") const; + bool z3950_close_request(mp::Package &package) const; + bool z3950_search_request(mp::Package &package, mp::odr &odr_en, Z_SRW_PDU *sru_pdu_res, Z_SRW_searchRetrieveRequest const *sr_req) const; + bool z3950_present_request(mp::Package &package, mp::odr &odr_en, Z_SRW_PDU *sru_pdu_res, Z_SRW_searchRetrieveRequest const *sr_req) const; + bool z3950_scan_request(mp::Package &package, mp::odr &odr_en, Z_SRW_PDU *sru_pdu_res, Z_SRW_scanRequest const *sr_req) const; - Z_ElementSetNames * build_esn_from_schema(mp::odr &odr_en, const char *schema) const; - int z3950_to_srw_diag(mp::odr &odr_en, Z_SRW_searchRetrieveResponse *srw_res, + + bool z3950_to_srw_diagnostics_ok(mp::odr &odr_en, + Z_SRW_searchRetrieveResponse *srw_res, + Z_Records *records) const; + + int z3950_to_srw_diag(mp::odr &odr_en, + Z_SRW_searchRetrieveResponse *srw_res, Z_DefaultDiagFormat *ddf) const; }; } } -yf::SRUtoZ3950::SRUtoZ3950() : m_p(new Rep) +yf::SRUtoZ3950::SRUtoZ3950() : m_p(new Impl) { } @@ -115,11 +102,38 @@ void yf::SRUtoZ3950::process(mp::Package &package) const m_p->process(package); } -void yf::SRUtoZ3950::Rep::configure(const xmlNode *xmlnode) +void yf::SRUtoZ3950::Impl::configure(const xmlNode *confignode) { + const xmlNode * dbnode; + + for (dbnode = confignode->children; dbnode; dbnode = dbnode->next){ + if (dbnode->type != XML_ELEMENT_NODE) + continue; + + std::string database; + mp::xml::check_element_mp(dbnode, "database"); + + for (struct _xmlAttr *attr = dbnode->properties; + attr; attr = attr->next){ + + mp::xml::check_attribute(attr, "", "name"); + database = mp::xml::get_text(attr); + + const xmlNode *explainnode; + for (explainnode = dbnode->children; + explainnode; explainnode = explainnode->next){ + if (explainnode->type != XML_ELEMENT_NODE) + continue; + if (explainnode) + break; + } + // assigning explain node to database name - no check yet + m_database_explain.insert(std::make_pair(database, explainnode)); + } + } } -void yf::SRUtoZ3950::Rep::process(mp::Package &package) const +void yf::SRUtoZ3950::Impl::process(mp::Package &package) { Z_GDU *zgdu_req = package.request().get(); @@ -131,61 +145,81 @@ void yf::SRUtoZ3950::Rep::process(mp::Package &package) const // only working on HTTP_Request packages now - - // TODO: Z3950 response parsing and translation to SRU package bool ok = true; mp::odr odr_de(ODR_DECODE); Z_SRW_PDU *sru_pdu_req = 0; mp::odr odr_en(ODR_ENCODE); - //Z_SRW_PDU *sru_pdu_res = 0; Z_SRW_PDU *sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response); + // determine database with the HTTP header information only + mp_util::SRUServerInfo sruinfo = mp_util::get_sru_server_info(package); + std::map::iterator idbexp; + idbexp = m_database_explain.find(sruinfo.database); + + // assign explain config XML DOM node if database is known + const xmlNode *explainnode = 0; + if (idbexp != m_database_explain.end()){ + explainnode = idbexp->second; + } + // just moving package if database is not known + else { + package.move(); + return; + } + + + // decode SRU request Z_SOAP *soap = 0; char *charset = 0; char *stylesheet = 0; - if (! (sru_pdu_req = decode_sru_request(package, odr_de, odr_en, - sru_pdu_res, soap, + // filter acts as sink for non-valid SRU requests + if (! (sru_pdu_req = mp_util::decode_sru_request(package, odr_de, odr_en, + sru_pdu_res, &soap, charset, stylesheet))) { - build_sru_response(package, odr_en, soap, - sru_pdu_res, charset, stylesheet); - package.session().close(); + if (soap) + { + mp_util::build_sru_explain(package, odr_en, sru_pdu_res, + sruinfo, explainnode); + mp_util::build_sru_response(package, odr_en, soap, + sru_pdu_res, charset, stylesheet); + } + else + { + metaproxy_1::odr odr; + Z_GDU *zgdu_res = + odr.create_HTTP_Response(package.session(), + zgdu_req->u.HTTP_Request, 400); + package.response() = zgdu_res; + } return; } - - // SRU request package translation to Z3950 package - if (sru_pdu_req) - std::cout << *sru_pdu_req << "\n"; - else - std::cout << "SRU empty\n"; - - - // explain + // filter acts as sink for SRU explain requests if (sru_pdu_req && sru_pdu_req->which == Z_SRW_explain_request) { Z_SRW_explainRequest *er_req = sru_pdu_req->u.explain_request; - //sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response); - - build_simple_explain(package, odr_en, sru_pdu_res, er_req); + //mp_util::build_simple_explain(package, odr_en, sru_pdu_res, + // sruinfo, er_req); + mp_util::build_sru_explain(package, odr_en, sru_pdu_res, + sruinfo, explainnode, er_req); } - - // searchRetrieve else if (sru_pdu_req && sru_pdu_req->which == Z_SRW_searchRetrieve_request && sru_pdu_req->u.request) - { + { // searchRetrieve Z_SRW_searchRetrieveRequest *sr_req = sru_pdu_req->u.request; sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_searchRetrieve_response); // checking that we have a query - ok = check_sru_query_exists(package, odr_en, sru_pdu_res, sr_req); + ok = mp_util::check_sru_query_exists(package, odr_en, + sru_pdu_res, sr_req); - if (ok && z3950_init_request(package)) + if (ok && z3950_init_request(package, odr_en, sru_pdu_res)) { { ok = z3950_search_request(package, odr_en, @@ -214,7 +248,14 @@ void yf::SRUtoZ3950::Rep::process(mp::Package &package) const sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_scan_response); - if (z3950_init_request(package)) + // we do not do scan at the moment, therefore issuing a diagnostic + yaz_add_srw_diagnostic(odr_en, + &(sru_pdu_res->u.scan_response->diagnostics), + &(sru_pdu_res->u.scan_response->num_diagnostics), + 4, "scan"); + + // to be used when we do scan + if (false && z3950_init_request(package, odr_en, sru_pdu_res)) { z3950_scan_request(package, odr_en, sru_pdu_res, sr_req); z3950_close_request(package); @@ -222,272 +263,31 @@ void yf::SRUtoZ3950::Rep::process(mp::Package &package) const } else { - std::cout << "SRU OPERATION NOT SUPPORTED \n"; + //std::cout << "SRU OPERATION NOT SUPPORTED \n"; sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response); // TODO: make nice diagnostic return package - package.session().close(); return; } - //build_sru_debug_package(package); - build_sru_response(package, odr_en, soap, - sru_pdu_res, charset, stylesheet); - return; - - - - - - - -} - - -bool yf::SRUtoZ3950::Rep::build_simple_explain(mp::Package &package, - mp::odr &odr_en, - Z_SRW_PDU *sru_pdu_res, - Z_SRW_explainRequest - const *er_req) const -{ - - // z3950'fy recordPacking - int record_packing = Z_SRW_recordPacking_XML; - if (er_req->recordPacking && 's' == *(er_req->recordPacking)) - record_packing = Z_SRW_recordPacking_string; - - // getting database info - std::string database("Default"); - if (er_req->database) - database = er_req->database; - - // building SRU explain record - std::string explain_xml - = mp_util::to_string( - "\n" - " \n" - " ") - + package.origin().server_host() - + mp_util::to_string("\n" - " ") - + mp_util::to_string(package.origin().server_port()) - + mp_util::to_string("\n" - " ") - + database - + mp_util::to_string("\n" - " \n" - "\n"); - - - // preparing explain record insert - Z_SRW_explainResponse *sru_res = sru_pdu_res->u.explain_response; - //sru_res->record - // = (Z_SRW_record *) odr_malloc(odr_en, sizeof(Z_SRW_record)); - - // inserting one and only explain record - - sru_res->record.recordPosition = odr_intdup(odr_en, 1); - sru_res->record.recordPacking = record_packing; - sru_res->record.recordSchema = "http://explain.z3950.org/dtd/2.0/"; - sru_res->record.recordData_len = 1 + explain_xml.size(); - sru_res->record.recordData_buf - = odr_strdupn(odr_en, (const char *)explain_xml.c_str(), - 1 + explain_xml.size()); - - return true; -}; - - -bool yf::SRUtoZ3950::Rep::build_sru_debug_package(mp::Package &package) const -{ - Z_GDU *zgdu_req = package.request().get(); - if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request) - { - Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request; - std::string content = debug_http(*http_req); - int http_code = 400; - http_response(package, content, http_code); - return true; - } - package.session().close(); - return false; -} - - -bool yf::SRUtoZ3950::Rep::build_sru_response(mp::Package &package, - mp::odr &odr_en, - Z_SOAP *soap, - const Z_SRW_PDU *sru_pdu_res, - char *charset, - const char *stylesheet) - const -{ - - // SRU request package translation to Z3950 package - if (sru_pdu_res) - std::cout << *(const_cast(sru_pdu_res)) << "\n"; - else - std::cout << "SRU empty\n"; - - - Z_GDU *zgdu_req = package.request().get(); - if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request) - { - Z_GDU *zgdu_res //= z_get_HTTP_Response(odr_en, 200); - = odr_en.create_HTTP_Response(package.session(), - zgdu_req->u.HTTP_Request, - 200); - - // adding HTTP response code and headers - Z_HTTP_Response * http_res = zgdu_res->u.HTTP_Response; - //http_res->code = http_code; - - std::string ctype("text/xml"); - if (charset){ - ctype += "; charset="; - ctype += charset; - } - - z_HTTP_header_add(odr_en, - &http_res->headers, "Content-Type", ctype.c_str()); - - // packaging Z_SOAP into HTML response - static Z_SOAP_Handler soap_handlers[4] = { - {"http://www.loc.gov/zing/srw/", 0, - (Z_SOAP_fun) yaz_srw_codec}, - {"http://www.loc.gov/zing/srw/v1.0/", 0, - (Z_SOAP_fun) yaz_srw_codec}, - {"http://www.loc.gov/zing/srw/update/", 0, - (Z_SOAP_fun) yaz_ucp_codec}, - {0, 0, 0} - }; - - - // empty stylesheet means NO stylesheet - if (stylesheet && *stylesheet == '\0') - stylesheet = 0; - - // encoding SRU package - - soap->u.generic->p = (void*) sru_pdu_res; - //int ret = - z_soap_codec_enc_xsl(odr_en, &soap, - &http_res->content_buf, &http_res->content_len, - soap_handlers, charset, stylesheet); - - - package.response() = zgdu_res; - return true; - } - package.session().close(); - return false; -} - - - - Z_SRW_PDU * yf::SRUtoZ3950::Rep::decode_sru_request(mp::Package &package, - mp::odr &odr_de, - mp::odr &odr_en, - Z_SRW_PDU *sru_pdu_res, - Z_SOAP *&soap, - char *charset, - char *stylesheet) - const -{ - Z_GDU *zgdu_req = package.request().get(); - Z_SRW_PDU *sru_pdu_req = 0; - - assert((zgdu_req->which == Z_GDU_HTTP_Request)); - - //ignoring all non HTTP_Request packages - //if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){ - // return 0; - //} - - Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request; - if (! http_req) - return 0; - - //Z_SRW_PDU *sru_pdu_res_exp = yaz_srw_get(odr_en, Z_SRW_explain_response); - - if (0 == yaz_sru_decode(http_req, &sru_pdu_req, &soap, - odr_de, &charset, - &(sru_pdu_res->u.response->diagnostics), - &(sru_pdu_res->u.response->num_diagnostics))) - { - if (sru_pdu_res->u.response->num_diagnostics) - { - //sru_pdu_res = sru_pdu_res_exp; - package.session().close(); - return 0; - } - return sru_pdu_req; - } - else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, &soap, - odr_de, &charset)) - return sru_pdu_req; - else - { - //sru_pdu_res = sru_pdu_res_exp; - package.session().close(); - return 0; - } - return 0; + // build and send SRU response + mp_util::build_sru_response(package, odr_en, soap, + sru_pdu_res, charset, stylesheet); } -bool -yf::SRUtoZ3950::Rep::check_sru_query_exists(mp::Package &package, - mp::odr &odr_en, - Z_SRW_PDU *sru_pdu_res, - Z_SRW_searchRetrieveRequest - const *sr_req) - const -{ - if( (sr_req->query_type == Z_SRW_query_type_cql && !sr_req->query.cql) ) - { - yaz_add_srw_diagnostic(odr_en, - &(sru_pdu_res->u.response->diagnostics), - &(sru_pdu_res->u.response->num_diagnostics), - 7, "query"); - yaz_add_srw_diagnostic(odr_en, - &(sru_pdu_res->u.response->diagnostics), - &(sru_pdu_res->u.response->num_diagnostics), - 10, "CQL query is empty"); - return false; - } - if( (sr_req->query_type == Z_SRW_query_type_xcql && !sr_req->query.xcql) ) - { - yaz_add_srw_diagnostic(odr_en, - &(sru_pdu_res->u.response->diagnostics), - &(sru_pdu_res->u.response->num_diagnostics), - 10, "XCQL query is empty"); - return false; - } - if( (sr_req->query_type == Z_SRW_query_type_pqf && !sr_req->query.pqf) ) - { - yaz_add_srw_diagnostic(odr_en, - &(sru_pdu_res->u.response->diagnostics), - &(sru_pdu_res->u.response->num_diagnostics), - 10, "PQF query is empty"); - return false; - } - return true; -}; - bool -yf::SRUtoZ3950::Rep::z3950_init_request(mp::Package &package, - const std::string &database) const +yf::SRUtoZ3950::Impl::z3950_init_request(mp::Package &package, + mp::odr &odr_en, + Z_SRW_PDU *sru_pdu_res, + const std::string &database) const { // prepare Z3950 package - //Session s; - //Package z3950_package(s, package.origin()); Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); // set initRequest APDU - mp::odr odr_en(ODR_ENCODE); Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_initRequest); Z_InitRequest *init_req = apdu->u.initRequest; //TODO: add user name in apdu @@ -509,12 +309,14 @@ yf::SRUtoZ3950::Rep::z3950_init_request(mp::Package &package, z3950_package.request() = apdu; // send Z3950 package - // std::cout << "z3950_init_request " << *apdu <<"\n"; z3950_package.move(); // dead Z3950 backend detection if (z3950_package.session().is_closed()){ - package.session().close(); + yaz_add_srw_diagnostic(odr_en, + &(sru_pdu_res->u.response->diagnostics), + &(sru_pdu_res->u.response->num_diagnostics), + 2, 0); return false; } @@ -522,18 +324,20 @@ yf::SRUtoZ3950::Rep::z3950_init_request(mp::Package &package, Z_GDU *z3950_gdu = z3950_package.response().get(); if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 - && z3950_gdu->u.z3950->which == Z_APDU_initResponse) + && z3950_gdu->u.z3950->which == Z_APDU_initResponse + && *z3950_gdu->u.z3950->u.initResponse->result) return true; + yaz_add_srw_diagnostic(odr_en, + &(sru_pdu_res->u.response->diagnostics), + &(sru_pdu_res->u.response->num_diagnostics), + 2, 0); return false; } bool -yf::SRUtoZ3950::Rep::z3950_close_request(mp::Package &package) const +yf::SRUtoZ3950::Impl::z3950_close_request(mp::Package &package) const { - // close SRU package - package.session().close(); - // prepare and close Z3950 package Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); @@ -558,13 +362,15 @@ yf::SRUtoZ3950::Rep::z3950_close_request(mp::Package &package) const return false; } -bool -yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package, - mp::odr &odr_en, - Z_SRW_PDU *sru_pdu_res, - Z_SRW_searchRetrieveRequest - const *sr_req) const +bool yf::SRUtoZ3950::Impl::z3950_search_request(mp::Package &package, + mp::odr &odr_en, + Z_SRW_PDU *sru_pdu_res, + Z_SRW_searchRetrieveRequest + const *sr_req) const { + + assert(sru_pdu_res->u.response); + Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); @@ -593,59 +399,70 @@ yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package, (const SRW_query&)sr_req->query, sr_req->query_type)) { - //send_to_srw_client_error(7, "query"); + yaz_add_srw_diagnostic(odr_en, + &(sru_pdu_res->u.response->diagnostics), + &(sru_pdu_res->u.response->num_diagnostics), + 7, "query"); return false; } z3950_package.request() = apdu; - //std::cout << "z3950_search_request " << *apdu << "\n"; + // send Z39.50 package off to backend z3950_package.move(); Z_GDU *z3950_gdu = z3950_package.response().get(); - //std::cout << "z3950_search_request " << *z3950_gdu << "\n"; //TODO: check success condition - //int yaz_diag_bib1_to_srw (int bib1_code); //int yaz_diag_srw_to_bib1(int srw_code); //Se kode i src/seshigh.c (srw_bend_search, srw_bend_init). - if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 - && z3950_gdu->u.z3950->which == Z_APDU_searchResponse - && z3950_gdu->u.z3950->u.searchResponse->searchStatus) + if (!z3950_gdu || z3950_gdu->which != Z_GDU_Z3950 + || z3950_gdu->u.z3950->which != Z_APDU_searchResponse + || !z3950_gdu->u.z3950->u.searchResponse + || !z3950_gdu->u.z3950->u.searchResponse->searchStatus) { + yaz_add_srw_diagnostic(odr_en, + &(sru_pdu_res->u.response->diagnostics), + &(sru_pdu_res->u.response->num_diagnostics), + 2, 0); + return false; + } + + // everything fine, continuing + Z_SearchResponse *sr = z3950_gdu->u.z3950->u.searchResponse; - Z_SearchResponse *sr = z3950_gdu->u.z3950->u.searchResponse; - if (sr) - { - // srw'fy number of records - sru_pdu_res->u.response->numberOfRecords - = (int *) odr_malloc(odr_en, sizeof(int *)); - *(sru_pdu_res->u.response->numberOfRecords) = *(sr->resultCount); - - // srw'fy nextRecordPosition - //sru_pdu_res->u.response->nextRecordPosition - // = (int *) odr_malloc(odr_en, sizeof(int *)); - //*(sru_pdu_res->u.response->nextRecordPosition) = 1; - - } - - return true; + // checking non surrogate diagnostics in Z3950 search response package + if (!z3950_to_srw_diagnostics_ok(odr_en, sru_pdu_res->u.response, + sr->records)) + { + return false; } + + // Finally, roll on and srw'fy number of records + sru_pdu_res->u.response->numberOfRecords + = (int *) odr_malloc(odr_en, sizeof(int *)); + *(sru_pdu_res->u.response->numberOfRecords) = *(sr->resultCount); - return false; + // srw'fy nextRecordPosition + //sru_pdu_res->u.response->nextRecordPosition + // = (int *) odr_malloc(odr_en, sizeof(int *)); + //*(sru_pdu_res->u.response->nextRecordPosition) = 1; + + return true; } bool -yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, +yf::SRUtoZ3950::Impl::z3950_present_request(mp::Package &package, mp::odr &odr_en, Z_SRW_PDU *sru_pdu_res, Z_SRW_searchRetrieveRequest const *sr_req) const { + assert(sru_pdu_res->u.response); if (!sr_req) return false; @@ -655,13 +472,6 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, if (!(sr_req->maximumRecords) || 0 == *(sr_req->maximumRecords)) return true; - // creating Z3950 package - Package z3950_package(package.session(), package.origin()); - z3950_package.copy_filter(package); - Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_presentRequest); - - assert(apdu->u.presentRequest); - bool send_z3950_present = true; // recordXPath unsupported. @@ -695,12 +505,16 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, 80, 0); } - // start record requested larger than number of records + // start record requested negative, or larger than number of records if (sr_req->startRecord - && sru_pdu_res->u.response->numberOfRecords - && *(sr_req->startRecord) > *(sru_pdu_res->u.response->numberOfRecords)) + && + ((*(sr_req->startRecord) < 0) // negative + || + (sru_pdu_res->u.response->numberOfRecords //out of range + && *(sr_req->startRecord) + > *(sru_pdu_res->u.response->numberOfRecords)) + )) { - // = *(sr_req->startRecord); send_z3950_present = false; yaz_add_srw_diagnostic(odr_en, &(sru_pdu_res->u.response->diagnostics), @@ -708,11 +522,28 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, 61, 0); } + // maximumRecords requested negative + if (sr_req->maximumRecords + && *(sr_req->maximumRecords) < 0) + + { + send_z3950_present = false; + yaz_add_srw_diagnostic(odr_en, + &(sru_pdu_res->u.response->diagnostics), + &(sru_pdu_res->u.response->num_diagnostics), + 6, "maximumRecords"); + } + // exit on all these above diagnostics if (!send_z3950_present) return false; // now packaging the z3950 present request + Package z3950_package(package.session(), package.origin()); + z3950_package.copy_filter(package); + Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_presentRequest); + + assert(apdu->u.presentRequest); // z3950'fy start record position if (sr_req->startRecord) @@ -722,9 +553,13 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, *(apdu->u.presentRequest->resultSetStartPoint) = 1; // z3950'fy number of records requested + // protect against requesting records out of range if (sr_req->maximumRecords) *(apdu->u.presentRequest->numberOfRecordsRequested) - = *(sr_req->maximumRecords); + = std::min(*(sr_req->maximumRecords), + *(sru_pdu_res->u.response->numberOfRecords) + - *(apdu->u.presentRequest->resultSetStartPoint) + + 1); // z3950'fy recordPacking int record_packing = Z_SRW_recordPacking_XML; @@ -732,18 +567,20 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, record_packing = Z_SRW_recordPacking_string; // RecordSyntax will always be XML - (apdu->u.presentRequest->preferredRecordSyntax) - = yaz_oidval_to_z3950oid (odr_en, CLASS_RECSYN, VAL_TEXT_XML); + apdu->u.presentRequest->preferredRecordSyntax + = odr_oiddup(odr_en, yaz_oid_recsyn_xml); // z3950'fy record schema if (sr_req->recordSchema) { apdu->u.presentRequest->recordComposition - = (Z_RecordComposition *) odr_malloc(odr_en, sizeof(Z_RecordComposition)); + = (Z_RecordComposition *) + odr_malloc(odr_en, sizeof(Z_RecordComposition)); apdu->u.presentRequest->recordComposition->which = Z_RecordComp_simple; apdu->u.presentRequest->recordComposition->u.simple - = build_esn_from_schema(odr_en, (const char *) sr_req->recordSchema); + = mp_util::build_esn_from_schema(odr_en, + (const char *) sr_req->recordSchema); } // z3950'fy time to live - flagged as diagnostics above @@ -752,7 +589,7 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, // attaching Z3950 package to filter chain z3950_package.request() = apdu; - //std::cout << "z3950_present_request " << *apdu << "\n"; + // sending Z30.50 present request z3950_package.move(); //check successful Z3950 present response @@ -766,26 +603,22 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, &(sru_pdu_res->u.response->diagnostics), &(sru_pdu_res->u.response->num_diagnostics), 2, 0); - package.session().close(); return false; } - + // everything fine, continuing - //std::cout << "z3950_present_request OK\n"; Z_PresentResponse *pr = z3950_gdu->u.z3950->u.presentResponse; Z_SRW_searchRetrieveResponse *sru_res = sru_pdu_res->u.response; - // checking non surrogate dioagnostics in Z3950 present response package - if (pr->records - && pr->records->which == Z_Records_NSD - && pr->records->u.nonSurrogateDiagnostic) - { - //int http_code = - z3950_to_srw_diag(odr_en, sru_res, pr->records->u.nonSurrogateDiagnostic); + + // checking non surrogate diagnostics in Z3950 present response package + if (!z3950_to_srw_diagnostics_ok(odr_en, sru_pdu_res->u.response, + pr->records)) return false; - } + + // copy all records if existing if (pr->records && pr->records->which == Z_Records_DBOSD) @@ -796,13 +629,19 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, sru_res->records = (Z_SRW_record *) odr_malloc(odr_en, - sru_res->num_records *sizeof(Z_SRW_record)); + sru_res->num_records + * sizeof(Z_SRW_record)); + // srw'fy nextRecordPosition - if (pr->nextResultSetPosition) + // next position never zero or behind the last z3950 record + if (pr->nextResultSetPosition + && *(pr->nextResultSetPosition) > 0 + && *(pr->nextResultSetPosition) + <= *(sru_pdu_res->u.response->numberOfRecords)) sru_res->nextRecordPosition = odr_intdup(odr_en, *(pr->nextResultSetPosition)); - + // inserting all records for (int i = 0; i < sru_res->num_records; i++) { @@ -810,7 +649,8 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, = pr->records->u.databaseOrSurDiagnostics->records[i]; sru_res->records[i].recordPosition - = odr_intdup(odr_en, i + *(apdu->u.presentRequest->resultSetStartPoint)); + = odr_intdup(odr_en, + i + *(apdu->u.presentRequest->resultSetStartPoint)); sru_res->records[i].recordPacking = record_packing; @@ -823,9 +663,8 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, else { Z_External *r = npr->u.databaseRecord; - oident *ent = oid_getentbyoid(r->direct_reference); - if (r->which == Z_External_octet - && ent->value == VAL_TEXT_XML) + if (r->direct_reference + && !oid_oidcmp(r->direct_reference, yaz_oid_recsyn_xml)) { sru_res->records[i].recordSchema = "dc"; sru_res->records[i].recordData_buf @@ -849,11 +688,13 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, } bool -yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package, +yf::SRUtoZ3950::Impl::z3950_scan_request(mp::Package &package, mp::odr &odr_en, Z_SRW_PDU *sru_pdu_res, Z_SRW_scanRequest const *sr_req) const { + assert(sru_pdu_res->u.scan_response); + Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); //mp::odr odr_en(ODR_ENCODE); @@ -910,7 +751,7 @@ yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package, return false; } -bool yf::SRUtoZ3950::Rep::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, +bool yf::SRUtoZ3950::Impl::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, const SRW_query &query, SRW_query_type query_type) const { @@ -953,120 +794,36 @@ bool yf::SRUtoZ3950::Rep::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, } -std::string -yf::SRUtoZ3950::Rep::sru_protocol(const Z_HTTP_Request &http_req) const -{ - const std::string mime_urlencoded("application/x-www-form-urlencoded"); - const std::string mime_text_xml("text/xml"); - const std::string mime_soap_xml("application/soap+xml"); - - const std::string http_method(http_req.method); - const std::string http_type - = mp_util::http_header_value(http_req.headers, "Content-Type"); - - if (http_method == "GET") - return "SRU GET"; - - if (http_method == "POST" - && http_type == mime_urlencoded) - return "SRU POST"; - - if ( http_method == "POST" - && (http_type == mime_text_xml - || http_type == mime_soap_xml)) - return "SRU SOAP"; - - return "HTTP"; -} - -std::string -yf::SRUtoZ3950::Rep::debug_http(const Z_HTTP_Request &http_req) const +bool +yf::SRUtoZ3950::Impl::z3950_to_srw_diagnostics_ok(mp::odr &odr_en, + Z_SRW_searchRetrieveResponse + *sru_res, + Z_Records *records) const { - std::string message("\n\n

" - "Metaproxy SRUtoZ3950 filter" - "

\n"); - - message += "

HTTP Info


\n"; - message += "

\n"; - message += "Method: " + std::string(http_req.method) + "
\n"; - message += "Version: " + std::string(http_req.version) + "
\n"; - message += "Path: " + std::string(http_req.path) + "
\n"; - - message += "Content-Type:" - + mp_util::http_header_value(http_req.headers, "Content-Type") - + "
\n"; - message += "Content-Length:" - + mp_util::http_header_value(http_req.headers, "Content-Length") - + "
\n"; - message += "

\n"; - - message += "

Headers


\n"; - message += "

\n"; - Z_HTTP_Header* header = http_req.headers; - while (header){ - message += "Header: " - + std::string(header->name) + ": " - + std::string(header->value) + "
\n"; - header = header->next; + // checking non surrogate diagnostics in Z3950 present response package + if (records + && records->which == Z_Records_NSD + && records->u.nonSurrogateDiagnostic) + { + z3950_to_srw_diag(odr_en, sru_res, + records->u.nonSurrogateDiagnostic); + return false; } - message += "

\n"; - message += "\n\n"; - return message; -} - -void yf::SRUtoZ3950::Rep::http_response(metaproxy_1::Package &package, - const std::string &content, - int http_code) const -{ - - Z_GDU *zgdu_req = package.request().get(); - Z_GDU *zgdu_res = 0; - mp::odr odr; - zgdu_res - = odr.create_HTTP_Response(package.session(), - zgdu_req->u.HTTP_Request, - http_code); - - zgdu_res->u.HTTP_Response->content_len = content.size(); - zgdu_res->u.HTTP_Response->content_buf - = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len); - - strncpy(zgdu_res->u.HTTP_Response->content_buf, - content.c_str(), zgdu_res->u.HTTP_Response->content_len); - - //z_HTTP_header_add(odr, &hres->headers, - // "Content-Type", content_type.c_str()); - package.response() = zgdu_res; + return true; } -Z_ElementSetNames * -yf::SRUtoZ3950::Rep::build_esn_from_schema(mp::odr &odr_en, - const char *schema) const -{ - if (!schema) - return 0; - - Z_ElementSetNames *esn - = (Z_ElementSetNames *) odr_malloc(odr_en, sizeof(Z_ElementSetNames)); - esn->which = Z_ElementSetNames_generic; - esn->u.generic = odr_strdup(odr_en, schema); - return esn; -} - int -yf::SRUtoZ3950::Rep::z3950_to_srw_diag(mp::odr &odr_en, +yf::SRUtoZ3950::Impl::z3950_to_srw_diag(mp::odr &odr_en, Z_SRW_searchRetrieveResponse *sru_res, Z_DefaultDiagFormat *ddf) const { int bib1_code = *ddf->condition; - if (bib1_code == 109) - return 404; sru_res->num_diagnostics = 1; sru_res->diagnostics = (Z_SRW_diagnostic *) odr_malloc(odr_en, sizeof(*sru_res->diagnostics)); yaz_mk_std_diagnostic(odr_en, sru_res->diagnostics, - yaz_diag_bib1_to_srw(*ddf->condition), + yaz_diag_bib1_to_srw(bib1_code), ddf->u.v2Addinfo); return 0; } @@ -1081,7 +838,7 @@ static mp::filter::Base* filter_creator() extern "C" { struct metaproxy_1_filter_struct metaproxy_1_filter_sru_to_z3950 = { 0, - "SRUtoZ3950", + "sru_z3950", filter_creator }; }