2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2011 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt. |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Adam Dickmeiss <adam@indexdata.dk> |
16 +----------------------------------------------------------------------+
28 #include "ext/standard/info.h"
31 #include <yaz/yaz-version.h>
34 #error YAZ version 3.0 or later must be used.
35 #elif YAZ_VERSIONL < 0x030000
36 #error YAZ version 3.0 or later must be used.
44 #include <yaz/proto.h>
45 #include <yaz/marcdisp.h>
46 #include <yaz/yaz-util.h>
47 #include <yaz/yaz-ccl.h>
48 #include <yaz/oid_db.h>
51 #ifndef ODR_INT_PRINTF
52 #define ODR_INT_PRINTF %d
57 typedef struct Yaz_AssociationInfo *Yaz_Association;
59 struct Yaz_AssociationInfo {
61 ZOOM_connection zoom_conn;
62 ZOOM_resultset zoom_set;
63 ZOOM_scanset zoom_scan;
64 ZOOM_package zoom_package;
73 static Yaz_Association yaz_association_mk()
75 Yaz_Association p = xmalloc(sizeof(*p));
77 p->zoom_conn = ZOOM_connection_create(0);
81 ZOOM_connection_option_set(p->zoom_conn, "implementationName", "PHP");
82 ZOOM_connection_option_set(p->zoom_conn, "async", "1");
87 p->bibset = ccl_qual_mk();
92 static void yaz_association_destroy(Yaz_Association p)
98 ZOOM_resultset_destroy(p->zoom_set);
99 ZOOM_scanset_destroy(p->zoom_scan);
100 ZOOM_package_destroy(p->zoom_package);
101 ZOOM_connection_destroy(p->zoom_conn);
102 xfree(p->sort_criteria);
103 ccl_qual_rm(&p->bibset);
107 static MUTEX_T yaz_mutex;
110 ZEND_DECLARE_MODULE_GLOBALS(yaz);
112 static Yaz_Association *shared_associations;
113 static int order_associations;
117 #ifdef COMPILE_DL_YAZ
121 #ifdef ZEND_BEGIN_ARG_INFO
122 ZEND_BEGIN_ARG_INFO(first_argument_force_ref, 0)
123 ZEND_ARG_PASS_INFO(1)
126 ZEND_BEGIN_ARG_INFO(second_argument_force_ref, 0)
127 ZEND_ARG_PASS_INFO(0)
128 ZEND_ARG_PASS_INFO(1)
131 ZEND_BEGIN_ARG_INFO(third_argument_force_ref, 0)
132 ZEND_ARG_PASS_INFO(0)
133 ZEND_ARG_PASS_INFO(0)
134 ZEND_ARG_PASS_INFO(1)
137 static unsigned char first_argument_force_ref[] = {
139 static unsigned char second_argument_force_ref[] = {
140 2, BYREF_NONE, BYREF_FORCE };
141 static unsigned char third_argument_force_ref[] = {
142 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
146 zend_function_entry yaz_functions [] = {
147 PHP_FE(yaz_connect, NULL)
148 PHP_FE(yaz_close, NULL)
149 PHP_FE(yaz_search, NULL)
150 PHP_FE(yaz_wait, first_argument_force_ref)
151 PHP_FE(yaz_errno, NULL)
152 PHP_FE(yaz_error, NULL)
153 PHP_FE(yaz_addinfo, NULL)
154 PHP_FE(yaz_hits, second_argument_force_ref)
155 PHP_FE(yaz_record, NULL)
156 PHP_FE(yaz_syntax, NULL)
157 PHP_FE(yaz_element, NULL)
158 PHP_FE(yaz_range, NULL)
159 PHP_FE(yaz_itemorder, NULL)
160 PHP_FE(yaz_es_result, NULL)
161 PHP_FE(yaz_scan, NULL)
162 PHP_FE(yaz_scan_result, second_argument_force_ref)
163 PHP_FE(yaz_present, NULL)
164 PHP_FE(yaz_ccl_conf, NULL)
165 PHP_FE(yaz_ccl_parse, third_argument_force_ref)
166 PHP_FE(yaz_database, NULL)
167 PHP_FE(yaz_sort, NULL)
168 PHP_FE(yaz_schema, NULL)
169 PHP_FE(yaz_set_option, NULL)
170 PHP_FE(yaz_get_option, NULL)
175 static void get_assoc(INTERNAL_FUNCTION_PARAMETERS, zval *id, Yaz_Association *assocp)
177 Yaz_Association *as = 0;
181 tsrm_mutex_lock(yaz_mutex);
184 ZEND_FETCH_RESOURCE(as, Yaz_Association *, &id, -1, "YAZ link", le_link);
186 if (as && *as && (*as)->order == YAZSG(assoc_seq) && (*as)->in_use) {
190 tsrm_mutex_unlock(yaz_mutex);
192 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid YAZ handle");
196 static void release_assoc(Yaz_Association assoc)
200 tsrm_mutex_unlock(yaz_mutex);
205 static const char *array_lookup_string(HashTable *ht, const char *idx)
209 if (ht && zend_hash_find(ht, (char *) idx, strlen(idx) + 1, (void **) &pvalue) == SUCCESS) {
210 SEPARATE_ZVAL(pvalue);
211 convert_to_string(*pvalue);
212 return (*pvalue)->value.str.val;
217 static long *array_lookup_long(HashTable *ht, const char *idx)
221 if (ht && zend_hash_find(ht, (char *) idx, strlen(idx) + 1, (void **) &pvalue) == SUCCESS) {
222 SEPARATE_ZVAL(pvalue);
223 convert_to_long(*pvalue);
224 return &(*pvalue)->value.lval;
229 static long *array_lookup_bool(HashTable *ht, const char *idx)
233 if (ht && zend_hash_find(ht, (char *) idx, strlen(idx) + 1, (void **) &pvalue) == SUCCESS) {
234 SEPARATE_ZVAL(pvalue);
235 convert_to_boolean(*pvalue);
236 return &(*pvalue)->value.lval;
241 static const char *option_get(Yaz_Association as, const char *name)
246 return ZOOM_connection_option_get(as->zoom_conn, name);
249 static int option_get_int(Yaz_Association as, const char *name, int def)
253 v = ZOOM_connection_option_get(as->zoom_conn, name);
262 static void option_set(Yaz_Association as, const char *name, const char *value)
265 ZOOM_connection_option_set(as->zoom_conn, name, value);
269 static void option_set_int(Yaz_Association as, const char *name, int v)
275 ZOOM_connection_option_set(as->zoom_conn, name, s);
279 static int strcmp_null(const char *s1, const char *s2)
281 if (s1 == 0 && s2 == 0) {
284 if (s1 == 0 || s2 == 0) {
287 return strcmp(s1, s2);
290 /* {{{ proto resource yaz_connect(string zurl [, array options])
291 Create target with given zurl. Returns positive id if successful. */
292 PHP_FUNCTION(yaz_connect)
298 const char *sru_str = 0, *sru_version_str = 0;
299 const char *user_str = 0, *group_str = 0, *pass_str = 0;
300 const char *cookie_str = 0, *proxy_str = 0;
301 const char *charset_str = 0;
302 const char *client_IP = 0;
303 const char *otherInfo[3];
304 const char *maximumRecordSize = 0;
305 const char *preferredMessageSize = 0;
309 int max_links = YAZSG(max_links);
311 otherInfo[0] = otherInfo[1] = otherInfo[2] = 0;
313 if (ZEND_NUM_ARGS() == 1) {
314 if (zend_parse_parameters(1 TSRMLS_CC, "s", &zurl_str, &zurl_len)
318 } else if (ZEND_NUM_ARGS() == 2) {
320 if (zend_parse_parameters(2 TSRMLS_CC, "sz", &zurl_str, &zurl_len,
325 if (Z_TYPE_PP(&user) == IS_ARRAY) {
326 long *persistent_val;
328 HashTable *ht = Z_ARRVAL_PP(&user);
330 sru_str = array_lookup_string(ht, "sru");
331 sru_version_str = array_lookup_string(ht, "sru_version");
332 user_str = array_lookup_string(ht, "user");
333 group_str = array_lookup_string(ht, "group");
334 pass_str = array_lookup_string(ht, "password");
335 cookie_str = array_lookup_string(ht, "cookie");
336 proxy_str = array_lookup_string(ht, "proxy");
337 charset_str = array_lookup_string(ht, "charset");
338 persistent_val = array_lookup_bool(ht, "persistent");
339 if (persistent_val) {
340 persistent = *persistent_val;
342 piggyback_val = array_lookup_bool(ht, "piggyback");
344 piggyback = *piggyback_val;
347 array_lookup_string(ht, "maximumRecordSize");
348 preferredMessageSize =
349 array_lookup_string(ht, "preferredMessageSize");
350 otherInfo[0] = array_lookup_string(ht, "otherInfo0");
351 otherInfo[1] = array_lookup_string(ht, "otherInfo1");
352 otherInfo[2] = array_lookup_string(ht, "otherInfo2");
353 } else if (Z_TYPE_PP(&user) == IS_STRING) {
354 convert_to_string_ex(&user);
355 if (*user->value.str.val)
356 user_str = user->value.str.val;
361 for (cp = zurl_str; *cp && strchr("\t\n ", *cp); cp++);
363 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty zurl");
366 /* see if we have it already ... */
368 tsrm_mutex_lock(yaz_mutex);
370 for (i = 0; i < max_links; i++) {
371 as = shared_associations[i];
372 if (persistent && as && !as->in_use &&
373 !strcmp_null(option_get(as, "host"), zurl_str) &&
374 !strcmp_null(option_get(as, "proxy"), proxy_str) &&
375 !strcmp_null(option_get(as, "sru"), sru_str) &&
376 !strcmp_null(option_get(as, "sru_version"), sru_version_str) &&
377 !strcmp_null(option_get(as, "user"), user_str) &&
378 !strcmp_null(option_get(as, "group"), group_str) &&
379 !strcmp_null(option_get(as, "pass"), pass_str) &&
380 !strcmp_null(option_get(as, "cookie"), cookie_str) &&
381 !strcmp_null(option_get(as, "charset"), charset_str))
384 if (i == max_links) {
385 /* we didn't have it (or already in use) */
387 int min_order = 2000000000;
389 /* find completely free slot or the oldest one */
390 for (i = 0; i < max_links && shared_associations[i]; i++) {
391 as = shared_associations[i];
392 if (persistent && !as->in_use && as->order < min_order) {
393 min_order = as->order;
398 if (i == max_links) {
403 tsrm_mutex_unlock(yaz_mutex);
405 sprintf(msg, "No YAZ handles available. max_links=%d",
407 php_error_docref(NULL TSRMLS_CC, E_WARNING,
408 "No YAZ handles available. max_links=%ld",
410 RETURN_LONG(0); /* no free slot */
411 } else { /* "best" free slot */
412 yaz_association_destroy(shared_associations[i]);
415 shared_associations[i] = as = yaz_association_mk();
417 option_set(as, "proxy", proxy_str);
418 option_set(as, "sru", sru_str);
419 option_set(as, "sru_version", sru_version_str);
420 option_set(as, "user", user_str);
421 option_set(as, "group", group_str);
422 option_set(as, "pass", pass_str);
423 option_set(as, "cookie", cookie_str);
424 option_set(as, "charset", charset_str);
426 if (maximumRecordSize)
427 option_set(as, "maximumRecordSize", maximumRecordSize);
428 if (preferredMessageSize)
429 option_set(as, "preferredMessageSize", preferredMessageSize);
430 option_set(as, "otherInfo0", otherInfo[0]);
431 option_set(as, "otherInfo1", otherInfo[1]);
432 option_set(as, "otherInfo2", otherInfo[2]);
433 option_set(as, "clientIP", client_IP);
434 option_set(as, "piggyback", piggyback ? "1" : "0");
435 option_set_int(as, "start", 0);
436 option_set_int(as, "count", 0);
437 ZOOM_connection_connect(as->zoom_conn, zurl_str, 0);
439 as->persistent = persistent;
440 as->order = YAZSG(assoc_seq);
441 as->time_stamp = time(0);
445 ZOOM_resultset_destroy(as->zoom_set);
449 tsrm_mutex_unlock(yaz_mutex);
452 ZEND_REGISTER_RESOURCE(return_value, &shared_associations[i], le_link);
453 as->zval_resource = Z_LVAL_P(return_value);
457 /* {{{ proto bool yaz_close(resource id)
458 Destory and close target */
459 PHP_FUNCTION(yaz_close)
464 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
468 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
473 zend_list_delete(id->value.lval);
479 /* {{{ proto bool yaz_search(resource id, string type, string query)
480 Specify query of type for search - returns true if successful */
481 PHP_FUNCTION(yaz_search)
483 char *query_str, *type_str;
484 int query_len, type_len;
488 if (ZEND_NUM_ARGS() != 3 ||
489 zend_parse_parameters(3 TSRMLS_CC, "zss", &id,
490 &type_str, &type_len,
491 &query_str, &query_len) == FAILURE) {
494 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
499 ZOOM_resultset_destroy(p->zoom_set);
504 if (!strcmp(type_str, "rpn")) {
505 ZOOM_query q = ZOOM_query_create();
506 if (ZOOM_query_prefix(q, query_str) == 0)
508 if (p->sort_criteria) {
509 ZOOM_query_sortby(q, p->sort_criteria);
511 xfree(p->sort_criteria);
512 p->sort_criteria = 0;
513 p->zoom_set = ZOOM_connection_search(p->zoom_conn, q);
516 ZOOM_query_destroy(q);
518 else if (!strcmp(type_str, "cql")) {
519 ZOOM_query q = ZOOM_query_create();
520 if (ZOOM_query_cql(q, query_str) == 0)
522 if (p->sort_criteria) {
523 ZOOM_query_sortby(q, p->sort_criteria);
525 xfree(p->sort_criteria);
526 p->sort_criteria = 0;
527 p->zoom_set = ZOOM_connection_search(p->zoom_conn, q);
530 ZOOM_query_destroy(q);
534 php_error_docref(NULL TSRMLS_CC, E_WARNING,
535 "Invalid query type %s", type_str);
541 /* {{{ proto bool yaz_present(resource id)
543 PHP_FUNCTION(yaz_present)
548 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
552 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
558 size_t start = option_get_int(p, "start", 0);
559 size_t count = option_get_int(p, "count", 0);
561 ZOOM_resultset_records(p->zoom_set, 0 /* recs */, start, count);
569 /* {{{ proto bool yaz_wait([array options])
571 PHP_FUNCTION(yaz_wait)
573 zval *pval_options = 0;
576 ZOOM_connection conn_ar[MAX_ASSOC];
577 Yaz_Association conn_as[MAX_ASSOC];
580 if (ZEND_NUM_ARGS() == 1) {
582 long *event_bool = 0;
583 HashTable *options_ht = 0;
584 if (zend_parse_parameters(1 TSRMLS_CC, "a", &pval_options) ==
588 options_ht = Z_ARRVAL_PP(&pval_options);
589 val = array_lookup_long(options_ht, "timeout");
593 event_bool = array_lookup_bool(options_ht, "event");
594 if (event_bool && *event_bool)
598 tsrm_mutex_lock(yaz_mutex);
600 for (i = 0; i<YAZSG(max_links); i++) {
601 Yaz_Association p = shared_associations[i];
602 if (p && p->order == YAZSG(assoc_seq)) {
605 sprintf(str, "%d", timeout);
606 ZOOM_connection_option_set(p->zoom_conn, "timeout", str);
608 conn_ar[no++] = p->zoom_conn;
612 tsrm_mutex_unlock(yaz_mutex);
615 long ev = ZOOM_event(no, conn_ar);
619 Yaz_Association p = conn_as[ev-1];
620 int event_code = ZOOM_connection_last_event(p->zoom_conn);
623 add_assoc_long(pval_options, "connid", ev);
624 add_assoc_long(pval_options, "eventcode", event_code);
627 zend_list_addref(p->zval_resource);
628 Z_LVAL_P(return_value) = p->zval_resource;
629 Z_TYPE_P(return_value) = IS_RESOURCE;
635 while (ZOOM_event(no, conn_ar))
642 /* {{{ proto int yaz_errno(resource id)
643 Return last error number (>0 for bib-1 diagnostic, <0 for other error, 0 for no error */
644 PHP_FUNCTION(yaz_errno)
649 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
653 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
657 RETVAL_LONG(ZOOM_connection_errcode(p->zoom_conn));
662 /* {{{ proto string yaz_error(resource id)
663 Return last error message */
664 PHP_FUNCTION(yaz_error)
669 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
673 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
675 int code = ZOOM_connection_errcode(p->zoom_conn);
676 const char *msg = ZOOM_connection_errmsg(p->zoom_conn);
681 return_value->value.str.len = strlen(msg);
682 return_value->value.str.val = estrndup(msg, return_value->value.str.len);
683 return_value->type = IS_STRING;
689 /* {{{ proto string yaz_addinfo(resource id)
690 Return additional info for last error (empty string if none) */
691 PHP_FUNCTION(yaz_addinfo)
696 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
700 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
702 const char *addinfo = ZOOM_connection_addinfo(p->zoom_conn);
704 return_value->value.str.len = strlen(addinfo);
705 return_value->value.str.val = estrndup(addinfo, return_value->value.str.len);
706 return_value->type = IS_STRING;
712 /* {{{ proto int yaz_hits(resource id [, array searchresult])
713 Return number of hits (result count) for last search */
714 PHP_FUNCTION(yaz_hits)
716 zval *id, *searchresult = 0;
719 if (ZEND_NUM_ARGS() == 1) {
720 if (zend_parse_parameters(1 TSRMLS_CC, "z", &id) == FAILURE) {
723 } else if (ZEND_NUM_ARGS() == 2) {
724 if (zend_parse_parameters(2 TSRMLS_CC, "za", &id, &searchresult)
732 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
733 if (p && p->zoom_set) {
734 RETVAL_LONG(ZOOM_resultset_size(p->zoom_set));
738 ZOOM_resultset_option_get(p->zoom_set, "resultSetStatus");
740 add_assoc_string(searchresult, "resultSetStatus",
746 ZOOM_resultset_option_get(p->zoom_set, "searchresult.size");
749 if (sz_str && *sz_str)
751 for (i = 0; i<sz; i++)
754 const char *opt_value;
757 MAKE_STD_ZVAL(zval_element);
758 array_init(zval_element);
759 add_next_index_zval(searchresult, zval_element);
761 sprintf(opt_name, "searchresult.%d.id", i);
762 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
764 add_assoc_string(zval_element, "id",
765 (char *) opt_value, 1);
767 sprintf(opt_name, "searchresult.%d.count", i);
768 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
770 add_assoc_long(zval_element, "count", atoi(opt_value));
772 sprintf(opt_name, "searchresult.%d.subquery.term", i);
773 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
775 add_assoc_string(zval_element, "subquery.term",
776 (char *) opt_value, 1);
778 sprintf(opt_name, "searchresult.%d.interpretation.term", i);
779 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
781 add_assoc_string(zval_element, "interpretation.term",
782 (char *) opt_value, 1);
784 sprintf(opt_name, "searchresult.%d.recommendation.term", i);
785 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
787 add_assoc_string(zval_element, "recommendation.term",
788 (char *) opt_value, 1);
799 static Z_GenericRecord *marc_to_grs1(const char *buf, ODR o)
803 int indicator_length;
804 int identifier_length;
806 int length_data_entry;
808 int length_implementation;
809 int max_elements = 256;
810 Z_GenericRecord *r = odr_malloc(o, sizeof(*r));
811 r->elements = odr_malloc(o, sizeof(*r->elements) * max_elements);
814 record_length = atoi_n(buf, 5);
815 if (record_length < 25) {
818 indicator_length = atoi_n(buf + 10, 1);
819 identifier_length = atoi_n(buf + 11, 1);
820 base_address = atoi_n(buf + 12, 5);
822 length_data_entry = atoi_n(buf + 20, 1);
823 length_starting = atoi_n(buf + 21, 1);
824 length_implementation = atoi_n(buf + 22, 1);
826 for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) {
827 entry_p += 3 + length_data_entry + length_starting;
828 if (entry_p >= record_length) {
834 Z_TaggedElement *tag;
835 tag = r->elements[r->num_elements++] = odr_malloc(o, sizeof(*tag));
836 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
838 tag->tagOccurrence = 0;
840 tag->appliedVariant = 0;
841 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
842 tag->tagValue->which = Z_StringOrNumeric_string;
843 tag->tagValue->u.string = odr_strdup(o, "leader");
845 tag->content = odr_malloc(o, sizeof(*tag->content));
846 tag->content->which = Z_ElementData_string;
847 tag->content->u.string = odr_strdupn(o, buf, 24);
849 base_address = entry_p + 1;
850 for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) {
851 Z_TaggedElement *tag;
857 int identifier_flag = 1;
859 memcpy(tag_str, buf+entry_p, 3);
863 if ((r->num_elements + 1) >= max_elements) {
864 Z_TaggedElement **tmp = r->elements;
866 /* double array space, throw away old buffer (nibble memory) */
867 r->elements = odr_malloc(o, sizeof(*r->elements) * (max_elements *= 2));
868 memcpy(r->elements, tmp, r->num_elements * sizeof(*tmp));
870 tag = r->elements[r->num_elements++] = odr_malloc(o, sizeof(*tag));
871 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
873 tag->tagOccurrence = 0;
875 tag->appliedVariant = 0;
876 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
877 tag->tagValue->which = Z_StringOrNumeric_string;
878 tag->tagValue->u.string = odr_strdup(o, tag_str);
880 tag->content = odr_malloc(o, sizeof(*tag->content));
881 tag->content->which = Z_ElementData_subtree;
883 tag->content->u.subtree = odr_malloc(o, sizeof(*tag->content->u.subtree));
884 tag->content->u.subtree->elements = odr_malloc(o, sizeof(*r->elements));
885 tag->content->u.subtree->num_elements = 1;
887 tag = tag->content->u.subtree->elements[0] = odr_malloc(o, sizeof(**tag->content->u.subtree->elements));
889 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
891 tag->tagOccurrence = 0;
893 tag->appliedVariant = 0;
894 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
895 tag->tagValue->which = Z_StringOrNumeric_string;
896 tag->content = odr_malloc(o, sizeof(*tag->content));
898 data_length = atoi_n(buf + entry_p, length_data_entry);
899 entry_p += length_data_entry;
900 data_offset = atoi_n(buf + entry_p, length_starting);
901 entry_p += length_starting;
902 i = data_offset + base_address;
903 end_offset = i + data_length - 1;
905 if (indicator_length > 0 && indicator_length < 5) {
906 if (buf[i + indicator_length] != ISO2709_IDFS) {
909 } else if (!memcmp(tag_str, "00", 2)) {
913 if (identifier_flag && indicator_length) {
915 tag->tagValue->u.string = odr_malloc(o, indicator_length + 1);
916 memcpy(tag->tagValue->u.string, buf + i, indicator_length);
917 tag->tagValue->u.string[indicator_length] = '\0';
918 i += indicator_length;
920 tag->content->which = Z_ElementData_subtree;
922 tag->content->u.subtree = odr_malloc(o, sizeof(*tag->content->u.subtree));
923 tag->content->u.subtree->elements = odr_malloc(o, 256 * sizeof(*r->elements));
924 tag->content->u.subtree->num_elements = 0;
926 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset) {
929 Z_TaggedElement *parent_tag = tag;
930 Z_TaggedElement *tag = odr_malloc(o, sizeof(*tag));
932 if (parent_tag->content->u.subtree->num_elements < 256) {
933 parent_tag->content->u.subtree->elements[
934 parent_tag->content->u.subtree->num_elements++] = tag;
937 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
939 tag->tagOccurrence = 0;
941 tag->appliedVariant = 0;
942 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
943 tag->tagValue->which = Z_StringOrNumeric_string;
946 tag->tagValue->u.string = odr_malloc(o, identifier_length);
947 memcpy(tag->tagValue->u.string, buf + i + 1, identifier_length - 1);
948 tag->tagValue->u.string[identifier_length - 1] = '\0';
949 i += identifier_length;
952 tag->content = odr_malloc(o, sizeof(*tag->content));
953 tag->content->which = Z_ElementData_string;
956 while ( buf[i] != ISO2709_RS &&
957 buf[i] != ISO2709_IDFS &&
958 buf[i] != ISO2709_FS && i < end_offset) {
962 tag->content->u.string = odr_malloc(o, i - i0 + 1);
963 memcpy(tag->content->u.string, buf + i0, i - i0);
964 tag->content->u.string[i - i0] = '\0';
969 tag->tagValue->u.string = "@";
970 tag->content->which = Z_ElementData_string;
972 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset) {
975 tag->content->u.string = odr_malloc(o, i - i0 +1);
976 memcpy(tag->content->u.string, buf + i0, i - i0);
977 tag->content->u.string[i-i0] = '\0';
990 static struct cvt_handle *cvt_open(const char *to, const char *from)
992 ODR o = odr_createmem(ODR_ENCODE);
994 struct cvt_handle *cvt = odr_malloc(o, sizeof(*cvt));
997 cvt->buf = odr_malloc(o, cvt->size);
1000 cvt->cd = yaz_iconv_open(to, from);
1004 static void cvt_close(struct cvt_handle *cvt)
1007 yaz_iconv_close(cvt->cd);
1008 odr_destroy(cvt->odr);
1011 static const char *cvt_string(const char *input, struct cvt_handle *cvt)
1016 size_t inbytesleft = strlen(input);
1017 const char *inp = input;
1018 size_t outbytesleft = cvt->size - 1;
1019 char *outp = cvt->buf;
1020 size_t r = yaz_iconv(cvt->cd, (char**) &inp, &inbytesleft,
1021 &outp, &outbytesleft);
1022 if (r == (size_t) (-1)) {
1023 int e = yaz_iconv_error(cvt->cd);
1024 if (e != YAZ_ICONV_E2BIG || cvt->size > 200000)
1029 cvt->size = cvt->size * 2 + 30;
1030 cvt->buf = (char*) odr_malloc(cvt->odr, cvt->size);
1032 cvt->buf[outp - cvt->buf] = '\0';
1039 static void retval_array3_grs1(zval *return_value, Z_GenericRecord *p,
1040 struct cvt_handle *cvt)
1046 struct tag_list *next;
1048 NMEM nmem = nmem_create();
1050 array_init(return_value);
1051 for (i = 0; i<p->num_elements; i++)
1053 struct tag_list *tl;
1056 Z_TaggedElement *e = p->elements[i];
1057 char tagstr[32], *tag = 0;
1059 if (e->tagValue->which == Z_StringOrNumeric_numeric)
1061 sprintf(tagstr, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1064 else if (e->tagValue->which == Z_StringOrNumeric_string)
1065 tag = e->tagValue->u.string, zval_element;
1070 for (tl = all_tags; tl; tl = tl->next)
1071 if (!strcmp(tl->tag, tag))
1074 zval_list = tl->zval_list;
1077 MAKE_STD_ZVAL(zval_list);
1078 array_init(zval_list);
1079 add_assoc_zval(return_value, tag, zval_list);
1081 tl = nmem_malloc(nmem, sizeof(*tl));
1082 tl->tag = nmem_strdup(nmem, tag);
1083 tl->zval_list = zval_list;
1084 tl->next = all_tags;
1087 MAKE_STD_ZVAL(zval_element);
1088 array_init(zval_element);
1089 add_next_index_zval(zval_list, zval_element);
1090 if (e->content->which == Z_ElementData_subtree)
1092 /* we have a subtree. Move to first child */
1093 Z_GenericRecord *sub = e->content->u.subtree;
1094 if (sub->num_elements >= 1)
1095 e = sub->elements[0];
1101 const char *tag = 0;
1102 if (e->tagValue->which == Z_StringOrNumeric_numeric)
1104 sprintf(tagstr, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1107 else if (e->tagValue->which == Z_StringOrNumeric_string)
1108 tag = e->tagValue->u.string;
1109 if (tag && e->content->which == Z_ElementData_subtree)
1112 Z_GenericRecord *sub = e->content->u.subtree;
1114 for (i = 0; tag[i]; i++)
1119 sprintf(ind_idx, "ind%d", i+1);
1120 ind_val[0] = tag[i];
1123 add_assoc_string(zval_element, ind_idx, ind_val, 1);
1125 for (i = 0; i<sub->num_elements; i++)
1127 Z_TaggedElement *e = sub->elements[i];
1128 const char *tag = 0;
1129 if (e->tagValue->which == Z_StringOrNumeric_numeric)
1131 sprintf(tagstr, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1134 else if (e->tagValue->which == Z_StringOrNumeric_string)
1135 tag = e->tagValue->u.string, zval_element;
1137 if (tag && e->content->which == Z_ElementData_string)
1139 const char *v = cvt_string(e->content->u.string, cvt);
1140 add_assoc_string(zval_element, (char*) tag, (char*) v,
1145 else if (tag && e->content->which == Z_ElementData_string)
1147 /* Leader or control field */
1148 const char *v = cvt_string(e->content->u.string, cvt);
1149 ZVAL_STRING(zval_element, (char*) v, 1);
1156 static void retval_array2_grs1(zval *return_value, Z_GenericRecord *p,
1157 struct cvt_handle *cvt)
1161 array_init(return_value);
1163 for (i = 0; i<p->num_elements; i++)
1167 Z_TaggedElement *e = p->elements[i];
1169 MAKE_STD_ZVAL(zval_element);
1170 array_init(zval_element);
1173 add_assoc_long(zval_element, "tagType", (long) *e->tagType);
1175 if (e->tagValue->which == Z_StringOrNumeric_string)
1176 add_assoc_string(zval_element, "tag", e->tagValue->u.string, 1);
1177 else if (e->tagValue->which == Z_StringOrNumeric_numeric)
1178 add_assoc_long(zval_element, "tag", (long) *e->tagValue->u.numeric);
1180 switch (e->content->which) {
1181 case Z_ElementData_string:
1184 const char *v = cvt_string(e->content->u.string, cvt);
1185 add_assoc_string(zval_element, "content", (char*) v, 1);
1188 case Z_ElementData_numeric:
1189 add_assoc_long(zval_element, "content", (long) *e->content->u.numeric);
1191 case Z_ElementData_trueOrFalse:
1192 add_assoc_bool(zval_element, "content",*e->content->u.trueOrFalse);
1194 case Z_ElementData_subtree:
1195 MAKE_STD_ZVAL(zval_sub);
1196 retval_array2_grs1(zval_sub, e->content->u.subtree, cvt);
1197 add_assoc_zval(zval_element, "content", zval_sub);
1199 add_next_index_zval(return_value, zval_element);
1203 static void retval_array1_grs1(zval *return_value, Z_GenericRecord *p,
1204 struct cvt_handle *cvt)
1206 Z_GenericRecord *grs[20];
1210 array_init(return_value);
1214 while (level >= 0) {
1216 Z_TaggedElement *e = 0;
1217 Z_GenericRecord *p = grs[level];
1222 if (eno[level] >= p->num_elements) {
1229 for (i = 0; i <= level; i++) {
1231 e = grs[i]->elements[eno[i]];
1234 tag_type = (long) *e->tagType;
1236 taglen = strlen(tag);
1237 sprintf(tag + taglen, "(%ld,", tag_type);
1238 taglen = strlen(tag);
1240 if (e->tagValue->which == Z_StringOrNumeric_string) {
1241 int len = strlen(e->tagValue->u.string);
1243 memcpy(tag + taglen, e->tagValue->u.string, len);
1244 tag[taglen+len] = '\0';
1245 } else if (e->tagValue->which == Z_StringOrNumeric_numeric) {
1246 sprintf(tag + taglen, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1248 taglen = strlen(tag);
1249 strcpy(tag + taglen, ")");
1252 ALLOC_ZVAL(my_zval);
1253 array_init(my_zval);
1254 INIT_PZVAL(my_zval);
1256 add_next_index_string(my_zval, tag, 1);
1258 switch (e->content->which) {
1259 case Z_ElementData_string:
1262 const char *v = cvt_string(e->content->u.string, cvt);
1263 add_next_index_string(my_zval, (char*) v, 1);
1266 case Z_ElementData_numeric:
1267 add_next_index_long(my_zval, (long) *e->content->u.numeric);
1269 case Z_ElementData_trueOrFalse:
1270 add_next_index_long(my_zval, *e->content->u.trueOrFalse);
1272 case Z_ElementData_subtree:
1275 grs[level] = e->content->u.subtree;
1279 zend_hash_next_index_insert(return_value->value.ht, (void *) &my_zval, sizeof(zval *), NULL);
1284 static void ext_grs1(zval *return_value, char type_args[][60],
1286 void (*array_func)(zval *, Z_GenericRecord *,
1287 struct cvt_handle *))
1289 Z_External *ext = (Z_External *) ZOOM_record_get(r, "ext", 0);
1290 if (ext && ext->which == Z_External_OPAC)
1291 ext = ext->u.opac->bibliographicRecord;
1293 struct cvt_handle *cvt = 0;
1294 if (type_args[2][0])
1295 cvt = cvt_open(type_args[3], type_args[2]);
1297 cvt = cvt_open(0, 0);
1299 if (ext->which == Z_External_grs1) {
1300 retval_array1_grs1(return_value, ext->u.grs1, cvt);
1301 } else if (ext->which == Z_External_octet) {
1302 Z_GenericRecord *rec = 0;
1303 if (yaz_oid_is_iso2709(ext->direct_reference))
1305 char *buf = (char *) (ext->u.octet_aligned->buf);
1306 rec = marc_to_grs1(buf, cvt->odr);
1309 (*array_func)(return_value, rec, cvt);
1317 /* {{{ proto string yaz_record(resource id, int pos, string type)
1318 Return record information at given result set position */
1319 PHP_FUNCTION(yaz_record)
1327 if (ZEND_NUM_ARGS() != 3) {
1331 if (zend_parse_parameters(3 TSRMLS_CC, "zls", &pval_id, &pos,
1332 &type, &type_len) == FAILURE) {
1336 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1338 if (p && p->zoom_set) {
1340 char type_args[4][60]; /* 0; 1=2,3 (1 is assumed charset) */
1341 type_args[0][0] = 0;
1342 type_args[1][0] = 0;
1343 type_args[2][0] = 0;
1344 type_args[3][0] = 0;
1345 sscanf(type, "%59[^;];%59[^=]=%59[^,],%59[^,]", type_args[0],
1346 type_args[1], type_args[2], type_args[3]);
1347 r = ZOOM_resultset_record(p->zoom_set, pos-1);
1348 if (!strcmp(type_args[0], "string")) {
1352 if (!strcmp(type_args[0], "array") ||
1353 !strcmp(type_args[0], "array1"))
1355 ext_grs1(return_value, type_args, r, retval_array1_grs1);
1356 } else if (!strcmp(type_args[0], "array2")) {
1357 ext_grs1(return_value, type_args, r, retval_array2_grs1);
1358 } else if (!strcmp(type_args[0], "array3")) {
1359 ext_grs1(return_value, type_args, r, retval_array3_grs1);
1362 const char *info = ZOOM_record_get(r, type, &rlen);
1364 return_value->value.str.len = (rlen > 0) ? rlen : 0;
1365 return_value->value.str.val =
1366 estrndup(info, return_value->value.str.len);
1367 return_value->type = IS_STRING;
1371 php_error_docref(NULL TSRMLS_CC, E_WARNING,
1372 "Bad yaz_record type %s - or unable "
1373 "to return record with type given", type);
1382 /* {{{ proto void yaz_syntax(resource id, string syntax)
1383 Set record syntax for retrieval */
1384 PHP_FUNCTION(yaz_syntax)
1391 if (ZEND_NUM_ARGS() != 2 ||
1392 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1393 &syntax, &syntax_len) == FAILURE) {
1397 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1398 option_set(p, "preferredRecordSyntax", syntax);
1403 /* {{{ proto void yaz_element(resource id, string elementsetname)
1404 Set Element-Set-Name for retrieval */
1405 PHP_FUNCTION(yaz_element)
1408 const char *element;
1412 if (ZEND_NUM_ARGS() != 2 ||
1413 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1414 &element, &element_len) == FAILURE) {
1417 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1419 option_set(p, "elementSetName", element);
1424 /* {{{ proto void yaz_schema(resource id, string schema)
1425 Set Schema for retrieval */
1426 PHP_FUNCTION(yaz_schema)
1433 if (ZEND_NUM_ARGS() != 2 ||
1434 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1435 &schema, &schema_len) == FAILURE) {
1439 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1440 option_set(p, "schema", schema);
1445 /* {{{ proto void yaz_set_option(resource id, mixed options)
1446 Set Option(s) for connection */
1447 PHP_FUNCTION(yaz_set_option)
1451 if (ZEND_NUM_ARGS() == 2) {
1452 zval *pval_ar, *pval_id;
1453 if (zend_parse_parameters(2 TSRMLS_CC, "za",
1454 &pval_id, &pval_ar) == FAILURE) {
1457 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1463 ht = Z_ARRVAL_PP(&pval_ar);
1464 for(zend_hash_internal_pointer_reset_ex(ht, &pos);
1465 zend_hash_get_current_data_ex(ht, (void**) &ent, &pos) == SUCCESS;
1466 zend_hash_move_forward_ex(ht, &pos)
1470 #if PHP_API_VERSION > 20010101
1471 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, 0, &pos);
1473 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, &pos);
1475 if (type != HASH_KEY_IS_STRING || Z_TYPE_PP(ent) != IS_STRING) {
1478 option_set(p, key, (*ent)->value.str.val);
1482 } else if (ZEND_NUM_ARGS() == 3) {
1485 int name_len, value_len;
1486 if (zend_parse_parameters(3 TSRMLS_CC, "zss",
1487 &pval_id, &name, &name_len,
1488 &value, &value_len) == FAILURE) {
1491 get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1492 option_set(p, name, value);
1500 /* {{{ proto string yaz_get_option(resource id, string name)
1501 Set Option(s) for connection */
1502 PHP_FUNCTION(yaz_get_option)
1509 if (ZEND_NUM_ARGS() != 2 ||
1510 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id, &name, &name_len)
1514 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1516 const char *name_str, *v;
1517 v = option_get(p, name);
1521 return_value->value.str.len = strlen(v);
1522 return_value->value.str.val = estrndup(v, return_value->value.str.len);
1523 return_value->type = IS_STRING;
1531 /* {{{ proto void yaz_range(resource id, int start, int number)
1532 Set result set start point and number of records to request */
1533 PHP_FUNCTION(yaz_range)
1539 if (ZEND_NUM_ARGS() != 3 ||
1540 zend_parse_parameters(3 TSRMLS_CC, "zll", &pval_id, &start, &number)
1545 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1546 option_set_int(p, "start", start > 0 ? start - 1 : 0);
1547 option_set_int(p, "count", number);
1552 /* {{{ proto void yaz_sort(resource id, string sortspec)
1553 Set result set sorting criteria */
1554 PHP_FUNCTION(yaz_sort)
1557 const char *criteria;
1561 if (ZEND_NUM_ARGS() != 2 ||
1562 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id, &criteria,
1563 &criteria_len) == FAILURE) {
1567 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1569 xfree(p->sort_criteria);
1570 p->sort_criteria = xstrdup(criteria);
1572 ZOOM_resultset_sort(p->zoom_set, "yaz", criteria);
1578 const char *ill_array_lookup(void *handle, const char *name)
1580 return array_lookup_string((HashTable *) handle, name);
1583 /* {{{ proto void yaz_itemorder(resource id, array package)
1584 Sends Item Order request */
1585 PHP_FUNCTION(yaz_itemorder)
1587 zval *pval_id, *pval_package;
1590 if (ZEND_NUM_ARGS() != 2 ||
1591 zend_parse_parameters(2 TSRMLS_CC, "za", &pval_id, &pval_package) ==
1595 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1597 ZOOM_options options = ZOOM_options_create();
1599 ZOOM_options_set_callback(options,
1600 ill_array_lookup, Z_ARRVAL_PP(&pval_package));
1601 ZOOM_package_destroy(p->zoom_package);
1602 p->zoom_package = ZOOM_connection_package(p->zoom_conn, options);
1603 ZOOM_package_send(p->zoom_package, "itemorder");
1604 ZOOM_options_set_callback(options, 0, 0);
1605 ZOOM_options_destroy(options);
1611 /* {{{ proto void yaz_es(resource id, string type, array package)
1612 Sends Extended Services Request */
1613 PHP_FUNCTION(yaz_es)
1615 zval *pval_id, *pval_package;
1620 if (ZEND_NUM_ARGS() != 3 ||
1621 zend_parse_parameters(3 TSRMLS_CC, "zsa", &pval_id,
1622 &type, &type_len, &pval_package) == FAILURE) {
1625 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1627 ZOOM_options options = ZOOM_options_create();
1629 ZOOM_options_set_callback(options, ill_array_lookup,
1630 Z_ARRVAL_PP(&pval_package));
1631 ZOOM_package_destroy(p->zoom_package);
1632 p->zoom_package = ZOOM_connection_package(p->zoom_conn, options);
1633 ZOOM_package_send(p->zoom_package, type);
1634 ZOOM_options_set_callback(options, 0, 0);
1635 ZOOM_options_destroy(options);
1641 /* {{{ proto void yaz_scan(resource id, type, query [, flags])
1642 Sends Scan Request */
1643 PHP_FUNCTION(yaz_scan)
1645 zval *pval_id, *pval_flags;
1647 int type_len, query_len;
1648 HashTable *flags_ht = 0;
1651 if (ZEND_NUM_ARGS() == 3) {
1652 if (zend_parse_parameters(3 TSRMLS_CC, "zss",
1653 &pval_id, &type, &type_len,
1654 &query, &query_len) == FAILURE) {
1657 } else if (ZEND_NUM_ARGS() == 4) {
1658 if (zend_parse_parameters(4 TSRMLS_CC, "zssa",
1659 &pval_id, &type, &type_len,
1660 &query, &query_len, &pval_flags) == FAILURE) {
1663 flags_ht = Z_ARRVAL_PP(&pval_flags);
1667 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1668 ZOOM_scanset_destroy(p->zoom_scan);
1671 option_set(p, "number", array_lookup_string(flags_ht, "number"));
1672 option_set(p, "position", array_lookup_string(flags_ht, "position"));
1673 option_set(p, "stepSize", array_lookup_string(flags_ht, "stepsize"));
1674 p->zoom_scan = ZOOM_connection_scan(p->zoom_conn, query);
1680 /* {{{ proto array yaz_es_result(resource id)
1681 Inspects Extended Services Result */
1682 PHP_FUNCTION(yaz_es_result)
1687 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z",
1688 &pval_id) == FAILURE) {
1692 array_init(return_value);
1694 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1695 if (p && p->zoom_package) {
1696 const char *str = ZOOM_package_option_get(p->zoom_package,
1700 add_assoc_string(return_value, "targetReference", (char *) str, 1);
1702 str = ZOOM_package_option_get(p->zoom_package,
1705 add_assoc_string(return_value, "xmlUpdateDoc", (char *) str, 1);
1712 /* {{{ proto array yaz_scan_result(resource id [, array options])
1713 Inspects Scan Result */
1714 PHP_FUNCTION(yaz_scan_result)
1716 zval *pval_id, *pval_opt = 0;
1719 if (ZEND_NUM_ARGS() == 2) {
1720 if (zend_parse_parameters(2 TSRMLS_CC, "zz",
1721 &pval_id, &pval_opt) == FAILURE) {
1724 } else if (ZEND_NUM_ARGS() == 1) {
1725 if (zend_parse_parameters(1 TSRMLS_CC, "z",
1726 &pval_id) == FAILURE) {
1733 array_init(return_value);
1735 if (pval_opt && array_init(pval_opt) == FAILURE) {
1739 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1740 if (p && p->zoom_scan) {
1742 /* ZOOM_scanset_term changed from YAZ 3 to YAZ 4 */
1743 #if YAZ_VERSIONL >= 0x040000
1748 int size = ZOOM_scanset_size(p->zoom_scan);
1750 for (pos = 0; pos < size; pos++) {
1751 const char *term = ZOOM_scanset_term(p->zoom_scan, pos, &occ, &len);
1754 ALLOC_ZVAL(my_zval);
1755 array_init(my_zval);
1756 INIT_PZVAL(my_zval);
1758 add_next_index_string(my_zval, "term", 1);
1761 add_next_index_stringl(my_zval, (char*) term, len, 1);
1763 add_next_index_string(my_zval, "?", 1);
1765 add_next_index_long(my_zval, occ);
1767 term = ZOOM_scanset_display_term(p->zoom_scan, pos, &occ, &len);
1770 add_next_index_stringl(my_zval, (char*) term, len, 1);
1772 add_next_index_string(my_zval, "?", 1);
1775 zend_hash_next_index_insert(return_value->value.ht, (void *) &my_zval, sizeof(zval *), NULL);
1781 add_assoc_long(pval_opt, "number", size);
1783 v = ZOOM_scanset_option_get(p->zoom_scan, "stepSize");
1785 add_assoc_long(pval_opt, "stepsize", atoi(v));
1787 v = ZOOM_scanset_option_get(p->zoom_scan, "position");
1789 add_assoc_long(pval_opt, "position", atoi(v));
1791 v = ZOOM_scanset_option_get(p->zoom_scan, "scanStatus");
1793 add_assoc_long(pval_opt, "status", atoi(v));
1801 /* {{{ proto void yaz_ccl_conf(resource id, array package)
1802 Configure CCL package */
1803 PHP_FUNCTION(yaz_ccl_conf)
1805 zval *pval_id, *pval_package;
1808 if (ZEND_NUM_ARGS() != 2 ||
1809 zend_parse_parameters(2 TSRMLS_CC, "za", &pval_id, &pval_package)
1813 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1815 HashTable *ht = Z_ARRVAL_PP(&pval_package);
1820 ccl_qual_rm(&p->bibset);
1821 p->bibset = ccl_qual_mk();
1823 for (zend_hash_internal_pointer_reset_ex(ht, &pos);
1824 zend_hash_get_current_data_ex(ht, (void**) &ent, &pos) == SUCCESS;
1825 zend_hash_move_forward_ex(ht, &pos)
1828 #if PHP_API_VERSION > 20010101
1829 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, 0, &pos);
1831 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, &pos);
1833 if (type != HASH_KEY_IS_STRING || Z_TYPE_PP(ent) != IS_STRING) {
1836 ccl_qual_fitem(p->bibset, (*ent)->value.str.val, key);
1843 /* {{{ proto bool yaz_ccl_parse(resource id, string query, array res)
1844 Parse a CCL query */
1845 PHP_FUNCTION(yaz_ccl_parse)
1847 zval *pval_id, *pval_res = 0;
1852 if (ZEND_NUM_ARGS() != 3 ||
1853 zend_parse_parameters(3 TSRMLS_CC, "zsz",
1854 &pval_id, &query, &query_len, &pval_res)
1859 zval_dtor(pval_res);
1860 array_init(pval_res);
1861 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1863 struct ccl_rpn_node *rpn;
1866 CCL_parser ccl_parser = ccl_parser_create(p->bibset);
1868 rpn = ccl_parser_find_str(ccl_parser, query);
1870 error_code = ccl_parser_get_error(ccl_parser, &error_pos);
1871 add_assoc_long(pval_res, "errorcode", error_code);
1875 add_assoc_string(pval_res, "errorstring",
1876 (char *) ccl_err_msg(error_code), 1);
1877 add_assoc_long(pval_res, "errorpos", error_pos);
1882 WRBUF wrbuf_pqf = wrbuf_alloc();
1883 ccl_stop_words_t csw = ccl_stop_words_create();
1884 int r = ccl_stop_words_tree(csw, p->bibset, &rpn);
1888 /* stop words were removed. Return stopwords info */
1889 zval *zval_stopwords;
1892 MAKE_STD_ZVAL(zval_stopwords);
1893 array_init(zval_stopwords);
1894 for (idx = 0; ; idx++)
1896 zval *zval_stopword;
1900 if (!ccl_stop_words_info(csw, idx, &qname, &term))
1903 MAKE_STD_ZVAL(zval_stopword);
1904 array_init(zval_stopword);
1906 add_assoc_string(zval_stopword, "field", (char *) qname, 1);
1907 add_assoc_string(zval_stopword, "term", (char *) term, 1);
1908 add_next_index_zval(zval_stopwords, zval_stopword);
1910 add_assoc_zval(pval_res, "stopwords", zval_stopwords);
1912 ccl_pquery(wrbuf_pqf, rpn);
1913 add_assoc_stringl(pval_res, "rpn",
1914 wrbuf_buf(wrbuf_pqf), wrbuf_len(wrbuf_pqf), 1);
1915 wrbuf_destroy(wrbuf_pqf);
1916 ccl_stop_words_destroy(csw);
1919 ccl_rpn_delete(rpn);
1927 /* {{{ proto bool yaz_database (resource id, string databases)
1928 Specify the databases within a session */
1929 PHP_FUNCTION(yaz_database)
1936 if (ZEND_NUM_ARGS() != 2 ||
1937 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1938 &database, &database_len) == FAILURE) {
1942 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1943 option_set(p, "databaseName", database);
1949 /* {{{ php_yaz_init_globals
1951 static void php_yaz_init_globals(zend_yaz_globals *yaz_globals)
1953 yaz_globals->assoc_seq = 0;
1954 yaz_globals->max_links = 100;
1955 yaz_globals->keepalive = 120;
1956 yaz_globals->log_file = NULL;
1957 yaz_globals->log_mask = NULL;
1961 static void yaz_close_session(Yaz_Association *as TSRMLS_DC)
1963 if (*as && (*as)->order == YAZSG(assoc_seq)) {
1964 if ((*as)->persistent) {
1967 yaz_association_destroy(*as);
1973 static void yaz_close_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1975 Yaz_Association *as = (Yaz_Association *) rsrc->ptr;
1976 yaz_close_session(as TSRMLS_CC);
1979 /* {{{ PHP_INI_BEGIN
1982 #if PHP_MAJOR_VERSION >= 5
1983 STD_PHP_INI_ENTRY("yaz.max_links", "100", PHP_INI_ALL, OnUpdateLong, max_links, zend_yaz_globals, yaz_globals)
1985 STD_PHP_INI_ENTRY("yaz.max_links", "100", PHP_INI_ALL, OnUpdateInt, max_links, zend_yaz_globals, yaz_globals)
1987 #if PHP_MAJOR_VERSION >= 5
1988 STD_PHP_INI_ENTRY("yaz.keepalive", "120", PHP_INI_ALL, OnUpdateLong, keepalive, zend_yaz_globals, yaz_globals)
1990 STD_PHP_INI_ENTRY("yaz.keepalive", "120", PHP_INI_ALL, OnUpdateInt, keepalive, zend_yaz_globals, yaz_globals)
1992 STD_PHP_INI_ENTRY("yaz.log_file", NULL, PHP_INI_ALL, OnUpdateString, log_file, zend_yaz_globals, yaz_globals)
1993 STD_PHP_INI_ENTRY("yaz.log_mask", NULL, PHP_INI_ALL, OnUpdateString, log_mask, zend_yaz_globals, yaz_globals)
1997 PHP_MINIT_FUNCTION(yaz)
2003 yaz_mutex = tsrm_mutex_alloc();
2006 ZEND_INIT_MODULE_GLOBALS(yaz, php_yaz_init_globals, NULL);
2008 REGISTER_INI_ENTRIES();
2010 REGISTER_LONG_CONSTANT("ZOOM_EVENT_NONE", ZOOM_EVENT_NONE,
2011 CONST_CS|CONST_PERSISTENT);
2012 REGISTER_LONG_CONSTANT("ZOOM_EVENT_CONNECT", ZOOM_EVENT_CONNECT,
2013 CONST_CS|CONST_PERSISTENT);
2014 REGISTER_LONG_CONSTANT("ZOOM_EVENT_SEND_DATA", ZOOM_EVENT_SEND_DATA,
2015 CONST_CS|CONST_PERSISTENT);
2016 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_DATA", ZOOM_EVENT_RECV_DATA,
2017 CONST_CS|CONST_PERSISTENT);
2018 REGISTER_LONG_CONSTANT("ZOOM_EVENT_TIMEOUT", ZOOM_EVENT_TIMEOUT,
2019 CONST_CS|CONST_PERSISTENT);
2020 REGISTER_LONG_CONSTANT("ZOOM_EVENT_UNKNOWN", ZOOM_EVENT_UNKNOWN,
2021 CONST_CS|CONST_PERSISTENT);
2022 REGISTER_LONG_CONSTANT("ZOOM_EVENT_SEND_APDU", ZOOM_EVENT_SEND_APDU,
2023 CONST_CS|CONST_PERSISTENT);
2024 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_APDU", ZOOM_EVENT_RECV_APDU,
2025 CONST_CS|CONST_PERSISTENT);
2026 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_RECORD", ZOOM_EVENT_RECV_RECORD,
2027 CONST_CS|CONST_PERSISTENT);
2028 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_SEARCH", ZOOM_EVENT_RECV_SEARCH,
2029 CONST_CS|CONST_PERSISTENT);
2031 fname = YAZSG(log_file);
2032 mask = YAZSG(log_mask);
2033 if (fname && *fname)
2035 yaz_log_init_file(fname);
2038 yaz_log_init_level(yaz_log_mask_str(mask));
2041 yaz_log_init_level(0);
2043 le_link = zend_register_list_destructors_ex(yaz_close_link, 0, "YAZ link", module_number);
2045 order_associations = 1;
2046 shared_associations = xmalloc(sizeof(*shared_associations) * MAX_ASSOC);
2047 for (i = 0; i < MAX_ASSOC; i++) {
2048 shared_associations[i] = 0;
2053 PHP_MSHUTDOWN_FUNCTION(yaz)
2057 if (shared_associations) {
2058 for (i = 0; i < MAX_ASSOC; i++) {
2059 yaz_association_destroy (shared_associations[i]);
2061 xfree(shared_associations);
2062 shared_associations = 0;
2065 tsrm_mutex_free(yaz_mutex);
2068 yaz_log_init_file(0);
2070 UNREGISTER_INI_ENTRIES();
2075 PHP_MINFO_FUNCTION(yaz)
2077 char version_str[20];
2079 strcpy(version_str, "unknown");
2080 yaz_version(version_str, 0);
2081 php_info_print_table_start();
2082 php_info_print_table_row(2, "YAZ Support", "enabled");
2083 php_info_print_table_row(2, "PHP/YAZ Version", PHP_YAZ_VERSION);
2084 php_info_print_table_row(2, "YAZ Version", version_str);
2085 php_info_print_table_row(2, "Compiled with YAZ version", YAZ_VERSION);
2086 php_info_print_table_end();
2089 PHP_RSHUTDOWN_FUNCTION(yaz)
2095 tsrm_mutex_lock(yaz_mutex);
2097 for (i = 0; i < YAZSG(max_links); i++) {
2098 Yaz_Association *as = shared_associations + i;
2101 if (now - (*as)->time_stamp > YAZSG(keepalive))
2103 yaz_association_destroy(*as);
2109 tsrm_mutex_unlock(yaz_mutex);
2114 PHP_RINIT_FUNCTION(yaz)
2118 sprintf(pidstr, "%ld", (long) getpid());
2120 tsrm_mutex_lock(yaz_mutex);
2122 YAZSG(assoc_seq) = order_associations++;
2124 tsrm_mutex_unlock(yaz_mutex);
2126 yaz_log_init_prefix(pidstr);
2130 zend_module_entry yaz_module_entry = {
2131 #if ZEND_MODULE_API_NO >= 20010901
2132 STANDARD_MODULE_HEADER,
2141 #if ZEND_MODULE_API_NO >= 20010901
2144 STANDARD_MODULE_PROPERTIES
2155 * vim600: sw=4 ts=4 fdm=marker
2156 * vim<600: sw=4 ts=4