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_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 charset_p += 10; /* skip ; charset= */
240 if (charset_p[i] == '"' || charset_p[i] == '\'')
241 sep = charset_p[i++];
242 *charset = odr_strdup(o, charset_p);
243 while (charset_p[i] && charset_p[i] != sep)
245 if (!sep && strchr("; \n\r", charset_p[i]))
247 if (charset_p[i] == '\\' && charset_p[i+1])
249 (*charset)[j++] = charset_p[i++];
251 (*charset)[j] = '\0';
256 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
257 Z_SOAP **soap_package, ODR decode, char **charset)
259 if (!strcmp(hreq->method, "POST"))
261 const char *content_type = z_HTTP_header_lookup(hreq->headers,
264 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
265 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
266 !yaz_strcmp_del("text/plain", content_type, "; ")))
268 char *db = "Default";
269 const char *p0 = hreq->path, *p1;
272 static Z_SOAP_Handler soap_handlers[5] = {
274 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
275 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
276 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
277 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
284 p1 = strchr(p0, '?');
286 p1 = p0 + strlen(p0);
288 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
290 ret = z_soap_codec(decode, soap_package,
291 &hreq->content_buf, &hreq->content_len,
293 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
295 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
296 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
298 /* last entry in handlers - SRU 2.0 - is turned into
299 offset 0.. due to other pieces relying on it */
300 if ((*soap_package)->u.generic->no == 3)
301 (*soap_package)->u.generic->no = 0;
302 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
303 (*srw_pdu)->u.request->database == 0)
304 (*srw_pdu)->u.request->database = db;
306 if ((*srw_pdu)->which == Z_SRW_explain_request &&
307 (*srw_pdu)->u.explain_request->database == 0)
308 (*srw_pdu)->u.explain_request->database = db;
310 if ((*srw_pdu)->which == Z_SRW_scan_request &&
311 (*srw_pdu)->u.scan_request->database == 0)
312 (*srw_pdu)->u.scan_request->database = db;
314 if ((*srw_pdu)->which == Z_SRW_update_request &&
315 (*srw_pdu)->u.update_request->database == 0)
316 (*srw_pdu)->u.update_request->database = db;
327 static int yaz_sru_decode_integer(ODR odr, const char *pname,
328 const char *valstr, Odr_int **valp,
329 Z_SRW_diagnostic **diag, int *num_diag,
335 if (sscanf(valstr, "%d", &ival) != 1)
337 yaz_add_srw_diagnostic(odr, diag, num_diag,
338 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
341 if (min_value >= 0 && ival < min_value)
343 yaz_add_srw_diagnostic(odr, diag, num_diag,
344 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
347 *valp = odr_intdup(odr, ival);
353 http://www.loc.gov/z3950/agency/zing/srw/service.html
355 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
356 Z_SOAP **soap_package, ODR decode, char **charset,
357 Z_SRW_diagnostic **diag, int *num_diag)
360 static Z_SOAP_Handler soap_handlers[2] = {
361 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
365 const char *content_type = z_HTTP_header_lookup(hreq->headers,
369 SRU GET: ignore content type.
370 SRU POST: we support "application/x-www-form-urlencoded";
371 not "multipart/form-data" .
373 if (!strcmp(hreq->method, "GET")
375 (!strcmp(hreq->method, "POST") && content_type &&
376 !yaz_strcmp_del("application/x-www-form-urlencoded",
377 content_type, "; ")))
379 char *db = "Default";
380 const char *p0 = hreq->path, *p1;
382 const char *operation = 0;
385 char *queryType = "cql";
389 char *stylesheet = 0;
390 char *scanClause = 0;
391 char *recordXPath = 0;
392 char *recordSchema = 0;
393 char *recordXMLEscaping = 0;
394 char *recordPacking = 0;
395 char *maximumRecords = 0;
396 char *startRecord = 0;
397 char *maximumTerms = 0;
398 char *responsePosition = 0;
399 const char *facetLimit = 0;
400 const char *facetStart = 0;
401 const char *facetSort = 0;
402 Z_SRW_extra_arg *extra_args = 0;
407 grab_charset(decode, content_type, charset);
408 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
413 p1 = strchr(p0, '?');
415 p1 = p0 + strlen(p0);
417 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
418 if (!strcmp(hreq->method, "POST"))
419 p1 = hreq->content_buf;
420 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
425 for (i = 0; uri_name[i]; i++)
427 char *n = uri_name[i];
428 char *v = uri_val[i];
429 if (!strcmp(n, "query"))
431 else if (!strcmp(n, "x-pquery"))
436 else if (!strcmp(n, "queryType"))
438 else if (!strcmp(n, "x-username"))
440 else if (!strcmp(n, "x-password"))
442 else if (!strcmp(n, "operation"))
444 else if (!strcmp(n, "stylesheet"))
446 else if (!strcmp(n, "sortKeys"))
448 else if (!strcmp(n, "recordXPath"))
450 else if (!strcmp(n, "recordSchema"))
452 else if (!strcmp(n, "recordPacking"))
454 else if (!strcmp(n, "recordXMLEscaping"))
455 recordXMLEscaping = v;
456 else if (!strcmp(n, "version"))
458 else if (!strcmp(n, "scanClause"))
460 else if (!strcmp(n, "x-pScanClause"))
465 else if (!strcmp(n, "maximumRecords"))
467 else if (!strcmp(n, "startRecord"))
469 else if (!strcmp(n, "maximumTerms"))
471 else if (!strcmp(n, "responsePosition"))
472 responsePosition = v;
473 else if (!strcmp(n, "facetLimit"))
475 else if (!strcmp(n, "facetStart"))
477 else if (!strcmp(n, "facetSort"))
479 else if (!strcmp(n, "extraRequestData"))
480 ; /* ignoring extraRequestData */
481 else if (n[0] == 'x' && n[1] == '-')
483 Z_SRW_extra_arg **l = &extra_args;
486 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
487 (*l)->name = odr_strdup(decode, n);
488 (*l)->value = odr_strdup(decode, v);
494 yaz_add_srw_diagnostic(decode, diag, num_diag,
495 YAZ_SRW_UNSUPP_PARAMETER, n);
502 operation = "searchRetrieve";
506 version = yaz_negotiate_sru_version(version);
509 { /* negotiation failed. */
510 yaz_add_srw_diagnostic(decode, diag, num_diag,
511 YAZ_SRW_UNSUPP_VERSION, "2.0");
517 yaz_add_srw_diagnostic(
518 decode, diag, num_diag,
519 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
520 operation = "explain";
522 if (strcmp(version, "2.0"))
524 if (recordXMLEscaping)
526 yaz_add_srw_diagnostic(decode, diag, num_diag,
527 YAZ_SRW_UNSUPP_PARAMETER,
528 "recordXMLEscaping");
531 recordXMLEscaping = recordPacking;
532 recordPacking = "packed";
534 if (!recordXMLEscaping)
535 recordXMLEscaping = "xml";
536 if (!strcmp(operation, "searchRetrieve"))
538 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
540 sr->srw_version = version;
541 sr->extra_args = extra_args;
543 yaz_srw_decodeauth(sr, hreq, username, password, decode);
545 sr->u.request->queryType = queryType;
546 sr->u.request->query = query;
549 yaz_add_srw_diagnostic(
550 decode, diag, num_diag,
551 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
555 sr->u.request->sort_type = Z_SRW_sort_type_sort;
556 sr->u.request->sort.sortKeys = sortKeys;
558 sr->u.request->recordXPath = recordXPath;
559 sr->u.request->recordSchema = recordSchema;
560 sr->u.request->recordPacking = recordXMLEscaping;
561 sr->u.request->packing = recordPacking;
562 sr->u.request->stylesheet = stylesheet;
563 yaz_sru_facet_request(decode , &sr->u.request->facetList,
564 &facetLimit, &facetStart, &facetSort);
566 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
567 &sr->u.request->maximumRecords,
570 yaz_sru_decode_integer(decode, "startRecord", startRecord,
571 &sr->u.request->startRecord,
574 sr->u.request->database = db;
576 (*soap_package) = (Z_SOAP *)
577 odr_malloc(decode, sizeof(**soap_package));
578 (*soap_package)->which = Z_SOAP_generic;
580 (*soap_package)->u.generic = (Z_SOAP_Generic *)
581 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
583 (*soap_package)->u.generic->p = sr;
584 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
585 (*soap_package)->u.generic->no = 0;
587 (*soap_package)->ns = "SRU";
591 else if (!strcmp(operation, "explain"))
593 /* Transfer SRU explain parameters to common struct */
594 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
595 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
597 sr->srw_version = version;
598 sr->extra_args = extra_args;
599 yaz_srw_decodeauth(sr, hreq, username, password, decode);
601 sr->u.explain_request->recordPacking = recordXMLEscaping;
602 sr->u.explain_request->packing = recordPacking;
603 sr->u.explain_request->database = db;
605 sr->u.explain_request->stylesheet = stylesheet;
607 (*soap_package) = (Z_SOAP *)
608 odr_malloc(decode, sizeof(**soap_package));
609 (*soap_package)->which = Z_SOAP_generic;
611 (*soap_package)->u.generic = (Z_SOAP_Generic *)
612 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
614 (*soap_package)->u.generic->p = sr;
615 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
616 (*soap_package)->u.generic->no = 0;
618 (*soap_package)->ns = "SRU";
622 else if (!strcmp(operation, "scan"))
624 /* Transfer SRU scan parameters to common struct */
625 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
626 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
628 sr->srw_version = version;
629 sr->extra_args = extra_args;
631 yaz_srw_decodeauth(sr, hreq, username, password, decode);
633 sr->u.scan_request->queryType = queryType;
634 sr->u.scan_request->scanClause = scanClause;
637 yaz_add_srw_diagnostic(
638 decode, diag, num_diag,
639 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
640 sr->u.scan_request->database = db;
642 yaz_sru_decode_integer(decode, "maximumTerms",
644 &sr->u.scan_request->maximumTerms,
647 yaz_sru_decode_integer(decode, "responsePosition",
649 &sr->u.scan_request->responsePosition,
652 sr->u.scan_request->stylesheet = stylesheet;
654 (*soap_package) = (Z_SOAP *)
655 odr_malloc(decode, sizeof(**soap_package));
656 (*soap_package)->which = Z_SOAP_generic;
658 (*soap_package)->u.generic = (Z_SOAP_Generic *)
659 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
661 (*soap_package)->u.generic->p = sr;
662 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
663 (*soap_package)->u.generic->no = 0;
665 (*soap_package)->ns = "SRU";
671 /* unsupported operation ... */
672 /* Act as if we received a explain request and throw diagnostic. */
674 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
676 sr->srw_version = version;
678 sr->u.explain_request->recordPacking = recordPacking;
679 sr->u.explain_request->database = db;
681 sr->u.explain_request->stylesheet = stylesheet;
683 (*soap_package) = (Z_SOAP *)
684 odr_malloc(decode, sizeof(**soap_package));
685 (*soap_package)->which = Z_SOAP_generic;
687 (*soap_package)->u.generic = (Z_SOAP_Generic *)
688 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
690 (*soap_package)->u.generic->p = sr;
691 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
692 (*soap_package)->u.generic->no = 0;
694 (*soap_package)->ns = "SRU";
696 yaz_add_srw_diagnostic(decode, diag, num_diag,
697 YAZ_SRW_UNSUPP_OPERATION, operation);
707 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
709 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
710 odr_malloc(o, sizeof(*res));
712 res->extraRecordData_buf = 0;
713 res->extraRecordData_len = 0;
714 res->recordIdentifier = 0;
719 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
721 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
724 for (i = 0; i<n; i++)
726 res[i].recordSchema = 0;
727 res[i].recordPacking = Z_SRW_recordPacking_string;
728 res[i].recordData_buf = 0;
729 res[i].recordData_len = 0;
730 res[i].recordPosition = 0;
735 Z_SRW_record *yaz_srw_get_record(ODR o)
737 return yaz_srw_get_records(o, 1);
740 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
742 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
743 p->srw_version = odr_strdup(o, version);
747 p->extraResponseData_buf = 0;
748 p->extraResponseData_len = 0;
752 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
754 return yaz_srw_get_core_ver(o, "2.0");
757 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
759 return yaz_srw_get_pdu(o, which, "2.0");
762 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
764 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
769 case Z_SRW_searchRetrieve_request:
770 sr->u.request = (Z_SRW_searchRetrieveRequest *)
771 odr_malloc(o, sizeof(*sr->u.request));
772 sr->u.request->queryType = "cql";
773 sr->u.request->query = 0;
774 sr->u.request->sort_type = Z_SRW_sort_type_none;
775 sr->u.request->sort.none = 0;
776 sr->u.request->startRecord = 0;
777 sr->u.request->maximumRecords = 0;
778 sr->u.request->recordSchema = 0;
779 sr->u.request->recordPacking = 0;
780 sr->u.request->packing = 0;
781 sr->u.request->recordXPath = 0;
782 sr->u.request->database = 0;
783 sr->u.request->resultSetTTL = 0;
784 sr->u.request->stylesheet = 0;
785 sr->u.request->facetList = 0;
787 case Z_SRW_searchRetrieve_response:
788 sr->u.response = (Z_SRW_searchRetrieveResponse *)
789 odr_malloc(o, sizeof(*sr->u.response));
790 sr->u.response->numberOfRecords = 0;
791 sr->u.response->resultCountPrecision = 0;
792 sr->u.response->resultSetId = 0;
793 sr->u.response->resultSetIdleTime = 0;
794 sr->u.response->records = 0;
795 sr->u.response->num_records = 0;
796 sr->u.response->diagnostics = 0;
797 sr->u.response->num_diagnostics = 0;
798 sr->u.response->nextRecordPosition = 0;
799 sr->u.response->extra_records = 0;
800 sr->u.response->facetList = 0;
801 sr->u.response->suggestions = 0;
803 case Z_SRW_explain_request:
804 sr->u.explain_request = (Z_SRW_explainRequest *)
805 odr_malloc(o, sizeof(*sr->u.explain_request));
806 sr->u.explain_request->recordPacking = 0;
807 sr->u.explain_request->packing = 0;
808 sr->u.explain_request->database = 0;
809 sr->u.explain_request->stylesheet = 0;
811 case Z_SRW_explain_response:
812 sr->u.explain_response = (Z_SRW_explainResponse *)
813 odr_malloc(o, sizeof(*sr->u.explain_response));
814 sr->u.explain_response->record.recordData_buf = 0;
815 sr->u.explain_response->record.recordData_len = 0;
816 sr->u.explain_response->record.recordSchema = 0;
817 sr->u.explain_response->record.recordPosition = 0;
818 sr->u.explain_response->record.recordPacking =
819 Z_SRW_recordPacking_string;
820 sr->u.explain_response->diagnostics = 0;
821 sr->u.explain_response->num_diagnostics = 0;
822 sr->u.explain_response->extra_record = 0;
824 case Z_SRW_scan_request:
825 sr->u.scan_request = (Z_SRW_scanRequest *)
826 odr_malloc(o, sizeof(*sr->u.scan_request));
827 sr->u.scan_request->database = 0;
828 sr->u.scan_request->stylesheet = 0;
829 sr->u.scan_request->maximumTerms = 0;
830 sr->u.scan_request->responsePosition = 0;
831 sr->u.scan_request->queryType = "cql";
832 sr->u.scan_request->scanClause = 0;
834 case Z_SRW_scan_response:
835 sr->u.scan_response = (Z_SRW_scanResponse *)
836 odr_malloc(o, sizeof(*sr->u.scan_response));
837 sr->u.scan_response->terms = 0;
838 sr->u.scan_response->num_terms = 0;
839 sr->u.scan_response->diagnostics = 0;
840 sr->u.scan_response->num_diagnostics = 0;
842 case Z_SRW_update_request:
843 sr->u.update_request = (Z_SRW_updateRequest *)
844 odr_malloc(o, sizeof(*sr->u.update_request));
845 sr->u.update_request->database = 0;
846 sr->u.update_request->stylesheet = 0;
847 sr->u.update_request->record = 0;
848 sr->u.update_request->recordId = 0;
849 sr->u.update_request->recordVersions = 0;
850 sr->u.update_request->num_recordVersions = 0;
851 sr->u.update_request->extra_record = 0;
852 sr->u.update_request->extraRequestData_buf = 0;
853 sr->u.update_request->extraRequestData_len = 0;
854 sr->u.request->database = 0;
856 case Z_SRW_update_response:
857 sr->u.update_response = (Z_SRW_updateResponse *)
858 odr_malloc(o, sizeof(*sr->u.update_response));
859 sr->u.update_response->operationStatus = 0;
860 sr->u.update_response->recordId = 0;
861 sr->u.update_response->recordVersions = 0;
862 sr->u.update_response->num_recordVersions = 0;
863 sr->u.update_response->record = 0;
864 sr->u.update_response->extra_record = 0;
865 sr->u.update_response->extraResponseData_buf = 0;
866 sr->u.update_response->extraResponseData_len = 0;
867 sr->u.update_response->diagnostics = 0;
868 sr->u.update_response->num_diagnostics = 0;
873 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
874 char *a_name, Odr_int *val)
879 value[*i] = (char *) odr_malloc(o, 40);
880 sprintf(value[*i], ODR_INT_PRINTF, *val);
885 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
886 char *a_name, char *val)
896 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
897 char **name, char **value, int max_names)
899 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
902 yaz_add_name_value_str(encode, name, value, &i, "version",
903 srw_pdu->srw_version);
904 name[i] = "operation";
905 switch (srw_pdu->which)
907 case Z_SRW_searchRetrieve_request:
908 value[i++] = "searchRetrieve";
909 queryType = srw_pdu->u.request->queryType;
912 if (queryType && strcmp(queryType, "cql"))
913 yaz_add_name_value_str(encode, name, value, &i, "queryType",
915 yaz_add_name_value_str(encode, name, value, &i, "query",
916 srw_pdu->u.request->query);
920 if (!strcmp(queryType, "cql"))
922 yaz_add_name_value_str(encode, name, value, &i, "query",
923 srw_pdu->u.request->query);
925 else if (!strcmp(queryType, "pqf"))
927 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
928 srw_pdu->u.request->query);
930 else if (!strcmp(queryType, "xcql"))
932 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
933 srw_pdu->u.request->query);
936 switch (srw_pdu->u.request->sort_type)
938 case Z_SRW_sort_type_none:
940 case Z_SRW_sort_type_sort:
941 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
942 srw_pdu->u.request->sort.sortKeys);
945 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
946 srw_pdu->u.request->startRecord);
947 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
948 srw_pdu->u.request->maximumRecords);
949 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
950 srw_pdu->u.request->recordSchema);
953 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
954 srw_pdu->u.request->recordPacking);
955 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
956 srw_pdu->u.request->packing);
959 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
960 srw_pdu->u.request->recordPacking);
961 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
962 srw_pdu->u.request->recordXPath);
963 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
964 srw_pdu->u.request->stylesheet);
965 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
966 srw_pdu->u.request->resultSetTTL);
968 const char *facetLimit = 0;
969 const char *facetStart = 0;
970 const char *facetSort = 0;
971 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
972 &facetLimit, &facetStart, &facetSort);
973 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
974 (char *) facetLimit);
975 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
976 (char *) facetStart);
977 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
981 case Z_SRW_explain_request:
982 value[i++] = "explain";
986 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
987 srw_pdu->u.explain_request->recordPacking);
988 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
989 srw_pdu->u.explain_request->packing);
992 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
993 srw_pdu->u.explain_request->recordPacking);
994 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
995 srw_pdu->u.explain_request->stylesheet);
997 case Z_SRW_scan_request:
999 queryType = srw_pdu->u.scan_request->queryType;
1002 if (queryType && strcmp(queryType, "cql"))
1003 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1005 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1006 srw_pdu->u.scan_request->scanClause);
1010 if (!queryType || !strcmp(queryType, "cql"))
1011 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1012 srw_pdu->u.scan_request->scanClause);
1013 else if (!strcmp(queryType, "pqf"))
1014 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1015 srw_pdu->u.scan_request->scanClause);
1016 else if (!strcmp(queryType, "xcql"))
1017 yaz_add_name_value_str(encode, name, value, &i,
1019 srw_pdu->u.scan_request->scanClause);
1021 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1022 srw_pdu->u.scan_request->responsePosition);
1023 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1024 srw_pdu->u.scan_request->maximumTerms);
1025 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1026 srw_pdu->u.scan_request->stylesheet);
1028 case Z_SRW_update_request:
1029 value[i++] = "update";
1034 if (srw_pdu->extra_args)
1036 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1037 for (; ea && i < max_names-1; ea = ea->next)
1040 value[i] = ea->value;
1049 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1050 ODR encode, const char *charset)
1052 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1056 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1057 srw_pdu->username, srw_pdu->password);
1058 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1060 yaz_array_to_uri(&uri_args, encode, name, value);
1062 hreq->method = "GET";
1065 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1067 sprintf(path, "%s?%s", hreq->path, uri_args);
1070 z_HTTP_header_add_content_type(encode, &hreq->headers,
1071 "text/xml", charset);
1075 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1076 ODR encode, const char *charset)
1078 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1081 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1082 srw_pdu->username, srw_pdu->password);
1083 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1086 yaz_array_to_uri(&uri_args, encode, name, value);
1088 hreq->method = "POST";
1090 hreq->content_buf = uri_args;
1091 hreq->content_len = strlen(uri_args);
1093 z_HTTP_header_add_content_type(encode, &hreq->headers,
1094 "application/x-www-form-urlencoded",
1099 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1100 ODR odr, const char *charset)
1102 Z_SOAP_Handler handlers[3] = {
1104 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1105 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1109 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1111 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1112 srw_pdu->username, srw_pdu->password);
1113 z_HTTP_header_add_content_type(odr,
1115 "text/xml", 0 /* no charset in MIME */);
1117 z_HTTP_header_add(odr, &hreq->headers,
1118 "SOAPAction", "\"\"");
1119 p->which = Z_SOAP_generic;
1120 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1121 p->u.generic->no = 0;
1122 p->u.generic->ns = 0;
1123 p->u.generic->p = srw_pdu;
1124 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1127 if (srw_pdu->which == Z_SRW_update_request ||
1128 srw_pdu->which == Z_SRW_update_response)
1129 p->u.generic->no = 1; /* second handler */
1131 return z_soap_codec_enc(odr, &p,
1133 &hreq->content_len, handlers,
1137 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1139 Z_SRW_recordVersion *ver
1140 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1142 for (i = 0; i < num; ++i)
1144 ver[i].versionType = 0;
1145 ver[i].versionValue = 0;
1150 const char *yaz_srw_pack_to_str(int pack)
1154 case Z_SRW_recordPacking_string:
1156 case Z_SRW_recordPacking_XML:
1158 case Z_SRW_recordPacking_URL:
1164 int yaz_srw_str_to_pack(const char *str)
1166 if (!yaz_matchstr(str, "string"))
1167 return Z_SRW_recordPacking_string;
1168 if (!yaz_matchstr(str, "xml"))
1169 return Z_SRW_recordPacking_XML;
1170 if (!yaz_matchstr(str, "url"))
1171 return Z_SRW_recordPacking_URL;
1175 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1181 Z_SRW_extra_arg **ea = &sr->extra_args;
1182 yaz_uri_to_array(extra_args, odr, &name, &val);
1184 /** append rather than override */
1189 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1190 (*ea)->name = *name;
1191 (*ea)->value = *val;
1204 * c-file-style: "Stroustrup"
1205 * indent-tabs-mode: nil
1207 * vim: shiftwidth=4 tabstop=8 expandtab