added correct SRU diagnostics when SRU package decoding fails
[metaproxy-moved-to-github.git] / src / filter_sru_to_z3950.cpp
1 /* $Id: filter_sru_to_z3950.cpp,v 1.10 2006-09-21 11:43:41 marc Exp $
2    Copyright (c) 2005-2006, Index Data.
3
4    See the LICENSE file for details
5  */
6
7 #include "config.hpp"
8 #include "filter.hpp"
9 #include "package.hpp"
10 #include "util.hpp"
11 #include "gduutil.hpp"
12 #include "filter_sru_to_z3950.hpp"
13
14 #include <yaz/zgdu.h>
15 #include <yaz/z-core.h>
16 #include <yaz/srw.h>
17 #include <yaz/pquery.h>
18
19 #include <boost/thread/mutex.hpp>
20
21 #include <iostream>
22 #include <sstream>
23 #include <string>
24
25
26 namespace mp = metaproxy_1;
27 namespace yf = mp::filter;
28
29 namespace metaproxy_1 
30 {
31
32     template<typename T>
33     std::string to_string(const T& t)
34     {
35         std::ostringstream o;
36         if(o << t)
37             return o.str();
38         
39         return std::string();
40     }
41
42     std::string http_header_value(const Z_HTTP_Header* header, 
43                                   const std::string name)
44     {
45         while (header && header->name
46                && std::string(header->name) !=  name)
47             header = header->next;
48         
49         if (header && header->name && std::string(header->name) == name
50             && header->value)
51             return std::string(header->value);
52
53         return std::string();
54     }
55     
56
57 }
58
59
60 namespace metaproxy_1 {
61     namespace filter {
62         class SRUtoZ3950::Rep {
63             //friend class SRUtoZ3950;
64         private:
65             union SRW_query {char * cql; char * xcql; char * pqf;};
66             typedef const int& SRW_query_type;
67         public:
68             void configure(const xmlNode *xmlnode);
69             void process(metaproxy_1::Package &package) const;
70         private:
71             std::string sru_protocol(const Z_HTTP_Request &http_req) const;
72             std::string debug_http(const Z_HTTP_Request &http_req) const;
73             void http_response(mp::Package &package, 
74                                const std::string &content, 
75                                int http_code = 200) const;
76             bool build_sru_debug_package(mp::Package &package) const;
77             bool build_sru_response(mp::Package &package, 
78                                     mp::odr &odr_en,
79                                     Z_SOAP *soap,
80                                     const Z_SRW_PDU *sru_pdu_res,
81                                     char *charset,
82                                     const char *stylesheet) const;
83             Z_SRW_PDU * decode_sru_request(mp::Package &package,   
84                                            mp::odr &odr_de,
85                                            mp::odr &odr_en,
86                                            Z_SRW_PDU *&sru_pdu_res,
87                                            Z_SOAP *&soap,
88                                            char *charset,
89                                            const char *stylesheet) const;
90             bool z3950_build_query(mp::odr &odr_en, Z_Query *z_query, 
91                                    const SRW_query &query, 
92                                    SRW_query_type query_type) const;
93             bool z3950_init_request(mp::Package &package, 
94                                          const std::string 
95                                          &database = "Default") const;
96             bool z3950_close_request(mp::Package &package) const;
97             bool z3950_search_request(mp::Package &package,
98                                       mp::odr &odr_en,
99                                       Z_SRW_PDU *sru_pdu_res,
100                                       Z_SRW_searchRetrieveRequest 
101                                           const *sr_req) const;
102                                       //const std::string &database, 
103                                       //const std::string &query, 
104                                       //int query_type) const;
105             bool z3950_present_request(mp::Package &package,
106                                        mp::odr &odr_en,
107                                        Z_SRW_PDU *sru_pdu_res,
108                                        Z_SRW_searchRetrieveRequest 
109                                        const *sr_req) const;
110             //unsigned int start_position,
111             //unsigned int records_requested) const;
112             bool z3950_scan_request(mp::Package &package,
113                                     mp::odr &odr_en,
114                                     Z_SRW_PDU *sru_pdu_res,
115                                     Z_SRW_scanRequest 
116                                     const *sr_req) const;
117             //const std::string &database, 
118             //const std::string &query, 
119             //int query_type) const;
120         };
121     }
122 }
123
124 yf::SRUtoZ3950::SRUtoZ3950() : m_p(new Rep)
125 {
126 }
127
128 yf::SRUtoZ3950::~SRUtoZ3950()
129 {  // must have a destructor because of boost::scoped_ptr
130 }
131
132 void yf::SRUtoZ3950::configure(const xmlNode *xmlnode)
133 {
134     m_p->configure(xmlnode);
135 }
136
137 void yf::SRUtoZ3950::process(mp::Package &package) const
138 {
139     m_p->process(package);
140 }
141
142 void yf::SRUtoZ3950::Rep::configure(const xmlNode *xmlnode)
143 {
144 }
145
146 void yf::SRUtoZ3950::Rep::process(mp::Package &package) const
147 {
148     Z_GDU *zgdu_req = package.request().get();
149
150     // ignoring all non HTTP_Request packages
151     if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
152         package.move();
153         return;
154     }
155     
156     // only working on  HTTP_Request packages now
157
158
159     // TODO: Z3950 response parsing and translation to SRU package
160     bool ok = true;    
161
162     Z_SRW_PDU *sru_pdu_req = 0;
163     mp::odr odr_de(ODR_DECODE);
164
165     Z_SRW_PDU *sru_pdu_res = 0;
166     mp::odr odr_en(ODR_ENCODE);
167
168     Z_SOAP *soap = 0;
169     char *charset = 0;
170     const char *stylesheet = 0;
171
172     if (! (sru_pdu_req = decode_sru_request(package, odr_de, odr_en, 
173                                             sru_pdu_res, soap,
174                                             charset, stylesheet)))
175     {
176         //build_sru_debug_package(package);
177         build_sru_response(package, odr_en, soap, 
178                            sru_pdu_res, charset, stylesheet);
179         return;
180     }
181     
182     
183     // SRU request package translation to Z3950 package
184     if (sru_pdu_req)
185         std::cout << *sru_pdu_req << "\n";
186     else
187         std::cout << "SRU empty\n";
188     
189
190     // explain
191     if (sru_pdu_req && sru_pdu_req->which == Z_SRW_explain_request)
192     {
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";
196         
197     }
198     
199
200     // searchRetrieve
201     if (sru_pdu_req && sru_pdu_req->which == Z_SRW_searchRetrieve_request)
202     {
203         Z_SRW_searchRetrieveRequest *sr_req = sru_pdu_req->u.request;   
204         
205         sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_searchRetrieve_response);
206
207         if (z3950_init_request(package))
208         {
209             {
210                 ok = z3950_search_request(package, odr_en,
211                                           sru_pdu_res, sr_req);
212
213                 if (ok 
214                     && sru_pdu_res->u.response->numberOfRecords
215                     && *(sru_pdu_res->u.response->numberOfRecords)
216                     && sr_req->maximumRecords
217                     && *(sr_req->maximumRecords))
218                     
219                     ok = z3950_present_request(package, odr_en,
220                                                sru_pdu_res,
221                                                sr_req);
222                 z3950_close_request(package);
223             }
224         }
225     }
226
227     // scan
228     else if (sru_pdu_req && sru_pdu_req->which == Z_SRW_scan_request)
229     {
230         Z_SRW_scanRequest  *sr_req = sru_pdu_req->u.scan_request;   
231
232         sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_scan_response);
233         
234         if (z3950_init_request(package))
235         {
236             z3950_scan_request(package, odr_en, sru_pdu_res, sr_req);    
237             z3950_close_request(package);
238         }        
239     }
240     else
241     {
242         std::cout << "SRU OPERATION NOT SUPPORTED \n";
243         sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response);
244         
245         // TODO: make nice diagnostic return package 
246         package.session().close();
247         return;
248     }
249
250     //build_sru_debug_package(package);
251     build_sru_response(package, odr_en, soap, 
252                        sru_pdu_res, charset, stylesheet);
253     return;
254
255
256
257
258
259
260
261 }
262
263 bool yf::SRUtoZ3950::Rep::build_sru_debug_package(mp::Package &package) const
264 {
265     Z_GDU *zgdu_req = package.request().get();
266     if  (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
267     {    
268         Z_HTTP_Request* http_req =  zgdu_req->u.HTTP_Request;
269         std::string content = debug_http(*http_req);
270         int http_code = 400;    
271         http_response(package, content, http_code);
272         return true;
273     }
274     package.session().close();
275     return false;
276 }
277
278
279 bool yf::SRUtoZ3950::Rep::build_sru_response(mp::Package &package, 
280                                              mp::odr &odr_en,
281                                              Z_SOAP *soap,
282                                              const Z_SRW_PDU *sru_pdu_res,
283                                              char *charset,
284                                              const char *stylesheet) 
285     const
286 {
287
288     // SRU request package translation to Z3950 package
289     if (sru_pdu_res)
290         std::cout << *(const_cast<Z_SRW_PDU *>(sru_pdu_res)) << "\n";
291     else
292         std::cout << "SRU empty\n";
293
294     
295     Z_GDU *zgdu_req = package.request().get();
296     if  (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
297     {    
298         Z_GDU *zgdu_res //= z_get_HTTP_Response(odr_en, 200);
299             = odr_en.create_HTTP_Response(package.session(), 
300                                           zgdu_req->u.HTTP_Request, 
301                                           200);
302
303         // adding HTTP response code and headers
304         Z_HTTP_Response * http_res = zgdu_res->u.HTTP_Response;
305         //http_res->code = http_code;
306         
307         std::string ctype("text/xml");
308         if (charset){
309             ctype += "; charset=";
310             ctype += charset;
311         }
312
313         z_HTTP_header_add(odr_en, 
314                           &http_res->headers, "Content-Type", ctype.c_str());
315
316          // packaging Z_SOAP into HTML response
317          static Z_SOAP_Handler soap_handlers[4] = {
318               {"http://www.loc.gov/zing/srw/", 0,
319                (Z_SOAP_fun) yaz_srw_codec},
320               {"http://www.loc.gov/zing/srw/v1.0/", 0,
321                (Z_SOAP_fun) yaz_srw_codec},
322               {"http://www.loc.gov/zing/srw/update/", 0,
323                (Z_SOAP_fun) yaz_ucp_codec},
324               {0, 0, 0}
325           };
326
327
328          // empty stylesheet means NO stylesheet
329          if (stylesheet && *stylesheet == '\0')
330              stylesheet = 0;
331          
332          // encoding SRU package
333          
334          soap->u.generic->p  = (void*) sru_pdu_res;         
335          //int ret = 
336          z_soap_codec_enc_xsl(odr_en, &soap, 
337                               &http_res->content_buf, &http_res->content_len,
338                               soap_handlers, charset, stylesheet);
339          
340
341          package.response() = zgdu_res;
342          return true;
343     }
344     package.session().close();
345     return false;
346 }
347
348
349
350  Z_SRW_PDU * yf::SRUtoZ3950::Rep::decode_sru_request(mp::Package &package,
351                                                      mp::odr &odr_de,
352                                                      mp::odr &odr_en,
353                                                      Z_SRW_PDU *&sru_pdu_res,
354                                                      Z_SOAP *&soap,
355                                                      char *charset,
356                                                      const char *stylesheet) 
357      const
358 {
359     Z_GDU *zgdu_req = package.request().get();
360     Z_SRW_PDU *sru_pdu_req = 0;
361
362     assert((zgdu_req->which == Z_GDU_HTTP_Request));
363     
364     //ignoring all non HTTP_Request packages
365     //if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
366     //    return 0;
367     //}
368     
369     Z_HTTP_Request* http_req =  zgdu_req->u.HTTP_Request;
370     if (! http_req)
371         return 0;
372
373     Z_SRW_PDU *sru_pdu_res_exp = yaz_srw_get(odr_en, Z_SRW_explain_response);
374     
375     if (0 == yaz_sru_decode(http_req, &sru_pdu_req, &soap, 
376                             odr_de, &charset, 
377                             &(sru_pdu_res_exp->u.response->diagnostics), 
378                             &(sru_pdu_res_exp->u.response->num_diagnostics)))
379     {
380         if (sru_pdu_res_exp->u.response->num_diagnostics)
381         {
382             sru_pdu_res = sru_pdu_res_exp;
383             package.session().close();
384             return 0;
385         }
386         return sru_pdu_req;
387     }
388     else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, &soap, 
389                                  odr_de, &charset))
390         return sru_pdu_req;
391     else 
392     {
393         sru_pdu_res = sru_pdu_res_exp;
394         package.session().close();
395         return 0;
396     }
397     return 0;
398 }
399
400 bool 
401 yf::SRUtoZ3950::Rep::z3950_init_request(mp::Package &package, 
402                                              const std::string &database) const
403 {
404     // prepare Z3950 package
405     //Session s;
406     //Package z3950_package(s, package.origin());
407     Package z3950_package(package.session(), package.origin());
408     z3950_package.copy_filter(package);
409
410     // set initRequest APDU
411     mp::odr odr_en(ODR_ENCODE);
412     Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_initRequest);
413     Z_InitRequest *init_req = apdu->u.initRequest;
414     //TODO: add user name in apdu
415     //TODO: add user passwd in apdu
416     //init_req->idAuthentication = org_init->idAuthentication;
417     //init_req->implementationId = "IDxyz";
418     //init_req->implementationName = "NAMExyz";
419     //init_req->implementationVersion = "VERSIONxyz";
420
421     ODR_MASK_SET(init_req->options, Z_Options_search);
422     ODR_MASK_SET(init_req->options, Z_Options_present);
423     ODR_MASK_SET(init_req->options, Z_Options_namedResultSets);
424     ODR_MASK_SET(init_req->options, Z_Options_scan);
425
426     ODR_MASK_SET(init_req->protocolVersion, Z_ProtocolVersion_1);
427     ODR_MASK_SET(init_req->protocolVersion, Z_ProtocolVersion_2);
428     ODR_MASK_SET(init_req->protocolVersion, Z_ProtocolVersion_3);
429
430     z3950_package.request() = apdu;
431
432     // send Z3950 package
433     // std::cout << "z3950_init_request " << *apdu <<"\n";
434     z3950_package.move();
435
436     // dead Z3950 backend detection
437     if (z3950_package.session().is_closed()){
438         package.session().close();
439         return false;
440     }
441
442     // check successful initResponse
443     Z_GDU *z3950_gdu = z3950_package.response().get();
444
445     if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 
446         && z3950_gdu->u.z3950->which == Z_APDU_initResponse)
447          return true;
448  
449     return false;
450 }
451
452 bool 
453 yf::SRUtoZ3950::Rep::z3950_close_request(mp::Package &package) const
454 {
455     // prepare Z3950 package 
456     Package z3950_package(package.session(), package.origin());
457     z3950_package.copy_filter(package);
458     z3950_package.session().close();
459
460     // set close APDU
461     //mp::odr odr_en(ODR_ENCODE);
462     //Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_close);
463     //z3950_package.request() = apdu;
464
465     z3950_package.move();
466
467     // check successful close response
468     //Z_GDU *z3950_gdu = z3950_package.response().get();
469     //if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 
470     //    && z3950_gdu->u.z3950->which == Z_APDU_close)
471     //    return true;
472
473     if (z3950_package.session().is_closed()){
474         //package.session().close();
475         return true;
476     }
477     return false;
478 }
479
480 bool 
481 yf::SRUtoZ3950::Rep::z3950_search_request(mp::Package &package,  
482                                           mp::odr &odr_en,
483                                           Z_SRW_PDU *sru_pdu_res,
484                                           Z_SRW_searchRetrieveRequest 
485                                           const *sr_req) const
486 {
487     Package z3950_package(package.session(), package.origin());
488     z3950_package.copy_filter(package); 
489     //mp::odr odr_en(ODR_ENCODE);
490     Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_searchRequest);
491
492     //add stuff in z3950 apdu
493     Z_SearchRequest *z_searchRequest = apdu->u.searchRequest;
494
495     // z3950'fy database
496     z_searchRequest->num_databaseNames = 1;
497     z_searchRequest->databaseNames = (char**)
498         odr_malloc(odr_en, sizeof(char *));
499     if (sr_req->database)
500         z_searchRequest->databaseNames[0] 
501             = odr_strdup(odr_en, const_cast<char *>(sr_req->database));
502     else
503         z_searchRequest->databaseNames[0] 
504             = odr_strdup(odr_en, "Default");
505
506
507     // z3950'fy query
508     Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query));
509     z_searchRequest->query = z_query;
510  
511     if (!z3950_build_query(odr_en, z_query, 
512                            (const SRW_query&)sr_req->query, 
513                            sr_req->query_type))
514     {    
515         //send_to_srw_client_error(7, "query");
516         return false;
517     }
518
519     z3950_package.request() = apdu;
520     //std::cout << "z3950_search_request " << *apdu << "\n";
521         
522     z3950_package.move();
523
524     //TODO: check success condition
525
526     //int yaz_diag_bib1_to_srw (int bib1_code);
527     //int yaz_diag_srw_to_bib1(int srw_code);
528     //Se kode i src/seshigh.c (srw_bend_search, srw_bend_init).
529
530     Z_GDU *z3950_gdu = z3950_package.response().get();
531     //std::cout << "z3950_search_request " << *z3950_gdu << "\n";
532
533     if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 
534         && z3950_gdu->u.z3950->which == Z_APDU_searchResponse
535         && z3950_gdu->u.z3950->u.searchResponse->searchStatus)
536     {
537
538         Z_SearchResponse *sr = z3950_gdu->u.z3950->u.searchResponse;
539         if (sr)
540         {
541             // srw'fy number of records
542             sru_pdu_res->u.response->numberOfRecords 
543                 = (int *) odr_malloc(odr_en, sizeof(int *));
544             *(sru_pdu_res->u.response->numberOfRecords) = *(sr->resultCount);
545
546             // srw'fy nextRecordPosition
547             //sru_pdu_res->u.response->nextRecordPosition 
548             //    = (int *) odr_malloc(odr_en, sizeof(int *));
549             //*(sru_pdu_res->u.response->nextRecordPosition) = 1;
550
551         }
552
553         return true;
554     }
555     
556     return false;
557 }
558
559 bool 
560 yf::SRUtoZ3950::Rep::z3950_present_request(mp::Package &package, 
561                                            mp::odr &odr_en,
562                                            Z_SRW_PDU *sru_pdu_res,
563                                            Z_SRW_searchRetrieveRequest 
564                                            const *sr_req)
565     const
566 {
567
568     if (!sr_req)
569         return false;
570
571     
572     // no need to work if nobody wants records seen ..
573     if (!(sr_req->maximumRecords) || 0 == *(sr_req->maximumRecords))
574         return true;
575
576     // creating Z3950 package
577     Package z3950_package(package.session(), package.origin());
578     z3950_package.copy_filter(package); 
579     //mp::odr odr_en(ODR_ENCODE);
580     Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_presentRequest);
581
582     //TODO: add stuff in apdu
583     assert(apdu->u.presentRequest);
584
585     bool send_z3950_present = true;
586
587     // recordXPath unsupported.
588     if (sr_req->recordXPath)
589     {
590         send_z3950_present = false;
591         yaz_add_srw_diagnostic(odr_en,
592                                &(sru_pdu_res->u.response->diagnostics), 
593                                &(sru_pdu_res->u.response->num_diagnostics), 
594                                72, 0);
595     }
596     
597     // resultSetTTL unsupported.
598     // resultSetIdleTime in response
599     if (sr_req->resultSetTTL)
600     {
601         send_z3950_present = false;
602         yaz_add_srw_diagnostic(odr_en,
603                                &(sru_pdu_res->u.response->diagnostics), 
604                                &(sru_pdu_res->u.response->num_diagnostics), 
605                                50, 0);
606     }
607     
608     // sort unsupported
609     if (sr_req->sort_type != Z_SRW_sort_type_none)
610     {
611         send_z3950_present = false;
612         yaz_add_srw_diagnostic(odr_en,
613                                &(sru_pdu_res->u.response->diagnostics), 
614                                &(sru_pdu_res->u.response->num_diagnostics), 
615                                80, 0);
616     }
617     
618     // exit on all these above diagnostics
619     if (!send_z3950_present)
620         return false;
621
622
623     // z3950'fy start record position
624     if (sr_req->startRecord)
625         *(apdu->u.presentRequest->resultSetStartPoint) 
626             = *(sr_req->startRecord);
627     else 
628         *(apdu->u.presentRequest->resultSetStartPoint) = 1;
629     
630     // z3950'fy number of records requested 
631     if (sr_req->maximumRecords)
632         *(apdu->u.presentRequest->numberOfRecordsRequested) 
633             = *(sr_req->maximumRecords);
634      
635     // TODO: recordPacking
636
637     // TODO: z3950'fy record schema
638     //if (sr_req->recordSchema)
639     //    *(apdu->u.presentRequest->preferredRecordSyntax) 
640     //        = *(sr_req->recordSchema);  
641
642     // TODO: z3950'fy time to live
643     //if (sr_req->resultSetTTL)
644
645
646
647
648     z3950_package.request() = apdu;
649
650     //std::cout << "z3950_present_request " << *apdu << "\n";   
651     z3950_package.move();
652
653     //TODO: check success condition
654     Z_GDU *z3950_gdu = z3950_package.response().get();
655     if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 
656         && z3950_gdu->u.z3950->which == Z_APDU_presentResponse)
657
658     {
659         //std::cout << "z3950_present_request OK\n";
660
661         Z_PresentResponse *pr = z3950_gdu->u.z3950->u.presentResponse;
662         if (pr)
663         {
664
665             // srw'fy number of returned records
666             //sru_pdu_res->u.response->num_records 
667             //    = *(pr->numberOfRecordsReturned);
668             //= (int *) odr_malloc(odr_en, sizeof(int *));
669             //*(sru_pdu_res->u.response->num_records) 
670             //    = *(pr->numberOfRecordsReturned);
671
672             // srw'fy nextRecordPosition
673             //if (! sru_pdu_res->u.response->nextRecordPosition)
674             sru_pdu_res->u.response->nextRecordPosition 
675                 = (int *) odr_malloc(odr_en, sizeof(int *));
676             *(sru_pdu_res->u.response->nextRecordPosition) 
677                 = *(pr->nextResultSetPosition);
678         }
679         return true;
680     }
681
682     return false;
683 }
684
685 bool 
686 yf::SRUtoZ3950::Rep::z3950_scan_request(mp::Package &package,
687                                         mp::odr &odr_en,
688                                         Z_SRW_PDU *sru_pdu_res,
689                                         Z_SRW_scanRequest const *sr_req) const 
690 {
691     Package z3950_package(package.session(), package.origin());
692     z3950_package.copy_filter(package); 
693     //mp::odr odr_en(ODR_ENCODE);
694     Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_scanRequest);
695
696     //TODO: add stuff in apdu
697     Z_ScanRequest *z_scanRequest = apdu->u.scanRequest;
698
699     // database repackaging
700     z_scanRequest->num_databaseNames = 1;
701     z_scanRequest->databaseNames = (char**)
702         odr_malloc(odr_en, sizeof(char *));
703     if (sr_req->database)
704         z_scanRequest->databaseNames[0] 
705             = odr_strdup(odr_en, const_cast<char *>(sr_req->database));
706     else
707         z_scanRequest->databaseNames[0] 
708             = odr_strdup(odr_en, "Default");
709
710
711     // query repackaging
712     // CQL or XCQL scan is not possible in Z3950, flagging a diagnostic
713     if (sr_req->query_type != Z_SRW_query_type_pqf)
714     {        
715         //send_to_srw_client_error(7, "query");
716         return false;
717     }
718
719     // PQF query repackaging
720     // need to use Z_AttributesPlusTerm structure, not Z_Query
721     // this can be digget out of a 
722     // Z_query->type1(Z_RPNQuery)->RPNStructure(Z_RPNStructure)
723     //   ->u.simple(Z_Operand)->u.attributesPlusTerm(Z_AttributesPlusTerm )
724
725     //Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query));
726     //z_searchRequest->query = z_query;
727
728     //if (!z3950_build_query(odr_en, z_query, 
729     //                       (const SRW_query&)sr_req->query, 
730     //                       sr_req->query_type))
731     //{    
732         //send_to_srw_client_error(7, "query");
733     //    return false;
734     //}
735
736     // TODO: 
737
738     z3950_package.request() = apdu;
739     std::cout << "z3950_scan_request " << *apdu << "\n";   
740
741     z3950_package.move();
742     //TODO: check success condition
743     return true;
744     return false;
745 }
746
747 bool yf::SRUtoZ3950::Rep::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, 
748                                             const SRW_query &query, 
749                                             SRW_query_type query_type) const
750 {        
751     if (query_type == Z_SRW_query_type_cql)
752     {
753         Z_External *ext = (Z_External *) 
754             odr_malloc(odr_en, sizeof(*ext));
755         ext->direct_reference = 
756             odr_getoidbystr(odr_en, "1.2.840.10003.16.2");
757         ext->indirect_reference = 0;
758         ext->descriptor = 0;
759         ext->which = Z_External_CQL;
760         ext->u.cql = const_cast<char *>(query.cql);
761         
762         z_query->which = Z_Query_type_104;
763         z_query->u.type_104 =  ext;
764         return true;
765     }
766
767     if (query_type == Z_SRW_query_type_pqf)
768     {
769         Z_RPNQuery *RPNquery;
770         YAZ_PQF_Parser pqf_parser;
771         
772         pqf_parser = yaz_pqf_create ();
773         
774         RPNquery = yaz_pqf_parse (pqf_parser, odr_en, query.pqf);
775         if (!RPNquery)
776         {
777             std::cout << "TODO: Handeling of bad PQF\n";
778             std::cout << "TODO: Diagnostic to be send\n";
779         }
780         z_query->which = Z_Query_type_1;
781         z_query->u.type_1 =  RPNquery;
782         
783         yaz_pqf_destroy(pqf_parser);
784         return true;
785     }
786     return false;
787 }
788
789
790 std::string 
791 yf::SRUtoZ3950::Rep::sru_protocol(const Z_HTTP_Request &http_req) const
792 {
793     const std::string mime_urlencoded("application/x-www-form-urlencoded");
794     const std::string mime_text_xml("text/xml");
795     const std::string mime_soap_xml("application/soap+xml");
796
797     const std::string http_method(http_req.method);
798     const std::string http_type 
799         =  http_header_value(http_req.headers, "Content-Type");
800
801     if (http_method == "GET")
802         return "SRU GET";
803
804     if (http_method == "POST"
805               && http_type  == mime_urlencoded)
806         return "SRU POST";
807     
808     if ( http_method == "POST"
809          && (http_type  == mime_text_xml
810              || http_type  == mime_soap_xml))
811         return "SRU SOAP";
812
813     return "HTTP";
814 }
815
816 std::string 
817 yf::SRUtoZ3950::Rep::debug_http(const Z_HTTP_Request &http_req) const
818 {
819     std::string message("<html>\n<body>\n<h1>"
820                         "Metaproxy SRUtoZ3950 filter"
821                         "</h1>\n");
822     
823     message += "<h3>HTTP Info</h3><br/>\n";
824     message += "<p>\n";
825     message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
826     message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
827     message += "<b>Path:   </b> " + std::string(http_req.path) + "<br/>\n";
828
829     message += "<b>Content-Type:</b>"
830         + http_header_value(http_req.headers, "Content-Type")
831         + "<br/>\n";
832     message += "<b>Content-Length:</b>"
833         + http_header_value(http_req.headers, "Content-Length")
834         + "<br/>\n";
835     message += "</p>\n";    
836     
837     message += "<h3>Headers</h3><br/>\n";
838     message += "<p>\n";    
839     Z_HTTP_Header* header = http_req.headers;
840     while (header){
841         message += "<b>Header: </b> <i>" 
842             + std::string(header->name) + ":</i> "
843             + std::string(header->value) + "<br/>\n";
844         header = header->next;
845     }
846     message += "</p>\n";    
847     message += "</body>\n</html>\n";
848     return message;
849 }
850
851 void yf::SRUtoZ3950::Rep::http_response(metaproxy_1::Package &package, 
852                                         const std::string &content, 
853                                         int http_code) const
854 {
855
856     Z_GDU *zgdu_req = package.request().get(); 
857     Z_GDU *zgdu_res = 0; 
858     mp::odr odr;
859     zgdu_res 
860        = odr.create_HTTP_Response(package.session(), 
861                                   zgdu_req->u.HTTP_Request, 
862                                   http_code);
863         
864     zgdu_res->u.HTTP_Response->content_len = content.size();
865     zgdu_res->u.HTTP_Response->content_buf 
866         = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
867     
868     strncpy(zgdu_res->u.HTTP_Response->content_buf, 
869             content.c_str(),  zgdu_res->u.HTTP_Response->content_len);
870     
871     //z_HTTP_header_add(odr, &hres->headers,
872     //                  "Content-Type", content_type.c_str());
873     package.response() = zgdu_res;
874 }
875
876
877
878
879 static mp::filter::Base* filter_creator()
880 {
881     return new mp::filter::SRUtoZ3950;
882 }
883
884 extern "C" {
885     struct metaproxy_1_filter_struct metaproxy_1_filter_sru_to_z3950 = {
886         0,
887         "SRUtoZ3950",
888         filter_creator
889     };
890 }
891
892
893 /*
894  * Local variables:
895  * c-basic-offset: 4
896  * indent-tabs-mode: nil
897  * c-file-style: "stroustrup"
898  * End:
899  * vim: shiftwidth=4 tabstop=8 expandtab
900  */