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 char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
25 return odr_strdupn(n, uri, len);
28 void yaz_encode_sru_dbpath_buf(char *dst, const char *db)
35 char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
37 char *dst = odr_malloc(out, 3 * strlen(db) + 2);
38 yaz_encode_sru_dbpath_buf(dst, db);
42 Z_AttributeElement *yaz_string_element_create(ODR o, int type,
45 Z_AttributeElement *element = (Z_AttributeElement*)
46 odr_malloc(o, sizeof(*element));
47 element->attributeType = odr_intdup(o, type);
48 element->attributeSet = odr_nullval();
49 element->which = Z_AttributeValue_complex;
50 element->value.complex = (Z_ComplexAttribute *)
51 odr_malloc(o, sizeof(Z_ComplexAttribute));
52 element->value.complex->num_list = 1;
53 element->value.complex->list = (Z_StringOrNumeric **)
54 odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *));
55 element->value.complex->list[0] = (Z_StringOrNumeric *)
56 odr_malloc(o, sizeof(Z_StringOrNumeric));
57 element->value.complex->list[0]->which = Z_StringOrNumeric_string;
58 element->value.complex->list[0]->u.string = odr_strdup(o, value);
59 element->value.complex->semanticAction = 0;
60 element->value.complex->num_semanticAction = 0;
64 Z_AttributeList *yaz_use_attribute_create(ODR o, const char *name)
66 Z_AttributeList *attributes = (Z_AttributeList *)
67 odr_malloc(o, sizeof(*attributes));
68 Z_AttributeElement **elements = (Z_AttributeElement**)
69 odr_malloc(o, attributes->num_attributes * sizeof(*elements));
71 elements[0] = yaz_string_element_create(o, 1, name);
72 attributes->num_attributes = 1;
73 attributes->attributes = elements;
78 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
79 const char *node_name,
80 const char *attribute_name)
82 struct _xmlAttr *attr;
83 // check if the node name matches
84 if (strcmp((const char*) ptr->name, node_name))
86 // check if the attribute name and return the value
87 for (attr = ptr->properties; attr; attr = attr->next)
88 if (attr->children && attr->children->type == XML_TEXT_NODE)
90 if (!strcmp((const char *) attr->name, attribute_name))
91 return (const char *) attr->children->content;
97 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
99 const char *content_type = z_HTTP_header_lookup(hres->headers,
103 if (!yaz_strcmp_del("text/xml", content_type, "; "))
105 if (!yaz_strcmp_del("application/xml", content_type, "; "))
112 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
113 * parameters. Added by SH.
115 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
116 char *username, char *password, ODR decode)
118 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
121 sr->username = username;
123 sr->password = password;
129 char ubuf[256] = "", pbuf[256] = "", *p;
130 if (strncmp(basic, "Basic ", 6))
134 if (!len || len > 256)
136 yaz_base64decode(basic, out);
137 /* Format of out should be username:password at this point */
139 if ((p = strchr(ubuf, ':')))
146 sr->username = odr_strdup(decode, ubuf);
148 sr->password = odr_strdup(decode, pbuf);
152 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
153 const char *uri, const char *message,
156 d->uri = odr_strdup(o, uri);
158 d->message = odr_strdup(o, message);
162 d->details = odr_strdup(o, details);
167 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
168 int code, const char *details)
172 sprintf(uri, "info:srw/diagnostic/1/%d", code);
173 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
176 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
177 int *num, const char *uri,
178 const char *message, const char *details)
180 Z_SRW_diagnostic *d_new;
181 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
183 memcpy(d_new, *d, *num *sizeof(**d));
186 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
190 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
191 int *num, int code, const char *addinfo)
195 sprintf(uri, "info:srw/diagnostic/1/%d", code);
196 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
200 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
201 int *num, int code, const char *addinfo)
205 sprintf(uri, "info:srw/diagnostic/12/%d", code);
206 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
210 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
211 int code, const char *details)
213 const char *message = yaz_diag_srw_str(code);
216 len += strlen(message);
218 len += strlen(details);
220 record->recordData_buf = (char *) odr_malloc(o, len);
222 sprintf(record->recordData_buf, "<diagnostic "
223 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
224 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
226 sprintf(record->recordData_buf + strlen(record->recordData_buf),
227 " <details>%s</details>\n", details);
229 sprintf(record->recordData_buf + strlen(record->recordData_buf),
230 " <message>%s</message>\n", message);
231 sprintf(record->recordData_buf + strlen(record->recordData_buf),
233 record->recordData_len = strlen(record->recordData_buf);
234 record->recordPosition = odr_intdup(o, pos);
235 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
238 static void grab_charset(ODR o, const char *content_type, char **charset)
242 const char *charset_p = 0;
243 if (content_type && (charset_p = strstr(content_type, "; charset=")))
247 charset_p += 10; /* skip ; charset= */
248 if (charset_p[i] == '"' || charset_p[i] == '\'')
249 sep = charset_p[i++];
250 *charset = odr_strdup(o, charset_p);
251 while (charset_p[i] && charset_p[i] != sep)
253 if (!sep && strchr("; \n\r", charset_p[i]))
255 if (charset_p[i] == '\\' && charset_p[i+1])
257 (*charset)[j++] = charset_p[i++];
259 (*charset)[j] = '\0';
264 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
265 Z_SOAP **soap_package, ODR decode, char **charset)
267 if (!strcmp(hreq->method, "POST"))
269 const char *content_type = z_HTTP_header_lookup(hreq->headers,
272 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
273 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
274 !yaz_strcmp_del("text/plain", content_type, "; ")))
276 char *db = "Default";
277 const char *p0 = hreq->path, *p1;
280 static Z_SOAP_Handler soap_handlers[5] = {
282 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
283 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
284 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
285 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
292 p1 = strchr(p0, '?');
294 p1 = p0 + strlen(p0);
296 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
298 ret = z_soap_codec(decode, soap_package,
299 &hreq->content_buf, &hreq->content_len,
301 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
303 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
304 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
306 /* last entry in handlers - SRU 2.0 - is turned into
307 offset 0.. due to other pieces relying on it */
308 if ((*soap_package)->u.generic->no == 3)
309 (*soap_package)->u.generic->no = 0;
310 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
311 (*srw_pdu)->u.request->database == 0)
312 (*srw_pdu)->u.request->database = db;
314 if ((*srw_pdu)->which == Z_SRW_explain_request &&
315 (*srw_pdu)->u.explain_request->database == 0)
316 (*srw_pdu)->u.explain_request->database = db;
318 if ((*srw_pdu)->which == Z_SRW_scan_request &&
319 (*srw_pdu)->u.scan_request->database == 0)
320 (*srw_pdu)->u.scan_request->database = db;
322 if ((*srw_pdu)->which == Z_SRW_update_request &&
323 (*srw_pdu)->u.update_request->database == 0)
324 (*srw_pdu)->u.update_request->database = db;
335 static int yaz_sru_decode_integer(ODR odr, const char *pname,
336 const char *valstr, Odr_int **valp,
337 Z_SRW_diagnostic **diag, int *num_diag,
343 if (sscanf(valstr, "%d", &ival) != 1)
345 yaz_add_srw_diagnostic(odr, diag, num_diag,
346 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
349 if (min_value >= 0 && ival < min_value)
351 yaz_add_srw_diagnostic(odr, diag, num_diag,
352 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
355 *valp = odr_intdup(odr, ival);
361 http://www.loc.gov/z3950/agency/zing/srw/service.html
363 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
364 Z_SOAP **soap_package, ODR decode, char **charset,
365 Z_SRW_diagnostic **diag, int *num_diag)
368 static Z_SOAP_Handler soap_handlers[2] = {
369 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
373 const char *content_type = z_HTTP_header_lookup(hreq->headers,
377 SRU GET: ignore content type.
378 SRU POST: we support "application/x-www-form-urlencoded";
379 not "multipart/form-data" .
381 if (!strcmp(hreq->method, "GET")
383 (!strcmp(hreq->method, "POST") && content_type &&
384 !yaz_strcmp_del("application/x-www-form-urlencoded",
385 content_type, "; ")))
387 char *db = "Default";
388 const char *p0 = hreq->path, *p1;
390 const char *operation = 0;
393 char *queryType = "cql";
397 char *stylesheet = 0;
398 char *scanClause = 0;
399 char *recordXPath = 0;
400 char *recordSchema = 0;
401 char *recordXMLEscaping = 0;
402 char *recordPacking = 0;
403 char *maximumRecords = 0;
404 char *startRecord = 0;
405 char *maximumTerms = 0;
406 char *responsePosition = 0;
407 const char *facetLimit = 0;
408 const char *facetStart = 0;
409 const char *facetSort = 0;
410 Z_SRW_extra_arg *extra_args = 0;
415 grab_charset(decode, content_type, charset);
416 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
421 p1 = strchr(p0, '?');
423 p1 = p0 + strlen(p0);
425 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
426 if (!strcmp(hreq->method, "POST"))
427 p1 = hreq->content_buf;
428 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
433 for (i = 0; uri_name[i]; i++)
435 char *n = uri_name[i];
436 char *v = uri_val[i];
437 if (!strcmp(n, "query"))
439 else if (!strcmp(n, "x-pquery"))
444 else if (!strcmp(n, "queryType"))
446 else if (!strcmp(n, "x-username"))
448 else if (!strcmp(n, "x-password"))
450 else if (!strcmp(n, "operation"))
452 else if (!strcmp(n, "stylesheet"))
454 else if (!strcmp(n, "sortKeys"))
456 else if (!strcmp(n, "recordXPath"))
458 else if (!strcmp(n, "recordSchema"))
460 else if (!strcmp(n, "recordPacking"))
462 else if (!strcmp(n, "recordXMLEscaping"))
463 recordXMLEscaping = v;
464 else if (!strcmp(n, "version"))
466 else if (!strcmp(n, "scanClause"))
468 else if (!strcmp(n, "x-pScanClause"))
473 else if (!strcmp(n, "maximumRecords"))
475 else if (!strcmp(n, "startRecord"))
477 else if (!strcmp(n, "maximumTerms"))
479 else if (!strcmp(n, "responsePosition"))
480 responsePosition = v;
481 else if (!strcmp(n, "facetLimit"))
483 else if (!strcmp(n, "facetStart"))
485 else if (!strcmp(n, "facetSort"))
487 else if (!strcmp(n, "extraRequestData"))
488 ; /* ignoring extraRequestData */
489 else if (n[0] == 'x' && n[1] == '-')
491 Z_SRW_extra_arg **l = &extra_args;
494 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
495 (*l)->name = odr_strdup(decode, n);
496 (*l)->value = odr_strdup(decode, v);
502 yaz_add_srw_diagnostic(decode, diag, num_diag,
503 YAZ_SRW_UNSUPP_PARAMETER, n);
510 operation = "searchRetrieve";
514 version = yaz_negotiate_sru_version(version);
517 { /* negotiation failed. */
518 yaz_add_srw_diagnostic(decode, diag, num_diag,
519 YAZ_SRW_UNSUPP_VERSION, "2.0");
525 yaz_add_srw_diagnostic(
526 decode, diag, num_diag,
527 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
528 operation = "explain";
530 if (strcmp(version, "2.0"))
532 if (recordXMLEscaping)
534 yaz_add_srw_diagnostic(decode, diag, num_diag,
535 YAZ_SRW_UNSUPP_PARAMETER,
536 "recordXMLEscaping");
539 recordXMLEscaping = recordPacking;
540 recordPacking = "packed";
542 if (!recordXMLEscaping)
543 recordXMLEscaping = "xml";
544 if (!strcmp(operation, "searchRetrieve"))
546 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
548 sr->srw_version = version;
549 sr->extra_args = extra_args;
551 yaz_srw_decodeauth(sr, hreq, username, password, decode);
553 sr->u.request->queryType = queryType;
554 sr->u.request->query = query;
557 yaz_add_srw_diagnostic(
558 decode, diag, num_diag,
559 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
563 sr->u.request->sort_type = Z_SRW_sort_type_sort;
564 sr->u.request->sort.sortKeys = sortKeys;
566 sr->u.request->recordXPath = recordXPath;
567 sr->u.request->recordSchema = recordSchema;
568 sr->u.request->recordPacking = recordXMLEscaping;
569 sr->u.request->packing = recordPacking;
570 sr->u.request->stylesheet = stylesheet;
571 yaz_sru_facet_request(decode , &sr->u.request->facetList,
572 &facetLimit, &facetStart, &facetSort);
574 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
575 &sr->u.request->maximumRecords,
578 yaz_sru_decode_integer(decode, "startRecord", startRecord,
579 &sr->u.request->startRecord,
582 sr->u.request->database = db;
584 (*soap_package) = (Z_SOAP *)
585 odr_malloc(decode, sizeof(**soap_package));
586 (*soap_package)->which = Z_SOAP_generic;
588 (*soap_package)->u.generic = (Z_SOAP_Generic *)
589 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
591 (*soap_package)->u.generic->p = sr;
592 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
593 (*soap_package)->u.generic->no = 0;
595 (*soap_package)->ns = "SRU";
599 else if (!strcmp(operation, "explain"))
601 /* Transfer SRU explain parameters to common struct */
602 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
603 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
605 sr->srw_version = version;
606 sr->extra_args = extra_args;
607 yaz_srw_decodeauth(sr, hreq, username, password, decode);
609 sr->u.explain_request->recordPacking = recordXMLEscaping;
610 sr->u.explain_request->packing = recordPacking;
611 sr->u.explain_request->database = db;
613 sr->u.explain_request->stylesheet = stylesheet;
615 (*soap_package) = (Z_SOAP *)
616 odr_malloc(decode, sizeof(**soap_package));
617 (*soap_package)->which = Z_SOAP_generic;
619 (*soap_package)->u.generic = (Z_SOAP_Generic *)
620 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
622 (*soap_package)->u.generic->p = sr;
623 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
624 (*soap_package)->u.generic->no = 0;
626 (*soap_package)->ns = "SRU";
630 else if (!strcmp(operation, "scan"))
632 /* Transfer SRU scan parameters to common struct */
633 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
634 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
636 sr->srw_version = version;
637 sr->extra_args = extra_args;
639 yaz_srw_decodeauth(sr, hreq, username, password, decode);
641 sr->u.scan_request->queryType = queryType;
642 sr->u.scan_request->scanClause = scanClause;
645 yaz_add_srw_diagnostic(
646 decode, diag, num_diag,
647 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
648 sr->u.scan_request->database = db;
650 yaz_sru_decode_integer(decode, "maximumTerms",
652 &sr->u.scan_request->maximumTerms,
655 yaz_sru_decode_integer(decode, "responsePosition",
657 &sr->u.scan_request->responsePosition,
660 sr->u.scan_request->stylesheet = stylesheet;
662 (*soap_package) = (Z_SOAP *)
663 odr_malloc(decode, sizeof(**soap_package));
664 (*soap_package)->which = Z_SOAP_generic;
666 (*soap_package)->u.generic = (Z_SOAP_Generic *)
667 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
669 (*soap_package)->u.generic->p = sr;
670 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
671 (*soap_package)->u.generic->no = 0;
673 (*soap_package)->ns = "SRU";
679 /* unsupported operation ... */
680 /* Act as if we received a explain request and throw diagnostic. */
682 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
684 sr->srw_version = version;
686 sr->u.explain_request->recordPacking = recordPacking;
687 sr->u.explain_request->database = db;
689 sr->u.explain_request->stylesheet = stylesheet;
691 (*soap_package) = (Z_SOAP *)
692 odr_malloc(decode, sizeof(**soap_package));
693 (*soap_package)->which = Z_SOAP_generic;
695 (*soap_package)->u.generic = (Z_SOAP_Generic *)
696 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
698 (*soap_package)->u.generic->p = sr;
699 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
700 (*soap_package)->u.generic->no = 0;
702 (*soap_package)->ns = "SRU";
704 yaz_add_srw_diagnostic(decode, diag, num_diag,
705 YAZ_SRW_UNSUPP_OPERATION, operation);
715 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
717 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
718 odr_malloc(o, sizeof(*res));
720 res->extraRecordData_buf = 0;
721 res->extraRecordData_len = 0;
722 res->recordIdentifier = 0;
727 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
729 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
732 for (i = 0; i<n; i++)
734 res[i].recordSchema = 0;
735 res[i].recordPacking = Z_SRW_recordPacking_string;
736 res[i].recordData_buf = 0;
737 res[i].recordData_len = 0;
738 res[i].recordPosition = 0;
743 Z_SRW_record *yaz_srw_get_record(ODR o)
745 return yaz_srw_get_records(o, 1);
748 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
750 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
751 p->srw_version = odr_strdup(o, version);
755 p->extraResponseData_buf = 0;
756 p->extraResponseData_len = 0;
760 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
762 return yaz_srw_get_core_ver(o, "2.0");
765 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
767 return yaz_srw_get_pdu(o, which, "2.0");
770 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
772 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
777 case Z_SRW_searchRetrieve_request:
778 sr->u.request = (Z_SRW_searchRetrieveRequest *)
779 odr_malloc(o, sizeof(*sr->u.request));
780 sr->u.request->queryType = "cql";
781 sr->u.request->query = 0;
782 sr->u.request->sort_type = Z_SRW_sort_type_none;
783 sr->u.request->sort.none = 0;
784 sr->u.request->startRecord = 0;
785 sr->u.request->maximumRecords = 0;
786 sr->u.request->recordSchema = 0;
787 sr->u.request->recordPacking = 0;
788 sr->u.request->packing = 0;
789 sr->u.request->recordXPath = 0;
790 sr->u.request->database = 0;
791 sr->u.request->resultSetTTL = 0;
792 sr->u.request->stylesheet = 0;
793 sr->u.request->facetList = 0;
795 case Z_SRW_searchRetrieve_response:
796 sr->u.response = (Z_SRW_searchRetrieveResponse *)
797 odr_malloc(o, sizeof(*sr->u.response));
798 sr->u.response->numberOfRecords = 0;
799 sr->u.response->resultCountPrecision = 0;
800 sr->u.response->resultSetId = 0;
801 sr->u.response->resultSetIdleTime = 0;
802 sr->u.response->records = 0;
803 sr->u.response->num_records = 0;
804 sr->u.response->diagnostics = 0;
805 sr->u.response->num_diagnostics = 0;
806 sr->u.response->nextRecordPosition = 0;
807 sr->u.response->extra_records = 0;
808 sr->u.response->facetList = 0;
809 sr->u.response->suggestions = 0;
811 case Z_SRW_explain_request:
812 sr->u.explain_request = (Z_SRW_explainRequest *)
813 odr_malloc(o, sizeof(*sr->u.explain_request));
814 sr->u.explain_request->recordPacking = 0;
815 sr->u.explain_request->packing = 0;
816 sr->u.explain_request->database = 0;
817 sr->u.explain_request->stylesheet = 0;
819 case Z_SRW_explain_response:
820 sr->u.explain_response = (Z_SRW_explainResponse *)
821 odr_malloc(o, sizeof(*sr->u.explain_response));
822 sr->u.explain_response->record.recordData_buf = 0;
823 sr->u.explain_response->record.recordData_len = 0;
824 sr->u.explain_response->record.recordSchema = 0;
825 sr->u.explain_response->record.recordPosition = 0;
826 sr->u.explain_response->record.recordPacking =
827 Z_SRW_recordPacking_string;
828 sr->u.explain_response->diagnostics = 0;
829 sr->u.explain_response->num_diagnostics = 0;
830 sr->u.explain_response->extra_record = 0;
832 case Z_SRW_scan_request:
833 sr->u.scan_request = (Z_SRW_scanRequest *)
834 odr_malloc(o, sizeof(*sr->u.scan_request));
835 sr->u.scan_request->database = 0;
836 sr->u.scan_request->stylesheet = 0;
837 sr->u.scan_request->maximumTerms = 0;
838 sr->u.scan_request->responsePosition = 0;
839 sr->u.scan_request->queryType = "cql";
840 sr->u.scan_request->scanClause = 0;
842 case Z_SRW_scan_response:
843 sr->u.scan_response = (Z_SRW_scanResponse *)
844 odr_malloc(o, sizeof(*sr->u.scan_response));
845 sr->u.scan_response->terms = 0;
846 sr->u.scan_response->num_terms = 0;
847 sr->u.scan_response->diagnostics = 0;
848 sr->u.scan_response->num_diagnostics = 0;
850 case Z_SRW_update_request:
851 sr->u.update_request = (Z_SRW_updateRequest *)
852 odr_malloc(o, sizeof(*sr->u.update_request));
853 sr->u.update_request->database = 0;
854 sr->u.update_request->stylesheet = 0;
855 sr->u.update_request->record = 0;
856 sr->u.update_request->recordId = 0;
857 sr->u.update_request->recordVersions = 0;
858 sr->u.update_request->num_recordVersions = 0;
859 sr->u.update_request->extra_record = 0;
860 sr->u.update_request->extraRequestData_buf = 0;
861 sr->u.update_request->extraRequestData_len = 0;
862 sr->u.request->database = 0;
864 case Z_SRW_update_response:
865 sr->u.update_response = (Z_SRW_updateResponse *)
866 odr_malloc(o, sizeof(*sr->u.update_response));
867 sr->u.update_response->operationStatus = 0;
868 sr->u.update_response->recordId = 0;
869 sr->u.update_response->recordVersions = 0;
870 sr->u.update_response->num_recordVersions = 0;
871 sr->u.update_response->record = 0;
872 sr->u.update_response->extra_record = 0;
873 sr->u.update_response->extraResponseData_buf = 0;
874 sr->u.update_response->extraResponseData_len = 0;
875 sr->u.update_response->diagnostics = 0;
876 sr->u.update_response->num_diagnostics = 0;
881 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
882 char *a_name, Odr_int *val)
887 value[*i] = (char *) odr_malloc(o, 40);
888 sprintf(value[*i], ODR_INT_PRINTF, *val);
893 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
894 char *a_name, char *val)
904 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
905 char **name, char **value, int max_names)
907 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
910 yaz_add_name_value_str(encode, name, value, &i, "version",
911 srw_pdu->srw_version);
912 name[i] = "operation";
913 switch (srw_pdu->which)
915 case Z_SRW_searchRetrieve_request:
916 value[i++] = "searchRetrieve";
917 queryType = srw_pdu->u.request->queryType;
920 if (queryType && strcmp(queryType, "cql"))
921 yaz_add_name_value_str(encode, name, value, &i, "queryType",
923 yaz_add_name_value_str(encode, name, value, &i, "query",
924 srw_pdu->u.request->query);
928 if (!strcmp(queryType, "cql"))
930 yaz_add_name_value_str(encode, name, value, &i, "query",
931 srw_pdu->u.request->query);
933 else if (!strcmp(queryType, "pqf"))
935 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
936 srw_pdu->u.request->query);
938 else if (!strcmp(queryType, "xcql"))
940 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
941 srw_pdu->u.request->query);
944 switch (srw_pdu->u.request->sort_type)
946 case Z_SRW_sort_type_none:
948 case Z_SRW_sort_type_sort:
949 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
950 srw_pdu->u.request->sort.sortKeys);
953 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
954 srw_pdu->u.request->startRecord);
955 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
956 srw_pdu->u.request->maximumRecords);
957 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
958 srw_pdu->u.request->recordSchema);
961 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
962 srw_pdu->u.request->recordPacking);
963 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
964 srw_pdu->u.request->packing);
967 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
968 srw_pdu->u.request->recordPacking);
969 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
970 srw_pdu->u.request->recordXPath);
971 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
972 srw_pdu->u.request->stylesheet);
973 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
974 srw_pdu->u.request->resultSetTTL);
976 const char *facetLimit = 0;
977 const char *facetStart = 0;
978 const char *facetSort = 0;
979 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
980 &facetLimit, &facetStart, &facetSort);
981 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
982 (char *) facetLimit);
983 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
984 (char *) facetStart);
985 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
989 case Z_SRW_explain_request:
990 value[i++] = "explain";
994 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
995 srw_pdu->u.explain_request->recordPacking);
996 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
997 srw_pdu->u.explain_request->packing);
1000 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1001 srw_pdu->u.explain_request->recordPacking);
1002 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1003 srw_pdu->u.explain_request->stylesheet);
1005 case Z_SRW_scan_request:
1006 value[i++] = "scan";
1007 queryType = srw_pdu->u.scan_request->queryType;
1010 if (queryType && strcmp(queryType, "cql"))
1011 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1013 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1014 srw_pdu->u.scan_request->scanClause);
1018 if (!queryType || !strcmp(queryType, "cql"))
1019 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1020 srw_pdu->u.scan_request->scanClause);
1021 else if (!strcmp(queryType, "pqf"))
1022 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1023 srw_pdu->u.scan_request->scanClause);
1024 else if (!strcmp(queryType, "xcql"))
1025 yaz_add_name_value_str(encode, name, value, &i,
1027 srw_pdu->u.scan_request->scanClause);
1029 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1030 srw_pdu->u.scan_request->responsePosition);
1031 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1032 srw_pdu->u.scan_request->maximumTerms);
1033 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1034 srw_pdu->u.scan_request->stylesheet);
1036 case Z_SRW_update_request:
1037 value[i++] = "update";
1042 if (srw_pdu->extra_args)
1044 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1045 for (; ea && i < max_names-1; ea = ea->next)
1048 value[i] = ea->value;
1057 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1058 ODR encode, const char *charset)
1060 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1065 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1066 srw_pdu->username, srw_pdu->password);
1067 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1069 yaz_array_to_uri(&uri_args, encode, name, value);
1071 hreq->method = "GET";
1073 cp = strchr(hreq->path, '#');
1078 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1080 sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1084 z_HTTP_header_add_content_type(encode, &hreq->headers,
1085 "text/xml", charset);
1089 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1090 ODR encode, const char *charset)
1092 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1095 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1096 srw_pdu->username, srw_pdu->password);
1097 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1100 yaz_array_to_uri(&uri_args, encode, name, value);
1102 hreq->method = "POST";
1104 hreq->content_buf = uri_args;
1105 hreq->content_len = strlen(uri_args);
1107 z_HTTP_header_add_content_type(encode, &hreq->headers,
1108 "application/x-www-form-urlencoded",
1113 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1114 ODR odr, const char *charset)
1116 Z_SOAP_Handler handlers[3] = {
1118 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1119 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1123 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1125 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1126 srw_pdu->username, srw_pdu->password);
1127 z_HTTP_header_add_content_type(odr,
1129 "text/xml", 0 /* no charset in MIME */);
1131 z_HTTP_header_add(odr, &hreq->headers,
1132 "SOAPAction", "\"\"");
1133 p->which = Z_SOAP_generic;
1134 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1135 p->u.generic->no = 0;
1136 p->u.generic->ns = 0;
1137 p->u.generic->p = srw_pdu;
1138 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1141 if (srw_pdu->which == Z_SRW_update_request ||
1142 srw_pdu->which == Z_SRW_update_response)
1143 p->u.generic->no = 1; /* second handler */
1145 return z_soap_codec_enc(odr, &p,
1147 &hreq->content_len, handlers,
1151 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1153 Z_SRW_recordVersion *ver
1154 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1156 for (i = 0; i < num; ++i)
1158 ver[i].versionType = 0;
1159 ver[i].versionValue = 0;
1164 const char *yaz_srw_pack_to_str(int pack)
1168 case Z_SRW_recordPacking_string:
1170 case Z_SRW_recordPacking_XML:
1172 case Z_SRW_recordPacking_URL:
1178 int yaz_srw_str_to_pack(const char *str)
1180 if (!yaz_matchstr(str, "string"))
1181 return Z_SRW_recordPacking_string;
1182 if (!yaz_matchstr(str, "xml"))
1183 return Z_SRW_recordPacking_XML;
1184 if (!yaz_matchstr(str, "url"))
1185 return Z_SRW_recordPacking_URL;
1189 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1195 Z_SRW_extra_arg **ea = &sr->extra_args;
1196 yaz_uri_to_array(extra_args, odr, &name, &val);
1198 /** append rather than override */
1203 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1204 (*ea)->name = *name;
1205 (*ea)->value = *val;
1218 * c-file-style: "Stroustrup"
1219 * indent-tabs-mode: nil
1221 * vim: shiftwidth=4 tabstop=8 expandtab