1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRW/SRU utilities.
16 #include <yaz/matchstr.h>
17 #include <yaz/base64.h>
18 #include <yaz/yaz-iconv.h>
21 #define MAX_SRU_PARAMETERS 30
23 static Z_SRW_extra_arg **append_extra_arg(ODR odr, Z_SRW_extra_arg **l,
24 const char *n, const char *v)
26 if (n && v && *v != '\0')
30 *l = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**l));
31 (*l)->name = odr_strdup(odr, n);
32 (*l)->value = odr_strdup(odr, v);
39 static Z_SRW_extra_arg **append_extra_arg_int(ODR odr, Z_SRW_extra_arg **l,
40 const char *n, Odr_int *v)
45 sprintf(str, ODR_INT_PRINTF, *v);
46 l = append_extra_arg(odr, l, n, str);
51 static char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
53 return odr_strdupn(n, uri, len);
56 void yaz_encode_sru_dbpath_buf(char *dst, const char *db)
63 char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
65 char *dst = odr_malloc(out, 3 * strlen(db) + 2);
66 yaz_encode_sru_dbpath_buf(dst, db);
71 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
72 const char *node_name,
73 const char *attribute_name)
75 struct _xmlAttr *attr;
76 // check if the node name matches
77 if (strcmp((const char*) ptr->name, node_name))
79 // check if the attribute name and return the value
80 for (attr = ptr->properties; attr; attr = attr->next)
81 if (attr->children && attr->children->type == XML_TEXT_NODE)
83 if (!strcmp((const char *) attr->name, attribute_name))
84 return (const char *) attr->children->content;
90 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
92 const char *content_type = z_HTTP_header_lookup(hres->headers,
96 if (!yaz_strcmp_del("text/xml", content_type, "; "))
98 if (!yaz_strcmp_del("application/xml", content_type, "; "))
105 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
106 * parameters. Added by SH.
108 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
109 char *username, char *password, ODR decode)
111 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
114 sr->username = username;
116 sr->password = password;
122 char ubuf[256] = "", pbuf[256] = "", *p;
123 if (strncmp(basic, "Basic ", 6))
127 if (!len || len > 256)
129 yaz_base64decode(basic, out);
130 /* Format of out should be username:password at this point */
132 if ((p = strchr(ubuf, ':')))
139 sr->username = odr_strdup(decode, ubuf);
141 sr->password = odr_strdup(decode, pbuf);
145 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
146 const char *uri, const char *message,
149 d->uri = odr_strdup(o, uri);
151 d->message = odr_strdup(o, message);
155 d->details = odr_strdup(o, details);
160 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
161 int code, const char *details)
165 sprintf(uri, "info:srw/diagnostic/1/%d", code);
166 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
169 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
170 int *num, const char *uri,
171 const char *message, const char *details)
173 Z_SRW_diagnostic *d_new;
174 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
176 memcpy(d_new, *d, *num *sizeof(**d));
179 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
183 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
184 int *num, int code, const char *addinfo)
188 sprintf(uri, "info:srw/diagnostic/1/%d", code);
189 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
193 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
194 int *num, int code, const char *addinfo)
198 sprintf(uri, "info:srw/diagnostic/12/%d", code);
199 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
203 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
204 int code, const char *details)
206 const char *message = yaz_diag_srw_str(code);
209 len += strlen(message);
211 len += strlen(details);
213 record->recordData_buf = (char *) odr_malloc(o, len);
215 sprintf(record->recordData_buf, "<diagnostic "
216 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
217 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
219 sprintf(record->recordData_buf + strlen(record->recordData_buf),
220 " <details>%s</details>\n", details);
222 sprintf(record->recordData_buf + strlen(record->recordData_buf),
223 " <message>%s</message>\n", message);
224 sprintf(record->recordData_buf + strlen(record->recordData_buf),
226 record->recordData_len = strlen(record->recordData_buf);
227 record->recordPosition = odr_intdup(o, pos);
228 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
231 static void grab_charset(ODR o, const char *content_type, char **charset)
235 const char *charset_p = 0;
236 if (content_type && (charset_p = strstr(content_type, "; charset=")))
240 charset_p += 10; /* skip ; charset= */
241 if (charset_p[i] == '"' || charset_p[i] == '\'')
242 sep = charset_p[i++];
243 *charset = odr_strdup(o, charset_p);
244 while (charset_p[i] && charset_p[i] != sep)
246 if (!sep && strchr("; \n\r", charset_p[i]))
248 if (charset_p[i] == '\\' && charset_p[i+1])
250 (*charset)[j++] = charset_p[i++];
252 (*charset)[j] = '\0';
257 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
258 Z_SOAP **soap_package, ODR decode, char **charset)
260 if (!strcmp(hreq->method, "POST"))
262 const char *content_type = z_HTTP_header_lookup(hreq->headers,
265 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
266 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
267 !yaz_strcmp_del("text/plain", content_type, "; ")))
269 char *db = "Default";
270 const char *p0 = hreq->path, *p1;
273 static Z_SOAP_Handler soap_handlers[5] = {
275 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
276 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
277 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
278 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
285 p1 = strchr(p0, '?');
287 p1 = p0 + strlen(p0);
289 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
291 ret = z_soap_codec(decode, soap_package,
292 &hreq->content_buf, &hreq->content_len,
294 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
296 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
297 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
299 /* last entry in handlers - SRU 2.0 - is turned into
300 offset 0.. due to other pieces relying on it */
301 if ((*soap_package)->u.generic->no == 3)
302 (*soap_package)->u.generic->no = 0;
303 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
304 (*srw_pdu)->u.request->database == 0)
305 (*srw_pdu)->u.request->database = db;
307 if ((*srw_pdu)->which == Z_SRW_explain_request &&
308 (*srw_pdu)->u.explain_request->database == 0)
309 (*srw_pdu)->u.explain_request->database = db;
311 if ((*srw_pdu)->which == Z_SRW_scan_request &&
312 (*srw_pdu)->u.scan_request->database == 0)
313 (*srw_pdu)->u.scan_request->database = db;
315 if ((*srw_pdu)->which == Z_SRW_update_request &&
316 (*srw_pdu)->u.update_request->database == 0)
317 (*srw_pdu)->u.update_request->database = db;
328 static int yaz_sru_decode_integer(ODR odr, const char *pname,
329 const char *valstr, Odr_int **valp,
330 Z_SRW_diagnostic **diag, int *num_diag,
336 if (sscanf(valstr, "%d", &ival) != 1)
338 yaz_add_srw_diagnostic(odr, diag, num_diag,
339 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
342 if (min_value >= 0 && ival < min_value)
344 yaz_add_srw_diagnostic(odr, diag, num_diag,
345 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
348 *valp = odr_intdup(odr, ival);
354 http://www.loc.gov/z3950/agency/zing/srw/service.html
356 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
357 Z_SOAP **soap_package, ODR decode, char **charset,
358 Z_SRW_diagnostic **diag, int *num_diag)
361 static Z_SOAP_Handler soap_handlers[2] = {
362 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
366 const char *content_type = z_HTTP_header_lookup(hreq->headers,
370 SRU GET: ignore content type.
371 SRU POST: we support "application/x-www-form-urlencoded";
372 not "multipart/form-data" .
374 if (!strcmp(hreq->method, "GET")
376 (!strcmp(hreq->method, "POST") && content_type &&
377 !yaz_strcmp_del("application/x-www-form-urlencoded",
378 content_type, "; ")))
380 char *db = "Default";
381 const char *p0 = hreq->path, *p1;
383 const char *operation = 0;
386 char *queryType = "cql";
390 char *stylesheet = 0;
391 char *scanClause = 0;
392 char *recordXPath = 0;
393 char *recordSchema = 0;
394 char *recordXMLEscaping = 0;
395 char *recordPacking = 0;
396 char *maximumRecords = 0;
397 char *startRecord = 0;
398 char *maximumTerms = 0;
399 char *responsePosition = 0;
400 const char *facetLimit = 0;
401 const char *facetStart = 0;
402 const char *facetSort = 0;
403 Z_SRW_extra_arg *extra_args = 0;
408 grab_charset(decode, content_type, charset);
409 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
414 p1 = strchr(p0, '?');
416 p1 = p0 + strlen(p0);
418 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
419 if (!strcmp(hreq->method, "POST"))
420 p1 = hreq->content_buf;
421 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
426 for (i = 0; uri_name[i]; i++)
428 char *n = uri_name[i];
429 char *v = uri_val[i];
430 if (!strcmp(n, "query"))
432 else if (!strcmp(n, "x-pquery"))
437 else if (!strcmp(n, "queryType"))
439 else if (!strcmp(n, "x-username"))
441 else if (!strcmp(n, "x-password"))
443 else if (!strcmp(n, "operation"))
445 else if (!strcmp(n, "stylesheet"))
447 else if (!strcmp(n, "sortKeys"))
449 else if (!strcmp(n, "recordXPath"))
451 else if (!strcmp(n, "recordSchema"))
453 else if (!strcmp(n, "recordPacking"))
455 else if (!strcmp(n, "recordXMLEscaping"))
456 recordXMLEscaping = v;
457 else if (!strcmp(n, "version"))
459 else if (!strcmp(n, "scanClause"))
461 else if (!strcmp(n, "x-pScanClause"))
466 else if (!strcmp(n, "maximumRecords"))
468 else if (!strcmp(n, "startRecord"))
470 else if (!strcmp(n, "maximumTerms"))
472 else if (!strcmp(n, "responsePosition"))
473 responsePosition = v;
474 else if (!strcmp(n, "facetLimit"))
476 else if (!strcmp(n, "facetStart"))
478 else if (!strcmp(n, "facetSort"))
480 else if (!strcmp(n, "extraRequestData"))
481 ; /* ignoring extraRequestData */
482 else if (n[0] == 'x' && n[1] == '-')
484 append_extra_arg(decode, &extra_args, n, v);
489 yaz_add_srw_diagnostic(decode, diag, num_diag,
490 YAZ_SRW_UNSUPP_PARAMETER, n);
497 operation = "searchRetrieve";
501 operation = "explain";
503 version = yaz_negotiate_sru_version(version);
506 { /* negotiation failed. */
507 yaz_add_srw_diagnostic(decode, diag, num_diag,
508 YAZ_SRW_UNSUPP_VERSION, "2.0");
514 yaz_add_srw_diagnostic(
515 decode, diag, num_diag,
516 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
517 operation = "explain";
519 if (strcmp(version, "2.0"))
521 if (recordXMLEscaping)
523 yaz_add_srw_diagnostic(decode, diag, num_diag,
524 YAZ_SRW_UNSUPP_PARAMETER,
525 "recordXMLEscaping");
528 recordXMLEscaping = recordPacking;
529 recordPacking = "packed";
531 if (!recordXMLEscaping)
532 recordXMLEscaping = "xml";
533 if (!strcmp(operation, "searchRetrieve"))
535 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
537 sr->srw_version = version;
538 sr->extra_args = extra_args;
540 yaz_srw_decodeauth(sr, hreq, username, password, decode);
542 sr->u.request->queryType = queryType;
543 sr->u.request->query = query;
546 yaz_add_srw_diagnostic(
547 decode, diag, num_diag,
548 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
552 sr->u.request->sort_type = Z_SRW_sort_type_sort;
553 sr->u.request->sort.sortKeys = sortKeys;
555 sr->u.request->recordXPath = recordXPath;
556 sr->u.request->recordSchema = recordSchema;
557 sr->u.request->recordPacking = recordXMLEscaping;
558 sr->u.request->packing = recordPacking;
559 sr->u.request->stylesheet = stylesheet;
560 yaz_sru_facet_request(decode , &sr->u.request->facetList,
561 &facetLimit, &facetStart, &facetSort);
563 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
564 &sr->u.request->maximumRecords,
567 yaz_sru_decode_integer(decode, "startRecord", startRecord,
568 &sr->u.request->startRecord,
571 sr->u.request->database = db;
573 (*soap_package) = (Z_SOAP *)
574 odr_malloc(decode, sizeof(**soap_package));
575 (*soap_package)->which = Z_SOAP_generic;
577 (*soap_package)->u.generic = (Z_SOAP_Generic *)
578 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
580 (*soap_package)->u.generic->p = sr;
581 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
582 (*soap_package)->u.generic->no = 0;
584 (*soap_package)->ns = "SRU";
588 else if (!strcmp(operation, "explain"))
590 /* Transfer SRU explain parameters to common struct */
591 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
592 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
594 sr->srw_version = version;
595 sr->extra_args = extra_args;
596 yaz_srw_decodeauth(sr, hreq, username, password, decode);
598 sr->u.explain_request->recordPacking = recordXMLEscaping;
599 sr->u.explain_request->packing = recordPacking;
600 sr->u.explain_request->database = db;
602 sr->u.explain_request->stylesheet = stylesheet;
604 (*soap_package) = (Z_SOAP *)
605 odr_malloc(decode, sizeof(**soap_package));
606 (*soap_package)->which = Z_SOAP_generic;
608 (*soap_package)->u.generic = (Z_SOAP_Generic *)
609 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
611 (*soap_package)->u.generic->p = sr;
612 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
613 (*soap_package)->u.generic->no = 0;
615 (*soap_package)->ns = "SRU";
619 else if (!strcmp(operation, "scan"))
621 /* Transfer SRU scan parameters to common struct */
622 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
623 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
625 sr->srw_version = version;
626 sr->extra_args = extra_args;
628 yaz_srw_decodeauth(sr, hreq, username, password, decode);
630 sr->u.scan_request->queryType = queryType;
631 sr->u.scan_request->scanClause = scanClause;
634 yaz_add_srw_diagnostic(
635 decode, diag, num_diag,
636 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
637 sr->u.scan_request->database = db;
639 yaz_sru_decode_integer(decode, "maximumTerms",
641 &sr->u.scan_request->maximumTerms,
644 yaz_sru_decode_integer(decode, "responsePosition",
646 &sr->u.scan_request->responsePosition,
649 sr->u.scan_request->stylesheet = stylesheet;
651 (*soap_package) = (Z_SOAP *)
652 odr_malloc(decode, sizeof(**soap_package));
653 (*soap_package)->which = Z_SOAP_generic;
655 (*soap_package)->u.generic = (Z_SOAP_Generic *)
656 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
658 (*soap_package)->u.generic->p = sr;
659 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
660 (*soap_package)->u.generic->no = 0;
662 (*soap_package)->ns = "SRU";
668 /* unsupported operation ... */
669 /* Act as if we received a explain request and throw diagnostic. */
671 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
673 sr->srw_version = version;
675 sr->u.explain_request->recordPacking = recordPacking;
676 sr->u.explain_request->database = db;
678 sr->u.explain_request->stylesheet = stylesheet;
680 (*soap_package) = (Z_SOAP *)
681 odr_malloc(decode, sizeof(**soap_package));
682 (*soap_package)->which = Z_SOAP_generic;
684 (*soap_package)->u.generic = (Z_SOAP_Generic *)
685 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
687 (*soap_package)->u.generic->p = sr;
688 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
689 (*soap_package)->u.generic->no = 0;
691 (*soap_package)->ns = "SRU";
693 yaz_add_srw_diagnostic(decode, diag, num_diag,
694 YAZ_SRW_UNSUPP_OPERATION, operation);
704 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
706 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
707 odr_malloc(o, sizeof(*res));
709 res->extraRecordData_buf = 0;
710 res->extraRecordData_len = 0;
711 res->recordIdentifier = 0;
716 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
718 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
721 for (i = 0; i<n; i++)
723 res[i].recordSchema = 0;
724 res[i].recordPacking = Z_SRW_recordPacking_string;
725 res[i].recordData_buf = 0;
726 res[i].recordData_len = 0;
727 res[i].recordPosition = 0;
732 Z_SRW_record *yaz_srw_get_record(ODR o)
734 return yaz_srw_get_records(o, 1);
737 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
739 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
740 p->srw_version = odr_strdup(o, version);
744 p->extraResponseData_buf = 0;
745 p->extraResponseData_len = 0;
749 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
751 return yaz_srw_get_core_ver(o, "2.0");
754 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
756 return yaz_srw_get_pdu(o, which, "2.0");
759 /* http://docs.oasis-open.org/search-ws/searchRetrieve/v1.0/os/schemas/sruResponse.xsd */
760 Z_SRW_PDU *yaz_srw_get_pdu_e(ODR o, int which, Z_SRW_PDU *req)
762 int version2 = !req->srw_version || strcmp(req->srw_version, "2.") > 0;
763 Z_SRW_PDU *res = yaz_srw_get_pdu(o, which, req->srw_version);
764 Z_SRW_extra_arg **l = &res->extra_args, *ea;
765 l = append_extra_arg(o, l, "version", req->srw_version);
766 if (req->which == Z_SRW_searchRetrieve_request &&
767 which == Z_SRW_searchRetrieve_response)
769 if (req->u.request->queryType &&
770 strcmp(req->u.request->queryType, "cql"))
771 l = append_extra_arg(o, l, "queryType", req->u.request->queryType);
772 l = append_extra_arg(o, l, "query", req->u.request->query);
773 l = append_extra_arg_int(o, l, "startRecord",
774 req->u.request->startRecord);
775 l = append_extra_arg_int(o, l, "maximumRecords",
776 req->u.request->maximumRecords);
779 l = append_extra_arg(o, l, "recordXMLEscaping",
780 req->u.request->recordPacking);
781 l = append_extra_arg(o, l, "recordPacking",
782 req->u.request->packing);
785 l = append_extra_arg(o, l, "recordPacking",
786 req->u.request->recordPacking);
787 l = append_extra_arg(o, l, "recordSchema",
788 req->u.request->recordSchema);
789 if (req->u.request->sort_type == Z_SRW_sort_type_sort)
790 l = append_extra_arg(o, l, "sortKeys",
791 req->u.request->sort.sortKeys);
792 l = append_extra_arg(o, l, "stylesheet", req->u.request->stylesheet);
794 if (req->which == Z_SRW_explain_request &&
795 which == Z_SRW_explain_response)
799 l = append_extra_arg(o, l, "recordXMLEscaping",
800 req->u.explain_request->recordPacking);
801 l = append_extra_arg(o, l, "recordPacking",
802 req->u.explain_request->packing);
805 l = append_extra_arg(o, l, "recordPacking",
806 req->u.explain_request->recordPacking);
807 l = append_extra_arg(o, l, "stylesheet",
808 req->u.explain_request->stylesheet);
810 for (ea = req->extra_args; ea; ea = ea->next)
811 l = append_extra_arg(o, l, ea->name, ea->value);
815 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
817 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
822 case Z_SRW_searchRetrieve_request:
823 sr->u.request = (Z_SRW_searchRetrieveRequest *)
824 odr_malloc(o, sizeof(*sr->u.request));
825 sr->u.request->queryType = "cql";
826 sr->u.request->query = 0;
827 sr->u.request->sort_type = Z_SRW_sort_type_none;
828 sr->u.request->sort.none = 0;
829 sr->u.request->startRecord = 0;
830 sr->u.request->maximumRecords = 0;
831 sr->u.request->recordSchema = 0;
832 sr->u.request->recordPacking = 0;
833 sr->u.request->packing = 0;
834 sr->u.request->recordXPath = 0;
835 sr->u.request->database = 0;
836 sr->u.request->resultSetTTL = 0;
837 sr->u.request->stylesheet = 0;
838 sr->u.request->facetList = 0;
840 case Z_SRW_searchRetrieve_response:
841 sr->u.response = (Z_SRW_searchRetrieveResponse *)
842 odr_malloc(o, sizeof(*sr->u.response));
843 sr->u.response->numberOfRecords = 0;
844 sr->u.response->resultCountPrecision = 0;
845 sr->u.response->resultSetId = 0;
846 sr->u.response->resultSetIdleTime = 0;
847 sr->u.response->records = 0;
848 sr->u.response->num_records = 0;
849 sr->u.response->diagnostics = 0;
850 sr->u.response->num_diagnostics = 0;
851 sr->u.response->nextRecordPosition = 0;
852 sr->u.response->extra_records = 0;
853 sr->u.response->facetList = 0;
854 sr->u.response->suggestions = 0;
856 case Z_SRW_explain_request:
857 sr->u.explain_request = (Z_SRW_explainRequest *)
858 odr_malloc(o, sizeof(*sr->u.explain_request));
859 sr->u.explain_request->recordPacking = 0;
860 sr->u.explain_request->packing = 0;
861 sr->u.explain_request->database = 0;
862 sr->u.explain_request->stylesheet = 0;
864 case Z_SRW_explain_response:
865 sr->u.explain_response = (Z_SRW_explainResponse *)
866 odr_malloc(o, sizeof(*sr->u.explain_response));
867 sr->u.explain_response->record.recordData_buf = 0;
868 sr->u.explain_response->record.recordData_len = 0;
869 sr->u.explain_response->record.recordSchema = 0;
870 sr->u.explain_response->record.recordPosition = 0;
871 sr->u.explain_response->record.recordPacking =
872 Z_SRW_recordPacking_string;
873 sr->u.explain_response->diagnostics = 0;
874 sr->u.explain_response->num_diagnostics = 0;
875 sr->u.explain_response->extra_record = 0;
877 case Z_SRW_scan_request:
878 sr->u.scan_request = (Z_SRW_scanRequest *)
879 odr_malloc(o, sizeof(*sr->u.scan_request));
880 sr->u.scan_request->database = 0;
881 sr->u.scan_request->stylesheet = 0;
882 sr->u.scan_request->maximumTerms = 0;
883 sr->u.scan_request->responsePosition = 0;
884 sr->u.scan_request->queryType = "cql";
885 sr->u.scan_request->scanClause = 0;
887 case Z_SRW_scan_response:
888 sr->u.scan_response = (Z_SRW_scanResponse *)
889 odr_malloc(o, sizeof(*sr->u.scan_response));
890 sr->u.scan_response->terms = 0;
891 sr->u.scan_response->num_terms = 0;
892 sr->u.scan_response->diagnostics = 0;
893 sr->u.scan_response->num_diagnostics = 0;
895 case Z_SRW_update_request:
896 sr->u.update_request = (Z_SRW_updateRequest *)
897 odr_malloc(o, sizeof(*sr->u.update_request));
898 sr->u.update_request->database = 0;
899 sr->u.update_request->stylesheet = 0;
900 sr->u.update_request->record = 0;
901 sr->u.update_request->recordId = 0;
902 sr->u.update_request->recordVersions = 0;
903 sr->u.update_request->num_recordVersions = 0;
904 sr->u.update_request->extra_record = 0;
905 sr->u.update_request->extraRequestData_buf = 0;
906 sr->u.update_request->extraRequestData_len = 0;
907 sr->u.request->database = 0;
909 case Z_SRW_update_response:
910 sr->u.update_response = (Z_SRW_updateResponse *)
911 odr_malloc(o, sizeof(*sr->u.update_response));
912 sr->u.update_response->operationStatus = 0;
913 sr->u.update_response->recordId = 0;
914 sr->u.update_response->recordVersions = 0;
915 sr->u.update_response->num_recordVersions = 0;
916 sr->u.update_response->record = 0;
917 sr->u.update_response->extra_record = 0;
918 sr->u.update_response->extraResponseData_buf = 0;
919 sr->u.update_response->extraResponseData_len = 0;
920 sr->u.update_response->diagnostics = 0;
921 sr->u.update_response->num_diagnostics = 0;
926 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
927 char *a_name, Odr_int *val)
932 value[*i] = (char *) odr_malloc(o, 40);
933 sprintf(value[*i], ODR_INT_PRINTF, *val);
938 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
939 char *a_name, char *val)
949 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
950 char **name, char **value, int max_names)
952 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
955 yaz_add_name_value_str(encode, name, value, &i, "version",
956 srw_pdu->srw_version);
957 name[i] = "operation";
958 switch (srw_pdu->which)
960 case Z_SRW_searchRetrieve_request:
961 value[i++] = "searchRetrieve";
962 queryType = srw_pdu->u.request->queryType;
965 if (queryType && strcmp(queryType, "cql"))
966 yaz_add_name_value_str(encode, name, value, &i, "queryType",
968 yaz_add_name_value_str(encode, name, value, &i, "query",
969 srw_pdu->u.request->query);
973 if (!strcmp(queryType, "cql"))
975 yaz_add_name_value_str(encode, name, value, &i, "query",
976 srw_pdu->u.request->query);
978 else if (!strcmp(queryType, "pqf"))
980 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
981 srw_pdu->u.request->query);
983 else if (!strcmp(queryType, "xcql"))
985 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
986 srw_pdu->u.request->query);
989 switch (srw_pdu->u.request->sort_type)
991 case Z_SRW_sort_type_none:
993 case Z_SRW_sort_type_sort:
994 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
995 srw_pdu->u.request->sort.sortKeys);
998 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
999 srw_pdu->u.request->startRecord);
1000 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
1001 srw_pdu->u.request->maximumRecords);
1002 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
1003 srw_pdu->u.request->recordSchema);
1006 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1007 srw_pdu->u.request->recordPacking);
1008 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1009 srw_pdu->u.request->packing);
1012 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1013 srw_pdu->u.request->recordPacking);
1014 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
1015 srw_pdu->u.request->recordXPath);
1016 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1017 srw_pdu->u.request->stylesheet);
1018 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
1019 srw_pdu->u.request->resultSetTTL);
1021 const char *facetLimit = 0;
1022 const char *facetStart = 0;
1023 const char *facetSort = 0;
1024 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
1025 &facetLimit, &facetStart, &facetSort);
1026 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
1027 (char *) facetLimit);
1028 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
1029 (char *) facetStart);
1030 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
1031 (char *) facetSort);
1034 case Z_SRW_explain_request:
1035 value[i++] = "explain";
1039 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1040 srw_pdu->u.explain_request->recordPacking);
1041 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1042 srw_pdu->u.explain_request->packing);
1045 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1046 srw_pdu->u.explain_request->recordPacking);
1047 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1048 srw_pdu->u.explain_request->stylesheet);
1050 case Z_SRW_scan_request:
1051 value[i++] = "scan";
1052 queryType = srw_pdu->u.scan_request->queryType;
1055 if (queryType && strcmp(queryType, "cql"))
1056 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1058 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1059 srw_pdu->u.scan_request->scanClause);
1063 if (!queryType || !strcmp(queryType, "cql"))
1064 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1065 srw_pdu->u.scan_request->scanClause);
1066 else if (!strcmp(queryType, "pqf"))
1067 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1068 srw_pdu->u.scan_request->scanClause);
1069 else if (!strcmp(queryType, "xcql"))
1070 yaz_add_name_value_str(encode, name, value, &i,
1072 srw_pdu->u.scan_request->scanClause);
1074 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1075 srw_pdu->u.scan_request->responsePosition);
1076 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1077 srw_pdu->u.scan_request->maximumTerms);
1078 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1079 srw_pdu->u.scan_request->stylesheet);
1081 case Z_SRW_update_request:
1082 value[i++] = "update";
1087 if (srw_pdu->extra_args)
1089 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1090 for (; ea && i < max_names-1; ea = ea->next)
1093 value[i] = ea->value;
1102 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1103 ODR encode, const char *charset)
1105 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1110 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1111 srw_pdu->username, srw_pdu->password);
1112 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1114 yaz_array_to_uri(&uri_args, encode, name, value);
1116 hreq->method = "GET";
1118 cp = strchr(hreq->path, '#');
1123 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1125 sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1129 z_HTTP_header_add_content_type(encode, &hreq->headers,
1130 "text/xml", charset);
1134 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1135 ODR encode, const char *charset)
1137 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1140 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1141 srw_pdu->username, srw_pdu->password);
1142 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1145 yaz_array_to_uri(&uri_args, encode, name, value);
1147 hreq->method = "POST";
1149 hreq->content_buf = uri_args;
1150 hreq->content_len = strlen(uri_args);
1152 z_HTTP_header_add_content_type(encode, &hreq->headers,
1153 "application/x-www-form-urlencoded",
1158 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1159 ODR odr, const char *charset)
1161 Z_SOAP_Handler handlers[3] = {
1163 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1164 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1168 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1170 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1171 srw_pdu->username, srw_pdu->password);
1172 z_HTTP_header_add_content_type(odr,
1174 "text/xml", 0 /* no charset in MIME */);
1176 z_HTTP_header_add(odr, &hreq->headers,
1177 "SOAPAction", "\"\"");
1178 p->which = Z_SOAP_generic;
1179 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1180 p->u.generic->no = 0;
1181 p->u.generic->ns = 0;
1182 p->u.generic->p = srw_pdu;
1183 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1186 if (srw_pdu->which == Z_SRW_update_request ||
1187 srw_pdu->which == Z_SRW_update_response)
1188 p->u.generic->no = 1; /* second handler */
1190 return z_soap_codec_enc(odr, &p,
1192 &hreq->content_len, handlers,
1196 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1198 Z_SRW_recordVersion *ver
1199 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1201 for (i = 0; i < num; ++i)
1203 ver[i].versionType = 0;
1204 ver[i].versionValue = 0;
1209 const char *yaz_srw_pack_to_str(int pack)
1213 case Z_SRW_recordPacking_string:
1215 case Z_SRW_recordPacking_XML:
1217 case Z_SRW_recordPacking_URL:
1223 int yaz_srw_str_to_pack(const char *str)
1225 if (!yaz_matchstr(str, "string"))
1226 return Z_SRW_recordPacking_string;
1227 if (!yaz_matchstr(str, "xml"))
1228 return Z_SRW_recordPacking_XML;
1229 if (!yaz_matchstr(str, "url"))
1230 return Z_SRW_recordPacking_URL;
1234 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1240 Z_SRW_extra_arg **ea = &sr->extra_args;
1241 yaz_uri_to_array(extra_args, odr, &name, &val);
1245 ea = append_extra_arg(odr, ea, *name, *val);
1256 * c-file-style: "Stroustrup"
1257 * indent-tabs-mode: nil
1259 * vim: shiftwidth=4 tabstop=8 expandtab