2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: srwutil.c,v 1.31 2005-09-12 10:23:53 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)
37 while ((cp = strchr(cp, '&')))
42 *name = odr_malloc(o, no * sizeof(char*));
43 *val = odr_malloc(o, no * sizeof(char*));
45 for (no = 0; *path; no++)
47 const char *p1 = strchr(path, '=');
53 (*name)[no] = odr_malloc(o, (p1-path)+1);
54 memcpy((*name)[no], path, p1-path);
55 (*name)[no][p1-path] = '\0';
58 p1 = strchr(path, '&');
60 p1 = strlen(path) + path;
61 (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
62 while (*path && *path != '&')
69 else if (*path == '%' && path[1] && path[2])
71 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
87 char *yaz_uri_val(const char *path, const char *name, ODR o)
89 size_t nlen = strlen(name);
95 const char *p1 = strchr(path, '=');
98 if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
104 p1 = strchr(path, '&');
106 p1 = strlen(path) + path;
107 ret = (char *) odr_malloc(o, p1 - path + 1);
108 while (*path && *path != '&')
115 else if (*path == '%' && path[1] && path[2])
117 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
126 path = strchr(p1, '&');
133 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
135 const char *v = yaz_uri_val(path, name, o);
137 *intp = odr_intdup(o, atoi(v));
140 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
141 int code, const char *details)
143 d->uri = (char *) odr_malloc(o, 50);
144 sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
147 d->details = odr_strdup(o, details);
152 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
153 int *num, int code, const char *addinfo)
155 Z_SRW_diagnostic *d_new;
156 d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
158 memcpy (d_new, *d, *num *sizeof(**d));
161 yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
165 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
166 Z_SOAP **soap_package, ODR decode, char **charset)
168 if (!strcmp(hreq->method, "POST"))
170 const char *content_type = z_HTTP_header_lookup(hreq->headers,
173 (!yaz_strcmp_del("text/xml", content_type, "; ") ||
174 !yaz_strcmp_del("text/plain", content_type, "; ")))
176 char *db = "Default";
177 const char *p0 = hreq->path, *p1;
179 const char *charset_p = 0;
181 static Z_SOAP_Handler soap_handlers[3] = {
183 {"http://www.loc.gov/zing/srw/", 0,
184 (Z_SOAP_fun) yaz_srw_codec},
185 {"http://www.loc.gov/zing/srw/v1.0/", 0,
186 (Z_SOAP_fun) yaz_srw_codec},
193 p1 = strchr(p0, '?');
195 p1 = p0 + strlen(p0);
198 db = (char*) odr_malloc(decode, p1 - p0 + 1);
199 memcpy (db, p0, p1 - p0);
203 if (charset && (charset_p = strstr(content_type, "; charset=")))
207 while (i < 20 && charset_p[i] &&
208 !strchr("; \n\r", charset_p[i]))
210 *charset = (char*) odr_malloc(decode, i+1);
211 memcpy(*charset, charset_p, i);
212 (*charset)[i] = '\0';
214 ret = z_soap_codec(decode, soap_package,
215 &hreq->content_buf, &hreq->content_len,
217 if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
219 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
221 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
222 (*srw_pdu)->u.request->database == 0)
223 (*srw_pdu)->u.request->database = db;
225 if ((*srw_pdu)->which == Z_SRW_explain_request &&
226 (*srw_pdu)->u.explain_request->database == 0)
227 (*srw_pdu)->u.explain_request->database = db;
229 if ((*srw_pdu)->which == Z_SRW_scan_request &&
230 (*srw_pdu)->u.scan_request->database == 0)
231 (*srw_pdu)->u.scan_request->database = db;
242 http://www.loc.gov/z3950/agency/zing/srw/service.html
244 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
245 Z_SOAP **soap_package, ODR decode, char **charset,
246 Z_SRW_diagnostic **diag, int *num_diag)
249 static Z_SOAP_Handler soap_handlers[2] = {
250 {"http://www.loc.gov/zing/srw/", 0,
251 (Z_SOAP_fun) yaz_srw_codec},
255 const char *content_type = z_HTTP_header_lookup(hreq->headers,
258 SRU GET: allow any content type.
259 SRU POST: we support "application/x-www-form-urlencoded";
260 not "multipart/form-data" .
262 if (!strcmp(hreq->method, "GET")
264 (!strcmp(hreq->method, "POST")
266 !yaz_strcmp_del("application/x-www-form-urlencoded",
271 char *db = "Default";
272 const char *p0 = hreq->path, *p1;
274 const char *operation = 0;
279 char *stylesheet = 0;
280 char *scanClause = 0;
281 char *pScanClause = 0;
282 char *recordXPath = 0;
283 char *recordSchema = 0;
284 char *recordPacking = "xml"; /* xml packing is default for SRU */
285 char *maximumRecords = 0;
286 char *startRecord = 0;
287 char *maximumTerms = 0;
288 char *responsePosition = 0;
289 char *extraRequestData = 0;
298 p1 = strchr(p0, '?');
300 p1 = p0 + strlen(p0);
303 db = (char*) odr_malloc(decode, p1 - p0 + 1);
304 memcpy (db, p0, p1 - p0);
307 if (!strcmp(hreq->method, "POST"))
308 p1 = hreq->content_buf;
309 yaz_uri_array(p1, decode, &uri_name, &uri_val);
314 for (i = 0; uri_name[i]; i++)
316 char *n = uri_name[i];
317 char *v = uri_val[i];
318 if (!strcmp(n, "query"))
320 else if (!strcmp(n, "x-pquery"))
322 else if (!strcmp(n, "operation"))
324 else if (!strcmp(n, "stylesheet"))
326 else if (!strcmp(n, "sortKeys"))
328 else if (!strcmp(n, "recordXPath"))
330 else if (!strcmp(n, "recordSchema"))
332 else if (!strcmp(n, "recordPacking"))
334 else if (!strcmp(n, "version"))
336 else if (!strcmp(n, "scanClause"))
338 else if (!strcmp(n, "x-pScanClause"))
340 else if (!strcmp(n, "maximumRecords"))
342 else if (!strcmp(n, "startRecord"))
344 else if (!strcmp(n, "maximumTerms"))
346 else if (!strcmp(n, "responsePosition"))
347 responsePosition = v;
348 else if (!strcmp(n, "extraRequestData"))
349 extraRequestData = v;
351 yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
357 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
360 if (strcmp(version, "1.1"))
361 yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
365 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
366 operation = "explain";
368 if (!strcmp(operation, "searchRetrieve"))
370 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
372 sr->srw_version = version;
376 sr->u.request->query_type = Z_SRW_query_type_cql;
377 sr->u.request->query.cql = query;
381 sr->u.request->query_type = Z_SRW_query_type_pqf;
382 sr->u.request->query.pqf = pQuery;
385 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
389 sr->u.request->sort_type = Z_SRW_sort_type_sort;
390 sr->u.request->sort.sortKeys = sortKeys;
392 sr->u.request->recordXPath = recordXPath;
393 sr->u.request->recordSchema = recordSchema;
394 sr->u.request->recordPacking = recordPacking;
395 sr->u.request->stylesheet = stylesheet;
398 sr->u.request->maximumRecords =
399 odr_intdup(decode, atoi(maximumRecords));
401 sr->u.request->startRecord =
402 odr_intdup(decode, atoi(startRecord));
404 sr->u.request->database = db;
406 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
407 (*soap_package)->which = Z_SOAP_generic;
409 (*soap_package)->u.generic =
410 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
412 (*soap_package)->u.generic->p = sr;
413 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
414 (*soap_package)->u.generic->no = 0;
416 (*soap_package)->ns = "SRU";
420 else if (!strcmp(operation, "explain"))
422 /* Transfer SRU explain parameters to common struct */
423 /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
424 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
426 sr->srw_version = version;
428 sr->u.explain_request->recordPacking = recordPacking;
429 sr->u.explain_request->database = db;
431 sr->u.explain_request->stylesheet = stylesheet;
433 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
434 (*soap_package)->which = Z_SOAP_generic;
436 (*soap_package)->u.generic =
437 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
439 (*soap_package)->u.generic->p = sr;
440 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
441 (*soap_package)->u.generic->no = 0;
443 (*soap_package)->ns = "SRU";
447 else if (!strcmp(operation, "scan"))
449 /* Transfer SRU scan parameters to common struct */
450 /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
451 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
453 sr->srw_version = version;
458 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
459 sr->u.scan_request->scanClause.cql = scanClause;
461 else if (pScanClause)
463 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
464 sr->u.scan_request->scanClause.pqf = pScanClause;
467 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
469 sr->u.scan_request->database = db;
472 sr->u.scan_request->maximumTerms =
473 odr_intdup(decode, atoi(maximumTerms));
474 if (responsePosition)
475 sr->u.scan_request->responsePosition =
476 odr_intdup(decode, atoi(responsePosition));
478 sr->u.scan_request->stylesheet = stylesheet;
480 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
481 (*soap_package)->which = Z_SOAP_generic;
483 (*soap_package)->u.generic =
484 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
486 (*soap_package)->u.generic->p = sr;
487 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
488 (*soap_package)->u.generic->no = 0;
490 (*soap_package)->ns = "SRU";
496 /* unsupported operation ... */
497 /* Act as if we received a explain request and throw diagnostic. */
499 Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
501 sr->srw_version = version;
503 sr->u.explain_request->recordPacking = recordPacking;
504 sr->u.explain_request->database = db;
506 sr->u.explain_request->stylesheet = stylesheet;
508 (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
509 (*soap_package)->which = Z_SOAP_generic;
511 (*soap_package)->u.generic =
512 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
514 (*soap_package)->u.generic->p = sr;
515 (*soap_package)->u.generic->ns = soap_handlers[0].ns;
516 (*soap_package)->u.generic->no = 0;
518 (*soap_package)->ns = "SRU";
520 yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
529 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
531 Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
533 sr->srw_version = odr_strdup(o, "1.1");
537 case Z_SRW_searchRetrieve_request:
538 sr->u.request = (Z_SRW_searchRetrieveRequest *)
539 odr_malloc(o, sizeof(*sr->u.request));
540 sr->u.request->query_type = Z_SRW_query_type_cql;
541 sr->u.request->query.cql = 0;
542 sr->u.request->sort_type = Z_SRW_sort_type_none;
543 sr->u.request->sort.none = 0;
544 sr->u.request->startRecord = 0;
545 sr->u.request->maximumRecords = 0;
546 sr->u.request->recordSchema = 0;
547 sr->u.request->recordPacking = 0;
548 sr->u.request->recordXPath = 0;
549 sr->u.request->database = 0;
550 sr->u.request->resultSetTTL = 0;
551 sr->u.request->stylesheet = 0;
553 case Z_SRW_searchRetrieve_response:
554 sr->u.response = (Z_SRW_searchRetrieveResponse *)
555 odr_malloc(o, sizeof(*sr->u.response));
556 sr->u.response->numberOfRecords = 0;
557 sr->u.response->resultSetId = 0;
558 sr->u.response->resultSetIdleTime = 0;
559 sr->u.response->records = 0;
560 sr->u.response->num_records = 0;
561 sr->u.response->diagnostics = 0;
562 sr->u.response->num_diagnostics = 0;
563 sr->u.response->nextRecordPosition = 0;
565 case Z_SRW_explain_request:
566 sr->u.explain_request = (Z_SRW_explainRequest *)
567 odr_malloc(o, sizeof(*sr->u.explain_request));
568 sr->u.explain_request->recordPacking = 0;
569 sr->u.explain_request->database = 0;
570 sr->u.explain_request->stylesheet = 0;
572 case Z_SRW_explain_response:
573 sr->u.explain_response = (Z_SRW_explainResponse *)
574 odr_malloc(o, sizeof(*sr->u.explain_response));
575 sr->u.explain_response->record.recordData_buf = 0;
576 sr->u.explain_response->record.recordData_len = 0;
577 sr->u.explain_response->record.recordSchema = 0;
578 sr->u.explain_response->record.recordPosition = 0;
579 sr->u.explain_response->record.recordPacking =
580 Z_SRW_recordPacking_string;
581 sr->u.explain_response->diagnostics = 0;
582 sr->u.explain_response->num_diagnostics = 0;
584 case Z_SRW_scan_request:
585 sr->u.scan_request = (Z_SRW_scanRequest *)
586 odr_malloc(o, sizeof(*sr->u.scan_request));
587 sr->u.scan_request->database = 0;
588 sr->u.scan_request->stylesheet = 0;
589 sr->u.scan_request->maximumTerms = 0;
590 sr->u.scan_request->responsePosition = 0;
591 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
592 sr->u.scan_request->scanClause.cql = 0;
594 case Z_SRW_scan_response:
595 sr->u.scan_response = (Z_SRW_scanResponse *)
596 odr_malloc(o, sizeof(*sr->u.scan_response));
597 sr->u.scan_response->terms = 0;
598 sr->u.scan_response->num_terms = 0;
599 sr->u.scan_response->diagnostics = 0;
600 sr->u.scan_response->num_diagnostics = 0;
608 static int srw_bib1_map[] = {
618 108, 10, /* Malformed query : Syntax error */
648 100, 1, /* bad map */
696 205, 1, /* bad map */
697 206, 1, /* bad map */
699 208, 1, /* bad map */
710 218, 1, /* bad map */
711 219, 1, /* bad map */
712 220, 1, /* bad map */
713 221, 1, /* bad map */
714 222, 1, /* bad map */
715 223, 1, /* bad map */
716 224, 1, /* bad map */
717 225, 1, /* bad map */
718 226, 1, /* bad map */
720 228, 1, /* bad map */
725 233, 1, /* bad map */
726 234, 1, /* bad map */
732 240, 1, /* bad map */
733 241, 1, /* bad map */
735 243, 1, /* bad map */
740 1001, 1, /* bad map */
741 1002, 1, /* bad map */
742 1003, 1, /* bad map */
743 1004, 1, /* bad map */
744 1005, 1, /* bad map */
745 1006, 1, /* bad map */
777 int yaz_diag_bib1_to_srw (int code)
779 const int *p = srw_bib1_map;
789 int yaz_diag_srw_to_bib1(int code)
791 const int *p = srw_bib1_map;
804 * indent-tabs-mode: nil
806 * vim: shiftwidth=4 tabstop=8 expandtab