From: Adam Dickmeiss Date: Wed, 12 Feb 2003 15:06:42 +0000 (+0000) Subject: SOAP, SRW codecs and HTTP transport for YAZ using libxml2. X-Git-Tag: YAZ.2.0~49 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=c620a713f1418315efcd4e6fab225e036775d365 SOAP, SRW codecs and HTTP transport for YAZ using libxml2. Updated ASN.1 for Z39.50 amendment String Identifiers for Schemas. --- diff --git a/CHANGELOG b/CHANGELOG index 0bbd392..29dc685 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,9 +3,8 @@ Possible compatibility problems with earlier versions marked with '*'. --- 1.9.3 2003/MM/DD Support for SRW 1.0. This is an optional feature and requires -gSOAP to operate. Enable it by specifying --with-gsoap for -configure. SRW stuff is located in sub directory srw. -Example applications are located in srwapps. +libxml and libxslt to operate. Enable it by specifying --with-xslt for +configure. Z39.50 Query Type-104 added - to facilitate CQL within Z39.50. diff --git a/Makefile.am b/Makefile.am index 4c1ea35..bf83b43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,10 +1,10 @@ ## Copyright (C) 1994-2003, Index Data ## All rights reserved. -## $Id: Makefile.am,v 1.18 2003-01-06 08:20:26 adam Exp $ +## $Id: Makefile.am,v 1.19 2003-02-12 15:06:42 adam Exp $ AUTOMAKE_OPTIONS = foreign -SUBDIRS = util odr comstack z39.50 ill srw zutil ccl cql server include lib client ztest zoom srwapps doc etc +SUBDIRS = util odr comstack z39.50 ill zutil ccl cql server include lib client ztest zoom doc etc aclocaldir=$(datadir)/aclocal diff --git a/client/client.c b/client/client.c index bb3b465..ddeacaf 100644 --- a/client/client.c +++ b/client/client.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: client.c,v 1.179 2003-01-27 21:31:35 adam Exp $ + * $Id: client.c,v 1.180 2003-02-12 15:06:43 adam Exp $ */ #include @@ -1788,13 +1788,14 @@ static int send_presentRequest(char *arg) compo.u.complex->generic = (Z_Specification *) odr_malloc(out, sizeof(*compo.u.complex->generic)); - compo.u.complex->generic->schema = (Odr_oid *) + compo.u.complex->generic->which = Z_Specification_oid; + compo.u.complex->generic->u.oid = (Odr_oid *) odr_oiddup(out, oid_ent_to_oid(&prefschema, oid)); - if (!compo.u.complex->generic->schema) + if (!compo.u.complex->generic->u.oid) { /* OID wasn't a schema! Try record syntax instead. */ prefschema.oclass = CLASS_RECSYN; - compo.u.complex->generic->schema = (Odr_oid *) + compo.u.complex->generic->u.oid = (Odr_oid *) odr_oiddup(out, oid_ent_to_oid(&prefschema, oid)); } if (!elementSetNames) diff --git a/configure.in b/configure.in index f8a4a0e..4763db1 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl YAZ Toolkit, Index Data 1994-2003 dnl See the file LICENSE for details. -dnl $Id: configure.in,v 1.102 2003-02-10 08:59:00 adam Exp $ +dnl $Id: configure.in,v 1.103 2003-02-12 15:06:42 adam Exp $ AC_INIT(include/yaz/yaz-version.h) AM_INIT_AUTOMAKE(yaz, 1.9.3) dnl @@ -308,35 +308,6 @@ if test "$enable_threads" = "yes" -a "$HAVETHREADS" = "0"; then fi AM_CONDITIONAL(ISTHR, test $HAVETHREADS = "1") dnl -dnl ----- gSOAP -AC_SUBST(GSOAP_LIB) -AC_SUBST(GSOAP_INCLUDE) -AC_SUBST(GSOAP_PREFIX) -gsoapdir=NONE -AC_ARG_WITH(gsoap, [ --with-gsoap[=PREFIX] Use gSOAP in PREFIX/{lib,include}],[gsoapdir=$withval]) -if test "x$gsoapdir" = "xNONE"; then - for d in /usr /usr/local; do - if test -f $d/include/stdsoap2.h; then - gsoapdir=$d - fi - done -fi -AC_MSG_CHECKING(for gSOAP prefix) -GSOAP_PREFIX=$gsoapdir -if test -x $gsoapdir/bin/soapcpp2; then - AC_MSG_RESULT($gsoapdir) - if test "$gsoapdir" != "/usr"; then - GSOAP_LIB="-L$gsoapdir/lib -lgsoap" - GSOAP_INCLUDE=-I$gsoapdir/include - fi - AC_DEFINE(HAVE_GSOAP) - usesrw=1 -else - AC_MSG_RESULT(Not found) - usesrw=0 -fi -AM_CONDITIONAL(SRW, test $usesrw = "1") -dnl dnl ----- XML/XSLT AC_SUBST(XSLT_LIB) AC_SUBST(XSLT_CFLAGS) @@ -384,7 +355,6 @@ yaz.spec util/Makefile odr/Makefile z39.50/Makefile -srw/Makefile ill/Makefile zutil/Makefile comstack/Makefile @@ -393,7 +363,6 @@ cql/Makefile server/Makefile include/Makefile include/yaz/Makefile -srwapps/Makefile lib/Makefile client/Makefile ztest/Makefile diff --git a/include/yaz/Makefile.am b/include/yaz/Makefile.am index 5bf7713..db28269 100644 --- a/include/yaz/Makefile.am +++ b/include/yaz/Makefile.am @@ -1,8 +1,8 @@ -## $Id: Makefile.am,v 1.19 2003-01-06 08:20:27 adam Exp $ +## $Id: Makefile.am,v 1.20 2003-02-12 15:06:43 adam Exp $ pkginclude_HEADERS= backend.h ccl.h cql.h comstack.h \ diagbib1.h sortspec.h log.h logrpn.h marcdisp.h nmem.h odr.h oid.h \ - options.h otherinfo.h pquery.h prt-ext.h readconf.h srw-util.h statserv.h \ + options.h otherinfo.h pquery.h prt-ext.h readconf.h statserv.h \ tcpip.h unix.h tpath.h wrbuf.h xmalloc.h \ yaz-ccl.h yaz-iconv.h yaz-util.h yaz-version.h yconfig.h proto.h \ \ @@ -11,5 +11,5 @@ pkginclude_HEADERS= backend.h ccl.h cql.h comstack.h \ z-grs.h z-mterm2.h z-opac.h z-rrf1.h z-rrf2.h z-sum.h z-sutrs.h z-uifr1.h \ z-univ.h zes-expi.h zes-exps.h zes-order.h zes-pquery.h \ zes-psched.h zes-admin.h zes-pset.h zes-update.h zes-update0.h \ - zoom.h z-charneg.h charneg.h + zoom.h z-charneg.h charneg.h soap.h srw.h diff --git a/include/yaz/backend.h b/include/yaz/backend.h index 27343c2..1e0ffff 100644 --- a/include/yaz/backend.h +++ b/include/yaz/backend.h @@ -23,7 +23,7 @@ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * - * $Id: backend.h,v 1.17 2003-01-06 08:20:27 adam Exp $ + * $Id: backend.h,v 1.18 2003-02-12 15:06:43 adam Exp $ */ #ifndef BACKEND_H @@ -259,8 +259,38 @@ typedef struct statserv_options_block char service_dependencies[128]; /* The services we are dependent on */ char service_display_name[128]; /* The service display name */ #endif /* WIN32 */ + struct bend_soap_handler *soap_handlers; } statserv_options_block; +struct bend_http_rr { + void *handle; + ODR stream; /* encoding stream */ + ODR decode; /* decoding stream */ + ODR print; /* print stream */ + Z_HTTP_Request *hreq; /* whole HTTP request */ + char *buf; + int len; +}; + +struct bend_soap_rr { + void *handle; /* user handle */ + ODR stream; + ODR decode; + ODR print; + const char *ns_env; /* SOAP NS */ + const char *ns_enc; /* SOAP Encoding NS */ + void *request_method; + void *response_body; + char *fault_code; + char *fault_string; +}; + +struct bend_soap_handler { + char *ns; + int (*handler)(struct bend_soap_rr *rr); + struct bend_soap_handler *next; +}; + YAZ_EXPORT int statserv_main( int argc, char **argv, bend_initresult *(*bend_init)(bend_initrequest *r), @@ -271,6 +301,9 @@ YAZ_EXPORT statserv_options_block *statserv_getcontrol(void); YAZ_EXPORT void statserv_setcontrol(statserv_options_block *block); YAZ_EXPORT int check_ip_tcpd(void *cd, const char *addr, int len, int type); +YAZ_EXPORT void statserv_add_soap_handler(int (*h)(struct bend_soap_rr *rr), + const char *ns); + YAZ_END_CDECL #endif diff --git a/include/yaz/odr.h b/include/yaz/odr.h index 629b7f6..a95d9e1 100644 --- a/include/yaz/odr.h +++ b/include/yaz/odr.h @@ -23,7 +23,7 @@ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * - * $Id: odr.h,v 1.7 2003-01-06 08:20:27 adam Exp $ + * $Id: odr.h,v 1.8 2003-02-12 15:06:43 adam Exp $ */ #ifndef ODR_H @@ -178,6 +178,7 @@ typedef struct odr_arm #define OSTACK 9 #define OCONLEN 10 #define OLENOV 11 +#define OHTTP 12 extern char *odr_errlist[]; diff --git a/include/yaz/proto.h b/include/yaz/proto.h index cf3858b..f1bf623 100644 --- a/include/yaz/proto.h +++ b/include/yaz/proto.h @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: proto.h,v 1.6 2003-01-06 08:20:27 adam Exp $ + * $Id: proto.h,v 1.7 2003-02-12 15:06:43 adam Exp $ */ #ifndef Z_PROTO_H #define Z_PROTO_H @@ -110,6 +110,51 @@ YAZ_EXPORT const char* yaz_z3950_oid_value_to_str(oid_value ov, oid_class oc); YAZ_EXPORT void yaz_display_grs1(WRBUF wrbuf, Z_GenericRecord *r, int flags); +typedef struct Z_HTTP_Header Z_HTTP_Header; + +struct Z_HTTP_Header { + char *name; + char *value; + Z_HTTP_Header *next; +}; + +typedef struct { + char *method; + char *version; + char *path; + Z_HTTP_Header *headers; + char *content_buf; + int content_len; +} Z_HTTP_Request; + +typedef struct { + int code; + char *version; + Z_HTTP_Header *headers; + char *content_buf; + int content_len; +} Z_HTTP_Response; + +#define Z_GDU_Z3950 1 +#define Z_GDU_HTTP_Request 2 +#define Z_GDU_HTTP_Response 3 +typedef struct { + int which; + union { + Z_APDU *z3950; + Z_HTTP_Request *HTTP_Request; + Z_HTTP_Response *HTTP_Response; + } u; +} Z_GDU ; +YAZ_EXPORT int z_GDU (ODR o, Z_GDU **p, int opt, const char *name); +YAZ_EXPORT void z_HTTP_header_add(ODR o, Z_HTTP_Header **hp, const char *n, + const char *v); +YAZ_EXPORT const char *z_HTTP_header_lookup(Z_HTTP_Header *hp, const char *n); + +YAZ_EXPORT const char *z_HTTP_errmsg(int code); + +YAZ_EXPORT Z_GDU *z_get_HTTP_Response(ODR o, int code); + YAZ_END_CDECL #include diff --git a/include/yaz/soap.h b/include/yaz/soap.h new file mode 100644 index 0000000..9c60462 --- /dev/null +++ b/include/yaz/soap.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002-2003, Index Data. + * See the file LICENSE for details. + * + * $Id: soap.h,v 1.1 2003-02-12 15:06:43 adam Exp $ + */ + +#ifndef YAZ_SOAP_H +#define YAZ_SOAP_H + +#include + +#if HAVE_XSLT +#include +#include +#endif + +typedef struct { + char *fault_code; + char *fault_string; + char *details; +} Z_SOAP_Fault; + +typedef struct { + int no; + char *ns; + void *p; +} Z_SOAP_Generic; + +#define Z_SOAP_fault 1 +#define Z_SOAP_generic 2 +#define Z_SOAP_error 3 +typedef struct { + int which; + union { + Z_SOAP_Fault *fault; + Z_SOAP_Generic *generic; + Z_SOAP_Fault *soap_error; + } u; + const char *ns; +} Z_SOAP; + +typedef struct { + char *ns; + void *client_data; + int (*f)(ODR o, xmlNodePtr ptr, void **handler_data, + void *client_data, const char *ns); +} Z_SOAP_Handler; + +YAZ_EXPORT int z_soap_codec(ODR o, Z_SOAP **pp, + char **content_buf, int *content_len, + Z_SOAP_Handler *handlers); + +#endif diff --git a/include/yaz/srw-util.h b/include/yaz/srw-util.h deleted file mode 100644 index a180c0a..0000000 --- a/include/yaz/srw-util.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $Id: srw-util.h,v 1.2 2003-01-20 13:04:50 adam Exp $ - Copyright (C) 2002-2003 - Index Data Aps - -This file is part of the YAZ toolkit. - -See the file LICENSE. -*/ - -#include "srw_H.h" -#include -struct cql_node *xcql_to_cqlnode(struct xcql__operandType *p); - -typedef struct xslt_maps_info *xslt_maps; -typedef struct xslt_map_result_info *xslt_map_result; - -xslt_maps xslt_maps_create(void); -int xslt_maps_file(xslt_maps m, const char *f); -void xslt_maps_free(xslt_maps m); - -xslt_map_result xslt_map (xslt_maps m, const char *schema_source, - const char *scheme_target, - const char *in_buf, int in_len); -void xslt_map_free (xslt_map_result res); - -char *xslt_map_result_buf(xslt_map_result res); -int xslt_map_result_len(xslt_map_result res); -char *xslt_map_result_schema(xslt_map_result res); -const char *yaz_srw_diag_str (int code); - -void yaz_srw_serve (struct soap *soap, - int (*sr_h)(void *userinfo, - struct soap * soap, - xsd__string *query, - struct xcql__operandType *xQuery, - xsd__string *sortKeys, - struct xsort__xSortKeysType *xSortKeys, - xsd__integer *startRecord, - xsd__integer *maximumRecords, - xsd__string *recordSchema, - xsd__string *recordPacking, - struct zs__searchRetrieveResponse *res), - int (*e_h)(void *userinfo, - struct soap *soap, - struct zs__explainResponse *explainResponse)); - -extern struct Namespace srw_namespaces[]; diff --git a/include/yaz/srw.h b/include/yaz/srw.h new file mode 100644 index 0000000..5f29e40 --- /dev/null +++ b/include/yaz/srw.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2003, Index Data. + * See the file LICENSE for details. + * + * $Id: srw.h,v 1.1 2003-02-12 15:06:43 adam Exp $ + */ + +#ifndef YAZ_SRW_H +#define YAZ_SRW_H + +#include + +typedef struct { + char *recordSchema; + char *recordData_buf; + int recordData_len; + int *recordPosition; +} Z_SRW_record; + +typedef struct { + int *code; + char *details; +} Z_SRW_diagnostic; + +typedef struct { + char *query; + char *pQuery; + void *xQuery; + char *sortKeys; + void *xSortKeys; + int *startRecord; + int *maximumRecords; + char *recordSchema; + char *recordPacking; +} Z_SRW_searchRetrieveRequest; + +typedef struct { + int * numberOfRecords; + char * resultSetId; + int * resultSetIdleTime; + + Z_SRW_record *records; + int num_records; + + Z_SRW_diagnostic *diagnostics; + int num_diagnostics; + int *nextRecordPosition; +} Z_SRW_searchRetrieveResponse; + +#define Z_SRW_searchRetrieve_request 1 +#define Z_SRW_searchRetrieve_response 2 + +typedef struct { + int which; + union { + Z_SRW_searchRetrieveRequest *request; + Z_SRW_searchRetrieveResponse *response; + } u; +} Z_SRW_searchRetrieve; + +YAZ_EXPORT int yaz_srw_codec(ODR o, xmlNodePtr pptr, + Z_SRW_searchRetrieve **handler_data, + void *client_data, const char *ns); +YAZ_EXPORT Z_SRW_searchRetrieve *yaz_srw_get(ODR o, int which); +#endif diff --git a/include/yaz/yaz-iconv.h b/include/yaz/yaz-iconv.h index a039280..322f7f7 100644 --- a/include/yaz/yaz-iconv.h +++ b/include/yaz/yaz-iconv.h @@ -23,7 +23,7 @@ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. * - * $Id: yaz-iconv.h,v 1.2 2003-01-06 08:20:27 adam Exp $ + * $Id: yaz-iconv.h,v 1.3 2003-02-12 15:06:43 adam Exp $ */ #ifndef YAZ_ICONV_H @@ -49,6 +49,8 @@ YAZ_EXPORT int yaz_iconv_isbuiltin(yaz_iconv_t cd); YAZ_EXPORT int yaz_matchstr(const char *s1, const char *s2); +YAZ_EXPORT int yaz_strcmp_del(const char *a, const char *b, const char *b_del); + YAZ_END_CDECL #endif diff --git a/lib/Makefile.am b/lib/Makefile.am index 8fd9e3b..549ce23 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,10 +1,4 @@ -## $Id: Makefile.am,v 1.25 2003-01-06 08:20:27 adam Exp $ - -if SRW -libsrw=../srw/libsrw.la -else -libsrw= -endif +## $Id: Makefile.am,v 1.26 2003-02-12 15:06:43 adam Exp $ if ISTHR extra=libyazthread.la @@ -81,5 +75,5 @@ tcpip.o: $(top_srcdir)/comstack/tcpip.c libyaz_la_LIBADD=../odr/libodr.la \ ../comstack/libcomstack.la ../server/libserver.la \ ../util/libutil.la ../ccl/libccl.la ../cql/libcql.la ../zutil/libzutil.la \ - ../ill/libill.la ../z39.50/libz39.50.la $(libsrw) + ../ill/libill.la ../z39.50/libz39.50.la diff --git a/odr/ber_any.c b/odr/ber_any.c index 1280040..5328dee 100644 --- a/odr/ber_any.c +++ b/odr/ber_any.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: ber_any.c,v 1.20 2003-01-06 08:20:27 adam Exp $ + * $Id: ber_any.c,v 1.21 2003-02-12 15:06:43 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -47,6 +47,47 @@ int completeBER(const unsigned char *buf, int len) return 0; if (!buf[0] && !buf[1]) return 0; + if (len > 5 && buf[0] >= 0x20 && buf[0] < 0x7f + && buf[1] >= 0x20 && buf[1] < 0x7f + && buf[2] >= 0x20 && buf[2] < 0x7f) + { + /* deal with HTTP request/response */ + int i = 2, content_len = 0; + + while (i <= len-4) + { + if (buf[i] == '\r' && buf[i+1] == '\n') + { + i += 2; + if (buf[i] == '\r' && buf[i+1] == '\n') + { + /* i += 2 seems not to work with GCC -O2 .. + so i+2 is used instead .. */ + if (len >= (i+2)+ content_len) + return (i+2)+ content_len; + break; + } + if (i < len-18) + { + if (!memcmp(buf+i, "Content-Length:", 15)) + { + i+= 15; + if (buf[i] == ' ') + i++; + content_len = 0; + while (i <= len-4 && isdigit(buf[i])) + content_len = content_len*10 + (buf[i++] - '0'); + if (content_len < 0) /* prevent negative offsets */ + content_len = 0; + } + } + } + else + i++; + } + return 0; + } + /* BER from now on .. */ if ((res = ber_dectag(b, &zclass, &tag, &cons)) <= 0) return 0; if (res > len) diff --git a/odr/odr.c b/odr/odr.c index 22f9b21..1f8a625 100644 --- a/odr/odr.c +++ b/odr/odr.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: odr.c,v 1.39 2003-01-06 08:20:27 adam Exp $ + * $Id: odr.c,v 1.40 2003-02-12 15:06:43 adam Exp $ * */ #if HAVE_CONFIG_H @@ -35,7 +35,8 @@ char *odr_errlist[] = "Malformed data", "Stack overflow", "Length of constructed type different from sum of members", - "Overflow writing definite length of constructed type" + "Overflow writing definite length of constructed type", + "HTTP Bad Request" }; char *odr_errmsg(int n) diff --git a/server/Makefile.am b/server/Makefile.am index 9c209d5..9bc6a8a 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.7 2002-09-11 21:25:57 adam Exp $ +## $Id: Makefile.am,v 1.8 2003-02-12 15:06:43 adam Exp $ noinst_LTLIBRARIES=libserver.la @@ -7,4 +7,4 @@ libserver_la_SOURCES = eventl.c seshigh.c statserv.c requestq.c tcpdchk.c \ EXTRA_DIST=service.c -AM_CPPFLAGS=-I$(top_srcdir)/include +AM_CPPFLAGS=-I$(top_srcdir)/include $(XSLT_CFLAGS) diff --git a/server/eventl.c b/server/eventl.c index ce38bd8..541bba4 100644 --- a/server/eventl.c +++ b/server/eventl.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 1995-2001, Index Data + * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: eventl.c,v 1.34 2002-11-26 16:56:21 adam Exp $ + * $Id: eventl.c,v 1.35 2003-02-12 15:06:43 adam Exp $ */ #include @@ -74,6 +74,8 @@ int event_loop(IOCHAN *iochans) max = 0; for (p = *iochans; p; p = p->next) { + yaz_log(LOG_LOG, "fd=%d flags=%d force_event=%d", + p->fd, p->flags, p->force_event); if (p->force_event) timeout = &nullto; /* polling select */ if (p->flags & EVENT_INPUT) @@ -85,7 +87,9 @@ int event_loop(IOCHAN *iochans) if (p->fd > max) max = p->fd; } + yaz_log(LOG_LOG, "select start"); res = YAZ_EV_SELECT(max + 1, &in, &out, &except, timeout); + yaz_log(LOG_LOG, "select end"); if (res < 0) { if (yaz_errno() == EINTR) diff --git a/server/eventl.h b/server/eventl.h index db3e636..95e45a4 100644 --- a/server/eventl.h +++ b/server/eventl.h @@ -1,44 +1,9 @@ /* - * Copyright (c) 1995-1999, Index Data + * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Log: eventl.h,v $ - * Revision 1.11 1999-04-20 09:56:48 adam - * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun). - * Modified all encoders/decoders to reflect this change. - * - * Revision 1.10 1998/01/29 13:30:23 adam - * Better event handle system for NT/Unix. - * - * Revision 1.9 1997/09/01 09:31:48 adam - * Removed definition statserv_remove from statserv.h to eventl.h. - * - * Revision 1.8 1995/06/19 12:39:09 quinn - * Fixed bug in timeout code. Added BER dumper. - * - * Revision 1.7 1995/06/16 10:31:34 quinn - * Added session timeout. - * - * Revision 1.6 1995/05/16 08:51:02 quinn - * License, documentation, and memory fixes - * - * Revision 1.5 1995/05/15 11:56:37 quinn - * Asynchronous facilities. Restructuring of seshigh code. - * - * Revision 1.4 1995/03/27 08:34:23 quinn - * Added dynamic server functionality. - * Released bindings to session.c (is now redundant) - * - * Revision 1.3 1995/03/15 08:37:42 quinn - * Now we're pretty much set for nonblocking I/O. - * - * Revision 1.2 1995/03/14 10:28:00 quinn - * More work on demo server. - * - * Revision 1.1 1995/03/10 18:22:45 quinn - * The rudiments of an asynchronous server. - * + * $Id: eventl.h,v 1.12 2003-02-12 15:06:43 adam Exp $ */ #ifndef EVENTL_H diff --git a/server/requestq.c b/server/requestq.c index 7c8ee00..26d9b43 100644 --- a/server/requestq.c +++ b/server/requestq.c @@ -4,7 +4,11 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: requestq.c,v $ - * Revision 1.8 2001-07-19 19:51:41 adam + * Revision 1.9 2003-02-12 15:06:43 adam + * SOAP, SRW codecs and HTTP transport for YAZ using libxml2. + * Updated ASN.1 for Z39.50 amendment String Identifiers for Schemas. + * + * Revision 1.8 2001/07/19 19:51:41 adam * Added typecasts to make C++ happy. * * Revision 1.7 1999/11/30 13:47:12 adam @@ -108,6 +112,7 @@ request *request_get(request_q *q) r->q = q; r->len_refid = 0; r->refid = 0; + r->gdu_request = 0; r->apdu_request = 0; r->request_mem = 0; r->len_response = 0; diff --git a/server/seshigh.c b/server/seshigh.c index 59361f5..9ba52f6 100644 --- a/server/seshigh.c +++ b/server/seshigh.c @@ -2,7 +2,7 @@ * Copyright (c) 1995-2003, Index Data * See the file LICENSE for details. * - * $Id: seshigh.c,v 1.133 2003-01-06 08:20:28 adam Exp $ + * $Id: seshigh.c,v 1.134 2003-02-12 15:06:43 adam Exp $ */ /* @@ -48,12 +48,16 @@ #include #include #include +#include +#include #include -static int process_request(association *assoc, request *req, char **msg); +static void process_gdu_request(association *assoc, request *req); +static int process_z_request(association *assoc, request *req, char **msg); void backend_response(IOCHAN i, int event); -static int process_response(association *assoc, request *req, Z_APDU *res); +static int process_gdu_response(association *assoc, request *req, Z_GDU *res); +static int process_z_response(association *assoc, request *req, Z_APDU *res); static Z_APDU *process_initRequest(association *assoc, request *reqb); static Z_APDU *process_searchRequest(association *assoc, request *reqb, int *fd); @@ -72,9 +76,7 @@ static Z_APDU *process_segmentRequest (association *assoc, request *reqb); static FILE *apduf = 0; /* for use in static mode */ static statserv_options_block *control_block = 0; -/* Chas: Added in from DALI */ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd); -/* Chas: End of addition from DALI */ /* * Create and initialize a new association-handle. @@ -195,7 +197,7 @@ static void do_close_req(association *a, int reason, char *message, apdu.u.close = cls; *cls->closeReason = reason; cls->diagnosticInformation = message; - process_response(a, req, &apdu); + process_z_response(a, req, &apdu); iochan_settimeout(a->client_chan, 60); } else @@ -305,22 +307,34 @@ void ir_session(IOCHAN h, int event) iochan_setevent(h, EVENT_INPUT); /* we got a complete PDU. Let's decode it */ - yaz_log(LOG_DEBUG, "Got PDU, %d bytes", res); + yaz_log(LOG_DEBUG, "Got PDU, %d bytes: lead=%02X %02X %02X", res, + assoc->input_buffer[0] & 0xff, + assoc->input_buffer[1] & 0xff, + assoc->input_buffer[2] & 0xff); req = request_get(&assoc->incoming); /* get a new request structure */ odr_reset(assoc->decode); odr_setbuf(assoc->decode, assoc->input_buffer, res, 0); - if (!z_APDU(assoc->decode, &req->apdu_request, 0, 0)) + if (!z_GDU(assoc->decode, &req->gdu_request, 0, 0)) { yaz_log(LOG_LOG, "ODR error on incoming PDU: %s [near byte %d] ", odr_errmsg(odr_geterror(assoc->decode)), odr_offset(assoc->decode)); - yaz_log(LOG_LOG, "PDU dump:"); - odr_dumpBER(yaz_log_file(), assoc->input_buffer, res); - do_close(assoc, Z_Close_protocolError, "Malformed package"); + if (assoc->decode->error != OHTTP) + { + yaz_log(LOG_LOG, "PDU dump:"); + odr_dumpBER(yaz_log_file(), assoc->input_buffer, res); + do_close(assoc, Z_Close_protocolError, "Malformed package"); + } + else + { + Z_GDU *p = z_get_HTTP_Response(assoc->encode, 400); + assoc->state = ASSOC_DEAD; + process_gdu_response(assoc, req, p); + } return; } req->request_mem = odr_extract_mem(assoc->decode); - if (assoc->print && !z_APDU(assoc->print, &req->apdu_request, 0, 0)) + if (assoc->print && !z_GDU(assoc->print, &req->gdu_request, 0, 0)) { yaz_log(LOG_WARN, "ODR print error: %s", odr_errmsg(odr_geterror(assoc->print))); @@ -333,10 +347,8 @@ void ir_session(IOCHAN h, int event) req = request_head(&assoc->incoming); if (req->state == REQUEST_IDLE) { - char *msg; request_deq(&assoc->incoming); - if (process_request(assoc, req, &msg) < 0) - do_close_req(assoc, Z_Close_systemProblem, msg, req); + process_gdu_request(assoc, req); } } if (event & assoc->cs_put_mask) @@ -345,7 +357,7 @@ void ir_session(IOCHAN h, int event) assoc->cs_put_mask = 0; yaz_log(LOG_DEBUG, "ir_session (output)"); - req->state = REQUEST_PENDING; + req->state = REQUEST_PENDING; switch (res = cs_put(conn, req->response, req->len_response)) { case -1: @@ -356,6 +368,10 @@ void ir_session(IOCHAN h, int event) break; case 0: /* all sent - release the request structure */ yaz_log(LOG_DEBUG, "Wrote PDU, %d bytes", req->len_response); +#if 0 + yaz_log(LOG_DEBUG, "HTTP out:\n%.*s", req->len_response, + req->response); +#endif nmem_destroy(req->request_mem); request_deq(&assoc->outgoing); request_release(req); @@ -363,9 +379,15 @@ void ir_session(IOCHAN h, int event) { /* restore mask for cs_get operation ... */ iochan_clearflag(h, EVENT_OUTPUT|EVENT_INPUT); iochan_setflag(h, assoc->cs_get_mask); + yaz_log(LOG_LOG, "queue empty mask=%d", assoc->cs_get_mask); + if (assoc->state == ASSOC_DEAD) + iochan_setevent(assoc->client_chan, EVENT_TIMEOUT); } else + { assoc->cs_put_mask = EVENT_OUTPUT; + yaz_log(LOG_LOG, "queue not empty"); + } break; default: if (conn->io_pending & CS_WANT_WRITE) @@ -384,10 +406,341 @@ void ir_session(IOCHAN h, int event) } } +static int process_z_request(association *assoc, request *req, char **msg); + +static int srw_bend_init(association *assoc) +{ + bend_initresult *binitres; + statserv_options_block *cb = statserv_getcontrol(); + + assoc->init = (bend_initrequest *) xmalloc (sizeof(*assoc->init)); + + assoc->init->stream = assoc->encode; + assoc->init->print = assoc->print; + assoc->init->auth = 0; + assoc->init->referenceId = 0; + assoc->init->implementation_version = 0; + assoc->init->implementation_id = 0; + assoc->init->implementation_name = 0; + assoc->init->bend_sort = NULL; + assoc->init->bend_search = NULL; + assoc->init->bend_present = NULL; + assoc->init->bend_esrequest = NULL; + assoc->init->bend_delete = NULL; + assoc->init->bend_scan = NULL; + assoc->init->bend_segment = NULL; + assoc->init->bend_fetch = NULL; + assoc->init->charneg_request = NULL; + assoc->init->charneg_response = NULL; + assoc->init->decode = assoc->decode; + + assoc->init->peer_name = + odr_strdup (assoc->encode, cs_addrstr(assoc->client_link)); + if (!(binitres = (*cb->bend_init)(assoc->init))) + { + yaz_log(LOG_WARN, "Bad response from backend."); + return 0; + } + assoc->backend = binitres->handle; + return 1; +} + +static void srw_bend_fetch(association *assoc, int pos, + Z_SRW_searchRetrieveRequest *srw_req, + Z_SRW_record *record) +{ + bend_fetch_rr rr; + ODR o = assoc->encode; + + rr.setname = "default"; + rr.number = pos; + rr.referenceId = 0; + rr.request_format = VAL_TEXT_XML; + rr.request_format_raw = yaz_oidval_to_z3950oid(assoc->decode, + CLASS_TRANSYN, + VAL_TEXT_XML); + rr.comp = odr_malloc(assoc->decode, sizeof(*rr.comp)); + rr.comp->which = Z_RecordComp_complex; + rr.comp->u.complex = odr_malloc(assoc->decode, sizeof(Z_CompSpec)); + rr.comp->u.complex->selectAlternativeSyntax = (bool_t *) + odr_malloc(assoc->encode, sizeof(bool_t)); + *rr.comp->u.complex->selectAlternativeSyntax = 0; + rr.comp->u.complex->num_dbSpecific = 0; + rr.comp->u.complex->dbSpecific = 0; + rr.comp->u.complex->num_recordSyntax = 0; + rr.comp->u.complex->recordSyntax = 0; + + rr.comp->u.complex->generic = odr_malloc(assoc->decode, + sizeof(Z_Specification)); + rr.comp->u.complex->generic->which = Z_Specification_uri; + rr.comp->u.complex->generic->u.uri = srw_req->recordSchema; + rr.comp->u.complex->generic->elementSpec = 0; + + rr.stream = assoc->encode; + rr.print = assoc->print; + + rr.basename = 0; + rr.len = 0; + rr.record = 0; + rr.last_in_set = 0; + rr.output_format = VAL_TEXT_XML; + rr.output_format_raw = 0; + rr.errcode = 0; + rr.errstring = 0; + rr.surrogate_flag = 0; + + (*assoc->init->bend_fetch)(assoc->backend, &rr); + + if (rr.len >= 0) + { + record->recordData_buf = rr.record; + record->recordData_len = rr.len; + record->recordPosition = odr_intdup(o, pos); + record->recordSchema = odr_strdup(o, srw_req->recordSchema); + } +} + +static void srw_bend_search(association *assoc, request *req, + Z_SRW_searchRetrieveRequest *srw_req, + Z_SRW_searchRetrieveResponse *srw_res) +{ + char *base = "Default"; + bend_search_rr rr; + Z_External *ext; + + if (!assoc->init) + srw_bend_init(assoc); + + rr.setname = "default"; + rr.replace_set = 1; + rr.num_bases = 1; + rr.basenames = &base; + rr.referenceId = 0; + + ext = (Z_External *) odr_malloc(assoc->decode, sizeof(*ext)); + ext->direct_reference = odr_getoidbystr(assoc->decode, + "1.2.840.10003.16.2"); + ext->indirect_reference = 0; + ext->descriptor = 0; + ext->which = Z_External_CQL; + if (srw_req->query) + ext->u.cql = srw_req->query; + else + ext->u.cql = "noterm"; + + rr.query = (Z_Query *) odr_malloc (assoc->decode, sizeof(*rr.query)); + rr.query->which = Z_Query_type_104; + rr.query->u.type_104 = ext; + + rr.stream = assoc->encode; + rr.decode = assoc->decode; + rr.print = assoc->print; + rr.request = req; + rr.association = assoc; + rr.fd = 0; + rr.hits = 0; + rr.errcode = 0; + rr.errstring = 0; + rr.search_info = 0; + (assoc->init->bend_search)(assoc->backend, &rr); + srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits); + if (rr.errcode) + { + srw_res->num_diagnostics = 1; + srw_res->diagnostics = + odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics)); + srw_res->diagnostics[0].code = + odr_intdup(assoc->encode, rr.errcode); + } + else + { + srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits); + if (srw_req->maximumRecords && *srw_req->maximumRecords > 0) + { + int number = *srw_req->maximumRecords; + int start = 1; + int i; + if (srw_req->startRecord) + start = *srw_req->startRecord; + if (start <= rr.hits) + { + int j = 0; + if (start + number > rr.hits) + number = rr.hits - start + 1; + srw_res->records = + odr_malloc(assoc->encode, + number * sizeof(*srw_res->records)); + for (i = 0; irecords[j].recordData_buf = 0; + srw_bend_fetch(assoc, i+start, srw_req, + srw_res->records + j); + if (srw_res->records[j].recordData_buf) + j++; + } + srw_res->num_records = j; + if (!j) + srw_res->records = 0; + yaz_log(LOG_LOG, "got %d records", j); + } + } + } +} + +static void process_http_request(association *assoc, request *req) +{ + Z_HTTP_Request *hreq = req->gdu_request->u.HTTP_Request; + Z_HTTP_Header *hp; + ODR o = assoc->encode; + Z_GDU *p; + Z_HTTP_Response *hres = 0; + int keepalive = 1; + +#if 0 + yaz_log(LOG_LOG, "HTTP Request. method=%s Version=%s Path=%s", + hreq->method, hreq->version, hreq->path); + + for (hp = hreq->headers; hp; hp = hp->next) + yaz_log(LOG_LOG, "%s: %s", hp->name, hp->value); +#endif + + if (!strcmp(hreq->method, "GET")) + { + if (!strcmp(hreq->path, "/")) + { + p = z_get_HTTP_Response(o, 200); + hres = p->u.HTTP_Response; + hres->content_buf = odr_malloc(o, 400); + sprintf (hres->content_buf, + "\n" + "\n" + " \n" + " YAZ " YAZ_VERSION "\n" + " \n" + " \n" + "

YAZ " + YAZ_VERSION "

\n" + " \n" + "\n"); + hres->content_len = strlen(hres->content_buf); + z_HTTP_header_add(o, &hres->headers, "Content-Type", "text/html"); + } + else + { + p = z_get_HTTP_Response(o, 404); + } + } + else if (!strcmp(hreq->method, "POST")) + { + const char *content_type = z_HTTP_header_lookup(hreq->headers, + "Content-Type"); + const char *soap_action = z_HTTP_header_lookup(hreq->headers, + "SOAPAction"); + p = 0; /* no response yet */ + if (content_type && soap_action && + !yaz_strcmp_del("text/xml", content_type, "; ")) + { + Z_SOAP *soap_package = 0; + int ret; + int http_code = 500; + + static Z_SOAP_Handler soap_handlers[2] = { + {"http://www.loc.gov/zing/srw/v1.0/", 0, yaz_srw_codec}, + {0, 0, 0} + }; + + ret = z_soap_codec(assoc->decode, &soap_package, + &hreq->content_buf, &hreq->content_len, + soap_handlers); + + if (!ret && soap_package->which == Z_SOAP_generic && + soap_package->u.generic->no == 0) + { + /* SRW package */ + Z_SRW_searchRetrieve *sr = soap_package->u.generic->p; + + if (sr->which == Z_SRW_searchRetrieve_request) + { + Z_SRW_searchRetrieve *res = + yaz_srw_get(assoc->encode, + Z_SRW_searchRetrieve_response); + + srw_bend_search(assoc, req, sr->u.request, res->u.response); + + soap_package->u.generic->p = res; + http_code = 200; + } + } + + p = z_get_HTTP_Response(o, 200); + hres = p->u.HTTP_Response; + ret = z_soap_codec(assoc->encode, &soap_package, + &hres->content_buf, &hres->content_len, + soap_handlers); + hres->code = http_code; + } + if (!p) /* still no response ? */ + p = z_get_HTTP_Response(o, 500); + } + else + { + p = z_get_HTTP_Response(o, 405); + hres = p->u.HTTP_Response; + + z_HTTP_header_add(o, &hres->headers, "Allow", "GET, POST"); + } + hres = p->u.HTTP_Response; + if (!strcmp(hreq->version, "1.0")) + { + const char *v = z_HTTP_header_lookup(hreq->headers, "Connection"); + if (v && !strcmp(v, "Keep-Alive")) + keepalive = 1; + else + keepalive = 0; + hres->version = "1.0"; + } + else + { + const char *v = z_HTTP_header_lookup(hreq->headers, "Connection"); + if (v && !strcmp(v, "close")) + keepalive = 0; + else + keepalive = 1; + hres->version = "1.1"; + } + if (!keepalive) + { + z_HTTP_header_add(o, &hres->headers, "Connection", "close"); + assoc->state = ASSOC_DEAD; + } + else + { + z_HTTP_header_add(o, &hres->headers, "Connection", "Keep-Alive"); + } + process_gdu_response(assoc, req, p); +} + +static void process_gdu_request(association *assoc, request *req) +{ + if (req->gdu_request->which == Z_GDU_Z3950) + { + char *msg = 0; + req->apdu_request = req->gdu_request->u.z3950; + if (process_z_request(assoc, req, &msg) < 0) + do_close_req(assoc, Z_Close_systemProblem, msg, req); + } + else if (req->gdu_request->which == Z_GDU_HTTP_Request) + process_http_request(assoc, req); + else + { + do_close_req(assoc, Z_Close_systemProblem, "bad protocol packet", req); + } +} + /* * Initiate request processing. */ -static int process_request(association *assoc, request *req, char **msg) +static int process_z_request(association *assoc, request *req, char **msg) { int fd = -1; Z_APDU *res; @@ -465,7 +818,7 @@ static int process_request(association *assoc, request *req, char **msg) if (res) { yaz_log(LOG_DEBUG, " result immediately available"); - retval = process_response(assoc, req, res); + retval = process_z_response(assoc, req, res); } else if (fd < 0) { @@ -515,7 +868,7 @@ void backend_response(IOCHAN i, int event) yaz_log(LOG_WARN, "Serious programmer's lapse or bug"); abort(); } - if ((res && process_response(assoc, req, res) < 0) || fd < 0) + if ((res && process_z_response(assoc, req, res) < 0) || fd < 0) { yaz_log(LOG_LOG, "Fatal error when talking to backend"); do_close(assoc, Z_Close_systemProblem, 0); @@ -532,7 +885,46 @@ void backend_response(IOCHAN i, int event) /* * Encode response, and transfer the request structure to the outgoing queue. */ -static int process_response(association *assoc, request *req, Z_APDU *res) +static int process_gdu_response(association *assoc, request *req, Z_GDU *res) +{ + odr_setbuf(assoc->encode, req->response, req->size_response, 1); + + if (assoc->print && !z_GDU(assoc->print, &res, 0, 0)) + { + yaz_log(LOG_WARN, "ODR print error: %s", + odr_errmsg(odr_geterror(assoc->print))); + odr_reset(assoc->print); + } + if (!z_GDU(assoc->encode, &res, 0, 0)) + { + yaz_log(LOG_WARN, "ODR error when encoding response: %s", + odr_errmsg(odr_geterror(assoc->decode))); + return -1; + } + req->response = odr_getbuf(assoc->encode, &req->len_response, + &req->size_response); + odr_setbuf(assoc->encode, 0, 0, 0); /* don'txfree if we abort later */ + odr_reset(assoc->encode); + req->state = REQUEST_IDLE; + request_enq(&assoc->outgoing, req); + /* turn the work over to the ir_session handler */ + iochan_setflag(assoc->client_chan, EVENT_OUTPUT); + assoc->cs_put_mask = EVENT_OUTPUT; + /* Is there more work to be done? give that to the input handler too */ +#if 1 + if (request_head(&assoc->incoming)) + { + yaz_log (LOG_DEBUG, "more work to be done"); + iochan_setevent(assoc->client_chan, EVENT_WORK); + } +#endif + return 0; +} + +/* + * Encode response, and transfer the request structure to the outgoing queue. + */ +static int process_z_response(association *assoc, request *req, Z_APDU *res) { odr_setbuf(assoc->encode, req->response, req->size_response, 1); @@ -1555,7 +1947,7 @@ void save_referenceId (request *reqb, Z_ReferenceId *refid) void bend_request_send (bend_association a, bend_request req, Z_APDU *res) { - process_response (a, req, res); + process_z_response (a, req, res); } bend_request bend_request_mk (bend_association a) @@ -1588,7 +1980,7 @@ int bend_backend_respond (bend_association a, bend_request req) { char *msg; int r; - r = process_request (a, req, &msg); + r = process_z_request (a, req, &msg); if (r < 0) yaz_log (LOG_WARN, "%s", msg); return r; @@ -1623,7 +2015,8 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) { bend_esrequest_rr esrequest; - Z_ExtendedServicesRequest *req = reqb->apdu_request->u.extendedServicesRequest; + Z_ExtendedServicesRequest *req = + reqb->apdu_request->u.extendedServicesRequest; Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_extendedServicesResponse); Z_ExtendedServicesResponse *resp = apdu->u.extendedServicesResponse; @@ -1680,3 +2073,4 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) yaz_log(LOG_DEBUG,"Send the result apdu"); return apdu; } + diff --git a/server/session.h b/server/session.h index 6e8f8b0..72623f3 100644 --- a/server/session.h +++ b/server/session.h @@ -3,7 +3,7 @@ * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Id: session.h,v 1.27 2003-01-06 08:20:28 adam Exp $ + * $Id: session.h,v 1.28 2003-02-12 15:06:43 adam Exp $ */ #ifndef SESSION_H @@ -28,7 +28,8 @@ typedef struct request char *refid; /* referenceid */ request_state state; - Z_APDU *apdu_request; /* Current request */ + Z_GDU *gdu_request; /* Current request */ + Z_APDU *apdu_request; /* Current Z39.50 request */ NMEM request_mem; /* memory handle for request */ int size_response; /* size of buffer */ diff --git a/server/statserv.c b/server/statserv.c index c4a7e9d..dd3dc75 100644 --- a/server/statserv.c +++ b/server/statserv.c @@ -6,7 +6,7 @@ * NT threaded server code by * Chas Woodfield, Fretwell Downing Informatics. * - * $Id: statserv.c,v 1.90 2003-01-14 08:21:14 adam Exp $ + * $Id: statserv.c,v 1.91 2003-02-12 15:06:43 adam Exp $ */ #include @@ -70,13 +70,14 @@ statserv_options_block control_block = { 0, /* default value for inet deamon */ 0, /* handle (for service, etc) */ 0, /* bend_init handle */ - 0 /* bend_close handle */ + 0, /* bend_close handle */ #ifdef WIN32 - ,"Z39.50 Server", /* NT Service Name */ + "Z39.50 Server", /* NT Service Name */ "Server", /* NT application Name */ "", /* NT Service Dependencies */ - "Z39.50 Server" /* NT Service Display Name */ + "Z39.50 Server", /* NT Service Display Name */ #endif /* WIN32 */ + 0 /* SOAP handlers */ }; /* @@ -446,7 +447,7 @@ static void listener(IOCHAN h, int event) if ((res = cs_listen_check(line, 0, 0, control_block.check_ip, control_block.daemon_name)) < 0) { - yaz_log(LOG_WARN, "cs_listen failed"); + yaz_log(LOG_WARN|LOG_ERRNO, "cs_listen failed"); return; } else if (res == 1) @@ -691,6 +692,32 @@ void statserv_setcontrol(statserv_options_block *block) memcpy(&control_block, block, sizeof(*block)); } +void statserv_add_soap_handler(int (*h)(struct bend_soap_rr *rr), + const char *ns) +{ + struct bend_soap_handler *sh = xmalloc(sizeof(*sh)); + + sh->handler = h; + sh->ns = xstrdup(ns); + sh->next = control_block.soap_handlers; + control_block.soap_handlers = sh; + yaz_log(LOG_LOG, "soap handler added"); +} + +static void statserv_reset(void) +{ + struct bend_soap_handler *sh = control_block.soap_handlers; + + control_block.soap_handlers = 0; + while (sh) + { + struct bend_soap_handler *sh_next = sh->next; + xfree (sh->ns); + xfree (sh); + sh = sh_next; + } +} + int statserv_start(int argc, char **argv) { int ret; @@ -921,6 +948,7 @@ void StopAppService(void *pHandle) { /* Stops the app */ statserv_closedown(); + statserv_reset(); } /* WIN32 */ #else @@ -938,6 +966,7 @@ int statserv_main(int argc, char **argv, statserv_setcontrol(cb); ret = statserv_start (argc, argv); statserv_closedown (); + statserv_reset(); return ret; } #endif diff --git a/srw/Makefile.am b/srw/Makefile.am deleted file mode 100644 index 13b9a7f..0000000 --- a/srw/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -# $Id: Makefile.am,v 1.2 2003-01-15 14:26:55 adam Exp $ -AM_CPPFLAGS = -I$(top_srcdir)/include $(GSOAP_INCLUDE) $(XSLT_CFLAGS) - -EXTRA_DIST = zing.h - -if SRW -noinst_LTLIBRARIES = libsrw.la - -libsrw_la_SOURCES = srw_C.c srw-namespace.c srw-xcql.c srw-xslt.c srw_Client.c srw-diag.c srw-server.c srw_Server.c - -include_HEADERS = srw_H.h srw_Stub.h - -LDADD = $(GSOAP_LIB) - -# Dependency for stdsoap2.h needed! -stdsoap2.h srw_C.c srw_Client.c srw_Server.c srw_H.h srw_Stub.h: zing.h - $(GSOAP_PREFIX)/bin/soapcpp2 -p srw_ -c zing.h - -srw-namespace.o: srw_H.h - -srw_C.o: srw_C.c - $(COMPILE) -c soapC.c -srw_Client.o: soapClient.c - $(COMPILE) -c srw_Client.c -srw_Server.o: srw_Server.c - $(COMPILE) -c srw_Server.c -endif diff --git a/srw/srw-diag.c b/srw/srw-diag.c deleted file mode 100644 index e514c95..0000000 --- a/srw/srw-diag.c +++ /dev/null @@ -1,108 +0,0 @@ -/* $Id: srw-diag.c,v 1.1 2003-01-06 08:20:28 adam Exp $ - Copyright (C) 2002-2003 - Index Data Aps - -This file is part of the YAZ toolkit. - -See the file LICENSE. -*/ - -#include - -static struct { - int code; - char *msg; -} msg_tab[] = { -/* General Diagnostics*/ -{1, "Permanent system error"}, -{2, "System temporarily unavailable"}, -{3, "Authentication error"}, -/* Diagnostics Relating to CQL*/ -{10, "Illegal query"}, -{11, "Unsupported query type (XCQL vs CQL)"}, -{12, "Too many characters in query"}, -{13, "Unbalanced or illegal use of parentheses"}, -{14, "Unbalanced or illegal use of quotes"}, -{15, "Illegal or unsupported index set"}, -{16, "Illegal or unsupported index"}, -{17, "Illegal or unsupported combination of index and index set"}, -{18, "Illegal or unsupported combination of indexes"}, -{19, "Illegal or unsupported relation"}, -{20, "Illegal or unsupported relation modifier"}, -{21, "Illegal or unsupported combination of relation modifers"}, -{22, "Illegal or unsupported combination of relation and index"}, -{23, "Too many characters in term"}, -{24, "Illegal combination of relation and term"}, -{25, "Special characters not quoted in term"}, -{26, "Non special character escaped in term"}, -{27, "Empty term unsupported"}, -{28, "Masking character not supported"}, -{29, "Masked words too short"}, -{30, "Too many masking characters in term"}, -{31, "Anchoring character not supported"}, -{32, "Anchoring character in illegal or unsupported position"}, -{33, "Combination of proximity/adjacency and masking characters not supported"}, -{34, "Combination of proximity/adjacency and anchoring characters not supported"}, -{35, "Terms only exclusion (stop) words"}, -{36, "Term in invalid format for index or relation"}, -{37, "Illegal or unsupported boolean operator"}, -{38, "Too many boolean operators in query"}, -{39, "Proximity not supported"}, -{40, "Illegal or unsupported proximity relation"}, -{41, "Illegal or unsupported proximity distance"}, -{42, "Illegal or unsupported proximity unit"}, -{43, "Illegal or unsupported proximity ordering"}, -{44, "Illegal or unsupported combination of proximity modifiers"}, -{45, "Index set name (prefix) assigned to multiple identifiers"}, -/* Diagnostics Relating to Result Sets*/ -{50, "Result sets not supported"}, -{51, "Result set does not exist"}, -{52, "Result set temporarily unavailable"}, -{53, "Result sets only supported for retrieval"}, -{54, "Retrieval may only occur from an existing result set"}, -{55, "Combination of result sets with search terms not supported"}, -{56, "Only combination of single result set with search terms supported"}, -{57, "Result set created but no records available"}, -{58, "Result set created with unpredictable partial results available"}, -{59, "Result set created with valid partial results available"}, -/* Diagnostics Relating to Records*/ -{60, "Too many records retrieved"}, -{61, "First record position out of range"}, -{62, "Negative number of records requested"}, -{63, "System error in retrieving records"}, -{64, "Record temporarily unavailable"}, -{65, "Record does not exist"}, -{66, "Unknown schema for retrieval"}, -{67, "Record not available in this schema"}, -{68, "Not authorised to send record"}, -{69, "Not authorised to send record in this schema"}, -{70, "Record too large to send"}, -/* Diagnostics Relating to Sorting*/ -{80, "Sort not supported"}, -{81, "Unsupported sort type (sortKeys vs xSortKeys)"}, -{82, "Illegal or unsupported sort sequence"}, -{83, "Too many records"}, -{84, "Too many sort keys"}, -{85, "Duplicate sort keys"}, -{86, "Incompatible record formats"}, -{87, "Unsupported schema for sort"}, -{88, "Unsupported tag path for sort"}, -{89, "Tag path illegal or unsupported for schema"}, -{90, "Illegal or unsupported direction value"}, -{91, "Illegal or unsupported case value"}, -{92, "Illegal or unsupported missing value action"}, -/* Diagnostics Relating to Explain*/ -{100, "Explain not supported"}, -{101, "Explain request type not supported (SOAP vs GET)"}, -{102, "Explain record temporarily unavailable"}, -{0, 0} -}; - -const char *yaz_srw_diag_str (int code) -{ - int i; - for (i=0; msg_tab[i].msg; i++) - if (msg_tab[i].code == code) - return msg_tab[i].msg; - return "Unknown error"; -} diff --git a/srw/srw-namespace.c b/srw/srw-namespace.c deleted file mode 100644 index 1659536..0000000 --- a/srw/srw-namespace.c +++ /dev/null @@ -1,29 +0,0 @@ -/* $Id: srw-namespace.c,v 1.1 2003-01-06 08:20:28 adam Exp $ - Copyright (C) 2002-2003 - Index Data Aps - -This file is part of the YAZ toolkit. - -See the file LICENSE. -*/ - -#include "srw_H.h" - -struct Namespace srw_namespaces[] = -{ - {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, - {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, -#if 1 - {"xsi", "http://schemas.xmlsoap.org/wsdl/"}, - {"xsd", "http://www.w3.org/2001/XMLSchema"}, -#else - {"xsi", "http://www.w3.org/1999/XMLSchema-instance"}, - {"xsd", "http://www.w3.org/1999/XMLSchema"}, -#endif - {"zs", "http://www.loc.gov/zing/srw/v1.0/"}, - {"zt", "http://www.loc.gov/zing/srw/v1.0/types/"}, - {"xcql", "http://www.loc.gov/zing/cql/v1.0/xcql/"}, - {"xsortkeys","http://www.loc.gov/zing/srw/v1.0/xsortkeys/"}, - {"diag", "http://www.loc.gov/zing/srw/v1.0/diagnostic/"}, - {NULL, NULL} -}; diff --git a/srw/srw-server.c b/srw/srw-server.c deleted file mode 100644 index 5a2ab0a..0000000 --- a/srw/srw-server.c +++ /dev/null @@ -1,74 +0,0 @@ - -#include -#include - -struct srw_info { - int (*sr_h)(void *userinfo, - struct soap * soap, - xsd__string *query, - struct xcql__operandType *xQuery, - xsd__string *sortKeys, - struct xsort__xSortKeysType *xSortKeys, - xsd__integer *startRecord, - xsd__integer *maximumRecords, - xsd__string *recordSchema, - xsd__string *recordPacking, - struct zs__searchRetrieveResponse *res); - int (*e_h)(void *userinfo, - struct soap *soap, - struct zs__explainResponse *explainResponse); - void *userinfo; -}; - -int zs__explainRequest (struct soap *soap, - struct zs__explainResponse *explainResponse) -{ - struct srw_info *info = (struct srw_info *) soap->user; - return (*info->e_h)(info->userinfo, soap, explainResponse); -} - -int zs__searchRetrieveRequest(struct soap * soap, - xsd__string *query, - struct xcql__operandType *xQuery, - xsd__string *sortKeys, - struct xsort__xSortKeysType *xSortKeys, - xsd__integer *startRecord, - xsd__integer *maximumRecords, - xsd__string *recordSchema, - xsd__string *recordPacking, - struct zs__searchRetrieveResponse *res) -{ - struct srw_info *info = (struct srw_info *) soap->user; - return (*info->sr_h)(info->userinfo, soap, - query, xQuery, sortKeys, xSortKeys, - startRecord, maximumRecords, - recordSchema, recordPacking, - res); -} - -void yaz_srw_serve (struct soap *soap, - int (*sr_h)(void *userinfo, - struct soap * soap, - xsd__string *query, - struct xcql__operandType *xQuery, - xsd__string *sortKeys, - struct xsort__xSortKeysType *xSortKeys, - xsd__integer *startRecord, - xsd__integer *maximumRecords, - xsd__string *recordSchema, - xsd__string *recordPacking, - struct zs__searchRetrieveResponse *res), - int (*e_h)(void *userinfo, - struct soap *soap, - struct zs__explainResponse *explainResponse)) -{ - struct srw_info info; - - info.sr_h = sr_h; - info.e_h = e_h; - info.userinfo = soap->user; - soap->user = &info; - soap->namespaces = srw_namespaces; - soap_serve(soap); -} - diff --git a/srw/srw-xcql.c b/srw/srw-xcql.c deleted file mode 100644 index bdd16fd..0000000 --- a/srw/srw-xcql.c +++ /dev/null @@ -1,84 +0,0 @@ -/* $Id: srw-xcql.c,v 1.1 2003-01-06 08:20:28 adam Exp $ - Copyright (C) 2002-2003 - Index Data Aps - -This file is part of the YAZ toolkit. - -See the file LICENSE. -*/ - -#include - -struct cql_node *xcql_to_cqlnode(struct xcql__operandType *p) -{ - struct cql_node *cn = 0; - if (p && p->searchClause) - { - cn = cql_node_mk_sc(p->searchClause->index, - p->searchClause->relation->value, - p->searchClause->term); - if (p->searchClause->relation->modifiers) - { - struct xcql__modifiersType *mods = - p->searchClause->relation->modifiers; - struct cql_node **cnp = &cn->u.st.modifiers; - - int i; - for (i = 0; i < mods->__sizeModifier; i++) - { - *cnp = cql_node_mk_mod(mods->modifier[i]->type, - mods->modifier[i]->value); - cnp = &(*cnp)->u.mod.next; - } - } - if (p->searchClause->prefixes) - { - struct xcql__prefixesType *prefixes = p->searchClause->prefixes; - struct cql_node **cnp = &cn->u.st.prefixes; - - int i; - for (i = 0; i < prefixes->__sizePrefix; i++) - { - *cnp = cql_node_mk_mod(prefixes->prefix[i]->name, - prefixes->prefix[i]->identifier); - cnp = &(*cnp)->u.mod.next; - } - } - } - else if (p && p->triple) - { - cn = cql_node_mk_boolean(p->triple->boolean->value); - - if (p->triple->boolean->modifiers) - { - struct xcql__modifiersType *mods = - p->triple->boolean->modifiers; - struct cql_node **cnp = &cn->u.bool.modifiers; - - int i; - for (i = 0; i < mods->__sizeModifier; i++) - { - *cnp = cql_node_mk_mod(mods->modifier[i]->type, - mods->modifier[i]->value); - cnp = &(*cnp)->u.mod.next; - } - } - if (p->triple->prefixes) - { - struct xcql__prefixesType *prefixes = p->triple->prefixes; - struct cql_node **cnp = &cn->u.bool.prefixes; - - int i; - for (i = 0; i < prefixes->__sizePrefix; i++) - { - *cnp = cql_node_mk_mod(prefixes->prefix[i]->name, - prefixes->prefix[i]->identifier); - cnp = &(*cnp)->u.mod.next; - } - } - cn->u.bool.left = xcql_to_cqlnode(p->triple->leftOperand); - cn->u.bool.right = xcql_to_cqlnode(p->triple->rightOperand); - } - return cn; -} - diff --git a/srw/srw-xslt.c b/srw/srw-xslt.c deleted file mode 100644 index c3dbac0..0000000 --- a/srw/srw-xslt.c +++ /dev/null @@ -1,209 +0,0 @@ -/* $Id: srw-xslt.c,v 1.1 2003-01-06 08:20:28 adam Exp $ - Copyright (C) 2002-2003 - Index Data Aps - -This file is part of the YAZ toolkit. - -See the file LICENSE. -*/ - -#if HAVE_XSLT -#include -#include -#include -#include -#endif - -#include - -struct xslt_maps_info { -#if HAVE_XSLT - xmlDocPtr doc; -#else - int dummy; -#endif -}; - -struct xslt_map_result_info { -#if HAVE_XSLT - xmlChar *buf; -#else - char *buf; -#endif - int len; - char *schema; -}; - -xslt_maps xslt_maps_create() -{ - xslt_maps m = malloc(sizeof(*m)); -#if HAVE_XSLT - m->doc = 0; -#endif - return m; -} - -void xslt_maps_free(xslt_maps m) -{ -#if HAVE_XSLT - xmlFreeDoc(m->doc); -#endif - free (m); -} - -int xslt_maps_file(xslt_maps m, const char *f) -{ -#if HAVE_XSLT - if (m->doc) - xmlFreeDoc(m->doc); - m->doc = xmlParseFile(f); - if (!m->doc) - return -1; - return 0; -#else - return -2; -#endif -} - -void xslt_map_free (xslt_map_result res) -{ - if (res) - { - free (res->schema); -#if HAVE_XSLT - xmlFree(res->buf); -#endif - free (res); - } -} - -xslt_map_result xslt_map (xslt_maps m, const char *schema_source, - const char *schema_target, - const char *in_buf, int in_len) -{ -#if HAVE_XSLT - const char *map_ns = "http://indexdata.dk/srw/schema-mappings/v1.0/"; - xmlNodePtr ptr; - - if (!m) - return 0; - ptr = xmlDocGetRootElement(m->doc); - while (ptr && ptr->type == XML_ELEMENT_NODE) - { - if (!strcmp(ptr->name, "schema-mappings")) - { - ptr = ptr->children; - break; - } - } - for (; ptr; ptr = ptr->next) - { - if (ptr->type == XML_ELEMENT_NODE && !strcmp(ptr->name, "map") - && !strcmp(ptr->ns->href, map_ns) && ptr->children) - { - xmlNodePtr src = ptr->children; - int source_ok = 0; - int target_ok = 0; - const char *full_target = 0; - const char *filename = 0; - - for (; src; src = src->next) - { - if (src->type == XML_ELEMENT_NODE && - !strcmp(src->name, "schema") && - !strcmp(src->ns->href, map_ns)) - { - struct _xmlAttr *attr = src->properties; - for (; attr; attr = attr->next) - if (!strcmp(attr->name, "target") && - attr->children && - attr->children->type == XML_TEXT_NODE) - { - full_target = attr->children->content; - if (!strcmp(attr->children->content, - schema_target)) - target_ok = 1; - } - else if (!strcmp(attr->name, "source") - && attr->children - && attr->children->type == XML_TEXT_NODE) - - { - if (!strcmp(schema_source, - attr->children->content)) - source_ok = 1; - } - else if (!strcmp(attr->name, "alias") - && attr->children - && attr->children->type == XML_TEXT_NODE) - { - if (!strcmp(attr->children->content, schema_target)) - target_ok = 1; - } - } - if (src->type == XML_ELEMENT_NODE && - !strcmp(src->name, "stylesheet") && - !strcmp(src->ns->href, map_ns)) - { - struct _xmlAttr *attr = src->properties; - for (; attr; attr = attr->next) - if (!strcmp(attr->name, "filename") && - attr->children && - attr->children->type == XML_TEXT_NODE) - { - filename = attr->children->content; - } - } - } - if (source_ok && target_ok) - { - if (filename) - { - xslt_map_result out = malloc(sizeof(*out)); - xmlDocPtr res, doc = xmlParseMemory(in_buf, in_len); - xmlDocPtr xslt_doc = xmlParseFile(filename); - xsltStylesheetPtr xsp; - - xsp = xsltParseStylesheetDoc(xslt_doc); - - res = xsltApplyStylesheet(xsp, doc, 0); - - xmlDocDumpMemory (res, &out->buf, &out->len); - - xsltFreeStylesheet(xsp); - - xmlFreeDoc(doc); - xmlFreeDoc(res); - - out->schema = strdup(full_target); - return out; - } - else - { - xslt_map_result out = malloc(sizeof(*out)); - out->buf = xmlMalloc(in_len); - memcpy (out->buf, in_buf, in_len); - out->len = in_len; - out->schema = strdup(full_target); - return out; - } - } - } - } -#endif - return 0; -} - -char *xslt_map_result_buf(xslt_map_result res) -{ - return res->buf; -} -int xslt_map_result_len(xslt_map_result res) -{ - return res->len; -} - -char *xslt_map_result_schema(xslt_map_result res) -{ - return res->schema; -} diff --git a/srw/zing.h b/srw/zing.h deleted file mode 100644 index 8224be3..0000000 --- a/srw/zing.h +++ /dev/null @@ -1,136 +0,0 @@ -/* $Id: zing.h,v 1.1 2003-01-06 08:20:28 adam Exp $ - Copyright (C) 2002 - Index Data Aps - -This file is part of the YAZ toolkit. - -See file LICENSE for details. -*/ -//gsoap zs service name: SRW -//gsoap zs service encoding: literal -//gsoap zs service namespace: http://www.loc.gov/zing/srw/v1.0/ -//gsoap zs schema namespace: http://www.loc.gov/zing/srw/v1.0/ -//gsoap xcql schema namespace: http://www.loc.gov/zing/cql/v1.0/xcql/ -//gsoap xsort schema namespace: http://www.loc.gov/zing/srw/v1.0/xsortkeys/ -//gsoap diag schema namespace: http://www.loc.gov/zing/srw/v1.0/diagnostic/ - -typedef char *xsd__string; -typedef int xsd__integer; -typedef int xsd__boolean; - -typedef xsd__string zs__idType; -typedef char *XML; - -struct zs__recordType { - xsd__string recordSchema; - xsd__string recordData; - xsd__integer recordPosition 0; -}; - -struct zs__records { - int __sizeRecords; - struct zs__recordType **record; -}; - -struct diag__diagnosticType { - xsd__integer code; - xsd__string details 0; -}; - -struct zs__diagnostics { - int __sizeDiagnostics; - struct diag__diagnosticType **diagnostic; -}; - -struct zs__searchRetrieveResponse { - xsd__integer numberOfRecords; - xsd__string resultSetId 1; - xsd__integer resultSetIdleTime 0; - - struct zs__records records 0; - struct zs__diagnostics diagnostics 0; - xsd__integer *nextRecordPosition 0; - xsd__string debugInfo; -}; - -struct xcql__prefixType { - xsd__string name; - xsd__string identifier; -}; - -struct xcql__prefixesType { - int __sizePrefix; - struct xcql__prefixType **prefix; -}; - -struct xcql__relationType { - xsd__string value; - struct xcql__modifiersType *modifiers 0; -}; - -struct xcql__searchClauseType { - struct xcql__prefixesType *prefixes 0; - xsd__string index 0; - struct xcql__relationType *relation 0; - xsd__string term; -}; - -struct xcql__modifierType { - xsd__string type 0; - xsd__string value; -}; - -struct xcql__modifiersType { - int __sizeModifier; - struct xcql__modifierType **modifier; -}; - -struct xcql__booleanType { - xsd__string value; - struct xcql__modifiersType *modifiers 0; -}; - -struct xcql__operandType { - struct xcql__searchClauseType *searchClause 0; - struct xcql__tripleType *triple 0; -}; - -struct xcql__tripleType { - struct xcql__prefixesType *prefixes 0; - struct xcql__booleanType *boolean; - struct xcql__operandType *leftOperand; - struct xcql__operandType *rightOperand; -}; - -struct xsort__sortKeyType { - xsd__string path; - xsd__string schema 0; - xsd__boolean ascending 0; - xsd__boolean caseSensitive 0; - xsd__string missingValue 0; -}; - -struct xsort__xSortKeysType { - int __sizeSortKey; - struct xsort__sortKeyType **sortKey; -}; - -int zs__searchRetrieveRequest ( - xsd__string *query, - struct xcql__operandType *xQuery, - xsd__string *sortKeys, - struct xsort__xSortKeysType *xSortKeys, - xsd__integer *startRecord, - xsd__integer *maximumRecords, - xsd__string *recordSchema, - xsd__string *recordPacking, - struct zs__searchRetrieveResponse *searchRetrieveResponse -); - -struct zs__explainResponse { - xsd__string Explain; -}; - -int zs__explainRequest ( - struct zs__explainResponse *explainResponse -); diff --git a/srwapps/Makefile.am b/srwapps/Makefile.am deleted file mode 100644 index a024153..0000000 --- a/srwapps/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -## $Id: Makefile.am,v 1.1 2003-01-06 08:20:28 adam Exp $ -## Copyright (C) 2002-2003, Index Data - -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/srw $(CFLAGSTHREADS) - -if SRW -bin_PROGRAMS = srw-gateway srw-client -endif - -if ISTHR -extra=../lib/libyazthread.la -endif - -LDADD = $(extra) ../lib/libyaz.la $(GSOAP_LIB) $(XSLT_LIB) $(LIBTHREAD) - -srw_gateway_SOURCES = srw-gateway.c -srw_client_SOURCES = srw-client.c - diff --git a/srwapps/srw-client.c b/srwapps/srw-client.c deleted file mode 100644 index e867562..0000000 --- a/srwapps/srw-client.c +++ /dev/null @@ -1,180 +0,0 @@ -/* $Id: srw-client.c,v 1.2 2003-01-13 14:32:41 adam Exp $ - Copyright (C) 2002-2003 - Index Data Aps - -This file is part of the YAZ toolkit. - -See file LICENSE for details. -*/ - -#include - -#include -#include - -int main (int argc, char **argv) -{ - struct soap soap; - char *action; - int ret; - struct zs__searchRetrieveResponse res; - char * query = 0; - struct xcql__operandType *xQuery = 0; - xsd__integer startRecord = 1; - xsd__integer maximumRecord = 0; - char *recordSchema = "http://www.loc.gov/marcxml/"; - xsd__string recordPacking = 0; - char *service = 0; - int xcql = 0; - int explain = 0; - char *arg; - - while ((ret = options("er:xs:", argv, argc, &arg)) != -2) - { - switch(ret) - { - case 0: - if (!service) - service = arg; - else if (!query) - query = arg; - break; - case 'e': - explain = 1; - break; - case 'r': - sscanf (arg, "%d,%d", &startRecord, &maximumRecord); - break; - case 'x': - xcql = 1; - break; - case 's': - recordSchema = arg; - } - } - if (!query) - { - printf ("usage:\n srw-client"); - printf (" [-e] [-r start,number] [-x] [-s schema] \n"); - printf (" http://localhost:8001/indexdata.dk/gils computer\n"); - exit (1); - } - soap_init(&soap); - soap.namespaces = srw_namespaces; - - if (explain) - { - struct zs__explainResponse eres; - ret = soap_call_zs__explainRequest(&soap, service, action, - &eres); - if (ret == SOAP_OK) - { - if (eres.Explain) - printf ("%s\n", eres.Explain); - else - printf ("no record\n"); - } - else - soap_print_fault(&soap, stderr); - } - - if (xcql) /* xquery */ - { /* just a hacked query for testing .. */ - struct xcql__searchClauseType *sc1, *sc2; - struct xcql__relationType *relation; - struct xcql__tripleType *triple; - xQuery = soap_malloc (&soap, sizeof(*xQuery)); - sc1 = soap_malloc (&soap, sizeof(*sc1)); - sc1->prefixes = 0; - sc1->index = "dc.title"; - relation = sc1->relation = soap_malloc(&soap, sizeof(*relation)); - sc1->term = "computer"; - relation->value = "="; - relation->modifiers = 0; - - sc2 = soap_malloc (&soap, sizeof(*sc2)); - sc2->prefixes = 0; - sc2->index = "dc.author"; - relation = sc2->relation = soap_malloc(&soap, sizeof(*relation)); - sc2->term = "knuth"; - relation->value = "="; - relation->modifiers = - soap_malloc (&soap, sizeof(*relation->modifiers)); - relation->modifiers->__sizeModifier = 1; - relation->modifiers->modifier = - soap_malloc (&soap, sizeof(*relation->modifiers->modifier)); - relation->modifiers->modifier[0] = - soap_malloc (&soap, sizeof(**relation->modifiers->modifier)); - relation->modifiers->modifier[0]->type = 0; - relation->modifiers->modifier[0]->value = soap_malloc (&soap, 6); - strcpy(relation->modifiers->modifier[0]->value, "fuzzy"); - ; - triple = soap_malloc (&soap, sizeof(*triple)); - triple->prefixes = 0; - triple->boolean = soap_malloc (&soap, sizeof(*triple->boolean)); - triple->boolean->value = "and"; - triple->boolean->modifiers = 0; - triple->leftOperand = - soap_malloc (&soap, sizeof(*triple->leftOperand)); - triple->leftOperand->searchClause = sc1; - triple->rightOperand = - soap_malloc (&soap, sizeof(*triple->rightOperand)); - triple->rightOperand->searchClause = sc2; - xQuery->triple = triple; - query = 0; - } - - ret = soap_call_zs__searchRetrieveRequest(&soap, service, action, - &query, xQuery, - 0, 0, - &startRecord, - &maximumRecord, - &recordSchema, - &recordPacking, - &res); - - if (ret == SOAP_OK) - { - if (res.diagnostics.__sizeDiagnostics > 0) - { - int i; - for (i = 0; i < - res.diagnostics.__sizeDiagnostics; - i++) - { - int code = res.diagnostics.diagnostic[i]->code; - char *details = - res.diagnostics.diagnostic[i]->details; - printf ("error = %d", code); - if (details) - printf (" details = %s", details); - printf ("\n"); - } - } - else - { - int i; - if (res.resultSetId) - printf ("set: %s\n", res.resultSetId); - printf ("numberOfRecords: %d\n", res.numberOfRecords); - for (i = 0; irecordData) - { - printf ("rec %d schema=%s string:\n%s\n", i+1, - res.records.record[i]->recordSchema, - res.records.record[i]->recordData); - } - } - } - } - else - { - soap_print_fault(&soap, stderr); - } - soap_end(&soap); - exit (0); - return 0; -} - diff --git a/srwapps/srw-gateway.c b/srwapps/srw-gateway.c deleted file mode 100644 index aa0f458..0000000 --- a/srwapps/srw-gateway.c +++ /dev/null @@ -1,911 +0,0 @@ -/* $Id: srw-gateway.c,v 1.2 2003-01-20 13:04:50 adam Exp $ - Copyright (C) 2002-2003 - Index Data Aps - -This file is part of the YAZ toolkit. - -See the file LICENSE. -*/ - -/* - * TODO: - * - * TTL for targets. Separate thread for cleanup. - * External target config and aliases. - */ - -/* note that soapH.h defines _REENTRANT so we check for it here */ -#ifdef _REENTRANT -#include -#define USE_THREADS 1 -#else -#define USE_THREADS 0 -#endif - -#include -#include -#include -#include -#include -#include - -#define RESULT_SETS 0 -#define SRW_DEBUG 1 - -struct tset { - ZOOM_resultset m_r; - long m_expiry_sec; /* date of creation */ - int m_idle_time; - char *m_query; - char *m_schema; - struct tset *m_next; -}; - -struct target { - ZOOM_connection m_c; - char *m_name; - int m_in_use; - struct tset *m_sets; - struct target *next; -}; - -struct srw_prop { - int optimize_level; - int idle_time; - int max_sets; - xslt_maps maps; -}; - -static cql_transform_t cql_transform_handle = 0; -static struct target *target_list = 0; -#if USE_THREADS -static pthread_mutex_t target_mutex = PTHREAD_MUTEX_INITIALIZER; -#define mylock(x) pthread_mutex_lock(x) -#define myunlock(x) pthread_mutex_unlock(x) -#else -#define mylock(x) -#define myunlock(x) -#endif - -#define ERROR_NO_TARGET -1 -#define ERROR_BAD_CQL 10 - -static int diag_bib1_to_srw (int code) -{ - static int map[] = { - 1, 1, - 2, 2, - 3, 11, - 4, 35, - 5, 12, - 6, 30, - 7, 30, - 8, 32, - 9, 29, - 10, 10, - 11, 12, - 13, 61, - 14, 63, - 15, 68, - 16, 70, - 17, 70, - 18, 50, - 19, 55, - 20, 56, - 21, 52, - 22, 50, - /* 23-26 no map */ - 27, 51, - 28, 52, - 29, 52, - 30, 51, - 31, 52, - 32, 52, - 33, 52, - /* 100 -105 */ - 106, 66, - 107, 11, - 108, 10, - 109, 2, - 110, 37, - /* 111- 112 */ - 113, 10, - 114, 16, - 115, 16, - 116, 16, - 117, 19, - 118, 22, - 119, 32, - 120, 28, - 121, 15, - 122, 32, - 123, 22, - 124, 24, - 125, 36, - 126, 36, - 127, 36, - 128, 51, - 129, 39, - 130, 43, - 131, 40, - 132, 42, - 201, 44, - 202, 41, - 203, 43, - /* 205 */ - 0 - }; - const int *p = map; - while (*p) - { - if (code == *p) - return p[1]; - p += 2; - } - return 0; -} - -static int searchRetrieve(void *userinfo, - struct soap * soap, - xsd__string *query, - struct xcql__operandType *xQuery, - xsd__string *sortKeys, - struct xsort__xSortKeysType *xSortKeys, - xsd__integer *startRecord, - xsd__integer *maximumRecords, - xsd__string *recordSchema, - xsd__string *recordPacking, - struct zs__searchRetrieveResponse *res); -static int explain (void *userinfo, - struct soap *soap, - struct zs__explainResponse *explainResponse); - -struct target *target_use (const char *action, const char *query, - const char *schema, struct tset **set, - struct srw_prop *prop) -{ - char name[80]; - struct target *l = 0; - struct timeval tv; - struct tset **ssp = 0; - long now; - int no_sets = 0; - - gettimeofday(&tv, 0); - now = tv.tv_sec; - - if (strlen(action) >= 80) - action = "localhost:210"; - if (strchr(action, '/') || strchr(action, ':')) - strcpy (name, action); - else - { - strcpy (name, "localhost/"); - if (*action == '\0') - strcat (name, "Default"); - else - strcat (name, action); - } - - /* See if we have the target and the same query */ - if (query) - for (l = target_list; l; l = l->next) - if (!l->m_in_use && !strcmp (l->m_name, name)) - { - struct tset *s = l->m_sets; - for (; s; s = s->m_next) - if (!strcmp(s->m_query, query) && - !strcmp (s->m_schema, schema)) - { - *set = s; - return l; - } - } - - /* OK, see if we have the target, then.. */ - for (l = target_list; l; l = l->next) - if (!strcmp (l->m_name, name) && !l->m_in_use) - { - struct tset *s = l->m_sets; - for (; s; s = s->m_next) - /* if m_expiry_sec is 0, the condition is true below */ - if (s->m_expiry_sec < now) - { - xfree (s->m_query); - s->m_query = xstrdup(""); - xfree (s->m_schema); - s->m_schema = xstrdup(""); - ZOOM_resultset_destroy(s->m_r); - s->m_r = 0; - *set = s; - return l; - } - break; - } - if (!l) - { - /* allright. Have to make a new one */ - l = xmalloc (sizeof(*l)); - l->m_name = xstrdup (name); - l->m_in_use = 1; - l->m_c = 0; - l->m_sets = 0; - l->next = target_list; - target_list = l; - } - for (ssp = &l->m_sets; *ssp; ssp = &(*ssp)->m_next) - no_sets++; - *ssp = xmalloc(sizeof(**ssp)); - (*ssp)->m_next = 0; - (*ssp)->m_query = xstrdup(""); - (*ssp)->m_schema = xstrdup(""); - (*ssp)->m_r = 0; - (*ssp)->m_expiry_sec = 0; - (*ssp)->m_idle_time = (no_sets >= prop->max_sets ? 0 : prop->idle_time); - *set = *ssp; - return l; -} - -static void target_destroy (struct target *t) -{ - struct target **tp; - - mylock(&target_mutex); - - for (tp = &target_list; *tp; tp = &(*tp)->next) - if (*tp == t) - { - struct tset *s = t->m_sets; - while (s) - { - struct tset *s_next = s->m_next; - xfree (s->m_query); - xfree (s->m_schema); - ZOOM_resultset_destroy (s->m_r); - xfree (s); - s = s_next; - } - - *tp = t->next; - - ZOOM_connection_destroy (t->m_c); - - xfree (t->m_name); - xfree (t); - break; - } - myunlock(&target_mutex); -} - -static void target_leave (struct target *l) -{ - mylock(&target_mutex); - l->m_in_use = 0; - - if (1) - { - struct tset *s = l->m_sets; - for (; s; s = s->m_next) - yaz_log(LOG_LOG, " set %s q=%s", - (s->m_r ? ZOOM_resultset_option_get(s->m_r,"setname"):""), - s->m_query); - } - myunlock(&target_mutex); -} - -#if USE_THREADS -static void *p_serve (void *p) -{ - struct soap *soap = p; - yaz_srw_serve(soap, searchRetrieve, explain); -} -#endif - - -static void standalone(struct soap *soap, const char *host, int port, - int max_thr, struct srw_prop *properties) -{ - struct soap **soap_thr = malloc (sizeof(*soap_thr) * max_thr); -#if USE_THREADS - pthread_t *tid = malloc (sizeof(pthread_t) * max_thr); -#endif - int m, s, i; - int cno = 0; - int stop = 0; - char fname[40]; - - m = soap_bind(soap, 0, port, 100); - if (m < 0) - { - yaz_log (LOG_WARN|LOG_ERRNO, "Cannot bind to %d", port); - stop = 1; - } - - for (i = 0; i 1) /* static mode for max_thr <= 1 */ - pthread_join(tid[i], 0); -#endif - soap_end(soap_thr[i]); - } - -#if SRW_DEBUG - sprintf (fname, "srw.recv.%05d.log", cno); - remove (fname); - soap_set_recv_logfile(soap_thr[i], fname); - - sprintf (fname, "srw.sent.%05d.log", cno); - remove (fname); - soap_set_sent_logfile(soap_thr[i], fname); - - sprintf (fname, "srw.test.%05d.log", cno); - remove (fname); - soap_set_test_logfile(soap_thr[i], fname); - - yaz_log (LOG_LOG, "starting session %d %ld.%ld.%ld.%ld", cno, - (long) (soap->ip>>24) & 0xff, - (long) (soap->ip>>16) & 0xff, - (long) (soap->ip>>8) & 0xff, - (long) soap->ip & 0xff); -#endif - soap_thr[i]->encodingStyle = 0; - soap_thr[i]->socket = s; - soap_thr[i]->user = properties; -#if USE_THREADS - if (max_thr <= 1) - yaz_srw_serve(soap_thr[i], - searchRetrieve, explain); /* static mode .. */ - else - pthread_create(&tid[i], 0, p_serve, soap_thr[i]); -#else - yaz_srw_serve(soap_thr[i], - searchRetrieve, explain); /* static mode .. */ -#endif - } - } -#if USE_THREADS - free (tid); -#endif - free (soap_thr); -} - -static void reconnect (struct target *t) -{ - struct tset *s; - - for (s = t->m_sets; s; s = s->m_next) - { - ZOOM_resultset_destroy(s->m_r); - s->m_r = 0; - } - ZOOM_connection_destroy (t->m_c); - - t->m_c = ZOOM_connection_create (0); - ZOOM_connection_connect (t->m_c, t->m_name, 0); -} - -int explain (void *userinfo, - struct soap *soap, - struct zs__explainResponse *explainResponse) -{ - explainResponse->Explain = - "\n" - " \n" - "\n"; - return SOAP_OK; -} - -int fetchone(struct soap *soap, struct srw_prop *properties, - ZOOM_record zrec, const char *schema, - char **rec_data, char **rec_schema) -{ - xslt_map_result res; - int xml_len; - const char *xml_rec = ZOOM_record_get(zrec, "xml", &xml_len); - if (!xml_rec) - { - return 65; - } - if (!strcmp(schema, "MARC21") || !strcmp(schema, "http://www.loc.gov/marcxml/")) - { - *rec_data = soap_malloc (soap, xml_len+1); - memcpy (*rec_data, xml_rec, xml_len); - (*rec_data)[xml_len] = 0; - *rec_schema = "http://www.loc.gov/marcxml/"; - } - else if ((res = xslt_map (properties->maps, "MARC21", - schema, xml_rec, xml_len))) - { - int len = xslt_map_result_len(res); - char *buf = xslt_map_result_buf(res); - - *rec_data = soap_malloc (soap, len+1); - memcpy (*rec_data, buf, len); - (*rec_data)[len] = 0; - - *rec_schema = soap_malloc(soap, - strlen(xslt_map_result_schema(res)) + 1); - strcpy(*rec_schema, xslt_map_result_schema(res)); - - xslt_map_free (res); - } - else - { - *rec_data = soap_malloc(soap, strlen(schema)+1); - strcpy(*rec_data, schema); - return 66; - } - return 0; -} - -int searchRetrieve(void *userinfo, - struct soap * soap, - xsd__string *query, - struct xcql__operandType *xQuery, - xsd__string *sortKeys, - struct xsort__xSortKeysType *xSortKeys, - xsd__integer *startRecord, - xsd__integer *maximumRecords, - xsd__string *recordSchema, - xsd__string *recordPacking, - struct zs__searchRetrieveResponse *res) -{ - const char *msg = 0, *addinfo = 0; - const char *schema = recordSchema ? *recordSchema : ""; - struct target *t = 0; - struct tset *s = 0; - int error = 0; - struct srw_prop *properties = (struct srw_prop*) userinfo; - WRBUF wr_log = wrbuf_alloc(); - - char pqf_buf[1024]; - char zurl[81]; - - *pqf_buf = '\0'; - *zurl = '\0'; - yaz_log (LOG_LOG, "HTTP: %s", soap->endpoint); - if (*soap->endpoint) - { - const char *cp = strstr(soap->endpoint, "//"); - if (cp) - cp = cp+2; /* skip method// */ - else - cp = soap->endpoint; - cp = strstr(cp, "/"); - if (cp) - { - size_t len; - cp++; - len = strlen(cp); - if (len > 80) - len = 80; - if (len) - memcpy (zurl, cp, len); - zurl[len] = '\0'; - } - } - else - { - const char *cp = getenv("PATH_INFO"); - if (cp && cp[0] && cp[1]) - { - size_t len; - cp++; /* skip / */ - len = strlen(cp); - if (len > 80) - len = 80; - if (len) - memcpy (zurl, cp, len); - zurl[len] = '\0'; - } - } - if (query) - { - CQL_parser cql_parser = cql_parser_create(); - int r = cql_parser_string(cql_parser, *query); - - if (r) - { - yaz_log (LOG_LOG, "cql failed: %s", *query); - error = ERROR_BAD_CQL; - } - else - { - struct cql_node *tree = cql_parser_result(cql_parser); - error = cql_transform_buf (cql_transform_handle, tree, - pqf_buf, sizeof(pqf_buf)); - if (error) - cql_transform_error(cql_transform_handle, &addinfo); - cql_parser_destroy(cql_parser); - yaz_log (LOG_LOG, "cql OK: %s", *query); - } - } - else if (xQuery) - { - struct cql_node *tree = xcql_to_cqlnode(xQuery); - yaz_log (LOG_LOG, "xcql"); - cql_transform_buf (cql_transform_handle, tree, - pqf_buf, sizeof(pqf_buf)); - cql_node_destroy(tree); - } - if (!error) - { - mylock(&target_mutex); - t = target_use (zurl, *pqf_buf ? pqf_buf : 0, schema, &s, properties); - myunlock(&target_mutex); - } - - if (!error && !t->m_c) - { - reconnect(t); - if (ZOOM_connection_error (t->m_c, &msg, &addinfo)) - { - yaz_log (LOG_LOG, "%s: connect failed", t->m_name); - error = ERROR_NO_TARGET; - } - else - yaz_log (LOG_LOG, "%s: connect ok", t->m_name); - } - if (!error && t->m_c && *pqf_buf) - { - if (properties->optimize_level <=1 || - strcmp (pqf_buf, s->m_query) || - strcmp (schema, s->m_schema)) - { - /* not the same query: remove result set .. */ - ZOOM_resultset_destroy (s->m_r); - s->m_r = 0; - } - else - { - /* same query: retrieve (instead of doing search) */ - if (maximumRecords && *maximumRecords > 0) - { - int start = startRecord ? *startRecord : 1; - yaz_log (LOG_LOG, "%s: present start=%d count=%d pqf=%s", - t->m_name, start, *maximumRecords, pqf_buf); - wrbuf_printf (wr_log, "%s: present start=%d count=%d pqf=%s", - t->m_name, start, *maximumRecords, pqf_buf); - ZOOM_resultset_records (s->m_r, 0, start-1, *maximumRecords); - error = ZOOM_connection_error (t->m_c, &msg, &addinfo); - if (error == ZOOM_ERROR_CONNECTION_LOST || - error == ZOOM_ERROR_CONNECT) - { - reconnect (t); - if ((error = ZOOM_connection_error (t->m_c, &msg, - &addinfo))) - { - yaz_log (LOG_LOG, "%s: connect failed", t->m_name); - error = ERROR_NO_TARGET; - } - } - else if (error) - { - yaz_log (LOG_LOG, "%s: present failed bib1-code=%d", - t->m_name, error); - error = diag_bib1_to_srw(error); - } - } - else - { - yaz_log (LOG_LOG, "%s: matched search pqf=%s", - t->m_name, pqf_buf); - wrbuf_printf (wr_log, "%s: matched search pqf=%s", - t->m_name, pqf_buf); - } - } - if (!error && !s->m_r) - { /* no result set usable. We must search ... */ - int pass; - for (pass = 0; pass < 2; pass++) - { - char val[30]; - int start = startRecord ? *startRecord : 1; - int count = maximumRecords ? *maximumRecords : 0; - - sprintf (val, "%d", start-1); - ZOOM_connection_option_set (t->m_c, "start", val); - - sprintf (val, "%d", count); - ZOOM_connection_option_set (t->m_c, "count", val); - - ZOOM_connection_option_set (t->m_c, "preferredRecordSyntax", - "usmarc"); - - xfree (s->m_query); - s->m_query = xstrdup (pqf_buf); - - xfree (s->m_schema); - s->m_schema = xstrdup (schema); - - yaz_log (LOG_LOG, "%s: search start=%d count=%d pqf=%s", - t->m_name, start, count, pqf_buf); - - wrbuf_printf (wr_log, "%s: search start=%d count=%d pqf=%s", - t->m_name, start, count, pqf_buf); - - s->m_r = ZOOM_connection_search_pqf (t->m_c, s->m_query); - - error = ZOOM_connection_error (t->m_c, &msg, &addinfo); - if (!error) - break; - if (error != ZOOM_ERROR_CONNECTION_LOST && - error != ZOOM_ERROR_CONNECT) - { - yaz_log (LOG_LOG, "%s: search failed bib1-code=%d", - t->m_name, error); - error = diag_bib1_to_srw(error); - break; - } - yaz_log (LOG_LOG, "%s: reconnect (search again)", t->m_name); - - /* try once more */ - reconnect(t); - - error = ZOOM_connection_error (t->m_c, &msg, &addinfo); - - if (error) - { - error = ERROR_NO_TARGET; - break; - } - } - } - } - - if (!error && t->m_c && s->m_r) - { - yaz_log (LOG_LOG, "%s: %d hits", t->m_name, - ZOOM_resultset_size(s->m_r)); - res->numberOfRecords = ZOOM_resultset_size(s->m_r); - - if (maximumRecords) - { - int i, j = 0; - int offset = startRecord ? *startRecord -1 : 0; - res->records.record = - soap_malloc(soap, sizeof(*res->records.record) * - *maximumRecords); - - for (i = 0; i < *maximumRecords; i++) - { - char *rec_data = 0; - char *rec_schema = 0; - ZOOM_record zrec = ZOOM_resultset_record (s->m_r, offset + i); - if (!zrec) - { - error = 65; - addinfo = schema; - break; - } - error = fetchone(soap, properties, zrec, schema, - &rec_data, &rec_schema); - if (error) - { - addinfo = rec_data; - break; - } - res->records.record[j] = - soap_malloc(soap, sizeof(**res->records.record)); - res->records.record[j]->recordData = rec_data; - res->records.record[j]->recordSchema = rec_schema; - j++; - } - res->records.__sizeRecords = j; - } - else - res->numberOfRecords = 0; - } - if (error) - { - if (s) - { - ZOOM_resultset_destroy (s->m_r); - s->m_r = 0; - } - if (error == ERROR_NO_TARGET) - { - addinfo = zurl; - ZOOM_connection_destroy (t->m_c); - t->m_c = 0; - } - else - { - res->diagnostics.__sizeDiagnostics = 1; - res->diagnostics.diagnostic = - soap_malloc (soap, sizeof(*res->diagnostics.diagnostic)); - res->diagnostics.diagnostic[0] = - soap_malloc (soap, sizeof(**res->diagnostics.diagnostic)); - - res->diagnostics.diagnostic[0]->code = error; - if (addinfo) - { - res->diagnostics.diagnostic[0]->details = - soap_malloc (soap, strlen(addinfo) + 1); - strcpy (res->diagnostics.diagnostic[0]->details, addinfo); - } - else - res->diagnostics.diagnostic[0]->details = 0; - } - } - else - { - if (s->m_r) - { - struct timeval tv; - const char *setname = ZOOM_resultset_option_get(s->m_r, "setname"); - if (strcmp(setname, "default") && s->m_idle_time) - { - res->resultSetId = soap_malloc(soap, strlen(setname)); - strcpy(res->resultSetId, setname); - res->resultSetIdleTime = s->m_idle_time; - gettimeofday(&tv, 0); - s->m_expiry_sec = res->resultSetIdleTime + tv.tv_sec + 2; - } else { - s->m_expiry_sec = 0; - } - } - } - - if (t) - { - if (properties->optimize_level > 0) - target_leave(t); - else - target_destroy(t); - } - wrbuf_free(wr_log, 1); - if (error == ERROR_NO_TARGET) - return soap_receiver_fault(soap, "Cannot connect to Z39.50 target", 0); - return SOAP_OK; -} - -int main(int argc, char **argv) -{ - struct soap soap; - int ret; - int port = 0; - int no_threads = 40; - char *arg; - const char *host = 0; - struct srw_prop properties; - - properties.optimize_level = 2; - properties.idle_time = 300; - properties.max_sets = 30; - properties.maps = 0; - - while ((ret = options("dO:T:l:hVp:s:x:i:", argv, argc, &arg)) != -2) - { - switch(ret) - { - case 0: - port = atoi(arg); - break; - case 'O': - properties.optimize_level = atoi(arg); - break; - case 'T': - no_threads = atoi(arg); - if (no_threads < 1 || no_threads > 200) - no_threads = 40; - break; - case 's': - if (!properties.maps) - { - properties.maps = xslt_maps_create(); - if (xslt_maps_file(properties.maps, arg)) - { - fprintf (stderr, "maps file %s could not be opened\n", - arg); - exit(1); - } - } - break; - case 'l': - yaz_log_init_file(arg); - break; - case 'V': - puts ("Version: $Id: srw-gateway.c,v 1.2 2003-01-20 13:04:50 adam Exp $" -#if SRW_DEBUG - " DEBUG" -#endif - ); - exit (0); - case 'p': - if (cql_transform_handle == 0) - cql_transform_handle = cql_transform_open_fname(arg); - break; - case 'x': - properties.max_sets = atoi(arg); - break; - case 'i': - properties.idle_time = atoi(arg); - break; - case 'h': - printf ("srw-gateway [options] \n"); - printf (" port port for standalone service; If port is omitted, CGI is used.\n"); - printf (" -O n optimize level. >= 1 cache connections, >=2 cache result sets.\n"); -#if USE_THREADS - printf (" -T n number of threads.\n"); -#else - printf (" -T unsupported in this version.\n"); -#endif - printf (" -l file log to file (instead of stderr).\n"); - printf (" -p file PQF properties.\n"); - printf (" -s file schema maps.\n"); - printf (" -i time idle time.\n"); - printf (" -x sets live sets.\n"); - printf (" -V show version.\n"); - exit (1); - default: - fprintf (stderr, "srw-gateway: bad option -%s ; use -h for help\n", - arg); - exit (1); - break; - - } - } - if (!cql_transform_handle) - cql_transform_handle = cql_transform_open_fname("pqf.properties"); - if (!properties.maps) - { - properties.maps = xslt_maps_create(); - xslt_maps_file(properties.maps, "maps.xml"); - } - soap.encodingStyle = 0; - if (port == 0 && getenv("QUERY_STRING")) - { - properties.optimize_level = 0; - - yaz_log_init_file("srw.log"); - yaz_log (LOG_LOG, "CGI begin"); - soap_init(&soap); - soap.user = &properties; - - yaz_srw_serve(&soap, searchRetrieve, explain); - - soap_end(&soap); - yaz_log (LOG_LOG, "CGI end"); - } - else if (port) - { - if (!cql_transform_handle) - { - fprintf(stderr, "no properties file; use option -p to specify\n"); - exit (1); - } - yaz_log (LOG_LOG, "standalone service on port %d", port); - - soap_init(&soap); - - standalone(&soap, host, port, no_threads, &properties); - } - else - { - fprintf(stderr, "srw-gateway: no port specified. Use -h for help\n"); - } - xslt_maps_free(properties.maps); - return 0; -} diff --git a/util/matchstr.c b/util/matchstr.c index 0863781..538b435 100644 --- a/util/matchstr.c +++ b/util/matchstr.c @@ -1,50 +1,9 @@ /* - * Copyright (c) 1995-2000, Index Data. + * Copyright (c) 1995-2003, Index Data. * See the file LICENSE for details. * Sebastian Hammer, Adam Dickmeiss * - * $Log: matchstr.c,v $ - * Revision 1.5 2000-02-29 13:44:55 adam - * Check for config.h (currently not generated). - * - * Revision 1.4 1999/11/30 13:47:12 adam - * Improved installation. Moved header files to include/yaz. - * - * Revision 1.3 1999/10/19 12:35:42 adam - * Minor bug fix (bug introduced by previous commit). - * - * Revision 1.2 1999/10/15 11:35:41 adam - * Character '.' matches any single character. - * - * Revision 1.1 1999/06/08 10:10:16 adam - * New sub directory zutil. Moved YAZ Compiler to be part of YAZ tree. - * - * Revision 1.7 1997/09/30 11:47:47 adam - * Added function 'cause checkergcc doesn't include assert handler. - * - * Revision 1.6 1997/09/04 07:54:34 adam - * Right hande side operand of yaz_matchstr may include a ? in - * which case it returns "match ok". - * - * Revision 1.5 1997/07/21 12:48:11 adam - * Removed windows DLL stubs. - * - * Revision 1.4 1997/05/01 15:07:55 adam - * Added DLL entry point routines. - * - * Revision 1.3 1996/10/29 13:36:28 adam - * Added header. - * - * Revision 1.2 1996/02/20 17:58:42 adam - * Added const to yaz_matchstr. - * - * Revision 1.1 1996/02/20 16:33:06 quinn - * Moved matchstr to global util - * - * Revision 1.1 1995/11/01 11:56:08 quinn - * Added Retrieval (data management) functions en masse. - * - * + * $Id: matchstr.c,v 1.6 2003-02-12 15:06:44 adam Exp $ */ #if HAVE_CONFIG_H #include @@ -91,6 +50,20 @@ int yaz_matchstr(const char *s1, const char *s2) return *s1 || *s2; } +int yaz_strcmp_del(const char *a, const char *b, const char *b_del) +{ + while (*a && *b) + { + if (*a != *b) + return *a - *b; + a++; + b++; + } + if (b_del && strchr(b_del, *b)) + return *a; + return *a - *b; +} + #ifdef __GNUC__ #ifdef __CHECKER__ void __assert_fail (const char *assertion, const char *file, diff --git a/yaz-config.in b/yaz-config.in index 5faf6d0..7824d02 100644 --- a/yaz-config.in +++ b/yaz-config.in @@ -1,5 +1,5 @@ #!/bin/sh -# $Id: yaz-config.in,v 1.15 2003-01-06 08:20:26 adam Exp $ +# $Id: yaz-config.in,v 1.16 2003-02-12 15:06:42 adam Exp $ yazprefix=@prefix@ yaz_echo_cflags=no yaz_echo_libs=no @@ -10,7 +10,7 @@ yaz_echo_comp=no yaz_src_root=@YAZ_SRC_ROOT@ yaz_build_root=@YAZ_BUILD_ROOT@ -yazextralibs="@GSOAP_LIB@ @XSLT_LIB@ @LIBS@" +yazextralibs="@XSLT_LIB@ @LIBS@" YAZVERSION=@VERSION@ usage() diff --git a/z39.50/z3950v3.asn b/z39.50/z3950v3.asn index 42c7ee8..09185f1 100644 --- a/z39.50/z3950v3.asn +++ b/z39.50/z3950v3.asn @@ -101,7 +101,7 @@ IdAuthentication ::= accessCtrl (6), scan (7), sort (8), - -- (9) (reserved) + -- (not used) (9), extendedServices (10), level-1Segmentation (11), level-2Segmentation (12), @@ -109,9 +109,12 @@ IdAuthentication ::= namedResultSets (14), encapsulation (15), resultCount (16), - negotiationModel (17), - duplicateDetection (18), - queryType104 (19)} + negotiationModel (17), + duplicateDetection (18), + queryType104 (19), + pQESCorrection (20), + stringSchema (21) +} -- end auxiliary definitions for Init PDUs @@ -355,7 +358,10 @@ SearchResponse ::= SEQUENCE{ -- selectAlternativeSyntax is 'true'. } Specification ::= SEQUENCE{ - schema [1] IMPLICIT OBJECT IDENTIFIER OPTIONAL, + schema CHOICE { + oid [1] IMPLICIT OBJECT IDENTIFIER, + uri [300] IMPLICIT InternationalString + } OPTIONAL, elementSpec [2] CHOICE{ elementSetName [1] IMPLICIT InternationalString, externalEspec [2] IMPLICIT EXTERNAL} OPTIONAL} diff --git a/zoom/Makefile.am b/zoom/Makefile.am index 235e489..4283b6f 100644 --- a/zoom/Makefile.am +++ b/zoom/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.7 2003-01-06 08:20:28 adam Exp $ +## $Id: Makefile.am,v 1.8 2003-02-12 15:06:44 adam Exp $ ## Copyright (C) 2001, Index Data AM_CPPFLAGS = -I$(top_srcdir)/include @@ -6,15 +6,15 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_PROGRAMS = zoomtst1 zoomtst2 zoomtst3 zoomtst4 zoomtst5 zoomtst6 zoomtst7 zoomtst8 bin_PROGRAMS = zoomsh -zoomtst1_LDADD = ../lib/libyaz.la $(GSOAP_LIB) -zoomtst2_LDADD = ../lib/libyaz.la $(GSOAP_LIB) -zoomtst3_LDADD = ../lib/libyaz.la $(GSOAP_LIB) -zoomtst4_LDADD = ../lib/libyaz.la $(GSOAP_LIB) -zoomtst5_LDADD = ../lib/libyaz.la $(GSOAP_LIB) -zoomtst6_LDADD = ../lib/libyaz.la $(GSOAP_LIB) -zoomtst7_LDADD = ../lib/libyazmalloc.la ../lib/libyaz.la $(GSOAP_LIB) -zoomtst8_LDADD = ../lib/libyaz.la $(GSOAP_LIB) -zoomsh_LDADD = ../lib/libyaz.la $(GSOAP_LIB) $(READLINE_LIBS) +zoomtst1_LDADD = ../lib/libyaz.la $(XSLT_LIB) +zoomtst2_LDADD = ../lib/libyaz.la $(XSLT_LIB) +zoomtst3_LDADD = ../lib/libyaz.la $(XSLT_LIB) +zoomtst4_LDADD = ../lib/libyaz.la $(XSLT_LIB) +zoomtst5_LDADD = ../lib/libyaz.la $(XSLT_LIB) +zoomtst6_LDADD = ../lib/libyaz.la $(XSLT_LIB) +zoomtst7_LDADD = ../lib/libyazmalloc.la ../lib/libyaz.la $(XSLT_LIB) +zoomtst8_LDADD = ../lib/libyaz.la $(XSLT_LIB) +zoomsh_LDADD = ../lib/libyaz.la $(XSLT_LIB) $(READLINE_LIBS) zoomtst1_SOURCES = zoomtst1.c zoomtst2_SOURCES = zoomtst2.c diff --git a/ztest/Makefile.am b/ztest/Makefile.am index 1f17acb..3922dd8 100644 --- a/ztest/Makefile.am +++ b/ztest/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.11 2002-04-15 09:44:44 adam Exp $ +## $Id: Makefile.am,v 1.12 2003-02-12 15:06:44 adam Exp $ if ISSSL sslbin=yaz-ztest-ssl @@ -16,11 +16,11 @@ extra=../lib/libyazthread.la endif yaz_ztest_LDADD=$(extra) ../lib/libyaz.la \ - $(LIBTHREAD) + $(XSLT_LIB) $(LIBTHREAD) yaz_ztest_ssl_LDADD=$(extra) ../lib/libyazssl.la ../lib/libyaz.la \ - $(SSL_LIBS) $(LIBTHREAD) + $(SSL_LIBS) $(XSLT_LIB) $(LIBTHREAD) AM_CFLAGS=@CFLAGSTHREADS@ -AM_CPPFLAGS=-I$(top_srcdir)/include +AM_CPPFLAGS=-I$(top_srcdir)/include $(XSLT_CFLAGS) diff --git a/zutil/Makefile.am b/zutil/Makefile.am index 2b848ba..08c742c 100644 --- a/zutil/Makefile.am +++ b/zutil/Makefile.am @@ -1,8 +1,13 @@ -## $Id: Makefile.am,v 1.14 2003-01-06 08:20:29 adam Exp $ +## $Id: Makefile.am,v 1.15 2003-02-12 15:06:44 adam Exp $ noinst_LTLIBRARIES = libzutil.la -AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/srw +AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/srw $(XSLT_CFLAGS) libzutil_la_SOURCES = zget.c yaz-ccl.c diagbib1.c logrpn.c \ otherinfo.c pquery.c sortspec.c z3950oid.c charneg.c \ - zoom-c.c zoom-opt.c zoom-p.h grs1disp.c + zoom-c.c zoom-opt.c zoom-p.h grs1disp.c zgdu.c soap.c srw.c + +srwtst_LDADD = ../odr/libodr.la libzutil.la $(XSLT_LIB) ../util/libutil.la +srwtst_SOURCES = srwtst.c + +noinst_PROGRAMS = srwtst \ No newline at end of file diff --git a/zutil/logrpn.c b/zutil/logrpn.c index 229c59f..9d46fad 100644 --- a/zutil/logrpn.c +++ b/zutil/logrpn.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2001, Index Data * All rights reserved. * - * $Id: logrpn.c,v 1.9 2003-01-06 08:20:29 adam Exp $ + * $Id: logrpn.c,v 1.10 2003-02-12 15:06:44 adam Exp $ */ #include @@ -353,7 +353,6 @@ void log_scan_term (Z_AttributesPlusTerm *zapt, oid_value ast) void yaz_log_zquery (Z_Query *q) { - static int cql_oid[] = {1, 2, 840, 10003, 16, 2, -1}; switch (q->which) { case Z_Query_type_1: case Z_Query_type_101: diff --git a/zutil/soap.c b/zutil/soap.c new file mode 100644 index 0000000..911f367 --- /dev/null +++ b/zutil/soap.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2002-2003, Index Data. + * See the file LICENSE for details. + * + * $Id: soap.c,v 1.1 2003-02-12 15:06:44 adam Exp $ + */ + +#include + +static const char *soap_v1_1 = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char *soap_v1_2 = "http://www.w3.org/2001/06/soap-envelope"; + +int z_soap_error(ODR o, Z_SOAP *p, + const char *fault_code, const char *fault_string, + const char *details) +{ + p->which = Z_SOAP_error; + p->u.soap_error = odr_malloc(o, sizeof(*p->u.soap_error)); + p->u.soap_error->fault_code = odr_strdup(o, fault_code); + p->u.soap_error->fault_string = odr_strdup(o, fault_string); + if (details) + p->u.soap_error->details = odr_strdup(o, details); + else + p->u.soap_error->details = 0; + return -1; +} + +int z_soap_codec(ODR o, Z_SOAP **pp, + char **content_buf, int *content_len, + Z_SOAP_Handler *handlers) +{ + if (o->direction == ODR_DECODE) + { + Z_SOAP *p; + xmlNodePtr ptr, pptr; + xmlDocPtr doc; + int i, ret; + + if (!content_buf || !*content_buf || !content_len) + return -1; + + *pp = p = odr_malloc(o, sizeof(*p)); + p->ns = soap_v1_1; + + doc = xmlParseMemory(*content_buf, *content_len); + if (!doc) + return z_soap_error(o, p, "SOAP-ENV:Client", + "Bad XML Document", 0); + /* check that root node is Envelope */ + ptr = xmlDocGetRootElement(doc); + if (!ptr || ptr->type != XML_ELEMENT_NODE || + strcmp(ptr->name, "Envelope")) + { + xmlFreeDoc(doc); + return z_soap_error(o, p, "SOAP-ENV:Client", + "No Envelope element", 0); + } + else + { + /* determine SOAP version */ + const char * ns_envelope = ptr->ns->href; + if (!strcmp(ns_envelope, soap_v1_1)) + p->ns = soap_v1_1; + else if (!strcmp(ns_envelope, soap_v1_2)) + p->ns = soap_v1_2; + else + { + xmlFreeDoc(doc); + return z_soap_error(o, p, "SOAP-ENV:Client", + "Bad SOAP version", 0); + } + } + ptr = ptr->children; + while(ptr && ptr->type == XML_TEXT_NODE) + ptr = ptr->next; + if (ptr && ptr->type == XML_ELEMENT_NODE && + !strcmp(ptr->ns->href, p->ns) && + !strcmp(ptr->name, "Header")) + { + ptr = ptr->next; + while(ptr && ptr->type == XML_TEXT_NODE) + ptr = ptr->next; + } + /* check that Body is present */ + if (!ptr || ptr->type != XML_ELEMENT_NODE || + strcmp(ptr->name, "Body")) + { + xmlFreeDoc(doc); + return z_soap_error(o, p, "SOAP-ENV:Client", + "SOAP Body element not found", 0); + } + if (strcmp(ptr->ns->href, p->ns)) + { + xmlFreeDoc(doc); + return z_soap_error(o, p, "SOAP-ENV:Client", + "SOAP bad NS for Body element", 0); + } + pptr = ptr; + ptr = ptr->children; + while (ptr && ptr->type == XML_TEXT_NODE) + ptr = ptr->next; + if (!ptr || ptr->type != XML_ELEMENT_NODE) + { + xmlFreeDoc(doc); + return z_soap_error(o, p, "SOAP-ENV:Client", + "SOAP No content for Body", 0); + } + /* check for fault package */ + if (!strcmp(ptr->ns->href, p->ns) + && !strcmp(ptr->name, "Fault") && ptr->children) + { + ptr = ptr->children; + + p->which = Z_SOAP_fault; + p->u.fault = odr_malloc(o, sizeof(*p->u.fault)); + p->u.fault->fault_code = 0; + p->u.fault->fault_string = 0; + p->u.fault->details = 0; + while (ptr) + { + if (ptr->children && ptr->children->type == XML_TEXT_NODE) + { + if (!strcmp(ptr->name, "faultcode")) + p->u.fault->fault_code = + odr_strdup(o, ptr->children->content); + if (!strcmp(ptr->name, "faultstring")) + p->u.fault->fault_string = + odr_strdup(o, ptr->children->content); + if (!strcmp(ptr->name, "details")) + p->u.fault->details = + odr_strdup(o, ptr->children->content); + } + ptr = ptr->next; + } + ret = 0; + } + else + { + for (i = 0; handlers[i].ns; i++) + if (!strcmp(ptr->ns->href, handlers[i].ns)) + break; + if (handlers[i].ns) + { + void *handler_data = 0; + ret = (*handlers[i].f)(o, pptr, &handler_data, + handlers[i].client_data, + handlers[i].ns); + if (ret || !handler_data) + z_soap_error(o, p, "SOAP-ENV:Client", + "SOAP Handler returned error", 0); + else + { + p->which = Z_SOAP_generic; + p->u.generic = odr_malloc(o, sizeof(*p->u.generic)); + p->u.generic->no = i; + p->u.generic->ns = handlers[i].ns; + p->u.generic->p = handler_data; + } + } + else + { + ret = z_soap_error(o, p, "SOAP-ENV:Client", + "No handler for NS", 0); + } + } + xmlFreeDoc(doc); + return ret; + } + else if (o->direction == ODR_ENCODE) + { + Z_SOAP *p = *pp; + xmlNsPtr ns_env; + xmlNodePtr envelope_ptr, body_ptr; + xmlChar *buf_out; + int len_out; + + xmlDocPtr doc = xmlNewDoc("1.0"); + + envelope_ptr = xmlNewNode(0, "Envelope"); + ns_env = xmlNewNs(envelope_ptr, p->ns, "SOAP-ENV"); + body_ptr = xmlNewChild(envelope_ptr, ns_env, "Body", 0); + xmlDocSetRootElement(doc, envelope_ptr); + + if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error) + { + Z_SOAP_Fault *f = p->u.fault; + xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env, "Fault", 0); + xmlNewChild(fault_ptr, ns_env, "faultcode", f->fault_code); + xmlNewChild(fault_ptr, ns_env, "faultstring", f->fault_string); + if (f->details) + xmlNewChild(fault_ptr, ns_env, "details", f->details); + } + else if (p->which == Z_SOAP_generic) + { + int ret, no = p->u.generic->no; + + ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p, + handlers[no].client_data, + handlers[no].ns); + if (ret) + return ret; + } + xmlDocDumpMemory(doc, &buf_out, &len_out); + *content_buf = odr_malloc(o, len_out); + *content_len = len_out; + memcpy(*content_buf, buf_out, len_out); + xmlFree(buf_out); + xmlFreeDoc(doc); + return 0; + } + return 0; +} diff --git a/zutil/srw.c b/zutil/srw.c new file mode 100644 index 0000000..1fa9fca --- /dev/null +++ b/zutil/srw.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2002-2003, Index Data. + * See the file LICENSE for details. + * + * $Id: srw.c,v 1.1 2003-02-12 15:06:44 adam Exp $ + */ + +#include + +static void add_xsd_string_n(xmlNodePtr ptr, const char *elem, char *val, + int len) +{ + if (val) + { + xmlNodePtr c = xmlNewChild(ptr, 0, elem, 0); + xmlNodePtr t = xmlNewTextLen(val, len); + xmlAddChild(c, t); + } +} + +static void add_xsd_string(xmlNodePtr ptr, const char *elem, char *val) +{ + if (val) + xmlNewChild(ptr, 0, elem, val); +} + +static void add_xsd_integer(xmlNodePtr ptr, const char *elem, int *val) +{ + if (val) + { + char str[30]; + sprintf(str, "%d", *val); + xmlNewChild(ptr, 0, elem, str); + } +} + +static int match_element(xmlNodePtr ptr, const char *elem) +{ + if (ptr->type == XML_ELEMENT_NODE && !strcmp(ptr->name, elem)) + return 1; + return 0; +} + +static int match_xsd_string_n(xmlNodePtr ptr, const char *elem, ODR o, + char **val, int *len) +{ + struct _xmlAttr *attr; + if (!match_element(ptr, elem)) + return 0; + for (attr = ptr->properties; attr; attr = attr->next) + if (!strcmp(attr->name, "type") && + attr->children && attr->children->type == XML_TEXT_NODE) + { + const char *t = strchr(attr->children->content, ':'); + if (t) + t = t + 1; + else + t = attr->children->content; + if (!strcmp(t, "string")) + break; + } + if (!attr) + return 0; + ptr = ptr->children; + if (!ptr || ptr->type != XML_TEXT_NODE) + return 0; + *val = odr_strdup(o, ptr->content); + if (len) + *len = strlen(ptr->content); + return 1; +} + + +static int match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o, + char **val) +{ + return match_xsd_string_n(ptr, elem, o, val, 0); +} + +static int match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o, int **val) +{ + struct _xmlAttr *attr; + if (!match_element(ptr, elem)) + return 0; + for (attr = ptr->properties; attr; attr = attr->next) + if (!strcmp(attr->name, "type") && + attr->children && attr->children->type == XML_TEXT_NODE) + { + const char *t = strchr(attr->children->content, ':'); + if (t) + t = t + 1; + else + t = attr->children->content; + if (!strcmp(t, "integer")) + break; + } + if (!attr) + return 0; + ptr = ptr->children; + if (!ptr || ptr->type != XML_TEXT_NODE) + return 0; + *val = odr_intdup(o, atoi(ptr->content)); + return 1; +} + +static int yaz_srw_records(ODR o, xmlNodePtr pptr, Z_SRW_record **recs, + int *num, void *client_data, const char *ns) +{ + if (o->direction == ODR_DECODE) + { + int i; + xmlNodePtr ptr; + *num = 0; + for (ptr = pptr->children; ptr; ptr = ptr->next) + { + if (ptr->type == XML_ELEMENT_NODE && + !strcmp(ptr->name, "record")) + (*num)++; + } + if (!*num) + return 1; + *recs = odr_malloc(o, *num * sizeof(**recs)); + for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++) + { + if (ptr->type == XML_ELEMENT_NODE && + !strcmp(ptr->name, "record")) + { + xmlNodePtr rptr; + (*recs)[i].recordSchema = 0; + (*recs)[i].recordData_buf = 0; + (*recs)[i].recordData_len = 0; + (*recs)[i].recordPosition = 0; + for (rptr = ptr->children; rptr; rptr = rptr->next) + { + if (match_xsd_string(rptr, "recordSchema", o, + &(*recs)[i].recordSchema)) + ; + else if (match_xsd_string_n(rptr, "recordData", o, + &(*recs)[i].recordData_buf, + &(*recs)[i].recordData_len)) + ; + else if (match_xsd_integer(rptr, "recordPosition", o, + &(*recs)[i].recordPosition)) + ; + } + } + } + } + else if (o->direction == ODR_ENCODE) + { + int i; + for (i = 0; i < *num; i++) + { + xmlNodePtr rptr = xmlNewChild(pptr, 0, "record", 0); + add_xsd_string(rptr, "recordSchema", (*recs)[i].recordSchema); + add_xsd_string_n(rptr, "recordData", (*recs)[i].recordData_buf, + (*recs)[i].recordData_len); + add_xsd_integer(rptr, "recordPosition", (*recs)[i].recordPosition); + } + } + return 0; +} + +static int yaz_srw_diagnostics(ODR o, xmlNodePtr pptr, Z_SRW_diagnostic **recs, + int *num, void *client_data, const char *ns) +{ + if (o->direction == ODR_DECODE) + { + int i; + xmlNodePtr ptr; + *num = 0; + for (ptr = pptr->children; ptr; ptr = ptr->next) + { + if (ptr->type == XML_ELEMENT_NODE && + !strcmp(ptr->name, "diagnostic")) + (*num)++; + } + if (!*num) + return 1; + *recs = odr_malloc(o, *num * sizeof(**recs)); + for (i = 0, ptr = pptr->children; ptr; ptr = ptr->next, i++) + { + if (ptr->type == XML_ELEMENT_NODE && + !strcmp(ptr->name, "diagnostic")) + { + xmlNodePtr rptr; + (*recs)[i].code = 0; + (*recs)[i].details = 0; + for (rptr = ptr->children; rptr; rptr = rptr->next) + { + if (match_xsd_integer(rptr, "code", o, + &(*recs)[i].code)) + ; + else if (match_xsd_string(rptr, "details", o, + &(*recs)[i].details)) + ; + } + i++; + } + } + } + else if (o->direction == ODR_ENCODE) + { + int i; + for (i = 0; i < *num; i++) + { + xmlNodePtr rptr = xmlNewChild(pptr, 0, "diagnostic", 0); + add_xsd_integer(rptr, "code", (*recs)[i].code); + add_xsd_string(rptr, "details", (*recs)[i].details); + } + } + return 0; +} + + +int yaz_srw_codec(ODR o, xmlNodePtr pptr, Z_SRW_searchRetrieve **handler_data, + void *client_data, const char *ns) +{ + if (o->direction == ODR_DECODE) + { + xmlNodePtr method = pptr->children; + + while (method && method->type == XML_TEXT_NODE) + method = method->next; + + if (method->type != XML_ELEMENT_NODE) + return -1; + if (method && !strcmp(method->name, "searchRetrieveRequest")) + { + Z_SRW_searchRetrieve **p = handler_data; + xmlNodePtr ptr = method->children; + Z_SRW_searchRetrieveRequest *req; + + *p = odr_malloc(o, sizeof(**p)); + (*p)->which = Z_SRW_searchRetrieve_request; + req = (*p)->u.request = odr_malloc(o, sizeof(*req)); + req->query = 0; + req->xQuery = 0; + req->sortKeys = 0; + req->xSortKeys = 0; + req->startRecord = 0; + req->maximumRecords = 0; + req->recordSchema = 0; + req->recordPacking = 0; + + for (; ptr; ptr = ptr->next) + { + if (match_xsd_string(ptr, "query", o, + &req->query)) + ; + else if (match_xsd_string(ptr, "pQuery", o, + &req->pQuery)) + ; + else if (match_xsd_string(ptr, "sortKeys", o, + &req->sortKeys)) + ; + else if (match_xsd_string(ptr, "recordSchema", o, + &req->recordSchema)) + ; + else if (match_xsd_string(ptr, "recordPacking", o, + &req->recordPacking)) + ; + else if (match_xsd_integer(ptr, "startRecord", o, + &req->startRecord)) + ; + else if (match_xsd_integer(ptr, "maximumRecords", o, + &req->maximumRecords)) + ; + /* missing is xQuery, xSortKeys .. */ + } + } + else if (method && !strcmp(method->name, "searchRetrieveResponse")) + { + Z_SRW_searchRetrieve **p = handler_data; + xmlNodePtr ptr = method->children; + Z_SRW_searchRetrieveResponse *res; + + *p = odr_malloc(o, sizeof(**p)); + (*p)->which = Z_SRW_searchRetrieve_response; + res = (*p)->u.response = odr_malloc(o, sizeof(*res)); + + res->numberOfRecords = 0; + res->resultSetId = 0; + res->resultSetIdleTime = 0; + res->records = 0; + res->num_records = 0; + res->diagnostics = 0; + res->num_diagnostics = 0; + res->nextRecordPosition = 0; + + for (; ptr; ptr = ptr->next) + { + if (match_xsd_integer(ptr, "numberOfRecords", o, + &res->numberOfRecords)) + ; + else if (match_xsd_string(ptr, "resultSetId", o, + &res->resultSetId)) + ; + else if (match_xsd_integer(ptr, "resultSetIdleTime", o, + &res->resultSetIdleTime)) + ; + else if (match_element(ptr, "records")) + yaz_srw_records(o, ptr, &res->records, + &res->num_records, client_data, + ns); + else if (match_element(ptr, "diagnostics")) + yaz_srw_diagnostics(o, ptr, &res->diagnostics, + &res->num_diagnostics, + client_data, ns); + else if (match_xsd_integer(ptr, "nextRecordPosition", o, + &res->nextRecordPosition)) + ; + } + + } + else + return -1; + + } + else if (o->direction == ODR_ENCODE) + { + Z_SRW_searchRetrieve **p = handler_data; + if ((*p)->which == Z_SRW_searchRetrieve_request) + { + Z_SRW_searchRetrieveRequest *req = (*p)->u.request; + xmlNsPtr ns_srw = xmlNewNs(pptr, ns, "zs"); + xmlNodePtr ptr = xmlNewChild(pptr, ns_srw, + "searchRetrieveRequest", 0); + + add_xsd_string(ptr, "query", req->query); + add_xsd_string(ptr, "pQuery", req->pQuery); + add_xsd_string(ptr, "sortKeys", req->sortKeys); + add_xsd_integer(ptr, "startRecord", req->startRecord); + add_xsd_integer(ptr, "maximumRecords", req->maximumRecords); + add_xsd_string(ptr, "recordSchema", req->recordSchema); + add_xsd_string(ptr, "recordPacking", req->recordPacking); + } + else if ((*p)->which == Z_SRW_searchRetrieve_response) + { + Z_SRW_searchRetrieveResponse *res = (*p)->u.response; + xmlNsPtr ns_srw = xmlNewNs(pptr, ns, "zs"); + xmlNodePtr ptr = xmlNewChild(pptr, ns_srw, + "searchRetrieveResponse", 0); + + add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords); + add_xsd_string(ptr, "resultSetId", res->resultSetId); + add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime); + if (res->num_records) + { + xmlNodePtr rptr = xmlNewChild(ptr, 0, "records", 0); + yaz_srw_records(o, rptr, &res->records, &res->num_records, + client_data, ns); + } + if (res->num_diagnostics) + { + xmlNodePtr rptr = xmlNewChild(ptr, 0, "diagnostics", 0); + yaz_srw_diagnostics(o, rptr, &res->diagnostics, + &res->num_diagnostics, client_data, ns); + } + add_xsd_integer(ptr, "nextRecordPosition", res->nextRecordPosition); + } + else + return -1; + + } + return 0; +} + +Z_SRW_searchRetrieve *yaz_srw_get(ODR o, int which) +{ + Z_SRW_searchRetrieve *sr = odr_malloc(o, sizeof(*o)); + sr->which = which; + switch(which) + { + case Z_SRW_searchRetrieve_request: + sr->u.request = odr_malloc(o, sizeof(*sr->u.request)); + sr->u.request->query = 0; + sr->u.request->xQuery = 0; + sr->u.request->sortKeys = 0; + sr->u.request->xSortKeys = 0; + sr->u.request->startRecord = 0; + sr->u.request->maximumRecords = 0; + sr->u.request->recordSchema = 0; + sr->u.request->recordPacking = 0; + break; + case Z_SRW_searchRetrieve_response: + sr->u.response = odr_malloc(o, sizeof(*sr->u.response)); + sr->u.response->numberOfRecords = 0; + sr->u.response->resultSetId = 0; + sr->u.response->resultSetIdleTime = 0; + sr->u.response->records = 0; + sr->u.response->num_records = 0; + sr->u.response->diagnostics = 0; + sr->u.response->num_diagnostics = 0; + sr->u.response->nextRecordPosition = 0; + } + return sr; +} diff --git a/zutil/yaz-ccl.c b/zutil/yaz-ccl.c index 12456d3..4e67499 100644 --- a/zutil/yaz-ccl.c +++ b/zutil/yaz-ccl.c @@ -2,12 +2,13 @@ * Copyright (c) 1996-2003, Index Data. * See the file LICENSE for details. * - * $Id: yaz-ccl.c,v 1.18 2003-01-06 08:20:29 adam Exp $ + * $Id: yaz-ccl.c,v 1.19 2003-02-12 15:06:44 adam Exp $ */ #include #include #include +#include #include #include diff --git a/zutil/zgdu.c b/zutil/zgdu.c new file mode 100644 index 0000000..c06777e --- /dev/null +++ b/zutil/zgdu.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2002-2003, Index Data. + * See the file LICENSE for details. + * + * $Id: zgdu.c,v 1.1 2003-02-12 15:06:44 adam Exp $ + */ + +#include + +#define HTTP_DEBUG 0 + +static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, + char **content_buf, int *content_len) +{ + int i = off; + + *headers = 0; + while (i < o->size-1 && o->buf[i] == '\r') + { + int po; + i++; + if (o->buf[i] != '\n') + { + o->error = OHTTP; + return 0; + } + i++; + if (o->buf[i] == '\r') + break; + for (po = i; ; i++) + { + if (i == o->size) + { + o->error = OHTTP; + return 0; + } + else if (o->buf[i] == ':') + break; + } + *headers = odr_malloc(o, sizeof(**headers)); + (*headers)->name = odr_malloc(o, i - po + 1); + memcpy ((*headers)->name, o->buf + po, i - po); + (*headers)->name[i - po] = '\0'; + i++; + while (i < o->size-1 && o->buf[i] == ' ') + i++; + for (po = i; i < o->size-1 && o->buf[i] != '\r' ; i++) + ; + + (*headers)->value = odr_malloc(o, i - po + 1); + memcpy ((*headers)->value, o->buf + po, i - po); + (*headers)->value[i - po] = '\0'; + + headers = &(*headers)->next; + } + *headers = 0; + i++; + if (o->buf[i] != '\n') + { + o->error = OHTTP; + return 0; + } + i++; + + if (i > o->size) + { + o->error = OHTTP; + return 0; + } + else if (i == o->size) + { + *content_buf = 0; + *content_len = 0; + } + else + { + *content_len = o->size - i; + *content_buf = odr_malloc(o, *content_len + 1); + memcpy(*content_buf, o->buf + i, *content_len); + (*content_buf)[*content_len] = '\0'; + } + return 1; +} + +void z_HTTP_header_add(ODR o, Z_HTTP_Header **hp, const char *n, + const char *v) +{ + while (*hp) + hp = &(*hp)->next; + *hp = odr_malloc(o, sizeof(**hp)); + (*hp)->name = odr_strdup(o, n); + (*hp)->value = odr_strdup(o, v); + (*hp)->next = 0; +} + +const char *z_HTTP_header_lookup(Z_HTTP_Header *hp, const char *n) +{ + for (; hp; hp = hp->next) + if (!strcmp(hp->name, n)) + return hp->value; + return 0; +} + + +Z_GDU *z_get_HTTP_Response(ODR o, int code) +{ + Z_GDU *p = odr_malloc(o, sizeof(*p)); + Z_HTTP_Response *hres; + + p->which = Z_GDU_HTTP_Response; + hres = p->u.HTTP_Response = odr_malloc(o, sizeof(*hres)); + hres->headers = 0; + hres->content_len = 0; + hres->content_buf = 0; + hres->code = code; + hres->version = "1.1"; + z_HTTP_header_add(o, &hres->headers, "Server", + "YAZ/" YAZ_VERSION); + if (code != 200) + { + hres->content_buf = odr_malloc(o, 400); + sprintf (hres->content_buf, + "\n" + "\n" + " \n" + " YAZ " YAZ_VERSION "\n" + " \n" + " \n" + "

YAZ " + YAZ_VERSION "

\n" + "

Error: %d

\n" + "

Description: %.50s

\n" + " \n" + "\n", + code, z_HTTP_errmsg(code)); + hres->content_len = strlen(hres->content_buf); + z_HTTP_header_add(o, &hres->headers, "Content-Type", "text/html"); + } + return p; +} + +const char *z_HTTP_errmsg(int code) +{ + if (code == 200) + return "OK"; + else if (code == 400) + return "Bad Request"; + else if (code == 404) + return "Not Found"; + else if (code == 405) + return "Method Not Allowed"; + else if (code == 500) + return "Internal Error"; + else + return "Unknown Error"; +} + +int z_GDU (ODR o, Z_GDU **p, int opt, const char *name) +{ + if (o->direction == ODR_DECODE) { + *p = odr_malloc(o, sizeof(**p)); + if (o->size > 10 && !memcmp(o->buf, "HTTP/", 5)) + { + int i, po; + Z_HTTP_Response *hr; + (*p)->which = Z_GDU_HTTP_Response; + + hr = (*p)->u.HTTP_Response = odr_malloc(o, sizeof(*hr)); + + po = i = 5; + while (i < o->size-2 && o->buf[i] != ' ' && o->buf[i] != '\r') + i++; + hr->version = odr_malloc(o, i - po + 1); + if (i - po) + memcpy(hr->version, o->buf + po, i - po); + hr->version[i-po] = 0; + if (o->buf[i] != ' ') + { + o->error = OHTTP; + return 0; + } + i++; + hr->code = 0; + while (i < o->size-2 && o->buf[i] >= '0' && o->buf[i] <= '9') + { + hr->code = hr->code*10 + (o->buf[i] - '0'); + i++; + } + while (i < o->size-1 && o->buf[i] != '\r') + i++; + return decode_headers_content(o, i, &hr->headers, + &hr->content_buf, &hr->content_len); + } + else if (o->size > 5 && + o->buf[0] >= 0x20 && o->buf[0] < 0x7f + && o->buf[1] >= 0x20 && o->buf[1] < 0x7f + && o->buf[2] >= 0x20 && o->buf[2] < 0x7f + && o->buf[3] >= 0x20 && o->buf[3] < 0x7f) + { + int i, po; + Z_HTTP_Request *hr; + +#if HTTP_DEBUG + fprintf(stderr, "HTTP decode:\n%.*s\n", o->size, o->buf); +#endif + (*p)->which = Z_GDU_HTTP_Request; + hr = (*p)->u.HTTP_Request = odr_malloc(o, sizeof(*hr)); + + /* method .. */ + for (i = 0; o->buf[i] != ' '; i++) + if (i >= o->size-5 || i > 30) + { + o->error = OHTTP; + return 0; + } + hr->method = odr_malloc(o, i+1); + memcpy (hr->method, o->buf, i); + hr->method[i] = '\0'; + /* path */ + po = i+1; + for (i = po; o->buf[i] != ' '; i++) + if (i >= o->size-5) + { + o->error = OHTTP; + return 0; + } + hr->path = odr_malloc(o, i - po + 1); + memcpy (hr->path, o->buf+po, i - po); + hr->path[i - po] = '\0'; + /* HTTP version */ + i++; + if (i > o->size-5 || memcmp(o->buf+i, "HTTP/", 5)) + { + o->error = OHTTP; + return 0; + } + i+= 5; + po = i; + while (o->buf[i] != '\r') + { + if (i >= o->size-1) + { + o->error = OHTTP; + return 0; + } + i++; + } + hr->version = odr_malloc(o, i - po + 1); + memcpy(hr->version, o->buf + po, i - po); + hr->version[i - po] = '\0'; + /* headers */ + return decode_headers_content(o, i, &hr->headers, + &hr->content_buf, &hr->content_len); + + } + else + { + (*p)->which = Z_GDU_Z3950; + return z_APDU(o, &(*p)->u.z3950, opt, 0); + } + } + else if (o->direction == ODR_ENCODE) + { + char sbuf[80]; + Z_HTTP_Header *h; + switch((*p)->which) + { + case Z_GDU_HTTP_Response: + sprintf(sbuf, "HTTP/%s %d %s\r\n", (*p)->u.HTTP_Response->version, + (*p)->u.HTTP_Response->code, + z_HTTP_errmsg((*p)->u.HTTP_Response->code)); + odr_write(o, sbuf, strlen(sbuf)); + /* apply Content-Length if not already applied */ + if (!z_HTTP_header_lookup((*p)->u.HTTP_Response->headers, + "Content-Length")) + { + char lstr[20]; + sprintf(lstr, "%d", (*p)->u.HTTP_Response->content_len); + z_HTTP_header_add(o, + &(*p)->u.HTTP_Response->headers, + "Content-Length", lstr); + } + for (h = (*p)->u.HTTP_Response->headers; h; h = h->next) + { + odr_write(o, h->name, strlen(h->name)); + odr_write(o, ": ", 2); + odr_write(o, h->value, strlen(h->value)); + odr_write(o, "\r\n", 2); + } + odr_write(o, "\r\n", 2); + if ((*p)->u.HTTP_Response->content_buf) + odr_write(o, (*p)->u.HTTP_Response->content_buf, + (*p)->u.HTTP_Response->content_len); +#if HTTP_DEBUG + fprintf(stderr, "HTTP response:\n%.*s\n", o->top, o->buf); +#endif + break; + case Z_GDU_HTTP_Request: + odr_write(o, (*p)->u.HTTP_Request->method, + strlen((*p)->u.HTTP_Request->method)); + odr_write(o, " ", 1); + odr_write(o, (*p)->u.HTTP_Request->path, + strlen((*p)->u.HTTP_Request->path)); + odr_write(o, " HTTP/", 6); + odr_write(o, (*p)->u.HTTP_Request->version, + strlen((*p)->u.HTTP_Request->version)); + odr_write(o, "\r\n", 2); + for (h = (*p)->u.HTTP_Request->headers; h; h = h->next) + { + odr_write(o, h->name, strlen(h->name)); + odr_write(o, ": ", 2); + odr_write(o, h->value, strlen(h->value)); + odr_write(o, "\r\n", 2); + } + odr_write(o, "\r\n", 2); + if ((*p)->u.HTTP_Request->content_buf) + odr_write(o, (*p)->u.HTTP_Request->content_buf, + (*p)->u.HTTP_Request->content_len); +#if HTTP_DEBUG + fprintf(stderr, "HTTP request:\n%.*s\n", o->top, o->buf); +#endif + break; + case Z_GDU_Z3950: + return z_APDU(o, &(*p)->u.z3950, opt, 0); + } + } + else if (o->direction == ODR_PRINT) + { + switch((*p)->which) + { + case Z_GDU_HTTP_Response: + fprintf (stderr, "not implemented"); + break; + case Z_GDU_HTTP_Request: + fprintf (stderr, "not implemented"); + break; + case Z_GDU_Z3950: + return z_APDU(o, &(*p)->u.z3950, opt, 0); + } + } + return 1; +} + diff --git a/zutil/zoom-c.c b/zutil/zoom-c.c index aaf9c90..a414e45 100644 --- a/zutil/zoom-c.c +++ b/zutil/zoom-c.c @@ -2,7 +2,7 @@ * Copyright (c) 2000-2003, Index Data * See the file LICENSE for details. * - * $Id: zoom-c.c,v 1.16 2003-01-24 12:15:45 adam Exp $ + * $Id: zoom-c.c,v 1.17 2003-02-12 15:06:44 adam Exp $ * * ZOOM layer for C, connections, result sets, queries. */ @@ -401,8 +401,6 @@ ZOOM_API(int) ZOOM_query_cql(ZOOM_query s, const char *str) { Z_External *ext; - char *buf; - int len; ext = (Z_External *) odr_malloc(s->odr, sizeof(*ext)); ext->direct_reference = odr_getoidbystr(s->odr, "1.2.840.10003.16.2"); @@ -1582,14 +1580,15 @@ static zoom_ret send_present (ZOOM_connection c) compo->u.complex->generic = (Z_Specification *) odr_malloc(c->odr_out, sizeof(*compo->u.complex->generic)); - compo->u.complex->generic->schema = (Odr_oid *) + compo->u.complex->generic->which = Z_Specification_oid; + compo->u.complex->generic->u.oid = (Odr_oid *) yaz_str_to_z3950oid (c->odr_out, CLASS_SCHEMA, schema); - if (!compo->u.complex->generic->schema) + if (!compo->u.complex->generic->u.oid) { /* OID wasn't a schema! Try record syntax instead. */ - compo->u.complex->generic->schema = (Odr_oid *) + compo->u.complex->generic->u.oid = (Odr_oid *) yaz_str_to_z3950oid (c->odr_out, CLASS_RECSYN, schema); } if (elementSetName && *elementSetName)