2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.29 2005-08-22 20:34:21 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,
172 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
173 !yaz_strcmp_del("text/plain", content_type, "; ")))
175 char *db = "Default";
176 const char *p0 = hreq->path, *p1;
178 const char *charset_p = 0;
180 static Z_SOAP_Handler soap_handlers[3] = {
182 {"http://www.loc.gov/zing/srw/", 0,
183 (Z_SOAP_fun) yaz_srw_codec},
184 {"http://www.loc.gov/zing/srw/v1.0/", 0,
185 (Z_SOAP_fun) yaz_srw_codec},
192 p1 = strchr(p0, '?');
194 p1 = p0 + strlen(p0);
197 db = (char*) odr_malloc(decode, p1 - p0 + 1);
198 memcpy (db, p0, p1 - p0);
202 if (charset && (charset_p = strstr(content_type, "; charset=")))
206 while (i < 20 && charset_p[i] &&
207 !strchr("; \n\r", charset_p[i]))
209 *charset = (char*) odr_malloc(decode, i+1);
210 memcpy(*charset, charset_p, i);
211 (*charset)[i] = '\0';
213 ret = z_soap_codec(decode, soap_package,
214 &hreq->content_buf, &hreq->content_len,
216 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
218 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
220 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
221 (*srw_pdu)->u.request->database == 0)
222 (*srw_pdu)->u.request->database = db;
224 if ((*srw_pdu)->which == Z_SRW_explain_request &&
225 (*srw_pdu)->u.explain_request->database == 0)
226 (*srw_pdu)->u.explain_request->database = db;
228 if ((*srw_pdu)->which == Z_SRW_scan_request &&
229 (*srw_pdu)->u.scan_request->database == 0)
230 (*srw_pdu)->u.scan_request->database = db;
241 http://www.loc.gov/z3950/agency/zing/srw/service.html
243 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
244 Z_SOAP **soap_package, ODR decode, char **charset,
245 Z_SRW_diagnostic **diag, int *num_diag)
248 static Z_SOAP_Handler soap_handlers[2] = {
249 {"http://www.loc.gov/zing/srw/", 0,
250 (Z_SOAP_fun) yaz_srw_codec},
254 if (!strcmp(hreq->method, "GET") ||
255 !strcmp(hreq->method, "POST") )
257 char *db = "Default";
258 const char *p0 = hreq->path, *p1;
260 const char *operation = 0;
265 char *stylesheet = 0;
266 char *scanClause = 0;
267 char *pScanClause = 0;
268 char *recordXPath = 0;
269 char *recordSchema = 0;
270 char *recordPacking = "xml"; /* xml packing is default for SRU */
271 char *maximumRecords = 0;
272 char *startRecord = 0;
273 char *maximumTerms = 0;
274 char *responsePosition = 0;
275 char *extraRequestData = 0;
284 p1 = strchr(p0, '?');
286 p1 = p0 + strlen(p0);
289 db = (char*) odr_malloc(decode, p1 - p0 + 1);
290 memcpy (db, p0, p1 - p0);
293 if (!strcmp(hreq->method, "POST"))
294 p1 = hreq->content_buf;
295 yaz_uri_array(p1, decode, &uri_name, &uri_val);
300 for (i = 0; uri_name[i]; i++)
302 char *n = uri_name[i];
303 char *v = uri_val[i];
304 if (!strcmp(n, "query"))
306 else if (!strcmp(n, "x-pquery"))
308 else if (!strcmp(n, "operation"))
310 else if (!strcmp(n, "stylesheet"))
312 else if (!strcmp(n, "sortKeys"))
314 else if (!strcmp(n, "recordXPath"))
316 else if (!strcmp(n, "recordSchema"))
318 else if (!strcmp(n, "recordPacking"))
320 else if (!strcmp(n, "version"))
322 else if (!strcmp(n, "scanClause"))
324 else if (!strcmp(n, "x-pScanClause"))
326 else if (!strcmp(n, "maximumRecords"))
328 else if (!strcmp(n, "startRecord"))
330 else if (!strcmp(n, "maximumTerms"))
332 else if (!strcmp(n, "responsePosition"))
333 responsePosition = v;
334 else if (!strcmp(n, "extraRequestData"))
335 extraRequestData = v;
337 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
343 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
346 if (strcmp(version, "1.1"))
347 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
351 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
352 operation = "explain";
354 if (!strcmp(operation, "searchRetrieve"))
356 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
358 sr->srw_version = version;
362 sr->u.request->query_type = Z_SRW_query_type_cql;
363 sr->u.request->query.cql = query;
367 sr->u.request->query_type = Z_SRW_query_type_pqf;
368 sr->u.request->query.pqf = pQuery;
371 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
375 sr->u.request->sort_type = Z_SRW_sort_type_sort;
376 sr->u.request->sort.sortKeys = sortKeys;
378 sr->u.request->recordXPath = recordXPath;
379 sr->u.request->recordSchema = recordSchema;
380 sr->u.request->recordPacking = recordPacking;
381 sr->u.request->stylesheet = stylesheet;
384 sr->u.request->maximumRecords =
385 odr_intdup(decode, atoi(maximumRecords));
387 sr->u.request->startRecord =
388 odr_intdup(decode, atoi(startRecord));
390 sr->u.request->database = db;
392 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
393 (*soap_package)->which = Z_SOAP_generic;
395 (*soap_package)->u.generic =
396 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
398 (*soap_package)->u.generic->p = sr;
399 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
400 (*soap_package)->u.generic->no = 0;
402 (*soap_package)->ns = "SRU";
406 else if (!strcmp(operation, "explain"))
408 /* Transfer SRU explain parameters to common struct */
409 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
410 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
412 sr->srw_version = version;
414 sr->u.explain_request->recordPacking = recordPacking;
415 sr->u.explain_request->database = db;
417 sr->u.explain_request->stylesheet = stylesheet;
419 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
420 (*soap_package)->which = Z_SOAP_generic;
422 (*soap_package)->u.generic =
423 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
425 (*soap_package)->u.generic->p = sr;
426 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
427 (*soap_package)->u.generic->no = 0;
429 (*soap_package)->ns = "SRU";
433 else if (!strcmp(operation, "scan"))
435 /* Transfer SRU scan parameters to common struct */
436 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
437 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
439 sr->srw_version = version;
444 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
445 sr->u.scan_request->scanClause.cql = scanClause;
447 else if (pScanClause)
449 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
450 sr->u.scan_request->scanClause.pqf = pScanClause;
453 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
455 sr->u.scan_request->database = db;
458 sr->u.scan_request->maximumTerms =
459 odr_intdup(decode, atoi(maximumTerms));
460 if (responsePosition)
461 sr->u.scan_request->responsePosition =
462 odr_intdup(decode, atoi(responsePosition));
464 sr->u.scan_request->stylesheet = stylesheet;
466 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
467 (*soap_package)->which = Z_SOAP_generic;
469 (*soap_package)->u.generic =
470 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
472 (*soap_package)->u.generic->p = sr;
473 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
474 (*soap_package)->u.generic->no = 0;
476 (*soap_package)->ns = "SRU";
482 /* unsupported operation ... */
483 /* Act as if we received a explain request and throw diagnostic. */
485 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
487 sr->srw_version = version;
489 sr->u.explain_request->recordPacking = recordPacking;
490 sr->u.explain_request->database = db;
492 sr->u.explain_request->stylesheet = stylesheet;
494 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
495 (*soap_package)->which = Z_SOAP_generic;
497 (*soap_package)->u.generic =
498 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
500 (*soap_package)->u.generic->p = sr;
501 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
502 (*soap_package)->u.generic->no = 0;
504 (*soap_package)->ns = "SRU";
506 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
515 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
517 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
519 sr->srw_version = odr_strdup(o, "1.1");
523 case Z_SRW_searchRetrieve_request:
524 sr->u.request = (Z_SRW_searchRetrieveRequest *)
525 odr_malloc(o, sizeof(*sr->u.request));
526 sr->u.request->query_type = Z_SRW_query_type_cql;
527 sr->u.request->query.cql = 0;
528 sr->u.request->sort_type = Z_SRW_sort_type_none;
529 sr->u.request->sort.none = 0;
530 sr->u.request->startRecord = 0;
531 sr->u.request->maximumRecords = 0;
532 sr->u.request->recordSchema = 0;
533 sr->u.request->recordPacking = 0;
534 sr->u.request->recordXPath = 0;
535 sr->u.request->database = 0;
536 sr->u.request->resultSetTTL = 0;
537 sr->u.request->stylesheet = 0;
539 case Z_SRW_searchRetrieve_response:
540 sr->u.response = (Z_SRW_searchRetrieveResponse *)
541 odr_malloc(o, sizeof(*sr->u.response));
542 sr->u.response->numberOfRecords = 0;
543 sr->u.response->resultSetId = 0;
544 sr->u.response->resultSetIdleTime = 0;
545 sr->u.response->records = 0;
546 sr->u.response->num_records = 0;
547 sr->u.response->diagnostics = 0;
548 sr->u.response->num_diagnostics = 0;
549 sr->u.response->nextRecordPosition = 0;
551 case Z_SRW_explain_request:
552 sr->u.explain_request = (Z_SRW_explainRequest *)
553 odr_malloc(o, sizeof(*sr->u.explain_request));
554 sr->u.explain_request->recordPacking = 0;
555 sr->u.explain_request->database = 0;
556 sr->u.explain_request->stylesheet = 0;
558 case Z_SRW_explain_response:
559 sr->u.explain_response = (Z_SRW_explainResponse *)
560 odr_malloc(o, sizeof(*sr->u.explain_response));
561 sr->u.explain_response->record.recordData_buf = 0;
562 sr->u.explain_response->record.recordData_len = 0;
563 sr->u.explain_response->record.recordSchema = 0;
564 sr->u.explain_response->record.recordPosition = 0;
565 sr->u.explain_response->record.recordPacking =
566 Z_SRW_recordPacking_string;
567 sr->u.explain_response->diagnostics = 0;
568 sr->u.explain_response->num_diagnostics = 0;
570 case Z_SRW_scan_request:
571 sr->u.scan_request = (Z_SRW_scanRequest *)
572 odr_malloc(o, sizeof(*sr->u.scan_request));
573 sr->u.scan_request->database = 0;
574 sr->u.scan_request->stylesheet = 0;
575 sr->u.scan_request->maximumTerms = 0;
576 sr->u.scan_request->responsePosition = 0;
577 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
578 sr->u.scan_request->scanClause.cql = 0;
580 case Z_SRW_scan_response:
581 sr->u.scan_response = (Z_SRW_scanResponse *)
582 odr_malloc(o, sizeof(*sr->u.scan_response));
583 sr->u.scan_response->terms = 0;
584 sr->u.scan_response->num_terms = 0;
585 sr->u.scan_response->diagnostics = 0;
586 sr->u.scan_response->num_diagnostics = 0;
594 static int srw_bib1_map[] = {
604 108, 10, /* Malformed query : Syntax error */
634 100, 1, /* bad map */
682 205, 1, /* bad map */
683 206, 1, /* bad map */
685 208, 1, /* bad map */
696 218, 1, /* bad map */
697 219, 1, /* bad map */
698 220, 1, /* bad map */
699 221, 1, /* bad map */
700 222, 1, /* bad map */
701 223, 1, /* bad map */
702 224, 1, /* bad map */
703 225, 1, /* bad map */
704 226, 1, /* bad map */
706 228, 1, /* bad map */
711 233, 1, /* bad map */
712 234, 1, /* bad map */
718 240, 1, /* bad map */
719 241, 1, /* bad map */
721 243, 1, /* bad map */
726 1001, 1, /* bad map */
727 1002, 1, /* bad map */
728 1003, 1, /* bad map */
729 1004, 1, /* bad map */
730 1005, 1, /* bad map */
731 1006, 1, /* bad map */
763 int yaz_diag_bib1_to_srw (int code)
765 const int *p = srw_bib1_map;
775 int yaz_diag_srw_to_bib1(int code)
777 const int *p = srw_bib1_map;
790 * indent-tabs-mode: nil
792 * vim: shiftwidth=4 tabstop=8 expandtab