metaproxy 1.22.1
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 = buf->use;
137 sru_res->record.recordData_buf = odr_strdupn(odr_en, (const char *) buf->content, buf->use);
138 xmlBufferFree(buf);
139 }
140}
141
142bool mp_util::build_sru_response(mp::Package &package,
143 mp::odr &odr_en,
144 Z_SOAP *soap,
145 const Z_SRW_PDU *sru_pdu_res,
146 char *charset,
147 const char *stylesheet)
148{
149 Z_GDU *zgdu_req = package.request().get();
150 if (zgdu_req && zgdu_req->which != Z_GDU_HTTP_Request)
151 {
152 package.session().close();
153 return false;
154 }
155
156 Z_GDU *zgdu_res //= z_get_HTTP_Response(odr_en, 200);
157 = odr_en.create_HTTP_Response(package.session(),
158 zgdu_req->u.HTTP_Request,
159 200);
160
161 // adding HTTP response code and headers
162 Z_HTTP_Response * http_res = zgdu_res->u.HTTP_Response;
163 //http_res->code = http_code;
164
165 std::string ctype("text/xml");
166 if (charset)
167 {
168 ctype += "; charset=";
169 ctype += charset;
170 }
171
172 z_HTTP_header_add(odr_en,
173 &http_res->headers, "Content-Type", ctype.c_str());
174
175 // packaging Z_SOAP into HTML response
176 static Z_SOAP_Handler soap_handlers[4] = {
177 {(char *)YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
178 {(char *)YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec},
179 {(char *)YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
180 {0, 0, 0}
181 };
182
183
184 // empty stylesheet means NO stylesheet
185 if (stylesheet && *stylesheet == '\0')
186 stylesheet = 0;
187
188 // encoding SRU package
189 soap->u.generic->p = (void*) sru_pdu_res;
190 //int ret =
191 z_soap_codec_enc_xsl(odr_en, &soap,
192 &http_res->content_buf, &http_res->content_len,
193 soap_handlers, charset, stylesheet);
194
195 package.response() = zgdu_res;
196 return true;
197}
198
199
200Z_SRW_PDU * mp_util::decode_sru_request(mp::Package &package,
201 mp::odr &odr_de,
202 mp::odr &odr_en,
203 Z_SRW_diagnostic **diagnostic,
204 int *num_diagnostic,
205 Z_SOAP **soap,
206 char *charset)
207{
208 Z_GDU *zgdu_req = package.request().get();
209 Z_SRW_PDU *sru_pdu_req = 0;
210
211 //assert((zgdu_req->which == Z_GDU_HTTP_Request));
212
213 //ignoring all non HTTP_Request packages
214 if (zgdu_req == 0 || zgdu_req->which != Z_GDU_HTTP_Request)
215 return 0;
216
217 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
218 if (! http_req)
219 return 0;
220
221 // checking if we got a SRU GET/POST/SOAP HTTP package
222 // closing connection if we did not ...
223 if (0 == yaz_sru_decode(http_req, &sru_pdu_req, soap,
224 odr_de, &charset,
225 diagnostic, num_diagnostic))
226 {
227 return sru_pdu_req;
228 }
229 else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, soap,
230 odr_de, &charset))
231 {
232 return sru_pdu_req;
233 }
234 package.session().close();
235 return 0;
236}
237
238
239bool
240mp_util::check_sru_query_exists(mp::Package &package,
241 mp::odr &odr_en,
242 Z_SRW_PDU *sru_pdu_res,
243 Z_SRW_searchRetrieveRequest const *sr_req)
244{
245 if (sr_req->query)
246 return true;
247 yaz_add_srw_diagnostic(odr_en,
248 &(sru_pdu_res->u.response->diagnostics),
249 &(sru_pdu_res->u.response->num_diagnostics),
250 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED,
251 "query");
252 yaz_add_srw_diagnostic(odr_en,
253 &(sru_pdu_res->u.response->diagnostics),
254 &(sru_pdu_res->u.response->num_diagnostics),
255 YAZ_SRW_QUERY_SYNTAX_ERROR,
256 "CQL query is empty");
257 return false;
258}
259
260
261Z_ElementSetNames *
262mp_util::build_esn_from_schema(mp::odr &odr_en, const char *schema)
263{
264 if (!schema)
265 return 0;
266
267 Z_ElementSetNames *esn
268 = (Z_ElementSetNames *) odr_malloc(odr_en, sizeof(Z_ElementSetNames));
269 esn->which = Z_ElementSetNames_generic;
270 esn->u.generic = odr_strdup(odr_en, schema);
271 return esn;
272}
273
274
275std::ostream& std::operator<<(std::ostream& os, Z_SRW_PDU& srw_pdu)
276{
277 os << "SRU";
278
279 switch (srw_pdu.which)
280 {
281 case Z_SRW_searchRetrieve_request:
282 os << " " << "searchRetrieveRequest";
283 {
284 Z_SRW_searchRetrieveRequest *sr = srw_pdu.u.request;
285 if (sr)
286 {
287 if (sr->database)
288 os << " " << (sr->database);
289 else
290 os << " -";
291 if (sr->startRecord)
292 os << " " << *(sr->startRecord);
293 else
294 os << " -";
295 if (sr->maximumRecords)
296 os << " " << *(sr->maximumRecords);
297 else
298 os << " -";
299 if (sr->recordPacking)
300 os << " " << (sr->recordPacking);
301 else
302 os << " -";
303
304 if (sr->recordSchema)
305 os << " " << (sr->recordSchema);
306 else
307 os << " -";
308 os << " " << (sr->queryType ? sr->queryType : "cql")
309 << " " << sr->query;
310 }
311 }
312 break;
313 case Z_SRW_searchRetrieve_response:
314 os << " " << "searchRetrieveResponse";
315 {
316 Z_SRW_searchRetrieveResponse *sr = srw_pdu.u.response;
317 if (sr)
318 {
319 if (! (sr->num_diagnostics))
320 {
321 os << " OK";
322 if (sr->numberOfRecords)
323 os << " " << *(sr->numberOfRecords);
324 else
325 os << " -";
326 //if (sr->num_records)
327 os << " " << (sr->num_records);
328 //else
329 //os << " -";
330 if (sr->nextRecordPosition)
331 os << " " << *(sr->nextRecordPosition);
332 else
333 os << " -";
334 }
335 else
336 {
337 os << " DIAG";
338 if (sr->diagnostics && sr->diagnostics->uri)
339 os << " " << (sr->diagnostics->uri);
340 else
341 os << " -";
342 if (sr->diagnostics && sr->diagnostics->message)
343 os << " " << (sr->diagnostics->message);
344 else
345 os << " -";
346 if (sr->diagnostics && sr->diagnostics->details)
347 os << " " << (sr->diagnostics->details);
348 else
349 os << " -";
350 }
351
352
353 }
354 }
355 break;
356 case Z_SRW_explain_request:
357 os << " " << "explainRequest";
358 break;
359 case Z_SRW_explain_response:
360 os << " " << "explainResponse";
361 break;
362 case Z_SRW_scan_request:
363 os << " " << "scanRequest";
364 break;
365 case Z_SRW_scan_response:
366 os << " " << "scanResponse";
367 break;
368 case Z_SRW_update_request:
369 os << " " << "updateRequest";
370 break;
371 case Z_SRW_update_response:
372 os << " " << "updateResponse";
373 break;
374 default:
375 os << " " << "UNKNOWN";
376 }
377
378 return os;
379}
380
381/*
382 * Local variables:
383 * c-basic-offset: 4
384 * c-file-style: "Stroustrup"
385 * indent-tabs-mode: nil
386 * End:
387 * vim: shiftwidth=4 tabstop=8 expandtab
388 */
389
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/")