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 = 0;
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));
69 attributes->num_attributes = 1;
70 attributes->attributes = (Z_AttributeElement**)
71 odr_malloc(o, sizeof(*attributes->attributes));
72 attributes->attributes[0] = yaz_string_element_create(o, 1, name);
77 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
78 const char *node_name,
79 const char *attribute_name)
81 struct _xmlAttr *attr;
82 // check if the node name matches
83 if (strcmp((const char*) ptr->name, node_name))
85 // check if the attribute name and return the value
86 for (attr = ptr->properties; attr; attr = attr->next)
87 if (attr->children && attr->children->type == XML_TEXT_NODE)
89 if (!strcmp((const char *) attr->name, attribute_name))
90 return (const char *) attr->children->content;
96 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
98 const char *content_type = z_HTTP_header_lookup(hres->headers,
102 if (!yaz_strcmp_del("text/xml", content_type, "; "))
104 if (!yaz_strcmp_del("application/xml", content_type, "; "))
111 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
112 * parameters. Added by SH.
114 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
115 char *username, char *password, ODR decode)
117 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
120 sr->username = username;
122 sr->password = password;
128 char ubuf[256] = "", pbuf[256] = "", *p;
129 if (strncmp(basic, "Basic ", 6))
133 if (!len || len > 256)
135 yaz_base64decode(basic, out);
136 /* Format of out should be username:password at this point */
138 if ((p = strchr(ubuf, ':')))
145 sr->username = odr_strdup(decode, ubuf);
147 sr->password = odr_strdup(decode, pbuf);
151 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
152 const char *uri, const char *message,
155 d->uri = odr_strdup(o, uri);
157 d->message = odr_strdup(o, message);
161 d->details = odr_strdup(o, details);
166 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
167 int code, const char *details)
171 sprintf(uri, "info:srw/diagnostic/1/%d", code);
172 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
175 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
176 int *num, const char *uri,
177 const char *message, const char *details)
179 Z_SRW_diagnostic *d_new;
180 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
182 memcpy(d_new, *d, *num *sizeof(**d));
185 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
189 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
190 int *num, int code, const char *addinfo)
194 sprintf(uri, "info:srw/diagnostic/1/%d", code);
195 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
199 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
200 int *num, int code, const char *addinfo)
204 sprintf(uri, "info:srw/diagnostic/12/%d", code);
205 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
209 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
210 int code, const char *details)
212 const char *message = yaz_diag_srw_str(code);
215 len += strlen(message);
217 len += strlen(details);
219 record->recordData_buf = (char *) odr_malloc(o, len);
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);
225 sprintf(record->recordData_buf + strlen(record->recordData_buf),
226 " <details>%s</details>\n", details);
228 sprintf(record->recordData_buf + strlen(record->recordData_buf),
229 " <message>%s</message>\n", message);
230 sprintf(record->recordData_buf + strlen(record->recordData_buf),
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";
237 static void grab_charset(ODR o, const char *content_type, char **charset)
241 const char *charset_p = 0;
242 if (content_type && (charset_p = strstr(content_type, "; charset=")))
246 charset_p += 10; /* skip ; charset= */
247 if (charset_p[i] == '"' || charset_p[i] == '\'')
248 sep = charset_p[i++];
249 *charset = odr_strdup(o, charset_p);
250 while (charset_p[i] && charset_p[i] != sep)
252 if (!sep && strchr("; \n\r", charset_p[i]))
254 if (charset_p[i] == '\\' && charset_p[i+1])
256 (*charset)[j++] = charset_p[i++];
258 (*charset)[j] = '\0';
263 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
264 Z_SOAP **soap_package, ODR decode, char **charset)
266 if (!strcmp(hreq->method, "POST"))
268 const char *content_type = z_HTTP_header_lookup(hreq->headers,
271 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
272 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
273 !yaz_strcmp_del("text/plain", content_type, "; ")))
275 char *db = "Default";
276 const char *p0 = hreq->path, *p1;
279 static Z_SOAP_Handler soap_handlers[5] = {
281 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
282 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
283 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
284 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
291 p1 = strchr(p0, '?');
293 p1 = p0 + strlen(p0);
295 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
297 ret = z_soap_codec(decode, soap_package,
298 &hreq->content_buf, &hreq->content_len,
300 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
302 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
303 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
305 /* last entry in handlers - SRU 2.0 - is turned into
306 offset 0.. due to other pieces relying on it */
307 if ((*soap_package)->u.generic->no == 3)
308 (*soap_package)->u.generic->no = 0;
309 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
310 (*srw_pdu)->u.request->database == 0)
311 (*srw_pdu)->u.request->database = db;
313 if ((*srw_pdu)->which == Z_SRW_explain_request &&
314 (*srw_pdu)->u.explain_request->database == 0)
315 (*srw_pdu)->u.explain_request->database = db;
317 if ((*srw_pdu)->which == Z_SRW_scan_request &&
318 (*srw_pdu)->u.scan_request->database == 0)
319 (*srw_pdu)->u.scan_request->database = db;
321 if ((*srw_pdu)->which == Z_SRW_update_request &&
322 (*srw_pdu)->u.update_request->database == 0)
323 (*srw_pdu)->u.update_request->database = db;
334 static int yaz_sru_decode_integer(ODR odr, const char *pname,
335 const char *valstr, Odr_int **valp,
336 Z_SRW_diagnostic **diag, int *num_diag,
342 if (sscanf(valstr, "%d", &ival) != 1)
344 yaz_add_srw_diagnostic(odr, diag, num_diag,
345 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
348 if (min_value >= 0 && ival < min_value)
350 yaz_add_srw_diagnostic(odr, diag, num_diag,
351 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
354 *valp = odr_intdup(odr, ival);
360 http://www.loc.gov/z3950/agency/zing/srw/service.html
362 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
363 Z_SOAP **soap_package, ODR decode, char **charset,
364 Z_SRW_diagnostic **diag, int *num_diag)
367 static Z_SOAP_Handler soap_handlers[2] = {
368 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
372 const char *content_type = z_HTTP_header_lookup(hreq->headers,
376 SRU GET: ignore content type.
377 SRU POST: we support "application/x-www-form-urlencoded";
378 not "multipart/form-data" .
380 if (!strcmp(hreq->method, "GET")
382 (!strcmp(hreq->method, "POST") && content_type &&
383 !yaz_strcmp_del("application/x-www-form-urlencoded",
384 content_type, "; ")))
386 char *db = "Default";
387 const char *p0 = hreq->path, *p1;
389 const char *operation = 0;
392 char *queryType = "cql";
396 char *stylesheet = 0;
397 char *scanClause = 0;
398 char *recordXPath = 0;
399 char *recordSchema = 0;
400 char *recordXMLEscaping = 0;
401 char *recordPacking = 0;
402 char *maximumRecords = 0;
403 char *startRecord = 0;
404 char *maximumTerms = 0;
405 char *responsePosition = 0;
406 const char *facetLimit = 0;
407 const char *facetStart = 0;
408 const char *facetSort = 0;
409 Z_SRW_extra_arg *extra_args = 0;
414 grab_charset(decode, content_type, charset);
415 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
420 p1 = strchr(p0, '?');
422 p1 = p0 + strlen(p0);
424 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
425 if (!strcmp(hreq->method, "POST"))
426 p1 = hreq->content_buf;
427 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
432 for (i = 0; uri_name[i]; i++)
434 char *n = uri_name[i];
435 char *v = uri_val[i];
436 if (!strcmp(n, "query"))
438 else if (!strcmp(n, "x-pquery"))
443 else if (!strcmp(n, "queryType"))
445 else if (!strcmp(n, "x-username"))
447 else if (!strcmp(n, "x-password"))
449 else if (!strcmp(n, "operation"))
451 else if (!strcmp(n, "stylesheet"))
453 else if (!strcmp(n, "sortKeys"))
455 else if (!strcmp(n, "recordXPath"))
457 else if (!strcmp(n, "recordSchema"))
459 else if (!strcmp(n, "recordPacking"))
461 else if (!strcmp(n, "recordXMLEscaping"))
462 recordXMLEscaping = v;
463 else if (!strcmp(n, "version"))
465 else if (!strcmp(n, "scanClause"))
467 else if (!strcmp(n, "x-pScanClause"))
472 else if (!strcmp(n, "maximumRecords"))
474 else if (!strcmp(n, "startRecord"))
476 else if (!strcmp(n, "maximumTerms"))
478 else if (!strcmp(n, "responsePosition"))
479 responsePosition = v;
480 else if (!strcmp(n, "facetLimit"))
482 else if (!strcmp(n, "facetStart"))
484 else if (!strcmp(n, "facetSort"))
486 else if (!strcmp(n, "extraRequestData"))
487 ; /* ignoring extraRequestData */
488 else if (n[0] == 'x' && n[1] == '-')
490 Z_SRW_extra_arg **l = &extra_args;
493 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
494 (*l)->name = odr_strdup(decode, n);
495 (*l)->value = odr_strdup(decode, v);
501 yaz_add_srw_diagnostic(decode, diag, num_diag,
502 YAZ_SRW_UNSUPP_PARAMETER, n);
509 operation = "searchRetrieve";
513 version = yaz_negotiate_sru_version(version);
516 { /* negotiation failed. */
517 yaz_add_srw_diagnostic(decode, diag, num_diag,
518 YAZ_SRW_UNSUPP_VERSION, "2.0");
524 yaz_add_srw_diagnostic(
525 decode, diag, num_diag,
526 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
527 operation = "explain";
529 if (strcmp(version, "2.0"))
531 if (recordXMLEscaping)
533 yaz_add_srw_diagnostic(decode, diag, num_diag,
534 YAZ_SRW_UNSUPP_PARAMETER,
535 "recordXMLEscaping");
538 recordXMLEscaping = recordPacking;
539 recordPacking = "packed";
541 if (!recordXMLEscaping)
542 recordXMLEscaping = "xml";
543 if (!strcmp(operation, "searchRetrieve"))
545 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
547 sr->srw_version = version;
548 sr->extra_args = extra_args;
550 yaz_srw_decodeauth(sr, hreq, username, password, decode);
552 sr->u.request->queryType = queryType;
553 sr->u.request->query = query;
556 yaz_add_srw_diagnostic(
557 decode, diag, num_diag,
558 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
562 sr->u.request->sort_type = Z_SRW_sort_type_sort;
563 sr->u.request->sort.sortKeys = sortKeys;
565 sr->u.request->recordXPath = recordXPath;
566 sr->u.request->recordSchema = recordSchema;
567 sr->u.request->recordPacking = recordXMLEscaping;
568 sr->u.request->packing = recordPacking;
569 sr->u.request->stylesheet = stylesheet;
570 yaz_sru_facet_request(decode , &sr->u.request->facetList,
571 &facetLimit, &facetStart, &facetSort);
573 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
574 &sr->u.request->maximumRecords,
577 yaz_sru_decode_integer(decode, "startRecord", startRecord,
578 &sr->u.request->startRecord,
581 sr->u.request->database = db;
583 (*soap_package) = (Z_SOAP *)
584 odr_malloc(decode, sizeof(**soap_package));
585 (*soap_package)->which = Z_SOAP_generic;
587 (*soap_package)->u.generic = (Z_SOAP_Generic *)
588 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
590 (*soap_package)->u.generic->p = sr;
591 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
592 (*soap_package)->u.generic->no = 0;
594 (*soap_package)->ns = "SRU";
598 else if (!strcmp(operation, "explain"))
600 /* Transfer SRU explain parameters to common struct */
601 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
602 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
604 sr->srw_version = version;
605 sr->extra_args = extra_args;
606 yaz_srw_decodeauth(sr, hreq, username, password, decode);
608 sr->u.explain_request->recordPacking = recordXMLEscaping;
609 sr->u.explain_request->packing = recordPacking;
610 sr->u.explain_request->database = db;
612 sr->u.explain_request->stylesheet = stylesheet;
614 (*soap_package) = (Z_SOAP *)
615 odr_malloc(decode, sizeof(**soap_package));
616 (*soap_package)->which = Z_SOAP_generic;
618 (*soap_package)->u.generic = (Z_SOAP_Generic *)
619 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
621 (*soap_package)->u.generic->p = sr;
622 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
623 (*soap_package)->u.generic->no = 0;
625 (*soap_package)->ns = "SRU";
629 else if (!strcmp(operation, "scan"))
631 /* Transfer SRU scan parameters to common struct */
632 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
633 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
635 sr->srw_version = version;
636 sr->extra_args = extra_args;
638 yaz_srw_decodeauth(sr, hreq, username, password, decode);
640 sr->u.scan_request->queryType = queryType;
641 sr->u.scan_request->scanClause = scanClause;
644 yaz_add_srw_diagnostic(
645 decode, diag, num_diag,
646 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
647 sr->u.scan_request->database = db;
649 yaz_sru_decode_integer(decode, "maximumTerms",
651 &sr->u.scan_request->maximumTerms,
654 yaz_sru_decode_integer(decode, "responsePosition",
656 &sr->u.scan_request->responsePosition,
659 sr->u.scan_request->stylesheet = stylesheet;
661 (*soap_package) = (Z_SOAP *)
662 odr_malloc(decode, sizeof(**soap_package));
663 (*soap_package)->which = Z_SOAP_generic;
665 (*soap_package)->u.generic = (Z_SOAP_Generic *)
666 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
668 (*soap_package)->u.generic->p = sr;
669 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
670 (*soap_package)->u.generic->no = 0;
672 (*soap_package)->ns = "SRU";
678 /* unsupported operation ... */
679 /* Act as if we received a explain request and throw diagnostic. */
681 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
683 sr->srw_version = version;
685 sr->u.explain_request->recordPacking = recordPacking;
686 sr->u.explain_request->database = db;
688 sr->u.explain_request->stylesheet = stylesheet;
690 (*soap_package) = (Z_SOAP *)
691 odr_malloc(decode, sizeof(**soap_package));
692 (*soap_package)->which = Z_SOAP_generic;
694 (*soap_package)->u.generic = (Z_SOAP_Generic *)
695 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
697 (*soap_package)->u.generic->p = sr;
698 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
699 (*soap_package)->u.generic->no = 0;
701 (*soap_package)->ns = "SRU";
703 yaz_add_srw_diagnostic(decode, diag, num_diag,
704 YAZ_SRW_UNSUPP_OPERATION, operation);
714 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
716 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
717 odr_malloc(o, sizeof(*res));
719 res->extraRecordData_buf = 0;
720 res->extraRecordData_len = 0;
721 res->recordIdentifier = 0;
726 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
728 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
731 for (i = 0; i<n; i++)
733 res[i].recordSchema = 0;
734 res[i].recordPacking = Z_SRW_recordPacking_string;
735 res[i].recordData_buf = 0;
736 res[i].recordData_len = 0;
737 res[i].recordPosition = 0;
742 Z_SRW_record *yaz_srw_get_record(ODR o)
744 return yaz_srw_get_records(o, 1);
747 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
749 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
750 p->srw_version = odr_strdup(o, version);
754 p->extraResponseData_buf = 0;
755 p->extraResponseData_len = 0;
759 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
761 return yaz_srw_get_core_ver(o, "2.0");
764 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
766 return yaz_srw_get_pdu(o, which, "2.0");
769 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
771 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
776 case Z_SRW_searchRetrieve_request:
777 sr->u.request = (Z_SRW_searchRetrieveRequest *)
778 odr_malloc(o, sizeof(*sr->u.request));
779 sr->u.request->queryType = "cql";
780 sr->u.request->query = 0;
781 sr->u.request->sort_type = Z_SRW_sort_type_none;
782 sr->u.request->sort.none = 0;
783 sr->u.request->startRecord = 0;
784 sr->u.request->maximumRecords = 0;
785 sr->u.request->recordSchema = 0;
786 sr->u.request->recordPacking = 0;
787 sr->u.request->packing = 0;
788 sr->u.request->recordXPath = 0;
789 sr->u.request->database = 0;
790 sr->u.request->resultSetTTL = 0;
791 sr->u.request->stylesheet = 0;
792 sr->u.request->facetList = 0;
794 case Z_SRW_searchRetrieve_response:
795 sr->u.response = (Z_SRW_searchRetrieveResponse *)
796 odr_malloc(o, sizeof(*sr->u.response));
797 sr->u.response->numberOfRecords = 0;
798 sr->u.response->resultCountPrecision = 0;
799 sr->u.response->resultSetId = 0;
800 sr->u.response->resultSetIdleTime = 0;
801 sr->u.response->records = 0;
802 sr->u.response->num_records = 0;
803 sr->u.response->diagnostics = 0;
804 sr->u.response->num_diagnostics = 0;
805 sr->u.response->nextRecordPosition = 0;
806 sr->u.response->extra_records = 0;
807 sr->u.response->facetList = 0;
808 sr->u.response->suggestions = 0;
810 case Z_SRW_explain_request:
811 sr->u.explain_request = (Z_SRW_explainRequest *)
812 odr_malloc(o, sizeof(*sr->u.explain_request));
813 sr->u.explain_request->recordPacking = 0;
814 sr->u.explain_request->packing = 0;
815 sr->u.explain_request->database = 0;
816 sr->u.explain_request->stylesheet = 0;
818 case Z_SRW_explain_response:
819 sr->u.explain_response = (Z_SRW_explainResponse *)
820 odr_malloc(o, sizeof(*sr->u.explain_response));
821 sr->u.explain_response->record.recordData_buf = 0;
822 sr->u.explain_response->record.recordData_len = 0;
823 sr->u.explain_response->record.recordSchema = 0;
824 sr->u.explain_response->record.recordPosition = 0;
825 sr->u.explain_response->record.recordPacking =
826 Z_SRW_recordPacking_string;
827 sr->u.explain_response->diagnostics = 0;
828 sr->u.explain_response->num_diagnostics = 0;
829 sr->u.explain_response->extra_record = 0;
831 case Z_SRW_scan_request:
832 sr->u.scan_request = (Z_SRW_scanRequest *)
833 odr_malloc(o, sizeof(*sr->u.scan_request));
834 sr->u.scan_request->database = 0;
835 sr->u.scan_request->stylesheet = 0;
836 sr->u.scan_request->maximumTerms = 0;
837 sr->u.scan_request->responsePosition = 0;
838 sr->u.scan_request->queryType = "cql";
839 sr->u.scan_request->scanClause = 0;
841 case Z_SRW_scan_response:
842 sr->u.scan_response = (Z_SRW_scanResponse *)
843 odr_malloc(o, sizeof(*sr->u.scan_response));
844 sr->u.scan_response->terms = 0;
845 sr->u.scan_response->num_terms = 0;
846 sr->u.scan_response->diagnostics = 0;
847 sr->u.scan_response->num_diagnostics = 0;
849 case Z_SRW_update_request:
850 sr->u.update_request = (Z_SRW_updateRequest *)
851 odr_malloc(o, sizeof(*sr->u.update_request));
852 sr->u.update_request->database = 0;
853 sr->u.update_request->stylesheet = 0;
854 sr->u.update_request->record = 0;
855 sr->u.update_request->recordId = 0;
856 sr->u.update_request->recordVersions = 0;
857 sr->u.update_request->num_recordVersions = 0;
858 sr->u.update_request->extra_record = 0;
859 sr->u.update_request->extraRequestData_buf = 0;
860 sr->u.update_request->extraRequestData_len = 0;
861 sr->u.request->database = 0;
863 case Z_SRW_update_response:
864 sr->u.update_response = (Z_SRW_updateResponse *)
865 odr_malloc(o, sizeof(*sr->u.update_response));
866 sr->u.update_response->operationStatus = 0;
867 sr->u.update_response->recordId = 0;
868 sr->u.update_response->recordVersions = 0;
869 sr->u.update_response->num_recordVersions = 0;
870 sr->u.update_response->record = 0;
871 sr->u.update_response->extra_record = 0;
872 sr->u.update_response->extraResponseData_buf = 0;
873 sr->u.update_response->extraResponseData_len = 0;
874 sr->u.update_response->diagnostics = 0;
875 sr->u.update_response->num_diagnostics = 0;
880 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
881 char *a_name, Odr_int *val)
886 value[*i] = (char *) odr_malloc(o, 40);
887 sprintf(value[*i], ODR_INT_PRINTF, *val);
892 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
893 char *a_name, char *val)
903 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
904 char **name, char **value, int max_names)
906 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
909 yaz_add_name_value_str(encode, name, value, &i, "version",
910 srw_pdu->srw_version);
911 name[i] = "operation";
912 switch (srw_pdu->which)
914 case Z_SRW_searchRetrieve_request:
915 value[i++] = "searchRetrieve";
916 queryType = srw_pdu->u.request->queryType;
919 if (queryType && strcmp(queryType, "cql"))
920 yaz_add_name_value_str(encode, name, value, &i, "queryType",
922 yaz_add_name_value_str(encode, name, value, &i, "query",
923 srw_pdu->u.request->query);
927 if (!strcmp(queryType, "cql"))
929 yaz_add_name_value_str(encode, name, value, &i, "query",
930 srw_pdu->u.request->query);
932 else if (!strcmp(queryType, "pqf"))
934 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
935 srw_pdu->u.request->query);
937 else if (!strcmp(queryType, "xcql"))
939 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
940 srw_pdu->u.request->query);
943 switch (srw_pdu->u.request->sort_type)
945 case Z_SRW_sort_type_none:
947 case Z_SRW_sort_type_sort:
948 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
949 srw_pdu->u.request->sort.sortKeys);
952 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
953 srw_pdu->u.request->startRecord);
954 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
955 srw_pdu->u.request->maximumRecords);
956 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
957 srw_pdu->u.request->recordSchema);
960 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
961 srw_pdu->u.request->recordPacking);
962 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
963 srw_pdu->u.request->packing);
966 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
967 srw_pdu->u.request->recordPacking);
968 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
969 srw_pdu->u.request->recordXPath);
970 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
971 srw_pdu->u.request->stylesheet);
972 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
973 srw_pdu->u.request->resultSetTTL);
975 const char *facetLimit = 0;
976 const char *facetStart = 0;
977 const char *facetSort = 0;
978 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
979 &facetLimit, &facetStart, &facetSort);
980 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
981 (char *) facetLimit);
982 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
983 (char *) facetStart);
984 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
988 case Z_SRW_explain_request:
989 value[i++] = "explain";
993 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
994 srw_pdu->u.explain_request->recordPacking);
995 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
996 srw_pdu->u.explain_request->packing);
999 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1000 srw_pdu->u.explain_request->recordPacking);
1001 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1002 srw_pdu->u.explain_request->stylesheet);
1004 case Z_SRW_scan_request:
1005 value[i++] = "scan";
1006 queryType = srw_pdu->u.scan_request->queryType;
1009 if (queryType && strcmp(queryType, "cql"))
1010 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1012 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1013 srw_pdu->u.scan_request->scanClause);
1017 if (!queryType || !strcmp(queryType, "cql"))
1018 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1019 srw_pdu->u.scan_request->scanClause);
1020 else if (!strcmp(queryType, "pqf"))
1021 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1022 srw_pdu->u.scan_request->scanClause);
1023 else if (!strcmp(queryType, "xcql"))
1024 yaz_add_name_value_str(encode, name, value, &i,
1026 srw_pdu->u.scan_request->scanClause);
1028 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1029 srw_pdu->u.scan_request->responsePosition);
1030 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1031 srw_pdu->u.scan_request->maximumTerms);
1032 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1033 srw_pdu->u.scan_request->stylesheet);
1035 case Z_SRW_update_request:
1036 value[i++] = "update";
1041 if (srw_pdu->extra_args)
1043 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1044 for (; ea && i < max_names-1; ea = ea->next)
1047 value[i] = ea->value;
1056 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1057 ODR encode, const char *charset)
1059 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1064 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1065 srw_pdu->username, srw_pdu->password);
1066 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1068 yaz_array_to_uri(&uri_args, encode, name, value);
1070 hreq->method = "GET";
1072 cp = strchr(hreq->path, '#');
1077 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1079 sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1083 z_HTTP_header_add_content_type(encode, &hreq->headers,
1084 "text/xml", charset);
1088 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1089 ODR encode, const char *charset)
1091 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1094 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1095 srw_pdu->username, srw_pdu->password);
1096 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1099 yaz_array_to_uri(&uri_args, encode, name, value);
1101 hreq->method = "POST";
1103 hreq->content_buf = uri_args;
1104 hreq->content_len = strlen(uri_args);
1106 z_HTTP_header_add_content_type(encode, &hreq->headers,
1107 "application/x-www-form-urlencoded",
1112 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1113 ODR odr, const char *charset)
1115 Z_SOAP_Handler handlers[3] = {
1117 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1118 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1122 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1124 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1125 srw_pdu->username, srw_pdu->password);
1126 z_HTTP_header_add_content_type(odr,
1128 "text/xml", 0 /* no charset in MIME */);
1130 z_HTTP_header_add(odr, &hreq->headers,
1131 "SOAPAction", "\"\"");
1132 p->which = Z_SOAP_generic;
1133 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1134 p->u.generic->no = 0;
1135 p->u.generic->ns = 0;
1136 p->u.generic->p = srw_pdu;
1137 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1140 if (srw_pdu->which == Z_SRW_update_request ||
1141 srw_pdu->which == Z_SRW_update_response)
1142 p->u.generic->no = 1; /* second handler */
1144 return z_soap_codec_enc(odr, &p,
1146 &hreq->content_len, handlers,
1150 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1152 Z_SRW_recordVersion *ver
1153 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1155 for (i = 0; i < num; ++i)
1157 ver[i].versionType = 0;
1158 ver[i].versionValue = 0;
1163 const char *yaz_srw_pack_to_str(int pack)
1167 case Z_SRW_recordPacking_string:
1169 case Z_SRW_recordPacking_XML:
1171 case Z_SRW_recordPacking_URL:
1177 int yaz_srw_str_to_pack(const char *str)
1179 if (!yaz_matchstr(str, "string"))
1180 return Z_SRW_recordPacking_string;
1181 if (!yaz_matchstr(str, "xml"))
1182 return Z_SRW_recordPacking_XML;
1183 if (!yaz_matchstr(str, "url"))
1184 return Z_SRW_recordPacking_URL;
1188 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1194 Z_SRW_extra_arg **ea = &sr->extra_args;
1195 yaz_uri_to_array(extra_args, odr, &name, &val);
1197 /** append rather than override */
1202 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1203 (*ea)->name = *name;
1204 (*ea)->value = *val;
1217 * c-file-style: "Stroustrup"
1218 * indent-tabs-mode: nil
1220 * vim: shiftwidth=4 tabstop=8 expandtab