X-Git-Url: http://lists.indexdata.com/cgi-bin?a=blobdiff_plain;f=src%2Ffilter_sru_to_z3950.cpp;h=ffc979052282b8e228a1aa028868f6943305bd20;hb=d625b10d219f5ece1aa7632e6cff2fcc5fcbd632;hp=c73d83923044222a3ce32ba41d022caafddd1947;hpb=c8f0b17ee415ed2acc7b7d59c0985c89ec92829c;p=metaproxy-moved-to-github.git diff --git a/src/filter_sru_to_z3950.cpp b/src/filter_sru_to_z3950.cpp index c73d839..ffc9790 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.23 2006-12-28 12:18:01 marc Exp $ +/* $Id: filter_sru_to_z3950.cpp,v 1.26 2007-01-08 11:10:06 marc Exp $ Copyright (c) 2005-2006, Index Data. See the LICENSE file for details - */ +*/ #include "config.hpp" #include "filter.hpp" @@ -23,6 +23,7 @@ #include #include #include +#include namespace mp = metaproxy_1; namespace mp_util = metaproxy_1::util; @@ -34,65 +35,42 @@ namespace metaproxy_1 { class SRUtoZ3950::Impl { public: void configure(const xmlNode *xmlnode); - void process(metaproxy_1::Package &package) const; + void process(metaproxy_1::Package &package); private: union SRW_query {char * cql; char * xcql; char * pqf;}; typedef const int& SRW_query_type; + 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; + 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, Z_DefaultDiagFormat *ddf) const; @@ -118,11 +96,38 @@ void yf::SRUtoZ3950::process(mp::Package &package) const m_p->process(package); } -void yf::SRUtoZ3950::Impl::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::Impl::process(mp::Package &package) const +void yf::SRUtoZ3950::Impl::process(mp::Package &package) { Z_GDU *zgdu_req = package.request().get(); @@ -134,47 +139,60 @@ void yf::SRUtoZ3950::Impl::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, + // 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_simple_explain(package, odr_en, sru_pdu_res, 0); - build_sru_response(package, odr_en, 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); package.session().close(); 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); + mp_util::build_sru_response(package, odr_en, soap, + sru_pdu_res, charset, stylesheet); + return; } // searchRetrieve @@ -187,7 +205,8 @@ void yf::SRUtoZ3950::Impl::process(mp::Package &package) const 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)) { @@ -241,274 +260,19 @@ void yf::SRUtoZ3950::Impl::process(mp::Package &package) const return; } - //build_sru_debug_package(package); - build_sru_response(package, odr_en, soap, - sru_pdu_res, charset, stylesheet); + // build and send SRU response + mp_util::build_sru_response(package, odr_en, soap, + sru_pdu_res, charset, stylesheet); return; } -bool yf::SRUtoZ3950::Impl::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 && er_req->recordPacking && 's' == *(er_req->recordPacking)) - record_packing = Z_SRW_recordPacking_string; - - // getting database info - std::string database("Default"); - if (er_req && er_req->database) - database = er_req->database; - - // getting host and port info - std::string host = package.origin().listen_host(); - std::string port = mp_util::to_string(package.origin().listen_port()); - - // overwriting host and port info if set from HTTP Host header - 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; - if (http_req) - { - std::string http_host_address - = mp_util::http_header_value(http_req->headers, "Host"); - - std::string::size_type i = http_host_address.rfind(":"); - if (i != std::string::npos) - { - host.assign(http_host_address, 0, i); - port.assign(http_host_address, i + 1, std::string::npos); - } - } - } - - // building SRU explain record - std::string explain_xml - = mp_util::to_string( - "\n" - " \n" - " ") - + host - + mp_util::to_string("\n" - " ") - + 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::Impl::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 = mp_util::http_headers_debug(*http_req); - int http_code = 400; - mp_util::http_response(package, content, http_code); - return true; - } - package.session().close(); - return false; -} - - -bool yf::SRUtoZ3950::Impl::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::Impl::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; -} - -bool -yf::SRUtoZ3950::Impl::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::Impl::z3950_init_request(mp::Package &package, - const std::string &database) const + 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); @@ -535,7 +299,6 @@ yf::SRUtoZ3950::Impl::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 @@ -630,13 +393,12 @@ yf::SRUtoZ3950::Impl::z3950_search_request(mp::Package &package, } 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 @@ -795,8 +557,8 @@ yf::SRUtoZ3950::Impl::z3950_present_request(mp::Package &package, 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 @@ -805,7 +567,7 @@ yf::SRUtoZ3950::Impl::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 @@ -825,7 +587,6 @@ yf::SRUtoZ3950::Impl::z3950_present_request(mp::Package &package, // 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; @@ -1016,106 +777,6 @@ bool yf::SRUtoZ3950::Impl::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, } -// std::string -// yf::SRUtoZ3950::Impl::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::Impl::debug_http(const Z_HTTP_Request &http_req) 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; -// } -// message += "

\n"; -// message += "\n\n"; -// return message; -// } - -// void yf::SRUtoZ3950::Impl::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; -// } - - -Z_ElementSetNames * -yf::SRUtoZ3950::Impl::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::Impl::z3950_to_srw_diag(mp::odr &odr_en,