2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.24 2005-01-16 21:56:24 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;
256 const char *operation = 0;
261 char *stylesheet = 0;
262 char *scanClause = 0;
263 char *pScanClause = 0;
264 char *recordXPath = 0;
265 char *recordSchema = 0;
266 char *recordPacking = "xml"; /* xml packing is default for SRU */
267 char *maximumRecords = 0;
268 char *startRecord = 0;
269 char *maximumTerms = 0;
270 char *responsePosition = 0;
271 char *extraRequestData = 0;
279 p1 = strchr(p0, '?');
281 p1 = p0 + strlen(p0);
284 db = (char*) odr_malloc(decode, p1 - p0 + 1);
285 memcpy (db, p0, p1 - p0);
288 yaz_uri_array(p1, decode, &uri_name, &uri_val);
293 for (i = 0; uri_name[i]; i++)
295 char *n = uri_name[i];
296 char *v = uri_val[i];
297 if (!strcmp(n, "query"))
299 else if (!strcmp(n, "x-pquery"))
301 else if (!strcmp(n, "operation"))
303 else if (!strcmp(n, "stylesheet"))
305 else if (!strcmp(n, "sortKeys"))
307 else if (!strcmp(n, "recordXPath"))
309 else if (!strcmp(n, "recordSchema"))
311 else if (!strcmp(n, "recordPacking"))
313 else if (!strcmp(n, "version"))
315 else if (!strcmp(n, "scanClause"))
317 else if (!strcmp(n, "x-pScanClause"))
319 else if (!strcmp(n, "maximumRecords"))
321 else if (!strcmp(n, "startRecord"))
323 else if (!strcmp(n, "maximumTerms"))
325 else if (!strcmp(n, "responsePosition"))
326 responsePosition = v;
327 else if (!strcmp(n, "extraRequestData"))
328 extraRequestData = v;
330 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
336 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
339 if (strcmp(version, "1.1"))
340 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
344 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
345 operation = "explain";
347 if (!strcmp(operation, "searchRetrieve"))
349 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
351 sr->srw_version = version;
355 sr->u.request->query_type = Z_SRW_query_type_cql;
356 sr->u.request->query.cql = query;
360 sr->u.request->query_type = Z_SRW_query_type_pqf;
361 sr->u.request->query.pqf = pQuery;
364 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
368 sr->u.request->sort_type = Z_SRW_sort_type_sort;
369 sr->u.request->sort.sortKeys = sortKeys;
371 sr->u.request->recordXPath = recordXPath;
372 sr->u.request->recordSchema = recordSchema;
373 sr->u.request->recordPacking = recordPacking;
374 sr->u.request->stylesheet = stylesheet;
377 sr->u.request->maximumRecords =
378 odr_intdup(decode, atoi(maximumRecords));
380 sr->u.request->startRecord =
381 odr_intdup(decode, atoi(startRecord));
383 sr->u.request->database = db;
385 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
386 (*soap_package)->which = Z_SOAP_generic;
388 (*soap_package)->u.generic =
389 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
391 (*soap_package)->u.generic->p = sr;
392 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
393 (*soap_package)->u.generic->no = 0;
395 (*soap_package)->ns = "SRU";
399 else if (!strcmp(operation, "explain"))
401 /* Transfer SRU explain parameters to common struct */
402 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
403 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
405 sr->srw_version = version;
407 sr->u.explain_request->recordPacking = recordPacking;
408 sr->u.explain_request->database = db;
410 sr->u.explain_request->stylesheet = stylesheet;
412 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
413 (*soap_package)->which = Z_SOAP_generic;
415 (*soap_package)->u.generic =
416 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
418 (*soap_package)->u.generic->p = sr;
419 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
420 (*soap_package)->u.generic->no = 0;
422 (*soap_package)->ns = "SRU";
426 else if (!strcmp(operation, "scan"))
428 /* Transfer SRU scan parameters to common struct */
429 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
430 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
432 sr->srw_version = version;
437 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
438 sr->u.scan_request->scanClause.cql = scanClause;
440 else if (pScanClause)
442 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
443 sr->u.scan_request->scanClause.pqf = pScanClause;
446 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
448 sr->u.scan_request->database = db;
451 sr->u.scan_request->maximumTerms =
452 odr_intdup(decode, atoi(maximumTerms));
453 if (responsePosition)
454 sr->u.scan_request->responsePosition =
455 odr_intdup(decode, atoi(responsePosition));
457 sr->u.scan_request->stylesheet = stylesheet;
459 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
460 (*soap_package)->which = Z_SOAP_generic;
462 (*soap_package)->u.generic =
463 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
465 (*soap_package)->u.generic->p = sr;
466 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
467 (*soap_package)->u.generic->no = 0;
469 (*soap_package)->ns = "SRU";
475 /* unsupported operation ... */
476 /* Act as if we received a explain request and throw diagnostic. */
478 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
480 sr->srw_version = version;
482 sr->u.explain_request->recordPacking = recordPacking;
483 sr->u.explain_request->database = db;
485 sr->u.explain_request->stylesheet = stylesheet;
487 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
488 (*soap_package)->which = Z_SOAP_generic;
490 (*soap_package)->u.generic =
491 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
493 (*soap_package)->u.generic->p = sr;
494 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
495 (*soap_package)->u.generic->no = 0;
497 (*soap_package)->ns = "SRU";
499 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
508 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
510 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
512 sr->srw_version = odr_strdup(o, "1.1");
516 case Z_SRW_searchRetrieve_request:
517 sr->u.request = (Z_SRW_searchRetrieveRequest *)
518 odr_malloc(o, sizeof(*sr->u.request));
519 sr->u.request->query_type = Z_SRW_query_type_cql;
520 sr->u.request->query.cql = 0;
521 sr->u.request->sort_type = Z_SRW_sort_type_none;
522 sr->u.request->sort.none = 0;
523 sr->u.request->startRecord = 0;
524 sr->u.request->maximumRecords = 0;
525 sr->u.request->recordSchema = 0;
526 sr->u.request->recordPacking = 0;
527 sr->u.request->recordXPath = 0;
528 sr->u.request->database = 0;
529 sr->u.request->resultSetTTL = 0;
530 sr->u.request->stylesheet = 0;
532 case Z_SRW_searchRetrieve_response:
533 sr->u.response = (Z_SRW_searchRetrieveResponse *)
534 odr_malloc(o, sizeof(*sr->u.response));
535 sr->u.response->numberOfRecords = 0;
536 sr->u.response->resultSetId = 0;
537 sr->u.response->resultSetIdleTime = 0;
538 sr->u.response->records = 0;
539 sr->u.response->num_records = 0;
540 sr->u.response->diagnostics = 0;
541 sr->u.response->num_diagnostics = 0;
542 sr->u.response->nextRecordPosition = 0;
544 case Z_SRW_explain_request:
545 sr->u.explain_request = (Z_SRW_explainRequest *)
546 odr_malloc(o, sizeof(*sr->u.explain_request));
547 sr->u.explain_request->recordPacking = 0;
548 sr->u.explain_request->database = 0;
549 sr->u.explain_request->stylesheet = 0;
551 case Z_SRW_explain_response:
552 sr->u.explain_response = (Z_SRW_explainResponse *)
553 odr_malloc(o, sizeof(*sr->u.explain_response));
554 sr->u.explain_response->record.recordData_buf = 0;
555 sr->u.explain_response->record.recordData_len = 0;
556 sr->u.explain_response->record.recordSchema = 0;
557 sr->u.explain_response->record.recordPosition = 0;
558 sr->u.explain_response->record.recordPacking =
559 Z_SRW_recordPacking_string;
560 sr->u.explain_response->diagnostics = 0;
561 sr->u.explain_response->num_diagnostics = 0;
563 case Z_SRW_scan_request:
564 sr->u.scan_request = (Z_SRW_scanRequest *)
565 odr_malloc(o, sizeof(*sr->u.scan_request));
566 sr->u.scan_request->database = 0;
567 sr->u.scan_request->stylesheet = 0;
568 sr->u.scan_request->maximumTerms = 0;
569 sr->u.scan_request->responsePosition = 0;
570 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
571 sr->u.scan_request->scanClause.cql = 0;
573 case Z_SRW_scan_response:
574 sr->u.scan_response = (Z_SRW_scanResponse *)
575 odr_malloc(o, sizeof(*sr->u.scan_response));
576 sr->u.scan_response->terms = 0;
577 sr->u.scan_response->num_terms = 0;
578 sr->u.scan_response->diagnostics = 0;
579 sr->u.scan_response->num_diagnostics = 0;
587 static int srw_bib1_map[] = {
597 108, 10, /* Malformed query : Syntax error */
627 100, 1, /* bad map */
675 205, 1, /* bad map */
676 206, 1, /* bad map */
678 208, 1, /* bad map */
689 218, 1, /* bad map */
690 219, 1, /* bad map */
691 220, 1, /* bad map */
692 221, 1, /* bad map */
693 222, 1, /* bad map */
694 223, 1, /* bad map */
695 224, 1, /* bad map */
696 225, 1, /* bad map */
697 226, 1, /* bad map */
699 228, 1, /* bad map */
704 233, 1, /* bad map */
705 234, 1, /* bad map */
711 240, 1, /* bad map */
712 241, 1, /* bad map */
714 243, 1, /* bad map */
719 1001, 1, /* bad map */
720 1002, 1, /* bad map */
721 1003, 1, /* bad map */
722 1004, 1, /* bad map */
723 1005, 1, /* bad map */
724 1006, 1, /* bad map */
756 int yaz_diag_bib1_to_srw (int code)
758 const int *p = srw_bib1_map;
768 int yaz_diag_srw_to_bib1(int code)
770 const int *p = srw_bib1_map;