From ef427d6fec231e98a5babda2436dad7968df7b46 Mon Sep 17 00:00:00 2001 From: Marc Cromme Date: Tue, 19 Sep 2006 13:50:17 +0000 Subject: [PATCH] parsing of SRW request packages, and sending of Z3950 init, search and present almost finished. Missing parsing of Z3950 packages and building of SRW response packages. --- src/filter_sru_to_z3950.cpp | 380 ++++++++++++++++++++++++++++++------------- src/gduutil.cpp | 138 +++++++++++++++- src/gduutil.hpp | 4 +- 3 files changed, 407 insertions(+), 115 deletions(-) diff --git a/src/filter_sru_to_z3950.cpp b/src/filter_sru_to_z3950.cpp index feec50e..d3f2bdb 100644 --- a/src/filter_sru_to_z3950.cpp +++ b/src/filter_sru_to_z3950.cpp @@ -1,4 +1,4 @@ -/* $Id: filter_sru_to_z3950.cpp,v 1.7 2006-09-15 14:18:25 marc Exp $ +/* $Id: filter_sru_to_z3950.cpp,v 1.8 2006-09-19 13:50:17 marc Exp $ Copyright (c) 2005-2006, Index Data. See the LICENSE file for details @@ -12,6 +12,7 @@ #include "filter_sru_to_z3950.hpp" #include +#include #include #include @@ -60,6 +61,9 @@ namespace metaproxy_1 { namespace filter { class SRUtoZ3950::Rep { //friend class SRUtoZ3950; + 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; @@ -70,20 +74,35 @@ namespace metaproxy_1 { const std::string &content, int http_code = 200) const; bool build_sru_debug_package(mp::Package &package) const; + Z_SRW_PDU * decode_sru_request(mp::Package &package, + mp::odr &odr_de) const; bool z3950_build_query(mp::odr &odr_en, Z_Query *z_query, - const std::string &query, - int query_type) const; + 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, unsigned int &hits, - const std::string &database, - const std::string &query, - int query_type) const; - bool z3950_present_request(mp::Package &package) const; - bool z3950_scan_request(mp::Package &package) const; + Z_SRW_searchRetrieveRequest + const *sr_req) const; + //const std::string &database, + //const std::string &query, + //int query_type) const; + bool z3950_present_request(mp::Package &package, + unsigned int &records_returned, + unsigned int &next_position, + Z_SRW_searchRetrieveRequest + const *sr_req) const; + //unsigned int start_position, + //unsigned int records_requested) const; + bool z3950_scan_request(mp::Package &package, + Z_SRW_scanRequest + const *sr_req) const; + //const std::string &database, + //const std::string &query, + //int query_type) const; }; } } @@ -124,107 +143,92 @@ void yf::SRUtoZ3950::Rep::process(mp::Package &package) const // TODO: Z3950 response parsing and translation to SRU package - Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request; - bool ok; - unsigned int search_hits = 0; - - if (z3950_init_request(package)) - { - ok = z3950_search_request(package, search_hits, "Default", - "dc.title=bacillus", Z_SRW_query_type_cql); - if (ok && search_hits) - ok = z3950_present_request(package); - //z3950_scan_request(package,"Default", - // "dc:title=bacillus", Z_SRW_query_type_cql); - z3950_close_request(package); - } - - build_sru_debug_package(package); - return; - - - - - - - + bool ok; - // SRU request package checking - - - //Z_GDU *zgdu_res = 0; Z_SRW_PDU *sru_pdu_req = 0; - //Z_SRW_PDU *sru_pdu_res = 0; - //Z_APDU *z3950_apdu_req = 0; - //Z_APDU *z3950_apdu_res = 0; - + mp::odr odr_de(ODR_DECODE); + mp::odr odr_en(ODR_ENCODE); - Z_SOAP *soap_req = 0; - char *charset = 0; - Z_SRW_diagnostic *diag = 0; - int num_diags = 0; - //mp::odr odr_de(ODR_DECODE); - - if (0 == yaz_sru_decode(http_req, &sru_pdu_req, &soap_req, - odr(ODR_DECODE), &charset, &diag, &num_diags)) - { - std::cout << "SRU GET/POST \n"; - } - else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, &soap_req, - odr(ODR_DECODE), &charset)) - { - std::cout << "SRU SOAP \n"; - } - else - { - std::cout << "SRU DECODING ERROR - SHOULD NEVER HAPPEN\n"; - package.session().close(); - return; - } - if (num_diags) + if (! (sru_pdu_req = decode_sru_request(package, odr_de))) { - std::cout << "SRU DIAGNOSTICS " << num_diags << "\n"; - // TODO: make nice diagnostic return package - //Z_SRW_PDU *srw_pdu_res = - // yaz_srw_get(odr(ODR_ENCODE), - // Z_SRW_searchRetrieve_response); - // Z_SRW_searchRetrieveResponse *srw_res = srw_pdu_res->u.response; - - // srw_res->diagnostics = diagnostic; - // srw_res->num_diagnostics = num_diagnostic; - // send_srw_response(srw_pdu_res); - // return; - - // package.session().close(); + std::cout << "TODO: correct error when SRW package could not be" + " parsed\n"; return; } - + // SRU request package translation to Z3950 package + if (sru_pdu_req) + std::cout << *sru_pdu_req << "\n"; + else + std::cout << "SRU empty\n"; + // searchRetrieve if (sru_pdu_req && sru_pdu_req->which == Z_SRW_searchRetrieve_request) { - //Z_SRW_searchRetrieveRequest *srw_req = sru_pdu_req->u.request; + Z_SRW_searchRetrieveRequest *sr_req = sru_pdu_req->u.request; + + // TODO: checking of unsupported operations and proper diagnostic setup // recordXPath unsupported. - //if (srw_req->recordXPath) + //if (sr_req->recordXPath) // yaz_add_srw_diagnostic(odr_decode(), // &diag, &num_diags, 72, 0); // sort unsupported - // if (srw_req->sort_type != Z_SRW_sort_type_none) + // if (sr_req->sort_type != Z_SRW_sort_type_none) // yaz_add_srw_diagnostic(odr_decode(), // &diag, &num_diags, 80, 0); + + + if (z3950_init_request(package)) + { + unsigned int search_hits = 0; + unsigned int records_returned = 0; + unsigned int next_position = 0; + { + ok = z3950_search_request(package, search_hits, sr_req); + //"Default", + //"dc.title=bacillus", + //Z_SRW_query_type_cql); + if (ok && search_hits) + ok = z3950_present_request(package, + records_returned, + next_position, + sr_req); + z3950_close_request(package); + } + } + } + + // scan + else if (sru_pdu_req && sru_pdu_req->which == Z_SRW_scan_request) + { + Z_SRW_scanRequest *sr_req = sru_pdu_req->u.scan_request; + if (z3950_init_request(package)) + { + z3950_scan_request(package, sr_req); + z3950_close_request(package); + } } else { std::cout << "SRU OPERATION NOT SUPPORTED \n"; // TODO: make nice diagnostic return package - // package.session().close(); + package.session().close(); return; } + build_sru_debug_package(package); + return; + + + + + + + } bool yf::SRUtoZ3950::Rep::build_sru_debug_package(mp::Package &package) const @@ -242,6 +246,60 @@ bool yf::SRUtoZ3950::Rep::build_sru_debug_package(mp::Package &package) const } + Z_SRW_PDU * yf::SRUtoZ3950::Rep::decode_sru_request(mp::Package &package, + mp::odr &odr_de) const +{ + Z_GDU *zgdu_req = package.request().get(); + Z_SRW_PDU *sru_pdu_req = 0; + + // 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_SOAP *soap_req = 0; + char *charset = 0; + Z_SRW_diagnostic *diag = 0; + int num_diags = 0; + + if (0 == yaz_sru_decode(http_req, &sru_pdu_req, &soap_req, + odr_de, &charset, &diag, &num_diags)) + { + if (num_diags) + { + std::cout << "SRU DIAGNOSTICS " << num_diags << "\n"; + // TODO: make nice diagnostic return package + //Z_SRW_PDU *srw_pdu_res = + // yaz_srw_get(odr(ODR_ENCODE), + // Z_SRW_searchRetrieve_response); + // Z_SRW_searchRetrieveResponse *srw_res = srw_pdu_res->u.response; + + // srw_res->diagnostics = diagnostic; + // srw_res->num_diagnostics = num_diagnostic; + // send_srw_response(srw_pdu_res); + // return; + + // package.session().close(); + return 0; + } + return sru_pdu_req; + } + else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, &soap_req, + odr_de, &charset)) + return sru_pdu_req; + else + { + //std::cout << "SRU DECODING ERROR - SHOULD NEVER HAPPEN\n"; + package.session().close(); + return 0; + } + return 0; +} + bool yf::SRUtoZ3950::Rep::z3950_init_request(mp::Package &package, const std::string &database) const @@ -325,10 +383,11 @@ yf::SRUtoZ3950::Rep::z3950_close_request(mp::Package &package) const bool yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package, unsigned int &hits, - const std::string &database, - const std::string &query, - int query_type) const + Z_SRW_searchRetrieveRequest + const *sr_req) const { + hits = 0; + Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); mp::odr odr_en(ODR_ENCODE); @@ -336,17 +395,26 @@ yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package, //TODO: add stuff in apdu Z_SearchRequest *z_searchRequest = apdu->u.searchRequest; + + // database repackaging z_searchRequest->num_databaseNames = 1; z_searchRequest->databaseNames = (char**) odr_malloc(odr_en, sizeof(char *)); - z_searchRequest->databaseNames[0] = odr_strdup(odr_en, database.c_str()); + if (sr_req->database) + z_searchRequest->databaseNames[0] + = odr_strdup(odr_en, const_cast(sr_req->database)); + else + z_searchRequest->databaseNames[0] + = odr_strdup(odr_en, "Default"); - // TODO query repackaging + + // query repackaging Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query)); z_searchRequest->query = z_query; - - if (!z3950_build_query(odr_en, z_query, query, query_type)) + if (!z3950_build_query(odr_en, z_query, + (const SRW_query&)sr_req->query, + sr_req->query_type)) { //send_to_srw_client_error(7, "query"); return false; @@ -372,13 +440,52 @@ yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package, } bool -yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package) const +yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, + unsigned int &records_returned, + unsigned int &next_position, + Z_SRW_searchRetrieveRequest + const *sr_req) +// unsigned int start_position, +// unsigned int records_requested) + const { + + if (!sr_req) + return false; + + records_returned = 0; + next_position = 1; + + // no need to work if nobody wants records seen .. + 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); mp::odr odr_en(ODR_ENCODE); Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_presentRequest); + //TODO: add stuff in apdu + assert(apdu->u.presentRequest); + + // z3950'fy start record position + if (sr_req->startRecord) + *(apdu->u.presentRequest->resultSetStartPoint) + = *(sr_req->startRecord); + else + *(apdu->u.presentRequest->resultSetStartPoint) = 1; + + // z3950'fy number of records requested + if (sr_req->maximumRecords) + *(apdu->u.presentRequest->numberOfRecordsRequested) + = *(sr_req->maximumRecords); + + // TODO: z3950'fy record schema + //if (sr_req->recordSchema) + // *(apdu->u.presentRequest->preferredRecordSyntax) + // = *(sr_req->recordSchema); + z3950_package.request() = apdu; //std::cout << "z3950_present_request " << *apdu << "\n"; @@ -388,26 +495,82 @@ yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package) const Z_GDU *z3950_gdu = z3950_package.response().get(); if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 && z3950_gdu->u.z3950->which == Z_APDU_presentResponse) - //&& z3950_gdu->u.z3950->u.presenthResponse->searchStatus) + //&& z3950_gdu->u.z3950->u.presentResponse->searchStatus) { - std::cout << "z3950_present_request OK\n"; - return true; + //std::cout << "z3950_present_request OK\n"; + records_returned = 0; + next_position = 0; + Z_PresentResponse *pr = z3950_gdu->u.z3950->u.presentResponse; + if (pr) + { + if (pr->numberOfRecordsReturned) + records_returned = *(pr->numberOfRecordsReturned); + if (pr->nextResultSetPosition) + next_position = *(pr->nextResultSetPosition); + } + return true; } return false; } bool -yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package) const +yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package, + Z_SRW_scanRequest const *sr_req) const + //const std::string &database, + //const std::string &query, + //int query_type) const { Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); mp::odr odr_en(ODR_ENCODE); Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_scanRequest); + //TODO: add stuff in apdu - z3950_package.request() = apdu; + Z_ScanRequest *z_scanRequest = apdu->u.scanRequest; + // database repackaging + z_scanRequest->num_databaseNames = 1; + z_scanRequest->databaseNames = (char**) + odr_malloc(odr_en, sizeof(char *)); + if (sr_req->database) + z_scanRequest->databaseNames[0] + = odr_strdup(odr_en, const_cast(sr_req->database)); + else + z_scanRequest->databaseNames[0] + = odr_strdup(odr_en, "Default"); + + + // query repackaging + // CQL or XCQL scan is not possible in Z3950, flagging a diagnostic + if (sr_req->query_type != Z_SRW_query_type_pqf) + { + //send_to_srw_client_error(7, "query"); + return false; + } + + // PQF query repackaging + // need to use Z_AttributesPlusTerm structure, not Z_Query + // this can be digget out of a + // Z_query->type1(Z_RPNQuery)->RPNStructure(Z_RPNStructure) + // ->u.simple(Z_Operand)->u.attributesPlusTerm(Z_AttributesPlusTerm ) + + //Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query)); + //z_searchRequest->query = z_query; + + //if (!z3950_build_query(odr_en, z_query, + // (const SRW_query&)sr_req->query, + // sr_req->query_type)) + //{ + //send_to_srw_client_error(7, "query"); + // return false; + //} + + // TODO: + + z3950_package.request() = apdu; std::cout << "z3950_scan_request " << *apdu << "\n"; + z3950_package.move(); //TODO: check success condition return true; @@ -415,8 +578,8 @@ yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package) const } bool yf::SRUtoZ3950::Rep::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, - const std::string &query, - int query_type) const + const SRW_query &query, + SRW_query_type query_type) const { if (query_type == Z_SRW_query_type_cql) { @@ -427,8 +590,7 @@ bool yf::SRUtoZ3950::Rep::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, ext->indirect_reference = 0; ext->descriptor = 0; ext->which = Z_External_CQL; - //ext->u.cql = srw_req->query.cql; - ext->u.cql = const_cast(query.c_str()); + ext->u.cql = const_cast(query.cql); z_query->which = Z_Query_type_104; z_query->u.type_104 = ext; @@ -442,24 +604,16 @@ bool yf::SRUtoZ3950::Rep::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, pqf_parser = yaz_pqf_create (); - RPNquery = yaz_pqf_parse (pqf_parser, odr_en, query.c_str()); - //srw_req->query.pqf); -// if (!RPNquery) -// { -// const char *pqf_msg; -// size_t off; -// int code = yaz_pqf_error (pqf_parser, &pqf_msg, &off); -// int ioff = off; -// yaz_log(YLOG_LOG, "%*s^\n", ioff+4, ""); -// yaz_log(YLOG_LOG, "Bad PQF: %s (code %d)\n", pqf_msg, code); - -// send_to_srw_client_error(10, 0); -// return; -// } + RPNquery = yaz_pqf_parse (pqf_parser, odr_en, query.pqf); + if (!RPNquery) + { + std::cout << "TODO: Handeling of bad PQF\n"; + std::cout << "TODO: Diagnostic to be send\n"; + } z_query->which = Z_Query_type_1; z_query->u.type_1 = RPNquery; - yaz_pqf_destroy (pqf_parser); + yaz_pqf_destroy(pqf_parser); return true; } return false; diff --git a/src/gduutil.cpp b/src/gduutil.cpp index c17d98c..7ef3f03 100644 --- a/src/gduutil.cpp +++ b/src/gduutil.cpp @@ -1,4 +1,4 @@ -/* $Id: gduutil.cpp,v 1.8 2006-09-18 10:25:00 marc Exp $ +/* $Id: gduutil.cpp,v 1.9 2006-09-19 13:50:17 marc Exp $ Copyright (c) 2005-2006, Index Data. See the LICENSE file for details @@ -539,6 +539,142 @@ std::ostream& std::operator<<(std::ostream& os, Z_APDU& zapdu) } +std::ostream& std::operator<<(std::ostream& os, Z_SRW_PDU& srw_pdu) +{ + os << "SRU"; + + switch(srw_pdu.which) { + case Z_SRW_searchRetrieve_request: + os << " " << "searchRetrieveRequest"; + { + Z_SRW_searchRetrieveRequest *sr = srw_pdu.u.request; + if (sr) + { + if (sr->database) + os << " " << (sr->database); + else + os << " -"; + if (sr->startRecord) + os << " " << *(sr->startRecord); + else + os << " -"; + if (sr->maximumRecords) + os << " " << *(sr->maximumRecords); + else + os << " -"; + if (sr->recordPacking) + os << " " << *(sr->recordPacking); + else + os << " -"; + + switch (sr->query_type){ + case Z_SRW_query_type_cql: + os << " CQL " << sr->query.cql; + break; + case Z_SRW_query_type_xcql: + os << " XCQL"; + break; + case Z_SRW_query_type_pqf: + os << " PQF " << sr->query.pqf; + break; + } + } + } + break; + case Z_SRW_searchRetrieve_response: + os << " " << "searchRetrieveResponse"; + break; + case Z_SRW_explain_request: + os << " " << "explainRequest"; + break; + case Z_SRW_explain_response: + os << " " << "explainResponse"; + break; + case Z_SRW_scan_request: + os << " " << "scanRequest"; + break; + case Z_SRW_scan_response: + os << " " << "scanResponse"; + break; + case Z_SRW_update_request: + os << " " << "updateRequest"; + break; + case Z_SRW_update_response: + os << " " << "updateResponse"; + break; + default: + os << " " << "UNKNOWN"; + } + + return os; +} + + +// { +// Z_InitRequest *ir +// = zapdu.u.initRequest; + +// Z_IdAuthentication *a = ir->idAuthentication; +// if (a && a->which == Z_IdAuthentication_idPass ) +// os << a->u.idPass->userId << " "; +// //<< ":" << a->u.idPass->groupId << " "; +// else +// os << "-" << " "; + +// std::list vhosts; +// mp::util::get_vhost_otherinfo(ir->otherInfo, vhosts); +// if (vhosts.size()){ +// copy(vhosts.begin(), vhosts.end(), +// ostream_iterator(os, " ")); +// } +// else +// os << "-" << " " ; + +// os << (ir->implementationId) << " " +// //<< ir->referenceId << " " +// << (ir->implementationName) << " " +// << (ir->implementationVersion); +// } +// break; +// case Z_APDU_initResponse: +// os << " " << "initResponse" << " "; +// { +// Z_InitResponse *ir +// = zapdu.u.initResponse; +// if (ir->result && *(ir->result)) +// os << "OK" << " " +// << (ir->implementationId) << " " +// //<< ir->referenceId << " " +// << (ir->implementationName) << " " +// << (ir->implementationVersion) << " "; +// else +// os << "DIAG"; +// } +// break; +// case Z_APDU_searchRequest: +// os << " " << "searchRequest" << " "; +// { +// Z_SearchRequest *sr +// = zapdu.u.searchRequest; + +// for (int i = 0; i < sr->num_databaseNames; i++) +// { +// os << sr->databaseNames[i]; +// if (i+1 == sr->num_databaseNames) +// os << " "; +// else +// os << "+"; +// } + +// WRBUF wr = wrbuf_alloc(); +// yaz_query_to_wrbuf(wr, sr->query); +// os << wrbuf_buf(wr); +// wrbuf_free(wr, 1); +// } +// break; + + + /* * Local variables: * c-basic-offset: 4 diff --git a/src/gduutil.hpp b/src/gduutil.hpp index d2be956..f097ca6 100644 --- a/src/gduutil.hpp +++ b/src/gduutil.hpp @@ -1,4 +1,4 @@ -/* $Id: gduutil.hpp,v 1.2 2006-08-30 14:37:11 marc Exp $ +/* $Id: gduutil.hpp,v 1.3 2006-09-19 13:50:17 marc Exp $ Copyright (c) 2005-2006, Index Data. See the LICENSE file for details @@ -9,6 +9,7 @@ #include #include +#include #include @@ -16,6 +17,7 @@ namespace std { std::ostream& operator<<(std::ostream& os, Z_GDU& zgdu); std::ostream& operator<<(std::ostream& os, Z_APDU& zapdu); + std::ostream& operator<<(std::ostream& os, Z_SRW_PDU& srw_pdu); std::ostream& operator<<(std::ostream& os, Z_HTTP_Request& httpreq); std::ostream& operator<<(std::ostream& os, Z_HTTP_Response& httpres); std::ostream& operator<<(std::ostream& os, Z_Records & rs); -- 1.7.10.4