1 /* $Id: util.cpp,v 1.22 2006-10-03 07:57:40 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 void mp_util::http_response(metaproxy_1::Package &package,
73 const std::string &content,
77 Z_GDU *zgdu_req = package.request().get();
81 = odr.create_HTTP_Response(package.session(),
82 zgdu_req->u.HTTP_Request,
85 zgdu_res->u.HTTP_Response->content_len = content.size();
86 zgdu_res->u.HTTP_Response->content_buf
87 = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
89 strncpy(zgdu_res->u.HTTP_Response->content_buf,
90 content.c_str(), zgdu_res->u.HTTP_Response->content_len);
92 //z_HTTP_header_add(odr, &hres->headers,
93 // "Content-Type", content_type.c_str());
94 package.response() = zgdu_res;
98 int mp_util::memcmp2(const void *buf1, int len1,
99 const void *buf2, int len2)
103 // compare buffer (common length)
104 int c = memcmp(buf1, buf2, d > 0 ? len2 : len1);
110 // compare (remaining bytes)
119 std::string mp_util::database_name_normalize(const std::string &s)
123 for (i = 0; i < r.length(); i++)
126 if (ch >= 'A' && ch <= 'Z')
127 r[i] = ch + 'a' - 'A';
133 void mp_util::piggyback(int smallSetUpperBound,
134 int largeSetLowerBound,
135 int mediumSetPresentNumber,
137 int &number_to_present)
139 // deal with piggyback
141 if (result_set_size < smallSetUpperBound)
143 // small set . Return all records in set
144 number_to_present = result_set_size;
146 else if (result_set_size > largeSetLowerBound)
148 // large set . Return no records
149 number_to_present = 0;
153 // medium set . Return mediumSetPresentNumber records
154 number_to_present = mediumSetPresentNumber;
155 if (number_to_present > result_set_size)
156 number_to_present = result_set_size;
161 bool mp_util::pqf(ODR odr, Z_APDU *apdu, const std::string &q)
163 YAZ_PQF_Parser pqf_parser = yaz_pqf_create();
165 Z_RPNQuery *rpn = yaz_pqf_parse(pqf_parser, odr, q.c_str());
168 yaz_pqf_destroy(pqf_parser);
171 yaz_pqf_destroy(pqf_parser);
172 Z_Query *query = (Z_Query *) odr_malloc(odr, sizeof(Z_Query));
173 query->which = Z_Query_type_1;
174 query->u.type_1 = rpn;
176 apdu->u.searchRequest->query = query;
181 std::string mp_util::zQueryToString(Z_Query *query)
183 std::string query_str = "";
185 if (query && query->which == Z_Query_type_1){
186 Z_RPNQuery *rpn = query->u.type_1;
190 // allocate wrbuf (strings in YAZ!)
191 WRBUF w = wrbuf_alloc();
194 yaz_rpnquery_to_wrbuf(w, rpn);
196 // from w to std::string
197 query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
205 if (query && query->which == Z_Query_type_1){
207 // allocate wrbuf (strings in YAZ!)
208 WRBUF w = wrbuf_alloc();
211 yaz_query_to_wrbuf(w, query);
213 // from w to std::string
214 query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
223 void mp_util::get_default_diag(Z_DefaultDiagFormat *r,
224 int &error_code, std::string &addinfo)
226 error_code = *r->condition;
229 case Z_DefaultDiagFormat_v2Addinfo:
230 addinfo = std::string(r->u.v2Addinfo);
232 case Z_DefaultDiagFormat_v3Addinfo:
233 addinfo = r->u.v3Addinfo;
238 void mp_util::get_init_diagnostics(
239 Z_InitResponse *initrs, int &error_code, std::string &addinfo)
241 Z_External *uif = initrs->userInformationField;
243 if (uif && uif->which == Z_External_userInfo1)
245 Z_OtherInformation *ui = uif->u.userInfo1;
247 for (i = 0; i < ui->num_elements; i++)
249 Z_OtherInformationUnit *unit = ui->list[i];
250 if (unit->which == Z_OtherInfo_externallyDefinedInfo &&
251 unit->information.externallyDefinedInfo &&
252 unit->information.externallyDefinedInfo->which ==
255 Z_DiagnosticFormat *diag =
256 unit->information.externallyDefinedInfo->u.diag1;
260 Z_DiagnosticFormat_s *ds = diag->elements[0];
261 if (ds->which == Z_DiagnosticFormat_s_defaultDiagRec)
262 mp::util::get_default_diag(ds->u.defaultDiagRec,
263 error_code, addinfo);
270 int mp_util::get_or_remove_vhost_otherinfo(
271 Z_OtherInformation **otherInformation,
273 std::list<std::string> &vhosts)
276 for (cat = 1; ; cat++)
278 // check virtual host
280 yaz_oi_get_string_oidval(otherInformation,
282 cat /* categoryValue */,
283 remove_flag /* delete flag */);
286 vhosts.push_back(std::string(vhost));
292 void mp_util::get_vhost_otherinfo(
293 Z_OtherInformation *otherInformation,
294 std::list<std::string> &vhosts)
296 get_or_remove_vhost_otherinfo(&otherInformation, false, vhosts);
299 int mp_util::remove_vhost_otherinfo(
300 Z_OtherInformation **otherInformation,
301 std::list<std::string> &vhosts)
303 return get_or_remove_vhost_otherinfo(otherInformation, true, vhosts);
306 void mp_util::set_vhost_otherinfo(
307 Z_OtherInformation **otherInformation, ODR odr,
308 const std::list<std::string> &vhosts)
311 std::list<std::string>::const_iterator it = vhosts.begin();
312 for (cat = 1; it != vhosts.end() ; cat++, it++)
314 yaz_oi_set_string_oidval(otherInformation, odr,
315 VAL_PROXY, cat, it->c_str());
319 void mp_util::split_zurl(std::string zurl, std::string &host,
320 std::list<std::string> &db)
322 const char *zurl_cstr = zurl.c_str();
323 const char *sep = strchr(zurl_cstr, '/');
327 host = std::string(zurl_cstr, sep - zurl_cstr);
329 const char *cp1 = sep+1;
332 const char *cp2 = strchr(cp1, '+');
334 db.push_back(std::string(cp1, cp2 - cp1));
337 db.push_back(std::string(cp1));
349 bool mp_util::set_databases_from_zurl(
350 ODR odr, std::string zurl,
351 int *db_num, char ***db_strings)
354 std::list<std::string> dblist;
356 split_zurl(zurl, host, dblist);
358 if (dblist.size() == 0)
360 *db_num = dblist.size();
361 *db_strings = (char **) odr_malloc(odr, sizeof(char*) * (*db_num));
363 std::list<std::string>::const_iterator it = dblist.begin();
364 for (int i = 0; it != dblist.end(); it++, i++)
365 (*db_strings)[i] = odr_strdup(odr, it->c_str());
369 mp::odr::odr(int type)
371 m_odr = odr_createmem(type);
376 m_odr = odr_createmem(ODR_ENCODE);
384 mp::odr::operator ODR() const
389 Z_APDU *mp::odr::create_close(const Z_APDU *in_apdu,
390 int reason, const char *addinfo)
392 Z_APDU *apdu = create_APDU(Z_APDU_close, in_apdu);
394 *apdu->u.close->closeReason = reason;
396 apdu->u.close->diagnosticInformation = odr_strdup(m_odr, addinfo);
400 Z_APDU *mp::odr::create_APDU(int type, const Z_APDU *in_apdu)
402 return mp::util::create_APDU(m_odr, type, in_apdu);
405 Z_APDU *mp_util::create_APDU(ODR odr, int type, const Z_APDU *in_apdu)
407 Z_APDU *out_apdu = zget_APDU(odr, type);
408 transfer_referenceId(odr, in_apdu, out_apdu);
412 void mp_util::transfer_referenceId(ODR odr, const Z_APDU *src, Z_APDU *dst)
414 Z_ReferenceId **id_to = mp::util::get_referenceId(dst);
418 Z_ReferenceId **id_from = mp::util::get_referenceId(src);
419 if (id_from && *id_from && id_to)
421 *id_to = (Z_ReferenceId*) odr_malloc (odr, sizeof(**id_to));
422 (*id_to)->size = (*id_to)->len = (*id_from)->len;
423 (*id_to)->buf = (unsigned char*) odr_malloc(odr, (*id_to)->len);
424 memcpy((*id_to)->buf, (*id_from)->buf, (*id_to)->len);
431 Z_APDU *mp::odr::create_initResponse(const Z_APDU *in_apdu,
432 int error, const char *addinfo)
434 Z_APDU *apdu = create_APDU(Z_APDU_initResponse, in_apdu);
437 apdu->u.initResponse->userInformationField =
438 zget_init_diagnostics(m_odr, error, addinfo);
439 *apdu->u.initResponse->result = 0;
444 Z_APDU *mp::odr::create_searchResponse(const Z_APDU *in_apdu,
445 int error, const char *addinfo)
447 Z_APDU *apdu = create_APDU(Z_APDU_searchResponse, in_apdu);
450 Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
451 *apdu->u.searchResponse->searchStatus = 0;
452 apdu->u.searchResponse->records = rec;
453 rec->which = Z_Records_NSD;
454 rec->u.nonSurrogateDiagnostic =
455 zget_DefaultDiagFormat(m_odr, error, addinfo);
461 Z_APDU *mp::odr::create_presentResponse(const Z_APDU *in_apdu,
462 int error, const char *addinfo)
464 Z_APDU *apdu = create_APDU(Z_APDU_presentResponse, in_apdu);
467 Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
468 apdu->u.presentResponse->records = rec;
470 rec->which = Z_Records_NSD;
471 rec->u.nonSurrogateDiagnostic =
472 zget_DefaultDiagFormat(m_odr, error, addinfo);
473 *apdu->u.presentResponse->presentStatus = Z_PresentStatus_failure;
478 Z_APDU *mp::odr::create_scanResponse(const Z_APDU *in_apdu,
479 int error, const char *addinfo)
481 Z_APDU *apdu = create_APDU(Z_APDU_scanResponse, in_apdu);
482 Z_ScanResponse *res = apdu->u.scanResponse;
483 res->entries = (Z_ListEntries *) odr_malloc(m_odr, sizeof(*res->entries));
484 res->entries->num_entries = 0;
485 res->entries->entries = 0;
489 *res->scanStatus = Z_Scan_failure;
491 res->entries->num_nonsurrogateDiagnostics = 1;
492 res->entries->nonsurrogateDiagnostics = (Z_DiagRec **)
493 odr_malloc(m_odr, sizeof(Z_DiagRec *));
494 res->entries->nonsurrogateDiagnostics[0] =
495 zget_DiagRec(m_odr, error, addinfo);
499 res->entries->num_nonsurrogateDiagnostics = 0;
500 res->entries->nonsurrogateDiagnostics = 0;
505 Z_GDU *mp::odr::create_HTTP_Response(mp::Session &session,
506 Z_HTTP_Request *hreq, int code)
508 const char *response_version = "1.0";
509 bool keepalive = false;
510 if (!strcmp(hreq->version, "1.0"))
512 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
513 if (v && !strcmp(v, "Keep-Alive"))
517 response_version = "1.0";
521 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
522 if (v && !strcmp(v, "close"))
526 response_version = "1.1";
529 Z_GDU *gdu = z_get_HTTP_Response(m_odr, code);
530 Z_HTTP_Response *hres = gdu->u.HTTP_Response;
531 hres->version = odr_strdup(m_odr, response_version);
533 z_HTTP_header_add(m_odr, &hres->headers, "Connection", "Keep-Alive");
538 Z_ReferenceId **mp_util::get_referenceId(const Z_APDU *apdu)
542 case Z_APDU_initRequest:
543 return &apdu->u.initRequest->referenceId;
544 case Z_APDU_initResponse:
545 return &apdu->u.initResponse->referenceId;
546 case Z_APDU_searchRequest:
547 return &apdu->u.searchRequest->referenceId;
548 case Z_APDU_searchResponse:
549 return &apdu->u.searchResponse->referenceId;
550 case Z_APDU_presentRequest:
551 return &apdu->u.presentRequest->referenceId;
552 case Z_APDU_presentResponse:
553 return &apdu->u.presentResponse->referenceId;
554 case Z_APDU_deleteResultSetRequest:
555 return &apdu->u.deleteResultSetRequest->referenceId;
556 case Z_APDU_deleteResultSetResponse:
557 return &apdu->u.deleteResultSetResponse->referenceId;
558 case Z_APDU_accessControlRequest:
559 return &apdu->u.accessControlRequest->referenceId;
560 case Z_APDU_accessControlResponse:
561 return &apdu->u.accessControlResponse->referenceId;
562 case Z_APDU_resourceControlRequest:
563 return &apdu->u.resourceControlRequest->referenceId;
564 case Z_APDU_resourceControlResponse:
565 return &apdu->u.resourceControlResponse->referenceId;
566 case Z_APDU_triggerResourceControlRequest:
567 return &apdu->u.triggerResourceControlRequest->referenceId;
568 case Z_APDU_resourceReportRequest:
569 return &apdu->u.resourceReportRequest->referenceId;
570 case Z_APDU_resourceReportResponse:
571 return &apdu->u.resourceReportResponse->referenceId;
572 case Z_APDU_scanRequest:
573 return &apdu->u.scanRequest->referenceId;
574 case Z_APDU_scanResponse:
575 return &apdu->u.scanResponse->referenceId;
576 case Z_APDU_sortRequest:
577 return &apdu->u.sortRequest->referenceId;
578 case Z_APDU_sortResponse:
579 return &apdu->u.sortResponse->referenceId;
580 case Z_APDU_segmentRequest:
581 return &apdu->u.segmentRequest->referenceId;
582 case Z_APDU_extendedServicesRequest:
583 return &apdu->u.extendedServicesRequest->referenceId;
584 case Z_APDU_extendedServicesResponse:
585 return &apdu->u.extendedServicesResponse->referenceId;
587 return &apdu->u.close->referenceId;
596 * indent-tabs-mode: nil
597 * c-file-style: "stroustrup"
599 * vim: shiftwidth=4 tabstop=8 expandtab