YAZ  4.2.60
srwutil.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <stdlib.h>
14 #include <assert.h>
15 #include <yaz/srw.h>
16 #include <yaz/matchstr.h>
17 #include <yaz/base64.h>
18 #include <yaz/yaz-iconv.h>
19 #include "sru-p.h"
20 
21 #define MAX_SRU_PARAMETERS 30
22 
23 static char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
24 {
25  return odr_strdupn(n, uri, len);
26 }
27 
28 void yaz_encode_sru_dbpath_buf(char *dst, const char *db)
29 {
30  assert(db);
31  *dst = '/';
32  strcpy(dst+1, db);
33 }
34 
35 char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
36 {
37  char *dst = odr_malloc(out, 3 * strlen(db) + 2);
39  return dst;
40 }
41 
43 {
44  Z_AttributeList *attributes= (Z_AttributeList *)
45  odr_malloc(o, sizeof(*attributes));
46  Z_AttributeElement ** elements;
47  attributes->num_attributes = 1;
48  elements = (Z_AttributeElement**)
49  odr_malloc(o, attributes->num_attributes * sizeof(*elements));
50  elements[0] = (Z_AttributeElement*) odr_malloc(o,sizeof(**elements));
51  elements[0]->attributeType = odr_intdup(o, 1);
52  elements[0]->attributeSet = odr_nullval();
53  elements[0]->which = Z_AttributeValue_complex;
54  elements[0]->value.complex = (Z_ComplexAttribute *)
55  odr_malloc(o, sizeof(Z_ComplexAttribute));
56  elements[0]->value.complex->num_list = 1;
57  elements[0]->value.complex->list = (Z_StringOrNumeric **)
58  odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *));
59  elements[0]->value.complex->list[0] = (Z_StringOrNumeric *)
60  odr_malloc(o, sizeof(Z_StringOrNumeric));
61  elements[0]->value.complex->list[0]->which = Z_StringOrNumeric_string;
62  elements[0]->value.complex->list[0]->u.string = odr_strdup(o, name);
63  elements[0]->value.complex->semanticAction = 0;
64  elements[0]->value.complex->num_semanticAction = 0;
65  attributes->attributes = elements;
66  return attributes;
67 }
68 
69 #if YAZ_HAVE_XML2
70 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
71  const char *node_name,
72  const char *attribute_name)
73 {
74  struct _xmlAttr *attr;
75  // check if the node name matches
76  if (strcmp((const char*) ptr->name, node_name))
77  return 0;
78  // check if the attribute name and return the value
79  for (attr = ptr->properties; attr; attr = attr->next)
80  if (attr->children && attr->children->type == XML_TEXT_NODE)
81  {
82  if (!strcmp((const char *) attr->name, attribute_name))
83  return (const char *) attr->children->content;
84  }
85  return 0;
86 }
87 #endif
88 
90 {
91  const char *content_type = z_HTTP_header_lookup(hres->headers,
92  "Content-Type");
93  if (content_type)
94  {
95  if (!yaz_strcmp_del("text/xml", content_type, "; "))
96  return 1;
97  if (!yaz_strcmp_del("application/xml", content_type, "; "))
98  return 1;
99  }
100  return 0;
101 }
102 
108  char *username, char *password, ODR decode)
109 {
110  const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
111 
112  if (username)
113  sr->username = username;
114  if (password)
115  sr->password = password;
116 
117  if (basic)
118  {
119  int len;
120  char out[256];
121  char ubuf[256] = "", pbuf[256] = "", *p;
122  if (strncmp(basic, "Basic ", 6))
123  return;
124  basic += 6;
125  len = strlen(basic);
126  if (!len || len > 256)
127  return;
128  yaz_base64decode(basic, out);
129  /* Format of out should be username:password at this point */
130  strcpy(ubuf, out);
131  if ((p = strchr(ubuf, ':')))
132  {
133  *(p++) = '\0';
134  if (*p)
135  strcpy(pbuf, p);
136  }
137  if (*ubuf)
138  sr->username = odr_strdup(decode, ubuf);
139  if (*pbuf)
140  sr->password = odr_strdup(decode, pbuf);
141  }
142 }
143 
144 void yaz_uri_val_int(const char *path, const char *name, ODR o, Odr_int **intp)
145 {
146  const char *v = yaz_uri_val(path, name, o);
147  if (v)
148  *intp = odr_intdup(o, atoi(v));
149 }
150 
152  const char *uri, const char *message,
153  const char *details)
154 {
155  d->uri = odr_strdup(o, uri);
156  if (message)
157  d->message = odr_strdup(o, message);
158  else
159  d->message = 0;
160  if (details)
161  d->details = odr_strdup(o, details);
162  else
163  d->details = 0;
164 }
165 
167  int code, const char *details)
168 {
169  char uri[40];
170 
171  sprintf(uri, "info:srw/diagnostic/1/%d", code);
172  yaz_mk_srw_diagnostic(o, d, uri, 0, details);
173 }
174 
176  int *num, const char *uri,
177  const char *message, const char *details)
178 {
179  Z_SRW_diagnostic *d_new;
180  d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
181  if (*num)
182  memcpy(d_new, *d, *num *sizeof(**d));
183  *d = d_new;
184 
185  yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
186  (*num)++;
187 }
188 
190  int *num, int code, const char *addinfo)
191 {
192  char uri[40];
193 
194  sprintf(uri, "info:srw/diagnostic/1/%d", code);
195  yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
196 }
197 
198 
200  int *num, int code, const char *addinfo)
201 {
202  char uri[40];
203 
204  sprintf(uri, "info:srw/diagnostic/12/%d", code);
205  yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
206 }
207 
208 
209 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
210  int code, const char *details)
211 {
212  const char *message = yaz_diag_srw_str(code);
213  int len = 200;
214  if (message)
215  len += strlen(message);
216  if (details)
217  len += strlen(details);
218 
219  record->recordData_buf = (char *) odr_malloc(o, len);
220 
221  sprintf(record->recordData_buf, "<diagnostic "
222  "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
223  " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
224  if (details)
225  sprintf(record->recordData_buf + strlen(record->recordData_buf),
226  " <details>%s</details>\n", details);
227  if (message)
228  sprintf(record->recordData_buf + strlen(record->recordData_buf),
229  " <message>%s</message>\n", message);
230  sprintf(record->recordData_buf + strlen(record->recordData_buf),
231  "</diagnostic>\n");
232  record->recordData_len = strlen(record->recordData_buf);
233  record->recordPosition = odr_intdup(o, pos);
234  record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
235 }
236 
237 static void grab_charset(ODR o, const char *content_type, char **charset)
238 {
239  if (charset)
240  {
241  const char *charset_p = 0;
242  if (content_type && (charset_p = strstr(content_type, "; charset=")))
243  {
244  int i = 0;
245  charset_p += 10;
246  while (i < 20 && charset_p[i] &&
247  !strchr("; \n\r", charset_p[i]))
248  i++;
249  *charset = (char*) odr_malloc(o, i+1);
250  memcpy(*charset, charset_p, i);
251  (*charset)[i] = '\0';
252  }
253  }
254 }
255 
257  Z_SOAP **soap_package, ODR decode, char **charset)
258 {
259  if (!strcmp(hreq->method, "POST"))
260  {
261  const char *content_type = z_HTTP_header_lookup(hreq->headers,
262  "Content-Type");
263  if (content_type &&
264  (!yaz_strcmp_del("text/xml", content_type, "; ") ||
265  !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
266  !yaz_strcmp_del("text/plain", content_type, "; ")))
267  {
268  char *db = "Default";
269  const char *p0 = hreq->path, *p1;
270  int ret = -1;
271 
272  static Z_SOAP_Handler soap_handlers[4] = {
273 #if YAZ_HAVE_XML2
277 #endif
278  {0, 0, 0}
279  };
280 
281  if (*p0 == '/')
282  p0++;
283  p1 = strchr(p0, '?');
284  if (!p1)
285  p1 = p0 + strlen(p0);
286  if (p1 != p0)
287  db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
288  grab_charset(decode, content_type, charset);
289 
290  ret = z_soap_codec(decode, soap_package,
291  &hreq->content_buf, &hreq->content_len,
292  soap_handlers);
293  if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
294  {
295  *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
296  yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
297 
298  if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
299  (*srw_pdu)->u.request->database == 0)
300  (*srw_pdu)->u.request->database = db;
301 
302  if ((*srw_pdu)->which == Z_SRW_explain_request &&
303  (*srw_pdu)->u.explain_request->database == 0)
304  (*srw_pdu)->u.explain_request->database = db;
305 
306  if ((*srw_pdu)->which == Z_SRW_scan_request &&
307  (*srw_pdu)->u.scan_request->database == 0)
308  (*srw_pdu)->u.scan_request->database = db;
309 
310  if ((*srw_pdu)->which == Z_SRW_update_request &&
311  (*srw_pdu)->u.update_request->database == 0)
312  (*srw_pdu)->u.update_request->database = db;
313 
314  return 0;
315  }
316  return 1;
317  }
318  }
319  return 2;
320 }
321 
322 #if YAZ_HAVE_XML2
323 static int yaz_sru_decode_integer(ODR odr, const char *pname,
324  const char *valstr, Odr_int **valp,
325  Z_SRW_diagnostic **diag, int *num_diag,
326  int min_value)
327 {
328  int ival;
329  if (!valstr)
330  return 0;
331  if (sscanf(valstr, "%d", &ival) != 1)
332  {
333  yaz_add_srw_diagnostic(odr, diag, num_diag,
335  return 0;
336  }
337  if (min_value >= 0 && ival < min_value)
338  {
339  yaz_add_srw_diagnostic(odr, diag, num_diag,
341  return 0;
342  }
343  *valp = odr_intdup(odr, ival);
344  return 1;
345 }
346 #endif
347 
352  Z_SOAP **soap_package, ODR decode, char **charset,
353  Z_SRW_diagnostic **diag, int *num_diag)
354 {
355 #if YAZ_HAVE_XML2
356  static Z_SOAP_Handler soap_handlers[2] = {
358  {0, 0, 0}
359  };
360 #endif
361  const char *content_type = z_HTTP_header_lookup(hreq->headers,
362  "Content-Type");
363 
364  /*
365  SRU GET: ignore content type.
366  SRU POST: we support "application/x-www-form-urlencoded";
367  not "multipart/form-data" .
368  */
369  if (!strcmp(hreq->method, "GET")
370  ||
371  (!strcmp(hreq->method, "POST") && content_type &&
372  !yaz_strcmp_del("application/x-www-form-urlencoded",
373  content_type, "; ")))
374  {
375  char *db = "Default";
376  const char *p0 = hreq->path, *p1;
377 #if YAZ_HAVE_XML2
378  const char *operation = 0;
379  char *version = 0;
380  char *query = 0;
381  char *pQuery = 0;
382  char *username = 0;
383  char *password = 0;
384  char *sortKeys = 0;
385  char *stylesheet = 0;
386  char *scanClause = 0;
387  char *pScanClause = 0;
388  char *recordXPath = 0;
389  char *recordSchema = 0;
390  char *recordPacking = "xml"; /* xml packing is default for SRU */
391  char *maximumRecords = 0;
392  char *startRecord = 0;
393  char *maximumTerms = 0;
394  char *responsePosition = 0;
395  Z_SRW_extra_arg *extra_args = 0;
396 #endif
397  char **uri_name;
398  char **uri_val;
399 
400  grab_charset(decode, content_type, charset);
401  if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
402  *charset = "UTF-8";
403 
404  if (*p0 == '/')
405  p0++;
406  p1 = strchr(p0, '?');
407  if (!p1)
408  p1 = p0 + strlen(p0);
409  if (p1 != p0)
410  db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
411  if (!strcmp(hreq->method, "POST"))
412  p1 = hreq->content_buf;
413  yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
414 #if YAZ_HAVE_XML2
415  if (uri_name)
416  {
417  int i;
418  for (i = 0; uri_name[i]; i++)
419  {
420  char *n = uri_name[i];
421  char *v = uri_val[i];
422  if (!strcmp(n, "query"))
423  query = v;
424  else if (!strcmp(n, "x-pquery"))
425  pQuery = v;
426  else if (!strcmp(n, "x-username"))
427  username = v;
428  else if (!strcmp(n, "x-password"))
429  password = v;
430  else if (!strcmp(n, "operation"))
431  operation = v;
432  else if (!strcmp(n, "stylesheet"))
433  stylesheet = v;
434  else if (!strcmp(n, "sortKeys"))
435  sortKeys = v;
436  else if (!strcmp(n, "recordXPath"))
437  recordXPath = v;
438  else if (!strcmp(n, "recordSchema"))
439  recordSchema = v;
440  else if (!strcmp(n, "recordPacking"))
441  recordPacking = v;
442  else if (!strcmp(n, "version"))
443  version = v;
444  else if (!strcmp(n, "scanClause"))
445  scanClause = v;
446  else if (!strcmp(n, "x-pScanClause"))
447  pScanClause = v;
448  else if (!strcmp(n, "maximumRecords"))
449  maximumRecords = v;
450  else if (!strcmp(n, "startRecord"))
451  startRecord = v;
452  else if (!strcmp(n, "maximumTerms"))
453  maximumTerms = v;
454  else if (!strcmp(n, "responsePosition"))
455  responsePosition = v;
456  else if (!strcmp(n, "extraRequestData"))
457  ; /* ignoring extraRequestData */
458  else if (n[0] == 'x' && n[1] == '-')
459  {
460  Z_SRW_extra_arg **l = &extra_args;
461  while (*l)
462  l = &(*l)->next;
463  *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
464  (*l)->name = odr_strdup(decode, n);
465  (*l)->value = odr_strdup(decode, v);
466  (*l)->next = 0;
467  }
468  else
469  {
470  if (*num_diag < 10)
471  yaz_add_srw_diagnostic(decode, diag, num_diag,
473  }
474  }
475  }
476  if (!version)
477  {
478  if (uri_name)
480  decode, diag, num_diag,
482  version = "1.1";
483  }
484 
485  version = yaz_negotiate_sru_version(version);
486 
487  if (!version)
488  { /* negotiation failed. */
489  yaz_add_srw_diagnostic(decode, diag, num_diag,
490  YAZ_SRW_UNSUPP_VERSION, "1.2");
491  version = "1.2";
492  }
493 
494  if (!operation)
495  {
496  if (uri_name)
498  decode, diag, num_diag,
500  operation = "explain";
501  }
502  if (!strcmp(operation, "searchRetrieve"))
503  {
505 
506  sr->srw_version = version;
507  sr->extra_args = extra_args;
508  *srw_pdu = sr;
509  yaz_srw_decodeauth(sr, hreq, username, password, decode);
510  if (query)
511  {
513  sr->u.request->query.cql = query;
514  }
515  else if (pQuery)
516  {
518  sr->u.request->query.pqf = pQuery;
519  }
520  else
522  decode, diag, num_diag,
524 
525  if (sortKeys)
526  {
528  sr->u.request->sort.sortKeys = sortKeys;
529  }
530  sr->u.request->recordXPath = recordXPath;
531  sr->u.request->recordSchema = recordSchema;
532  sr->u.request->recordPacking = recordPacking;
533  sr->u.request->stylesheet = stylesheet;
534 
535  yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
536  &sr->u.request->maximumRecords,
537  diag, num_diag, 0);
538 
539  yaz_sru_decode_integer(decode, "startRecord", startRecord,
540  &sr->u.request->startRecord,
541  diag, num_diag, 1);
542 
543  sr->u.request->database = db;
544 
545  (*soap_package) = (Z_SOAP *)
546  odr_malloc(decode, sizeof(**soap_package));
547  (*soap_package)->which = Z_SOAP_generic;
548 
549  (*soap_package)->u.generic = (Z_SOAP_Generic *)
550  odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
551 
552  (*soap_package)->u.generic->p = sr;
553  (*soap_package)->u.generic->ns = soap_handlers[0].ns;
554  (*soap_package)->u.generic->no = 0;
555 
556  (*soap_package)->ns = "SRU";
557 
558  return 0;
559  }
560  else if (!strcmp(operation, "explain"))
561  {
562  /* Transfer SRU explain parameters to common struct */
563  /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
565 
566  sr->srw_version = version;
567  sr->extra_args = extra_args;
568  yaz_srw_decodeauth(sr, hreq, username, password, decode);
569  *srw_pdu = sr;
570  sr->u.explain_request->recordPacking = recordPacking;
571  sr->u.explain_request->database = db;
572 
573  sr->u.explain_request->stylesheet = stylesheet;
574 
575  (*soap_package) = (Z_SOAP *)
576  odr_malloc(decode, sizeof(**soap_package));
577  (*soap_package)->which = Z_SOAP_generic;
578 
579  (*soap_package)->u.generic = (Z_SOAP_Generic *)
580  odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
581 
582  (*soap_package)->u.generic->p = sr;
583  (*soap_package)->u.generic->ns = soap_handlers[0].ns;
584  (*soap_package)->u.generic->no = 0;
585 
586  (*soap_package)->ns = "SRU";
587 
588  return 0;
589  }
590  else if (!strcmp(operation, "scan"))
591  {
592  /* Transfer SRU scan parameters to common struct */
593  /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
595 
596  sr->srw_version = version;
597  sr->extra_args = extra_args;
598  *srw_pdu = sr;
599  yaz_srw_decodeauth(sr, hreq, username, password, decode);
600 
601  if (scanClause)
602  {
604  sr->u.scan_request->scanClause.cql = scanClause;
605  }
606  else if (pScanClause)
607  {
609  sr->u.scan_request->scanClause.pqf = pScanClause;
610  }
611  else
613  decode, diag, num_diag,
615  sr->u.scan_request->database = db;
616 
617  yaz_sru_decode_integer(decode, "maximumTerms",
618  maximumTerms,
620  diag, num_diag, 0);
621 
622  yaz_sru_decode_integer(decode, "responsePosition",
623  responsePosition,
625  diag, num_diag, 0);
626 
627  sr->u.scan_request->stylesheet = stylesheet;
628 
629  (*soap_package) = (Z_SOAP *)
630  odr_malloc(decode, sizeof(**soap_package));
631  (*soap_package)->which = Z_SOAP_generic;
632 
633  (*soap_package)->u.generic = (Z_SOAP_Generic *)
634  odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
635 
636  (*soap_package)->u.generic->p = sr;
637  (*soap_package)->u.generic->ns = soap_handlers[0].ns;
638  (*soap_package)->u.generic->no = 0;
639 
640  (*soap_package)->ns = "SRU";
641 
642  return 0;
643  }
644  else
645  {
646  /* unsupported operation ... */
647  /* Act as if we received a explain request and throw diagnostic. */
648 
650 
651  sr->srw_version = version;
652  *srw_pdu = sr;
653  sr->u.explain_request->recordPacking = recordPacking;
654  sr->u.explain_request->database = db;
655 
656  sr->u.explain_request->stylesheet = stylesheet;
657 
658  (*soap_package) = (Z_SOAP *)
659  odr_malloc(decode, sizeof(**soap_package));
660  (*soap_package)->which = Z_SOAP_generic;
661 
662  (*soap_package)->u.generic = (Z_SOAP_Generic *)
663  odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
664 
665  (*soap_package)->u.generic->p = sr;
666  (*soap_package)->u.generic->ns = soap_handlers[0].ns;
667  (*soap_package)->u.generic->no = 0;
668 
669  (*soap_package)->ns = "SRU";
670 
671  yaz_add_srw_diagnostic(decode, diag, num_diag,
672  YAZ_SRW_UNSUPP_OPERATION, operation);
673  return 0;
674  }
675 #else
676  return 1;
677 #endif
678  }
679  return 2;
680 }
681 
683 {
685  odr_malloc(o, sizeof(*res));
686 
687  res->extraRecordData_buf = 0;
688  res->extraRecordData_len = 0;
689  res->recordIdentifier = 0;
690  return res;
691 }
692 
693 
695 {
696  Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
697  int i;
698 
699  for (i = 0; i<n; i++)
700  {
701  res[i].recordSchema = 0;
703  res[i].recordData_buf = 0;
704  res[i].recordData_len = 0;
705  res[i].recordPosition = 0;
706  }
707  return res;
708 }
709 
711 {
712  return yaz_srw_get_records(o, 1);
713 }
714 
715 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
716 {
717  Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
718  p->srw_version = odr_strdup(o, version);
719  p->username = 0;
720  p->password = 0;
721  p->extra_args = 0;
722  p->extraResponseData_buf = 0;
723  p->extraResponseData_len = 0;
724  return p;
725 }
726 
728 {
729  return yaz_srw_get_core_ver(o, "1.1");
730 }
731 
732 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
733 {
734  return yaz_srw_get_pdu(o, which, "1.1");
735 }
736 
737 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
738 {
739  Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
740 
741  sr->which = which;
742  switch(which)
743  {
746  odr_malloc(o, sizeof(*sr->u.request));
748  sr->u.request->query.cql = 0;
750  sr->u.request->sort.none = 0;
751  sr->u.request->startRecord = 0;
752  sr->u.request->maximumRecords = 0;
753  sr->u.request->recordSchema = 0;
754  sr->u.request->recordPacking = 0;
755  sr->u.request->recordXPath = 0;
756  sr->u.request->database = 0;
757  sr->u.request->resultSetTTL = 0;
758  sr->u.request->stylesheet = 0;
759  sr->u.request->facetList = 0;
760  break;
763  odr_malloc(o, sizeof(*sr->u.response));
764  sr->u.response->numberOfRecords = 0;
765  sr->u.response->resultSetId = 0;
766  sr->u.response->resultSetIdleTime = 0;
767  sr->u.response->records = 0;
768  sr->u.response->num_records = 0;
769  sr->u.response->diagnostics = 0;
770  sr->u.response->num_diagnostics = 0;
771  sr->u.response->nextRecordPosition = 0;
772  sr->u.response->extra_records = 0;
773  sr->u.response->facetList = 0;
774  sr->u.response->suggestions = 0;
775  break;
778  odr_malloc(o, sizeof(*sr->u.explain_request));
780  sr->u.explain_request->database = 0;
781  sr->u.explain_request->stylesheet = 0;
782  break;
785  odr_malloc(o, sizeof(*sr->u.explain_response));
792  sr->u.explain_response->diagnostics = 0;
795  break;
796  case Z_SRW_scan_request:
798  odr_malloc(o, sizeof(*sr->u.scan_request));
799  sr->u.scan_request->database = 0;
800  sr->u.scan_request->stylesheet = 0;
801  sr->u.scan_request->maximumTerms = 0;
804  sr->u.scan_request->scanClause.cql = 0;
805  break;
806  case Z_SRW_scan_response:
808  odr_malloc(o, sizeof(*sr->u.scan_response));
809  sr->u.scan_response->terms = 0;
810  sr->u.scan_response->num_terms = 0;
811  sr->u.scan_response->diagnostics = 0;
813  break;
816  odr_malloc(o, sizeof(*sr->u.update_request));
817  sr->u.update_request->database = 0;
818  sr->u.update_request->stylesheet = 0;
819  sr->u.update_request->record = 0;
820  sr->u.update_request->recordId = 0;
823  sr->u.update_request->extra_record = 0;
826  sr->u.request->database = 0;
827  break;
830  odr_malloc(o, sizeof(*sr->u.update_response));
832  sr->u.update_response->recordId = 0;
835  sr->u.update_response->record = 0;
836  sr->u.update_response->extra_record = 0;
839  sr->u.update_response->diagnostics = 0;
841  }
842  return sr;
843 }
844 
845 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
846  char *a_name, Odr_int *val)
847 {
848  if (val)
849  {
850  name[*i] = a_name;
851  value[*i] = (char *) odr_malloc(o, 40);
852  sprintf(value[*i], ODR_INT_PRINTF, *val);
853  (*i)++;
854  }
855 }
856 
857 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
858  char *a_name, char *val)
859 {
860  if (val)
861  {
862  name[*i] = a_name;
863  value[*i] = val;
864  (*i)++;
865  }
866 }
867 
868 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
869  char **name, char **value, int max_names)
870 {
871  int i = 0;
872  yaz_add_name_value_str(encode, name, value, &i, "version", srw_pdu->srw_version);
873  name[i] = "operation";
874  switch(srw_pdu->which)
875  {
877  value[i++] = "searchRetrieve";
878  switch(srw_pdu->u.request->query_type)
879  {
881  yaz_add_name_value_str(encode, name, value, &i, "query",
882  srw_pdu->u.request->query.cql);
883  break;
885  yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
886  srw_pdu->u.request->query.pqf);
887  break;
889  yaz_add_name_value_str(encode, name, value, &i, "x-cql",
890  srw_pdu->u.request->query.xcql);
891  break;
892  }
893  switch(srw_pdu->u.request->sort_type)
894  {
896  break;
898  yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
899  srw_pdu->u.request->sort.sortKeys);
900  break;
901  }
902  yaz_add_name_value_int(encode, name, value, &i, "startRecord",
903  srw_pdu->u.request->startRecord);
904  yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
905  srw_pdu->u.request->maximumRecords);
906  yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
907  srw_pdu->u.request->recordSchema);
908  yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
909  srw_pdu->u.request->recordPacking);
910  yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
911  srw_pdu->u.request->recordXPath);
912  yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
913  srw_pdu->u.request->stylesheet);
914  yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
915  srw_pdu->u.request->resultSetTTL);
916  break;
918  value[i++] = "explain";
919  yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
920  srw_pdu->u.explain_request->stylesheet);
921  break;
922  case Z_SRW_scan_request:
923  value[i++] = "scan";
924 
925  switch(srw_pdu->u.scan_request->query_type)
926  {
928  yaz_add_name_value_str(encode, name, value, &i, "scanClause",
929  srw_pdu->u.scan_request->scanClause.cql);
930  break;
932  yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
933  srw_pdu->u.scan_request->scanClause.pqf);
934  break;
936  yaz_add_name_value_str(encode, name, value, &i, "x-cqlScanClause",
937  srw_pdu->u.scan_request->scanClause.xcql);
938  break;
939  }
940  yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
941  srw_pdu->u.scan_request->responsePosition);
942  yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
943  srw_pdu->u.scan_request->maximumTerms);
944  yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
945  srw_pdu->u.scan_request->stylesheet);
946  break;
948  value[i++] = "update";
949  break;
950  default:
951  return -1;
952  }
953  if (srw_pdu->extra_args)
954  {
955  Z_SRW_extra_arg *ea = srw_pdu->extra_args;
956  for (; ea && i < max_names-1; ea = ea->next)
957  {
958  name[i] = ea->name;
959  value[i] = ea->value;
960  i++;
961  }
962  }
963  name[i++] = 0;
964 
965  return 0;
966 }
967 
969  ODR encode, const char *charset)
970 {
971  char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
972  char *uri_args;
973  char *path;
974 
975  z_HTTP_header_add_basic_auth(encode, &hreq->headers,
976  srw_pdu->username, srw_pdu->password);
977  if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
978  return -1;
979  yaz_array_to_uri(&uri_args, encode, name, value);
980 
981  hreq->method = "GET";
982 
983  path = (char *)
984  odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
985 
986  sprintf(path, "%s?%s", hreq->path, uri_args);
987  yaz_log(YLOG_DEBUG, "SRU HTTP Get Request %s", path);
988  hreq->path = path;
989 
991  "text/xml", charset);
992  return 0;
993 }
994 
996  ODR encode, const char *charset)
997 {
998  char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
999  char *uri_args;
1000 
1001  z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1002  srw_pdu->username, srw_pdu->password);
1003  if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1004  return -1;
1005 
1006  yaz_array_to_uri(&uri_args, encode, name, value);
1007 
1008  hreq->method = "POST";
1009 
1010  hreq->content_buf = uri_args;
1011  hreq->content_len = strlen(uri_args);
1012 
1013  z_HTTP_header_add_content_type(encode, &hreq->headers,
1014  "application/x-www-form-urlencoded",
1015  charset);
1016  return 0;
1017 }
1018 
1020  ODR odr, const char *charset)
1021 {
1022  Z_SOAP_Handler handlers[3] = {
1023 #if YAZ_HAVE_XML2
1026 #endif
1027  {0, 0, 0}
1028  };
1029  Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1030 
1032  srw_pdu->username, srw_pdu->password);
1034  &hreq->headers,
1035  "text/xml", charset);
1036 
1037  z_HTTP_header_add(odr, &hreq->headers,
1038  "SOAPAction", "\"\"");
1039  p->which = Z_SOAP_generic;
1040  p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1041  p->u.generic->no = 0;
1042  p->u.generic->ns = 0;
1043  p->u.generic->p = srw_pdu;
1044  p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1045 
1046 #if YAZ_HAVE_XML2
1047  if (srw_pdu->which == Z_SRW_update_request ||
1048  srw_pdu->which == Z_SRW_update_response)
1049  p->u.generic->no = 1; /* second handler */
1050 #endif
1051  return z_soap_codec_enc(odr, &p,
1052  &hreq->content_buf,
1053  &hreq->content_len, handlers,
1054  charset);
1055 }
1056 
1058 {
1059  Z_SRW_recordVersion *ver
1060  = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1061  int i;
1062  for (i = 0; i < num; ++i)
1063  {
1064  ver[i].versionType = 0;
1065  ver[i].versionValue = 0;
1066  }
1067  return ver;
1068 }
1069 
1070 const char *yaz_srw_pack_to_str(int pack)
1071 {
1072  switch(pack)
1073  {
1075  return "string";
1077  return "xml";
1079  return "url";
1080  }
1081  return 0;
1082 }
1083 
1084 int yaz_srw_str_to_pack(const char *str)
1085 {
1086  if (!yaz_matchstr(str, "string"))
1088  if (!yaz_matchstr(str, "xml"))
1089  return Z_SRW_recordPacking_XML;
1090  if (!yaz_matchstr(str, "url"))
1091  return Z_SRW_recordPacking_URL;
1092  return -1;
1093 }
1094 
1095 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1096 {
1097  if (extra_args)
1098  {
1099  char **name;
1100  char **val;
1101  Z_SRW_extra_arg **ea = &sr->extra_args;
1102  yaz_uri_to_array(extra_args, odr, &name, &val);
1103 
1104  while (*name)
1105  {
1106  *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1107  (*ea)->name = *name;
1108  (*ea)->value = *val;
1109  ea = &(*ea)->next;
1110  val++;
1111  name++;
1112  }
1113  *ea = 0;
1114  }
1115 }
1116 
1117 
1118 /*
1119  * Local variables:
1120  * c-basic-offset: 4
1121  * c-file-style: "Stroustrup"
1122  * indent-tabs-mode: nil
1123  * End:
1124  * vim: shiftwidth=4 tabstop=8 expandtab
1125  */
1126