Updated ASN.1 for Z39.50 amendment String Identifiers for Schemas.
--- 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.
## 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
* 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 <stdio.h>
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)
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
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)
util/Makefile
odr/Makefile
z39.50/Makefile
-srw/Makefile
ill/Makefile
zutil/Makefile
comstack/Makefile
server/Makefile
include/Makefile
include/yaz/Makefile
-srwapps/Makefile
lib/Makefile
client/Makefile
ztest/Makefile
-## $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 \
\
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
* 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
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),
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
* 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
#define OSTACK 9
#define OCONLEN 10
#define OLENOV 11
+#define OHTTP 12
extern char *odr_errlist[];
* 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
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 <yaz/prt-ext.h>
--- /dev/null
+/*
+ * 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 <yaz/odr.h>
+
+#if HAVE_XSLT
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#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
+++ /dev/null
-/* $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 <yaz/cql.h>
-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[];
--- /dev/null
+/*
+ * 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 <yaz/soap.h>
+
+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
* 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
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
-## $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
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
* 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 <config.h>
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)
* 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
"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)
-## $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
EXTRA_DIST=service.c
-AM_CPPFLAGS=-I$(top_srcdir)/include
+AM_CPPFLAGS=-I$(top_srcdir)/include $(XSLT_CFLAGS)
/*
- * 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 <stdio.h>
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)
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)
/*
- * 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
* 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
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;
* 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 $
*/
/*
#include <yaz/diagbib1.h>
#include <yaz/charneg.h>
#include <yaz/otherinfo.h>
+#include <yaz/yaz-util.h>
+#include <yaz/srw.h>
#include <yaz/backend.h>
-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);
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.
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
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)));
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)
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:
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);
{ /* 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)
}
}
+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; i<number; i++)
+ {
+ srw_res->records[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,
+ "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
+ "<HTML>\n"
+ " <HEAD>\n"
+ " <TITLE>YAZ " YAZ_VERSION "</TITLE>\n"
+ " </HEAD>\n"
+ " <BODY>\n"
+ " <P><A HREF=\"http://www.indexdata.dk/yaz/\">YAZ</A> "
+ YAZ_VERSION "</P>\n"
+ " </BODY>\n"
+ "</HTML>\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;
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)
{
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);
/*
* 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);
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)
{
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;
{
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;
yaz_log(LOG_DEBUG,"Send the result apdu");
return apdu;
}
+
* 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
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 */
* 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 <stdio.h>
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 */
};
/*
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)
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;
{
/* Stops the app */
statserv_closedown();
+ statserv_reset();
}
/* WIN32 */
#else
statserv_setcontrol(cb);
ret = statserv_start (argc, argv);
statserv_closedown ();
+ statserv_reset();
return ret;
}
#endif
+++ /dev/null
-# $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
+++ /dev/null
-/* $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 <yaz/srw-util.h>
-
-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";
-}
+++ /dev/null
-/* $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}
-};
+++ /dev/null
-
-#include <yaz/srw-util.h>
-#include <yaz/xmalloc.h>
-
-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);
-}
-
+++ /dev/null
-/* $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 <yaz/srw-util.h>
-
-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;
-}
-
+++ /dev/null
-/* $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 <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxslt/xsltutils.h>
-#include <libxslt/transform.h>
-#endif
-
-#include <yaz/srw-util.h>
-
-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;
-}
+++ /dev/null
-/* $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
-);
+++ /dev/null
-## $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
-
+++ /dev/null
-/* $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 <stdio.h>
-
-#include <yaz/options.h>
-#include <yaz/srw-util.h>
-
-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] <service> <query>\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; i<res.records.__sizeRecords;
- i++)
- {
- if (res.records.record[i]->recordData)
- {
- 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;
-}
-
+++ /dev/null
-/* $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 <pthread.h>
-#define USE_THREADS 1
-#else
-#define USE_THREADS 0
-#endif
-
-#include <yaz/srw-util.h>
-#include <yaz/xmalloc.h>
-#include <yaz/zoom.h>
-#include <yaz/log.h>
-#include <yaz/options.h>
-#include <yaz/wrbuf.h>
-
-#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<max_thr; i++)
- soap_thr[i] = 0;
-
- while (!stop)
- {
- for (i = 0; i<max_thr; i++)
- {
- s = soap_accept(soap);
- if (s < 0)
- break;
- cno++;
- if (!soap_thr[i])
- {
- soap_thr[i] = soap_new();
- if (!soap_thr[i])
- {
- stop = 1;
- break;
- }
- }
- else
- {
-#if USE_THREADS
- if (max_thr > 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 =
- "<explain>\n"
- " <!-- not implemented -->\n"
- "</explain>\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] <port>\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;
-}
/*
- * 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 <config.h>
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,
#!/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
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()
accessCtrl (6),
scan (7),
sort (8),
- -- (9) (reserved)
+ -- (not used) (9),
extendedServices (10),
level-1Segmentation (11),
level-2Segmentation (12),
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
-- 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}
-## $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
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
-## $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
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)
-## $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
* 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 <stdio.h>
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:
--- /dev/null
+/*
+ * 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 <yaz/soap.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 <yaz/srw.h>
+
+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;
+}
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <yaz/yaz-ccl.h>
#include <yaz/pquery.h>
--- /dev/null
+/*
+ * 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 <yaz/proto.h>
+
+#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,
+ "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
+ "<HTML>\n"
+ " <HEAD>\n"
+ " <TITLE>YAZ " YAZ_VERSION "</TITLE>\n"
+ " </HEAD>\n"
+ " <BODY>\n"
+ " <P><A HREF=\"http://www.indexdata.dk/yaz/\">YAZ</A> "
+ YAZ_VERSION "</P>\n"
+ " <P>Error: %d</P>\n"
+ " <P>Description: %.50s</P>\n"
+ " </BODY>\n"
+ "</HTML>\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;
+}
+
* 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.
*/
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");
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)