metaproxy  1.13.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 
155 std::string mp_util::database_name_normalize(const std::string &s)
156 {
157  std::string r = s;
158  size_t i;
159  for (i = 0; i < r.length(); i++)
160  {
161  int ch = r[i];
162  if (ch >= 'A' && ch <= 'Z')
163  r[i] = ch + 'a' - 'A';
164  }
165  return r;
166 
167 }
168 
169 Z_RecordComposition *mp_util::piggyback_to_RecordComposition(
170  ODR odr, Odr_int result_set_size, Z_SearchRequest *sreq)
171 {
172  Z_RecordComposition *comp = 0;
173  Odr_int present_dummy;
174  const char *element_set_name = 0;
175  mp::util::piggyback_sr(sreq, result_set_size,
176  present_dummy, &element_set_name);
177  if (element_set_name)
178  {
179  comp = (Z_RecordComposition *) odr_malloc(odr, sizeof(*comp));
180  comp->which = Z_RecordComp_simple;
181  comp->u.simple = (Z_ElementSetNames *)
182  odr_malloc(odr, sizeof(Z_ElementSetNames));
183  comp->u.simple->which = Z_ElementSetNames_generic;
184  comp->u.simple->u.generic = odr_strdup(odr, element_set_name);
185  }
186  return comp;
187 }
188 
189 void mp_util::piggyback_sr(Z_SearchRequest *sreq,
190  Odr_int result_set_size,
191  Odr_int &number_to_present,
192  const char **element_set_name)
193 {
194  Z_ElementSetNames *esn;
195  const char *smallSetElementSetNames = 0;
196  const char *mediumSetElementSetNames = 0;
197 
198  esn = sreq->smallSetElementSetNames;
199  if (esn && esn->which == Z_ElementSetNames_generic)
200  smallSetElementSetNames = esn->u.generic;
201 
202  esn = sreq->mediumSetElementSetNames;
203  if (esn && esn->which == Z_ElementSetNames_generic)
204  mediumSetElementSetNames = esn->u.generic;
205 
206  piggyback(*sreq->smallSetUpperBound,
207  *sreq->largeSetLowerBound,
208  *sreq->mediumSetPresentNumber,
209  smallSetElementSetNames,
210  mediumSetElementSetNames,
211  result_set_size,
212  number_to_present,
213  element_set_name);
214 }
215 
216 void mp_util::piggyback(int smallSetUpperBound,
217  int largeSetLowerBound,
218  int mediumSetPresentNumber,
219  int result_set_size,
220  int &number_to_present)
221 {
222  Odr_int tmp = number_to_present;
223  piggyback(smallSetUpperBound, largeSetLowerBound, mediumSetPresentNumber,
224  0, 0, result_set_size, tmp, 0);
225  number_to_present = tmp;
226 }
227 
228 void mp_util::piggyback(Odr_int smallSetUpperBound,
229  Odr_int largeSetLowerBound,
230  Odr_int mediumSetPresentNumber,
231  const char *smallSetElementSetNames,
232  const char *mediumSetElementSetNames,
233  Odr_int result_set_size,
234  Odr_int &number_to_present,
235  const char **element_set_name)
236 {
237  // deal with piggyback
238 
239  if (result_set_size < smallSetUpperBound)
240  {
241  // small set . Return all records in set
242  number_to_present = result_set_size;
243  if (element_set_name && smallSetElementSetNames)
244  *element_set_name = smallSetElementSetNames;
245 
246  }
247  else if (result_set_size > largeSetLowerBound)
248  {
249  // large set . Return no records
250  number_to_present = 0;
251  if (element_set_name)
252  *element_set_name = 0;
253  }
254  else
255  {
256  // medium set . Return mediumSetPresentNumber records
257  number_to_present = mediumSetPresentNumber;
258  if (number_to_present > result_set_size)
259  number_to_present = result_set_size;
260  if (element_set_name && mediumSetElementSetNames)
261  *element_set_name = mediumSetElementSetNames;
262  }
263 }
264 
265 bool mp_util::pqf(ODR odr, Z_APDU *apdu, const std::string &q)
266 {
267  YAZ_PQF_Parser pqf_parser = yaz_pqf_create();
268 
269  Z_RPNQuery *rpn = yaz_pqf_parse(pqf_parser, odr, q.c_str());
270  if (!rpn)
271  {
272  yaz_pqf_destroy(pqf_parser);
273  return false;
274  }
275  yaz_pqf_destroy(pqf_parser);
276  Z_Query *query = (Z_Query *) odr_malloc(odr, sizeof(Z_Query));
277  query->which = Z_Query_type_1;
278  query->u.type_1 = rpn;
279 
280  apdu->u.searchRequest->query = query;
281  return true;
282 }
283 
284 
285 std::string mp_util::zQueryToString(Z_Query *query)
286 {
287  std::string query_str = "";
288 
289  if (query && query->which == Z_Query_type_1)
290  {
291  Z_RPNQuery *rpn = query->u.type_1;
292 
293  if (rpn)
294  {
295  mp::wrbuf w;
296 
297  // put query in w
298  yaz_rpnquery_to_wrbuf(w, rpn);
299 
300  // from w to std::string
301  query_str = std::string(w.buf(), w.len());
302  }
303  }
304 
305 #if 0
306  if (query && query->which == Z_Query_type_1){
307 
308  // allocate wrbuf (strings in YAZ!)
309  WRBUF w = wrbuf_alloc();
310 
311  // put query in w
312  yaz_query_to_wrbuf(w, query);
313 
314  // from w to std::string
315  query_str = std::string(wrbuf_buf(w), wrbuf_len(w));
316 
317  // destroy wrbuf
318  wrbuf_free(w, 1);
319  }
320 #endif
321  return query_str;
322 }
323 
324 void mp_util::get_default_diag(Z_DefaultDiagFormat *r,
325  int &error_code, std::string &addinfo)
326 {
327  error_code = *r->condition;
328  switch (r->which)
329  {
330  case Z_DefaultDiagFormat_v2Addinfo:
331  addinfo = std::string(r->u.v2Addinfo);
332  break;
333  case Z_DefaultDiagFormat_v3Addinfo:
334  addinfo = r->u.v3Addinfo;
335  break;
336  }
337 }
338 
339 void mp_util::get_init_diagnostics(
340  Z_InitResponse *initrs, int &error_code, std::string &addinfo)
341 {
342 
343  Z_DefaultDiagFormat *df = yaz_decode_init_diag(0, initrs);
344 
345  if (df)
346  get_default_diag(df, error_code, addinfo);
347 }
348 
349 int mp_util::get_or_remove_vhost_otherinfo(
350  Z_OtherInformation **otherInformation,
351  bool remove_flag,
352  std::list<std::string> &vhosts)
353 {
354  int cat;
355  for (cat = 1; ; cat++)
356  {
357  // check virtual host
358  const char *vhost =
359  yaz_oi_get_string_oid(otherInformation,
360  yaz_oid_userinfo_proxy,
361  cat /* categoryValue */,
362  remove_flag /* delete flag */);
363  if (!vhost)
364  break;
365  vhosts.push_back(std::string(vhost));
366  }
367  --cat;
368  return cat;
369 }
370 
371 void mp_util::get_vhost_otherinfo(
372  Z_OtherInformation *otherInformation,
373  std::list<std::string> &vhosts)
374 {
375  get_or_remove_vhost_otherinfo(&otherInformation, false, vhosts);
376 }
377 
378 int mp_util::remove_vhost_otherinfo(
379  Z_OtherInformation **otherInformation,
380  std::list<std::string> &vhosts)
381 {
382  return get_or_remove_vhost_otherinfo(otherInformation, true, vhosts);
383 }
384 
385 void mp_util::set_vhost_otherinfo(
386  Z_OtherInformation **otherInformation, ODR odr,
387  const std::list<std::string> &vhosts)
388 {
389  int cat;
390  std::list<std::string>::const_iterator it = vhosts.begin();
391 
392  for (cat = 1; it != vhosts.end() ; cat++, it++)
393  {
394  yaz_oi_set_string_oid(otherInformation, odr,
395  yaz_oid_userinfo_proxy, cat, it->c_str());
396  }
397 }
398 
399 void mp_util::set_vhost_otherinfo(
400  Z_OtherInformation **otherInformation, ODR odr,
401  const std::string vhost, const int cat)
402 {
403  yaz_oi_set_string_oid(otherInformation, odr,
404  yaz_oid_userinfo_proxy, cat, vhost.c_str());
405 }
406 
407 void mp_util::split_zurl(std::string zurl, std::string &host,
408  std::list<std::string> &db)
409 {
410  const char *zurl_cstr = zurl.c_str();
411  const char *args = 0;
412  cs_get_host_args(zurl_cstr, &args);
413 
414  if (args && *args)
415  {
416  host = std::string(zurl_cstr, args - zurl_cstr - 1);
417 
418  const char *cp1 = args;
419  while (1)
420  {
421  const char *cp2 = strchr(cp1, '+');
422  if (cp2)
423  db.push_back(std::string(cp1, cp2 - cp1));
424  else
425  {
426  db.push_back(std::string(cp1));
427  break;
428  }
429  cp1 = cp2+1;
430  }
431  }
432  else
433  host = zurl;
434 }
435 
436 bool mp_util::set_databases_from_zurl(
437  ODR odr, std::string zurl,
438  int *db_num, char ***db_strings)
439 {
440  std::string host;
441  std::list<std::string> dblist;
442 
443  split_zurl(zurl, host, dblist);
444 
445  if (dblist.size() == 0)
446  return false;
447  *db_num = dblist.size();
448  *db_strings = (char **) odr_malloc(odr, sizeof(char*) * (*db_num));
449 
450  std::list<std::string>::const_iterator it = dblist.begin();
451  for (int i = 0; it != dblist.end(); it++, i++)
452  (*db_strings)[i] = odr_strdup(odr, it->c_str());
453  return true;
454 }
455 
456 mp::odr::odr(int type)
457 {
458  m_odr = odr_createmem(type);
459 }
460 
461 mp::odr::odr()
462 {
463  m_odr = odr_createmem(ODR_ENCODE);
464 }
465 
466 mp::odr::~odr()
467 {
468  odr_destroy(m_odr);
469 }
470 
471 mp::odr::operator ODR() const
472 {
473  return m_odr;
474 }
475 
476 Z_APDU *mp::odr::create_close(const Z_APDU *in_apdu,
477  int reason, const char *addinfo)
478 {
479  Z_APDU *apdu = create_APDU(Z_APDU_close, in_apdu);
480 
481  *apdu->u.close->closeReason = reason;
482  if (addinfo)
483  apdu->u.close->diagnosticInformation = odr_strdup(m_odr, addinfo);
484  return apdu;
485 }
486 
487 Z_APDU *mp::odr::create_APDU(int type, const Z_APDU *in_apdu)
488 {
489  return mp::util::create_APDU(m_odr, type, in_apdu);
490 }
491 
492 Z_APDU *mp_util::create_APDU(ODR odr, int type, const Z_APDU *in_apdu)
493 {
494  Z_APDU *out_apdu = zget_APDU(odr, type);
495  transfer_referenceId(odr, in_apdu, out_apdu);
496  return out_apdu;
497 }
498 
499 void mp_util::transfer_referenceId(ODR odr, const Z_APDU *src, Z_APDU *dst)
500 {
501  Z_ReferenceId **id_to = mp::util::get_referenceId(dst);
502  *id_to = 0;
503  if (src)
504  {
505  Z_ReferenceId **id_from = mp::util::get_referenceId(src);
506  if (id_from && *id_from)
507  *id_to = odr_create_Odr_oct(odr, (*id_from)->buf,
508  (*id_from)->len);
509  }
510 }
511 
512 Z_APDU *mp::odr::create_initResponse(const Z_APDU *in_apdu,
513  int error, const char *addinfo)
514 {
515  Z_APDU *apdu = create_APDU(Z_APDU_initResponse, in_apdu);
516  if (error)
517  {
518  apdu->u.initResponse->userInformationField =
519  zget_init_diagnostics(m_odr, error, addinfo);
520  *apdu->u.initResponse->result = 0;
521  }
522  apdu->u.initResponse->implementationName =
523  odr_prepend(m_odr, "Metaproxy",
524  apdu->u.initResponse->implementationName);
525  apdu->u.initResponse->implementationVersion =
526  odr_prepend(m_odr,
527  VERSION, apdu->u.initResponse->implementationVersion);
528 
529  return apdu;
530 }
531 
532 Z_APDU *mp::odr::create_searchResponse(const Z_APDU *in_apdu,
533  int error, const char *addinfo)
534 {
535  Z_APDU *apdu = create_APDU(Z_APDU_searchResponse, in_apdu);
536  if (error)
537  {
538  Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
539  *apdu->u.searchResponse->searchStatus = 0;
540  apdu->u.searchResponse->records = rec;
541  rec->which = Z_Records_NSD;
542  rec->u.nonSurrogateDiagnostic =
543  zget_DefaultDiagFormat(m_odr, error, addinfo);
544 
545  }
546  return apdu;
547 }
548 
549 Z_APDU *mp::odr::create_presentResponse(const Z_APDU *in_apdu,
550  int error, const char *addinfo)
551 {
552  Z_APDU *apdu = create_APDU(Z_APDU_presentResponse, in_apdu);
553  if (error)
554  {
555  Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records));
556  apdu->u.presentResponse->records = rec;
557 
558  rec->which = Z_Records_NSD;
559  rec->u.nonSurrogateDiagnostic =
560  zget_DefaultDiagFormat(m_odr, error, addinfo);
561  *apdu->u.presentResponse->presentStatus = Z_PresentStatus_failure;
562  }
563  return apdu;
564 }
565 
566 Z_APDU *mp::odr::create_scanResponse(const Z_APDU *in_apdu,
567  int error, const char *addinfo)
568 {
569  Z_APDU *apdu = create_APDU(Z_APDU_scanResponse, in_apdu);
570  Z_ScanResponse *res = apdu->u.scanResponse;
571  res->entries = (Z_ListEntries *) odr_malloc(m_odr, sizeof(*res->entries));
572  res->entries->num_entries = 0;
573  res->entries->entries = 0;
574 
575  if (error)
576  {
577  *res->scanStatus = Z_Scan_failure;
578 
579  res->entries->num_nonsurrogateDiagnostics = 1;
580  res->entries->nonsurrogateDiagnostics = (Z_DiagRec **)
581  odr_malloc(m_odr, sizeof(Z_DiagRec *));
582  res->entries->nonsurrogateDiagnostics[0] =
583  zget_DiagRec(m_odr, error, addinfo);
584  }
585  else
586  {
587  res->entries->num_nonsurrogateDiagnostics = 0;
588  res->entries->nonsurrogateDiagnostics = 0;
589  }
590  return apdu;
591 }
592 
593 Z_GDU *mp::odr::create_HTTP_Response_details(mp::Session &session,
594  Z_HTTP_Request *hreq, int code,
595  const char *details)
596 {
597  const char *response_version = "1.0";
598  bool keepalive = false;
599  if (!strcmp(hreq->version, "1.0"))
600  {
601  const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
602  if (v && !strcmp(v, "Keep-Alive"))
603  keepalive = true;
604  else
605  session.close();
606  response_version = "1.0";
607  }
608  else
609  {
610  const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
611  if (v && !strcmp(v, "close"))
612  session.close();
613  else
614  keepalive = true;
615  response_version = "1.1";
616  }
617 
618  Z_GDU *gdu = z_get_HTTP_Response_server(
619  m_odr, code, details, "Metaproxy/" VERSION,
620  "http://www.indexdata.com/metaproxy");
621  Z_HTTP_Response *hres = gdu->u.HTTP_Response;
622  hres->version = odr_strdup(m_odr, response_version);
623  if (keepalive)
624  z_HTTP_header_add(m_odr, &hres->headers, "Connection", "Keep-Alive");
625  return gdu;
626 }
627 
628 Z_GDU *mp::odr::create_HTTP_Response(mp::Session &session,
629  Z_HTTP_Request *hreq, int code)
630 {
631  return create_HTTP_Response_details(session, hreq, code, 0);
632 
633 }
634 
635 Z_ReferenceId **mp_util::get_referenceId(const Z_APDU *apdu)
636 {
637  switch (apdu->which)
638  {
639  case Z_APDU_initRequest:
640  return &apdu->u.initRequest->referenceId;
641  case Z_APDU_initResponse:
642  return &apdu->u.initResponse->referenceId;
643  case Z_APDU_searchRequest:
644  return &apdu->u.searchRequest->referenceId;
645  case Z_APDU_searchResponse:
646  return &apdu->u.searchResponse->referenceId;
647  case Z_APDU_presentRequest:
648  return &apdu->u.presentRequest->referenceId;
649  case Z_APDU_presentResponse:
650  return &apdu->u.presentResponse->referenceId;
651  case Z_APDU_deleteResultSetRequest:
652  return &apdu->u.deleteResultSetRequest->referenceId;
653  case Z_APDU_deleteResultSetResponse:
654  return &apdu->u.deleteResultSetResponse->referenceId;
655  case Z_APDU_accessControlRequest:
656  return &apdu->u.accessControlRequest->referenceId;
657  case Z_APDU_accessControlResponse:
658  return &apdu->u.accessControlResponse->referenceId;
659  case Z_APDU_resourceControlRequest:
660  return &apdu->u.resourceControlRequest->referenceId;
661  case Z_APDU_resourceControlResponse:
662  return &apdu->u.resourceControlResponse->referenceId;
663  case Z_APDU_triggerResourceControlRequest:
664  return &apdu->u.triggerResourceControlRequest->referenceId;
665  case Z_APDU_resourceReportRequest:
666  return &apdu->u.resourceReportRequest->referenceId;
667  case Z_APDU_resourceReportResponse:
668  return &apdu->u.resourceReportResponse->referenceId;
669  case Z_APDU_scanRequest:
670  return &apdu->u.scanRequest->referenceId;
671  case Z_APDU_scanResponse:
672  return &apdu->u.scanResponse->referenceId;
673  case Z_APDU_sortRequest:
674  return &apdu->u.sortRequest->referenceId;
675  case Z_APDU_sortResponse:
676  return &apdu->u.sortResponse->referenceId;
677  case Z_APDU_segmentRequest:
678  return &apdu->u.segmentRequest->referenceId;
679  case Z_APDU_extendedServicesRequest:
680  return &apdu->u.extendedServicesRequest->referenceId;
681  case Z_APDU_extendedServicesResponse:
682  return &apdu->u.extendedServicesResponse->referenceId;
683  case Z_APDU_close:
684  return &apdu->u.close->referenceId;
685  }
686  return 0;
687 }
688 
689 std::string mp_util::uri_encode(std::string s)
690 {
691  char *x = (char *) xmalloc(1 + s.length() * 3);
692  yaz_encode_uri_component(x, s.c_str());
693  std::string result(x);
694  xfree(x);
695  return result;
696 }
697 
698 
699 std::string mp_util::uri_decode(std::string s)
700 {
701  char *x = (char *) xmalloc(1 + s.length());
702  yaz_decode_uri_component(x, s.c_str(), s.length());
703  std::string result(x);
704  xfree(x);
705  return result;
706 }
707 
708 mp::wrbuf::wrbuf()
709 {
710  m_wrbuf = wrbuf_alloc();
711 }
712 
713 mp::wrbuf::~wrbuf()
714 {
715  wrbuf_destroy(m_wrbuf);
716 }
717 
718 mp::wrbuf::operator WRBUF() const
719 {
720  return m_wrbuf;
721 }
722 
723 size_t mp::wrbuf::len()
724 {
725  return wrbuf_len(m_wrbuf);
726 }
727 
728 const char *mp::wrbuf::buf()
729 {
730  return wrbuf_buf(m_wrbuf);
731 }
732 
733 const char *mp::wrbuf::c_str()
734 {
735  return wrbuf_cstr(m_wrbuf);
736 }
737 
738 const char *mp::wrbuf::c_str_null()
739 {
740  return wrbuf_cstr_null(m_wrbuf);
741 }
742 
743 bool mp::util::match_ip(const std::string &pattern, const std::string &value)
744 {
745  std::vector<std::string> globitems;
746  // split may produce empty strings as results - in particular
747  // the empty pattern produces one empty string (vector size 1)
748  boost::split(globitems, pattern, boost::is_any_of(" "));
749  bool ret_value = true; // for now (if only empty values)
750  std::vector<std::string>::const_iterator it = globitems.begin();
751  for (; it != globitems.end(); it++)
752  {
753  const char *c_str = (*it).c_str();
754  if (*c_str)
755  {
756  ret_value = false; // at least one non-empty value
757  if (yaz_match_glob(c_str, value.c_str()))
758  return true;
759  }
760  }
761  return ret_value;
762 }
763 
764 /*
765  * Local variables:
766  * c-basic-offset: 4
767  * c-file-style: "Stroustrup"
768  * indent-tabs-mode: nil
769  * End:
770  * vim: shiftwidth=4 tabstop=8 expandtab
771  */
772 
static const int result_set_size
#define VERSION
Definition: config.hpp:86