1 /* $Id: util.cpp,v 1.29 2007-05-09 21:23:09 adam Exp $
2 Copyright (c) 2005-2007, Index Data.
4 This file is part of Metaproxy.
6 Metaproxy is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
11 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with Metaproxy; see the file LICENSE. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 #include <yaz/pquery.h>
27 #include <yaz/otherinfo.h>
28 #include <yaz/querytowrbuf.h>
29 #include <yaz/oid_db.h>
33 namespace mp = metaproxy_1;
35 // Doxygen doesn't like mp::util, so we use this instead
36 namespace mp_util = metaproxy_1::util;
39 mp_util::record_composition_to_esn(Z_RecordComposition *comp)
41 if (comp && comp->which == Z_RecordComp_complex)
43 if (comp->u.complex->generic
44 && comp->u.complex->generic->elementSpec
45 && (comp->u.complex->generic->elementSpec->which ==
46 Z_ElementSpec_elementSetName))
47 return comp->u.complex->generic->elementSpec->u.elementSetName;
49 else if (comp && comp->which == Z_RecordComp_simple &&
50 comp->u.simple->which == Z_ElementSetNames_generic)
51 return comp->u.simple->u.generic;
57 std::string mp_util::http_header_value(const Z_HTTP_Header* header,
58 const std::string name)
60 while (header && header->name
61 && std::string(header->name) != name)
62 header = header->next;
64 if (header && header->name && std::string(header->name) == name
66 return std::string(header->value);
71 std::string mp_util::http_headers_debug(const Z_HTTP_Request &http_req)
73 std::string message("<html>\n<body>\n<h1>"
74 "Metaproxy SRUtoZ3950 filter"
77 message += "<h3>HTTP Info</h3><br/>\n";
79 message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
80 message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
81 message += "<b>Path: </b> " + std::string(http_req.path) + "<br/>\n";
83 message += "<b>Content-Type:</b>"
84 + mp_util::http_header_value(http_req.headers, "Content-Type")
86 message += "<b>Content-Length:</b>"
87 + mp_util::http_header_value(http_req.headers, "Content-Length")
91 message += "<h3>Headers</h3><br/>\n";
93 Z_HTTP_Header* header = http_req.headers;
95 message += "<b>Header: </b> <i>"
96 + std::string(header->name) + ":</i> "
97 + std::string(header->value) + "<br/>\n";
98 header = header->next;
101 message += "</body>\n</html>\n";
106 void mp_util::http_response(metaproxy_1::Package &package,
107 const std::string &content,
111 Z_GDU *zgdu_req = package.request().get();
115 = odr.create_HTTP_Response(package.session(),
116 zgdu_req->u.HTTP_Request,
119 zgdu_res->u.HTTP_Response->content_len = content.size();
120 zgdu_res->u.HTTP_Response->content_buf
121 = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
123 strncpy(zgdu_res->u.HTTP_Response->content_buf,
124 content.c_str(), zgdu_res->u.HTTP_Response->content_len);
126 //z_HTTP_header_add(odr, &hres->headers,
127 // "Content-Type", content_type.c_str());
128 package.response() = zgdu_res;
132 int mp_util::memcmp2(const void *buf1, int len1,
133 const void *buf2, int len2)
137 // compare buffer (common length)
138 int c = memcmp(buf1, buf2, d > 0 ? len2 : len1);
144 // compare (remaining bytes)
153 std::string mp_util::database_name_normalize(const std::string &s)
157 for (i = 0; i < r.length(); i++)
160 if (ch >= 'A' && ch <= 'Z')
161 r[i] = ch + 'a' - 'A';
167 void mp_util::piggyback(int smallSetUpperBound,
168 int largeSetLowerBound,
169 int mediumSetPresentNumber,
171 int &number_to_present)
173 // deal with piggyback
175 if (result_set_size < smallSetUpperBound)
177 // small set . Return all records in set
178 number_to_present = result_set_size;
180 else if (result_set_size > largeSetLowerBound)
182 // large set . Return no records
183 number_to_present = 0;
187 // medium set . Return mediumSetPresentNumber records
188 number_to_present = mediumSetPresentNumber;
189 if (number_to_present > result_set_size)
190 number_to_present = result_set_size;
195 bool mp_util::pqf(ODR odr, Z_APDU *apdu, const std::string &q)
197 YAZ_PQF_Parser pqf_parser = yaz_pqf_create();
199 Z_RPNQuery *rpn = yaz_pqf_parse(pqf_parser, odr, q.c_str());
202 yaz_pqf_destroy(pqf_parser);
205 yaz_pqf_destroy(pqf_parser);
206 Z_Query *query = (Z_Query *) odr_malloc(odr, sizeof(Z_Query));
207 query->which = Z_Query_type_1;
208 query->u.type_1 = rpn;
210 apdu->u.searchRequest->query = query;
215 std::string mp_util::zQueryToString(Z_Query *query)
217 std::string query_str = "";
219 if (query && query->which == Z_Query_type_1){
220 Z_RPNQuery *rpn = query->u.type_1;
224 // allocate wrbuf (strings in YAZ!)
225 WRBUF w = wrbuf_alloc();
228 yaz_rpnquery_to_wrbuf(w, rpn);
230 // from w to std::string
231 query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
239 if (query && query->which == Z_Query_type_1){
241 // allocate wrbuf (strings in YAZ!)
242 WRBUF w = wrbuf_alloc();
245 yaz_query_to_wrbuf(w, query);
247 // from w to std::string
248 query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
257 void mp_util::get_default_diag(Z_DefaultDiagFormat *r,
258 int &error_code, std::string &addinfo)
260 error_code = *r->condition;
263 case Z_DefaultDiagFormat_v2Addinfo:
264 addinfo = std::string(r->u.v2Addinfo);
266 case Z_DefaultDiagFormat_v3Addinfo:
267 addinfo = r->u.v3Addinfo;
272 void mp_util::get_init_diagnostics(
273 Z_InitResponse *initrs, int &error_code, std::string &addinfo)
275 Z_External *uif = initrs->userInformationField;
277 if (uif && uif->which == Z_External_userInfo1)
279 Z_OtherInformation *ui = uif->u.userInfo1;
281 for (i = 0; i < ui->num_elements; i++)
283 Z_OtherInformationUnit *unit = ui->list[i];
284 if (unit->which == Z_OtherInfo_externallyDefinedInfo &&
285 unit->information.externallyDefinedInfo &&
286 unit->information.externallyDefinedInfo->which ==
289 Z_DiagnosticFormat *diag =
290 unit->information.externallyDefinedInfo->u.diag1;
294 Z_DiagnosticFormat_s *ds = diag->elements[0];
295 if (ds->which == Z_DiagnosticFormat_s_defaultDiagRec)
296 mp::util::get_default_diag(ds->u.defaultDiagRec,
297 error_code, addinfo);
304 int mp_util::get_or_remove_vhost_otherinfo(
305 Z_OtherInformation **otherInformation,
307 std::list<std::string> &vhosts)
310 for (cat = 1; ; cat++)
312 // check virtual host
314 yaz_oi_get_string_oid(otherInformation,
315 yaz_oid_userinfo_proxy,
316 cat /* categoryValue */,
317 remove_flag /* delete flag */);
320 vhosts.push_back(std::string(vhost));
326 void mp_util::get_vhost_otherinfo(
327 Z_OtherInformation *otherInformation,
328 std::list<std::string> &vhosts)
330 get_or_remove_vhost_otherinfo(&otherInformation, false, vhosts);
333 int mp_util::remove_vhost_otherinfo(
334 Z_OtherInformation **otherInformation,
335 std::list<std::string> &vhosts)
337 return get_or_remove_vhost_otherinfo(otherInformation, true, vhosts);
340 void mp_util::set_vhost_otherinfo(
341 Z_OtherInformation **otherInformation, ODR odr,
342 const std::list<std::string> &vhosts)
345 std::list<std::string>::const_iterator it = vhosts.begin();
347 for (cat = 1; it != vhosts.end() ; cat++, it++)
349 yaz_oi_set_string_oid(otherInformation, odr,
350 yaz_oid_userinfo_proxy, cat, it->c_str());
354 void mp_util::set_vhost_otherinfo(
355 Z_OtherInformation **otherInformation, ODR odr,
356 const std::string vhost, const int cat)
358 yaz_oi_set_string_oid(otherInformation, odr,
359 yaz_oid_userinfo_proxy, cat, vhost.c_str());
362 void mp_util::split_zurl(std::string zurl, std::string &host,
363 std::list<std::string> &db)
365 const char *zurl_cstr = zurl.c_str();
366 const char *sep = strchr(zurl_cstr, '/');
370 host = std::string(zurl_cstr, sep - zurl_cstr);
372 const char *cp1 = sep+1;
375 const char *cp2 = strchr(cp1, '+');
377 db.push_back(std::string(cp1, cp2 - cp1));
380 db.push_back(std::string(cp1));
392 bool mp_util::set_databases_from_zurl(
393 ODR odr, std::string zurl,
394 int *db_num, char ***db_strings)
397 std::list<std::string> dblist;
399 split_zurl(zurl, host, dblist);
401 if (dblist.size() == 0)
403 *db_num = dblist.size();
404 *db_strings = (char **) odr_malloc(odr, sizeof(char*) * (*db_num));
406 std::list<std::string>::const_iterator it = dblist.begin();
407 for (int i = 0; it != dblist.end(); it++, i++)
408 (*db_strings)[i] = odr_strdup(odr, it->c_str());
412 mp::odr::odr(int type)
414 m_odr = odr_createmem(type);
419 m_odr = odr_createmem(ODR_ENCODE);
427 mp::odr::operator ODR() const
432 Z_APDU *mp::odr::create_close(const Z_APDU *in_apdu,
433 int reason, const char *addinfo)
435 Z_APDU *apdu = create_APDU(Z_APDU_close, in_apdu);
437 *apdu->u.close->closeReason = reason;
439 apdu->u.close->diagnosticInformation = odr_strdup(m_odr, addinfo);
443 Z_APDU *mp::odr::create_APDU(int type, const Z_APDU *in_apdu)
445 return mp::util::create_APDU(m_odr, type, in_apdu);
448 Z_APDU *mp_util::create_APDU(ODR odr, int type, const Z_APDU *in_apdu)
450 Z_APDU *out_apdu = zget_APDU(odr, type);
451 transfer_referenceId(odr, in_apdu, out_apdu);
455 void mp_util::transfer_referenceId(ODR odr, const Z_APDU *src, Z_APDU *dst)
457 Z_ReferenceId **id_to = mp::util::get_referenceId(dst);
461 Z_ReferenceId **id_from = mp::util::get_referenceId(src);
462 if (id_from && *id_from && id_to)
464 *id_to = (Z_ReferenceId*) odr_malloc (odr, sizeof(**id_to));
465 (*id_to)->size = (*id_to)->len = (*id_from)->len;
466 (*id_to)->buf = (unsigned char*) odr_malloc(odr, (*id_to)->len);
467 memcpy((*id_to)->buf, (*id_from)->buf, (*id_to)->len);
474 Z_APDU *mp::odr::create_initResponse(const Z_APDU *in_apdu,
475 int error, const char *addinfo)
477 Z_APDU *apdu = create_APDU(Z_APDU_initResponse, in_apdu);
480 apdu->u.initResponse->userInformationField =
481 zget_init_diagnostics(m_odr, error, addinfo);
482 *apdu->u.initResponse->result = 0;
487 Z_APDU *mp::odr::create_searchResponse(const Z_APDU *in_apdu,
488 int error, const char *addinfo)
490 Z_APDU *apdu = create_APDU(Z_APDU_searchResponse, in_apdu);
493 Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
494 *apdu->u.searchResponse->searchStatus = 0;
495 apdu->u.searchResponse->records = rec;
496 rec->which = Z_Records_NSD;
497 rec->u.nonSurrogateDiagnostic =
498 zget_DefaultDiagFormat(m_odr, error, addinfo);
504 Z_APDU *mp::odr::create_presentResponse(const Z_APDU *in_apdu,
505 int error, const char *addinfo)
507 Z_APDU *apdu = create_APDU(Z_APDU_presentResponse, in_apdu);
510 Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
511 apdu->u.presentResponse->records = rec;
513 rec->which = Z_Records_NSD;
514 rec->u.nonSurrogateDiagnostic =
515 zget_DefaultDiagFormat(m_odr, error, addinfo);
516 *apdu->u.presentResponse->presentStatus = Z_PresentStatus_failure;
521 Z_APDU *mp::odr::create_scanResponse(const Z_APDU *in_apdu,
522 int error, const char *addinfo)
524 Z_APDU *apdu = create_APDU(Z_APDU_scanResponse, in_apdu);
525 Z_ScanResponse *res = apdu->u.scanResponse;
526 res->entries = (Z_ListEntries *) odr_malloc(m_odr, sizeof(*res->entries));
527 res->entries->num_entries = 0;
528 res->entries->entries = 0;
532 *res->scanStatus = Z_Scan_failure;
534 res->entries->num_nonsurrogateDiagnostics = 1;
535 res->entries->nonsurrogateDiagnostics = (Z_DiagRec **)
536 odr_malloc(m_odr, sizeof(Z_DiagRec *));
537 res->entries->nonsurrogateDiagnostics[0] =
538 zget_DiagRec(m_odr, error, addinfo);
542 res->entries->num_nonsurrogateDiagnostics = 0;
543 res->entries->nonsurrogateDiagnostics = 0;
548 Z_GDU *mp::odr::create_HTTP_Response(mp::Session &session,
549 Z_HTTP_Request *hreq, int code)
551 const char *response_version = "1.0";
552 bool keepalive = false;
553 if (!strcmp(hreq->version, "1.0"))
555 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
556 if (v && !strcmp(v, "Keep-Alive"))
560 response_version = "1.0";
564 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
565 if (v && !strcmp(v, "close"))
569 response_version = "1.1";
572 Z_GDU *gdu = z_get_HTTP_Response(m_odr, code);
573 Z_HTTP_Response *hres = gdu->u.HTTP_Response;
574 hres->version = odr_strdup(m_odr, response_version);
576 z_HTTP_header_add(m_odr, &hres->headers, "Connection", "Keep-Alive");
581 Z_ReferenceId **mp_util::get_referenceId(const Z_APDU *apdu)
585 case Z_APDU_initRequest:
586 return &apdu->u.initRequest->referenceId;
587 case Z_APDU_initResponse:
588 return &apdu->u.initResponse->referenceId;
589 case Z_APDU_searchRequest:
590 return &apdu->u.searchRequest->referenceId;
591 case Z_APDU_searchResponse:
592 return &apdu->u.searchResponse->referenceId;
593 case Z_APDU_presentRequest:
594 return &apdu->u.presentRequest->referenceId;
595 case Z_APDU_presentResponse:
596 return &apdu->u.presentResponse->referenceId;
597 case Z_APDU_deleteResultSetRequest:
598 return &apdu->u.deleteResultSetRequest->referenceId;
599 case Z_APDU_deleteResultSetResponse:
600 return &apdu->u.deleteResultSetResponse->referenceId;
601 case Z_APDU_accessControlRequest:
602 return &apdu->u.accessControlRequest->referenceId;
603 case Z_APDU_accessControlResponse:
604 return &apdu->u.accessControlResponse->referenceId;
605 case Z_APDU_resourceControlRequest:
606 return &apdu->u.resourceControlRequest->referenceId;
607 case Z_APDU_resourceControlResponse:
608 return &apdu->u.resourceControlResponse->referenceId;
609 case Z_APDU_triggerResourceControlRequest:
610 return &apdu->u.triggerResourceControlRequest->referenceId;
611 case Z_APDU_resourceReportRequest:
612 return &apdu->u.resourceReportRequest->referenceId;
613 case Z_APDU_resourceReportResponse:
614 return &apdu->u.resourceReportResponse->referenceId;
615 case Z_APDU_scanRequest:
616 return &apdu->u.scanRequest->referenceId;
617 case Z_APDU_scanResponse:
618 return &apdu->u.scanResponse->referenceId;
619 case Z_APDU_sortRequest:
620 return &apdu->u.sortRequest->referenceId;
621 case Z_APDU_sortResponse:
622 return &apdu->u.sortResponse->referenceId;
623 case Z_APDU_segmentRequest:
624 return &apdu->u.segmentRequest->referenceId;
625 case Z_APDU_extendedServicesRequest:
626 return &apdu->u.extendedServicesRequest->referenceId;
627 case Z_APDU_extendedServicesResponse:
628 return &apdu->u.extendedServicesResponse->referenceId;
630 return &apdu->u.close->referenceId;
639 * indent-tabs-mode: nil
640 * c-file-style: "stroustrup"
642 * vim: shiftwidth=4 tabstop=8 expandtab