1 /* $Id: util.cpp,v 1.21 2006-10-02 13:44:48 marc Exp $
2 Copyright (c) 2005-2006, Index Data.
4 See the LICENSE file for details
11 #include <yaz/pquery.h>
12 #include <yaz/otherinfo.h>
13 #include <yaz/querytowrbuf.h> // for yaz_query_to_wrbuf()
17 namespace mp = metaproxy_1;
19 // Doxygen doesn't like mp::util, so we use this instead
20 namespace mp_util = metaproxy_1::util;
23 std::string mp_util::http_header_value(const Z_HTTP_Header* header,
24 const std::string name)
26 while (header && header->name
27 && std::string(header->name) != name)
28 header = header->next;
30 if (header && header->name && std::string(header->name) == name
32 return std::string(header->value);
37 std::string mp_util::http_headers_debug(const Z_HTTP_Request &http_req)
39 std::string message("<html>\n<body>\n<h1>"
40 "Metaproxy SRUtoZ3950 filter"
43 message += "<h3>HTTP Info</h3><br/>\n";
45 message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
46 message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
47 message += "<b>Path: </b> " + std::string(http_req.path) + "<br/>\n";
49 message += "<b>Content-Type:</b>"
50 + mp_util::http_header_value(http_req.headers, "Content-Type")
52 message += "<b>Content-Length:</b>"
53 + mp_util::http_header_value(http_req.headers, "Content-Length")
57 message += "<h3>Headers</h3><br/>\n";
59 Z_HTTP_Header* header = http_req.headers;
61 message += "<b>Header: </b> <i>"
62 + std::string(header->name) + ":</i> "
63 + std::string(header->value) + "<br/>\n";
64 header = header->next;
67 message += "</body>\n</html>\n";
72 int mp_util::memcmp2(const void *buf1, int len1,
73 const void *buf2, int len2)
77 // compare buffer (common length)
78 int c = memcmp(buf1, buf2, d > 0 ? len2 : len1);
84 // compare (remaining bytes)
93 std::string mp_util::database_name_normalize(const std::string &s)
97 for (i = 0; i < r.length(); i++)
100 if (ch >= 'A' && ch <= 'Z')
101 r[i] = ch + 'a' - 'A';
107 void mp_util::piggyback(int smallSetUpperBound,
108 int largeSetLowerBound,
109 int mediumSetPresentNumber,
111 int &number_to_present)
113 // deal with piggyback
115 if (result_set_size < smallSetUpperBound)
117 // small set . Return all records in set
118 number_to_present = result_set_size;
120 else if (result_set_size > largeSetLowerBound)
122 // large set . Return no records
123 number_to_present = 0;
127 // medium set . Return mediumSetPresentNumber records
128 number_to_present = mediumSetPresentNumber;
129 if (number_to_present > result_set_size)
130 number_to_present = result_set_size;
135 bool mp_util::pqf(ODR odr, Z_APDU *apdu, const std::string &q)
137 YAZ_PQF_Parser pqf_parser = yaz_pqf_create();
139 Z_RPNQuery *rpn = yaz_pqf_parse(pqf_parser, odr, q.c_str());
142 yaz_pqf_destroy(pqf_parser);
145 yaz_pqf_destroy(pqf_parser);
146 Z_Query *query = (Z_Query *) odr_malloc(odr, sizeof(Z_Query));
147 query->which = Z_Query_type_1;
148 query->u.type_1 = rpn;
150 apdu->u.searchRequest->query = query;
155 std::string mp_util::zQueryToString(Z_Query *query)
157 std::string query_str = "";
159 if (query && query->which == Z_Query_type_1){
160 Z_RPNQuery *rpn = query->u.type_1;
164 // allocate wrbuf (strings in YAZ!)
165 WRBUF w = wrbuf_alloc();
168 yaz_rpnquery_to_wrbuf(w, rpn);
170 // from w to std::string
171 query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
179 if (query && query->which == Z_Query_type_1){
181 // allocate wrbuf (strings in YAZ!)
182 WRBUF w = wrbuf_alloc();
185 yaz_query_to_wrbuf(w, query);
187 // from w to std::string
188 query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
197 void mp_util::get_default_diag(Z_DefaultDiagFormat *r,
198 int &error_code, std::string &addinfo)
200 error_code = *r->condition;
203 case Z_DefaultDiagFormat_v2Addinfo:
204 addinfo = std::string(r->u.v2Addinfo);
206 case Z_DefaultDiagFormat_v3Addinfo:
207 addinfo = r->u.v3Addinfo;
212 void mp_util::get_init_diagnostics(
213 Z_InitResponse *initrs, int &error_code, std::string &addinfo)
215 Z_External *uif = initrs->userInformationField;
217 if (uif && uif->which == Z_External_userInfo1)
219 Z_OtherInformation *ui = uif->u.userInfo1;
221 for (i = 0; i < ui->num_elements; i++)
223 Z_OtherInformationUnit *unit = ui->list[i];
224 if (unit->which == Z_OtherInfo_externallyDefinedInfo &&
225 unit->information.externallyDefinedInfo &&
226 unit->information.externallyDefinedInfo->which ==
229 Z_DiagnosticFormat *diag =
230 unit->information.externallyDefinedInfo->u.diag1;
234 Z_DiagnosticFormat_s *ds = diag->elements[0];
235 if (ds->which == Z_DiagnosticFormat_s_defaultDiagRec)
236 mp::util::get_default_diag(ds->u.defaultDiagRec,
237 error_code, addinfo);
244 int mp_util::get_or_remove_vhost_otherinfo(
245 Z_OtherInformation **otherInformation,
247 std::list<std::string> &vhosts)
250 for (cat = 1; ; cat++)
252 // check virtual host
254 yaz_oi_get_string_oidval(otherInformation,
256 cat /* categoryValue */,
257 remove_flag /* delete flag */);
260 vhosts.push_back(std::string(vhost));
266 void mp_util::get_vhost_otherinfo(
267 Z_OtherInformation *otherInformation,
268 std::list<std::string> &vhosts)
270 get_or_remove_vhost_otherinfo(&otherInformation, false, vhosts);
273 int mp_util::remove_vhost_otherinfo(
274 Z_OtherInformation **otherInformation,
275 std::list<std::string> &vhosts)
277 return get_or_remove_vhost_otherinfo(otherInformation, true, vhosts);
280 void mp_util::set_vhost_otherinfo(
281 Z_OtherInformation **otherInformation, ODR odr,
282 const std::list<std::string> &vhosts)
285 std::list<std::string>::const_iterator it = vhosts.begin();
286 for (cat = 1; it != vhosts.end() ; cat++, it++)
288 yaz_oi_set_string_oidval(otherInformation, odr,
289 VAL_PROXY, cat, it->c_str());
293 void mp_util::split_zurl(std::string zurl, std::string &host,
294 std::list<std::string> &db)
296 const char *zurl_cstr = zurl.c_str();
297 const char *sep = strchr(zurl_cstr, '/');
301 host = std::string(zurl_cstr, sep - zurl_cstr);
303 const char *cp1 = sep+1;
306 const char *cp2 = strchr(cp1, '+');
308 db.push_back(std::string(cp1, cp2 - cp1));
311 db.push_back(std::string(cp1));
323 bool mp_util::set_databases_from_zurl(
324 ODR odr, std::string zurl,
325 int *db_num, char ***db_strings)
328 std::list<std::string> dblist;
330 split_zurl(zurl, host, dblist);
332 if (dblist.size() == 0)
334 *db_num = dblist.size();
335 *db_strings = (char **) odr_malloc(odr, sizeof(char*) * (*db_num));
337 std::list<std::string>::const_iterator it = dblist.begin();
338 for (int i = 0; it != dblist.end(); it++, i++)
339 (*db_strings)[i] = odr_strdup(odr, it->c_str());
343 mp::odr::odr(int type)
345 m_odr = odr_createmem(type);
350 m_odr = odr_createmem(ODR_ENCODE);
358 mp::odr::operator ODR() const
363 Z_APDU *mp::odr::create_close(const Z_APDU *in_apdu,
364 int reason, const char *addinfo)
366 Z_APDU *apdu = create_APDU(Z_APDU_close, in_apdu);
368 *apdu->u.close->closeReason = reason;
370 apdu->u.close->diagnosticInformation = odr_strdup(m_odr, addinfo);
374 Z_APDU *mp::odr::create_APDU(int type, const Z_APDU *in_apdu)
376 return mp::util::create_APDU(m_odr, type, in_apdu);
379 Z_APDU *mp_util::create_APDU(ODR odr, int type, const Z_APDU *in_apdu)
381 Z_APDU *out_apdu = zget_APDU(odr, type);
382 transfer_referenceId(odr, in_apdu, out_apdu);
386 void mp_util::transfer_referenceId(ODR odr, const Z_APDU *src, Z_APDU *dst)
388 Z_ReferenceId **id_to = mp::util::get_referenceId(dst);
392 Z_ReferenceId **id_from = mp::util::get_referenceId(src);
393 if (id_from && *id_from && id_to)
395 *id_to = (Z_ReferenceId*) odr_malloc (odr, sizeof(**id_to));
396 (*id_to)->size = (*id_to)->len = (*id_from)->len;
397 (*id_to)->buf = (unsigned char*) odr_malloc(odr, (*id_to)->len);
398 memcpy((*id_to)->buf, (*id_from)->buf, (*id_to)->len);
405 Z_APDU *mp::odr::create_initResponse(const Z_APDU *in_apdu,
406 int error, const char *addinfo)
408 Z_APDU *apdu = create_APDU(Z_APDU_initResponse, in_apdu);
411 apdu->u.initResponse->userInformationField =
412 zget_init_diagnostics(m_odr, error, addinfo);
413 *apdu->u.initResponse->result = 0;
418 Z_APDU *mp::odr::create_searchResponse(const Z_APDU *in_apdu,
419 int error, const char *addinfo)
421 Z_APDU *apdu = create_APDU(Z_APDU_searchResponse, in_apdu);
424 Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
425 *apdu->u.searchResponse->searchStatus = 0;
426 apdu->u.searchResponse->records = rec;
427 rec->which = Z_Records_NSD;
428 rec->u.nonSurrogateDiagnostic =
429 zget_DefaultDiagFormat(m_odr, error, addinfo);
435 Z_APDU *mp::odr::create_presentResponse(const Z_APDU *in_apdu,
436 int error, const char *addinfo)
438 Z_APDU *apdu = create_APDU(Z_APDU_presentResponse, in_apdu);
441 Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
442 apdu->u.presentResponse->records = rec;
444 rec->which = Z_Records_NSD;
445 rec->u.nonSurrogateDiagnostic =
446 zget_DefaultDiagFormat(m_odr, error, addinfo);
447 *apdu->u.presentResponse->presentStatus = Z_PresentStatus_failure;
452 Z_APDU *mp::odr::create_scanResponse(const Z_APDU *in_apdu,
453 int error, const char *addinfo)
455 Z_APDU *apdu = create_APDU(Z_APDU_scanResponse, in_apdu);
456 Z_ScanResponse *res = apdu->u.scanResponse;
457 res->entries = (Z_ListEntries *) odr_malloc(m_odr, sizeof(*res->entries));
458 res->entries->num_entries = 0;
459 res->entries->entries = 0;
463 *res->scanStatus = Z_Scan_failure;
465 res->entries->num_nonsurrogateDiagnostics = 1;
466 res->entries->nonsurrogateDiagnostics = (Z_DiagRec **)
467 odr_malloc(m_odr, sizeof(Z_DiagRec *));
468 res->entries->nonsurrogateDiagnostics[0] =
469 zget_DiagRec(m_odr, error, addinfo);
473 res->entries->num_nonsurrogateDiagnostics = 0;
474 res->entries->nonsurrogateDiagnostics = 0;
479 Z_GDU *mp::odr::create_HTTP_Response(mp::Session &session,
480 Z_HTTP_Request *hreq, int code)
482 const char *response_version = "1.0";
483 bool keepalive = false;
484 if (!strcmp(hreq->version, "1.0"))
486 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
487 if (v && !strcmp(v, "Keep-Alive"))
491 response_version = "1.0";
495 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
496 if (v && !strcmp(v, "close"))
500 response_version = "1.1";
503 Z_GDU *gdu = z_get_HTTP_Response(m_odr, code);
504 Z_HTTP_Response *hres = gdu->u.HTTP_Response;
505 hres->version = odr_strdup(m_odr, response_version);
507 z_HTTP_header_add(m_odr, &hres->headers, "Connection", "Keep-Alive");
512 Z_ReferenceId **mp_util::get_referenceId(const Z_APDU *apdu)
516 case Z_APDU_initRequest:
517 return &apdu->u.initRequest->referenceId;
518 case Z_APDU_initResponse:
519 return &apdu->u.initResponse->referenceId;
520 case Z_APDU_searchRequest:
521 return &apdu->u.searchRequest->referenceId;
522 case Z_APDU_searchResponse:
523 return &apdu->u.searchResponse->referenceId;
524 case Z_APDU_presentRequest:
525 return &apdu->u.presentRequest->referenceId;
526 case Z_APDU_presentResponse:
527 return &apdu->u.presentResponse->referenceId;
528 case Z_APDU_deleteResultSetRequest:
529 return &apdu->u.deleteResultSetRequest->referenceId;
530 case Z_APDU_deleteResultSetResponse:
531 return &apdu->u.deleteResultSetResponse->referenceId;
532 case Z_APDU_accessControlRequest:
533 return &apdu->u.accessControlRequest->referenceId;
534 case Z_APDU_accessControlResponse:
535 return &apdu->u.accessControlResponse->referenceId;
536 case Z_APDU_resourceControlRequest:
537 return &apdu->u.resourceControlRequest->referenceId;
538 case Z_APDU_resourceControlResponse:
539 return &apdu->u.resourceControlResponse->referenceId;
540 case Z_APDU_triggerResourceControlRequest:
541 return &apdu->u.triggerResourceControlRequest->referenceId;
542 case Z_APDU_resourceReportRequest:
543 return &apdu->u.resourceReportRequest->referenceId;
544 case Z_APDU_resourceReportResponse:
545 return &apdu->u.resourceReportResponse->referenceId;
546 case Z_APDU_scanRequest:
547 return &apdu->u.scanRequest->referenceId;
548 case Z_APDU_scanResponse:
549 return &apdu->u.scanResponse->referenceId;
550 case Z_APDU_sortRequest:
551 return &apdu->u.sortRequest->referenceId;
552 case Z_APDU_sortResponse:
553 return &apdu->u.sortResponse->referenceId;
554 case Z_APDU_segmentRequest:
555 return &apdu->u.segmentRequest->referenceId;
556 case Z_APDU_extendedServicesRequest:
557 return &apdu->u.extendedServicesRequest->referenceId;
558 case Z_APDU_extendedServicesResponse:
559 return &apdu->u.extendedServicesResponse->referenceId;
561 return &apdu->u.close->referenceId;
570 * indent-tabs-mode: nil
571 * c-file-style: "stroustrup"
573 * vim: shiftwidth=4 tabstop=8 expandtab