1 /* $Id: filter_sru_to_z3950.cpp,v 1.5 2006-09-14 20:29:50 marc Exp $
2 Copyright (c) 2005-2006, Index Data.
4 See the LICENSE file for details
11 #include "filter_sru_to_z3950.hpp"
16 #include <boost/thread/mutex.hpp>
23 namespace mp = metaproxy_1;
24 namespace yf = mp::filter;
30 std::string to_string(const T& t)
39 std::string http_header_value(const Z_HTTP_Header* header,
40 const std::string name)
42 while (header && header->name
43 && std::string(header->name) != name)
44 header = header->next;
46 if (header && header->name && std::string(header->name) == name
48 return std::string(header->value);
57 namespace metaproxy_1 {
59 class SRUtoZ3950::Rep {
60 //friend class SRUtoZ3950;
62 void configure(const xmlNode *xmlnode);
63 void process(metaproxy_1::Package &package) const;
65 std::string sru_protocol(const Z_HTTP_Request &http_req) const;
66 std::string debug_http(const Z_HTTP_Request &http_req) const;
67 void http_response(mp::Package &package,
68 const std::string &content,
69 int http_code = 200) const;
70 bool build_sru_debug_package(mp::Package &package) const;
71 bool z3950_init_request(mp::Package &package,
73 &database = "Default") const;
74 bool z3950_close_request(mp::Package &package) const;
75 bool z3950_search_request(mp::Package &package) const;
76 bool z3950_scan_request(mp::Package &package) const;
81 yf::SRUtoZ3950::SRUtoZ3950() : m_p(new Rep)
85 yf::SRUtoZ3950::~SRUtoZ3950()
86 { // must have a destructor because of boost::scoped_ptr
89 void yf::SRUtoZ3950::configure(const xmlNode *xmlnode)
91 m_p->configure(xmlnode);
94 void yf::SRUtoZ3950::process(mp::Package &package) const
96 m_p->process(package);
99 void yf::SRUtoZ3950::Rep::configure(const xmlNode *xmlnode)
103 void yf::SRUtoZ3950::Rep::process(mp::Package &package) const
105 Z_GDU *zgdu_req = package.request().get();
107 // ignoring all non HTTP_Request packages
108 if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
113 // only working on HTTP_Request packages now
115 z3950_init_request(package);
116 //z3950_search_request(package);
117 //z3950_scan_request(package);
118 z3950_close_request(package);
121 // TODO: Z3950 response parsing and translation to SRU package
122 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
125 build_sru_debug_package(package);
135 // SRU request package checking
139 Z_SRW_PDU *sru_pdu_req = 0;
140 Z_SRW_PDU *sru_pdu_res = 0;
141 Z_APDU *z3950_apdu_req = 0;
142 Z_APDU *z3950_apdu_res = 0;
145 Z_SOAP *soap_req = 0;
147 Z_SRW_diagnostic *diag = 0;
149 //mp::odr odr_de(ODR_DECODE);
151 if (0 == yaz_sru_decode(http_req, &sru_pdu_req, &soap_req,
152 odr(ODR_DECODE), &charset, &diag, &num_diags))
154 std::cout << "SRU GET/POST \n";
156 else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, &soap_req,
157 odr(ODR_DECODE), &charset))
159 std::cout << "SRU SOAP \n";
163 std::cout << "SRU DECODING ERROR - SHOULD NEVER HAPPEN\n";
164 package.session().close();
170 std::cout << "SRU DIAGNOSTICS " << num_diags << "\n";
171 // TODO: make nice diagnostic return package
172 //Z_SRW_PDU *srw_pdu_res =
173 // yaz_srw_get(odr(ODR_ENCODE),
174 // Z_SRW_searchRetrieve_response);
175 // Z_SRW_searchRetrieveResponse *srw_res = srw_pdu_res->u.response;
177 // srw_res->diagnostics = diagnostic;
178 // srw_res->num_diagnostics = num_diagnostic;
179 // send_srw_response(srw_pdu_res);
182 // package.session().close();
187 // SRU request package translation to Z3950 package
190 if (sru_pdu_req && sru_pdu_req->which == Z_SRW_searchRetrieve_request)
192 Z_SRW_searchRetrieveRequest *srw_req = sru_pdu_req->u.request;
194 // recordXPath unsupported.
195 //if (srw_req->recordXPath)
196 // yaz_add_srw_diagnostic(odr_decode(),
197 // &diag, &num_diags, 72, 0);
199 // if (srw_req->sort_type != Z_SRW_sort_type_none)
200 // yaz_add_srw_diagnostic(odr_decode(),
201 // &diag, &num_diags, 80, 0);
205 std::cout << "SRU OPERATION NOT SUPPORTED \n";
206 // TODO: make nice diagnostic return package
207 // package.session().close();
213 bool yf::SRUtoZ3950::Rep::build_sru_debug_package(mp::Package &package) const
215 Z_GDU *zgdu_req = package.request().get();
216 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
218 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
219 std::string content = debug_http(*http_req);
221 http_response(package, content, http_code);
229 yf::SRUtoZ3950::Rep::z3950_init_request(mp::Package &package,
230 const std::string &database) const
232 // prepare Z3950 package
233 Package z3950_package(package.session(), package.origin());
234 z3950_package.copy_filter(package);
236 // set initRequest APDU
237 mp::odr odr_en(ODR_ENCODE);
238 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_initRequest);
239 //TODO: add database name in apdu
240 z3950_package.request() = apdu;
242 // send Z3950 package
243 z3950_package.move();
244 if (z3950_package.session().is_closed()){
245 package.session().close();
249 // check successful initResponse
250 Z_GDU *gdu = package.response().get();
251 if (gdu && gdu->which == Z_GDU_Z3950
252 && gdu->u.z3950->which == Z_APDU_initResponse)
259 yf::SRUtoZ3950::Rep::z3950_close_request(mp::Package &package) const
261 // prepare Z3950 package
262 Package z3950_package(package.session(), package.origin());
263 z3950_package.copy_filter(package);
265 // set initRequest APDU
266 mp::odr odr_en(ODR_ENCODE);
267 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_close);
268 //TODO: add database name in apdu
269 z3950_package.request() = apdu;
271 // send Z3950 package
272 z3950_package.move();
273 //if (z3950_package.session().is_closed()){
274 // package.session().close();
278 // check successful initResponse
279 Z_GDU *gdu = package.response().get();
280 if (gdu && gdu->which == Z_GDU_Z3950
281 && gdu->u.z3950->which == Z_APDU_close)
288 yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package) const
290 Package z3950_package(package.session(), package.origin());
291 z3950_package.copy_filter(package);
292 mp::odr odr_en(ODR_ENCODE);
293 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_searchRequest);
294 //TODO: add stuff in apdu
297 z3950_package.request() = apdu;
298 z3950_package.move();
299 //TODO: check success condition
305 yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package) const
307 Package z3950_package(package.session(), package.origin());
308 z3950_package.copy_filter(package);
309 mp::odr odr_en(ODR_ENCODE);
310 Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_scanRequest);
311 //TODO: add stuff in apdu
312 z3950_package.request() = apdu;
313 z3950_package.move();
314 //TODO: check success condition
322 yf::SRUtoZ3950::Rep::sru_protocol(const Z_HTTP_Request &http_req) const
324 const std::string mime_urlencoded("application/x-www-form-urlencoded");
325 const std::string mime_text_xml("text/xml");
326 const std::string mime_soap_xml("application/soap+xml");
328 const std::string http_method(http_req.method);
329 const std::string http_type
330 = http_header_value(http_req.headers, "Content-Type");
332 if (http_method == "GET")
335 if (http_method == "POST"
336 && http_type == mime_urlencoded)
339 if ( http_method == "POST"
340 && (http_type == mime_text_xml
341 || http_type == mime_soap_xml))
348 yf::SRUtoZ3950::Rep::debug_http(const Z_HTTP_Request &http_req) const
350 std::string message("<html>\n<body>\n<h1>"
351 "Metaproxy SRUtoZ3950 filter"
354 message += "<h3>HTTP Info</h3><br/>\n";
356 message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
357 message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
358 message += "<b>Path: </b> " + std::string(http_req.path) + "<br/>\n";
360 message += "<b>Content-Type:</b>"
361 + http_header_value(http_req.headers, "Content-Type")
363 message += "<b>Content-Length:</b>"
364 + http_header_value(http_req.headers, "Content-Length")
368 message += "<h3>Headers</h3><br/>\n";
370 Z_HTTP_Header* header = http_req.headers;
372 message += "<b>Header: </b> <i>"
373 + std::string(header->name) + ":</i> "
374 + std::string(header->value) + "<br/>\n";
375 header = header->next;
378 message += "</body>\n</html>\n";
382 void yf::SRUtoZ3950::Rep::http_response(metaproxy_1::Package &package,
383 const std::string &content,
387 Z_GDU *zgdu_req = package.request().get();
391 = odr.create_HTTP_Response(package.session(),
392 zgdu_req->u.HTTP_Request,
395 zgdu_res->u.HTTP_Response->content_len = content.size();
396 zgdu_res->u.HTTP_Response->content_buf
397 = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
399 strncpy(zgdu_res->u.HTTP_Response->content_buf,
400 content.c_str(), zgdu_res->u.HTTP_Response->content_len);
402 //z_HTTP_header_add(odr, &hres->headers,
403 // "Content-Type", content_type.c_str());
404 package.response() = zgdu_res;
410 static mp::filter::Base* filter_creator()
412 return new mp::filter::SRUtoZ3950;
416 struct metaproxy_1_filter_struct metaproxy_1_filter_sru_to_z3950 = {
427 * indent-tabs-mode: nil
428 * c-file-style: "stroustrup"
430 * vim: shiftwidth=4 tabstop=8 expandtab