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_uri_val_int(const char *path, const char *name, ODR o, Odr_int **intp)
146 const char *v = yaz_uri_val(path, name, o);
148 *intp = odr_intdup(o, atoi(v));
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 while (i < 20 && charset_p[i] &&
247 !strchr("; \n\r", charset_p[i]))
249 *charset = odr_strdupn(o, charset_p, i);
254 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
255 Z_SOAP **soap_package, ODR decode, char **charset)
257 if (!strcmp(hreq->method, "POST"))
259 const char *content_type = z_HTTP_header_lookup(hreq->headers,
262 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
263 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
264 !yaz_strcmp_del("text/plain", content_type, "; ")))
266 char *db = "Default";
267 const char *p0 = hreq->path, *p1;
270 static Z_SOAP_Handler soap_handlers[5] = {
272 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
273 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
274 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
275 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
282 p1 = strchr(p0, '?');
284 p1 = p0 + strlen(p0);
286 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
287 grab_charset(decode, content_type, charset);
289 ret = z_soap_codec(decode, soap_package,
290 &hreq->content_buf, &hreq->content_len,
292 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
294 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
295 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
297 /* last entry in handlers - SRU 2.0 - is turned into
298 offset 0.. due to other pieces relying on it */
299 if ((*soap_package)->u.generic->no == 3)
300 (*soap_package)->u.generic->no = 0;
301 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
302 (*srw_pdu)->u.request->database == 0)
303 (*srw_pdu)->u.request->database = db;
305 if ((*srw_pdu)->which == Z_SRW_explain_request &&
306 (*srw_pdu)->u.explain_request->database == 0)
307 (*srw_pdu)->u.explain_request->database = db;
309 if ((*srw_pdu)->which == Z_SRW_scan_request &&
310 (*srw_pdu)->u.scan_request->database == 0)
311 (*srw_pdu)->u.scan_request->database = db;
313 if ((*srw_pdu)->which == Z_SRW_update_request &&
314 (*srw_pdu)->u.update_request->database == 0)
315 (*srw_pdu)->u.update_request->database = db;
326 static int yaz_sru_decode_integer(ODR odr, const char *pname,
327 const char *valstr, Odr_int **valp,
328 Z_SRW_diagnostic **diag, int *num_diag,
334 if (sscanf(valstr, "%d", &ival) != 1)
336 yaz_add_srw_diagnostic(odr, diag, num_diag,
337 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
340 if (min_value >= 0 && ival < min_value)
342 yaz_add_srw_diagnostic(odr, diag, num_diag,
343 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
346 *valp = odr_intdup(odr, ival);
352 http://www.loc.gov/z3950/agency/zing/srw/service.html
354 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
355 Z_SOAP **soap_package, ODR decode, char **charset,
356 Z_SRW_diagnostic **diag, int *num_diag)
359 static Z_SOAP_Handler soap_handlers[2] = {
360 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
364 const char *content_type = z_HTTP_header_lookup(hreq->headers,
368 SRU GET: ignore content type.
369 SRU POST: we support "application/x-www-form-urlencoded";
370 not "multipart/form-data" .
372 if (!strcmp(hreq->method, "GET")
374 (!strcmp(hreq->method, "POST") && content_type &&
375 !yaz_strcmp_del("application/x-www-form-urlencoded",
376 content_type, "; ")))
378 char *db = "Default";
379 const char *p0 = hreq->path, *p1;
381 const char *operation = 0;
384 char *queryType = "cql";
388 char *stylesheet = 0;
389 char *scanClause = 0;
390 char *recordXPath = 0;
391 char *recordSchema = 0;
392 char *recordXMLEscaping = 0;
393 char *recordPacking = 0;
394 char *maximumRecords = 0;
395 char *startRecord = 0;
396 char *maximumTerms = 0;
397 char *responsePosition = 0;
398 const char *facetLimit = 0;
399 const char *facetStart = 0;
400 const char *facetSort = 0;
401 Z_SRW_extra_arg *extra_args = 0;
406 grab_charset(decode, content_type, charset);
407 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
412 p1 = strchr(p0, '?');
414 p1 = p0 + strlen(p0);
416 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
417 if (!strcmp(hreq->method, "POST"))
418 p1 = hreq->content_buf;
419 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
424 for (i = 0; uri_name[i]; i++)
426 char *n = uri_name[i];
427 char *v = uri_val[i];
428 if (!strcmp(n, "query"))
430 else if (!strcmp(n, "x-pquery"))
435 else if (!strcmp(n, "queryType"))
437 else if (!strcmp(n, "x-username"))
439 else if (!strcmp(n, "x-password"))
441 else if (!strcmp(n, "operation"))
443 else if (!strcmp(n, "stylesheet"))
445 else if (!strcmp(n, "sortKeys"))
447 else if (!strcmp(n, "recordXPath"))
449 else if (!strcmp(n, "recordSchema"))
451 else if (!strcmp(n, "recordPacking"))
453 else if (!strcmp(n, "recordXMLEscaping"))
454 recordXMLEscaping = v;
455 else if (!strcmp(n, "version"))
457 else if (!strcmp(n, "scanClause"))
459 else if (!strcmp(n, "x-pScanClause"))
464 else if (!strcmp(n, "maximumRecords"))
466 else if (!strcmp(n, "startRecord"))
468 else if (!strcmp(n, "maximumTerms"))
470 else if (!strcmp(n, "responsePosition"))
471 responsePosition = v;
472 else if (!strcmp(n, "facetLimit"))
474 else if (!strcmp(n, "facetStart"))
476 else if (!strcmp(n, "facetSort"))
478 else if (!strcmp(n, "extraRequestData"))
479 ; /* ignoring extraRequestData */
480 else if (n[0] == 'x' && n[1] == '-')
482 Z_SRW_extra_arg **l = &extra_args;
485 *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
486 (*l)->name = odr_strdup(decode, n);
487 (*l)->value = odr_strdup(decode, v);
493 yaz_add_srw_diagnostic(decode, diag, num_diag,
494 YAZ_SRW_UNSUPP_PARAMETER, n);
501 operation = "searchRetrieve";
505 version = yaz_negotiate_sru_version(version);
508 { /* negotiation failed. */
509 yaz_add_srw_diagnostic(decode, diag, num_diag,
510 YAZ_SRW_UNSUPP_VERSION, "2.0");
516 yaz_add_srw_diagnostic(
517 decode, diag, num_diag,
518 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
519 operation = "explain";
521 if (strcmp(version, "2.0"))
523 if (recordXMLEscaping)
525 yaz_add_srw_diagnostic(decode, diag, num_diag,
526 YAZ_SRW_UNSUPP_PARAMETER,
527 "recordXMLEscaping");
530 recordXMLEscaping = recordPacking;
531 recordPacking = "packed";
533 if (!recordXMLEscaping)
534 recordXMLEscaping = "xml";
535 if (!strcmp(operation, "searchRetrieve"))
537 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
539 sr->srw_version = version;
540 sr->extra_args = extra_args;
542 yaz_srw_decodeauth(sr, hreq, username, password, decode);
544 sr->u.request->queryType = queryType;
545 sr->u.request->query = query;
548 yaz_add_srw_diagnostic(
549 decode, diag, num_diag,
550 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
554 sr->u.request->sort_type = Z_SRW_sort_type_sort;
555 sr->u.request->sort.sortKeys = sortKeys;
557 sr->u.request->recordXPath = recordXPath;
558 sr->u.request->recordSchema = recordSchema;
559 sr->u.request->recordPacking = recordXMLEscaping;
560 sr->u.request->packing = recordPacking;
561 sr->u.request->stylesheet = stylesheet;
562 yaz_sru_facet_request(decode , &sr->u.request->facetList,
563 &facetLimit, &facetStart, &facetSort);
565 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
566 &sr->u.request->maximumRecords,
569 yaz_sru_decode_integer(decode, "startRecord", startRecord,
570 &sr->u.request->startRecord,
573 sr->u.request->database = db;
575 (*soap_package) = (Z_SOAP *)
576 odr_malloc(decode, sizeof(**soap_package));
577 (*soap_package)->which = Z_SOAP_generic;
579 (*soap_package)->u.generic = (Z_SOAP_Generic *)
580 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
582 (*soap_package)->u.generic->p = sr;
583 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
584 (*soap_package)->u.generic->no = 0;
586 (*soap_package)->ns = "SRU";
590 else if (!strcmp(operation, "explain"))
592 /* Transfer SRU explain parameters to common struct */
593 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
594 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
596 sr->srw_version = version;
597 sr->extra_args = extra_args;
598 yaz_srw_decodeauth(sr, hreq, username, password, decode);
600 sr->u.explain_request->recordPacking = recordXMLEscaping;
601 sr->u.explain_request->packing = recordPacking;
602 sr->u.explain_request->database = db;
604 sr->u.explain_request->stylesheet = stylesheet;
606 (*soap_package) = (Z_SOAP *)
607 odr_malloc(decode, sizeof(**soap_package));
608 (*soap_package)->which = Z_SOAP_generic;
610 (*soap_package)->u.generic = (Z_SOAP_Generic *)
611 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
613 (*soap_package)->u.generic->p = sr;
614 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
615 (*soap_package)->u.generic->no = 0;
617 (*soap_package)->ns = "SRU";
621 else if (!strcmp(operation, "scan"))
623 /* Transfer SRU scan parameters to common struct */
624 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
625 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
627 sr->srw_version = version;
628 sr->extra_args = extra_args;
630 yaz_srw_decodeauth(sr, hreq, username, password, decode);
632 sr->u.scan_request->queryType = queryType;
633 sr->u.scan_request->scanClause = scanClause;
636 yaz_add_srw_diagnostic(
637 decode, diag, num_diag,
638 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
639 sr->u.scan_request->database = db;
641 yaz_sru_decode_integer(decode, "maximumTerms",
643 &sr->u.scan_request->maximumTerms,
646 yaz_sru_decode_integer(decode, "responsePosition",
648 &sr->u.scan_request->responsePosition,
651 sr->u.scan_request->stylesheet = stylesheet;
653 (*soap_package) = (Z_SOAP *)
654 odr_malloc(decode, sizeof(**soap_package));
655 (*soap_package)->which = Z_SOAP_generic;
657 (*soap_package)->u.generic = (Z_SOAP_Generic *)
658 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
660 (*soap_package)->u.generic->p = sr;
661 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
662 (*soap_package)->u.generic->no = 0;
664 (*soap_package)->ns = "SRU";
670 /* unsupported operation ... */
671 /* Act as if we received a explain request and throw diagnostic. */
673 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
675 sr->srw_version = version;
677 sr->u.explain_request->recordPacking = recordPacking;
678 sr->u.explain_request->database = db;
680 sr->u.explain_request->stylesheet = stylesheet;
682 (*soap_package) = (Z_SOAP *)
683 odr_malloc(decode, sizeof(**soap_package));
684 (*soap_package)->which = Z_SOAP_generic;
686 (*soap_package)->u.generic = (Z_SOAP_Generic *)
687 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
689 (*soap_package)->u.generic->p = sr;
690 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
691 (*soap_package)->u.generic->no = 0;
693 (*soap_package)->ns = "SRU";
695 yaz_add_srw_diagnostic(decode, diag, num_diag,
696 YAZ_SRW_UNSUPP_OPERATION, operation);
706 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
708 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
709 odr_malloc(o, sizeof(*res));
711 res->extraRecordData_buf = 0;
712 res->extraRecordData_len = 0;
713 res->recordIdentifier = 0;
718 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
720 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
723 for (i = 0; i<n; i++)
725 res[i].recordSchema = 0;
726 res[i].recordPacking = Z_SRW_recordPacking_string;
727 res[i].recordData_buf = 0;
728 res[i].recordData_len = 0;
729 res[i].recordPosition = 0;
734 Z_SRW_record *yaz_srw_get_record(ODR o)
736 return yaz_srw_get_records(o, 1);
739 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
741 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
742 p->srw_version = odr_strdup(o, version);
746 p->extraResponseData_buf = 0;
747 p->extraResponseData_len = 0;
751 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
753 return yaz_srw_get_core_ver(o, "2.0");
756 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
758 return yaz_srw_get_pdu(o, which, "2.0");
761 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
763 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
768 case Z_SRW_searchRetrieve_request:
769 sr->u.request = (Z_SRW_searchRetrieveRequest *)
770 odr_malloc(o, sizeof(*sr->u.request));
771 sr->u.request->queryType = "cql";
772 sr->u.request->query = 0;
773 sr->u.request->sort_type = Z_SRW_sort_type_none;
774 sr->u.request->sort.none = 0;
775 sr->u.request->startRecord = 0;
776 sr->u.request->maximumRecords = 0;
777 sr->u.request->recordSchema = 0;
778 sr->u.request->recordPacking = 0;
779 sr->u.request->packing = 0;
780 sr->u.request->recordXPath = 0;
781 sr->u.request->database = 0;
782 sr->u.request->resultSetTTL = 0;
783 sr->u.request->stylesheet = 0;
784 sr->u.request->facetList = 0;
786 case Z_SRW_searchRetrieve_response:
787 sr->u.response = (Z_SRW_searchRetrieveResponse *)
788 odr_malloc(o, sizeof(*sr->u.response));
789 sr->u.response->numberOfRecords = 0;
790 sr->u.response->resultCountPrecision = 0;
791 sr->u.response->resultSetId = 0;
792 sr->u.response->resultSetIdleTime = 0;
793 sr->u.response->records = 0;
794 sr->u.response->num_records = 0;
795 sr->u.response->diagnostics = 0;
796 sr->u.response->num_diagnostics = 0;
797 sr->u.response->nextRecordPosition = 0;
798 sr->u.response->extra_records = 0;
799 sr->u.response->facetList = 0;
800 sr->u.response->suggestions = 0;
802 case Z_SRW_explain_request:
803 sr->u.explain_request = (Z_SRW_explainRequest *)
804 odr_malloc(o, sizeof(*sr->u.explain_request));
805 sr->u.explain_request->recordPacking = 0;
806 sr->u.explain_request->packing = 0;
807 sr->u.explain_request->database = 0;
808 sr->u.explain_request->stylesheet = 0;
810 case Z_SRW_explain_response:
811 sr->u.explain_response = (Z_SRW_explainResponse *)
812 odr_malloc(o, sizeof(*sr->u.explain_response));
813 sr->u.explain_response->record.recordData_buf = 0;
814 sr->u.explain_response->record.recordData_len = 0;
815 sr->u.explain_response->record.recordSchema = 0;
816 sr->u.explain_response->record.recordPosition = 0;
817 sr->u.explain_response->record.recordPacking =
818 Z_SRW_recordPacking_string;
819 sr->u.explain_response->diagnostics = 0;
820 sr->u.explain_response->num_diagnostics = 0;
821 sr->u.explain_response->extra_record = 0;
823 case Z_SRW_scan_request:
824 sr->u.scan_request = (Z_SRW_scanRequest *)
825 odr_malloc(o, sizeof(*sr->u.scan_request));
826 sr->u.scan_request->database = 0;
827 sr->u.scan_request->stylesheet = 0;
828 sr->u.scan_request->maximumTerms = 0;
829 sr->u.scan_request->responsePosition = 0;
830 sr->u.scan_request->queryType = "cql";
831 sr->u.scan_request->scanClause = 0;
833 case Z_SRW_scan_response:
834 sr->u.scan_response = (Z_SRW_scanResponse *)
835 odr_malloc(o, sizeof(*sr->u.scan_response));
836 sr->u.scan_response->terms = 0;
837 sr->u.scan_response->num_terms = 0;
838 sr->u.scan_response->diagnostics = 0;
839 sr->u.scan_response->num_diagnostics = 0;
841 case Z_SRW_update_request:
842 sr->u.update_request = (Z_SRW_updateRequest *)
843 odr_malloc(o, sizeof(*sr->u.update_request));
844 sr->u.update_request->database = 0;
845 sr->u.update_request->stylesheet = 0;
846 sr->u.update_request->record = 0;
847 sr->u.update_request->recordId = 0;
848 sr->u.update_request->recordVersions = 0;
849 sr->u.update_request->num_recordVersions = 0;
850 sr->u.update_request->extra_record = 0;
851 sr->u.update_request->extraRequestData_buf = 0;
852 sr->u.update_request->extraRequestData_len = 0;
853 sr->u.request->database = 0;
855 case Z_SRW_update_response:
856 sr->u.update_response = (Z_SRW_updateResponse *)
857 odr_malloc(o, sizeof(*sr->u.update_response));
858 sr->u.update_response->operationStatus = 0;
859 sr->u.update_response->recordId = 0;
860 sr->u.update_response->recordVersions = 0;
861 sr->u.update_response->num_recordVersions = 0;
862 sr->u.update_response->record = 0;
863 sr->u.update_response->extra_record = 0;
864 sr->u.update_response->extraResponseData_buf = 0;
865 sr->u.update_response->extraResponseData_len = 0;
866 sr->u.update_response->diagnostics = 0;
867 sr->u.update_response->num_diagnostics = 0;
872 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
873 char *a_name, Odr_int *val)
878 value[*i] = (char *) odr_malloc(o, 40);
879 sprintf(value[*i], ODR_INT_PRINTF, *val);
884 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
885 char *a_name, char *val)
895 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
896 char **name, char **value, int max_names)
898 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
901 yaz_add_name_value_str(encode, name, value, &i, "version",
902 srw_pdu->srw_version);
903 name[i] = "operation";
904 switch (srw_pdu->which)
906 case Z_SRW_searchRetrieve_request:
907 value[i++] = "searchRetrieve";
908 queryType = srw_pdu->u.request->queryType;
911 if (queryType && strcmp(queryType, "cql"))
912 yaz_add_name_value_str(encode, name, value, &i, "queryType",
914 yaz_add_name_value_str(encode, name, value, &i, "query",
915 srw_pdu->u.request->query);
919 if (!strcmp(queryType, "cql"))
921 yaz_add_name_value_str(encode, name, value, &i, "query",
922 srw_pdu->u.request->query);
924 else if (!strcmp(queryType, "pqf"))
926 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
927 srw_pdu->u.request->query);
929 else if (!strcmp(queryType, "xcql"))
931 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
932 srw_pdu->u.request->query);
935 switch (srw_pdu->u.request->sort_type)
937 case Z_SRW_sort_type_none:
939 case Z_SRW_sort_type_sort:
940 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
941 srw_pdu->u.request->sort.sortKeys);
944 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
945 srw_pdu->u.request->startRecord);
946 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
947 srw_pdu->u.request->maximumRecords);
948 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
949 srw_pdu->u.request->recordSchema);
952 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
953 srw_pdu->u.request->recordPacking);
954 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
955 srw_pdu->u.request->packing);
958 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
959 srw_pdu->u.request->recordPacking);
960 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
961 srw_pdu->u.request->recordXPath);
962 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
963 srw_pdu->u.request->stylesheet);
964 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
965 srw_pdu->u.request->resultSetTTL);
967 const char *facetLimit = 0;
968 const char *facetStart = 0;
969 const char *facetSort = 0;
970 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
971 &facetLimit, &facetStart, &facetSort);
972 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
973 (char *) facetLimit);
974 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
975 (char *) facetStart);
976 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
980 case Z_SRW_explain_request:
981 value[i++] = "explain";
985 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
986 srw_pdu->u.explain_request->recordPacking);
987 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
988 srw_pdu->u.explain_request->packing);
991 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
992 srw_pdu->u.explain_request->recordPacking);
993 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
994 srw_pdu->u.explain_request->stylesheet);
996 case Z_SRW_scan_request:
998 queryType = srw_pdu->u.scan_request->queryType;
1001 if (queryType && strcmp(queryType, "cql"))
1002 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1004 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1005 srw_pdu->u.scan_request->scanClause);
1009 if (!queryType || !strcmp(queryType, "cql"))
1010 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1011 srw_pdu->u.scan_request->scanClause);
1012 else if (!strcmp(queryType, "pqf"))
1013 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1014 srw_pdu->u.scan_request->scanClause);
1015 else if (!strcmp(queryType, "xcql"))
1016 yaz_add_name_value_str(encode, name, value, &i,
1018 srw_pdu->u.scan_request->scanClause);
1020 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1021 srw_pdu->u.scan_request->responsePosition);
1022 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1023 srw_pdu->u.scan_request->maximumTerms);
1024 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1025 srw_pdu->u.scan_request->stylesheet);
1027 case Z_SRW_update_request:
1028 value[i++] = "update";
1033 if (srw_pdu->extra_args)
1035 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1036 for (; ea && i < max_names-1; ea = ea->next)
1039 value[i] = ea->value;
1048 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1049 ODR encode, const char *charset)
1051 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1055 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1056 srw_pdu->username, srw_pdu->password);
1057 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1059 yaz_array_to_uri(&uri_args, encode, name, value);
1061 hreq->method = "GET";
1064 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1066 sprintf(path, "%s?%s", hreq->path, uri_args);
1069 z_HTTP_header_add_content_type(encode, &hreq->headers,
1070 "text/xml", charset);
1074 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1075 ODR encode, const char *charset)
1077 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1080 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1081 srw_pdu->username, srw_pdu->password);
1082 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1085 yaz_array_to_uri(&uri_args, encode, name, value);
1087 hreq->method = "POST";
1089 hreq->content_buf = uri_args;
1090 hreq->content_len = strlen(uri_args);
1092 z_HTTP_header_add_content_type(encode, &hreq->headers,
1093 "application/x-www-form-urlencoded",
1098 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1099 ODR odr, const char *charset)
1101 Z_SOAP_Handler handlers[3] = {
1103 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1104 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1108 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1110 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1111 srw_pdu->username, srw_pdu->password);
1112 z_HTTP_header_add_content_type(odr,
1114 "text/xml", charset);
1116 z_HTTP_header_add(odr, &hreq->headers,
1117 "SOAPAction", "\"\"");
1118 p->which = Z_SOAP_generic;
1119 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1120 p->u.generic->no = 0;
1121 p->u.generic->ns = 0;
1122 p->u.generic->p = srw_pdu;
1123 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1126 if (srw_pdu->which == Z_SRW_update_request ||
1127 srw_pdu->which == Z_SRW_update_response)
1128 p->u.generic->no = 1; /* second handler */
1130 return z_soap_codec_enc(odr, &p,
1132 &hreq->content_len, handlers,
1136 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1138 Z_SRW_recordVersion *ver
1139 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1141 for (i = 0; i < num; ++i)
1143 ver[i].versionType = 0;
1144 ver[i].versionValue = 0;
1149 const char *yaz_srw_pack_to_str(int pack)
1153 case Z_SRW_recordPacking_string:
1155 case Z_SRW_recordPacking_XML:
1157 case Z_SRW_recordPacking_URL:
1163 int yaz_srw_str_to_pack(const char *str)
1165 if (!yaz_matchstr(str, "string"))
1166 return Z_SRW_recordPacking_string;
1167 if (!yaz_matchstr(str, "xml"))
1168 return Z_SRW_recordPacking_XML;
1169 if (!yaz_matchstr(str, "url"))
1170 return Z_SRW_recordPacking_URL;
1174 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1180 Z_SRW_extra_arg **ea = &sr->extra_args;
1181 yaz_uri_to_array(extra_args, odr, &name, &val);
1183 /** append rather than override */
1188 *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
1189 (*ea)->name = *name;
1190 (*ea)->value = *val;
1203 * c-file-style: "Stroustrup"
1204 * indent-tabs-mode: nil
1206 * vim: shiftwidth=4 tabstop=8 expandtab