summaryrefslogtreecommitdiff
path: root/ext/yaz/php_yaz.c
diff options
context:
space:
mode:
authorAdam Dickmeiss <dickmeiss@php.net>2000-05-25 21:54:35 +0000
committerAdam Dickmeiss <dickmeiss@php.net>2000-05-25 21:54:35 +0000
commit5dadceb115b26c2c3ee43176291f929aa85e6f98 (patch)
treed1806a1e2bf55defdc378234ca927c19fe4b768b /ext/yaz/php_yaz.c
parent8a5bc5b674ab1b45035e3f6a627504ee5524df2c (diff)
downloadphp-git-5dadceb115b26c2c3ee43176291f929aa85e6f98.tar.gz
Added extension YAZ (Z39.50 client role).
Diffstat (limited to 'ext/yaz/php_yaz.c')
-rw-r--r--ext/yaz/php_yaz.c1598
1 files changed, 1598 insertions, 0 deletions
diff --git a/ext/yaz/php_yaz.c b/ext/yaz/php_yaz.c
new file mode 100644
index 0000000000..d807b19e9e
--- /dev/null
+++ b/ext/yaz/php_yaz.c
@@ -0,0 +1,1598 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Adam Dickmeiss <adam@indexdata.dk> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include "php.h"
+
+#if HAVE_YAZ
+#include "php_yaz.h"
+
+#include <yaz/proto.h>
+#include <yaz/tcpip.h>
+#include <yaz/pquery.h>
+#include <yaz/diagbib1.h>
+#include <yaz/otherinfo.h>
+#include <yaz/marcdisp.h>
+#include <yaz/yaz-util.h>
+
+#define MAX_ASSOC 100
+
+#define PHP_YAZ_DEBUG 1
+
+typedef struct Yaz_ResultSetInfo *Yaz_ResultSet;
+typedef struct Yaz_AssociationInfo *Yaz_Association;
+typedef struct Yaz_RecordCacheInfo *Yaz_RecordCache;
+
+struct Yaz_RecordCacheInfo {
+ Z_NamePlusRecordList recordList;
+ Yaz_RecordCache next;
+};
+
+struct Yaz_ResultSetInfo {
+ Z_Query *query;
+ Z_ReferenceId *referenceId;
+ ODR odr;
+ int resultCount;
+ Yaz_ResultSet next;
+ Z_NamePlusRecordList *recordList;
+};
+
+#define PHP_YAZ_SELECT_READ 1
+#define PHP_YAZ_SELECT_WRITE 2
+#define PHP_YAZ_STATE_CONNECTING 1
+#define PHP_YAZ_STATE_ESTABLISHED 2
+#define PHP_YAZ_STATE_CLOSED 3
+
+#define PHP_YAZ_ERROR_CONNECTION_LOST (-1)
+#define PHP_YAZ_ERROR_DECODE (-2)
+#define PHP_YAZ_ERROR_ENCODE (-3)
+#define PHP_YAZ_ERROR_CONNECT (-4)
+#define PHP_YAZ_ERROR_INIT (-5)
+#define PHP_YAZ_ERROR_TIMEOUT (-6)
+
+struct Yaz_AssociationInfo {
+ char *host_port;
+ int num_databaseNames;
+ char **databaseNames;
+ COMSTACK cs;
+ char *cookie;
+ char *proxy;
+ char *auth_open;
+ char *user;
+ char *group;
+ char *pass;
+ int error;
+ char *addinfo;
+ Yaz_ResultSet resultSets;
+ int order;
+ int state;
+ int mask_select;
+ int reconnect_flag;
+ ODR odr_in;
+ ODR odr_out;
+ char *buf_out;
+ int len_out;
+ char *buf_in;
+ int len_in;
+ int (*action)(Yaz_Association t);
+ int resultSetStartPoint;
+ int numberOfRecordsRequested;
+ char *elementSetNames;
+ char *preferredRecordSyntax;
+};
+
+static Yaz_Association yaz_association_mk ()
+{
+ Yaz_Association p = xmalloc (sizeof(*p));
+ p->host_port = 0;
+ p->num_databaseNames = 0;
+ p->databaseNames = 0;
+ p->cs = 0;
+ p->cookie = 0;
+ p->proxy = 0;
+ p->auth_open = 0;
+ p->user = 0;
+ p->group = 0;
+ p->pass = 0;
+ p->error = 0;
+ p->addinfo = 0;
+ p->resultSets = 0;
+ p->order = 0;
+ p->state = PHP_YAZ_STATE_CLOSED;
+ p->mask_select = 0;
+ p->reconnect_flag = 0;
+ p->odr_in = odr_createmem (ODR_DECODE);
+ p->odr_out = odr_createmem (ODR_ENCODE);
+ p->buf_out = 0;
+ p->len_out = 0;
+ p->buf_in = 0;
+ p->len_in = 0;
+ p->action = 0;
+ p->resultSetStartPoint = 1;
+ p->numberOfRecordsRequested = 10;
+ p->elementSetNames = 0;
+ p->preferredRecordSyntax = 0;
+ return p;
+}
+
+static void yaz_association_destroy (Yaz_Association p)
+{
+ int i;
+ if (!p)
+ return ;
+ xfree (p->host_port);
+ for (i = 0; i<p->num_databaseNames; i++)
+ xfree (p->databaseNames[i]);
+ xfree (p->databaseNames);
+ if (p->cs)
+ cs_close (p->cs);
+ xfree (p->cookie);
+ xfree (p->proxy);
+ xfree (p->auth_open);
+ xfree (p->user);
+ xfree (p->group);
+ xfree (p->pass);
+ xfree (p->addinfo);
+ odr_destroy (p->odr_in);
+ odr_destroy (p->odr_out);
+ /* buf_out */
+ /* buf_in */
+ /* action */
+ xfree (p->elementSetNames);
+ xfree (p->preferredRecordSyntax);
+}
+
+static Yaz_ResultSet yaz_resultset_mk()
+{
+ ODR odr = odr_createmem (ODR_ENCODE);
+ Yaz_ResultSet p = odr_malloc (odr, sizeof(*p));
+
+ p->query = 0;
+ p->referenceId = 0;
+ p->odr = odr;
+ p->resultCount = 0;
+ p->next = 0;
+ p->recordList = 0;
+ return p;
+}
+
+static void yaz_resultset_destroy (Yaz_ResultSet p)
+{
+ if (!p)
+ return;
+ if (p->odr)
+ odr_destroy (p->odr);
+}
+
+static Yaz_Association *shared_associations;
+static int order_associations;
+
+/*
+ when id = 0, it means all targes...
+ id = yaz_connect(zurl, user,group, pass);
+ yaz_set_db(id, db)
+ yaz_error(id)
+ yaz_errno(id)
+ yaz_addinfo(id)
+
+ yaz_wait()
+ yaz_range(id, from, to, syntax, elementset)
+ yaz_search(id, type, query)
+ yaz_hits(id)
+ yaz_record(id, pos)
+
+ yaz_scan(id)
+ yaz_scan_point(id, scanterm, before, after)
+ yaz_scan_result(id, pos)
+
+ yaz_close(id)
+*/
+
+function_entry yaz_functions [] = {
+ PHP_FE(yaz_connect, NULL)
+ PHP_FE(yaz_close, NULL)
+ PHP_FE(yaz_search, NULL)
+ PHP_FE(yaz_wait, NULL)
+ PHP_FE(yaz_errno, NULL)
+ PHP_FE(yaz_error, NULL)
+ PHP_FE(yaz_addinfo, NULL)
+ PHP_FE(yaz_hits, NULL)
+ PHP_FE(yaz_record, NULL)
+ PHP_FE(yaz_syntax, NULL)
+ PHP_FE(yaz_element, NULL)
+ PHP_FE(yaz_range, NULL)
+ {NULL, NULL, NULL}
+};
+
+static Yaz_Association get_assoc (pval **id)
+{
+ int i;
+ convert_to_long_ex(id);
+ i = (*id)->value.lval;
+
+ if (i < 1 || i > MAX_ASSOC)
+ return 0;
+ return shared_associations[i-1];
+}
+
+
+static void do_close (Yaz_Association p)
+{
+ p->mask_select = 0;
+ p->state = PHP_YAZ_STATE_CLOSED;
+ if (p->cs)
+ {
+ cs_close (p->cs);
+ p->cs = 0;
+ }
+}
+
+static void do_connect (Yaz_Association p)
+{
+ void *addr;
+
+ p->reconnect_flag = 0;
+ p->cs = cs_create (tcpip_type, 0, PROTO_Z3950);
+ addr = tcpip_strtoaddr (p->host_port);
+ if (!addr)
+ {
+ do_close(p);
+ p->error = PHP_YAZ_ERROR_CONNECT;
+ return;
+ }
+ cs_connect (p->cs, addr);
+ p->state = PHP_YAZ_STATE_CONNECTING;
+ p->mask_select = PHP_YAZ_SELECT_READ | PHP_YAZ_SELECT_WRITE;
+}
+
+static void response_diag (Yaz_Association t, Z_DiagRec *p)
+{
+ Z_DefaultDiagFormat *r;
+ char *addinfo = 0;
+
+ xfree (t->addinfo);
+ t->addinfo = 0;
+ if (p->which != Z_DiagRec_defaultFormat)
+ {
+ t->error = PHP_YAZ_ERROR_DECODE;
+ return;
+ }
+ r = p->u.defaultFormat;
+#ifdef ASN_COMPILED
+ switch (r->which)
+ {
+ case Z_DefaultDiagFormat_v2Addinfo:
+ addinfo = r->u.v2Addinfo;
+ break;
+ case Z_DefaultDiagFormat_v3Addinfo:
+ addinfo = r->u.v3Addinfo;
+ break;
+ }
+#else
+ addinfo = r->addinfo;
+#endif
+ if (addinfo)
+ t->addinfo = xstrdup (addinfo);
+ t->error = *r->condition;
+}
+
+static int send_present (Yaz_Association t);
+
+void handle_records (Yaz_Association t, Z_Records *sr)
+{
+ if (sr && sr->which == Z_Records_NSD)
+ {
+#ifdef ASN_COMPILED
+ Z_DiagRec dr, *dr_p = &dr;
+ dr.which = Z_DiagRec_defaultFormat;
+ dr.u.defaultFormat = sr->u.nonSurrogateDiagnostic;
+
+ response_diag (t, dr_p);
+#else
+ response_diag (t, sr->u.nonSurrogateDiagnostic);
+#endif
+ }
+ else if (sr && sr->which == Z_Records_multipleNSD)
+ {
+ if (sr->u.multipleNonSurDiagnostics->num_diagRecs >= 1)
+ response_diag(t, sr->u.multipleNonSurDiagnostics->diagRecs[0]);
+ else
+ t->error = PHP_YAZ_ERROR_DECODE;
+ }
+ else
+ {
+ if (t->numberOfRecordsRequested > 0 && !t->resultSets->recordList)
+ {
+ int i;
+
+ t->resultSets->recordList =
+ odr_malloc (t->resultSets->odr,
+ sizeof(*t->resultSets->recordList));
+ t->resultSets->recordList->records =
+ odr_malloc (t->resultSets->odr, t->numberOfRecordsRequested
+ * sizeof(*t->resultSets->recordList->records));
+ for (i = 0; i < t->numberOfRecordsRequested; i++)
+ t->resultSets->recordList->records[i] = 0;
+ if (t->numberOfRecordsRequested + t->resultSetStartPoint-1 >
+ t->resultSets->resultCount)
+ t->numberOfRecordsRequested = t->resultSets->resultCount -
+ t->resultSetStartPoint + 1;
+ t->resultSets->recordList->num_records =
+ t->numberOfRecordsRequested;
+ }
+ if (sr && sr->which == Z_Records_DBOSD)
+ {
+ int j, i;
+ Z_NamePlusRecordList *p =
+ sr->u.databaseOrSurDiagnostics;
+ for (j = 0; j < t->resultSets->recordList->num_records; j++)
+ if (!t->resultSets->recordList->records[j])
+ break;
+ for (i = 0; i<p->num_records; i++)
+ t->resultSets->recordList->records[i+j] = p->records[i];
+ /* transfer our response to search_nmem .. we need it later */
+ nmem_transfer (t->resultSets->odr->mem, odr_extract_mem (t->odr_in));
+ }
+ }
+}
+
+static void search_response (Yaz_Association t, Z_SearchResponse *sr)
+{
+ t->resultSets->resultCount = *sr->resultCount;
+ handle_records (t, sr->records);
+}
+
+static void present_response (Yaz_Association t, Z_PresentResponse *pr)
+{
+ handle_records (t, pr->records);
+}
+
+static void handle_apdu (Yaz_Association t, Z_APDU *apdu)
+{
+ Z_InitResponse *initrs;
+
+ t->mask_select = 0;
+
+ switch(apdu->which)
+ {
+ case Z_APDU_initResponse:
+ initrs = apdu->u.initResponse;
+ if (!*initrs->result)
+ {
+ t->error = PHP_YAZ_ERROR_INIT;
+ }
+ else
+ {
+ char *cookie =
+ yaz_oi_get_string_oidval (&apdu->u.initResponse->otherInfo,
+ VAL_COOKIE, 1, 0);
+ if (cookie)
+ {
+ xfree(t->cookie);
+ t->cookie = xstrdup(cookie);
+ }
+ (*t->action) (t);
+ }
+ break;
+ case Z_APDU_searchResponse:
+ search_response (t, apdu->u.searchResponse);
+ send_present (t);
+ break;
+ case Z_APDU_presentResponse:
+ present_response (t, apdu->u.presentResponse);
+ send_present (t);
+ break;
+#if 0
+ case Z_APDU_scanResponse:
+ zlog (req, t->name, " scan response");
+ scanResponse (req, t, apdu->u.scanResponse);
+ break;
+#endif
+#if USE_ES
+ case Z_APDU_extendedServicesResponse:
+ zlog (req, t->name, " ES response");
+ esResponse (req, t, apdu->u.extendedServicesResponse);
+ break;
+#endif
+ case Z_APDU_close:
+ do_close(t);
+ if (t->reconnect_flag)
+ do_connect (t);
+ else
+ t->error = PHP_YAZ_ERROR_CONNECTION_LOST;
+ break;
+ default:
+ do_close (t);
+ t->error = PHP_YAZ_ERROR_DECODE;
+ break;
+ }
+}
+
+static int do_read (Yaz_Association t)
+{
+ int r;
+ Z_APDU *apdu;
+
+ r = cs_get (t->cs, &t->buf_in, &t->len_in);
+ if (r == 1)
+ return 0;
+ if (r <= 0)
+ {
+ do_close (t);
+ if (t->reconnect_flag)
+ {
+ do_connect (t);
+ }
+ else
+ {
+ do_close (t);
+ t->error = PHP_YAZ_ERROR_CONNECTION_LOST;
+ }
+ }
+ else
+ {
+ odr_reset (t->odr_in);
+ odr_setbuf (t->odr_in, t->buf_in, r, 0);
+ if (!z_APDU (t->odr_in, &apdu, 0, 0))
+ {
+ do_close (t);
+ t->error = PHP_YAZ_ERROR_DECODE;
+ }
+ else
+ {
+ /* apdu_log(req, t->odr_print, apdu); */
+ handle_apdu (t, apdu);
+ }
+ }
+ return 1;
+}
+
+static int do_write (Yaz_Association t)
+{
+ int r;
+
+ if ((r=cs_put (t->cs, t->buf_out, t->len_out)) < 0)
+ {
+ if (t->reconnect_flag)
+ {
+ do_close (t);
+ do_connect (t);
+ }
+ else
+ {
+ if (t->state == PHP_YAZ_STATE_CONNECTING)
+ t->error = PHP_YAZ_ERROR_CONNECT;
+ else
+ t->error = PHP_YAZ_ERROR_CONNECTION_LOST;
+ do_close (t);
+ return 1;
+ }
+ }
+ else if (r == 1)
+ {
+ t->state = PHP_YAZ_STATE_ESTABLISHED;
+ t->mask_select = PHP_YAZ_SELECT_READ|PHP_YAZ_SELECT_WRITE;
+ }
+ else
+ {
+ t->state = PHP_YAZ_STATE_ESTABLISHED;
+ t->mask_select = PHP_YAZ_SELECT_READ;
+ }
+ return 0;
+}
+
+
+static int send_APDU (Yaz_Association t, Z_APDU *a)
+{
+ if (t->cookie)
+ {
+ Z_OtherInformation **oi;
+ yaz_oi_APDU(a, &oi);
+ yaz_oi_set_string_oidval(oi, t->odr_out, VAL_COOKIE, 1, t->cookie);
+ }
+/* from ZAP */
+#if 0
+ if (req->request->connection)
+ {
+ Z_OtherInformation **oi;
+ zlog (req, t->name, " encoding client_ip");
+ yaz_oi_APDU(a, &oi);
+ yaz_oi_set_string_oidval(oi, t->odr_out, VAL_CLIENT_IP, 1,
+ req->request->connection->remote_ip);
+ }
+#endif
+ if (!z_APDU(t->odr_out, &a, 0, 0))
+ {
+ do_close (t);
+ t->error = PHP_YAZ_ERROR_ENCODE;
+ return -1;
+ }
+ /* apdu_log(req, t->odr_print, a); */
+ t->buf_out = odr_getbuf(t->odr_out, &t->len_out, 0);
+ odr_reset(t->odr_out);
+ do_write (t);
+ return 0;
+}
+
+static char **set_DatabaseNames (Yaz_Association t, int *num)
+{
+ char **databaseNames;
+ char *c, *cp = strchr (t->host_port, '/');
+ int no = 2;
+
+ if (cp)
+ {
+ c = cp;
+ while ((c = strchr(c, '+')))
+ {
+ c++;
+ no++;
+ }
+ }
+ else
+ cp = "/Default";
+ databaseNames = odr_malloc (t->odr_out, no * sizeof(*databaseNames));
+ no = 0;
+ while (*cp)
+ {
+ c = ++cp;
+ c = strchr (c, '+');
+ if (!c)
+ c = cp + strlen(cp);
+ else if (c == cp)
+ continue;
+ /* cp ptr to first char of db name, c is char following db name */
+ databaseNames[no] = odr_malloc (t->odr_out, 1+c-cp);
+ memcpy (databaseNames[no], cp, c-cp);
+ databaseNames[no][c-cp] = '\0';
+ no++;
+ cp = c;
+ }
+ databaseNames[no] = NULL;
+ *num = no;
+ return databaseNames;
+}
+
+static int send_search (Yaz_Association t)
+{
+ Yaz_ResultSet r = t->resultSets;
+ Z_APDU *apdu = zget_APDU(t->odr_out, Z_APDU_searchRequest);
+ Z_SearchRequest *sreq = apdu->u.searchRequest;
+
+ /* resultSetPrepare (req, t, req->cur_pa); */
+ if (t->resultSetStartPoint == 1)
+ {
+ sreq->largeSetLowerBound = odr_malloc (t->odr_out, sizeof(int));
+ *sreq->largeSetLowerBound = 999999;
+ sreq->smallSetUpperBound = &t->numberOfRecordsRequested;
+ sreq->mediumSetPresentNumber = &t->numberOfRecordsRequested;
+ if (t->elementSetNames && *t->elementSetNames)
+ {
+ Z_ElementSetNames *esn = odr_malloc (t->odr_out, sizeof(*esn));
+
+ esn->which = Z_ElementSetNames_generic;
+ esn->u.generic = t->elementSetNames;
+ sreq->mediumSetElementSetNames = esn;
+ sreq->smallSetElementSetNames = esn;
+ }
+ }
+ else
+ {
+ sreq->smallSetUpperBound = odr_malloc (t->odr_out, sizeof(int));
+ *sreq->smallSetUpperBound = 0;
+ sreq->largeSetLowerBound = odr_malloc (t->odr_out, sizeof(int));
+ *sreq->largeSetLowerBound = 1;
+ sreq->mediumSetPresentNumber = odr_malloc (t->odr_out, sizeof(int));
+ *sreq->mediumSetPresentNumber = 0;
+ }
+ sreq->query = r->query;
+ if (t->preferredRecordSyntax && *t->preferredRecordSyntax)
+ {
+ struct oident ident;
+
+ ident.proto = PROTO_Z3950;
+ ident.oclass = CLASS_RECSYN;
+ ident.value = oid_getvalbyname (t->preferredRecordSyntax);
+ sreq->preferredRecordSyntax =
+ odr_oiddup (t->odr_out, oid_getoidbyent (&ident));
+ }
+ sreq->databaseNames = set_DatabaseNames (t, &sreq->num_databaseNames);
+
+ send_APDU (t, apdu);
+ return 1;
+}
+
+static int send_present (Yaz_Association t)
+{
+ Z_APDU *apdu = zget_APDU(t->odr_out, Z_APDU_presentRequest);
+ Z_PresentRequest *req = apdu->u.presentRequest;
+ int i = 0;
+
+ if (!t->resultSets->recordList) /* no records to retrieve at all .. */
+ {
+#if PHP_YAZ_DEBUG
+ php_log_err("No records to retrieve...");
+#endif
+ return 0;
+ }
+
+ while (1)
+ {
+ if (i >= t->resultSets->recordList->num_records)
+ { /* got all records ... */
+ /* searchHits (zreq, t); */
+ return 0;
+ }
+ if (!t->resultSets->recordList->records[i])
+ break;
+ i++;
+ }
+ /* got record(s) to retrieve */
+
+ req->resultSetStartPoint = odr_malloc (t->odr_out, sizeof(int));
+ *req->resultSetStartPoint = t->resultSetStartPoint + i;
+
+ req->numberOfRecordsRequested = odr_malloc (t->odr_out, sizeof(int));
+ *req->numberOfRecordsRequested = t->resultSets->recordList->num_records - i;
+
+ if (t->preferredRecordSyntax && *t->preferredRecordSyntax)
+ {
+ struct oident ident;
+
+ ident.proto = PROTO_Z3950;
+ ident.oclass = CLASS_RECSYN;
+ ident.value = oid_getvalbyname (t->preferredRecordSyntax);
+ req->preferredRecordSyntax =
+ odr_oiddup (t->odr_out, oid_getoidbyent (&ident));
+ }
+
+ if (t->elementSetNames && *t->elementSetNames)
+ {
+ Z_ElementSetNames *esn = odr_malloc (t->odr_out, sizeof(*esn));
+ Z_RecordComposition *compo = odr_malloc (t->odr_out, sizeof(*compo));
+
+ esn->which = Z_ElementSetNames_generic;
+ esn->u.generic = t->elementSetNames;
+ compo->which = Z_RecordComp_simple;
+ compo->u.simple = esn;
+ req->recordComposition = compo;
+ }
+ send_APDU (t, apdu);
+ return 1;
+}
+
+static void send_init(Yaz_Association t)
+{
+ int i = 0;
+ Z_APDU *apdu = zget_APDU(t->odr_out, Z_APDU_initRequest);
+ Z_InitRequest *ireq = apdu->u.initRequest;
+ Z_IdPass *pass = odr_malloc(t->odr_out, sizeof(*pass));
+ Z_IdAuthentication *auth = odr_malloc(t->odr_out, sizeof(*auth));
+ const char *auth_open = t->auth_open;
+ const char *auth_groupId = t->group;
+ const char *auth_userId = t->user;
+ const char *auth_password = t->pass;
+
+ ODR_MASK_SET(ireq->options, Z_Options_search);
+ ODR_MASK_SET(ireq->options, Z_Options_present);
+ ODR_MASK_SET(ireq->options, Z_Options_namedResultSets);
+ ODR_MASK_SET(ireq->options, Z_Options_scan);
+
+ ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_1);
+ ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_2);
+ ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_3);
+
+ ireq->implementationName = "PHP/YAZ";
+
+ *ireq->maximumRecordSize = 1024*1024;
+ *ireq->preferredMessageSize = 1024*1024;
+
+ if (auth_open && *auth_open)
+ {
+ auth->which = Z_IdAuthentication_open;
+ auth->u.open = odr_malloc(t->odr_out, strlen(auth_open)+1);
+ strcpy(auth->u.open, auth_open);
+ ireq->idAuthentication = auth;
+ }
+ pass->groupId = 0;
+ if (auth_groupId && *auth_groupId)
+ {
+ pass->groupId = odr_malloc(t->odr_out, strlen(auth_groupId)+1);
+ strcpy(pass->groupId, auth_groupId);
+ i++;
+ }
+ pass->userId = 0;
+ if (auth_userId && *auth_userId)
+ {
+ pass->userId = odr_malloc(t->odr_out, strlen(auth_userId)+1);
+ strcpy(pass->userId, auth_userId);
+ i++;
+ }
+ pass->password = 0;
+ if (auth_password && *auth_password)
+ {
+ pass->password = odr_malloc(t->odr_out, strlen(auth_password)+1);
+ strcpy(pass->password, auth_password);
+ i++;
+ }
+ if(i)
+ {
+ auth->which = Z_IdAuthentication_idPass;
+ auth->u.idPass = pass;
+ ireq->idAuthentication = auth;
+ }
+ if (t->proxy)
+ yaz_oi_set_string_oidval(&ireq->otherInfo, t->odr_out,
+ VAL_PROXY, 1, t->host_port);
+ send_APDU (t, apdu);
+}
+
+static int do_event (int *id)
+{
+ fd_set input, output;
+ int i;
+ int no = 0;
+ int max_fd = 0;
+ struct timeval tv;
+
+ tv.tv_sec = 15;
+ tv.tv_usec = 0;
+
+ FD_ZERO (&input);
+ FD_ZERO (&output);
+ for (i = 0; i < MAX_ASSOC; i++)
+ {
+ Yaz_Association p = shared_associations[i];
+ int fd;
+ if (!p || p->order != order_associations || !p->cs)
+ continue;
+ fd = cs_fileno (p->cs);
+ if (max_fd < fd)
+ max_fd = fd;
+ if (p->mask_select & PHP_YAZ_SELECT_READ)
+ {
+ FD_SET (fd, &input);
+ no++;
+ }
+ if (p->mask_select & PHP_YAZ_SELECT_WRITE)
+ {
+ FD_SET (fd, &output);
+ no++;
+ }
+ }
+ if (!no)
+ return 0;
+ no = select (max_fd+1, &input, &output, 0, &tv);
+ for (i = 0; i<MAX_ASSOC; i++)
+ {
+ int fd;
+ Yaz_Association p = shared_associations[i];
+ if (!p || p->order != order_associations || !p->cs)
+ continue;
+ *id = i+1;
+ fd =cs_fileno(p->cs);
+ if (no <= 0)
+ {
+ if (p->mask_select) /* only mark for those still pending */
+ {
+ if (p->state == PHP_YAZ_STATE_CONNECTING)
+ p->error = PHP_YAZ_ERROR_CONNECT;
+ else
+ p->error = PHP_YAZ_ERROR_TIMEOUT;
+ do_close (p);
+ }
+ }
+ else if (p->state == PHP_YAZ_STATE_CONNECTING)
+ {
+ if (FD_ISSET (fd, &input))
+ {
+ do_close(p);
+ p->error = PHP_YAZ_ERROR_CONNECT;
+ return 2;
+ }
+ else if (FD_ISSET (fd, &output))
+ {
+ send_init(p);
+ }
+ }
+ else if (p->state == PHP_YAZ_STATE_ESTABLISHED)
+ {
+ if (FD_ISSET (fd, &input))
+ do_read (p);
+ if (p->cs && FD_ISSET (fd, &output))
+ do_write (p);
+ }
+ else
+ {
+ do_close (p);
+ p->error = PHP_YAZ_ERROR_CONNECTION_LOST;
+ }
+ }
+ return no;
+}
+
+/* {{{ proto int yaz_connect(string zurl)
+ Create target with given zurl. Returns positive id if succesful. */
+PHP_FUNCTION(yaz_connect)
+{
+ int i;
+ char *cp;
+ char *zurl_str;
+ pval **zurl;
+ if (ARG_COUNT(ht) < 1 || zend_get_parameters_ex (1, &zurl) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex (zurl);
+ zurl_str = (*zurl)->value.str.val;
+ for (cp = zurl_str; *cp && strchr("\t\n ", *cp); cp++)
+ ;
+ if (!*cp)
+ RETURN_LONG(0);
+
+ /* see if we have it already ... */
+ for (i = 0; i<MAX_ASSOC; i++)
+ if (shared_associations[i] && shared_associations[i]->host_port &&
+ shared_associations[i]->order != order_associations &&
+ !strcmp (shared_associations[i]->host_port, zurl_str))
+ break;
+ if (i == MAX_ASSOC)
+ {
+ /* we didn't have it (or already in use) */
+ int i0 = -1;
+ int min_order = 2000000000;
+ /* find completely free slot or the oldest one */
+ for (i = 0; i<MAX_ASSOC && shared_associations[i]; i++)
+ if (shared_associations[i]->order < min_order
+ && shared_associations[i]->order != order_associations)
+ {
+ min_order = shared_associations[i]->order;
+ i0 = i;
+ }
+ if (i == MAX_ASSOC)
+ {
+ i = i0;
+ if (i == -1)
+ {
+ RETURN_LONG(0); /* no free slot */
+ }
+ else /* "best" free slot */
+ yaz_association_destroy(shared_associations[i]);
+ }
+ shared_associations[i] = yaz_association_mk ();
+ shared_associations[i]->host_port = xstrdup (zurl_str);
+ }
+ shared_associations[i]->order = order_associations;
+ shared_associations[i]->error = 0;
+ shared_associations[i]->numberOfRecordsRequested = 10;
+ shared_associations[i]->resultSetStartPoint = 1;
+ RETURN_LONG(i+1);
+}
+/* }}} */
+
+/* {{{ proto int yaz_close(int id)
+ Destory and close target */
+PHP_FUNCTION(yaz_close)
+{
+ pval **id;
+ int i;
+ if (ARG_COUNT(ht) != 1)
+ WRONG_PARAM_COUNT;
+ if (zend_get_parameters_ex (1, &id) == FAILURE)
+ RETURN_FALSE;
+ convert_to_long_ex (id);
+ i = (*id)->value.lval -1;
+ if (i < 0 || i >= MAX_ASSOC || !shared_associations[i])
+ RETURN_FALSE;
+ yaz_association_destroy (shared_associations[i]);
+ shared_associations[i] = 0;
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int yaz_search(int id, string type, string query)
+ Specify query of type for search - returns true if successful */
+PHP_FUNCTION(yaz_search)
+{
+ char *query_str, *type_str;
+ pval **id, **type, **query;
+ Yaz_Association p;
+ Yaz_ResultSet r;
+ if (ARG_COUNT(ht) != 3)
+ WRONG_PARAM_COUNT;
+ if (zend_get_parameters_ex(3, &id, &type, &query) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (id);
+ if (!p)
+ {
+#if PHP_YAZ_DEBUG
+ php_log_err ("get_assoc failed");
+#endif
+ RETURN_FALSE;
+ }
+ convert_to_string_ex (type);
+ type_str = (*type)->value.str.val;
+ convert_to_string_ex (query);
+ query_str = (*query)->value.str.val;
+ yaz_resultset_destroy (p->resultSets);
+ r = p->resultSets = yaz_resultset_mk();
+ r->query = odr_malloc (r->odr, sizeof(*r->query));
+ if (!strcmp (type_str, "rpn"))
+ {
+ r->query->which = Z_Query_type_1;
+ r->query->u.type_1 = p_query_rpn (r->odr, PROTO_Z3950, query_str);
+ if (!r->query->u.type_1)
+ {
+ yaz_resultset_destroy(r);
+ p->resultSets = 0;
+#if PHP_YAZ_DEBUG
+ php_log_err ("bad rpn");
+#endif
+ RETURN_FALSE;
+ }
+ }
+ else
+ {
+ yaz_resultset_destroy(r);
+ p->resultSets = 0;
+#if PHP_YAZ_DEBUG
+ php_log_err ("bad query type");
+#endif
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int yaz_wait()
+ Process all outstanding events. */
+PHP_FUNCTION(yaz_wait)
+{
+ int i;
+ int id;
+ for (i = 0; i<MAX_ASSOC; i++)
+ {
+ Yaz_Association p = shared_associations[i];
+ if (!p || p->order != order_associations || !p->resultSets)
+ continue;
+ p->action = send_search;
+ if (!p->cs)
+ {
+ do_connect (p);
+ }
+ else
+ {
+ p->reconnect_flag = 1;
+ send_search (p);
+ }
+ }
+ while (do_event(&id))
+ ;
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int yaz_errno(int id)
+ Return last error number (>0 for bib-1 diagnostic, <0 for other error, 0 for no error */
+PHP_FUNCTION(yaz_errno)
+{
+ pval **id;
+ Yaz_Association p;
+ if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &id) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (id);
+ if (!p)
+ {
+ RETURN_LONG(0);
+ }
+ RETURN_LONG(p->error);
+}
+/* }}} */
+
+/* {{{ proto string yaz_error(int id)
+ Return last error message */
+PHP_FUNCTION(yaz_error)
+{
+ pval **id;
+ Yaz_Association p;
+ if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &id) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (id);
+ if (p && p->error)
+ {
+ const char *msg = 0;
+ if (p->error < 0)
+ {
+ switch (p->error)
+ {
+ case PHP_YAZ_ERROR_CONNECTION_LOST:
+ msg = "connection lost";
+ break;
+ case PHP_YAZ_ERROR_DECODE:
+ msg = "decoding failure";
+ break;
+ case PHP_YAZ_ERROR_ENCODE:
+ msg = "encoding failure";
+ break;
+ case PHP_YAZ_ERROR_CONNECT:
+ msg = "connect failed";
+ break;
+ case PHP_YAZ_ERROR_INIT:
+ msg = "initialization failed";
+ break;
+ case PHP_YAZ_ERROR_TIMEOUT:
+ msg = "timeout failure";
+ break;
+ default:
+ msg = "unknown failure";
+ break;
+ }
+ }
+ else
+ {
+ msg = diagbib1_str (p->error);
+ if (!msg)
+ msg = "unknown diagnostic";
+ }
+ /* Not macro using because RETURN_STRING throws away const */
+ return_value->value.str.len = strlen(msg);
+ return_value->value.str.val =
+ estrndup(msg, return_value->value.str.len);
+ return_value->type = IS_STRING;
+ }
+}
+/* }}} */
+
+/* {{{ proto string yaz_addinfo(int id)
+ Return additional info for last error (empty string if none) */
+PHP_FUNCTION(yaz_addinfo)
+{
+ pval **id;
+ Yaz_Association p;
+ if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &id) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (id);
+ if (p && p->error > 0 && p->addinfo && *p->addinfo)
+ {
+ RETURN_STRING(p->addinfo, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto int yaz_hits(int id)
+ Return number of hits (result count) for last search */
+PHP_FUNCTION(yaz_hits)
+{
+ pval **id;
+ Yaz_Association p;
+ if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &id) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (id);
+ if (!p || !p->resultSets)
+ {
+ RETURN_LONG(0);
+ }
+ RETURN_LONG(p->resultSets->resultCount);
+}
+/* }}} */
+
+Z_GenericRecord *marc_to_grs1(const char *buf, ODR o, Odr_oid *oid)
+{
+ int entry_p;
+ int record_length;
+ int indicator_length;
+ int identifier_length;
+ int base_address;
+ int length_data_entry;
+ int length_starting;
+ int length_implementation;
+ int max_elements = 256;
+ Z_GenericRecord *r = odr_malloc (o, sizeof(*r));
+ r->elements = odr_malloc (o, sizeof(*r->elements) * max_elements);
+ r->num_elements = 0;
+
+ record_length = atoi_n (buf, 5);
+ if (record_length < 25)
+ return 0;
+ indicator_length = atoi_n (buf+10, 1);
+ identifier_length = atoi_n (buf+11, 1);
+ base_address = atoi_n (buf+12, 4);
+
+ length_data_entry = atoi_n (buf+20, 1);
+ length_starting = atoi_n (buf+21, 1);
+ length_implementation = atoi_n (buf+22, 1);
+
+ for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
+ {
+ entry_p += 3+length_data_entry+length_starting;
+ if (entry_p >= record_length)
+ return 0;
+ }
+ base_address = entry_p+1;
+ for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
+ {
+ Z_TaggedElement *tag;
+ int data_length;
+ int data_offset;
+ int end_offset;
+ int i;
+ char tag_str[4];
+
+ memcpy (tag_str, buf+entry_p, 3);
+ entry_p += 3;
+ tag_str[3] = '\0';
+
+ if ((r->num_elements + 1) >= max_elements)
+ {
+ Z_TaggedElement **tmp = r->elements;
+
+ /* double array space, throw away old buffer (nibble memory) */
+ r->elements = odr_malloc(o, sizeof(*r->elements) *
+ (max_elements *= 2));
+ memcpy(r->elements, tmp, r->num_elements * sizeof(*tmp));
+ }
+ tag = r->elements[r->num_elements++] = odr_malloc (o, sizeof(*tag));
+ tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
+ *tag->tagType = 3;
+ tag->tagOccurrence = 0;
+ tag->metaData = 0;
+ tag->appliedVariant = 0;
+ tag->tagValue = odr_malloc (o, sizeof(*tag->tagValue));
+ tag->tagValue->which = Z_StringOrNumeric_string;
+ tag->tagValue->u.string = odr_strdup(o, tag_str);
+
+ tag->content = odr_malloc(o, sizeof(*tag->content));
+ tag->content->which = Z_ElementData_subtree;
+
+ tag->content->u.subtree =
+ odr_malloc (o, sizeof(*tag->content->u.subtree));
+ tag->content->u.subtree->elements = odr_malloc (o, sizeof(*r->elements));
+ tag->content->u.subtree->num_elements = 1;
+
+ tag = tag->content->u.subtree->elements[0] =
+ odr_malloc (o, sizeof(**tag->content->u.subtree->elements));
+
+ tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
+ *tag->tagType = 3;
+ tag->tagOccurrence = 0;
+ tag->metaData = 0;
+ tag->appliedVariant = 0;
+ tag->tagValue = odr_malloc (o, sizeof(*tag->tagValue));
+ tag->tagValue->which = Z_StringOrNumeric_string;
+ tag->content = odr_malloc(o, sizeof(*tag->content));
+
+ data_length = atoi_n (buf+entry_p, length_data_entry);
+ entry_p += length_data_entry;
+ data_offset = atoi_n (buf+entry_p, length_starting);
+ entry_p += length_starting;
+ i = data_offset + base_address;
+ end_offset = i+data_length-1;
+
+ if (memcmp (tag_str, "00", 2) && indicator_length)
+ {
+ /* indicator */
+ tag->tagValue->u.string = odr_malloc(o, indicator_length+1);
+ memcpy (tag->tagValue->u.string, buf + i, indicator_length);
+ tag->tagValue->u.string[indicator_length] = '\0';
+ i += indicator_length;
+
+ tag->content->which = Z_ElementData_subtree;
+
+ tag->content->u.subtree =
+ odr_malloc (o, sizeof(*tag->content->u.subtree));
+ tag->content->u.subtree->elements =
+ odr_malloc (o, 256 * sizeof(*r->elements));
+ tag->content->u.subtree->num_elements = 0;
+
+ while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS
+ && i < end_offset)
+ {
+ int i0;
+ /* prepare tag */
+ Z_TaggedElement *parent_tag = tag;
+ Z_TaggedElement *tag = odr_malloc (o, sizeof(*tag));
+
+ if (parent_tag->content->u.subtree->num_elements < 256)
+ parent_tag->content->u.subtree->elements[
+ parent_tag->content->u.subtree->num_elements++] = tag;
+
+ tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
+ *tag->tagType = 3;
+ tag->tagOccurrence = 0;
+ tag->metaData = 0;
+ tag->appliedVariant = 0;
+ tag->tagValue = odr_malloc (o, sizeof(*tag->tagValue));
+ tag->tagValue->which = Z_StringOrNumeric_string;
+
+ /* sub field */
+ tag->tagValue->u.string = odr_malloc (o, identifier_length);
+ memcpy (tag->tagValue->u.string, buf+i+1, identifier_length-1);
+ tag->tagValue->u.string[identifier_length-1] = '\0';
+ i += identifier_length;
+
+ /* data ... */
+ tag->content = odr_malloc(o, sizeof(*tag->content));
+ tag->content->which = Z_ElementData_string;
+
+ i0 = i;
+ while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
+ buf[i] != ISO2709_FS && i < end_offset)
+ i++;
+
+ tag->content->u.string = odr_malloc (o, i - i0 + 1);
+ memcpy (tag->content->u.string, buf + i0, i - i0);
+ tag->content->u.string[i - i0] = '\0';
+ }
+ }
+ else
+ {
+ int i0 = i;
+
+ tag->tagValue->u.string = "@";
+ tag->content->which = Z_ElementData_string;
+
+ while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS &&
+ i < end_offset)
+ i++;
+ tag->content->u.string = odr_malloc (o, i - i0 +1);
+ memcpy (tag->content->u.string, buf+i0, i - i0);
+ tag->content->u.string[i-i0] = '\0';
+ }
+ }
+ return r;
+}
+
+static void retval_grs1 (zval *return_value, Z_GenericRecord *p)
+{
+ Z_GenericRecord *grs[20];
+ int eno[20];
+ int level = 0;
+
+ if (array_init(return_value) == FAILURE)
+ {
+ RETURN_FALSE;
+ }
+ eno[level] = 0;
+ grs[level] = p;
+ while (level >= 0)
+ {
+ zval *my_zval;
+ Z_TaggedElement *e = 0;
+ Z_GenericRecord *p = grs[level];
+ int i;
+ char tag[256];
+ int taglen = 0;
+
+ if (eno[level] >= p->num_elements)
+ {
+ --level;
+ if (level >= 0)
+ eno[level]++;
+ continue;
+ }
+ // eno[level]++;
+
+ *tag = '\0';
+ for (i = 0; i<=level; i++)
+ {
+ int tag_type = 3;
+ e = grs[i]->elements[eno[i]];
+
+ if (e->tagType)
+ tag_type = *e->tagType;
+
+ taglen = strlen(tag);
+ sprintf (tag+taglen, "(%d,", tag_type);
+ taglen = strlen(tag);
+
+ if (e->tagValue->which == Z_StringOrNumeric_string)
+ {
+ int len = strlen(e->tagValue->u.string);
+ memcpy (tag + taglen, e->tagValue->u.string, len);
+ tag[taglen+len] = '\0';
+ }
+ else if (e->tagValue->which == Z_StringOrNumeric_numeric)
+ {
+ sprintf (tag + taglen, "%d", *e->tagValue->u.numeric);
+ }
+ taglen = strlen(tag);
+ strcpy (tag + taglen, ")");
+ }
+ ALLOC_ZVAL(my_zval);
+ array_init(my_zval);
+ INIT_PZVAL(my_zval);
+
+ add_next_index_string(my_zval, tag, 1);
+
+ switch (e->content->which)
+ {
+ case Z_ElementData_string:
+ add_next_index_string (my_zval, e->content->u.string, 1);
+ break;
+ case Z_ElementData_numeric:
+ add_next_index_long (my_zval, *e->content->u.numeric);
+ break;
+ case Z_ElementData_trueOrFalse:
+ add_next_index_long (my_zval, *e->content->u.trueOrFalse);
+ break;
+ case Z_ElementData_subtree:
+ level++;
+ grs[level] = e->content->u.subtree;
+ eno[level] = -1;
+ default:
+ }
+ zend_hash_next_index_insert (return_value->value.ht,
+ (void *) &my_zval, sizeof(zval *), NULL);
+ eno[level]++;
+ }
+}
+
+
+/* {{{ proto string yaz_record(int id, int pos, string type)
+ Return record information at given result set position */
+PHP_FUNCTION(yaz_record)
+{
+ pval **pval_id, **pval_pos, **pval_type;
+ Yaz_Association p;
+ int pos;
+ char *type;
+
+ if (ARG_COUNT(ht) != 3)
+ WRONG_PARAM_COUNT;
+ if (zend_get_parameters_ex(3, &pval_id, &pval_pos, &pval_type) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (pval_id);
+
+ convert_to_long_ex(pval_pos);
+ pos = (*pval_pos)->value.lval;
+
+ convert_to_string_ex(pval_type);
+ type = (*pval_type)->value.str.val;
+
+ if (p && p->resultSets && p->resultSets->recordList &&
+ pos >= p->resultSetStartPoint &&
+ pos < p->resultSetStartPoint + p->resultSets->recordList->num_records)
+ {
+ Z_NamePlusRecord *npr =
+ p->resultSets->recordList->records[pos - p->resultSetStartPoint];
+ if (npr->which == Z_NamePlusRecord_databaseRecord)
+ {
+ Z_External *r = (Z_External *) npr->u.databaseRecord;
+ oident *ent = oid_getentbyoid(r->direct_reference);
+
+ if (!strcmp (type, "syntax"))
+ {
+ if (ent && ent->desc)
+ RETVAL_STRING(ent->desc, 1);
+ }
+ else if (!strcmp (type, "string"))
+ {
+ if (r->which == Z_External_sutrs && ent->value == VAL_SUTRS)
+ {
+ RETVAL_STRINGL(r->u.sutrs->buf, r->u.sutrs->len, 1);
+ }
+ else if (r->which == Z_External_octet)
+ {
+ char *buf = (char *) (r->u.octet_aligned->buf);
+ int len = r->u.octet_aligned->len;
+
+ switch (ent->value)
+ {
+ case VAL_SOIF:
+ case VAL_HTML:
+ break;
+ case VAL_TEXT_XML:
+ case VAL_APPLICATION_XML:
+ break;
+ default:
+ }
+ RETVAL_STRINGL(buf, len, 1);
+ }
+ }
+ else if (!strcmp (type, "array"))
+ {
+ if (r->which == Z_External_grs1 && ent->value == VAL_GRS1)
+ {
+ retval_grs1 (return_value, r->u.grs1);
+ }
+ else if (r->which == Z_External_octet)
+ {
+ char *buf = (char *) (r->u.octet_aligned->buf);
+ ODR odr = odr_createmem (ODR_DECODE);
+ Z_GenericRecord *rec = 0;
+
+ switch (ent->value)
+ {
+ case VAL_SOIF:
+ case VAL_HTML:
+ break;
+ case VAL_TEXT_XML:
+ case VAL_APPLICATION_XML:
+ /* text2grs1 (&buf, &len, t->odr_in, 0, 0); */
+ break;
+ default:
+ rec = marc_to_grs1 (buf, odr, r->direct_reference);
+ }
+ if (rec)
+ retval_grs1 (return_value, rec);
+ odr_destroy (odr);
+ }
+ }
+ }
+ }
+}
+/* }}} */
+
+
+/* {{{ proto int yaz_syntax(int id, string syntax)
+ Set record syntax for retrieval */
+PHP_FUNCTION(yaz_syntax)
+{
+ pval **pval_id, **pval_syntax;
+ Yaz_Association p;
+ if (ARG_COUNT(ht) != 2 ||
+ zend_get_parameters_ex(2, &pval_id, &pval_syntax) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (pval_id);
+ if (p)
+ {
+ convert_to_string_ex (pval_syntax);
+ xfree (p->preferredRecordSyntax);
+ p->preferredRecordSyntax = xstrdup ((*pval_syntax)->value.str.val);
+ }
+}
+/* }}} */
+
+/* {{{ proto int yaz_element(int id, string elementsetname)
+ Set Element-Set-Name for retrieval */
+PHP_FUNCTION(yaz_element)
+{
+ pval **pval_id, **pval_element;
+ Yaz_Association p;
+ if (ARG_COUNT(ht) != 2 ||
+ zend_get_parameters_ex(2, &pval_id, &pval_element) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (pval_id);
+ if (p)
+ {
+ convert_to_string_ex (pval_element);
+ xfree (p->elementSetNames);
+ p->elementSetNames = xstrdup ((*pval_element)->value.str.val);
+ }
+}
+/* }}} */
+
+/* {{{ proto int yaz_range(int id, int start, int number)
+ Set result set start point and number of records to request */
+
+PHP_FUNCTION(yaz_range)
+{
+ pval **pval_id, **pval_start, **pval_number;
+ Yaz_Association p;
+ if (ARG_COUNT(ht) != 3 ||
+ zend_get_parameters_ex(3, &pval_id, &pval_start, &pval_number) ==
+ FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ p = get_assoc (pval_id);
+ if (p)
+ {
+ convert_to_long_ex (pval_start);
+ p->resultSetStartPoint = (*pval_start)->value.lval;
+ convert_to_long_ex (pval_number);
+ p->numberOfRecordsRequested = (*pval_number)->value.lval;
+ }
+}
+/* }}} */
+
+PHP_MINIT_FUNCTION(yaz)
+{
+ int i;
+#if PHP_YAZ_DEBUG
+ php_log_err ("PHP_MINIT_FUNCTION yaz");
+#endif
+ nmem_init();
+ order_associations = 1;
+ shared_associations = xmalloc (sizeof(*shared_associations) * MAX_ASSOC);
+ for (i = 0; i<MAX_ASSOC; i++)
+ shared_associations[i] = 0;
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(yaz)
+{
+ int i;
+
+#if PHP_YAZ_DEBUG
+ php_log_err ("PHP_MSHUTDOWN_FUNCTION yaz");
+#endif
+ if (!shared_associations)
+ return SUCCESS;
+ for (i = 0; i<MAX_ASSOC; i++)
+ yaz_association_destroy (shared_associations[i]);
+ xfree (shared_associations);
+ shared_associations = 0;
+ nmem_exit();
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(yaz)
+{
+#if PHP_YAZ_DEBUG
+ php_log_err ("PHP_MINFO_FUNCTION yaz");
+#endif
+}
+
+PHP_RSHUTDOWN_FUNCTION(yaz)
+{
+#if PHP_YAZ_DEBUG
+ php_log_err ("PHP_RSHUTDOWN yaz");
+#endif
+ return SUCCESS;
+}
+
+PHP_RINIT_FUNCTION(yaz)
+{
+ order_associations++;
+#if PHP_YAZ_DEBUG
+ php_log_err ("PHP_RINIT yaz");
+#endif
+ return SUCCESS;
+}
+
+zend_module_entry yaz_module_entry = {
+ "YAZ",
+ yaz_functions,
+ PHP_MINIT(yaz),
+ PHP_MSHUTDOWN(yaz),
+ PHP_RINIT(yaz),
+ PHP_RSHUTDOWN(yaz),
+ PHP_MINFO(yaz),
+ STANDARD_MODULE_PROPERTIES
+};
+
+#if COMPILE_DL
+DLEXPORT zend_module_entry *get_module(void) { return &yaz_module_entry; }
+#endif
+
+
+#endif
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */