2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.25 2005-01-17 10:19:48 adam Exp $
9 * \brief Implements SRW/SRU utilities.
14 #include <yaz/yaz-iconv.h>
16 static int hex_digit (int ch)
18 if (ch >= '0' && ch <= '9')
20 else if (ch >= 'a' && ch <= 'f')
22 else if (ch >= 'A' && ch <= 'F')
27 int yaz_uri_array(const char *path, ODR o, char ***name, char ***val)
36 while ((cp = strchr(cp, '&')))
41 *name = odr_malloc(o, no * sizeof(char**));
42 *val = odr_malloc(o, no * sizeof(char**));
44 for (no = 0; *path; no++)
46 const char *p1 = strchr(path, '=');
52 (*name)[no] = odr_malloc(o, (p1-path)+1);
53 memcpy((*name)[no], path, p1-path);
54 (*name)[no][p1-path] = '\0';
57 p1 = strchr(path, '&');
59 p1 = strlen(path) + path;
60 (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
61 while (*path && *path != '&')
68 else if (*path == '%' && path[1] && path[2])
70 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
86 char *yaz_uri_val(const char *path, const char *name, ODR o)
88 size_t nlen = strlen(name);
94 const char *p1 = strchr(path, '=');
97 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
103 p1 = strchr(path, '&');
105 p1 = strlen(path) + path;
106 ret = (char *) odr_malloc(o, p1 - path + 1);
107 while (*path && *path != '&')
114 else if (*path == '%' && path[1] && path[2])
116 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
125 path = strchr(p1, '&');
132 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
134 const char *v = yaz_uri_val(path, name, o);
136 *intp = odr_intdup(o, atoi(v));
139 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
140 int code, const char *details)
142 d->uri = (char *) odr_malloc(o, 50);
143 sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
146 d->details = odr_strdup(o, details);
151 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
152 int *num, int code, const char *addinfo)
154 Z_SRW_diagnostic *d_new;
155 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
157 memcpy (d_new, *d, *num *sizeof(**d));
160 yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
164 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
165 Z_SOAP **soap_package, ODR decode, char **charset)
167 if (!strcmp(hreq->method, "POST"))
169 const char *content_type = z_HTTP_header_lookup(hreq->headers,
171 if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
173 char *db = "Default";
174 const char *p0 = hreq->path, *p1;
176 const char *charset_p = 0;
178 static Z_SOAP_Handler soap_handlers[3] = {
180 {"http://www.loc.gov/zing/srw/", 0,
181 (Z_SOAP_fun) yaz_srw_codec},
182 {"http://www.loc.gov/zing/srw/v1.0/", 0,
183 (Z_SOAP_fun) yaz_srw_codec},
190 p1 = strchr(p0, '?');
192 p1 = p0 + strlen(p0);
195 db = (char*) odr_malloc(decode, p1 - p0 + 1);
196 memcpy (db, p0, p1 - p0);
200 if (charset && (charset_p = strstr(content_type, "; charset=")))
204 while (i < 20 && charset_p[i] &&
205 !strchr("; \n\r", charset_p[i]))
207 *charset = (char*) odr_malloc(decode, i+1);
208 memcpy(*charset, charset_p, i);
209 (*charset)[i] = '\0';
211 ret = z_soap_codec(decode, soap_package,
212 &hreq->content_buf, &hreq->content_len,
214 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
216 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
218 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
219 (*srw_pdu)->u.request->database == 0)
220 (*srw_pdu)->u.request->database = db;
222 if ((*srw_pdu)->which == Z_SRW_explain_request &&
223 (*srw_pdu)->u.explain_request->database == 0)
224 (*srw_pdu)->u.explain_request->database = db;
226 if ((*srw_pdu)->which == Z_SRW_scan_request &&
227 (*srw_pdu)->u.scan_request->database == 0)
228 (*srw_pdu)->u.scan_request->database = db;
239 http://www.loc.gov/z3950/agency/zing/srw/service.html
241 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
242 Z_SOAP **soap_package, ODR decode, char **charset,
243 Z_SRW_diagnostic **diag, int *num_diag)
246 static Z_SOAP_Handler soap_handlers[2] = {
247 {"http://www.loc.gov/zing/srw/", 0,
248 (Z_SOAP_fun) yaz_srw_codec},
252 if (!strcmp(hreq->method, "GET"))
254 char *db = "Default";
255 const char *p0 = hreq->path, *p1;
257 const char *operation = 0;
262 char *stylesheet = 0;
263 char *scanClause = 0;
264 char *pScanClause = 0;
265 char *recordXPath = 0;
266 char *recordSchema = 0;
267 char *recordPacking = "xml"; /* xml packing is default for SRU */
268 char *maximumRecords = 0;
269 char *startRecord = 0;
270 char *maximumTerms = 0;
271 char *responsePosition = 0;
272 char *extraRequestData = 0;
281 p1 = strchr(p0, '?');
283 p1 = p0 + strlen(p0);
286 db = (char*) odr_malloc(decode, p1 - p0 + 1);
287 memcpy (db, p0, p1 - p0);
290 yaz_uri_array(p1, decode, &uri_name, &uri_val);
295 for (i = 0; uri_name[i]; i++)
297 char *n = uri_name[i];
298 char *v = uri_val[i];
299 if (!strcmp(n, "query"))
301 else if (!strcmp(n, "x-pquery"))
303 else if (!strcmp(n, "operation"))
305 else if (!strcmp(n, "stylesheet"))
307 else if (!strcmp(n, "sortKeys"))
309 else if (!strcmp(n, "recordXPath"))
311 else if (!strcmp(n, "recordSchema"))
313 else if (!strcmp(n, "recordPacking"))
315 else if (!strcmp(n, "version"))
317 else if (!strcmp(n, "scanClause"))
319 else if (!strcmp(n, "x-pScanClause"))
321 else if (!strcmp(n, "maximumRecords"))
323 else if (!strcmp(n, "startRecord"))
325 else if (!strcmp(n, "maximumTerms"))
327 else if (!strcmp(n, "responsePosition"))
328 responsePosition = v;
329 else if (!strcmp(n, "extraRequestData"))
330 extraRequestData = v;
332 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
338 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
341 if (strcmp(version, "1.1"))
342 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
346 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
347 operation = "explain";
349 if (!strcmp(operation, "searchRetrieve"))
351 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
353 sr->srw_version = version;
357 sr->u.request->query_type = Z_SRW_query_type_cql;
358 sr->u.request->query.cql = query;
362 sr->u.request->query_type = Z_SRW_query_type_pqf;
363 sr->u.request->query.pqf = pQuery;
366 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
370 sr->u.request->sort_type = Z_SRW_sort_type_sort;
371 sr->u.request->sort.sortKeys = sortKeys;
373 sr->u.request->recordXPath = recordXPath;
374 sr->u.request->recordSchema = recordSchema;
375 sr->u.request->recordPacking = recordPacking;
376 sr->u.request->stylesheet = stylesheet;
379 sr->u.request->maximumRecords =
380 odr_intdup(decode, atoi(maximumRecords));
382 sr->u.request->startRecord =
383 odr_intdup(decode, atoi(startRecord));
385 sr->u.request->database = db;
387 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
388 (*soap_package)->which = Z_SOAP_generic;
390 (*soap_package)->u.generic =
391 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
393 (*soap_package)->u.generic->p = sr;
394 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
395 (*soap_package)->u.generic->no = 0;
397 (*soap_package)->ns = "SRU";
401 else if (!strcmp(operation, "explain"))
403 /* Transfer SRU explain parameters to common struct */
404 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
405 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
407 sr->srw_version = version;
409 sr->u.explain_request->recordPacking = recordPacking;
410 sr->u.explain_request->database = db;
412 sr->u.explain_request->stylesheet = stylesheet;
414 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
415 (*soap_package)->which = Z_SOAP_generic;
417 (*soap_package)->u.generic =
418 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
420 (*soap_package)->u.generic->p = sr;
421 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
422 (*soap_package)->u.generic->no = 0;
424 (*soap_package)->ns = "SRU";
428 else if (!strcmp(operation, "scan"))
430 /* Transfer SRU scan parameters to common struct */
431 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
432 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
434 sr->srw_version = version;
439 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
440 sr->u.scan_request->scanClause.cql = scanClause;
442 else if (pScanClause)
444 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
445 sr->u.scan_request->scanClause.pqf = pScanClause;
448 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
450 sr->u.scan_request->database = db;
453 sr->u.scan_request->maximumTerms =
454 odr_intdup(decode, atoi(maximumTerms));
455 if (responsePosition)
456 sr->u.scan_request->responsePosition =
457 odr_intdup(decode, atoi(responsePosition));
459 sr->u.scan_request->stylesheet = stylesheet;
461 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
462 (*soap_package)->which = Z_SOAP_generic;
464 (*soap_package)->u.generic =
465 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
467 (*soap_package)->u.generic->p = sr;
468 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
469 (*soap_package)->u.generic->no = 0;
471 (*soap_package)->ns = "SRU";
477 /* unsupported operation ... */
478 /* Act as if we received a explain request and throw diagnostic. */
480 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
482 sr->srw_version = version;
484 sr->u.explain_request->recordPacking = recordPacking;
485 sr->u.explain_request->database = db;
487 sr->u.explain_request->stylesheet = stylesheet;
489 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
490 (*soap_package)->which = Z_SOAP_generic;
492 (*soap_package)->u.generic =
493 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
495 (*soap_package)->u.generic->p = sr;
496 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
497 (*soap_package)->u.generic->no = 0;
499 (*soap_package)->ns = "SRU";
501 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
510 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
512 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
514 sr->srw_version = odr_strdup(o, "1.1");
518 case Z_SRW_searchRetrieve_request:
519 sr->u.request = (Z_SRW_searchRetrieveRequest *)
520 odr_malloc(o, sizeof(*sr->u.request));
521 sr->u.request->query_type = Z_SRW_query_type_cql;
522 sr->u.request->query.cql = 0;
523 sr->u.request->sort_type = Z_SRW_sort_type_none;
524 sr->u.request->sort.none = 0;
525 sr->u.request->startRecord = 0;
526 sr->u.request->maximumRecords = 0;
527 sr->u.request->recordSchema = 0;
528 sr->u.request->recordPacking = 0;
529 sr->u.request->recordXPath = 0;
530 sr->u.request->database = 0;
531 sr->u.request->resultSetTTL = 0;
532 sr->u.request->stylesheet = 0;
534 case Z_SRW_searchRetrieve_response:
535 sr->u.response = (Z_SRW_searchRetrieveResponse *)
536 odr_malloc(o, sizeof(*sr->u.response));
537 sr->u.response->numberOfRecords = 0;
538 sr->u.response->resultSetId = 0;
539 sr->u.response->resultSetIdleTime = 0;
540 sr->u.response->records = 0;
541 sr->u.response->num_records = 0;
542 sr->u.response->diagnostics = 0;
543 sr->u.response->num_diagnostics = 0;
544 sr->u.response->nextRecordPosition = 0;
546 case Z_SRW_explain_request:
547 sr->u.explain_request = (Z_SRW_explainRequest *)
548 odr_malloc(o, sizeof(*sr->u.explain_request));
549 sr->u.explain_request->recordPacking = 0;
550 sr->u.explain_request->database = 0;
551 sr->u.explain_request->stylesheet = 0;
553 case Z_SRW_explain_response:
554 sr->u.explain_response = (Z_SRW_explainResponse *)
555 odr_malloc(o, sizeof(*sr->u.explain_response));
556 sr->u.explain_response->record.recordData_buf = 0;
557 sr->u.explain_response->record.recordData_len = 0;
558 sr->u.explain_response->record.recordSchema = 0;
559 sr->u.explain_response->record.recordPosition = 0;
560 sr->u.explain_response->record.recordPacking =
561 Z_SRW_recordPacking_string;
562 sr->u.explain_response->diagnostics = 0;
563 sr->u.explain_response->num_diagnostics = 0;
565 case Z_SRW_scan_request:
566 sr->u.scan_request = (Z_SRW_scanRequest *)
567 odr_malloc(o, sizeof(*sr->u.scan_request));
568 sr->u.scan_request->database = 0;
569 sr->u.scan_request->stylesheet = 0;
570 sr->u.scan_request->maximumTerms = 0;
571 sr->u.scan_request->responsePosition = 0;
572 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
573 sr->u.scan_request->scanClause.cql = 0;
575 case Z_SRW_scan_response:
576 sr->u.scan_response = (Z_SRW_scanResponse *)
577 odr_malloc(o, sizeof(*sr->u.scan_response));
578 sr->u.scan_response->terms = 0;
579 sr->u.scan_response->num_terms = 0;
580 sr->u.scan_response->diagnostics = 0;
581 sr->u.scan_response->num_diagnostics = 0;
589 static int srw_bib1_map[] = {
599 108, 10, /* Malformed query : Syntax error */
629 100, 1, /* bad map */
677 205, 1, /* bad map */
678 206, 1, /* bad map */
680 208, 1, /* bad map */
691 218, 1, /* bad map */
692 219, 1, /* bad map */
693 220, 1, /* bad map */
694 221, 1, /* bad map */
695 222, 1, /* bad map */
696 223, 1, /* bad map */
697 224, 1, /* bad map */
698 225, 1, /* bad map */
699 226, 1, /* bad map */
701 228, 1, /* bad map */
706 233, 1, /* bad map */
707 234, 1, /* bad map */
713 240, 1, /* bad map */
714 241, 1, /* bad map */
716 243, 1, /* bad map */
721 1001, 1, /* bad map */
722 1002, 1, /* bad map */
723 1003, 1, /* bad map */
724 1004, 1, /* bad map */
725 1005, 1, /* bad map */
726 1006, 1, /* bad map */
758 int yaz_diag_bib1_to_srw (int code)
760 const int *p = srw_bib1_map;
770 int yaz_diag_srw_to_bib1(int code)
772 const int *p = srw_bib1_map;