1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 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_AttributeList *yaz_use_attribute_create(ODR o, const char *name)
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;
70 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
71 const char *node_name,
72 const char *attribute_name)
74 struct _xmlAttr *attr;
75 // check if the node name matches
76 if (strcmp((const char*) ptr->name, node_name))
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)
82 if (!strcmp((const char *) attr->name, attribute_name))
83 return (const char *) attr->children->content;
89 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
91 const char *content_type = z_HTTP_header_lookup(hres->headers,
95 if (!yaz_strcmp_del("text/xml", content_type, "; "))
97 if (!yaz_strcmp_del("application/xml", content_type, "; "))
104 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
105 * parameters. Added by SH.
107 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
108 char *username, char *password, ODR decode)
110 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
113 sr->username = username;
115 sr->password = password;
121 char ubuf[256] = "", pbuf[256] = "", *p;
122 if (strncmp(basic, "Basic ", 6))
126 if (!len || len > 256)
128 yaz_base64decode(basic, out);
129 /* Format of out should be username:password at this point */
131 if ((p = strchr(ubuf, ':')))
138 sr->username = odr_strdup(decode, ubuf);
140 sr->password = odr_strdup(decode, pbuf);
144 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
145 const char *uri, const char *message,
148 d->uri = odr_strdup(o, uri);
150 d->message = odr_strdup(o, message);
154 d->details = odr_strdup(o, details);
159 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
160 int code, const char *details)
164 sprintf(uri, "info:srw/diagnostic/1/%d", code);
165 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
168 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
169 int *num, const char *uri,
170 const char *message, const char *details)
172 Z_SRW_diagnostic *d_new;
173 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
175 memcpy(d_new, *d, *num *sizeof(**d));
178 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
182 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
183 int *num, int code, const char *addinfo)
187 sprintf(uri, "info:srw/diagnostic/1/%d", code);
188 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
192 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
193 int *num, int code, const char *addinfo)
197 sprintf(uri, "info:srw/diagnostic/12/%d", code);
198 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
202 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
203 int code, const char *details)
205 const char *message = yaz_diag_srw_str(code);
208 len += strlen(message);
210 len += strlen(details);
212 record->recordData_buf = (char *) odr_malloc(o, len);
214 sprintf(record->recordData_buf, "<diagnostic "
215 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
216 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
218 sprintf(record->recordData_buf + strlen(record->recordData_buf),
219 " <details>%s</details>\n", details);
221 sprintf(record->recordData_buf + strlen(record->recordData_buf),
222 " <message>%s</message>\n", message);
223 sprintf(record->recordData_buf + strlen(record->recordData_buf),
225 record->recordData_len = strlen(record->recordData_buf);
226 record->recordPosition = odr_intdup(o, pos);
227 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
230 static void grab_charset(ODR o, const char *content_type, char **charset)
234 const char *charset_p = 0;
235 if (content_type && (charset_p = strstr(content_type, "; charset=")))
239 while (i < 20 && charset_p[i] &&
240 !strchr("; \n\r", charset_p[i]))
242 *charset = odr_strdupn(o, charset_p, i);
247 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
248 Z_SOAP **soap_package, ODR decode, char **charset)
250 if (!strcmp(hreq->method, "POST"))
252 const char *content_type = z_HTTP_header_lookup(hreq->headers,
255 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
256 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
257 !yaz_strcmp_del("text/plain", content_type, "; ")))
259 char *db = "Default";
260 const char *p0 = hreq->path, *p1;
263 static Z_SOAP_Handler soap_handlers[5] = {
265 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
266 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
267 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
268 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
275 p1 = strchr(p0, '?');
277 p1 = p0 + strlen(p0);
279 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
280 grab_charset(decode, content_type, charset);
282 ret = z_soap_codec(decode, soap_package,
283 &hreq->content_buf, &hreq->content_len,
285 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
287 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
288 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
290 /* last entry in handlers - SRU 2.0 - is turned into
291 offset 0.. due to other pieces relying on it */
292 if ((*soap_package)->u.generic->no == 3)
293 (*soap_package)->u.generic->no = 0;
294 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
295 (*srw_pdu)->u.request->database == 0)
296 (*srw_pdu)->u.request->database = db;
298 if ((*srw_pdu)->which == Z_SRW_explain_request &&
299 (*srw_pdu)->u.explain_request->database == 0)
300 (*srw_pdu)->u.explain_request->database = db;
302 if ((*srw_pdu)->which == Z_SRW_scan_request &&
303 (*srw_pdu)->u.scan_request->database == 0)
304 (*srw_pdu)->u.scan_request->database = db;
306 if ((*srw_pdu)->which == Z_SRW_update_request &&
307 (*srw_pdu)->u.update_request->database == 0)
308 (*srw_pdu)->u.update_request->database = db;
319 static int yaz_sru_decode_integer(ODR odr, const char *pname,
320 const char *valstr, Odr_int **valp,
321 Z_SRW_diagnostic **diag, int *num_diag,
327 if (sscanf(valstr, "%d", &ival) != 1)
329 yaz_add_srw_diagnostic(odr, diag, num_diag,
330 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
333 if (min_value >= 0 && ival < min_value)
335 yaz_add_srw_diagnostic(odr, diag, num_diag,
336 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
339 *valp = odr_intdup(odr, ival);
345 http://www.loc.gov/z3950/agency/zing/srw/service.html
347 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
348 Z_SOAP **soap_package, ODR decode, char **charset,
349 Z_SRW_diagnostic **diag, int *num_diag)
352 static Z_SOAP_Handler soap_handlers[2] = {
353 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
357 const char *content_type = z_HTTP_header_lookup(hreq->headers,
361 SRU GET: ignore content type.
362 SRU POST: we support "application/x-www-form-urlencoded";
363 not "multipart/form-data" .
365 if (!strcmp(hreq->method, "GET")
367 (!strcmp(hreq->method, "POST") && content_type &&
368 !yaz_strcmp_del("application/x-www-form-urlencoded",
369 content_type, "; ")))
371 char *db = "Default";
372 const char *p0 = hreq->path, *p1;
374 const char *operation = 0;
377 char *queryType = "cql";
381 char *stylesheet = 0;
382 char *scanClause = 0;
383 char *recordXPath = 0;
384 char *recordSchema = 0;
385 char *recordXMLEscaping = 0;
386 char *recordPacking = 0;
387 char *maximumRecords = 0;
388 char *startRecord = 0;
389 char *maximumTerms = 0;
390 char *responsePosition = 0;
391 const char *facetLimit = 0;
392 const char *facetStart = 0;
393 const char *facetSort = 0;
394 Z_SRW_extra_arg *extra_args = 0;
399 grab_charset(decode, content_type, charset);
400 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
405 p1 = strchr(p0, '?');
407 p1 = p0 + strlen(p0);
409 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
410 if (!strcmp(hreq->method, "POST"))
411 p1 = hreq->content_buf;
412 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
417 for (i = 0; uri_name[i]; i++)
419 char *n = uri_name[i];
420 char *v = uri_val[i];
421 if (!strcmp(n, "query"))
423 else if (!strcmp(n, "x-pquery"))
428 else if (!strcmp(n, "queryType"))
430 else if (!strcmp(n, "x-username"))
432 else if (!strcmp(n, "x-password"))
434 else if (!strcmp(n, "operation"))
436 else if (!strcmp(n, "stylesheet"))
438 else if (!strcmp(n, "sortKeys"))
440 else if (!strcmp(n, "recordXPath"))
442 else if (!strcmp(n, "recordSchema"))
444 else if (!strcmp(n, "recordPacking"))
446 else if (!strcmp(n, "recordXMLEscaping"))
447 recordXMLEscaping = v;
448 else if (!strcmp(n, "version"))
450 else if (!strcmp(n, "scanClause"))
452 else if (!strcmp(n, "x-pScanClause"))
457 else if (!strcmp(n, "maximumRecords"))
459 else if (!strcmp(n, "startRecord"))
461 else if (!strcmp(n, "maximumTerms"))
463 else if (!strcmp(n, "responsePosition"))
464 responsePosition = v;
465 else if (!strcmp(n, "facetLimit"))
467 else if (!strcmp(n, "facetStart"))
469 else if (!strcmp(n, "facetSort"))
471 else if (!strcmp(n, "extraRequestData"))
472 ; /* ignoring extraRequestData */
473 else if (n[0] == 'x' && n[1] == '-')
475 Z_SRW_extra_arg **l = &extra_args;
478 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
479 (*l)->name = odr_strdup(decode, n);
480 (*l)->value = odr_strdup(decode, v);
486 yaz_add_srw_diagnostic(decode, diag, num_diag,
487 YAZ_SRW_UNSUPP_PARAMETER, n);
494 operation = "searchRetrieve";
498 version = yaz_negotiate_sru_version(version);
501 { /* negotiation failed. */
502 yaz_add_srw_diagnostic(decode, diag, num_diag,
503 YAZ_SRW_UNSUPP_VERSION, "2.0");
509 yaz_add_srw_diagnostic(
510 decode, diag, num_diag,
511 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
512 operation = "explain";
514 if (strcmp(version, "2.0"))
516 if (recordXMLEscaping)
518 yaz_add_srw_diagnostic(decode, diag, num_diag,
519 YAZ_SRW_UNSUPP_PARAMETER,
520 "recordXMLEscaping");
523 recordXMLEscaping = recordPacking;
524 recordPacking = "packed";
526 if (!recordXMLEscaping)
527 recordXMLEscaping = "xml";
528 if (!strcmp(operation, "searchRetrieve"))
530 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
532 sr->srw_version = version;
533 sr->extra_args = extra_args;
535 yaz_srw_decodeauth(sr, hreq, username, password, decode);
537 sr->u.request->queryType = queryType;
538 sr->u.request->query = query;
541 yaz_add_srw_diagnostic(
542 decode, diag, num_diag,
543 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
547 sr->u.request->sort_type = Z_SRW_sort_type_sort;
548 sr->u.request->sort.sortKeys = sortKeys;
550 sr->u.request->recordXPath = recordXPath;
551 sr->u.request->recordSchema = recordSchema;
552 sr->u.request->recordPacking = recordXMLEscaping;
553 sr->u.request->packing = recordPacking;
554 sr->u.request->stylesheet = stylesheet;
555 yaz_sru_facet_request(decode , &sr->u.request->facetList,
556 &facetLimit, &facetStart, &facetSort);
558 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
559 &sr->u.request->maximumRecords,
562 yaz_sru_decode_integer(decode, "startRecord", startRecord,
563 &sr->u.request->startRecord,
566 sr->u.request->database = db;
568 (*soap_package) = (Z_SOAP *)
569 odr_malloc(decode, sizeof(**soap_package));
570 (*soap_package)->which = Z_SOAP_generic;
572 (*soap_package)->u.generic = (Z_SOAP_Generic *)
573 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
575 (*soap_package)->u.generic->p = sr;
576 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
577 (*soap_package)->u.generic->no = 0;
579 (*soap_package)->ns = "SRU";
583 else if (!strcmp(operation, "explain"))
585 /* Transfer SRU explain parameters to common struct */
586 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
587 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
589 sr->srw_version = version;
590 sr->extra_args = extra_args;
591 yaz_srw_decodeauth(sr, hreq, username, password, decode);
593 sr->u.explain_request->recordPacking = recordXMLEscaping;
594 sr->u.explain_request->packing = recordPacking;
595 sr->u.explain_request->database = db;
597 sr->u.explain_request->stylesheet = stylesheet;
599 (*soap_package) = (Z_SOAP *)
600 odr_malloc(decode, sizeof(**soap_package));
601 (*soap_package)->which = Z_SOAP_generic;
603 (*soap_package)->u.generic = (Z_SOAP_Generic *)
604 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
606 (*soap_package)->u.generic->p = sr;
607 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
608 (*soap_package)->u.generic->no = 0;
610 (*soap_package)->ns = "SRU";
614 else if (!strcmp(operation, "scan"))
616 /* Transfer SRU scan parameters to common struct */
617 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
618 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
620 sr->srw_version = version;
621 sr->extra_args = extra_args;
623 yaz_srw_decodeauth(sr, hreq, username, password, decode);
625 sr->u.scan_request->queryType = queryType;
626 sr->u.scan_request->scanClause = scanClause;
629 yaz_add_srw_diagnostic(
630 decode, diag, num_diag,
631 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
632 sr->u.scan_request->database = db;
634 yaz_sru_decode_integer(decode, "maximumTerms",
636 &sr->u.scan_request->maximumTerms,
639 yaz_sru_decode_integer(decode, "responsePosition",
641 &sr->u.scan_request->responsePosition,
644 sr->u.scan_request->stylesheet = stylesheet;
646 (*soap_package) = (Z_SOAP *)
647 odr_malloc(decode, sizeof(**soap_package));
648 (*soap_package)->which = Z_SOAP_generic;
650 (*soap_package)->u.generic = (Z_SOAP_Generic *)
651 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
653 (*soap_package)->u.generic->p = sr;
654 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
655 (*soap_package)->u.generic->no = 0;
657 (*soap_package)->ns = "SRU";
663 /* unsupported operation ... */
664 /* Act as if we received a explain request and throw diagnostic. */
666 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
668 sr->srw_version = version;
670 sr->u.explain_request->recordPacking = recordPacking;
671 sr->u.explain_request->database = db;
673 sr->u.explain_request->stylesheet = stylesheet;
675 (*soap_package) = (Z_SOAP *)
676 odr_malloc(decode, sizeof(**soap_package));
677 (*soap_package)->which = Z_SOAP_generic;
679 (*soap_package)->u.generic = (Z_SOAP_Generic *)
680 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
682 (*soap_package)->u.generic->p = sr;
683 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
684 (*soap_package)->u.generic->no = 0;
686 (*soap_package)->ns = "SRU";
688 yaz_add_srw_diagnostic(decode, diag, num_diag,
689 YAZ_SRW_UNSUPP_OPERATION, operation);
699 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
701 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
702 odr_malloc(o, sizeof(*res));
704 res->extraRecordData_buf = 0;
705 res->extraRecordData_len = 0;
706 res->recordIdentifier = 0;
711 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
713 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
716 for (i = 0; i<n; i++)
718 res[i].recordSchema = 0;
719 res[i].recordPacking = Z_SRW_recordPacking_string;
720 res[i].recordData_buf = 0;
721 res[i].recordData_len = 0;
722 res[i].recordPosition = 0;
727 Z_SRW_record *yaz_srw_get_record(ODR o)
729 return yaz_srw_get_records(o, 1);
732 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
734 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
735 p->srw_version = odr_strdup(o, version);
739 p->extraResponseData_buf = 0;
740 p->extraResponseData_len = 0;
744 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
746 return yaz_srw_get_core_ver(o, "2.0");
749 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
751 return yaz_srw_get_pdu(o, which, "2.0");
754 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
756 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
761 case Z_SRW_searchRetrieve_request:
762 sr->u.request = (Z_SRW_searchRetrieveRequest *)
763 odr_malloc(o, sizeof(*sr->u.request));
764 sr->u.request->queryType = "cql";
765 sr->u.request->query = 0;
766 sr->u.request->sort_type = Z_SRW_sort_type_none;
767 sr->u.request->sort.none = 0;
768 sr->u.request->startRecord = 0;
769 sr->u.request->maximumRecords = 0;
770 sr->u.request->recordSchema = 0;
771 sr->u.request->recordPacking = 0;
772 sr->u.request->packing = 0;
773 sr->u.request->recordXPath = 0;
774 sr->u.request->database = 0;
775 sr->u.request->resultSetTTL = 0;
776 sr->u.request->stylesheet = 0;
777 sr->u.request->facetList = 0;
779 case Z_SRW_searchRetrieve_response:
780 sr->u.response = (Z_SRW_searchRetrieveResponse *)
781 odr_malloc(o, sizeof(*sr->u.response));
782 sr->u.response->numberOfRecords = 0;
783 sr->u.response->resultCountPrecision = 0;
784 sr->u.response->resultSetId = 0;
785 sr->u.response->resultSetIdleTime = 0;
786 sr->u.response->records = 0;
787 sr->u.response->num_records = 0;
788 sr->u.response->diagnostics = 0;
789 sr->u.response->num_diagnostics = 0;
790 sr->u.response->nextRecordPosition = 0;
791 sr->u.response->extra_records = 0;
792 sr->u.response->facetList = 0;
793 sr->u.response->suggestions = 0;
795 case Z_SRW_explain_request:
796 sr->u.explain_request = (Z_SRW_explainRequest *)
797 odr_malloc(o, sizeof(*sr->u.explain_request));
798 sr->u.explain_request->recordPacking = 0;
799 sr->u.explain_request->packing = 0;
800 sr->u.explain_request->database = 0;
801 sr->u.explain_request->stylesheet = 0;
803 case Z_SRW_explain_response:
804 sr->u.explain_response = (Z_SRW_explainResponse *)
805 odr_malloc(o, sizeof(*sr->u.explain_response));
806 sr->u.explain_response->record.recordData_buf = 0;
807 sr->u.explain_response->record.recordData_len = 0;
808 sr->u.explain_response->record.recordSchema = 0;
809 sr->u.explain_response->record.recordPosition = 0;
810 sr->u.explain_response->record.recordPacking =
811 Z_SRW_recordPacking_string;
812 sr->u.explain_response->diagnostics = 0;
813 sr->u.explain_response->num_diagnostics = 0;
814 sr->u.explain_response->extra_record = 0;
816 case Z_SRW_scan_request:
817 sr->u.scan_request = (Z_SRW_scanRequest *)
818 odr_malloc(o, sizeof(*sr->u.scan_request));
819 sr->u.scan_request->database = 0;
820 sr->u.scan_request->stylesheet = 0;
821 sr->u.scan_request->maximumTerms = 0;
822 sr->u.scan_request->responsePosition = 0;
823 sr->u.scan_request->queryType = "cql";
824 sr->u.scan_request->scanClause = 0;
826 case Z_SRW_scan_response:
827 sr->u.scan_response = (Z_SRW_scanResponse *)
828 odr_malloc(o, sizeof(*sr->u.scan_response));
829 sr->u.scan_response->terms = 0;
830 sr->u.scan_response->num_terms = 0;
831 sr->u.scan_response->diagnostics = 0;
832 sr->u.scan_response->num_diagnostics = 0;
834 case Z_SRW_update_request:
835 sr->u.update_request = (Z_SRW_updateRequest *)
836 odr_malloc(o, sizeof(*sr->u.update_request));
837 sr->u.update_request->database = 0;
838 sr->u.update_request->stylesheet = 0;
839 sr->u.update_request->record = 0;
840 sr->u.update_request->recordId = 0;
841 sr->u.update_request->recordVersions = 0;
842 sr->u.update_request->num_recordVersions = 0;
843 sr->u.update_request->extra_record = 0;
844 sr->u.update_request->extraRequestData_buf = 0;
845 sr->u.update_request->extraRequestData_len = 0;
846 sr->u.request->database = 0;
848 case Z_SRW_update_response:
849 sr->u.update_response = (Z_SRW_updateResponse *)
850 odr_malloc(o, sizeof(*sr->u.update_response));
851 sr->u.update_response->operationStatus = 0;
852 sr->u.update_response->recordId = 0;
853 sr->u.update_response->recordVersions = 0;
854 sr->u.update_response->num_recordVersions = 0;
855 sr->u.update_response->record = 0;
856 sr->u.update_response->extra_record = 0;
857 sr->u.update_response->extraResponseData_buf = 0;
858 sr->u.update_response->extraResponseData_len = 0;
859 sr->u.update_response->diagnostics = 0;
860 sr->u.update_response->num_diagnostics = 0;
865 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
866 char *a_name, Odr_int *val)
871 value[*i] = (char *) odr_malloc(o, 40);
872 sprintf(value[*i], ODR_INT_PRINTF, *val);
877 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
878 char *a_name, char *val)
888 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
889 char **name, char **value, int max_names)
891 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
894 yaz_add_name_value_str(encode, name, value, &i, "version",
895 srw_pdu->srw_version);
896 name[i] = "operation";
897 switch (srw_pdu->which)
899 case Z_SRW_searchRetrieve_request:
900 value[i++] = "searchRetrieve";
901 queryType = srw_pdu->u.request->queryType;
904 if (queryType && strcmp(queryType, "cql"))
905 yaz_add_name_value_str(encode, name, value, &i, "queryType",
907 yaz_add_name_value_str(encode, name, value, &i, "query",
908 srw_pdu->u.request->query);
912 if (!strcmp(queryType, "cql"))
914 yaz_add_name_value_str(encode, name, value, &i, "query",
915 srw_pdu->u.request->query);
917 else if (!strcmp(queryType, "pqf"))
919 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
920 srw_pdu->u.request->query);
922 else if (!strcmp(queryType, "xcql"))
924 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
925 srw_pdu->u.request->query);
928 switch (srw_pdu->u.request->sort_type)
930 case Z_SRW_sort_type_none:
932 case Z_SRW_sort_type_sort:
933 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
934 srw_pdu->u.request->sort.sortKeys);
937 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
938 srw_pdu->u.request->startRecord);
939 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
940 srw_pdu->u.request->maximumRecords);
941 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
942 srw_pdu->u.request->recordSchema);
945 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
946 srw_pdu->u.request->recordPacking);
947 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
948 srw_pdu->u.request->packing);
951 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
952 srw_pdu->u.request->recordPacking);
953 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
954 srw_pdu->u.request->recordXPath);
955 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
956 srw_pdu->u.request->stylesheet);
957 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
958 srw_pdu->u.request->resultSetTTL);
960 const char *facetLimit = 0;
961 const char *facetStart = 0;
962 const char *facetSort = 0;
963 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
964 &facetLimit, &facetStart, &facetSort);
965 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
966 (char *) facetLimit);
967 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
968 (char *) facetStart);
969 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
973 case Z_SRW_explain_request:
974 value[i++] = "explain";
978 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
979 srw_pdu->u.explain_request->recordPacking);
980 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
981 srw_pdu->u.explain_request->packing);
984 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
985 srw_pdu->u.explain_request->recordPacking);
986 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
987 srw_pdu->u.explain_request->stylesheet);
989 case Z_SRW_scan_request:
991 queryType = srw_pdu->u.scan_request->queryType;
994 if (queryType && strcmp(queryType, "cql"))
995 yaz_add_name_value_str(encode, name, value, &i, "queryType",
997 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
998 srw_pdu->u.scan_request->scanClause);
1002 if (!queryType || !strcmp(queryType, "cql"))
1003 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1004 srw_pdu->u.scan_request->scanClause);
1005 else if (!strcmp(queryType, "pqf"))
1006 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1007 srw_pdu->u.scan_request->scanClause);
1008 else if (!strcmp(queryType, "xcql"))
1009 yaz_add_name_value_str(encode, name, value, &i,
1011 srw_pdu->u.scan_request->scanClause);
1013 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1014 srw_pdu->u.scan_request->responsePosition);
1015 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1016 srw_pdu->u.scan_request->maximumTerms);
1017 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1018 srw_pdu->u.scan_request->stylesheet);
1020 case Z_SRW_update_request:
1021 value[i++] = "update";
1026 if (srw_pdu->extra_args)
1028 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1029 for (; ea && i < max_names-1; ea = ea->next)
1032 value[i] = ea->value;
1041 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1042 ODR encode, const char *charset)
1044 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1048 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1049 srw_pdu->username, srw_pdu->password);
1050 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1052 yaz_array_to_uri(&uri_args, encode, name, value);
1054 hreq->method = "GET";
1057 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1059 sprintf(path, "%s?%s", hreq->path, uri_args);
1062 z_HTTP_header_add_content_type(encode, &hreq->headers,
1063 "text/xml", charset);
1067 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1068 ODR encode, const char *charset)
1070 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1073 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1074 srw_pdu->username, srw_pdu->password);
1075 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1078 yaz_array_to_uri(&uri_args, encode, name, value);
1080 hreq->method = "POST";
1082 hreq->content_buf = uri_args;
1083 hreq->content_len = strlen(uri_args);
1085 z_HTTP_header_add_content_type(encode, &hreq->headers,
1086 "application/x-www-form-urlencoded",
1091 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1092 ODR odr, const char *charset)
1094 Z_SOAP_Handler handlers[3] = {
1096 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1097 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1101 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1103 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1104 srw_pdu->username, srw_pdu->password);
1105 z_HTTP_header_add_content_type(odr,
1107 "text/xml", charset);
1109 z_HTTP_header_add(odr, &hreq->headers,
1110 "SOAPAction", "\"\"");
1111 p->which = Z_SOAP_generic;
1112 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1113 p->u.generic->no = 0;
1114 p->u.generic->ns = 0;
1115 p->u.generic->p = srw_pdu;
1116 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1119 if (srw_pdu->which == Z_SRW_update_request ||
1120 srw_pdu->which == Z_SRW_update_response)
1121 p->u.generic->no = 1; /* second handler */
1123 return z_soap_codec_enc(odr, &p,
1125 &hreq->content_len, handlers,
1129 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1131 Z_SRW_recordVersion *ver
1132 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1134 for (i = 0; i < num; ++i)
1136 ver[i].versionType = 0;
1137 ver[i].versionValue = 0;
1142 const char *yaz_srw_pack_to_str(int pack)
1146 case Z_SRW_recordPacking_string:
1148 case Z_SRW_recordPacking_XML:
1150 case Z_SRW_recordPacking_URL:
1156 int yaz_srw_str_to_pack(const char *str)
1158 if (!yaz_matchstr(str, "string"))
1159 return Z_SRW_recordPacking_string;
1160 if (!yaz_matchstr(str, "xml"))
1161 return Z_SRW_recordPacking_XML;
1162 if (!yaz_matchstr(str, "url"))
1163 return Z_SRW_recordPacking_URL;
1167 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1173 Z_SRW_extra_arg **ea = &sr->extra_args;
1174 yaz_uri_to_array(extra_args, odr, &name, &val);
1176 /** append rather than override */
1181 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1182 (*ea)->name = *name;
1183 (*ea)->value = *val;
1196 * c-file-style: "Stroustrup"
1197 * indent-tabs-mode: nil
1199 * vim: shiftwidth=4 tabstop=8 expandtab