metaproxy 1.22.4
sru_util.cpp
Go to the documentation of this file.
1/* This file is part of Metaproxy.
2 Copyright (C) Index Data
3
4Metaproxy is free software; you can redistribute it and/or modify it under
5the terms of the GNU General Public License as published by the Free
6Software Foundation; either version 2, or (at your option) any later
7version.
8
9Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "sru_util.hpp"
20#include <metaproxy/util.hpp>
21
22#include <iostream>
23#include <string>
24
25namespace mp = metaproxy_1;
26
27// Doxygen doesn't like mp::gdu, so we use this instead
28namespace mp_util = metaproxy_1::util;
29
30const std::string xmlns_explain("http://explain.z3950.org/dtd/2.0/");
31
32bool mp_util::build_sru_debug_package(mp::Package &package)
33{
34 Z_GDU *zgdu_req = package.request().get();
35 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
36 {
37 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
38 std::string content = mp_util::http_headers_debug(*http_req);
39 int http_code = 400;
40 mp_util::http_response(package, content, http_code);
41 return true;
42 }
43 package.session().close();
44 return false;
45}
46
48{
50
51 // getting host and port info
52 sruinfo.host = "localhost";
53 sruinfo.port = "80";
54
55 // overwriting host and port info if set from HTTP Host header
56 Z_GDU *zgdu_req = package.request().get();
57 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
58 {
59 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
60 if (http_req)
61 {
62 std::string http_path = http_req->path;
63
64 // taking out GET parameters
65 std::string::size_type ipath = http_path.rfind("?");
66 if (ipath != std::string::npos)
67 http_path.assign(http_path, 0, ipath);
68
69 // assign to database name
70 if (http_path.size() > 1)
71 sruinfo.database.assign(http_path, 1, std::string::npos);
72
73 std::string http_host_address
74 = mp_util::http_header_value(http_req->headers, "Host");
75
76 std::string::size_type iaddress = http_host_address.rfind(":");
77 if (iaddress != std::string::npos)
78 {
79 sruinfo.host.assign(http_host_address, 0, iaddress);
80 sruinfo.port.assign(http_host_address, iaddress + 1,
81 std::string::npos);
82 }
83 }
84 }
85 return sruinfo;
86}
87
88
89void mp_util::build_sru_explain(metaproxy_1::Package &package,
90 metaproxy_1::odr &odr_en,
91 Z_SRW_PDU *sru_pdu_res,
92 SRUServerInfo sruinfo,
93 const xmlNode *explain,
94 Z_SRW_explainRequest const *er_req)
95{
96 // z3950'fy recordPacking
97 int record_packing = Z_SRW_recordPacking_XML;
98 if (er_req && er_req->recordPacking && 's' == *(er_req->recordPacking))
99 record_packing = Z_SRW_recordPacking_string;
100
101 // preparing explain record insert
102 Z_SRW_explainResponse *sru_res = sru_pdu_res->u.explain_response;
103
104 // inserting one and only explain record
105 sru_res->record.recordPosition = odr_intdup(odr_en, 1);
106 sru_res->record.recordPacking = record_packing;
107 sru_res->record.recordSchema = odr_strdup(odr_en, xmlns_explain.c_str());
108
109 if (explain == 0 || explain->doc == 0)
110 {
111 std::string explain_xml
112 = mp_util::to_string(
113 "<explain xmlns=\"" + xmlns_explain + "\">\n"
114 " <serverInfo protocol='SRU'>\n"
115 " <host>")
116 + sruinfo.host
117 + mp_util::to_string("</host>\n"
118 " <port>")
119 + sruinfo.port
120 + mp_util::to_string("</port>\n"
121 " <database>")
122 + sruinfo.database
123 + mp_util::to_string("</database>\n"
124 " </serverInfo>\n"
125 "</explain>\n");
126
127 sru_res->record.recordData_len = explain_xml.size();
128 sru_res->record.recordData_buf = odr_strdup(odr_en, explain_xml.c_str());
129 }
130 else
131 {
132 xmlNode *tmp = xmlCopyNode((xmlNode *) explain, 1);
133 xmlBufferPtr buf = xmlBufferCreate();
134 xmlNodeDump(buf, tmp->doc, tmp, 2, 1);
135 xmlFreeNode(tmp);
136 sru_res->record.recordData_len = xmlBufferLength(buf);
137 sru_res->record.recordData_buf =
138 odr_strdupn(odr_en, (const char *) xmlBufferContent(buf), xmlBufferLength(buf));
139 xmlBufferFree(buf);
140 }
141}
142
143bool mp_util::build_sru_response(mp::Package &package,
144 mp::odr &odr_en,
145 Z_SOAP *soap,
146 const Z_SRW_PDU *sru_pdu_res,
147 char *charset,
148 const char *stylesheet)
149{
150 Z_GDU *zgdu_req = package.request().get();
151 if (zgdu_req && zgdu_req->which != Z_GDU_HTTP_Request)
152 {
153 package.session().close();
154 return false;
155 }
156
157 Z_GDU *zgdu_res //= z_get_HTTP_Response(odr_en, 200);
158 = odr_en.create_HTTP_Response(package.session(),
159 zgdu_req->u.HTTP_Request,
160 200);
161
162 // adding HTTP response code and headers
163 Z_HTTP_Response * http_res = zgdu_res->u.HTTP_Response;
164 //http_res->code = http_code;
165
166 std::string ctype("text/xml");
167 if (charset)
168 {
169 ctype += "; charset=";
170 ctype += charset;
171 }
172
173 z_HTTP_header_add(odr_en,
174 &http_res->headers, "Content-Type", ctype.c_str());
175
176 // packaging Z_SOAP into HTML response
177 static Z_SOAP_Handler soap_handlers[4] = {
178 {(char *)YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
179 {(char *)YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec},
180 {(char *)YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
181 {0, 0, 0}
182 };
183
184
185 // empty stylesheet means NO stylesheet
186 if (stylesheet && *stylesheet == '\0')
187 stylesheet = 0;
188
189 // encoding SRU package
190 soap->u.generic->p = (void*) sru_pdu_res;
191 //int ret =
192 z_soap_codec_enc_xsl(odr_en, &soap,
193 &http_res->content_buf, &http_res->content_len,
194 soap_handlers, charset, stylesheet);
195
196 package.response() = zgdu_res;
197 return true;
198}
199
200
201Z_SRW_PDU * mp_util::decode_sru_request(mp::Package &package,
202 mp::odr &odr_de,
203 mp::odr &odr_en,
204 Z_SRW_diagnostic **diagnostic,
205 int *num_diagnostic,
206 Z_SOAP **soap,
207 char *charset)
208{
209 Z_GDU *zgdu_req = package.request().get();
210 Z_SRW_PDU *sru_pdu_req = 0;
211
212 //assert((zgdu_req->which == Z_GDU_HTTP_Request));
213
214 //ignoring all non HTTP_Request packages
215 if (zgdu_req == 0 || zgdu_req->which != Z_GDU_HTTP_Request)
216 return 0;
217
218 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
219 if (! http_req)
220 return 0;
221
222 // checking if we got a SRU GET/POST/SOAP HTTP package
223 // closing connection if we did not ...
224 if (0 == yaz_sru_decode(http_req, &sru_pdu_req, soap,
225 odr_de, &charset,
226 diagnostic, num_diagnostic))
227 {
228 return sru_pdu_req;
229 }
230 else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, soap,
231 odr_de, &charset))
232 {
233 return sru_pdu_req;
234 }
235 package.session().close();
236 return 0;
237}
238
239
240bool
241mp_util::check_sru_query_exists(mp::Package &package,
242 mp::odr &odr_en,
243 Z_SRW_PDU *sru_pdu_res,
244 Z_SRW_searchRetrieveRequest const *sr_req)
245{
246 if (sr_req->query)
247 return true;
248 yaz_add_srw_diagnostic(odr_en,
249 &(sru_pdu_res->u.response->diagnostics),
250 &(sru_pdu_res->u.response->num_diagnostics),
251 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED,
252 "query");
253 yaz_add_srw_diagnostic(odr_en,
254 &(sru_pdu_res->u.response->diagnostics),
255 &(sru_pdu_res->u.response->num_diagnostics),
256 YAZ_SRW_QUERY_SYNTAX_ERROR,
257 "CQL query is empty");
258 return false;
259}
260
261
262Z_ElementSetNames *
263mp_util::build_esn_from_schema(mp::odr &odr_en, const char *schema)
264{
265 if (!schema)
266 return 0;
267
268 Z_ElementSetNames *esn
269 = (Z_ElementSetNames *) odr_malloc(odr_en, sizeof(Z_ElementSetNames));
270 esn->which = Z_ElementSetNames_generic;
271 esn->u.generic = odr_strdup(odr_en, schema);
272 return esn;
273}
274
275
276std::ostream& std::operator<<(std::ostream& os, Z_SRW_PDU& srw_pdu)
277{
278 os << "SRU";
279
280 switch (srw_pdu.which)
281 {
282 case Z_SRW_searchRetrieve_request:
283 os << " " << "searchRetrieveRequest";
284 {
285 Z_SRW_searchRetrieveRequest *sr = srw_pdu.u.request;
286 if (sr)
287 {
288 if (sr->database)
289 os << " " << (sr->database);
290 else
291 os << " -";
292 if (sr->startRecord)
293 os << " " << *(sr->startRecord);
294 else
295 os << " -";
296 if (sr->maximumRecords)
297 os << " " << *(sr->maximumRecords);
298 else
299 os << " -";
300 if (sr->recordPacking)
301 os << " " << (sr->recordPacking);
302 else
303 os << " -";
304
305 if (sr->recordSchema)
306 os << " " << (sr->recordSchema);
307 else
308 os << " -";
309 os << " " << (sr->queryType ? sr->queryType : "cql")
310 << " " << sr->query;
311 }
312 }
313 break;
314 case Z_SRW_searchRetrieve_response:
315 os << " " << "searchRetrieveResponse";
316 {
317 Z_SRW_searchRetrieveResponse *sr = srw_pdu.u.response;
318 if (sr)
319 {
320 if (! (sr->num_diagnostics))
321 {
322 os << " OK";
323 if (sr->numberOfRecords)
324 os << " " << *(sr->numberOfRecords);
325 else
326 os << " -";
327 //if (sr->num_records)
328 os << " " << (sr->num_records);
329 //else
330 //os << " -";
331 if (sr->nextRecordPosition)
332 os << " " << *(sr->nextRecordPosition);
333 else
334 os << " -";
335 }
336 else
337 {
338 os << " DIAG";
339 if (sr->diagnostics && sr->diagnostics->uri)
340 os << " " << (sr->diagnostics->uri);
341 else
342 os << " -";
343 if (sr->diagnostics && sr->diagnostics->message)
344 os << " " << (sr->diagnostics->message);
345 else
346 os << " -";
347 if (sr->diagnostics && sr->diagnostics->details)
348 os << " " << (sr->diagnostics->details);
349 else
350 os << " -";
351 }
352
353
354 }
355 }
356 break;
357 case Z_SRW_explain_request:
358 os << " " << "explainRequest";
359 break;
360 case Z_SRW_explain_response:
361 os << " " << "explainResponse";
362 break;
363 case Z_SRW_scan_request:
364 os << " " << "scanRequest";
365 break;
366 case Z_SRW_scan_response:
367 os << " " << "scanResponse";
368 break;
369 case Z_SRW_update_request:
370 os << " " << "updateRequest";
371 break;
372 case Z_SRW_update_response:
373 os << " " << "updateResponse";
374 break;
375 default:
376 os << " " << "UNKNOWN";
377 }
378
379 return os;
380}
381
382/*
383 * Local variables:
384 * c-basic-offset: 4
385 * c-file-style: "Stroustrup"
386 * indent-tabs-mode: nil
387 * End:
388 * vim: shiftwidth=4 tabstop=8 expandtab
389 */
390
Z_SRW_PDU * decode_sru_request(metaproxy_1::Package &package, metaproxy_1::odr &odr_de, metaproxy_1::odr &odr_en, Z_SRW_diagnostic **diagnostic, int *num_diagnostic, Z_SOAP **soap, char *charset)
bool build_sru_debug_package(metaproxy_1::Package &package)
SRUServerInfo get_sru_server_info(metaproxy_1::Package &package)
bool build_sru_response(metaproxy_1::Package &package, metaproxy_1::odr &odr_en, Z_SOAP *soap, const Z_SRW_PDU *sru_pdu_res, char *charset, const char *stylesheet)
Z_ElementSetNames * build_esn_from_schema(metaproxy_1::odr &odr_en, const char *schema)
bool check_sru_query_exists(metaproxy_1::Package &package, metaproxy_1::odr &odr_en, Z_SRW_PDU *sru_pdu_res, Z_SRW_searchRetrieveRequest const *sr_req)
void build_sru_explain(metaproxy_1::Package &package, metaproxy_1::odr &odr_en, Z_SRW_PDU *sru_pdu_res, SRUServerInfo sruinfo, const xmlNode *explain=0, Z_SRW_explainRequest const *er_req=0)
Definition sru_util.cpp:89
std::ostream & operator<<(std::ostream &os, Z_GDU &zgdu)
Definition gduutil.cpp:33
const std::string xmlns_explain("http://explain.z3950.org/dtd/2.0/")