metaproxy  1.21.0
util.cpp
Go to the documentation of this file.
1 /* This file is part of Metaproxy.
2  Copyright (C) Index Data
3 
4 Metaproxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "config.hpp"
20 #include <metaproxy/util.hpp>
21 
22 #include <yaz/odr.h>
23 #include <yaz/comstack.h>
24 #include <yaz/pquery.h>
25 #include <yaz/otherinfo.h>
26 #include <yaz/querytowrbuf.h>
27 #include <yaz/oid_db.h>
28 #include <yaz/srw.h>
29 #include <yaz/match_glob.h>
30 
31 #include <boost/algorithm/string.hpp>
32 
33 #include <iostream>
34 
35 namespace mp = metaproxy_1;
36 
37 // Doxygen doesn't like mp::util, so we use this instead
38 namespace mp_util = metaproxy_1::util;
39 
40 const char *
41 mp_util::record_composition_to_esn(Z_RecordComposition *comp)
42 {
43  if (comp && comp->which == Z_RecordComp_complex)
44  {
45  if (comp->u.complex->generic
46  && comp->u.complex->generic->elementSpec
47  && (comp->u.complex->generic->elementSpec->which ==
48  Z_ElementSpec_elementSetName))
49  return comp->u.complex->generic->elementSpec->u.elementSetName;
50  }
51  else if (comp && comp->which == Z_RecordComp_simple &&
52  comp->u.simple->which == Z_ElementSetNames_generic)
53  return comp->u.simple->u.generic;
54  return 0;
55 }
56 
57 
58 
59 std::string mp_util::http_header_value(const Z_HTTP_Header* header,
60  const std::string name)
61 {
62  while (header && header->name
63  && std::string(header->name) != name)
64  header = header->next;
65 
66  if (header && header->name && std::string(header->name) == name
67  && header->value)
68  return std::string(header->value);
69 
70  return std::string();
71 }
72 
73 std::string mp_util::http_headers_debug(const Z_HTTP_Request &http_req)
74 {
75  std::string message("<html>\n<body>\n<h1>"
76  "Metaproxy SRUtoZ3950 filter"
77  "</h1>\n");
78 
79  message += "<h3>HTTP Info</h3><br/>\n";
80  message += "<p>\n";
81  message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
82  message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
83  message += "<b>Path: </b> " + std::string(http_req.path) + "<br/>\n";
84 
85  message += "<b>Content-Type:</b>"
86  + mp_util::http_header_value(http_req.headers, "Content-Type")
87  + "<br/>\n";
88  message += "<b>Content-Length:</b>"
89  + mp_util::http_header_value(http_req.headers, "Content-Length")
90  + "<br/>\n";
91  message += "</p>\n";
92 
93  message += "<h3>Headers</h3><br/>\n";
94  message += "<p>\n";
95  Z_HTTP_Header* header = http_req.headers;
96  while (header){
97  message += "<b>Header: </b> <i>"
98  + std::string(header->name) + ":</i> "
99  + std::string(header->value) + "<br/>\n";
100  header = header->next;
101  }
102  message += "</p>\n";
103  message += "</body>\n</html>\n";
104  return message;
105 }
106 
107 
108 void mp_util::http_response(metaproxy_1::Package &package,
109  const std::string &content,
110  int http_code)
111 {
112 
113  Z_GDU *zgdu_req = package.request().get();
114  Z_GDU *zgdu_res = 0;
115  mp::odr odr;
116  zgdu_res
117  = odr.create_HTTP_Response(package.session(),
118  zgdu_req->u.HTTP_Request,
119  http_code);
120 
121  zgdu_res->u.HTTP_Response->content_len = content.size();
122  zgdu_res->u.HTTP_Response->content_buf
123  = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
124 
125  strncpy(zgdu_res->u.HTTP_Response->content_buf,
126  content.c_str(), zgdu_res->u.HTTP_Response->content_len);
127 
128  //z_HTTP_header_add(odr, &hres->headers,
129  // "Content-Type", content_type.c_str());
130  package.response() = zgdu_res;
131 }
132 
133 
134 int mp_util::memcmp2(const void *buf1, int len1,
135  const void *buf2, int len2)
136 {
137  int d = len1 - len2;
138 
139  // compare buffer (common length)
140  int c = memcmp(buf1, buf2, d > 0 ? len2 : len1);
141  if (c > 0)
142  return 1;
143  else if (c < 0)
144  return -1;
145 
146  // compare (remaining bytes)
147  if (d > 0)
148  return 1;
149  else if (d < 0)
150  return -1;
151  return 0;
152 }
153 
154 bool mp_util::match(const std::list<std::string> &db1,
155  const std::list<std::string> &db2)
156 {
157  std::list<std::string>::const_iterator it1 = db1.begin();
158  std::list<std::string>::const_iterator it2 = db2.begin();
159  while (it1 != db1.end() && it2 != db2.end())
160  {
161  std::string s1 = database_name_normalize(*it1);
162  std::string s2 = database_name_normalize(*it2);
163  if (s1.compare(s2) != 0)
164  return false;
165  it1++;
166  it2++;
167  }
168  return it1 == db1.end() && it2 == db2.end();
169 }
170 
171 std::string mp_util::database_name_normalize(const std::string &s)
172 {
173  std::string r = s;
174  size_t i;
175  for (i = 0; i < r.length(); i++)
176  {
177  int ch = r[i];
178  if (ch >= 'A' && ch <= 'Z')
179  r[i] = ch + 'a' - 'A';
180  }
181  return r;
182 
183 }
184 
185 Z_RecordComposition *mp_util::piggyback_to_RecordComposition(
186  ODR odr, Odr_int result_set_size, Z_SearchRequest *sreq)
187 {
188  Z_RecordComposition *comp = 0;
189  Odr_int present_dummy;
190  const char *element_set_name = 0;
191  mp::util::piggyback_sr(sreq, result_set_size,
192  present_dummy, &element_set_name);
193  if (element_set_name)
194  {
195  comp = (Z_RecordComposition *) odr_malloc(odr, sizeof(*comp));
196  comp->which = Z_RecordComp_simple;
197  comp->u.simple = (Z_ElementSetNames *)
198  odr_malloc(odr, sizeof(Z_ElementSetNames));
199  comp->u.simple->which = Z_ElementSetNames_generic;
200  comp->u.simple->u.generic = odr_strdup(odr, element_set_name);
201  }
202  return comp;
203 }
204 
205 void mp_util::piggyback_sr(Z_SearchRequest *sreq,
206  Odr_int result_set_size,
207  Odr_int &number_to_present,
208  const char **element_set_name)
209 {
210  Z_ElementSetNames *esn;
211  const char *smallSetElementSetNames = 0;
212  const char *mediumSetElementSetNames = 0;
213 
214  esn = sreq->smallSetElementSetNames;
215  if (esn && esn->which == Z_ElementSetNames_generic)
216  smallSetElementSetNames = esn->u.generic;
217 
218  esn = sreq->mediumSetElementSetNames;
219  if (esn && esn->which == Z_ElementSetNames_generic)
220  mediumSetElementSetNames = esn->u.generic;
221 
222  piggyback(*sreq->smallSetUpperBound,
223  *sreq->largeSetLowerBound,
224  *sreq->mediumSetPresentNumber,
225  smallSetElementSetNames,
226  mediumSetElementSetNames,
228  number_to_present,
229  element_set_name);
230 }
231 
232 void mp_util::piggyback(int smallSetUpperBound,
233  int largeSetLowerBound,
234  int mediumSetPresentNumber,
235  int result_set_size,
236  int &number_to_present)
237 {
238  Odr_int tmp = number_to_present;
239  piggyback(smallSetUpperBound, largeSetLowerBound, mediumSetPresentNumber,
240  0, 0, result_set_size, tmp, 0);
241  number_to_present = tmp;
242 }
243 
244 void mp_util::piggyback(Odr_int smallSetUpperBound,
245  Odr_int largeSetLowerBound,
246  Odr_int mediumSetPresentNumber,
247  const char *smallSetElementSetNames,
248  const char *mediumSetElementSetNames,
249  Odr_int result_set_size,
250  Odr_int &number_to_present,
251  const char **element_set_name)
252 {
253  // deal with piggyback
254 
255  if (result_set_size < smallSetUpperBound)
256  {
257  // small set . Return all records in set
258  number_to_present = result_set_size;
259  if (element_set_name && smallSetElementSetNames)
260  *element_set_name = smallSetElementSetNames;
261 
262  }
263  else if (result_set_size > largeSetLowerBound)
264  {
265  // large set . Return no records
266  number_to_present = 0;
267  if (element_set_name)
268  *element_set_name = 0;
269  }
270  else
271  {
272  // medium set . Return mediumSetPresentNumber records
273  number_to_present = mediumSetPresentNumber;
274  if (number_to_present > result_set_size)
275  number_to_present = result_set_size;
276  if (element_set_name && mediumSetElementSetNames)
277  *element_set_name = mediumSetElementSetNames;
278  }
279 }
280 
281 bool mp_util::pqf(ODR odr, Z_APDU *apdu, const std::string &q)
282 {
283  YAZ_PQF_Parser pqf_parser = yaz_pqf_create();
284 
285  Z_RPNQuery *rpn = yaz_pqf_parse(pqf_parser, odr, q.c_str());
286  if (!rpn)
287  {
288  yaz_pqf_destroy(pqf_parser);
289  return false;
290  }
291  yaz_pqf_destroy(pqf_parser);
292  Z_Query *query = (Z_Query *) odr_malloc(odr, sizeof(Z_Query));
293  query->which = Z_Query_type_1;
294  query->u.type_1 = rpn;
295 
296  apdu->u.searchRequest->query = query;
297  return true;
298 }
299 
300 
301 std::string mp_util::zQueryToString(Z_Query *query)
302 {
303  std::string query_str = "";
304 
305  if (query && query->which == Z_Query_type_1)
306  {
307  Z_RPNQuery *rpn = query->u.type_1;
308 
309  if (rpn)
310  {
311  mp::wrbuf w;
312 
313  // put query in w
314  yaz_rpnquery_to_wrbuf(w, rpn);
315 
316  // from w to std::string
317  query_str = std::string(w.buf(), w.len());
318  }
319  }
320 
321 #if 0
322  if (query && query->which == Z_Query_type_1){
323 
324  // allocate wrbuf (strings in YAZ!)
325  WRBUF w = wrbuf_alloc();
326 
327  // put query in w
328  yaz_query_to_wrbuf(w, query);
329 
330  // from w to std::string
331  query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
332 
333  // destroy wrbuf
334  wrbuf_free(w, 1);
335  }
336 #endif
337  return query_str;
338 }
339 
340 void mp_util::get_default_diag(Z_DefaultDiagFormat *r,
341  int &error_code, std::string &addinfo)
342 {
343  error_code = *r->condition;
344  switch (r->which)
345  {
346  case Z_DefaultDiagFormat_v2Addinfo:
347  addinfo = std::string(r->u.v2Addinfo);
348  break;
349  case Z_DefaultDiagFormat_v3Addinfo:
350  addinfo = r->u.v3Addinfo;
351  break;
352  }
353 }
354 
355 void mp_util::get_init_diagnostics(
356  Z_InitResponse *initrs, int &error_code, std::string &addinfo)
357 {
358 
359  Z_DefaultDiagFormat *df = yaz_decode_init_diag(0, initrs);
360 
361  if (df)
362  get_default_diag(df, error_code, addinfo);
363 }
364 
365 int mp_util::get_or_remove_vhost_otherinfo(
366  Z_OtherInformation **otherInformation,
367  bool remove_flag,
368  std::list<std::string> &vhosts)
369 {
370  int cat;
371  for (cat = 1; ; cat++)
372  {
373  // check virtual host
374  const char *vhost =
375  yaz_oi_get_string_oid(otherInformation,
376  yaz_oid_userinfo_proxy,
377  cat /* categoryValue */,
378  remove_flag /* delete flag */);
379  if (!vhost)
380  break;
381  vhosts.push_back(std::string(vhost));
382  }
383  --cat;
384  return cat;
385 }
386 
387 void mp_util::get_vhost_otherinfo(
388  Z_OtherInformation *otherInformation,
389  std::list<std::string> &vhosts)
390 {
391  get_or_remove_vhost_otherinfo(&otherInformation, false, vhosts);
392 }
393 
394 int mp_util::remove_vhost_otherinfo(
395  Z_OtherInformation **otherInformation,
396  std::list<std::string> &vhosts)
397 {
398  return get_or_remove_vhost_otherinfo(otherInformation, true, vhosts);
399 }
400 
401 void mp_util::set_vhost_otherinfo(
402  Z_OtherInformation **otherInformation, ODR odr,
403  const std::list<std::string> &vhosts)
404 {
405  int cat;
406  std::list<std::string>::const_iterator it = vhosts.begin();
407 
408  for (cat = 1; it != vhosts.end() ; cat++, it++)
409  {
410  yaz_oi_set_string_oid(otherInformation, odr,
411  yaz_oid_userinfo_proxy, cat, it->c_str());
412  }
413 }
414 
415 void mp_util::set_vhost_otherinfo(
416  Z_OtherInformation **otherInformation, ODR odr,
417  const std::string vhost, const int cat)
418 {
419  yaz_oi_set_string_oid(otherInformation, odr,
420  yaz_oid_userinfo_proxy, cat, vhost.c_str());
421 }
422 
423 void mp_util::split_zurl(std::string zurl, std::string &host,
424  std::list<std::string> &db)
425 {
426  const char *zurl_cstr = zurl.c_str();
427  const char *args = 0;
428  cs_get_host_args(zurl_cstr, &args);
429 
430  if (args && *args)
431  {
432  host = std::string(zurl_cstr, args - zurl_cstr - 1);
433 
434  const char *cp1 = args;
435  while (1)
436  {
437  const char *cp2 = strchr(cp1, '+');
438  if (cp2)
439  db.push_back(std::string(cp1, cp2 - cp1));
440  else
441  {
442  db.push_back(std::string(cp1));
443  break;
444  }
445  cp1 = cp2+1;
446  }
447  }
448  else
449  host = zurl;
450 }
451 
452 bool mp_util::set_databases_from_zurl(
453  ODR odr, std::string zurl,
454  int *db_num, char ***db_strings)
455 {
456  std::string host;
457  std::list<std::string> dblist;
458 
459  split_zurl(zurl, host, dblist);
460 
461  if (dblist.size() == 0)
462  return false;
463  *db_num = dblist.size();
464  *db_strings = (char **) odr_malloc(odr, sizeof(char*) * (*db_num));
465 
466  std::list<std::string>::const_iterator it = dblist.begin();
467  for (int i = 0; it != dblist.end(); it++, i++)
468  (*db_strings)[i] = odr_strdup(odr, it->c_str());
469  return true;
470 }
471 
472 mp::odr::odr(int type)
473 {
474  m_odr = odr_createmem(type);
475 }
476 
477 mp::odr::odr()
478 {
479  m_odr = odr_createmem(ODR_ENCODE);
480 }
481 
482 mp::odr::~odr()
483 {
484  odr_destroy(m_odr);
485 }
486 
487 mp::odr::operator ODR() const
488 {
489  return m_odr;
490 }
491 
492 Z_APDU *mp::odr::create_close(const Z_APDU *in_apdu,
493  int reason, const char *addinfo)
494 {
495  Z_APDU *apdu = create_APDU(Z_APDU_close, in_apdu);
496 
497  *apdu->u.close->closeReason = reason;
498  if (addinfo)
499  apdu->u.close->diagnosticInformation = odr_strdup(m_odr, addinfo);
500  return apdu;
501 }
502 
503 Z_APDU *mp::odr::create_APDU(int type, const Z_APDU *in_apdu)
504 {
505  return mp::util::create_APDU(m_odr, type, in_apdu);
506 }
507 
508 Z_APDU *mp_util::create_APDU(ODR odr, int type, const Z_APDU *in_apdu)
509 {
510  Z_APDU *out_apdu = zget_APDU(odr, type);
511  transfer_referenceId(odr, in_apdu, out_apdu);
512  return out_apdu;
513 }
514 
515 void mp_util::transfer_referenceId(ODR odr, const Z_APDU *src, Z_APDU *dst)
516 {
517  Z_ReferenceId **id_to = mp::util::get_referenceId(dst);
518  *id_to = 0;
519  if (src)
520  {
521  Z_ReferenceId **id_from = mp::util::get_referenceId(src);
522  if (id_from && *id_from)
523  *id_to = odr_create_Odr_oct(odr, (*id_from)->buf,
524  (*id_from)->len);
525  }
526 }
527 
528 Z_APDU *mp::odr::create_initResponse(const Z_APDU *in_apdu,
529  int error, const char *addinfo)
530 {
531  Z_APDU *apdu = create_APDU(Z_APDU_initResponse, in_apdu);
532  if (error)
533  {
534  apdu->u.initResponse->userInformationField =
535  zget_init_diagnostics(m_odr, error, addinfo);
536  *apdu->u.initResponse->result = 0;
537  }
538  apdu->u.initResponse->implementationName =
539  odr_prepend(m_odr, "Metaproxy",
540  apdu->u.initResponse->implementationName);
541  apdu->u.initResponse->implementationVersion =
542  odr_prepend(m_odr,
543  VERSION, apdu->u.initResponse->implementationVersion);
544 
545  return apdu;
546 }
547 
548 Z_APDU *mp::odr::create_searchResponse(const Z_APDU *in_apdu,
549  int error, const char *addinfo)
550 {
551  Z_APDU *apdu = create_APDU(Z_APDU_searchResponse, in_apdu);
552  if (error)
553  {
554  Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
555  *apdu->u.searchResponse->searchStatus = 0;
556  apdu->u.searchResponse->records = rec;
557  rec->which = Z_Records_NSD;
558  rec->u.nonSurrogateDiagnostic =
559  zget_DefaultDiagFormat(m_odr, error, addinfo);
560 
561  }
562  return apdu;
563 }
564 
565 Z_APDU *mp::odr::create_presentResponse(const Z_APDU *in_apdu,
566  int error, const char *addinfo)
567 {
568  Z_APDU *apdu = create_APDU(Z_APDU_presentResponse, in_apdu);
569  if (error)
570  {
571  Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
572  apdu->u.presentResponse->records = rec;
573 
574  rec->which = Z_Records_NSD;
575  rec->u.nonSurrogateDiagnostic =
576  zget_DefaultDiagFormat(m_odr, error, addinfo);
577  *apdu->u.presentResponse->presentStatus = Z_PresentStatus_failure;
578  }
579  return apdu;
580 }
581 
582 Z_APDU *mp::odr::create_scanResponse(const Z_APDU *in_apdu,
583  int error, const char *addinfo)
584 {
585  Z_APDU *apdu = create_APDU(Z_APDU_scanResponse, in_apdu);
586  Z_ScanResponse *res = apdu->u.scanResponse;
587  res->entries = (Z_ListEntries *) odr_malloc(m_odr, sizeof(*res->entries));
588  res->entries->num_entries = 0;
589  res->entries->entries = 0;
590 
591  if (error)
592  {
593  *res->scanStatus = Z_Scan_failure;
594 
595  res->entries->num_nonsurrogateDiagnostics = 1;
596  res->entries->nonsurrogateDiagnostics = (Z_DiagRec **)
597  odr_malloc(m_odr, sizeof(Z_DiagRec *));
598  res->entries->nonsurrogateDiagnostics[0] =
599  zget_DiagRec(m_odr, error, addinfo);
600  }
601  else
602  {
603  res->entries->num_nonsurrogateDiagnostics = 0;
604  res->entries->nonsurrogateDiagnostics = 0;
605  }
606  return apdu;
607 }
608 
609 Z_GDU *mp::odr::create_HTTP_Response_details(mp::Session &session,
610  Z_HTTP_Request *hreq, int code,
611  const char *details)
612 {
613  const char *response_version = "1.0";
614  bool keepalive = false;
615  if (!strcmp(hreq->version, "1.0"))
616  {
617  const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
618  if (v && !strcmp(v, "Keep-Alive"))
619  keepalive = true;
620  else
621  session.close();
622  response_version = "1.0";
623  }
624  else
625  {
626  const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
627  if (v && !strcmp(v, "close"))
628  session.close();
629  else
630  keepalive = true;
631  response_version = "1.1";
632  }
633 
634  Z_GDU *gdu = z_get_HTTP_Response_server(
635  m_odr, code, details, "Metaproxy/" VERSION,
636  "http://www.indexdata.com/metaproxy");
637  Z_HTTP_Response *hres = gdu->u.HTTP_Response;
638  hres->version = odr_strdup(m_odr, response_version);
639  if (keepalive)
640  z_HTTP_header_add(m_odr, &hres->headers, "Connection", "Keep-Alive");
641  return gdu;
642 }
643 
644 Z_GDU *mp::odr::create_HTTP_Response(mp::Session &session,
645  Z_HTTP_Request *hreq, int code)
646 {
647  return create_HTTP_Response_details(session, hreq, code, 0);
648 
649 }
650 
651 Z_ReferenceId **mp_util::get_referenceId(const Z_APDU *apdu)
652 {
653  switch (apdu->which)
654  {
655  case Z_APDU_initRequest:
656  return &apdu->u.initRequest->referenceId;
657  case Z_APDU_initResponse:
658  return &apdu->u.initResponse->referenceId;
659  case Z_APDU_searchRequest:
660  return &apdu->u.searchRequest->referenceId;
661  case Z_APDU_searchResponse:
662  return &apdu->u.searchResponse->referenceId;
663  case Z_APDU_presentRequest:
664  return &apdu->u.presentRequest->referenceId;
665  case Z_APDU_presentResponse:
666  return &apdu->u.presentResponse->referenceId;
667  case Z_APDU_deleteResultSetRequest:
668  return &apdu->u.deleteResultSetRequest->referenceId;
669  case Z_APDU_deleteResultSetResponse:
670  return &apdu->u.deleteResultSetResponse->referenceId;
671  case Z_APDU_accessControlRequest:
672  return &apdu->u.accessControlRequest->referenceId;
673  case Z_APDU_accessControlResponse:
674  return &apdu->u.accessControlResponse->referenceId;
675  case Z_APDU_resourceControlRequest:
676  return &apdu->u.resourceControlRequest->referenceId;
677  case Z_APDU_resourceControlResponse:
678  return &apdu->u.resourceControlResponse->referenceId;
679  case Z_APDU_triggerResourceControlRequest:
680  return &apdu->u.triggerResourceControlRequest->referenceId;
681  case Z_APDU_resourceReportRequest:
682  return &apdu->u.resourceReportRequest->referenceId;
683  case Z_APDU_resourceReportResponse:
684  return &apdu->u.resourceReportResponse->referenceId;
685  case Z_APDU_scanRequest:
686  return &apdu->u.scanRequest->referenceId;
687  case Z_APDU_scanResponse:
688  return &apdu->u.scanResponse->referenceId;
689  case Z_APDU_sortRequest:
690  return &apdu->u.sortRequest->referenceId;
691  case Z_APDU_sortResponse:
692  return &apdu->u.sortResponse->referenceId;
693  case Z_APDU_segmentRequest:
694  return &apdu->u.segmentRequest->referenceId;
695  case Z_APDU_extendedServicesRequest:
696  return &apdu->u.extendedServicesRequest->referenceId;
697  case Z_APDU_extendedServicesResponse:
698  return &apdu->u.extendedServicesResponse->referenceId;
699  case Z_APDU_close:
700  return &apdu->u.close->referenceId;
701  }
702  return 0;
703 }
704 
705 std::string mp_util::uri_encode(std::string s)
706 {
707  char *x = (char *) xmalloc(1 + s.length() * 3);
708  yaz_encode_uri_component(x, s.c_str());
709  std::string result(x);
710  xfree(x);
711  return result;
712 }
713 
714 
715 std::string mp_util::uri_decode(std::string s)
716 {
717  char *x = (char *) xmalloc(1 + s.length());
718  yaz_decode_uri_component(x, s.c_str(), s.length());
719  std::string result(x);
720  xfree(x);
721  return result;
722 }
723 
724 mp::wrbuf::wrbuf()
725 {
726  m_wrbuf = wrbuf_alloc();
727 }
728 
729 mp::wrbuf::~wrbuf()
730 {
731  wrbuf_destroy(m_wrbuf);
732 }
733 
734 mp::wrbuf::operator WRBUF() const
735 {
736  return m_wrbuf;
737 }
738 
739 size_t mp::wrbuf::len()
740 {
741  return wrbuf_len(m_wrbuf);
742 }
743 
744 const char *mp::wrbuf::buf()
745 {
746  return wrbuf_buf(m_wrbuf);
747 }
748 
749 const char *mp::wrbuf::c_str()
750 {
751  return wrbuf_cstr(m_wrbuf);
752 }
753 
754 const char *mp::wrbuf::c_str_null()
755 {
756  return wrbuf_cstr_null(m_wrbuf);
757 }
758 
759 bool mp::util::match_ip(const std::string &pattern, const std::string &value)
760 {
761  std::vector<std::string> globitems;
762  // split may produce empty strings as results - in particular
763  // the empty pattern produces one empty string (vector size 1)
764  boost::split(globitems, pattern, boost::is_any_of(" "));
765  bool ret_value = true; // for now (if only empty values)
766  const char *value_c = value.c_str();
767  int ipv4_mapped = strlen(value_c) > 7 && memcmp(value_c, "::ffff:", 7) == 0;
768  std::vector<std::string>::const_iterator it = globitems.begin();
769  for (; it != globitems.end(); it++)
770  {
771  const char *c_str = (*it).c_str();
772  if (*c_str)
773  {
774  ret_value = false; // at least one non-empty value
775  if (yaz_match_glob(c_str, value_c))
776  return true;
777  if (!strchr(c_str, ':') && ipv4_mapped &&
778  yaz_match_glob(c_str, value_c + 7))
779  return true;
780  }
781  }
782  return ret_value;
783 }
784 
785 /*
786  * Local variables:
787  * c-basic-offset: 4
788  * c-file-style: "Stroustrup"
789  * indent-tabs-mode: nil
790  * End:
791  * vim: shiftwidth=4 tabstop=8 expandtab
792  */
793 
#define VERSION
Definition: config.hpp:88
static const int result_set_size