diff options
Diffstat (limited to 'ext/yaz/php_yaz.c')
-rw-r--r-- | ext/yaz/php_yaz.c | 2704 |
1 files changed, 0 insertions, 2704 deletions
diff --git a/ext/yaz/php_yaz.c b/ext/yaz/php_yaz.c deleted file mode 100644 index 8862fdef00..0000000000 --- a/ext/yaz/php_yaz.c +++ /dev/null @@ -1,2704 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP version 4.0 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2001 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$ */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" - -#if HAVE_YAZ -#include "ext/standard/info.h" -#include "php_yaz.h" - -#include <yaz/proto.h> -#include <yaz/tcpip.h> -#include <yaz/pquery.h> - -#ifdef YAZ_DATE -#if YAZ_DATE >= 20010808L -#define YAZ_HAS_SORT_SPEC 1 -#endif -#endif - -#if YAZ_HAS_SORT_SPEC -#include <yaz/sortspec.h> -#endif -#include <yaz/diagbib1.h> -#include <yaz/otherinfo.h> -#include <yaz/marcdisp.h> -#include <yaz/yaz-util.h> -#include <yaz/yaz-version.h> -#include <yaz/yaz-ccl.h> -#include <yaz/ill.h> - -#define MAX_ASSOC 100 - -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; - int sorted; -}; - -#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; - char *local_databases; - COMSTACK cs; - char *cookie_in; - char *cookie_out; - char *user; - char *group; - char *pass; - char *proxy; - int piggyback; - int error; - char *addinfo; - Yaz_ResultSet resultSets; - int persistent; - int in_use; - int order; - int state; - int mask_select; - int reconnect_flag; - char *sort_criteria; - ODR odr_in; - ODR odr_out; - ODR odr_scan; - Z_ScanResponse *scan_response; - 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; - - CCL_parser ccl_parser; - char *ill_buf_out; - int ill_len_out; -}; - -static Yaz_Association yaz_association_mk () -{ - Yaz_Association p = xmalloc (sizeof(*p)); - p->host_port = 0; - p->num_databaseNames = 0; - p->databaseNames = 0; - p->local_databases = 0; - p->cs = 0; - p->cookie_in = 0; - p->cookie_out = 0; - p->user = 0; - p->group = 0; - p->pass = 0; - p->proxy = 0; - p->error = 0; - p->addinfo = 0; - p->resultSets = 0; - p->in_use = 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->odr_scan = odr_createmem (ODR_ENCODE); - p->scan_response = 0; - p->buf_out = 0; - p->len_out = 0; - p->buf_in = 0; - p->len_in = 0; - p->action = 0; - p->ill_buf_out = 0; - p->ill_len_out = 0; - p->resultSetStartPoint = 1; - p->numberOfRecordsRequested = 10; - p->elementSetNames = 0; - p->preferredRecordSyntax = 0; - p->ccl_parser = ccl_parser_create(); - p->ccl_parser->bibset = 0; - p->sort_criteria = 0; - return p; -} - -static void yaz_association_destroy (Yaz_Association p) -{ - int i; - if (!p) - return ; - xfree (p->host_port); - xfree (p->local_databases); - 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_in); - xfree (p->cookie_out); - xfree (p->sort_criteria); - xfree (p->user); - xfree (p->group); - xfree (p->pass); - xfree (p->proxy); - xfree (p->addinfo); - odr_destroy (p->odr_in); - odr_destroy (p->odr_out); - odr_destroy (p->odr_scan); - /* buf_out */ - /* buf_in */ - /* action */ - xfree (p->ill_buf_out); - xfree (p->elementSetNames); - xfree (p->preferredRecordSyntax); - ccl_qual_rm(&p->ccl_parser->bibset); - ccl_parser_destroy(p->ccl_parser); -} - -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; - p->sorted = 0; - return p; -} - -static void yaz_resultset_destroy (Yaz_ResultSet p) -{ - if (!p) - return; - if (p->odr) - odr_destroy (p->odr); -} - -#ifdef ZTS -static MUTEX_T yaz_mutex; -#endif - -ZEND_DECLARE_MODULE_GLOBALS(yaz); - -static Yaz_Association *shared_associations; -static int order_associations; -static int le_link; - -static unsigned char third_argument_force_ref[] = { - 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; - -static unsigned char second_argument_force_ref[] = { - 2, BYREF_NONE, BYREF_FORCE }; - -function_entry yaz_functions [] = { - PHP_FE(yaz_connect, NULL) - PHP_FE(yaz_close, NULL) - PHP_FE(yaz_search, NULL) - PHP_FE(yaz_wait, second_argument_force_ref) - 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) - PHP_FE(yaz_itemorder, NULL) - PHP_FE(yaz_scan, NULL) - PHP_FE(yaz_scan_result, second_argument_force_ref) - PHP_FE(yaz_present, NULL) - PHP_FE(yaz_ccl_conf, NULL) - PHP_FE(yaz_ccl_parse, third_argument_force_ref) - PHP_FE(yaz_database, NULL) - PHP_FE(yaz_sort, NULL) - {NULL, NULL, NULL} -}; - -static void get_assoc (INTERNAL_FUNCTION_PARAMETERS, pval **id, - Yaz_Association *assocp) -{ - Yaz_Association *as = 0; - YAZSLS_FETCH(); - - *assocp = 0; -#ifdef ZTS - tsrm_mutex_lock (yaz_mutex); -#endif - ZEND_FETCH_RESOURCE(as, Yaz_Association *, id, -1, - "YAZ link", le_link); - if (as && *as && (*as)->order == YAZSG(assoc_seq) && (*as)->in_use) - { - *assocp = *as; - } - else - { -#ifdef ZTS - tsrm_mutex_unlock (yaz_mutex); -#endif - php_error(E_WARNING, "Invalid YAZ handle"); - } -} - -static void release_assoc (Yaz_Association assoc) -{ -#ifdef ZTS - if (assoc) - tsrm_mutex_unlock(yaz_mutex); -#endif -} -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); - - if (p->proxy) - addr = tcpip_strtoaddr (p->proxy); - else - 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 const char *array_lookup_string(HashTable *ht, const char *idx) -{ - pval **pvalue; - - if (ht && zend_hash_find(ht, (char*) idx, strlen(idx)+1, - (void**) &pvalue) == SUCCESS) - { - SEPARATE_ZVAL(pvalue); - convert_to_string(*pvalue); - return (*pvalue)->value.str.val; - } - return 0; -} - -static long *array_lookup_long(HashTable *ht, const char *idx) -{ - pval **pvalue; - - if (ht && zend_hash_find(ht, (char*) idx, strlen(idx)+1, - (void**) &pvalue) == SUCCESS) - { - SEPARATE_ZVAL(pvalue); - convert_to_long(*pvalue); - return &(*pvalue)->value.lval; - } - return 0; -} - -static long *array_lookup_bool(HashTable *ht, const char *idx) -{ - pval **pvalue; - - if (ht && zend_hash_find(ht, (char*) idx, strlen(idx)+1, - (void**) &pvalue) == SUCCESS) - { - SEPARATE_ZVAL(pvalue); - convert_to_boolean(*pvalue); - return &(*pvalue)->value.lval; - } - return 0; -} - -static int send_present (Yaz_Association t); -static int send_sort_present (Yaz_Association t); -static int send_sort (Yaz_Association t); - -static void handle_records (Yaz_Association t, Z_Records *sr, - int present_phase) -{ - 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->resultSets->recordList->num_records = - t->resultSets->resultCount - t->resultSetStartPoint + 1; - else - t->resultSets->recordList->num_records = - t->numberOfRecordsRequested; - } - if (sr && sr->which == Z_Records_DBOSD) - { - int j, i; - NMEM nmem = odr_extract_mem (t->odr_in); - Z_NamePlusRecordList *p = - sr->u.databaseOrSurDiagnostics; - if (t->resultSets->recordList) - { - 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, nmem); - nmem_destroy (nmem); - } - if (present_phase && p->num_records == 0) - { - /* present response and we didn't get any records! */ - t->error = PHP_YAZ_ERROR_DECODE; - t->resultSets->recordList = 0; - } - } - else if (present_phase) - { - /* present response and we didn't get any records! */ - t->error = PHP_YAZ_ERROR_DECODE; - t->resultSets->recordList = 0; - } - } -} - -static void search_response (Yaz_Association t, Z_SearchResponse *sr) -{ - t->resultSets->resultCount = *sr->resultCount; - handle_records (t, sr->records, 0); -} - -static void present_response (Yaz_Association t, Z_PresentResponse *pr) -{ - handle_records (t, pr->records, 1); -} - -static void scan_response (Yaz_Association t, Z_ScanResponse *res) -{ - NMEM nmem = odr_extract_mem (t->odr_in); - if (res->entries && res->entries->nonsurrogateDiagnostics) - response_diag(t, res->entries->nonsurrogateDiagnostics[0]); - t->scan_response = res; - nmem_transfer (t->odr_scan->mem, nmem); - nmem_destroy (nmem); -} - -static void sort_response (Yaz_Association t, Z_SortResponse *res) -{ - if (t->resultSets) - t->resultSets->sorted = 1; - if (res->diagnostics && res->num_diagnostics > 0) - response_diag (t, res->diagnostics[0]); -} - -static void es_response (Yaz_Association t, - Z_ExtendedServicesResponse *res) -{ - if (res->diagnostics && res->num_diagnostics > 0) - response_diag(t, res->diagnostics[0]); -} - -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_in); - t->cookie_in = xstrdup(cookie); - } - if (t->action) - (*t->action) (t); - t->action = 0; - } - break; - case Z_APDU_searchResponse: - search_response (t, apdu->u.searchResponse); - send_sort_present (t); - break; - case Z_APDU_presentResponse: - present_response (t, apdu->u.presentResponse); - send_present (t); - break; - case Z_APDU_scanResponse: - scan_response (t, apdu->u.scanResponse); - break; - case Z_APDU_extendedServicesResponse: - es_response (t, apdu->u.extendedServicesResponse); - break; - case Z_APDU_sortResponse: - sort_response (t, apdu->u.sortResponse); - send_present (t); - break; - 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_ex (Yaz_Association t, char *buf_out, int len_out) -{ - int r; - - if ((r=cs_put (t->cs, buf_out, 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 do_write(Yaz_Association t) -{ - return do_write_ex (t, t->buf_out, t->len_out); -} - -static int send_packet (Yaz_Association t) -{ - return do_write_ex (t, t->ill_buf_out, t->ill_len_out); -} - -static int encode_APDU(Yaz_Association t, Z_APDU *a, ODR out) -{ - char str[120]; - - if (a == 0) - abort(); - sprintf (str, "send_APDU t=%p type=%d", t, a->which); - if (t->cookie_out) - { - Z_OtherInformation **oi; - yaz_oi_APDU(a, &oi); - yaz_oi_set_string_oidval(oi, out, VAL_COOKIE, 1, t->cookie_out); - } - if (!z_APDU(out, &a, 0, 0)) - { - FILE *outf = fopen("/tmp/apdu.txt", "w"); - if (outf) - { - ODR odr_pr = odr_createmem(ODR_PRINT); - fprintf (outf, "a=%p\n", a); - odr_setprint(odr_pr, outf); - z_APDU(odr_pr, &a, 0, 0); - odr_destroy(odr_pr); - fclose (outf); - } - php_error (E_WARNING, "YAZ: Couldn't encode APDU"); - do_close (t); - t->error = PHP_YAZ_ERROR_ENCODE; - return -1; - } - return 0; -} - -static int send_APDU (Yaz_Association t, Z_APDU *a) -{ - encode_APDU(t, a, t->odr_out); - t->buf_out = odr_getbuf(t->odr_out, &t->len_out, 0); - odr_reset(t->odr_out); - do_write (t); - return 0; -} - -/* set database names. Take local databases (if set); otherwise - take databases given in ZURL (if set); otherwise use Default */ -static char **set_DatabaseNames (Yaz_Association t, int *num) -{ - char **databaseNames; - char *c; - int no = 2; - char *cp = t->local_databases; - - if (!cp || !*cp) - { - cp = strchr (t->host_port, '/'); - if (cp) - cp++; - } - 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 = strchr (cp, '+'); - if (!c) - c = cp + strlen(cp); - else if (c == cp) - { - 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'; - cp = c; - if (*cp) - cp++; - } - 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 && t->piggyback && - (t->sort_criteria == 0 || *t->sort_criteria == 0) ) - { - sreq->largeSetLowerBound = odr_malloc (t->odr_out, sizeof(int)); - *sreq->largeSetLowerBound = 9999999; - 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_sort_present (Yaz_Association t) -{ - if (!send_sort(t)) - send_present (t); -} - -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->error) /* don't continue on error */ - return 0; - if (!t->resultSets) /* no result set yet? */ - return 0; - while (t->resultSets->recordList) - { - if (i >= t->resultSets->recordList->num_records) - { /* got all records ... */ - 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)); - if (t->resultSets->recordList) - *req->numberOfRecordsRequested = - t->resultSets->recordList->num_records - i; - else - *req->numberOfRecordsRequested = t->numberOfRecordsRequested; - - if (*req->numberOfRecordsRequested <= 0) - return 0; - - 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; -} - -#if YAZ_HAS_SORT_SPEC - -#else - -static int *odr_intdup(ODR o, int v) -{ - int *dst = (int*) odr_malloc (o, sizeof(int)); - *dst = v; - return dst; -} - -static Z_SortKeySpecList *yaz_sort_spec (ODR out, const char *arg) -{ - int oid[OID_SIZE]; - oident bib1; - char sort_string_buf[32], sort_flags[32]; - Z_SortKeySpecList *sksl = (Z_SortKeySpecList *) - odr_malloc (out, sizeof(*sksl)); - int off; - - sksl->num_specs = 0; - sksl->specs = (Z_SortKeySpec **)odr_malloc (out, sizeof(sksl->specs) * 20); - - bib1.proto = PROTO_Z3950; - bib1.oclass = CLASS_ATTSET; - bib1.value = VAL_BIB1; - while ((sscanf (arg, "%31s %31s%n", sort_string_buf, - sort_flags, &off)) == 2 && off > 1) - { - int i; - char *sort_string_sep; - char *sort_string = sort_string_buf; - Z_SortKeySpec *sks = (Z_SortKeySpec *)odr_malloc (out, sizeof(*sks)); - Z_SortKey *sk = (Z_SortKey *)odr_malloc (out, sizeof(*sk)); - - arg += off; - sksl->specs[sksl->num_specs++] = sks; - sks->sortElement = (Z_SortElement *) - odr_malloc (out, sizeof(*sks->sortElement)); - sks->sortElement->which = Z_SortElement_generic; - sks->sortElement->u.generic = sk; - - if ((sort_string_sep = strchr (sort_string, '='))) - { - int i = 0; - sk->which = Z_SortKey_sortAttributes; - sk->u.sortAttributes = (Z_SortAttributes *) - odr_malloc (out, sizeof(*sk->u.sortAttributes)); - sk->u.sortAttributes->id = oid_ent_to_oid(&bib1, oid); - sk->u.sortAttributes->list = (Z_AttributeList *) - odr_malloc (out, sizeof(*sk->u.sortAttributes->list)); - sk->u.sortAttributes->list->attributes = (Z_AttributeElement **) - odr_malloc (out, 10 * - sizeof(*sk->u.sortAttributes->list->attributes)); - while (i < 10 && sort_string && sort_string_sep) - { - Z_AttributeElement *el = (Z_AttributeElement *) - odr_malloc (out, sizeof(*el)); - sk->u.sortAttributes->list->attributes[i] = el; - el->attributeSet = 0; - el->attributeType = odr_intdup (out, atoi (sort_string)); - el->which = Z_AttributeValue_numeric; - el->value.numeric = - odr_intdup (out, atoi (sort_string_sep + 1)); - i++; - sort_string = strchr(sort_string, ','); - if (sort_string) - { - sort_string++; - sort_string_sep = strchr (sort_string, '='); - } - } - sk->u.sortAttributes->list->num_attributes = i; - } - else - { - sk->which = Z_SortKey_sortField; - sk->u.sortField = odr_strdup (out, sort_string); - } - sks->sortRelation = odr_intdup (out, Z_SortRelation_ascending); - sks->caseSensitivity = odr_intdup (out, Z_SortCase_caseSensitive); - - sks->which = Z_SortKeySpec_null; - sks->u.null = odr_nullval (); - - for (i = 0; sort_flags[i]; i++) - { - switch (sort_flags[i]) - { - case 'd': - case 'D': - case '>': - *sks->sortRelation = Z_SortRelation_descending; - break; - case 'a': - case 'A': - case '<': - *sks->sortRelation = Z_SortRelation_ascending; - break; - case 'i': - case 'I': - *sks->caseSensitivity = Z_SortCase_caseInsensitive; - break; - case 'S': - case 's': - *sks->caseSensitivity = Z_SortCase_caseSensitive; - break; - } - } - } - if (!sksl->num_specs) - return 0; - return sksl; -} -#endif - -static int send_sort (Yaz_Association t) -{ - if (t->error) - return 0; - if (!t->resultSets || t->resultSets->sorted) - return 0; - if (t->sort_criteria && *t->sort_criteria) - { - Z_APDU *apdu = zget_APDU(t->odr_out, Z_APDU_sortRequest); - Z_SortRequest *req = apdu->u.sortRequest; - - req->num_inputResultSetNames = 1; - req->inputResultSetNames = (Z_InternationalString **) - odr_malloc (t->odr_out, sizeof(*req->inputResultSetNames)); - req->inputResultSetNames[0] = odr_strdup (t->odr_out, "default"); - req->sortedResultSetName = odr_strdup (t->odr_out, "default"); - req->sortSequence = yaz_sort_spec (t->odr_out, t->sort_criteria); - if (!req->sortSequence) - { - t->resultSets->sorted = 1; - return 0; - } - send_APDU (t, apdu); - return 1; - } - return 0; -} - -static void send_init(Yaz_Association t) -{ - Z_APDU *apdu = zget_APDU(t->odr_out, Z_APDU_initRequest); - Z_InitRequest *ireq = apdu->u.initRequest; - Z_IdAuthentication *auth = odr_malloc(t->odr_out, sizeof(*auth)); - 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->options, Z_Options_sort); - ODR_MASK_SET(ireq->options, Z_Options_extendedServices); - - 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_groupId || auth_password) - { - - Z_IdPass *pass = odr_malloc(t->odr_out, sizeof(*pass)); - int i = 0; - 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; - } - } - else if (auth_userId) - { - auth->which = Z_IdAuthentication_open; - auth->u.open = odr_malloc(t->odr_out, strlen(auth_userId)+1); - strcpy(auth->u.open, auth_userId); - 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, int timeout) -{ - fd_set input, output; - int i; - int no = 0; - int max_fd = 0; - struct timeval tv; - YAZSLS_FETCH(); - - tv.tv_sec = timeout; - tv.tv_usec = 0; - -#ifdef ZTS - tsrm_mutex_lock (yaz_mutex); -#endif - 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 != YAZSG(assoc_seq) || !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++; - } - } -#ifdef ZTS - tsrm_mutex_unlock (yaz_mutex); -#endif - if (!no) - return 0; - no = select (max_fd+1, &input, &output, 0, &tv); -#ifdef ZTS - tsrm_mutex_lock (yaz_mutex); -#endif - for (i = 0; i<MAX_ASSOC; i++) - { - int fd; - Yaz_Association p = shared_associations[i]; - if (!p || p->order != YAZSG(assoc_seq) || !p->cs) - continue; - *id = i+1; - fd =cs_fileno(p->cs); - if (no <= 0) - { - if (p->mask_select) /* only mark for those still pending */ - { - p->error = PHP_YAZ_ERROR_TIMEOUT; - do_close (p); - } - } - else if (p->state == PHP_YAZ_STATE_CONNECTING) - { - if (FD_ISSET (fd, &output)) - { - send_init(p); - } - else if (FD_ISSET (fd, &input)) - { - do_close(p); - p->error = PHP_YAZ_ERROR_CONNECT; - } - } - 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; - } - } -#ifdef ZTS - tsrm_mutex_unlock (yaz_mutex); -#endif - return no; -} - -static int strcmp_null(const char *s1, const char *s2) -{ - if (s1 == 0 && s2 == 0) - return 0; - if (s1 == 0 || s2 == 0) - return -1; - return strcmp(s1, s2); -} - -/* {{{ proto int yaz_connect(string zurl [ array options]) - Create target with given zurl. Returns positive id if successful. */ -PHP_FUNCTION(yaz_connect) -{ - int i; - char *cp; - char *zurl_str; - const char *user_str = 0, *group_str = 0, *pass_str = 0; - const char *cookie_str = 0, *proxy_str = 0; - int persistent = 1; - int piggyback = 1; - pval **zurl, **user = 0; - Yaz_Association as; - YAZSLS_FETCH(); - - if (ZEND_NUM_ARGS() == 1) - { - if (zend_get_parameters_ex (1, &zurl) == FAILURE) - WRONG_PARAM_COUNT; - } - else if (ZEND_NUM_ARGS() == 2) - { - if (zend_get_parameters_ex (2, &zurl, &user) == FAILURE) - WRONG_PARAM_COUNT; - - if (Z_TYPE_PP(user) == IS_ARRAY) - { - long *persistent_val; - long *piggyback_val; - HashTable *ht = Z_ARRVAL_PP(user); - user_str = array_lookup_string(ht, "user"); - group_str = array_lookup_string(ht, "group"); - pass_str = array_lookup_string(ht, "password"); - cookie_str = array_lookup_string(ht, "cookie"); - proxy_str = array_lookup_string(ht, "proxy"); - persistent_val = array_lookup_bool(ht, "persistent"); - if (persistent_val) - persistent = *persistent_val; - piggyback_val = array_lookup_bool(ht, "piggyback"); - if (piggyback_val) - piggyback = *piggyback_val; - } - else - { - convert_to_string_ex (user); - user_str = (*user)->value.str.val; - } - } - else - { - 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 ... */ -#ifdef ZTS - tsrm_mutex_lock (yaz_mutex); -#endif - for (i = 0; i<MAX_ASSOC; i++) - { - as = shared_associations[i]; - if (persistent && as && !as->in_use && - !strcmp_null (as->host_port, zurl_str) && - !strcmp_null (as->user, user_str) && - !strcmp_null (as->group, group_str) && - !strcmp_null (as->pass, pass_str) && - !strcmp_null (as->proxy, proxy_str) && - !strcmp_null (as->cookie_out, cookie_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++) - { - as = shared_associations[i]; - if (persistent && !as->in_use && as->order < min_order) - { - min_order = as->order; - i0 = i; - } - } - if (i == MAX_ASSOC) - { - i = i0; - if (i == -1) - { -#ifdef ZTS - tsrm_mutex_unlock (yaz_mutex); -#endif - RETURN_LONG(0); /* no free slot */ - } - else /* "best" free slot */ - yaz_association_destroy(shared_associations[i]); - } - shared_associations[i] = as = yaz_association_mk (); - as->host_port = xstrdup (zurl_str); - if (cookie_str) - as->cookie_out = xstrdup (cookie_str); - if (user_str) - as->user = xstrdup (user_str); - if (group_str) - as->group = xstrdup (group_str); - if (pass_str) - as->pass = xstrdup (pass_str); - if (proxy_str) - as->proxy = xstrdup (proxy_str); - } - as->action = 0; - as->in_use = 1; - as->persistent = persistent; - as->order = YAZSG(assoc_seq); - as->error = 0; - xfree (as->sort_criteria); - as->sort_criteria = 0; - as->piggyback = piggyback; - as->numberOfRecordsRequested = 10; - as->resultSetStartPoint = 1; - xfree (as->local_databases); - as->local_databases = 0; -#ifdef ZTS - tsrm_mutex_unlock (yaz_mutex); -#endif - ZEND_REGISTER_RESOURCE(return_value, &shared_associations[i], le_link); -} -/* }}} */ - -/* {{{ proto int yaz_close(int id) - Destory and close target */ -PHP_FUNCTION(yaz_close) -{ - Yaz_Association p; - pval **id; - if (ZEND_NUM_ARGS() != 1) - WRONG_PARAM_COUNT; - if (zend_get_parameters_ex (1, &id) == FAILURE) - RETURN_FALSE; - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p); - if (!p) - RETURN_FALSE; - release_assoc (p); - zend_list_delete ((*id)->value.lval); - 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 (ZEND_NUM_ARGS() == 3) - { - if (zend_get_parameters_ex(3, &id, &type, &query) == FAILURE) - { - WRONG_PARAM_COUNT; - } - } - else - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p); - if (!p) - { - RETURN_FALSE; - } - p->action = 0; - 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; - RETVAL_FALSE; - } - else - { - RETVAL_TRUE; - } - } - else if (!strcmp(type_str, "ccl")) - { - r->query->which = Z_Query_type_2; - r->query->u.type_2 = odr_malloc (r->odr, sizeof(*r->query->u.type_2)); - r->query->u.type_2->buf = odr_strdup(r->odr, query_str); - r->query->u.type_2->len = strlen(query_str); - } - else - { - yaz_resultset_destroy(r); - p->resultSets = 0; - RETVAL_FALSE; - } - if (p->resultSets) - p->action = send_search; - release_assoc (p); -} -/* }}} */ - -/* {{{ proto int yaz_present(int id) - Retrieve records */ -PHP_FUNCTION(yaz_present) -{ - pval **id; - Yaz_Association p; - if (ZEND_NUM_ARGS() != 1) - WRONG_PARAM_COUNT; - if (zend_get_parameters_ex(1, &id) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p); - if (!p) - { - RETURN_FALSE; - } - p->action = 0; - if (p->resultSets) - { - p->resultSets->recordList = 0; - p->action = send_sort_present; - } - release_assoc (p); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto int yaz_wait([array options]) - Process events. */ -PHP_FUNCTION(yaz_wait) -{ - int i, id, timeout = 15; - YAZSLS_FETCH(); - - if (ZEND_NUM_ARGS() == 1) - { - long *val = 0; - pval **pval_options = 0; - HashTable *options_ht = 0; - if (zend_get_parameters_ex(1, &pval_options) == FAILURE) - { - WRONG_PARAM_COUNT; - } - if (Z_TYPE_PP(pval_options) != IS_ARRAY) - { - php_error(E_WARNING, "yaz_wait: Expected array parameter"); - RETURN_FALSE; - } - options_ht = Z_ARRVAL_PP(pval_options); - val = array_lookup_long(options_ht, "timeout"); - if (val) - timeout = *val; - } -#ifdef ZTS - tsrm_mutex_lock (yaz_mutex); -#endif - for (i = 0; i<MAX_ASSOC; i++) - { - Yaz_Association p = shared_associations[i]; - if (!p || p->order != YAZSG(assoc_seq) || !p->action - || p->mask_select) - continue; - if (!p->cs) - { - do_connect (p); - } - else - { - p->reconnect_flag = 1; - (*p->action)(p); - } - } -#ifdef ZTS - tsrm_mutex_unlock (yaz_mutex); -#endif - while (do_event(&id, timeout)) - ; - 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 (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &id) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p); - if (!p) - { - RETURN_LONG(0); - } - RETVAL_LONG(p->error); - release_assoc (p); -} -/* }}} */ - -/* {{{ proto string yaz_error(int id) - Return last error message */ -PHP_FUNCTION(yaz_error) -{ - pval **id; - Yaz_Association p; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &id) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p); - 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; - } - release_assoc (p); -} -/* }}} */ - -/* {{{ 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 (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &id) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p); - if (p && p->error > 0 && p->addinfo && *p->addinfo) - { - RETVAL_STRING(p->addinfo, 1); - } - release_assoc (p); -} -/* }}} */ - -/* {{{ 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 (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &id) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p); - if (!p || !p->resultSets) - { - RETVAL_LONG(0); - } - else - { - RETVAL_LONG(p->resultSets->resultCount); - } - release_assoc (p); -} -/* }}} */ - -static 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]; - int identifier_flag = 1; - - 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 (indicator_length == 2) - { - if (buf[i + indicator_length] != ISO2709_IDFS) - identifier_flag = 0; - } - else if (!memcmp (tag_str, "00", 2)) - identifier_flag = 0; - - - if (identifier_flag && 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; - } - 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 (ZEND_NUM_ARGS() != 3) - WRONG_PARAM_COUNT; - if (zend_get_parameters_ex(3, &pval_id, &pval_pos, &pval_type) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - - 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; - npr = p->resultSets->recordList->records[pos - p->resultSetStartPoint]; - - if (npr && 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, "database")) - { - if (npr->databaseName) - RETVAL_STRING(npr->databaseName, 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: - break; - } - 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); - } - } - } - } - release_assoc (p); -} -/* }}} */ - - -/* {{{ 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 (ZEND_NUM_ARGS() != 2 || - zend_get_parameters_ex(2, &pval_id, &pval_syntax) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - convert_to_string_ex (pval_syntax); - xfree (p->preferredRecordSyntax); - p->preferredRecordSyntax = xstrdup ((*pval_syntax)->value.str.val); - } - release_assoc (p); -} -/* }}} */ - -/* {{{ 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 (ZEND_NUM_ARGS() != 2 || - zend_get_parameters_ex(2, &pval_id, &pval_element) == FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - convert_to_string_ex (pval_element); - xfree (p->elementSetNames); - p->elementSetNames = xstrdup ((*pval_element)->value.str.val); - } - release_assoc (p); -} -/* }}} */ - -/* {{{ 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 (ZEND_NUM_ARGS() != 3 || - zend_get_parameters_ex(3, &pval_id, &pval_start, &pval_number) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - convert_to_long_ex (pval_start); - p->resultSetStartPoint = (*pval_start)->value.lval; - if (p->resultSetStartPoint < 1) - p->resultSetStartPoint = 1; - convert_to_long_ex (pval_number); - p->numberOfRecordsRequested = (*pval_number)->value.lval; - } - release_assoc (p); -} -/* }}} */ - -/* {{{ proto int yaz_sort(int id, string sortspec) - Set result set sorting criteria */ - -PHP_FUNCTION(yaz_sort) -{ - pval **pval_id, **pval_criteria; - Yaz_Association p; - if (ZEND_NUM_ARGS() != 2 || - zend_get_parameters_ex(2, &pval_id, &pval_criteria) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - convert_to_string_ex (pval_criteria); - if (p->resultSets && p->resultSets->sorted) - { - if (!p->sort_criteria || strcmp (p->sort_criteria, - (*pval_criteria)->value.str.val)) - p->resultSets->sorted = 0; - } - xfree (p->sort_criteria); - p->sort_criteria = xstrdup ((*pval_criteria)->value.str.val); - } - release_assoc (p); -} -/* }}} */ - -static const char *ill_array_lookup (void *clientData, const char *idx) -{ - return array_lookup_string((HashTable *) clientData, idx+4); -} - -static Z_External *encode_ill_request (Yaz_Association t, HashTable *ht) -{ - ODR out = t->odr_out; - ILL_Request *req; - Z_External *r = 0; - struct ill_get_ctl ctl; - - ctl.odr = t->odr_out; - ctl.clientData = ht; - ctl.f = ill_array_lookup; - - req = ill_get_ILLRequest(&ctl, "ill", 0); - - if (!ill_Request (out, &req, 0, 0)) - { - int ill_request_size; - char *ill_request_buf = odr_getbuf (out, &ill_request_size, 0); - if (ill_request_buf) - odr_setbuf (out, ill_request_buf, ill_request_size, 1); - php_error(E_WARNING, "yaz_itemorder: Expected array parameter"); - return 0; - } - else - { - oident oid; - int illRequest_size = 0; - char *illRequest_buf = odr_getbuf (out, &illRequest_size, 0); - - oid.proto = PROTO_GENERAL; - oid.oclass = CLASS_GENERAL; - oid.value = VAL_ISO_ILL_1; - - r = (Z_External *) odr_malloc (out, sizeof(*r)); - r->direct_reference = odr_oiddup(out,oid_getoidbyent(&oid)); - r->indirect_reference = 0; - r->descriptor = 0; - r->which = Z_External_single; - - r->u.single_ASN1_type = (Odr_oct *) - odr_malloc (out, sizeof(*r->u.single_ASN1_type)); - r->u.single_ASN1_type->buf = odr_malloc (out, illRequest_size); - r->u.single_ASN1_type->len = illRequest_size; - r->u.single_ASN1_type->size = illRequest_size; - memcpy (r->u.single_ASN1_type->buf, illRequest_buf, illRequest_size); - } - return r; -} - -static Z_ItemOrder *encode_item_order(Yaz_Association t, - HashTable *ht) -{ - Z_ItemOrder *req = odr_malloc (t->odr_out, sizeof(*req)); - const char *str; - -#ifdef ASN_COMPILED - req->which=Z_IOItemOrder_esRequest; -#else - req->which=Z_ItemOrder_esRequest; -#endif - req->u.esRequest = (Z_IORequest *) - odr_malloc(t->odr_out,sizeof(Z_IORequest)); - - /* to keep part ... */ - req->u.esRequest->toKeep = (Z_IOOriginPartToKeep *) - odr_malloc(t->odr_out,sizeof(Z_IOOriginPartToKeep)); - req->u.esRequest->toKeep->supplDescription = 0; - req->u.esRequest->toKeep->contact = - odr_malloc (t->odr_out, sizeof(*req->u.esRequest->toKeep->contact)); - - str = array_lookup_string (ht, "contact-name"); - req->u.esRequest->toKeep->contact->name = str ? - nmem_strdup (t->odr_out->mem, str) : 0; - - str = array_lookup_string (ht, "contact-phone"); - req->u.esRequest->toKeep->contact->phone = str ? - nmem_strdup (t->odr_out->mem, str) : 0; - - str = array_lookup_string (ht, "contact-email"); - req->u.esRequest->toKeep->contact->email = str ? - nmem_strdup (t->odr_out->mem, str) : 0; - - req->u.esRequest->toKeep->addlBilling = 0; - - /* not to keep part ... */ - req->u.esRequest->notToKeep = (Z_IOOriginPartNotToKeep *) - odr_malloc(t->odr_out,sizeof(Z_IOOriginPartNotToKeep)); - - req->u.esRequest->notToKeep->resultSetItem = (Z_IOResultSetItem *) - odr_malloc(t->odr_out, sizeof(Z_IOResultSetItem)); - req->u.esRequest->notToKeep->resultSetItem->resultSetId = "default"; - req->u.esRequest->notToKeep->resultSetItem->item = - (int *) odr_malloc(t->odr_out, sizeof(int)); - - str = array_lookup_string (ht, "itemorder-item"); - *req->u.esRequest->notToKeep->resultSetItem->item = - (str ? atoi(str) : 1); - - req->u.esRequest->notToKeep->itemRequest = - encode_ill_request(t, ht); - - return req; -} - -static Z_APDU *encode_es_itemorder (Yaz_Association t, HashTable *ht) -{ - Z_APDU *apdu = zget_APDU(t->odr_out, Z_APDU_extendedServicesRequest); - Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; - const char *str; - struct oident oident; - int oid[OID_SIZE]; - Z_External *r = odr_malloc (t->odr_out, sizeof(*r)); - - *req->function = Z_ExtendedServicesRequest_create; - oident.proto = PROTO_Z3950; - oident.oclass = CLASS_EXTSERV; - oident.value = VAL_ITEMORDER; - req->taskSpecificParameters = r; - r->direct_reference = - odr_oiddup(t->odr_out, oid_ent_to_oid(&oident, oid)); - r->indirect_reference = 0; - r->descriptor = 0; - r->which = Z_External_itemOrder; - r->u.itemOrder = encode_item_order (t, ht); - req->packageType = odr_oiddup(t->odr_out, oid_ent_to_oid(&oident, oid)); - - str = array_lookup_string(ht, "package-name"); - if (str && *str) - req->packageName = nmem_strdup (t->odr_out->mem, str); - - str = array_lookup_string(ht, "user-id"); - if (str) - req->userId = nmem_strdup (t->odr_out->mem, str); - - return apdu; -} - - -/* {{{ proto int yaz_itemorder(int id, array package) - Sends Item Order request */ - -PHP_FUNCTION(yaz_itemorder) -{ - pval **pval_id, **pval_package; - Yaz_Association p; - if (ZEND_NUM_ARGS() != 2 || - zend_get_parameters_ex(2, &pval_id, &pval_package) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - if (Z_TYPE_PP(pval_package) != IS_ARRAY) - { - php_error(E_WARNING, "yaz_itemorder: Expected array parameter"); - RETURN_FALSE; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - Z_APDU *apdu; - p->action = 0; - apdu = encode_es_itemorder (p, Z_ARRVAL_PP(pval_package)); - if (apdu) - { - char *buf; - encode_APDU(p, apdu, p->odr_out); - buf = odr_getbuf(p->odr_out, &p->ill_len_out, 0); - xfree (p->ill_buf_out); - p->ill_buf_out = xmalloc (p->ill_len_out); - memcpy (p->ill_buf_out, buf, p->ill_len_out); - p->action = send_packet; - } - } - release_assoc (p); -} -/* }}} */ - -static Z_APDU *encode_scan (Yaz_Association t, const char *type, - const char *query, HashTable *ht) -{ - Z_APDU *apdu = zget_APDU(t->odr_out, Z_APDU_scanRequest); - Z_ScanRequest *req = apdu->u.scanRequest; - const char *val; - if (!strcmp(type, "rpn")) - { - if (!(req->termListAndStartPoint = - p_query_scan(t->odr_out, PROTO_Z3950, &req->attributeSet, - query))) - { - char str[80]; - sprintf (str, "YAZ: Bad Scan query: '%.40s'", query); - php_error (E_WARNING, str); - return 0; - } - } - else - { - char str[80]; - sprintf (str, "YAZ: Bad Scan query type: '%.40s'", type); - php_error (E_WARNING, str); - return 0; - } - val = array_lookup_string(ht, "number"); - if (val && *val) - *req->numberOfTermsRequested = atoi(val); - val = array_lookup_string(ht, "position"); - if (val && *val) - { - req->preferredPositionInResponse = - odr_malloc (t->odr_out, sizeof(int)); - *req->preferredPositionInResponse = atoi(val); - } - val = array_lookup_string(ht, "stepsize"); - if (val && *val) - { - req->stepSize = odr_malloc (t->odr_out, sizeof(int)); - *req->stepSize = atoi(val); - } - req->databaseNames = set_DatabaseNames (t, &req->num_databaseNames); - return apdu; -} - -/* {{{ proto int yaz_scan(int id, type, query [, flags]) - Sends Scan Request */ -PHP_FUNCTION(yaz_scan) -{ - pval **pval_id, **pval_type, **pval_query, **pval_flags = 0; - HashTable *flags_ht = 0; - Yaz_Association p; - if (ZEND_NUM_ARGS() == 3) - { - if (zend_get_parameters_ex(3, &pval_id, &pval_type, &pval_query) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - } - else if (ZEND_NUM_ARGS() == 4) - { - if (zend_get_parameters_ex(4, &pval_id, &pval_type, &pval_query, - &pval_flags) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - if (Z_TYPE_PP(pval_flags) != IS_ARRAY) - { - php_error(E_WARNING, "yaz_scan: Bad flags parameter"); - RETURN_FALSE; - } - flags_ht = Z_ARRVAL_PP(pval_flags); - } - else - { - WRONG_PARAM_COUNT; - } - convert_to_string_ex (pval_type); - convert_to_string_ex (pval_query); - - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - Z_APDU *apdu; - p->action = 0; - apdu = encode_scan (p, Z_STRVAL_PP(pval_type), Z_STRVAL_PP(pval_query), - flags_ht); - if (apdu) - { - char *buf; - odr_reset(p->odr_scan); - p->scan_response = 0; - encode_APDU(p, apdu, p->odr_out); - buf = odr_getbuf(p->odr_out, &p->ill_len_out, 0); - xfree (p->ill_buf_out); - p->ill_buf_out = xmalloc (p->ill_len_out); - memcpy (p->ill_buf_out, buf, p->ill_len_out); - p->action = send_packet; - } - } - release_assoc (p); -} -/* }}} */ - -/* {{{ proto int yaz_scan_result(int id, array options) - Inspects Scan Result */ -PHP_FUNCTION(yaz_scan_result) -{ - pval **pval_id, **pval_opt = 0; - Yaz_Association p; - if (ZEND_NUM_ARGS() == 2) - { - if (zend_get_parameters_ex(2, &pval_id, &pval_opt) == FAILURE) - { - WRONG_PARAM_COUNT; - } - } - else if (ZEND_NUM_ARGS() == 1) - { - if (zend_get_parameters_ex(1, &pval_id) == FAILURE) - { - WRONG_PARAM_COUNT; - } - } - else - { - WRONG_PARAM_COUNT; - } - if (array_init(return_value) == FAILURE) - { - RETURN_FALSE; - } - if (pval_opt && array_init(*pval_opt) == FAILURE) - { - RETURN_FALSE; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p && p->scan_response) - { - int i; - Z_ScanResponse *res = p->scan_response; - if (pval_opt) - { - if (res->numberOfEntriesReturned) - add_assoc_long(*pval_opt, "number", - *res->numberOfEntriesReturned); - if (res->stepSize) - add_assoc_long(*pval_opt, "stepsize", *res->stepSize); - if (res->positionOfTerm) - add_assoc_long(*pval_opt, "position", *res->positionOfTerm); - if (res->scanStatus) - add_assoc_long(*pval_opt, "status", *res->scanStatus); - } - for (i = 0; res->entries && i < res->entries->num_entries; i++) - { - zval *my_zval; - ALLOC_ZVAL(my_zval); - array_init(my_zval); - INIT_PZVAL(my_zval); - - if (res->entries->entries[i]->which == Z_Entry_termInfo) - { - Z_TermInfo *t = res->entries->entries[i]->u.termInfo; - add_next_index_string(my_zval, "term", 1); - - if (t->term->which == Z_Term_general) - add_next_index_stringl (my_zval, t->term->u.general->buf, - t->term->u.general->len, 1); - else - add_next_index_string (my_zval, "?", 1); - add_next_index_long (my_zval, t->globalOccurrences ? - *t->globalOccurrences : 0); - } - else - add_next_index_string(my_zval, "unknown", 1); - - zend_hash_next_index_insert ( - return_value->value.ht, (void *) &my_zval, sizeof(zval *), - NULL); - } - - } - release_assoc (p); -} -/* }}} */ - -/* {{{ proto int yaz_ccl_conf(int id, array package) - Configure CCL package */ - -PHP_FUNCTION(yaz_ccl_conf) -{ - pval **pval_id, **pval_package; - Yaz_Association p; - if (ZEND_NUM_ARGS() != 2 || - zend_get_parameters_ex(2, &pval_id, &pval_package) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - if (Z_TYPE_PP(pval_package) != IS_ARRAY) - { - php_error(E_WARNING, "yaz_ccl_conf: Expected array parameter"); - RETURN_FALSE; - } - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - HashTable *ht = Z_ARRVAL_PP(pval_package); - HashPosition pos; - zval **ent; - char *key; - - ccl_qual_rm(&p->ccl_parser->bibset); - p->ccl_parser->bibset = ccl_qual_mk(); - for(zend_hash_internal_pointer_reset_ex(ht, &pos); - zend_hash_get_current_data_ex(ht, (void**) &ent, &pos) == SUCCESS; - zend_hash_move_forward_ex(ht, &pos)) - { - ulong idx; -#if PHP_API_VERSION > 20010101 - int type = zend_hash_get_current_key_ex(ht, &key, 0, - &idx, 0, &pos); -#else - int type = zend_hash_get_current_key_ex(ht, &key, 0, - &idx, &pos); -#endif - if (type != HASH_KEY_IS_STRING || Z_TYPE_PP(ent) != IS_STRING) - continue; - ccl_qual_fitem(p->ccl_parser->bibset, (*ent)->value.str.val, key); - } - } - release_assoc (p); -} -/* }}} */ - -/* {{{ proto int yaz_ccl_parse(int id, string query, array res) - Parse a CCL query */ - -PHP_FUNCTION(yaz_ccl_parse) -{ - pval **pval_id, **pval_query, **pval_res = 0; - Yaz_Association p; - if (ZEND_NUM_ARGS() != 3 || - zend_get_parameters_ex(3, &pval_id, &pval_query, &pval_res) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - - pval_destructor(*pval_res); - if (array_init(*pval_res) == FAILURE) - { - php_error(E_WARNING, "cannot initialize array"); - RETURN_FALSE; - } - convert_to_string_ex (pval_query); - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - const char *query_str = (*pval_query)->value.str.val; - struct ccl_rpn_node *rpn; - struct ccl_token *token_list = - ccl_parser_tokenize(p->ccl_parser, query_str); - rpn = ccl_parser_find(p->ccl_parser, token_list); - ccl_token_del(token_list); - - add_assoc_long(*pval_res, "errorcode", p->ccl_parser->error_code); - if (p->ccl_parser->error_code) - { - add_assoc_string(*pval_res, "errorstring", - (char*) ccl_err_msg(p->ccl_parser->error_code), - 1); - add_assoc_long(*pval_res, "errorpos", - p->ccl_parser->error_pos - query_str); - RETVAL_FALSE; - } - else - { - WRBUF wrbuf_pqf = wrbuf_alloc(); - ccl_pquery(wrbuf_pqf, rpn); - add_assoc_stringl(*pval_res, "rpn", wrbuf_buf(wrbuf_pqf), - wrbuf_len(wrbuf_pqf),1); - wrbuf_free(wrbuf_pqf, 1); - RETVAL_TRUE; - } - ccl_rpn_delete(rpn); - } - else - RETVAL_FALSE; - release_assoc (p); -} -/* }}} */ - -/* {{{ proto int yaz_ccl_parse(int id, string query, array res) - Parse a CCL query */ - -PHP_FUNCTION(yaz_database) -{ - pval **pval_id, **pval_database; - Yaz_Association p; - if (ZEND_NUM_ARGS() != 2 || - zend_get_parameters_ex(2, &pval_id, &pval_database) == - FAILURE) - { - WRONG_PARAM_COUNT; - } - convert_to_string_ex (pval_database); - get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p); - if (p) - { - xfree (p->local_databases); - p->local_databases = xstrdup ((*pval_database)->value.str.val); - RETVAL_TRUE; - } - else - RETVAL_FALSE; - release_assoc (p); -} -/* }}} */ - - -/* {{{ php_yaz_init_globals - */ -static void php_yaz_init_globals(zend_yaz_globals *yaz_globals) -{ - yaz_globals->assoc_seq = 0; -} -/* }}} */ - -void yaz_close_session(Yaz_Association *as) -{ - YAZSLS_FETCH(); - - if (*as && (*as)->order == YAZSG(assoc_seq)) - { - if ((*as)->persistent) - (*as)->in_use = 0; - else - { - yaz_association_destroy(*as); - *as = 0; - } - } -} - -static void yaz_close_link (zend_rsrc_list_entry *rsrc) -{ - Yaz_Association *as = (Yaz_Association *) rsrc->ptr; - yaz_close_session (as); -} - -PHP_MINIT_FUNCTION(yaz) -{ - int i; - nmem_init(); -#ifdef ZTS - yaz_mutex = tsrm_mutex_alloc(); -#endif - ZEND_INIT_MODULE_GLOBALS(yaz, php_yaz_init_globals, NULL); - - le_link = zend_register_list_destructors_ex (yaz_close_link, 0, - "YAZ link", module_number); - 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 (shared_associations) - { - for (i = 0; i<MAX_ASSOC; i++) - yaz_association_destroy (shared_associations[i]); - xfree (shared_associations); - shared_associations = 0; - nmem_exit(); - } -#ifdef ZTS - tsrm_mutex_free (yaz_mutex); -#endif - return SUCCESS; -} - -PHP_MINFO_FUNCTION(yaz) -{ - php_info_print_table_start(); - php_info_print_table_row(2, "YAZ Support", "enabled"); - php_info_print_table_row(2, "YAZ Version", YAZ_VERSION); - php_info_print_table_end(); -} - -PHP_RSHUTDOWN_FUNCTION(yaz) -{ - return SUCCESS; -} - -PHP_RINIT_FUNCTION(yaz) -{ - YAZSLS_FETCH(); -#ifdef ZTS - tsrm_mutex_lock (yaz_mutex); -#endif - YAZSG(assoc_seq) = order_associations++; -#ifdef ZTS - tsrm_mutex_unlock (yaz_mutex); -#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 -}; - -#ifdef COMPILE_DL_YAZ -ZEND_GET_MODULE(yaz) -#endif - -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 tw=78 fdm=marker - * vim<600: sw=4 ts=4 tw=78 - */ |