1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
5 /**
6 * \file srwutil.c
7 * \brief Implements SRW/SRU utilities.
8 */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <stdlib.h>
14 #include <assert.h>
15 #include <yaz/srw.h>
16 #include <yaz/matchstr.h>
17 #include <yaz/base64.h>
18 #include <yaz/yaz-iconv.h>
19 #include "sru-p.h"
20
21 #define MAX_SRU_PARAMETERS 30
22
append_extra_arg(ODR odr,Z_SRW_extra_arg ** l,const char * n,const char * v)23 static Z_SRW_extra_arg **append_extra_arg(ODR odr, Z_SRW_extra_arg **l,
24 const char *n, const char *v)
25 {
26 if (n && v && *v != '\0')
27 {
28 while (*l)
29 l = &(*l)->next;
30 *l = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**l));
31 (*l)->name = odr_strdup(odr, n);
32 (*l)->value = odr_strdup(odr, v);
33 (*l)->next = 0;
34 l = &(*l)->next;
35 }
36 return l;
37 }
38
append_extra_arg_int(ODR odr,Z_SRW_extra_arg ** l,const char * n,Odr_int * v)39 static Z_SRW_extra_arg **append_extra_arg_int(ODR odr, Z_SRW_extra_arg **l,
40 const char *n, Odr_int *v)
41 {
42 if (v)
43 {
44 char str[32];
45 sprintf(str, ODR_INT_PRINTF, *v);
46 l = append_extra_arg(odr, l, n, str);
47 }
48 return l;
49 }
50
yaz_decode_sru_dbpath_odr(ODR n,const char * uri,size_t len)51 static char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
52 {
53 return odr_strdupn(n, uri, len);
54 }
55
yaz_encode_sru_dbpath_buf(char * dst,const char * db)56 void yaz_encode_sru_dbpath_buf(char *dst, const char *db)
57 {
58 assert(db);
59 *dst = '/';
60 strcpy(dst+1, db);
61 }
62
yaz_encode_sru_dbpath_odr(ODR out,const char * db)63 char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
64 {
65 char *dst = odr_malloc(out, 3 * strlen(db) + 2);
66 yaz_encode_sru_dbpath_buf(dst, db);
67 return dst;
68 }
69
70 #if YAZ_HAVE_XML2
yaz_element_attribute_value_get(xmlNodePtr ptr,const char * node_name,const char * attribute_name)71 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
72 const char *node_name,
73 const char *attribute_name)
74 {
75 struct _xmlAttr *attr;
76 // check if the node name matches
77 if (strcmp((const char*) ptr->name, node_name))
78 return 0;
79 // check if the attribute name and return the value
80 for (attr = ptr->properties; attr; attr = attr->next)
81 if (attr->children && attr->children->type == XML_TEXT_NODE)
82 {
83 if (!strcmp((const char *) attr->name, attribute_name))
84 return (const char *) attr->children->content;
85 }
86 return 0;
87 }
88 #endif
89
yaz_srw_check_content_type(Z_HTTP_Response * hres)90 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
91 {
92 const char *content_type = z_HTTP_header_lookup(hres->headers,
93 "Content-Type");
94 if (content_type)
95 {
96 if (!yaz_strcmp_del("text/xml", content_type, "; "))
97 return 1;
98 if (!yaz_strcmp_del("application/xml", content_type, "; "))
99 return 1;
100 if (!yaz_strcmp_del("application/sru+xml", content_type, "; "))
101 return 1;
102 }
103 return 0;
104 }
105
106 /**
107 * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
108 * parameters. Added by SH.
109 */
yaz_srw_decodeauth(Z_SRW_PDU * sr,Z_HTTP_Request * hreq,char * username,char * password,ODR decode)110 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
111 char *username, char *password, ODR decode)
112 {
113 const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
114
115 if (username)
116 sr->username = username;
117 if (password)
118 sr->password = password;
119
120 if (basic)
121 {
122 int len;
123 char out[256];
124 char ubuf[256] = "", pbuf[256] = "", *p;
125 if (strncmp(basic, "Basic ", 6))
126 return;
127 basic += 6;
128 len = strlen(basic);
129 if (!len || len > 256)
130 return;
131 yaz_base64decode(basic, out);
132 /* Format of out should be username:password at this point */
133 strcpy(ubuf, out);
134 if ((p = strchr(ubuf, ':')))
135 {
136 *(p++) = '\0';
137 if (*p)
138 strcpy(pbuf, p);
139 }
140 if (*ubuf)
141 sr->username = odr_strdup(decode, ubuf);
142 if (*pbuf)
143 sr->password = odr_strdup(decode, pbuf);
144 }
145 }
146
yaz_mk_srw_diagnostic(ODR o,Z_SRW_diagnostic * d,const char * uri,const char * message,const char * details)147 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
148 const char *uri, const char *message,
149 const char *details)
150 {
151 d->uri = odr_strdup(o, uri);
152 if (message)
153 d->message = odr_strdup(o, message);
154 else
155 d->message = 0;
156 if (details)
157 d->details = odr_strdup(o, details);
158 else
159 d->details = 0;
160 }
161
yaz_mk_std_diagnostic(ODR o,Z_SRW_diagnostic * d,int code,const char * details)162 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
163 int code, const char *details)
164 {
165 char uri[40];
166
167 sprintf(uri, "info:srw/diagnostic/1/%d", code);
168 yaz_mk_srw_diagnostic(o, d, uri, 0, details);
169 }
170
yaz_add_srw_diagnostic_uri(ODR o,Z_SRW_diagnostic ** d,int * num,const char * uri,const char * message,const char * details)171 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
172 int *num, const char *uri,
173 const char *message, const char *details)
174 {
175 Z_SRW_diagnostic *d_new;
176 d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
177 if (*num)
178 memcpy(d_new, *d, *num *sizeof(**d));
179 *d = d_new;
180
181 yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
182 (*num)++;
183 }
184
yaz_add_srw_diagnostic(ODR o,Z_SRW_diagnostic ** d,int * num,int code,const char * addinfo)185 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
186 int *num, int code, const char *addinfo)
187 {
188 char uri[40];
189
190 sprintf(uri, "info:srw/diagnostic/1/%d", code);
191 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
192 }
193
194
yaz_add_sru_update_diagnostic(ODR o,Z_SRW_diagnostic ** d,int * num,int code,const char * addinfo)195 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
196 int *num, int code, const char *addinfo)
197 {
198 char uri[40];
199
200 sprintf(uri, "info:srw/diagnostic/12/%d", code);
201 yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
202 }
203
204
yaz_mk_sru_surrogate(ODR o,Z_SRW_record * record,int pos,int code,const char * details)205 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
206 int code, const char *details)
207 {
208 const char *message = yaz_diag_srw_str(code);
209 int len = 200;
210 if (message)
211 len += strlen(message);
212 if (details)
213 len += strlen(details);
214
215 record->recordData_buf = (char *) odr_malloc(o, len);
216
217 sprintf(record->recordData_buf, "<diagnostic "
218 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
219 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
220 if (details)
221 sprintf(record->recordData_buf + strlen(record->recordData_buf),
222 " <details>%s</details>\n", details);
223 if (message)
224 sprintf(record->recordData_buf + strlen(record->recordData_buf),
225 " <message>%s</message>\n", message);
226 sprintf(record->recordData_buf + strlen(record->recordData_buf),
227 "</diagnostic>\n");
228 record->recordData_len = strlen(record->recordData_buf);
229 record->recordPosition = odr_intdup(o, pos);
230 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
231 }
232
grab_charset(ODR o,const char * content_type,char ** charset)233 static void grab_charset(ODR o, const char *content_type, char **charset)
234 {
235 if (charset)
236 {
237 const char *charset_p = 0;
238 if (content_type && (charset_p = strstr(content_type, "; charset=")))
239 {
240 int j = 0, i = 0;
241 int sep = 0;
242 charset_p += 10; /* skip ; charset= */
243 if (charset_p[i] == '"' || charset_p[i] == '\'')
244 sep = charset_p[i++];
245 *charset = odr_strdup(o, charset_p);
246 while (charset_p[i] && charset_p[i] != sep)
247 {
248 if (!sep && strchr("; \n\r", charset_p[i]))
249 break;
250 if (charset_p[i] == '\\' && charset_p[i+1])
251 i++;
252 (*charset)[j++] = charset_p[i++];
253 }
254 (*charset)[j] = '\0';
255 }
256 }
257 }
258
yaz_srw_decode(Z_HTTP_Request * hreq,Z_SRW_PDU ** srw_pdu,Z_SOAP ** soap_package,ODR decode,char ** charset)259 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
260 Z_SOAP **soap_package, ODR decode, char **charset)
261 {
262 if (!strcmp(hreq->method, "POST"))
263 {
264 const char *content_type = z_HTTP_header_lookup(hreq->headers,
265 "Content-Type");
266 if (content_type &&
267 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
268 !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
269 !yaz_strcmp_del("text/plain", content_type, "; ")))
270 {
271 char *db = "Default";
272 const char *p0 = hreq->path, *p1;
273 int ret = -1;
274
275 static Z_SOAP_Handler soap_handlers[5] = {
276 #if YAZ_HAVE_XML2
277 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
278 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
279 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
280 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
281 #endif
282 {0, 0, 0}
283 };
284
285 if (*p0 == '/')
286 p0++;
287 p1 = strchr(p0, '?');
288 if (!p1)
289 p1 = p0 + strlen(p0);
290 if (p1 != p0)
291 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
292
293 ret = z_soap_codec(decode, soap_package,
294 &hreq->content_buf, &hreq->content_len,
295 soap_handlers);
296 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
297 {
298 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
299 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
300
301 /* last entry in handlers - SRU 2.0 - is turned into
302 offset 0.. due to other pieces relying on it */
303 if ((*soap_package)->u.generic->no == 3)
304 (*soap_package)->u.generic->no = 0;
305 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
306 (*srw_pdu)->u.request->database == 0)
307 (*srw_pdu)->u.request->database = db;
308
309 if ((*srw_pdu)->which == Z_SRW_explain_request &&
310 (*srw_pdu)->u.explain_request->database == 0)
311 (*srw_pdu)->u.explain_request->database = db;
312
313 if ((*srw_pdu)->which == Z_SRW_scan_request &&
314 (*srw_pdu)->u.scan_request->database == 0)
315 (*srw_pdu)->u.scan_request->database = db;
316
317 if ((*srw_pdu)->which == Z_SRW_update_request &&
318 (*srw_pdu)->u.update_request->database == 0)
319 (*srw_pdu)->u.update_request->database = db;
320
321 return 0;
322 }
323 return 1;
324 }
325 }
326 return 2;
327 }
328
329 #if YAZ_HAVE_XML2
yaz_sru_decode_integer(ODR odr,const char * pname,const char * valstr,Odr_int ** valp,Z_SRW_diagnostic ** diag,int * num_diag,int min_value)330 static int yaz_sru_decode_integer(ODR odr, const char *pname,
331 const char *valstr, Odr_int **valp,
332 Z_SRW_diagnostic **diag, int *num_diag,
333 int min_value)
334 {
335 int ival;
336 if (!valstr)
337 return 0;
338 if (sscanf(valstr, "%d", &ival) != 1)
339 {
340 yaz_add_srw_diagnostic(odr, diag, num_diag,
341 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
342 return 0;
343 }
344 if (min_value >= 0 && ival < min_value)
345 {
346 yaz_add_srw_diagnostic(odr, diag, num_diag,
347 YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
348 return 0;
349 }
350 *valp = odr_intdup(odr, ival);
351 return 1;
352 }
353 #endif
354
355 /**
356 http://www.loc.gov/standards/sru/companionSpecs/srw.html
357 */
yaz_sru_decode(Z_HTTP_Request * hreq,Z_SRW_PDU ** srw_pdu,Z_SOAP ** soap_package,ODR decode,char ** charset,Z_SRW_diagnostic ** diag,int * num_diag)358 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
359 Z_SOAP **soap_package, ODR decode, char **charset,
360 Z_SRW_diagnostic **diag, int *num_diag)
361 {
362 #if YAZ_HAVE_XML2
363 static Z_SOAP_Handler soap_handlers[2] = {
364 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
365 {0, 0, 0}
366 };
367 #endif
368 const char *content_type = z_HTTP_header_lookup(hreq->headers,
369 "Content-Type");
370
371 /*
372 SRU GET: ignore content type.
373 SRU POST: we support "application/x-www-form-urlencoded";
374 not "multipart/form-data" .
375 */
376 if (!strcmp(hreq->method, "GET")
377 ||
378 (!strcmp(hreq->method, "POST") && content_type &&
379 !yaz_strcmp_del("application/x-www-form-urlencoded",
380 content_type, "; ")))
381 {
382 char *db = "Default";
383 const char *p0 = hreq->path, *p1;
384 #if YAZ_HAVE_XML2
385 const char *operation = 0;
386 char *version = 0;
387 char *query = 0;
388 char *queryType = "cql";
389 char *username = 0;
390 char *password = 0;
391 char *sortKeys = 0;
392 char *stylesheet = 0;
393 char *scanClause = 0;
394 char *recordXPath = 0;
395 char *recordSchema = 0;
396 char *recordXMLEscaping = 0;
397 char *recordPacking = 0;
398 char *maximumRecords = 0;
399 char *startRecord = 0;
400 char *maximumTerms = 0;
401 char *responsePosition = 0;
402 const char *facetLimit = 0;
403 const char *facetStart = 0;
404 const char *facetSort = 0;
405 Z_SRW_extra_arg *extra_args = 0;
406 #endif
407 char **uri_name;
408 char **uri_val;
409
410 grab_charset(decode, content_type, charset);
411 if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
412 *charset = "UTF-8";
413
414 if (*p0 == '/')
415 p0++;
416 p1 = strchr(p0, '?');
417 if (!p1)
418 p1 = p0 + strlen(p0);
419 if (p1 != p0)
420 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
421 if (!strcmp(hreq->method, "POST") && hreq->content_buf)
422 p1 = hreq->content_buf;
423 yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
424 #if YAZ_HAVE_XML2
425 if (uri_name)
426 {
427 int i;
428 for (i = 0; uri_name[i]; i++)
429 {
430 char *n = uri_name[i];
431 char *v = uri_val[i];
432 if (!strcmp(n, "query"))
433 query = v;
434 else if (!strcmp(n, "x-pquery"))
435 {
436 query = v;
437 queryType = "pqf";
438 }
439 else if (!strcmp(n, "queryType"))
440 queryType = v;
441 else if (!strcmp(n, "x-username"))
442 username = v;
443 else if (!strcmp(n, "x-password"))
444 password = v;
445 else if (!strcmp(n, "operation"))
446 operation = v;
447 else if (!strcmp(n, "stylesheet"))
448 stylesheet = v;
449 else if (!strcmp(n, "sortKeys"))
450 sortKeys = v;
451 else if (!strcmp(n, "recordXPath"))
452 recordXPath = v;
453 else if (!strcmp(n, "recordSchema"))
454 recordSchema = v;
455 else if (!strcmp(n, "recordPacking"))
456 recordPacking = v;
457 else if (!strcmp(n, "recordXMLEscaping"))
458 recordXMLEscaping = v;
459 else if (!strcmp(n, "version"))
460 version = v;
461 else if (!strcmp(n, "scanClause"))
462 scanClause = v;
463 else if (!strcmp(n, "x-pScanClause"))
464 {
465 scanClause = v;
466 queryType = "pqf";
467 }
468 else if (!strcmp(n, "maximumRecords"))
469 maximumRecords = v;
470 else if (!strcmp(n, "startRecord"))
471 startRecord = v;
472 else if (!strcmp(n, "maximumTerms"))
473 maximumTerms = v;
474 else if (!strcmp(n, "responsePosition"))
475 responsePosition = v;
476 else if (!strcmp(n, "facetLimit"))
477 facetLimit = v;
478 else if (!strcmp(n, "facetStart"))
479 facetStart = v;
480 else if (!strcmp(n, "facetSort"))
481 facetSort = v;
482 else if (!strcmp(n, "extraRequestData"))
483 ; /* ignoring extraRequestData */
484 else if (n[0] == 'x' && n[1] == '-')
485 {
486 append_extra_arg(decode, &extra_args, n, v);
487 }
488 else
489 {
490 if (*num_diag < 10)
491 yaz_add_srw_diagnostic(decode, diag, num_diag,
492 YAZ_SRW_UNSUPP_PARAMETER, n);
493 }
494 }
495 }
496 if (!operation)
497 {
498 if (query)
499 operation = "searchRetrieve";
500 else if (scanClause)
501 operation = "scan";
502 else
503 operation = "explain";
504 }
505 version = yaz_negotiate_sru_version(version);
506
507 if (!version)
508 { /* negotiation failed. */
509 yaz_add_srw_diagnostic(decode, diag, num_diag,
510 YAZ_SRW_UNSUPP_VERSION, "2.0");
511 version = "2.0";
512 }
513 if (!operation)
514 {
515 if (uri_name)
516 yaz_add_srw_diagnostic(
517 decode, diag, num_diag,
518 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
519 operation = "explain";
520 }
521 if (strcmp(version, "2.0"))
522 {
523 if (recordXMLEscaping)
524 {
525 yaz_add_srw_diagnostic(decode, diag, num_diag,
526 YAZ_SRW_UNSUPP_PARAMETER,
527 "recordXMLEscaping");
528
529 }
530 recordXMLEscaping = recordPacking;
531 recordPacking = "packed";
532 }
533 if (!recordXMLEscaping)
534 recordXMLEscaping = "xml";
535 if (!strcmp(operation, "searchRetrieve"))
536 {
537 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
538
539 sr->srw_version = version;
540 sr->extra_args = extra_args;
541 *srw_pdu = sr;
542 yaz_srw_decodeauth(sr, hreq, username, password, decode);
543
544 sr->u.request->queryType = queryType;
545 sr->u.request->query = query;
546
547 if (!query)
548 yaz_add_srw_diagnostic(
549 decode, diag, num_diag,
550 YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
551
552 if (sortKeys)
553 {
554 sr->u.request->sort_type = Z_SRW_sort_type_sort;
555 sr->u.request->sort.sortKeys = sortKeys;
556 }
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);
564
565 yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
566 &sr->u.request->maximumRecords,
567 diag, num_diag, 0);
568
569 yaz_sru_decode_integer(decode, "startRecord", startRecord,
570 &sr->u.request->startRecord,
571 diag, num_diag, 1);
572
573 sr->u.request->database = db;
574
575 (*soap_package) = (Z_SOAP *)
576 odr_malloc(decode, sizeof(**soap_package));
577 (*soap_package)->which = Z_SOAP_generic;
578
579 (*soap_package)->u.generic = (Z_SOAP_Generic *)
580 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
581
582 (*soap_package)->u.generic->p = sr;
583 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
584 (*soap_package)->u.generic->no = 0;
585
586 (*soap_package)->ns = "SRU";
587
588 return 0;
589 }
590 else if (!strcmp(operation, "explain"))
591 {
592 /* Transfer SRU explain parameters to common struct */
593 /* http://www.loc.gov/standards/sru/explain/ */
594 /* http://zeerex.z3950.org/overview/ */
595 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
596
597 sr->srw_version = version;
598 sr->extra_args = extra_args;
599 yaz_srw_decodeauth(sr, hreq, username, password, decode);
600 *srw_pdu = sr;
601 sr->u.explain_request->recordPacking = recordXMLEscaping;
602 sr->u.explain_request->packing = recordPacking;
603 sr->u.explain_request->database = db;
604
605 sr->u.explain_request->stylesheet = stylesheet;
606
607 (*soap_package) = (Z_SOAP *)
608 odr_malloc(decode, sizeof(**soap_package));
609 (*soap_package)->which = Z_SOAP_generic;
610
611 (*soap_package)->u.generic = (Z_SOAP_Generic *)
612 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
613
614 (*soap_package)->u.generic->p = sr;
615 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
616 (*soap_package)->u.generic->no = 0;
617
618 (*soap_package)->ns = "SRU";
619
620 return 0;
621 }
622 else if (!strcmp(operation, "scan"))
623 {
624 /* Transfer SRU scan parameters to common struct */
625 /* http://www.loc.gov/standards/sru/companionSpecs/scan.html */
626 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
627
628 sr->srw_version = version;
629 sr->extra_args = extra_args;
630 *srw_pdu = sr;
631 yaz_srw_decodeauth(sr, hreq, username, password, decode);
632
633 sr->u.scan_request->queryType = queryType;
634 sr->u.scan_request->scanClause = scanClause;
635
636 if (!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;
641
642 yaz_sru_decode_integer(decode, "maximumTerms",
643 maximumTerms,
644 &sr->u.scan_request->maximumTerms,
645 diag, num_diag, 0);
646
647 yaz_sru_decode_integer(decode, "responsePosition",
648 responsePosition,
649 &sr->u.scan_request->responsePosition,
650 diag, num_diag, 0);
651
652 sr->u.scan_request->stylesheet = stylesheet;
653
654 (*soap_package) = (Z_SOAP *)
655 odr_malloc(decode, sizeof(**soap_package));
656 (*soap_package)->which = Z_SOAP_generic;
657
658 (*soap_package)->u.generic = (Z_SOAP_Generic *)
659 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
660
661 (*soap_package)->u.generic->p = sr;
662 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
663 (*soap_package)->u.generic->no = 0;
664
665 (*soap_package)->ns = "SRU";
666
667 return 0;
668 }
669 else
670 {
671 /* unsupported operation ... */
672 /* Act as if we received a explain request and throw diagnostic. */
673
674 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
675
676 sr->srw_version = version;
677 *srw_pdu = sr;
678 sr->u.explain_request->recordPacking = recordPacking;
679 sr->u.explain_request->database = db;
680
681 sr->u.explain_request->stylesheet = stylesheet;
682
683 (*soap_package) = (Z_SOAP *)
684 odr_malloc(decode, sizeof(**soap_package));
685 (*soap_package)->which = Z_SOAP_generic;
686
687 (*soap_package)->u.generic = (Z_SOAP_Generic *)
688 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
689
690 (*soap_package)->u.generic->p = sr;
691 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
692 (*soap_package)->u.generic->no = 0;
693
694 (*soap_package)->ns = "SRU";
695
696 yaz_add_srw_diagnostic(decode, diag, num_diag,
697 YAZ_SRW_UNSUPP_OPERATION, operation);
698 return 0;
699 }
700 #else
701 return 1;
702 #endif
703 }
704 return 2;
705 }
706
yaz_srw_get_extra_record(ODR o)707 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
708 {
709 Z_SRW_extra_record *res = (Z_SRW_extra_record *)
710 odr_malloc(o, sizeof(*res));
711
712 res->extraRecordData_buf = 0;
713 res->extraRecordData_len = 0;
714 res->recordIdentifier = 0;
715 return res;
716 }
717
718
yaz_srw_get_records(ODR o,int n)719 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
720 {
721 Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
722 int i;
723
724 for (i = 0; i<n; i++)
725 {
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;
731 }
732 return res;
733 }
734
yaz_srw_get_record(ODR o)735 Z_SRW_record *yaz_srw_get_record(ODR o)
736 {
737 return yaz_srw_get_records(o, 1);
738 }
739
yaz_srw_get_core_ver(ODR o,const char * version)740 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
741 {
742 Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
743 p->srw_version = odr_strdup(o, version);
744 p->username = 0;
745 p->password = 0;
746 p->extra_args = 0;
747 p->extraResponseData_buf = 0;
748 p->extraResponseData_len = 0;
749 return p;
750 }
751
yaz_srw_get_core_v_2_0(ODR o)752 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
753 {
754 return yaz_srw_get_core_ver(o, "2.0");
755 }
756
yaz_srw_get(ODR o,int which)757 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
758 {
759 return yaz_srw_get_pdu(o, which, "2.0");
760 }
761
762 /* http://docs.oasis-open.org/search-ws/searchRetrieve/v1.0/os/schemas/sruResponse.xsd */
yaz_srw_get_pdu_e(ODR o,int which,Z_SRW_PDU * req)763 Z_SRW_PDU *yaz_srw_get_pdu_e(ODR o, int which, Z_SRW_PDU *req)
764 {
765 int version2 = !req->srw_version || strcmp(req->srw_version, "2.") > 0;
766 Z_SRW_PDU *res = yaz_srw_get_pdu(o, which, req->srw_version);
767 Z_SRW_extra_arg **l = &res->extra_args, *ea;
768 l = append_extra_arg(o, l, "version", req->srw_version);
769 if (req->which == Z_SRW_searchRetrieve_request &&
770 which == Z_SRW_searchRetrieve_response)
771 {
772 if (req->u.request->queryType &&
773 strcmp(req->u.request->queryType, "cql"))
774 l = append_extra_arg(o, l, "queryType", req->u.request->queryType);
775 l = append_extra_arg(o, l, "query", req->u.request->query);
776 l = append_extra_arg_int(o, l, "startRecord",
777 req->u.request->startRecord);
778 l = append_extra_arg_int(o, l, "maximumRecords",
779 req->u.request->maximumRecords);
780 if (version2)
781 {
782 l = append_extra_arg(o, l, "recordXMLEscaping",
783 req->u.request->recordPacking);
784 l = append_extra_arg(o, l, "recordPacking",
785 req->u.request->packing);
786 }
787 else
788 l = append_extra_arg(o, l, "recordPacking",
789 req->u.request->recordPacking);
790 l = append_extra_arg(o, l, "recordSchema",
791 req->u.request->recordSchema);
792 if (req->u.request->sort_type == Z_SRW_sort_type_sort)
793 l = append_extra_arg(o, l, "sortKeys",
794 req->u.request->sort.sortKeys);
795 l = append_extra_arg(o, l, "stylesheet", req->u.request->stylesheet);
796 }
797 if (req->which == Z_SRW_explain_request &&
798 which == Z_SRW_explain_response)
799 {
800 if (version2)
801 {
802 l = append_extra_arg(o, l, "recordXMLEscaping",
803 req->u.explain_request->recordPacking);
804 l = append_extra_arg(o, l, "recordPacking",
805 req->u.explain_request->packing);
806 }
807 else
808 l = append_extra_arg(o, l, "recordPacking",
809 req->u.explain_request->recordPacking);
810 l = append_extra_arg(o, l, "stylesheet",
811 req->u.explain_request->stylesheet);
812 }
813 for (ea = req->extra_args; ea; ea = ea->next)
814 l = append_extra_arg(o, l, ea->name, ea->value);
815 return res;
816 }
817
yaz_srw_get_pdu(ODR o,int which,const char * version)818 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
819 {
820 Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
821
822 sr->which = which;
823 switch (which)
824 {
825 case Z_SRW_searchRetrieve_request:
826 sr->u.request = (Z_SRW_searchRetrieveRequest *)
827 odr_malloc(o, sizeof(*sr->u.request));
828 sr->u.request->queryType = "cql";
829 sr->u.request->query = 0;
830 sr->u.request->sort_type = Z_SRW_sort_type_none;
831 sr->u.request->sort.none = 0;
832 sr->u.request->startRecord = 0;
833 sr->u.request->maximumRecords = 0;
834 sr->u.request->recordSchema = 0;
835 sr->u.request->recordPacking = 0;
836 sr->u.request->packing = 0;
837 sr->u.request->recordXPath = 0;
838 sr->u.request->database = 0;
839 sr->u.request->resultSetTTL = 0;
840 sr->u.request->stylesheet = 0;
841 sr->u.request->facetList = 0;
842 break;
843 case Z_SRW_searchRetrieve_response:
844 sr->u.response = (Z_SRW_searchRetrieveResponse *)
845 odr_malloc(o, sizeof(*sr->u.response));
846 sr->u.response->numberOfRecords = 0;
847 sr->u.response->resultCountPrecision = 0;
848 sr->u.response->resultSetId = 0;
849 sr->u.response->resultSetIdleTime = 0;
850 sr->u.response->records = 0;
851 sr->u.response->num_records = 0;
852 sr->u.response->diagnostics = 0;
853 sr->u.response->num_diagnostics = 0;
854 sr->u.response->nextRecordPosition = 0;
855 sr->u.response->extra_records = 0;
856 sr->u.response->facetList = 0;
857 sr->u.response->suggestions = 0;
858 break;
859 case Z_SRW_explain_request:
860 sr->u.explain_request = (Z_SRW_explainRequest *)
861 odr_malloc(o, sizeof(*sr->u.explain_request));
862 sr->u.explain_request->recordPacking = 0;
863 sr->u.explain_request->packing = 0;
864 sr->u.explain_request->database = 0;
865 sr->u.explain_request->stylesheet = 0;
866 break;
867 case Z_SRW_explain_response:
868 sr->u.explain_response = (Z_SRW_explainResponse *)
869 odr_malloc(o, sizeof(*sr->u.explain_response));
870 sr->u.explain_response->record.recordData_buf = 0;
871 sr->u.explain_response->record.recordData_len = 0;
872 sr->u.explain_response->record.recordSchema = 0;
873 sr->u.explain_response->record.recordPosition = 0;
874 sr->u.explain_response->record.recordPacking =
875 Z_SRW_recordPacking_string;
876 sr->u.explain_response->diagnostics = 0;
877 sr->u.explain_response->num_diagnostics = 0;
878 sr->u.explain_response->extra_record = 0;
879 break;
880 case Z_SRW_scan_request:
881 sr->u.scan_request = (Z_SRW_scanRequest *)
882 odr_malloc(o, sizeof(*sr->u.scan_request));
883 sr->u.scan_request->database = 0;
884 sr->u.scan_request->stylesheet = 0;
885 sr->u.scan_request->maximumTerms = 0;
886 sr->u.scan_request->responsePosition = 0;
887 sr->u.scan_request->queryType = "cql";
888 sr->u.scan_request->scanClause = 0;
889 break;
890 case Z_SRW_scan_response:
891 sr->u.scan_response = (Z_SRW_scanResponse *)
892 odr_malloc(o, sizeof(*sr->u.scan_response));
893 sr->u.scan_response->terms = 0;
894 sr->u.scan_response->num_terms = 0;
895 sr->u.scan_response->diagnostics = 0;
896 sr->u.scan_response->num_diagnostics = 0;
897 break;
898 case Z_SRW_update_request:
899 sr->u.update_request = (Z_SRW_updateRequest *)
900 odr_malloc(o, sizeof(*sr->u.update_request));
901 sr->u.update_request->database = 0;
902 sr->u.update_request->stylesheet = 0;
903 sr->u.update_request->record = 0;
904 sr->u.update_request->recordId = 0;
905 sr->u.update_request->recordVersions = 0;
906 sr->u.update_request->num_recordVersions = 0;
907 sr->u.update_request->extra_record = 0;
908 sr->u.update_request->extraRequestData_buf = 0;
909 sr->u.update_request->extraRequestData_len = 0;
910 sr->u.request->database = 0;
911 break;
912 case Z_SRW_update_response:
913 sr->u.update_response = (Z_SRW_updateResponse *)
914 odr_malloc(o, sizeof(*sr->u.update_response));
915 sr->u.update_response->operationStatus = 0;
916 sr->u.update_response->recordId = 0;
917 sr->u.update_response->recordVersions = 0;
918 sr->u.update_response->num_recordVersions = 0;
919 sr->u.update_response->record = 0;
920 sr->u.update_response->extra_record = 0;
921 sr->u.update_response->extraResponseData_buf = 0;
922 sr->u.update_response->extraResponseData_len = 0;
923 sr->u.update_response->diagnostics = 0;
924 sr->u.update_response->num_diagnostics = 0;
925 }
926 return sr;
927 }
928
yaz_add_name_value_int(ODR o,char ** name,char ** value,int * i,char * a_name,Odr_int * val)929 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
930 char *a_name, Odr_int *val)
931 {
932 if (val)
933 {
934 name[*i] = a_name;
935 value[*i] = (char *) odr_malloc(o, 40);
936 sprintf(value[*i], ODR_INT_PRINTF, *val);
937 (*i)++;
938 }
939 }
940
yaz_add_name_value_str(ODR o,char ** name,char ** value,int * i,char * a_name,char * val)941 void yaz_add_name_value_str(ODR o, char **name, char **value, int *i,
942 char *a_name, char *val)
943 {
944 if (val)
945 {
946 name[*i] = a_name;
947 value[*i] = val;
948 (*i)++;
949 }
950 }
951
yaz_get_sru_parms(const Z_SRW_PDU * srw_pdu,ODR encode,char ** name,char ** value,int max_names)952 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
953 char **name, char **value, int max_names)
954 {
955 int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
956 int i = 0;
957 char *queryType;
958 yaz_add_name_value_str(encode, name, value, &i, "version",
959 srw_pdu->srw_version);
960 name[i] = "operation";
961 switch (srw_pdu->which)
962 {
963 case Z_SRW_searchRetrieve_request:
964 value[i++] = "searchRetrieve";
965 queryType = srw_pdu->u.request->queryType;
966 if (version2)
967 {
968 if (queryType && strcmp(queryType, "cql"))
969 yaz_add_name_value_str(encode, name, value, &i, "queryType",
970 queryType);
971 yaz_add_name_value_str(encode, name, value, &i, "query",
972 srw_pdu->u.request->query);
973 }
974 else
975 {
976 if (!strcmp(queryType, "cql"))
977 {
978 yaz_add_name_value_str(encode, name, value, &i, "query",
979 srw_pdu->u.request->query);
980 }
981 else if (!strcmp(queryType, "pqf"))
982 {
983 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
984 srw_pdu->u.request->query);
985 }
986 else if (!strcmp(queryType, "xcql"))
987 {
988 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
989 srw_pdu->u.request->query);
990 }
991 }
992 switch (srw_pdu->u.request->sort_type)
993 {
994 case Z_SRW_sort_type_none:
995 break;
996 case Z_SRW_sort_type_sort:
997 yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
998 srw_pdu->u.request->sort.sortKeys);
999 break;
1000 }
1001 yaz_add_name_value_int(encode, name, value, &i, "startRecord",
1002 srw_pdu->u.request->startRecord);
1003 yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
1004 srw_pdu->u.request->maximumRecords);
1005 yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
1006 srw_pdu->u.request->recordSchema);
1007 if (version2)
1008 {
1009 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1010 srw_pdu->u.request->recordPacking);
1011 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1012 srw_pdu->u.request->packing);
1013 }
1014 else
1015 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1016 srw_pdu->u.request->recordPacking);
1017 yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
1018 srw_pdu->u.request->recordXPath);
1019 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1020 srw_pdu->u.request->stylesheet);
1021 yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
1022 srw_pdu->u.request->resultSetTTL);
1023 {
1024 const char *facetLimit = 0;
1025 const char *facetStart = 0;
1026 const char *facetSort = 0;
1027 yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
1028 &facetLimit, &facetStart, &facetSort);
1029 yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
1030 (char *) facetLimit);
1031 yaz_add_name_value_str(encode, name, value, &i, "facetStart",
1032 (char *) facetStart);
1033 yaz_add_name_value_str(encode, name, value, &i, "facetSort",
1034 (char *) facetSort);
1035 }
1036 break;
1037 case Z_SRW_explain_request:
1038 value[i++] = "explain";
1039
1040 if (version2)
1041 {
1042 yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1043 srw_pdu->u.explain_request->recordPacking);
1044 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1045 srw_pdu->u.explain_request->packing);
1046 }
1047 else
1048 yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1049 srw_pdu->u.explain_request->recordPacking);
1050 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1051 srw_pdu->u.explain_request->stylesheet);
1052 break;
1053 case Z_SRW_scan_request:
1054 value[i++] = "scan";
1055 queryType = srw_pdu->u.scan_request->queryType;
1056 if (version2)
1057 {
1058 if (queryType && strcmp(queryType, "cql"))
1059 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1060 queryType);
1061 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1062 srw_pdu->u.scan_request->scanClause);
1063 }
1064 else
1065 {
1066 if (!queryType || !strcmp(queryType, "cql"))
1067 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1068 srw_pdu->u.scan_request->scanClause);
1069 else if (!strcmp(queryType, "pqf"))
1070 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1071 srw_pdu->u.scan_request->scanClause);
1072 else if (!strcmp(queryType, "xcql"))
1073 yaz_add_name_value_str(encode, name, value, &i,
1074 "x-cqlScanClause",
1075 srw_pdu->u.scan_request->scanClause);
1076 }
1077 yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1078 srw_pdu->u.scan_request->responsePosition);
1079 yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1080 srw_pdu->u.scan_request->maximumTerms);
1081 yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1082 srw_pdu->u.scan_request->stylesheet);
1083 break;
1084 case Z_SRW_update_request:
1085 value[i++] = "update";
1086 break;
1087 default:
1088 return -1;
1089 }
1090 if (srw_pdu->extra_args)
1091 {
1092 Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1093 for (; ea && i < max_names-1; ea = ea->next)
1094 {
1095 name[i] = ea->name;
1096 value[i] = ea->value;
1097 i++;
1098 }
1099 }
1100 name[i++] = 0;
1101
1102 return 0;
1103 }
1104
yaz_sru_get_encode(Z_HTTP_Request * hreq,Z_SRW_PDU * srw_pdu,ODR encode,const char * charset)1105 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1106 ODR encode, const char *charset)
1107 {
1108 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1109 char *uri_args;
1110 char *path;
1111 char *cp;
1112
1113 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1114 srw_pdu->username, srw_pdu->password);
1115 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1116 return -1;
1117 yaz_array_to_uri(&uri_args, encode, name, value);
1118
1119 hreq->method = "GET";
1120
1121 cp = strchr(hreq->path, '#');
1122 if (cp)
1123 *cp = '\0';
1124
1125 path = (char *)
1126 odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1127
1128 sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1129 uri_args);
1130 hreq->path = path;
1131
1132 z_HTTP_header_add_content_type(encode, &hreq->headers,
1133 "text/xml", charset);
1134 return 0;
1135 }
1136
yaz_sru_post_encode(Z_HTTP_Request * hreq,Z_SRW_PDU * srw_pdu,ODR encode,const char * charset)1137 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1138 ODR encode, const char *charset)
1139 {
1140 char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1141 char *uri_args;
1142
1143 z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1144 srw_pdu->username, srw_pdu->password);
1145 if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1146 return -1;
1147
1148 yaz_array_to_uri(&uri_args, encode, name, value);
1149
1150 hreq->method = "POST";
1151
1152 hreq->content_buf = uri_args;
1153 hreq->content_len = strlen(uri_args);
1154
1155 z_HTTP_header_add_content_type(encode, &hreq->headers,
1156 "application/x-www-form-urlencoded",
1157 charset);
1158 return 0;
1159 }
1160
yaz_sru_soap_encode(Z_HTTP_Request * hreq,Z_SRW_PDU * srw_pdu,ODR odr,const char * charset)1161 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1162 ODR odr, const char *charset)
1163 {
1164 Z_SOAP_Handler handlers[3] = {
1165 #if YAZ_HAVE_XML2
1166 {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1167 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1168 #endif
1169 {0, 0, 0}
1170 };
1171 Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1172
1173 z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1174 srw_pdu->username, srw_pdu->password);
1175 z_HTTP_header_add_content_type(odr,
1176 &hreq->headers,
1177 "text/xml", 0 /* no charset in MIME */);
1178
1179 z_HTTP_header_add(odr, &hreq->headers,
1180 "SOAPAction", "\"\"");
1181 p->which = Z_SOAP_generic;
1182 p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1183 p->u.generic->no = 0;
1184 p->u.generic->ns = 0;
1185 p->u.generic->p = srw_pdu;
1186 p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1187
1188 #if YAZ_HAVE_XML2
1189 if (srw_pdu->which == Z_SRW_update_request ||
1190 srw_pdu->which == Z_SRW_update_response)
1191 p->u.generic->no = 1; /* second handler */
1192 #endif
1193 return z_soap_codec_enc(odr, &p,
1194 &hreq->content_buf,
1195 &hreq->content_len, handlers,
1196 charset);
1197 }
1198
yaz_srw_get_record_versions(ODR odr,int num)1199 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1200 {
1201 Z_SRW_recordVersion *ver
1202 = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1203 int i;
1204 for (i = 0; i < num; ++i)
1205 {
1206 ver[i].versionType = 0;
1207 ver[i].versionValue = 0;
1208 }
1209 return ver;
1210 }
1211
yaz_srw_pack_to_str(int pack)1212 const char *yaz_srw_pack_to_str(int pack)
1213 {
1214 switch(pack)
1215 {
1216 case Z_SRW_recordPacking_string:
1217 return "string";
1218 case Z_SRW_recordPacking_XML:
1219 return "xml";
1220 case Z_SRW_recordPacking_URL:
1221 return "url";
1222 }
1223 return 0;
1224 }
1225
yaz_srw_str_to_pack(const char * str)1226 int yaz_srw_str_to_pack(const char *str)
1227 {
1228 if (!yaz_matchstr(str, "string"))
1229 return Z_SRW_recordPacking_string;
1230 if (!yaz_matchstr(str, "xml"))
1231 return Z_SRW_recordPacking_XML;
1232 if (!yaz_matchstr(str, "url"))
1233 return Z_SRW_recordPacking_URL;
1234 return -1;
1235 }
1236
yaz_encode_sru_extra(Z_SRW_PDU * sr,ODR odr,const char * extra_args)1237 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1238 {
1239 if (extra_args)
1240 {
1241 char **name;
1242 char **val;
1243 Z_SRW_extra_arg **ea = &sr->extra_args;
1244 yaz_uri_to_array(extra_args, odr, &name, &val);
1245
1246 while (*name)
1247 {
1248 ea = append_extra_arg(odr, ea, *name, *val);
1249 val++;
1250 name++;
1251 }
1252 }
1253 }
1254
1255
1256 /*
1257 * Local variables:
1258 * c-basic-offset: 4
1259 * c-file-style: "Stroustrup"
1260 * indent-tabs-mode: nil
1261 * End:
1262 * vim: shiftwidth=4 tabstop=8 expandtab
1263 */
1264
1265