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);
43 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
44 const char *node_name,
45 const char *attribute_name)
47 struct _xmlAttr *attr;
48 // check if the node name matches
49 if (strcmp((const char*) ptr->name, node_name))
51 // check if the attribute name and return the value
52 for (attr = ptr->properties; attr; attr = attr->next)
53 if (attr->children && attr->children->type == XML_TEXT_NODE)
55 if (!strcmp((const char *) attr->name, attribute_name))
56 return (const char *) attr->children->content;
62 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
64 const char *content_type = z_HTTP_header_lookup(hres->headers,
68 if (!yaz_strcmp_del("text/xml", content_type, "; "))
70 if (!yaz_strcmp_del("application/xml", content_type, "; "))
77 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
78 * parameters. Added by SH.
80 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
81 char *username, char *password, ODR decode)
83 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
86 sr->username = username;
88 sr->password = password;
94 char ubuf[256] = "", pbuf[256] = "", *p;
95 if (strncmp(basic, "Basic ", 6))
99 if (!len || len > 256)
101 yaz_base64decode(basic, out);
102 /* Format of out should be username:password at this point */
104 if ((p = strchr(ubuf, ':')))
111 sr->username = odr_strdup(decode, ubuf);
113 sr->password = odr_strdup(decode, pbuf);
117 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
118 const char *uri, const char *message,
121 d->uri = odr_strdup(o, uri);
123 d->message = odr_strdup(o, message);
127 d->details = odr_strdup(o, details);
132 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
133 int code, const char *details)
137 sprintf(uri, "info:srw/diagnostic/1/%d", code);
138 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
141 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
142 int *num, const char *uri,
143 const char *message, const char *details)
145 Z_SRW_diagnostic *d_new;
146 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
148 memcpy(d_new, *d, *num *sizeof(**d));
151 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
155 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
156 int *num, int code, const char *addinfo)
160 sprintf(uri, "info:srw/diagnostic/1/%d", code);
161 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
165 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
166 int *num, int code, const char *addinfo)
170 sprintf(uri, "info:srw/diagnostic/12/%d", code);
171 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
175 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
176 int code, const char *details)
178 const char *message = yaz_diag_srw_str(code);
181 len += strlen(message);
183 len += strlen(details);
185 record->recordData_buf = (char *) odr_malloc(o, len);
187 sprintf(record->recordData_buf, "<diagnostic "
188 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
189 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
191 sprintf(record->recordData_buf + strlen(record->recordData_buf),
192 " <details>%s</details>\n", details);
194 sprintf(record->recordData_buf + strlen(record->recordData_buf),
195 " <message>%s</message>\n", message);
196 sprintf(record->recordData_buf + strlen(record->recordData_buf),
198 record->recordData_len = strlen(record->recordData_buf);
199 record->recordPosition = odr_intdup(o, pos);
200 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
203 static void grab_charset(ODR o, const char *content_type, char **charset)
207 const char *charset_p = 0;
208 if (content_type && (charset_p = strstr(content_type, "; charset=")))
212 charset_p += 10; /* skip ; charset= */
213 if (charset_p[i] == '"' || charset_p[i] == '\'')
214 sep = charset_p[i++];
215 *charset = odr_strdup(o, charset_p);
216 while (charset_p[i] && charset_p[i] != sep)
218 if (!sep && strchr("; \n\r", charset_p[i]))
220 if (charset_p[i] == '\\' && charset_p[i+1])
222 (*charset)[j++] = charset_p[i++];
224 (*charset)[j] = '\0';
229 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
230 Z_SOAP **soap_package, ODR decode, char **charset)
232 if (!strcmp(hreq->method, "POST"))
234 const char *content_type = z_HTTP_header_lookup(hreq->headers,
237 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
238 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
239 !yaz_strcmp_del("text/plain", content_type, "; ")))
241 char *db = "Default";
242 const char *p0 = hreq->path, *p1;
245 static Z_SOAP_Handler soap_handlers[5] = {
247 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
248 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
249 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
250 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
257 p1 = strchr(p0, '?');
259 p1 = p0 + strlen(p0);
261 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
263 ret = z_soap_codec(decode, soap_package,
264 &hreq->content_buf, &hreq->content_len,
266 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
268 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
269 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
271 /* last entry in handlers - SRU 2.0 - is turned into
272 offset 0.. due to other pieces relying on it */
273 if ((*soap_package)->u.generic->no == 3)
274 (*soap_package)->u.generic->no = 0;
275 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
276 (*srw_pdu)->u.request->database == 0)
277 (*srw_pdu)->u.request->database = db;
279 if ((*srw_pdu)->which == Z_SRW_explain_request &&
280 (*srw_pdu)->u.explain_request->database == 0)
281 (*srw_pdu)->u.explain_request->database = db;
283 if ((*srw_pdu)->which == Z_SRW_scan_request &&
284 (*srw_pdu)->u.scan_request->database == 0)
285 (*srw_pdu)->u.scan_request->database = db;
287 if ((*srw_pdu)->which == Z_SRW_update_request &&
288 (*srw_pdu)->u.update_request->database == 0)
289 (*srw_pdu)->u.update_request->database = db;
300 static int yaz_sru_decode_integer(ODR odr, const char *pname,
301 const char *valstr, Odr_int **valp,
302 Z_SRW_diagnostic **diag, int *num_diag,
308 if (sscanf(valstr, "%d", &ival) != 1)
310 yaz_add_srw_diagnostic(odr, diag, num_diag,
311 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
314 if (min_value >= 0 && ival < min_value)
316 yaz_add_srw_diagnostic(odr, diag, num_diag,
317 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
320 *valp = odr_intdup(odr, ival);
326 http://www.loc.gov/z3950/agency/zing/srw/service.html
328 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
329 Z_SOAP **soap_package, ODR decode, char **charset,
330 Z_SRW_diagnostic **diag, int *num_diag)
333 static Z_SOAP_Handler soap_handlers[2] = {
334 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
338 const char *content_type = z_HTTP_header_lookup(hreq->headers,
342 SRU GET: ignore content type.
343 SRU POST: we support "application/x-www-form-urlencoded";
344 not "multipart/form-data" .
346 if (!strcmp(hreq->method, "GET")
348 (!strcmp(hreq->method, "POST") && content_type &&
349 !yaz_strcmp_del("application/x-www-form-urlencoded",
350 content_type, "; ")))
352 char *db = "Default";
353 const char *p0 = hreq->path, *p1;
355 const char *operation = 0;
358 char *queryType = "cql";
362 char *stylesheet = 0;
363 char *scanClause = 0;
364 char *recordXPath = 0;
365 char *recordSchema = 0;
366 char *recordXMLEscaping = 0;
367 char *recordPacking = 0;
368 char *maximumRecords = 0;
369 char *startRecord = 0;
370 char *maximumTerms = 0;
371 char *responsePosition = 0;
372 const char *facetLimit = 0;
373 const char *facetStart = 0;
374 const char *facetSort = 0;
375 Z_SRW_extra_arg *extra_args = 0;
380 grab_charset(decode, content_type, charset);
381 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
386 p1 = strchr(p0, '?');
388 p1 = p0 + strlen(p0);
390 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
391 if (!strcmp(hreq->method, "POST"))
392 p1 = hreq->content_buf;
393 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
398 for (i = 0; uri_name[i]; i++)
400 char *n = uri_name[i];
401 char *v = uri_val[i];
402 if (!strcmp(n, "query"))
404 else if (!strcmp(n, "x-pquery"))
409 else if (!strcmp(n, "queryType"))
411 else if (!strcmp(n, "x-username"))
413 else if (!strcmp(n, "x-password"))
415 else if (!strcmp(n, "operation"))
417 else if (!strcmp(n, "stylesheet"))
419 else if (!strcmp(n, "sortKeys"))
421 else if (!strcmp(n, "recordXPath"))
423 else if (!strcmp(n, "recordSchema"))
425 else if (!strcmp(n, "recordPacking"))
427 else if (!strcmp(n, "recordXMLEscaping"))
428 recordXMLEscaping = v;
429 else if (!strcmp(n, "version"))
431 else if (!strcmp(n, "scanClause"))
433 else if (!strcmp(n, "x-pScanClause"))
438 else if (!strcmp(n, "maximumRecords"))
440 else if (!strcmp(n, "startRecord"))
442 else if (!strcmp(n, "maximumTerms"))
444 else if (!strcmp(n, "responsePosition"))
445 responsePosition = v;
446 else if (!strcmp(n, "facetLimit"))
448 else if (!strcmp(n, "facetStart"))
450 else if (!strcmp(n, "facetSort"))
452 else if (!strcmp(n, "extraRequestData"))
453 ; /* ignoring extraRequestData */
454 else if (n[0] == 'x' && n[1] == '-')
456 Z_SRW_extra_arg **l = &extra_args;
459 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
460 (*l)->name = odr_strdup(decode, n);
461 (*l)->value = odr_strdup(decode, v);
467 yaz_add_srw_diagnostic(decode, diag, num_diag,
468 YAZ_SRW_UNSUPP_PARAMETER, n);
475 operation = "searchRetrieve";
479 version = yaz_negotiate_sru_version(version);
482 { /* negotiation failed. */
483 yaz_add_srw_diagnostic(decode, diag, num_diag,
484 YAZ_SRW_UNSUPP_VERSION, "2.0");
490 yaz_add_srw_diagnostic(
491 decode, diag, num_diag,
492 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
493 operation = "explain";
495 if (strcmp(version, "2.0"))
497 if (recordXMLEscaping)
499 yaz_add_srw_diagnostic(decode, diag, num_diag,
500 YAZ_SRW_UNSUPP_PARAMETER,
501 "recordXMLEscaping");
504 recordXMLEscaping = recordPacking;
505 recordPacking = "packed";
507 if (!recordXMLEscaping)
508 recordXMLEscaping = "xml";
509 if (!strcmp(operation, "searchRetrieve"))
511 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
513 sr->srw_version = version;
514 sr->extra_args = extra_args;
516 yaz_srw_decodeauth(sr, hreq, username, password, decode);
518 sr->u.request->queryType = queryType;
519 sr->u.request->query = query;
522 yaz_add_srw_diagnostic(
523 decode, diag, num_diag,
524 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
528 sr->u.request->sort_type = Z_SRW_sort_type_sort;
529 sr->u.request->sort.sortKeys = sortKeys;
531 sr->u.request->recordXPath = recordXPath;
532 sr->u.request->recordSchema = recordSchema;
533 sr->u.request->recordPacking = recordXMLEscaping;
534 sr->u.request->packing = recordPacking;
535 sr->u.request->stylesheet = stylesheet;
536 yaz_sru_facet_request(decode , &sr->u.request->facetList,
537 &facetLimit, &facetStart, &facetSort);
539 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
540 &sr->u.request->maximumRecords,
543 yaz_sru_decode_integer(decode, "startRecord", startRecord,
544 &sr->u.request->startRecord,
547 sr->u.request->database = db;
549 (*soap_package) = (Z_SOAP *)
550 odr_malloc(decode, sizeof(**soap_package));
551 (*soap_package)->which = Z_SOAP_generic;
553 (*soap_package)->u.generic = (Z_SOAP_Generic *)
554 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
556 (*soap_package)->u.generic->p = sr;
557 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
558 (*soap_package)->u.generic->no = 0;
560 (*soap_package)->ns = "SRU";
564 else if (!strcmp(operation, "explain"))
566 /* Transfer SRU explain parameters to common struct */
567 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
568 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
570 sr->srw_version = version;
571 sr->extra_args = extra_args;
572 yaz_srw_decodeauth(sr, hreq, username, password, decode);
574 sr->u.explain_request->recordPacking = recordXMLEscaping;
575 sr->u.explain_request->packing = recordPacking;
576 sr->u.explain_request->database = db;
578 sr->u.explain_request->stylesheet = stylesheet;
580 (*soap_package) = (Z_SOAP *)
581 odr_malloc(decode, sizeof(**soap_package));
582 (*soap_package)->which = Z_SOAP_generic;
584 (*soap_package)->u.generic = (Z_SOAP_Generic *)
585 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
587 (*soap_package)->u.generic->p = sr;
588 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
589 (*soap_package)->u.generic->no = 0;
591 (*soap_package)->ns = "SRU";
595 else if (!strcmp(operation, "scan"))
597 /* Transfer SRU scan parameters to common struct */
598 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
599 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
601 sr->srw_version = version;
602 sr->extra_args = extra_args;
604 yaz_srw_decodeauth(sr, hreq, username, password, decode);
606 sr->u.scan_request->queryType = queryType;
607 sr->u.scan_request->scanClause = scanClause;
610 yaz_add_srw_diagnostic(
611 decode, diag, num_diag,
612 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
613 sr->u.scan_request->database = db;
615 yaz_sru_decode_integer(decode, "maximumTerms",
617 &sr->u.scan_request->maximumTerms,
620 yaz_sru_decode_integer(decode, "responsePosition",
622 &sr->u.scan_request->responsePosition,
625 sr->u.scan_request->stylesheet = stylesheet;
627 (*soap_package) = (Z_SOAP *)
628 odr_malloc(decode, sizeof(**soap_package));
629 (*soap_package)->which = Z_SOAP_generic;
631 (*soap_package)->u.generic = (Z_SOAP_Generic *)
632 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
634 (*soap_package)->u.generic->p = sr;
635 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
636 (*soap_package)->u.generic->no = 0;
638 (*soap_package)->ns = "SRU";
644 /* unsupported operation ... */
645 /* Act as if we received a explain request and throw diagnostic. */
647 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
649 sr->srw_version = version;
651 sr->u.explain_request->recordPacking = recordPacking;
652 sr->u.explain_request->database = db;
654 sr->u.explain_request->stylesheet = stylesheet;
656 (*soap_package) = (Z_SOAP *)
657 odr_malloc(decode, sizeof(**soap_package));
658 (*soap_package)->which = Z_SOAP_generic;
660 (*soap_package)->u.generic = (Z_SOAP_Generic *)
661 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
663 (*soap_package)->u.generic->p = sr;
664 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
665 (*soap_package)->u.generic->no = 0;
667 (*soap_package)->ns = "SRU";
669 yaz_add_srw_diagnostic(decode, diag, num_diag,
670 YAZ_SRW_UNSUPP_OPERATION, operation);
680 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
682 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
683 odr_malloc(o, sizeof(*res));
685 res->extraRecordData_buf = 0;
686 res->extraRecordData_len = 0;
687 res->recordIdentifier = 0;
692 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
694 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
697 for (i = 0; i<n; i++)
699 res[i].recordSchema = 0;
700 res[i].recordPacking = Z_SRW_recordPacking_string;
701 res[i].recordData_buf = 0;
702 res[i].recordData_len = 0;
703 res[i].recordPosition = 0;
708 Z_SRW_record *yaz_srw_get_record(ODR o)
710 return yaz_srw_get_records(o, 1);
713 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
715 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
716 p->srw_version = odr_strdup(o, version);
720 p->extraResponseData_buf = 0;
721 p->extraResponseData_len = 0;
725 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
727 return yaz_srw_get_core_ver(o, "2.0");
730 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
732 return yaz_srw_get_pdu(o, which, "2.0");
735 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
737 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
742 case Z_SRW_searchRetrieve_request:
743 sr->u.request = (Z_SRW_searchRetrieveRequest *)
744 odr_malloc(o, sizeof(*sr->u.request));
745 sr->u.request->queryType = "cql";
746 sr->u.request->query = 0;
747 sr->u.request->sort_type = Z_SRW_sort_type_none;
748 sr->u.request->sort.none = 0;
749 sr->u.request->startRecord = 0;
750 sr->u.request->maximumRecords = 0;
751 sr->u.request->recordSchema = 0;
752 sr->u.request->recordPacking = 0;
753 sr->u.request->packing = 0;
754 sr->u.request->recordXPath = 0;
755 sr->u.request->database = 0;
756 sr->u.request->resultSetTTL = 0;
757 sr->u.request->stylesheet = 0;
758 sr->u.request->facetList = 0;
760 case Z_SRW_searchRetrieve_response:
761 sr->u.response = (Z_SRW_searchRetrieveResponse *)
762 odr_malloc(o, sizeof(*sr->u.response));
763 sr->u.response->numberOfRecords = 0;
764 sr->u.response->resultCountPrecision = 0;
765 sr->u.response->resultSetId = 0;
766 sr->u.response->resultSetIdleTime = 0;
767 sr->u.response->records = 0;
768 sr->u.response->num_records = 0;
769 sr->u.response->diagnostics = 0;
770 sr->u.response->num_diagnostics = 0;
771 sr->u.response->nextRecordPosition = 0;
772 sr->u.response->extra_records = 0;
773 sr->u.response->facetList = 0;
774 sr->u.response->suggestions = 0;
776 case Z_SRW_explain_request:
777 sr->u.explain_request = (Z_SRW_explainRequest *)
778 odr_malloc(o, sizeof(*sr->u.explain_request));
779 sr->u.explain_request->recordPacking = 0;
780 sr->u.explain_request->packing = 0;
781 sr->u.explain_request->database = 0;
782 sr->u.explain_request->stylesheet = 0;
784 case Z_SRW_explain_response:
785 sr->u.explain_response = (Z_SRW_explainResponse *)
786 odr_malloc(o, sizeof(*sr->u.explain_response));
787 sr->u.explain_response->record.recordData_buf = 0;
788 sr->u.explain_response->record.recordData_len = 0;
789 sr->u.explain_response->record.recordSchema = 0;
790 sr->u.explain_response->record.recordPosition = 0;
791 sr->u.explain_response->record.recordPacking =
792 Z_SRW_recordPacking_string;
793 sr->u.explain_response->diagnostics = 0;
794 sr->u.explain_response->num_diagnostics = 0;
795 sr->u.explain_response->extra_record = 0;
797 case Z_SRW_scan_request:
798 sr->u.scan_request = (Z_SRW_scanRequest *)
799 odr_malloc(o, sizeof(*sr->u.scan_request));
800 sr->u.scan_request->database = 0;
801 sr->u.scan_request->stylesheet = 0;
802 sr->u.scan_request->maximumTerms = 0;
803 sr->u.scan_request->responsePosition = 0;
804 sr->u.scan_request->queryType = "cql";
805 sr->u.scan_request->scanClause = 0;
807 case Z_SRW_scan_response:
808 sr->u.scan_response = (Z_SRW_scanResponse *)
809 odr_malloc(o, sizeof(*sr->u.scan_response));
810 sr->u.scan_response->terms = 0;
811 sr->u.scan_response->num_terms = 0;
812 sr->u.scan_response->diagnostics = 0;
813 sr->u.scan_response->num_diagnostics = 0;
815 case Z_SRW_update_request:
816 sr->u.update_request = (Z_SRW_updateRequest *)
817 odr_malloc(o, sizeof(*sr->u.update_request));
818 sr->u.update_request->database = 0;
819 sr->u.update_request->stylesheet = 0;
820 sr->u.update_request->record = 0;
821 sr->u.update_request->recordId = 0;
822 sr->u.update_request->recordVersions = 0;
823 sr->u.update_request->num_recordVersions = 0;
824 sr->u.update_request->extra_record = 0;
825 sr->u.update_request->extraRequestData_buf = 0;
826 sr->u.update_request->extraRequestData_len = 0;
827 sr->u.request->database = 0;
829 case Z_SRW_update_response:
830 sr->u.update_response = (Z_SRW_updateResponse *)
831 odr_malloc(o, sizeof(*sr->u.update_response));
832 sr->u.update_response->operationStatus = 0;
833 sr->u.update_response->recordId = 0;
834 sr->u.update_response->recordVersions = 0;
835 sr->u.update_response->num_recordVersions = 0;
836 sr->u.update_response->record = 0;
837 sr->u.update_response->extra_record = 0;
838 sr->u.update_response->extraResponseData_buf = 0;
839 sr->u.update_response->extraResponseData_len = 0;
840 sr->u.update_response->diagnostics = 0;
841 sr->u.update_response->num_diagnostics = 0;
846 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
847 char *a_name, Odr_int *val)
852 value[*i] = (char *) odr_malloc(o, 40);
853 sprintf(value[*i], ODR_INT_PRINTF, *val);
858 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
859 char *a_name, char *val)
869 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
870 char **name, char **value, int max_names)
872 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
875 yaz_add_name_value_str(encode, name, value, &i, "version",
876 srw_pdu->srw_version);
877 name[i] = "operation";
878 switch (srw_pdu->which)
880 case Z_SRW_searchRetrieve_request:
881 value[i++] = "searchRetrieve";
882 queryType = srw_pdu->u.request->queryType;
885 if (queryType && strcmp(queryType, "cql"))
886 yaz_add_name_value_str(encode, name, value, &i, "queryType",
888 yaz_add_name_value_str(encode, name, value, &i, "query",
889 srw_pdu->u.request->query);
893 if (!strcmp(queryType, "cql"))
895 yaz_add_name_value_str(encode, name, value, &i, "query",
896 srw_pdu->u.request->query);
898 else if (!strcmp(queryType, "pqf"))
900 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
901 srw_pdu->u.request->query);
903 else if (!strcmp(queryType, "xcql"))
905 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
906 srw_pdu->u.request->query);
909 switch (srw_pdu->u.request->sort_type)
911 case Z_SRW_sort_type_none:
913 case Z_SRW_sort_type_sort:
914 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
915 srw_pdu->u.request->sort.sortKeys);
918 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
919 srw_pdu->u.request->startRecord);
920 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
921 srw_pdu->u.request->maximumRecords);
922 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
923 srw_pdu->u.request->recordSchema);
926 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
927 srw_pdu->u.request->recordPacking);
928 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
929 srw_pdu->u.request->packing);
932 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
933 srw_pdu->u.request->recordPacking);
934 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
935 srw_pdu->u.request->recordXPath);
936 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
937 srw_pdu->u.request->stylesheet);
938 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
939 srw_pdu->u.request->resultSetTTL);
941 const char *facetLimit = 0;
942 const char *facetStart = 0;
943 const char *facetSort = 0;
944 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
945 &facetLimit, &facetStart, &facetSort);
946 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
947 (char *) facetLimit);
948 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
949 (char *) facetStart);
950 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
954 case Z_SRW_explain_request:
955 value[i++] = "explain";
959 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
960 srw_pdu->u.explain_request->recordPacking);
961 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
962 srw_pdu->u.explain_request->packing);
965 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
966 srw_pdu->u.explain_request->recordPacking);
967 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
968 srw_pdu->u.explain_request->stylesheet);
970 case Z_SRW_scan_request:
972 queryType = srw_pdu->u.scan_request->queryType;
975 if (queryType && strcmp(queryType, "cql"))
976 yaz_add_name_value_str(encode, name, value, &i, "queryType",
978 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
979 srw_pdu->u.scan_request->scanClause);
983 if (!queryType || !strcmp(queryType, "cql"))
984 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
985 srw_pdu->u.scan_request->scanClause);
986 else if (!strcmp(queryType, "pqf"))
987 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
988 srw_pdu->u.scan_request->scanClause);
989 else if (!strcmp(queryType, "xcql"))
990 yaz_add_name_value_str(encode, name, value, &i,
992 srw_pdu->u.scan_request->scanClause);
994 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
995 srw_pdu->u.scan_request->responsePosition);
996 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
997 srw_pdu->u.scan_request->maximumTerms);
998 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
999 srw_pdu->u.scan_request->stylesheet);
1001 case Z_SRW_update_request:
1002 value[i++] = "update";
1007 if (srw_pdu->extra_args)
1009 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1010 for (; ea && i < max_names-1; ea = ea->next)
1013 value[i] = ea->value;
1022 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1023 ODR encode, const char *charset)
1025 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1030 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1031 srw_pdu->username, srw_pdu->password);
1032 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1034 yaz_array_to_uri(&uri_args, encode, name, value);
1036 hreq->method = "GET";
1038 cp = strchr(hreq->path, '#');
1043 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1045 sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1049 z_HTTP_header_add_content_type(encode, &hreq->headers,
1050 "text/xml", charset);
1054 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1055 ODR encode, const char *charset)
1057 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1060 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1061 srw_pdu->username, srw_pdu->password);
1062 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1065 yaz_array_to_uri(&uri_args, encode, name, value);
1067 hreq->method = "POST";
1069 hreq->content_buf = uri_args;
1070 hreq->content_len = strlen(uri_args);
1072 z_HTTP_header_add_content_type(encode, &hreq->headers,
1073 "application/x-www-form-urlencoded",
1078 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1079 ODR odr, const char *charset)
1081 Z_SOAP_Handler handlers[3] = {
1083 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1084 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1088 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1090 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1091 srw_pdu->username, srw_pdu->password);
1092 z_HTTP_header_add_content_type(odr,
1094 "text/xml", 0 /* no charset in MIME */);
1096 z_HTTP_header_add(odr, &hreq->headers,
1097 "SOAPAction", "\"\"");
1098 p->which = Z_SOAP_generic;
1099 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1100 p->u.generic->no = 0;
1101 p->u.generic->ns = 0;
1102 p->u.generic->p = srw_pdu;
1103 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1106 if (srw_pdu->which == Z_SRW_update_request ||
1107 srw_pdu->which == Z_SRW_update_response)
1108 p->u.generic->no = 1; /* second handler */
1110 return z_soap_codec_enc(odr, &p,
1112 &hreq->content_len, handlers,
1116 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1118 Z_SRW_recordVersion *ver
1119 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1121 for (i = 0; i < num; ++i)
1123 ver[i].versionType = 0;
1124 ver[i].versionValue = 0;
1129 const char *yaz_srw_pack_to_str(int pack)
1133 case Z_SRW_recordPacking_string:
1135 case Z_SRW_recordPacking_XML:
1137 case Z_SRW_recordPacking_URL:
1143 int yaz_srw_str_to_pack(const char *str)
1145 if (!yaz_matchstr(str, "string"))
1146 return Z_SRW_recordPacking_string;
1147 if (!yaz_matchstr(str, "xml"))
1148 return Z_SRW_recordPacking_XML;
1149 if (!yaz_matchstr(str, "url"))
1150 return Z_SRW_recordPacking_URL;
1154 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1160 Z_SRW_extra_arg **ea = &sr->extra_args;
1161 yaz_uri_to_array(extra_args, odr, &name, &val);
1163 /** append rather than override */
1168 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1169 (*ea)->name = *name;
1170 (*ea)->value = *val;
1183 * c-file-style: "Stroustrup"
1184 * indent-tabs-mode: nil
1186 * vim: shiftwidth=4 tabstop=8 expandtab