2 * Copyright (c) 2002-2004, Index Data.
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.19 2004-11-21 21:56:28 adam Exp $
9 * \brief Implements SRW/SRU utilities.
13 #include <yaz/yaz-iconv.h>
15 static int hex_digit (int ch)
17 if (ch >= '0' && ch <= '9')
19 else if (ch >= 'a' && ch <= 'f')
21 else if (ch >= 'A' && ch <= 'F')
26 int yaz_uri_array(const char *path, ODR o, char ***name, char ***val)
35 while ((cp = strchr(cp, '&')))
40 *name = odr_malloc(o, no * sizeof(char**));
41 *val = odr_malloc(o, no * sizeof(char**));
43 for (no = 0; *path; no++)
45 const char *p1 = strchr(path, '=');
51 (*name)[no] = odr_malloc(o, (p1-path)+1);
52 memcpy((*name)[no], path, p1-path);
53 (*name)[no][p1-path] = '\0';
56 p1 = strchr(path, '&');
58 p1 = strlen(path) + path;
59 (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
60 while (*path && *path != '&')
67 else if (*path == '%' && path[1] && path[2])
69 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
85 char *yaz_uri_val(const char *path, const char *name, ODR o)
87 size_t nlen = strlen(name);
93 const char *p1 = strchr(path, '=');
96 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
102 p1 = strchr(path, '&');
104 p1 = strlen(path) + path;
105 ret = (char *) odr_malloc(o, p1 - path + 1);
106 while (*path && *path != '&')
113 else if (*path == '%' && path[1] && path[2])
115 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
124 path = strchr(p1, '&');
131 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
133 const char *v = yaz_uri_val(path, name, o);
135 *intp = odr_intdup(o, atoi(v));
138 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
139 int code, const char *details)
141 d->uri = (char *) odr_malloc(o, 50);
142 sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
145 d->details = odr_strdup(o, details);
150 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
151 int *num, int code, const char *addinfo)
153 Z_SRW_diagnostic *d_new;
154 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
156 memcpy (d_new, *d, *num *sizeof(**d));
159 yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
163 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
164 Z_SOAP **soap_package, ODR decode, char **charset)
166 if (!strcmp(hreq->method, "POST"))
168 const char *content_type = z_HTTP_header_lookup(hreq->headers,
170 if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
172 char *db = "Default";
173 const char *p0 = hreq->path, *p1;
175 const char *charset_p = 0;
177 static Z_SOAP_Handler soap_handlers[3] = {
179 {"http://www.loc.gov/zing/srw/", 0,
180 (Z_SOAP_fun) yaz_srw_codec},
181 {"http://www.loc.gov/zing/srw/v1.0/", 0,
182 (Z_SOAP_fun) yaz_srw_codec},
189 p1 = strchr(p0, '?');
191 p1 = p0 + strlen(p0);
194 db = (char*) odr_malloc(decode, p1 - p0 + 1);
195 memcpy (db, p0, p1 - p0);
199 if (charset && (charset_p = strstr(content_type, "; charset=")))
203 while (i < 20 && charset_p[i] &&
204 !strchr("; \n\r", charset_p[i]))
206 *charset = (char*) odr_malloc(decode, i+1);
207 memcpy(*charset, charset_p, i);
208 (*charset)[i] = '\0';
210 ret = z_soap_codec(decode, soap_package,
211 &hreq->content_buf, &hreq->content_len,
213 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
215 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
217 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
218 (*srw_pdu)->u.request->database == 0)
219 (*srw_pdu)->u.request->database = db;
221 if ((*srw_pdu)->which == Z_SRW_explain_request &&
222 (*srw_pdu)->u.explain_request->database == 0)
223 (*srw_pdu)->u.explain_request->database = db;
225 if ((*srw_pdu)->which == Z_SRW_scan_request &&
226 (*srw_pdu)->u.scan_request->database == 0)
227 (*srw_pdu)->u.scan_request->database = db;
237 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
238 Z_SOAP **soap_package, ODR decode, char **charset,
239 Z_SRW_diagnostic **diag, int *num_diag)
242 static Z_SOAP_Handler soap_handlers[2] = {
243 {"http://www.loc.gov/zing/srw/", 0,
244 (Z_SOAP_fun) yaz_srw_codec},
248 if (!strcmp(hreq->method, "GET"))
250 char *db = "Default";
251 const char *p0 = hreq->path, *p1;
252 const char *operation = 0;
257 char *stylesheet = 0;
258 char *scanClause = 0;
259 char *recordXPath = 0;
260 char *recordSchema = 0;
261 char *recordPacking = "xml"; /* xml packing is default for SRU */
262 char *maximumRecords = 0;
263 char *startRecord = 0;
271 p1 = strchr(p0, '?');
273 p1 = p0 + strlen(p0);
276 db = (char*) odr_malloc(decode, p1 - p0 + 1);
277 memcpy (db, p0, p1 - p0);
280 yaz_uri_array(p1, decode, &uri_name, &uri_val);
285 for (i = 0; uri_name[i]; i++)
287 char *n = uri_name[i];
288 char *v = uri_val[i];
289 if (!strcmp(n, "query"))
291 else if (!strcmp(n, "x-pquery"))
293 else if (!strcmp(n, "operation"))
295 else if (!strcmp(n, "stylesheet"))
297 else if (!strcmp(n, "sortKeys"))
299 else if (!strcmp(n, "recordXPath"))
301 else if (!strcmp(n, "recordSchema"))
303 else if (!strcmp(n, "recordPacking"))
305 else if (!strcmp(n, "version"))
307 else if (!strcmp(n, "scanClause"))
309 else if (!strcmp(n, "maximumRecords"))
311 else if (!strcmp(n, "startRecord"))
314 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
320 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
323 if (strcmp(version, "1.1"))
324 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
328 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
329 operation = "explain";
331 if (!strcmp(operation, "searchRetrieve"))
333 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
335 sr->srw_version = version;
339 sr->u.request->query_type = Z_SRW_query_type_cql;
340 sr->u.request->query.cql = query;
344 sr->u.request->query_type = Z_SRW_query_type_pqf;
345 sr->u.request->query.pqf = pQuery;
348 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
352 sr->u.request->sort_type = Z_SRW_sort_type_sort;
353 sr->u.request->sort.sortKeys = sortKeys;
355 sr->u.request->recordXPath = recordXPath;
356 sr->u.request->recordSchema = recordSchema;
357 sr->u.request->recordPacking = recordPacking;
358 sr->u.request->stylesheet = stylesheet;
361 sr->u.request->maximumRecords =
362 odr_intdup(decode, atoi(maximumRecords));
364 sr->u.request->startRecord =
365 odr_intdup(decode, atoi(startRecord));
367 sr->u.request->database = db;
369 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
370 (*soap_package)->which = Z_SOAP_generic;
372 (*soap_package)->u.generic =
373 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
375 (*soap_package)->u.generic->p = sr;
376 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
377 (*soap_package)->u.generic->no = 0;
379 (*soap_package)->ns = "SRU";
383 else if (!strcmp(operation, "explain"))
385 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
387 sr->srw_version = version;
389 sr->u.explain_request->recordPacking = recordPacking;
390 sr->u.explain_request->database = db;
392 sr->u.explain_request->stylesheet = stylesheet;
394 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
395 (*soap_package)->which = Z_SOAP_generic;
397 (*soap_package)->u.generic =
398 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
400 (*soap_package)->u.generic->p = sr;
401 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
402 (*soap_package)->u.generic->no = 0;
404 (*soap_package)->ns = "SRU";
408 else if (!strcmp(operation, "scan"))
410 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
413 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
415 sr->srw_version = version;
417 sr->u.scan_request->scanClause = scanClause;
418 sr->u.scan_request->database = db;
419 sr->u.scan_request->stylesheet = stylesheet;
421 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
422 (*soap_package)->which = Z_SOAP_generic;
424 (*soap_package)->u.generic =
425 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
427 (*soap_package)->u.generic->p = sr;
428 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
429 (*soap_package)->u.generic->no = 0;
431 (*soap_package)->ns = "SRU";
437 /* unsupported operation ... */
438 /* Act as if we received a explain request and throw diagnostic. */
440 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
442 sr->srw_version = version;
444 sr->u.explain_request->recordPacking = recordPacking;
445 sr->u.explain_request->database = db;
447 sr->u.explain_request->stylesheet = stylesheet;
449 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
450 (*soap_package)->which = Z_SOAP_generic;
452 (*soap_package)->u.generic =
453 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
455 (*soap_package)->u.generic->p = sr;
456 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
457 (*soap_package)->u.generic->no = 0;
459 (*soap_package)->ns = "SRU";
461 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
470 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
472 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
474 sr->srw_version = odr_strdup(o, "1.1");
478 case Z_SRW_searchRetrieve_request:
479 sr->u.request = (Z_SRW_searchRetrieveRequest *)
480 odr_malloc(o, sizeof(*sr->u.request));
481 sr->u.request->query_type = Z_SRW_query_type_cql;
482 sr->u.request->query.cql = 0;
483 sr->u.request->sort_type = Z_SRW_sort_type_none;
484 sr->u.request->sort.none = 0;
485 sr->u.request->startRecord = 0;
486 sr->u.request->maximumRecords = 0;
487 sr->u.request->recordSchema = 0;
488 sr->u.request->recordPacking = 0;
489 sr->u.request->recordXPath = 0;
490 sr->u.request->database = 0;
491 sr->u.request->resultSetTTL = 0;
492 sr->u.request->stylesheet = 0;
494 case Z_SRW_searchRetrieve_response:
495 sr->u.response = (Z_SRW_searchRetrieveResponse *)
496 odr_malloc(o, sizeof(*sr->u.response));
497 sr->u.response->numberOfRecords = 0;
498 sr->u.response->resultSetId = 0;
499 sr->u.response->resultSetIdleTime = 0;
500 sr->u.response->records = 0;
501 sr->u.response->num_records = 0;
502 sr->u.response->diagnostics = 0;
503 sr->u.response->num_diagnostics = 0;
504 sr->u.response->nextRecordPosition = 0;
506 case Z_SRW_explain_request:
507 sr->u.explain_request = (Z_SRW_explainRequest *)
508 odr_malloc(o, sizeof(*sr->u.explain_request));
509 sr->u.explain_request->recordPacking = 0;
510 sr->u.explain_request->database = 0;
511 sr->u.explain_request->stylesheet = 0;
513 case Z_SRW_explain_response:
514 sr->u.explain_response = (Z_SRW_explainResponse *)
515 odr_malloc(o, sizeof(*sr->u.explain_response));
516 sr->u.explain_response->record.recordData_buf = 0;
517 sr->u.explain_response->record.recordData_len = 0;
518 sr->u.explain_response->record.recordSchema = 0;
519 sr->u.explain_response->record.recordPosition = 0;
520 sr->u.explain_response->record.recordPacking =
521 Z_SRW_recordPacking_string;
522 sr->u.explain_response->diagnostics = 0;
523 sr->u.explain_response->num_diagnostics = 0;
525 case Z_SRW_scan_request:
526 sr->u.scan_request = (Z_SRW_scanRequest *)
527 odr_malloc(o, sizeof(*sr->u.scan_request));
528 sr->u.scan_request->database = 0;
529 sr->u.scan_request->stylesheet = 0;
530 sr->u.scan_request->maximumTerms = 0;
531 sr->u.scan_request->responsePosition = 0;
532 sr->u.scan_request->scanClause = 0;
534 case Z_SRW_scan_response:
535 sr->u.scan_response = (Z_SRW_scanResponse *)
536 odr_malloc(o, sizeof(*sr->u.scan_response));
537 sr->u.scan_response->terms = 0;
538 sr->u.scan_response->num_terms = 0;
539 sr->u.scan_response->diagnostics = 0;
540 sr->u.scan_response->num_diagnostics = 0;
548 static int srw_bib1_map[] = {
558 108, 10, /* Malformed query : Syntax error */
588 100, 1, /* bad map */
636 205, 1, /* bad map */
637 206, 1, /* bad map */
639 208, 1, /* bad map */
650 218, 1, /* bad map */
651 219, 1, /* bad map */
652 220, 1, /* bad map */
653 221, 1, /* bad map */
654 222, 1, /* bad map */
655 223, 1, /* bad map */
656 224, 1, /* bad map */
657 225, 1, /* bad map */
658 226, 1, /* bad map */
660 228, 1, /* bad map */
665 233, 1, /* bad map */
666 234, 1, /* bad map */
672 240, 1, /* bad map */
673 241, 1, /* bad map */
675 243, 1, /* bad map */
680 1001, 1, /* bad map */
681 1002, 1, /* bad map */
682 1003, 1, /* bad map */
683 1004, 1, /* bad map */
684 1005, 1, /* bad map */
685 1006, 1, /* bad map */
717 int yaz_diag_bib1_to_srw (int code)
719 const int *p = srw_bib1_map;
729 int yaz_diag_srw_to_bib1(int code)
731 const int *p = srw_bib1_map;