1 /* $Id: filter_sru_to_z3950.cpp,v 1.12 2006-09-22 14:09:27 marc Exp $
2 Copyright (c) 2005-2006, Index Data.
4 See the LICENSE file for details
11 #include "gduutil.hpp"
12 #include "filter_sru_to_z3950.hpp"
15 #include <yaz/z-core.h>
17 #include <yaz/pquery.h>
19 #include <boost/thread/mutex.hpp>
26 namespace mp = metaproxy_1;
27 namespace yf = mp::filter;
33 std::string to_string(const T& t)
42 std::string http_header_value(const Z_HTTP_Header* header,
43 const std::string name)
45 while (header && header->name
46 && std::string(header->name) != name)
47 header = header->next;
49 if (header && header->name && std::string(header->name) == name
51 return std::string(header->value);
60 namespace metaproxy_1 {
62 class SRUtoZ3950::Rep {
64 union SRW_query {char * cql; char * xcql; char * pqf;};
65 typedef const int& SRW_query_type;
67 void configure(const xmlNode *xmlnode);
68 void process(metaproxy_1::Package &package) const;
70 std::string sru_protocol(const Z_HTTP_Request &http_req) const;
71 std::string debug_http(const Z_HTTP_Request &http_req) const;
72 void http_response(mp::Package &package,
73 const std::string &content,
74 int http_code = 200) const;
75 bool build_sru_debug_package(mp::Package &package) const;
76 bool build_sru_response(mp::Package &package,
79 const Z_SRW_PDU *sru_pdu_res,
81 const char *stylesheet) const;
82 Z_SRW_PDU * decode_sru_request(mp::Package &package,
85 Z_SRW_PDU *sru_pdu_res,
88 char *stylesheet) const;
89 bool check_sru_query_exists(mp::Package &package,
91 Z_SRW_PDU *sru_pdu_res,
92 Z_SRW_searchRetrieveRequest
94 bool z3950_build_query(mp::odr &odr_en, Z_Query *z_query,
95 const SRW_query &query,
96 SRW_query_type query_type) const;
97 bool z3950_init_request(mp::Package &package,
99 &database = "Default") const;
100 bool z3950_close_request(mp::Package &package) const;
101 bool z3950_search_request(mp::Package &package,
103 Z_SRW_PDU *sru_pdu_res,
104 Z_SRW_searchRetrieveRequest
105 const *sr_req) const;
106 bool z3950_present_request(mp::Package &package,
108 Z_SRW_PDU *sru_pdu_res,
109 Z_SRW_searchRetrieveRequest
110 const *sr_req) const;
111 bool z3950_scan_request(mp::Package &package,
113 Z_SRW_PDU *sru_pdu_res,
115 const *sr_req) const;
116 Z_ElementSetNames * build_esn_from_schema(mp::odr &odr_en, const char *schema) const;
117 int z3950_to_srw_diag(mp::odr &odr_en, Z_SRW_searchRetrieveResponse *srw_res,
118 Z_DefaultDiagFormat *ddf) const;
123 yf::SRUtoZ3950::SRUtoZ3950() : m_p(new Rep)
127 yf::SRUtoZ3950::~SRUtoZ3950()
128 { // must have a destructor because of boost::scoped_ptr
131 void yf::SRUtoZ3950::configure(const xmlNode *xmlnode)
133 m_p->configure(xmlnode);
136 void yf::SRUtoZ3950::process(mp::Package &package) const
138 m_p->process(package);
141 void yf::SRUtoZ3950::Rep::configure(const xmlNode *xmlnode)
145 void yf::SRUtoZ3950::Rep::process(mp::Package &package) const
147 Z_GDU *zgdu_req = package.request().get();
149 // ignoring all non HTTP_Request packages
150 if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
155 // only working on HTTP_Request packages now
158 // TODO: Z3950 response parsing and translation to SRU package
161 mp::odr odr_de(ODR_DECODE);
162 Z_SRW_PDU *sru_pdu_req = 0;
164 mp::odr odr_en(ODR_ENCODE);
165 //Z_SRW_PDU *sru_pdu_res = 0;
166 Z_SRW_PDU *sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response);
170 char *stylesheet = 0;
172 if (! (sru_pdu_req = decode_sru_request(package, odr_de, odr_en,
174 charset, stylesheet)))
176 build_sru_response(package, odr_en, soap,
177 sru_pdu_res, charset, stylesheet);
178 package.session().close();
183 // SRU request package translation to Z3950 package
185 std::cout << *sru_pdu_req << "\n";
187 std::cout << "SRU empty\n";
191 if (sru_pdu_req && sru_pdu_req->which == Z_SRW_explain_request)
193 //Z_SRW_searchRetrieveRequest *sr_req = sru_pdu_req->u.request;
194 // sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response);
195 std::cout << "TODO: implement explain response";
202 && sru_pdu_req->which == Z_SRW_searchRetrieve_request
203 && sru_pdu_req->u.request)
205 Z_SRW_searchRetrieveRequest *sr_req = sru_pdu_req->u.request;
207 sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_searchRetrieve_response);
209 // checking that we have a query
210 ok = check_sru_query_exists(package, odr_en, sru_pdu_res, sr_req);
212 if (ok && z3950_init_request(package))
215 ok = z3950_search_request(package, odr_en,
216 sru_pdu_res, sr_req);
219 && sru_pdu_res->u.response->numberOfRecords
220 && *(sru_pdu_res->u.response->numberOfRecords)
221 && sr_req->maximumRecords
222 && *(sr_req->maximumRecords))
224 ok = z3950_present_request(package, odr_en,
227 z3950_close_request(package);
234 && sru_pdu_req->which == Z_SRW_scan_request
235 && sru_pdu_req->u.scan_request)
237 Z_SRW_scanRequest *sr_req = sru_pdu_req->u.scan_request;
239 sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_scan_response);
241 if (z3950_init_request(package))
243 z3950_scan_request(package, odr_en, sru_pdu_res, sr_req);
244 z3950_close_request(package);
249 std::cout << "SRU OPERATION NOT SUPPORTED \n";
250 sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response);
252 // TODO: make nice diagnostic return package
253 package.session().close();
257 //build_sru_debug_package(package);
258 build_sru_response(package, odr_en, soap,
259 sru_pdu_res, charset, stylesheet);
270 bool yf::SRUtoZ3950::Rep::build_sru_debug_package(mp::Package &package) const
272 Z_GDU *zgdu_req = package.request().get();
273 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
275 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
276 std::string content = debug_http(*http_req);
278 http_response(package, content, http_code);
281 package.session().close();
286 bool yf::SRUtoZ3950::Rep::build_sru_response(mp::Package &package,
289 const Z_SRW_PDU *sru_pdu_res,
291 const char *stylesheet)
295 // SRU request package translation to Z3950 package
297 std::cout << *(const_cast<Z_SRW_PDU *>(sru_pdu_res)) << "\n";
299 std::cout << "SRU empty\n";
302 Z_GDU *zgdu_req = package.request().get();
303 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
305 Z_GDU *zgdu_res //= z_get_HTTP_Response(odr_en, 200);
306 = odr_en.create_HTTP_Response(package.session(),
307 zgdu_req->u.HTTP_Request,
310 // adding HTTP response code and headers
311 Z_HTTP_Response * http_res = zgdu_res->u.HTTP_Response;
312 //http_res->code = http_code;
314 std::string ctype("text/xml");
316 ctype += "; charset=";
320 z_HTTP_header_add(odr_en,
321 &http_res->headers, "Content-Type", ctype.c_str());
323 // packaging Z_SOAP into HTML response
324 static Z_SOAP_Handler soap_handlers[4] = {
325 {"http://www.loc.gov/zing/srw/", 0,
326 (Z_SOAP_fun) yaz_srw_codec},
327 {"http://www.loc.gov/zing/srw/v1.0/", 0,
328 (Z_SOAP_fun) yaz_srw_codec},
329 {"http://www.loc.gov/zing/srw/update/", 0,
330 (Z_SOAP_fun) yaz_ucp_codec},
335 // empty stylesheet means NO stylesheet
336 if (stylesheet && *stylesheet == '\0')
339 // encoding SRU package
341 soap->u.generic->p = (void*) sru_pdu_res;
343 z_soap_codec_enc_xsl(odr_en, &soap,
344 &http_res->content_buf, &http_res->content_len,
345 soap_handlers, charset, stylesheet);
348 package.response() = zgdu_res;
351 package.session().close();
357 Z_SRW_PDU * yf::SRUtoZ3950::Rep::decode_sru_request(mp::Package &package,
360 Z_SRW_PDU *sru_pdu_res,
366 Z_GDU *zgdu_req = package.request().get();
367 Z_SRW_PDU *sru_pdu_req = 0;
369 assert((zgdu_req->which == Z_GDU_HTTP_Request));
371 //ignoring all non HTTP_Request packages
372 //if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
376 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
380 //Z_SRW_PDU *sru_pdu_res_exp = yaz_srw_get(odr_en, Z_SRW_explain_response);
382 if (0 == yaz_sru_decode(http_req, &sru_pdu_req, &soap,
384 &(sru_pdu_res->u.response->diagnostics),
385 &(sru_pdu_res->u.response->num_diagnostics)))
387 if (sru_pdu_res->u.response->num_diagnostics)
389 //sru_pdu_res = sru_pdu_res_exp;
390 package.session().close();
395 else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, &soap,
400 //sru_pdu_res = sru_pdu_res_exp;
401 package.session().close();
408 yf::SRUtoZ3950::Rep::check_sru_query_exists(mp::Package &package, mp::odr &odr_en,
409 Z_SRW_PDU *sru_pdu_res,
410 Z_SRW_searchRetrieveRequest const *sr_req)
413 if( (sr_req->query_type == Z_SRW_query_type_cql && !sr_req->query.cql) )
415 yaz_add_srw_diagnostic(odr_en,
416 &(sru_pdu_res->u.response->diagnostics),
417 &(sru_pdu_res->u.response->num_diagnostics),
419 yaz_add_srw_diagnostic(odr_en,
420 &(sru_pdu_res->u.response->diagnostics),
421 &(sru_pdu_res->u.response->num_diagnostics),
422 10, "CQL query is empty");
425 if( (sr_req->query_type == Z_SRW_query_type_xcql && !sr_req->query.xcql) )
427 yaz_add_srw_diagnostic(odr_en,
428 &(sru_pdu_res->u.response->diagnostics),
429 &(sru_pdu_res->u.response->num_diagnostics),
430 10, "XCQL query is empty");
433 if( (sr_req->query_type == Z_SRW_query_type_pqf && !sr_req->query.pqf) )
435 yaz_add_srw_diagnostic(odr_en,
436 &(sru_pdu_res->u.response->diagnostics),
437 &(sru_pdu_res->u.response->num_diagnostics),
438 10, "PQF query is empty");
447 yf::SRUtoZ3950::Rep::z3950_init_request(mp::Package &package,
448 const std::string &database) const
450 // prepare Z3950 package
452 //Package z3950_package(s, package.origin());
453 Package z3950_package(package.session(), package.origin());
454 z3950_package.copy_filter(package);
456 // set initRequest APDU
457 mp::odr odr_en(ODR_ENCODE);
458 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_initRequest);
459 Z_InitRequest *init_req = apdu->u.initRequest;
460 //TODO: add user name in apdu
461 //TODO: add user passwd in apdu
462 //init_req->idAuthentication = org_init->idAuthentication;
463 //init_req->implementationId = "IDxyz";
464 //init_req->implementationName = "NAMExyz";
465 //init_req->implementationVersion = "VERSIONxyz";
467 ODR_MASK_SET(init_req->options, Z_Options_search);
468 ODR_MASK_SET(init_req->options, Z_Options_present);
469 ODR_MASK_SET(init_req->options, Z_Options_namedResultSets);
470 ODR_MASK_SET(init_req->options, Z_Options_scan);
472 ODR_MASK_SET(init_req->protocolVersion, Z_ProtocolVersion_1);
473 ODR_MASK_SET(init_req->protocolVersion, Z_ProtocolVersion_2);
474 ODR_MASK_SET(init_req->protocolVersion, Z_ProtocolVersion_3);
476 z3950_package.request() = apdu;
478 // send Z3950 package
479 // std::cout << "z3950_init_request " << *apdu <<"\n";
480 z3950_package.move();
482 // dead Z3950 backend detection
483 if (z3950_package.session().is_closed()){
484 package.session().close();
488 // check successful initResponse
489 Z_GDU *z3950_gdu = z3950_package.response().get();
491 if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950
492 && z3950_gdu->u.z3950->which == Z_APDU_initResponse)
499 yf::SRUtoZ3950::Rep::z3950_close_request(mp::Package &package) const
502 package.session().close();
504 // prepare and close Z3950 package
505 Package z3950_package(package.session(), package.origin());
506 z3950_package.copy_filter(package);
507 z3950_package.session().close();
510 //mp::odr odr_en(ODR_ENCODE);
511 //Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_close);
512 //z3950_package.request() = apdu;
514 z3950_package.move();
516 // check successful close response
517 //Z_GDU *z3950_gdu = z3950_package.response().get();
518 //if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950
519 // && z3950_gdu->u.z3950->which == Z_APDU_close)
522 if (z3950_package.session().is_closed()){
529 yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package,
531 Z_SRW_PDU *sru_pdu_res,
532 Z_SRW_searchRetrieveRequest
535 Package z3950_package(package.session(), package.origin());
536 z3950_package.copy_filter(package);
538 //add stuff in z3950 apdu
539 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_searchRequest);
540 Z_SearchRequest *z_searchRequest = apdu->u.searchRequest;
543 z_searchRequest->num_databaseNames = 1;
544 z_searchRequest->databaseNames = (char**)
545 odr_malloc(odr_en, sizeof(char *));
547 if (sr_req->database)
548 z_searchRequest->databaseNames[0]
549 = odr_strdup(odr_en, const_cast<char *>(sr_req->database));
551 z_searchRequest->databaseNames[0]
552 = odr_strdup(odr_en, "Default");
556 Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query));
557 z_searchRequest->query = z_query;
559 if (!z3950_build_query(odr_en, z_query,
560 (const SRW_query&)sr_req->query,
563 //send_to_srw_client_error(7, "query");
567 z3950_package.request() = apdu;
568 //std::cout << "z3950_search_request " << *apdu << "\n";
570 z3950_package.move();
573 Z_GDU *z3950_gdu = z3950_package.response().get();
574 //std::cout << "z3950_search_request " << *z3950_gdu << "\n";
576 //TODO: check success condition
578 //int yaz_diag_bib1_to_srw (int bib1_code);
579 //int yaz_diag_srw_to_bib1(int srw_code);
580 //Se kode i src/seshigh.c (srw_bend_search, srw_bend_init).
582 if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950
583 && z3950_gdu->u.z3950->which == Z_APDU_searchResponse
584 && z3950_gdu->u.z3950->u.searchResponse->searchStatus)
587 Z_SearchResponse *sr = z3950_gdu->u.z3950->u.searchResponse;
590 // srw'fy number of records
591 sru_pdu_res->u.response->numberOfRecords
592 = (int *) odr_malloc(odr_en, sizeof(int *));
593 *(sru_pdu_res->u.response->numberOfRecords) = *(sr->resultCount);
595 // srw'fy nextRecordPosition
596 //sru_pdu_res->u.response->nextRecordPosition
597 // = (int *) odr_malloc(odr_en, sizeof(int *));
598 //*(sru_pdu_res->u.response->nextRecordPosition) = 1;
609 yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package,
611 Z_SRW_PDU *sru_pdu_res,
612 Z_SRW_searchRetrieveRequest
621 // no need to work if nobody wants records seen ..
622 if (!(sr_req->maximumRecords) || 0 == *(sr_req->maximumRecords))
625 // creating Z3950 package
626 Package z3950_package(package.session(), package.origin());
627 z3950_package.copy_filter(package);
628 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_presentRequest);
630 assert(apdu->u.presentRequest);
632 bool send_z3950_present = true;
634 // recordXPath unsupported.
635 if (sr_req->recordXPath)
637 send_z3950_present = false;
638 yaz_add_srw_diagnostic(odr_en,
639 &(sru_pdu_res->u.response->diagnostics),
640 &(sru_pdu_res->u.response->num_diagnostics),
644 // resultSetTTL unsupported.
645 // resultSetIdleTime in response
646 if (sr_req->resultSetTTL)
648 send_z3950_present = false;
649 yaz_add_srw_diagnostic(odr_en,
650 &(sru_pdu_res->u.response->diagnostics),
651 &(sru_pdu_res->u.response->num_diagnostics),
656 if (sr_req->sort_type != Z_SRW_sort_type_none)
658 send_z3950_present = false;
659 yaz_add_srw_diagnostic(odr_en,
660 &(sru_pdu_res->u.response->diagnostics),
661 &(sru_pdu_res->u.response->num_diagnostics),
665 // start record requested larger than number of records
666 if (sr_req->startRecord
667 && sru_pdu_res->u.response->numberOfRecords
668 && *(sr_req->startRecord) > *(sru_pdu_res->u.response->numberOfRecords))
670 // = *(sr_req->startRecord);
671 send_z3950_present = false;
672 yaz_add_srw_diagnostic(odr_en,
673 &(sru_pdu_res->u.response->diagnostics),
674 &(sru_pdu_res->u.response->num_diagnostics),
678 // exit on all these above diagnostics
679 if (!send_z3950_present)
682 // now packaging the z3950 present request
684 // z3950'fy start record position
685 if (sr_req->startRecord)
686 *(apdu->u.presentRequest->resultSetStartPoint)
687 = *(sr_req->startRecord);
689 *(apdu->u.presentRequest->resultSetStartPoint) = 1;
691 // z3950'fy number of records requested
692 if (sr_req->maximumRecords)
693 *(apdu->u.presentRequest->numberOfRecordsRequested)
694 = *(sr_req->maximumRecords);
696 // z3950'fy recordPacking
697 int record_packing = Z_SRW_recordPacking_XML;
698 if (sr_req->recordPacking && 's' == *(sr_req->recordPacking))
699 record_packing = Z_SRW_recordPacking_string;
701 // RecordSyntax will always be XML
702 (apdu->u.presentRequest->preferredRecordSyntax)
703 = yaz_oidval_to_z3950oid (odr_en, CLASS_RECSYN, VAL_TEXT_XML);
705 // z3950'fy record schema
706 if (sr_req->recordSchema)
708 apdu->u.presentRequest->recordComposition
709 = (Z_RecordComposition *) odr_malloc(odr_en, sizeof(Z_RecordComposition));
710 apdu->u.presentRequest->recordComposition->which
711 = Z_RecordComp_simple;
712 apdu->u.presentRequest->recordComposition->u.simple
713 = build_esn_from_schema(odr_en, (const char *) sr_req->recordSchema);
716 // z3950'fy time to live - flagged as diagnostics above
717 //if (sr_req->resultSetTTL)
719 // attaching Z3950 package to filter chain
720 z3950_package.request() = apdu;
722 //std::cout << "z3950_present_request " << *apdu << "\n";
723 z3950_package.move();
725 //check successful Z3950 present response
726 Z_GDU *z3950_gdu = z3950_package.response().get();
727 if (!z3950_gdu || z3950_gdu->which != Z_GDU_Z3950
728 || z3950_gdu->u.z3950->which != Z_APDU_presentResponse
729 || !z3950_gdu->u.z3950->u.presentResponse)
732 yaz_add_srw_diagnostic(odr_en,
733 &(sru_pdu_res->u.response->diagnostics),
734 &(sru_pdu_res->u.response->num_diagnostics),
736 package.session().close();
741 // everything fine, continuing
742 //std::cout << "z3950_present_request OK\n";
744 Z_PresentResponse *pr = z3950_gdu->u.z3950->u.presentResponse;
745 Z_SRW_searchRetrieveResponse *sru_res = sru_pdu_res->u.response;
747 // checking non surrogate dioagnostics in Z3950 present response package
749 && pr->records->which == Z_Records_NSD
750 && pr->records->u.nonSurrogateDiagnostic)
753 z3950_to_srw_diag(odr_en, sru_res, pr->records->u.nonSurrogateDiagnostic);
757 // copy all records if existing
758 if (pr->records && pr->records->which == Z_Records_DBOSD)
760 // srw'fy number of returned records
762 = pr->records->u.databaseOrSurDiagnostics->num_records;
765 = (Z_SRW_record *) odr_malloc(odr_en,
766 sru_res->num_records *sizeof(Z_SRW_record));
768 // srw'fy nextRecordPosition
769 if (pr->nextResultSetPosition)
770 sru_res->nextRecordPosition
771 = odr_intdup(odr_en, *(pr->nextResultSetPosition));
773 // inserting all records
774 for (int i = 0; i < sru_res->num_records; i++)
776 Z_NamePlusRecord *npr
777 = pr->records->u.databaseOrSurDiagnostics->records[i];
779 sru_res->records[i].recordPosition
780 = odr_intdup(odr_en, i + *(apdu->u.presentRequest->resultSetStartPoint));
782 sru_res->records[i].recordPacking = record_packing;
784 if (npr->which != Z_NamePlusRecord_databaseRecord)
786 sru_res->records[i].recordSchema = "diagnostic";
787 sru_res->records[i].recordData_buf = "67";
788 sru_res->records[i].recordData_len = 2;
792 Z_External *r = npr->u.databaseRecord;
793 oident *ent = oid_getentbyoid(r->direct_reference);
794 if (r->which == Z_External_octet
795 && ent->value == VAL_TEXT_XML)
797 sru_res->records[i].recordSchema = "dc";
798 sru_res->records[i].recordData_buf
799 = odr_strdupn(odr_en,
800 (const char *)r->u.octet_aligned->buf,
801 r->u.octet_aligned->len);
802 sru_res->records[i].recordData_len
803 = r->u.octet_aligned->len;
807 sru_res->records[i].recordSchema = "diagnostic";
808 sru_res->records[i].recordData_buf = "67";
809 sru_res->records[i].recordData_len = 2;
819 yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package,
821 Z_SRW_PDU *sru_pdu_res,
822 Z_SRW_scanRequest const *sr_req) const
824 Package z3950_package(package.session(), package.origin());
825 z3950_package.copy_filter(package);
826 //mp::odr odr_en(ODR_ENCODE);
827 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_scanRequest);
829 //TODO: add stuff in apdu
830 Z_ScanRequest *z_scanRequest = apdu->u.scanRequest;
832 // database repackaging
833 z_scanRequest->num_databaseNames = 1;
834 z_scanRequest->databaseNames = (char**)
835 odr_malloc(odr_en, sizeof(char *));
836 if (sr_req->database)
837 z_scanRequest->databaseNames[0]
838 = odr_strdup(odr_en, const_cast<char *>(sr_req->database));
840 z_scanRequest->databaseNames[0]
841 = odr_strdup(odr_en, "Default");
845 // CQL or XCQL scan is not possible in Z3950, flagging a diagnostic
846 if (sr_req->query_type != Z_SRW_query_type_pqf)
848 //send_to_srw_client_error(7, "query");
852 // PQF query repackaging
853 // need to use Z_AttributesPlusTerm structure, not Z_Query
854 // this can be digget out of a
855 // Z_query->type1(Z_RPNQuery)->RPNStructure(Z_RPNStructure)
856 // ->u.simple(Z_Operand)->u.attributesPlusTerm(Z_AttributesPlusTerm )
858 //Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query));
859 //z_searchRequest->query = z_query;
861 //if (!z3950_build_query(odr_en, z_query,
862 // (const SRW_query&)sr_req->query,
863 // sr_req->query_type))
865 //send_to_srw_client_error(7, "query");
871 z3950_package.request() = apdu;
872 std::cout << "z3950_scan_request " << *apdu << "\n";
874 z3950_package.move();
875 //TODO: check success condition
880 bool yf::SRUtoZ3950::Rep::z3950_build_query(mp::odr &odr_en, Z_Query *z_query,
881 const SRW_query &query,
882 SRW_query_type query_type) const
884 if (query_type == Z_SRW_query_type_cql)
886 Z_External *ext = (Z_External *)
887 odr_malloc(odr_en, sizeof(*ext));
888 ext->direct_reference =
889 odr_getoidbystr(odr_en, "1.2.840.10003.16.2");
890 ext->indirect_reference = 0;
892 ext->which = Z_External_CQL;
893 ext->u.cql = const_cast<char *>(query.cql);
895 z_query->which = Z_Query_type_104;
896 z_query->u.type_104 = ext;
900 if (query_type == Z_SRW_query_type_pqf)
902 Z_RPNQuery *RPNquery;
903 YAZ_PQF_Parser pqf_parser;
905 pqf_parser = yaz_pqf_create ();
907 RPNquery = yaz_pqf_parse (pqf_parser, odr_en, query.pqf);
910 std::cout << "TODO: Handeling of bad PQF\n";
911 std::cout << "TODO: Diagnostic to be send\n";
913 z_query->which = Z_Query_type_1;
914 z_query->u.type_1 = RPNquery;
916 yaz_pqf_destroy(pqf_parser);
924 yf::SRUtoZ3950::Rep::sru_protocol(const Z_HTTP_Request &http_req) const
926 const std::string mime_urlencoded("application/x-www-form-urlencoded");
927 const std::string mime_text_xml("text/xml");
928 const std::string mime_soap_xml("application/soap+xml");
930 const std::string http_method(http_req.method);
931 const std::string http_type
932 = http_header_value(http_req.headers, "Content-Type");
934 if (http_method == "GET")
937 if (http_method == "POST"
938 && http_type == mime_urlencoded)
941 if ( http_method == "POST"
942 && (http_type == mime_text_xml
943 || http_type == mime_soap_xml))
950 yf::SRUtoZ3950::Rep::debug_http(const Z_HTTP_Request &http_req) const
952 std::string message("<html>\n<body>\n<h1>"
953 "Metaproxy SRUtoZ3950 filter"
956 message += "<h3>HTTP Info</h3><br/>\n";
958 message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
959 message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
960 message += "<b>Path: </b> " + std::string(http_req.path) + "<br/>\n";
962 message += "<b>Content-Type:</b>"
963 + http_header_value(http_req.headers, "Content-Type")
965 message += "<b>Content-Length:</b>"
966 + http_header_value(http_req.headers, "Content-Length")
970 message += "<h3>Headers</h3><br/>\n";
972 Z_HTTP_Header* header = http_req.headers;
974 message += "<b>Header: </b> <i>"
975 + std::string(header->name) + ":</i> "
976 + std::string(header->value) + "<br/>\n";
977 header = header->next;
980 message += "</body>\n</html>\n";
984 void yf::SRUtoZ3950::Rep::http_response(metaproxy_1::Package &package,
985 const std::string &content,
989 Z_GDU *zgdu_req = package.request().get();
993 = odr.create_HTTP_Response(package.session(),
994 zgdu_req->u.HTTP_Request,
997 zgdu_res->u.HTTP_Response->content_len = content.size();
998 zgdu_res->u.HTTP_Response->content_buf
999 = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
1001 strncpy(zgdu_res->u.HTTP_Response->content_buf,
1002 content.c_str(), zgdu_res->u.HTTP_Response->content_len);
1004 //z_HTTP_header_add(odr, &hres->headers,
1005 // "Content-Type", content_type.c_str());
1006 package.response() = zgdu_res;
1010 Z_ElementSetNames * yf::SRUtoZ3950::Rep::build_esn_from_schema(mp::odr &odr_en, const char *schema) const
1015 Z_ElementSetNames *esn
1016 = (Z_ElementSetNames *) odr_malloc(odr_en, sizeof(Z_ElementSetNames));
1017 esn->which = Z_ElementSetNames_generic;
1018 esn->u.generic = odr_strdup(odr_en, schema);
1022 int yf::SRUtoZ3950::Rep::z3950_to_srw_diag(mp::odr &odr_en, Z_SRW_searchRetrieveResponse *sru_res,
1023 Z_DefaultDiagFormat *ddf) const
1025 int bib1_code = *ddf->condition;
1026 if (bib1_code == 109)
1028 sru_res->num_diagnostics = 1;
1029 sru_res->diagnostics = (Z_SRW_diagnostic *)
1030 odr_malloc(odr_en, sizeof(*sru_res->diagnostics));
1031 yaz_mk_std_diagnostic(odr_en, sru_res->diagnostics,
1032 yaz_diag_bib1_to_srw(*ddf->condition),
1039 static mp::filter::Base* filter_creator()
1041 return new mp::filter::SRUtoZ3950;
1045 struct metaproxy_1_filter_struct metaproxy_1_filter_sru_to_z3950 = {
1056 * indent-tabs-mode: nil
1057 * c-file-style: "stroustrup"
1059 * vim: shiftwidth=4 tabstop=8 expandtab