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)
597 else if (ZEND_NUM_ARGS() > 1) {
601 tsrm_mutex_lock(yaz_mutex);
603 for (i = 0; i<YAZSG(max_links); i++) {
604 Yaz_Association p = shared_associations[i];
605 if (p && p->order == YAZSG(assoc_seq)) {
608 sprintf(str, "%d", timeout);
609 ZOOM_connection_option_set(p->zoom_conn, "timeout", str);
611 conn_ar[no++] = p->zoom_conn;
615 tsrm_mutex_unlock(yaz_mutex);
618 long ev = ZOOM_event(no, conn_ar);
622 Yaz_Association p = conn_as[ev-1];
623 int event_code = ZOOM_connection_last_event(p->zoom_conn);
626 add_assoc_long(pval_options, "connid", ev);
627 add_assoc_long(pval_options, "eventcode", event_code);
630 zend_list_addref(p->zval_resource);
631 Z_LVAL_P(return_value) = p->zval_resource;
632 Z_TYPE_P(return_value) = IS_RESOURCE;
638 while (ZOOM_event(no, conn_ar))
645 /* {{{ proto int yaz_errno(resource id)
646 Return last error number (>0 for bib-1 diagnostic, <0 for other error, 0 for no error */
647 PHP_FUNCTION(yaz_errno)
652 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
656 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
660 RETVAL_LONG(ZOOM_connection_errcode(p->zoom_conn));
665 /* {{{ proto string yaz_error(resource id)
666 Return last error message */
667 PHP_FUNCTION(yaz_error)
672 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
676 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
678 int code = ZOOM_connection_errcode(p->zoom_conn);
679 const char *msg = ZOOM_connection_errmsg(p->zoom_conn);
684 return_value->value.str.len = strlen(msg);
685 return_value->value.str.val = estrndup(msg, return_value->value.str.len);
686 return_value->type = IS_STRING;
692 /* {{{ proto string yaz_addinfo(resource id)
693 Return additional info for last error (empty string if none) */
694 PHP_FUNCTION(yaz_addinfo)
699 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z", &id)
703 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
705 const char *addinfo = ZOOM_connection_addinfo(p->zoom_conn);
707 return_value->value.str.len = strlen(addinfo);
708 return_value->value.str.val = estrndup(addinfo, return_value->value.str.len);
709 return_value->type = IS_STRING;
715 /* {{{ proto int yaz_hits(resource id [, array searchresult])
716 Return number of hits (result count) for last search */
717 PHP_FUNCTION(yaz_hits)
719 zval *id, *searchresult = 0;
722 if (ZEND_NUM_ARGS() == 1) {
723 if (zend_parse_parameters(1 TSRMLS_CC, "z", &id) == FAILURE) {
726 } else if (ZEND_NUM_ARGS() == 2) {
727 if (zend_parse_parameters(2 TSRMLS_CC, "za", &id, &searchresult)
735 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, id, &p);
736 if (p && p->zoom_set) {
737 RETVAL_LONG(ZOOM_resultset_size(p->zoom_set));
741 ZOOM_resultset_option_get(p->zoom_set, "resultSetStatus");
743 add_assoc_string(searchresult, "resultSetStatus",
749 ZOOM_resultset_option_get(p->zoom_set, "searchresult.size");
752 if (sz_str && *sz_str)
754 for (i = 0; i<sz; i++)
757 const char *opt_value;
760 MAKE_STD_ZVAL(zval_element);
761 array_init(zval_element);
762 add_next_index_zval(searchresult, zval_element);
764 sprintf(opt_name, "searchresult.%d.id", i);
765 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
767 add_assoc_string(zval_element, "id",
768 (char *) opt_value, 1);
770 sprintf(opt_name, "searchresult.%d.count", i);
771 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
773 add_assoc_long(zval_element, "count", atoi(opt_value));
775 sprintf(opt_name, "searchresult.%d.subquery.term", i);
776 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
778 add_assoc_string(zval_element, "subquery.term",
779 (char *) opt_value, 1);
781 sprintf(opt_name, "searchresult.%d.interpretation.term", i);
782 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
784 add_assoc_string(zval_element, "interpretation.term",
785 (char *) opt_value, 1);
787 sprintf(opt_name, "searchresult.%d.recommendation.term", i);
788 opt_value = ZOOM_resultset_option_get(p->zoom_set, opt_name);
790 add_assoc_string(zval_element, "recommendation.term",
791 (char *) opt_value, 1);
802 static Z_GenericRecord *marc_to_grs1(const char *buf, ODR o)
806 int indicator_length;
807 int identifier_length;
809 int length_data_entry;
811 int length_implementation;
812 int max_elements = 256;
813 Z_GenericRecord *r = odr_malloc(o, sizeof(*r));
814 r->elements = odr_malloc(o, sizeof(*r->elements) * max_elements);
817 record_length = atoi_n(buf, 5);
818 if (record_length < 25) {
821 indicator_length = atoi_n(buf + 10, 1);
822 identifier_length = atoi_n(buf + 11, 1);
823 base_address = atoi_n(buf + 12, 5);
825 length_data_entry = atoi_n(buf + 20, 1);
826 length_starting = atoi_n(buf + 21, 1);
827 length_implementation = atoi_n(buf + 22, 1);
829 for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) {
830 entry_p += 3 + length_data_entry + length_starting;
831 if (entry_p >= record_length) {
837 Z_TaggedElement *tag;
838 tag = r->elements[r->num_elements++] = odr_malloc(o, sizeof(*tag));
839 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
841 tag->tagOccurrence = 0;
843 tag->appliedVariant = 0;
844 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
845 tag->tagValue->which = Z_StringOrNumeric_string;
846 tag->tagValue->u.string = odr_strdup(o, "leader");
848 tag->content = odr_malloc(o, sizeof(*tag->content));
849 tag->content->which = Z_ElementData_string;
850 tag->content->u.string = odr_strdupn(o, buf, 24);
852 base_address = entry_p + 1;
853 for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) {
854 Z_TaggedElement *tag;
860 int identifier_flag = 1;
862 memcpy(tag_str, buf+entry_p, 3);
866 if ((r->num_elements + 1) >= max_elements) {
867 Z_TaggedElement **tmp = r->elements;
869 /* double array space, throw away old buffer (nibble memory) */
870 r->elements = odr_malloc(o, sizeof(*r->elements) * (max_elements *= 2));
871 memcpy(r->elements, tmp, r->num_elements * sizeof(*tmp));
873 tag = r->elements[r->num_elements++] = odr_malloc(o, sizeof(*tag));
874 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
876 tag->tagOccurrence = 0;
878 tag->appliedVariant = 0;
879 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
880 tag->tagValue->which = Z_StringOrNumeric_string;
881 tag->tagValue->u.string = odr_strdup(o, tag_str);
883 tag->content = odr_malloc(o, sizeof(*tag->content));
884 tag->content->which = Z_ElementData_subtree;
886 tag->content->u.subtree = odr_malloc(o, sizeof(*tag->content->u.subtree));
887 tag->content->u.subtree->elements = odr_malloc(o, sizeof(*r->elements));
888 tag->content->u.subtree->num_elements = 1;
890 tag = tag->content->u.subtree->elements[0] = odr_malloc(o, sizeof(**tag->content->u.subtree->elements));
892 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
894 tag->tagOccurrence = 0;
896 tag->appliedVariant = 0;
897 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
898 tag->tagValue->which = Z_StringOrNumeric_string;
899 tag->content = odr_malloc(o, sizeof(*tag->content));
901 data_length = atoi_n(buf + entry_p, length_data_entry);
902 entry_p += length_data_entry;
903 data_offset = atoi_n(buf + entry_p, length_starting);
904 entry_p += length_starting;
905 i = data_offset + base_address;
906 end_offset = i + data_length - 1;
908 if (indicator_length > 0 && indicator_length < 5) {
909 if (buf[i + indicator_length] != ISO2709_IDFS) {
912 } else if (!memcmp(tag_str, "00", 2)) {
916 if (identifier_flag && indicator_length) {
918 tag->tagValue->u.string = odr_malloc(o, indicator_length + 1);
919 memcpy(tag->tagValue->u.string, buf + i, indicator_length);
920 tag->tagValue->u.string[indicator_length] = '\0';
921 i += indicator_length;
923 tag->content->which = Z_ElementData_subtree;
925 tag->content->u.subtree = odr_malloc(o, sizeof(*tag->content->u.subtree));
926 tag->content->u.subtree->elements = odr_malloc(o, 256 * sizeof(*r->elements));
927 tag->content->u.subtree->num_elements = 0;
929 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset) {
932 Z_TaggedElement *parent_tag = tag;
933 Z_TaggedElement *tag = odr_malloc(o, sizeof(*tag));
935 if (parent_tag->content->u.subtree->num_elements < 256) {
936 parent_tag->content->u.subtree->elements[
937 parent_tag->content->u.subtree->num_elements++] = tag;
940 tag->tagType = odr_malloc(o, sizeof(*tag->tagType));
942 tag->tagOccurrence = 0;
944 tag->appliedVariant = 0;
945 tag->tagValue = odr_malloc(o, sizeof(*tag->tagValue));
946 tag->tagValue->which = Z_StringOrNumeric_string;
949 tag->tagValue->u.string = odr_malloc(o, identifier_length);
950 memcpy(tag->tagValue->u.string, buf + i + 1, identifier_length - 1);
951 tag->tagValue->u.string[identifier_length - 1] = '\0';
952 i += identifier_length;
955 tag->content = odr_malloc(o, sizeof(*tag->content));
956 tag->content->which = Z_ElementData_string;
959 while ( buf[i] != ISO2709_RS &&
960 buf[i] != ISO2709_IDFS &&
961 buf[i] != ISO2709_FS && i < end_offset) {
965 tag->content->u.string = odr_malloc(o, i - i0 + 1);
966 memcpy(tag->content->u.string, buf + i0, i - i0);
967 tag->content->u.string[i - i0] = '\0';
972 tag->tagValue->u.string = "@";
973 tag->content->which = Z_ElementData_string;
975 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset) {
978 tag->content->u.string = odr_malloc(o, i - i0 +1);
979 memcpy(tag->content->u.string, buf + i0, i - i0);
980 tag->content->u.string[i-i0] = '\0';
993 static struct cvt_handle *cvt_open(const char *to, const char *from)
995 ODR o = odr_createmem(ODR_ENCODE);
997 struct cvt_handle *cvt = odr_malloc(o, sizeof(*cvt));
1000 cvt->buf = odr_malloc(o, cvt->size);
1003 cvt->cd = yaz_iconv_open(to, from);
1007 static void cvt_close(struct cvt_handle *cvt)
1010 yaz_iconv_close(cvt->cd);
1011 odr_destroy(cvt->odr);
1014 static const char *cvt_string(const char *input, struct cvt_handle *cvt)
1019 size_t inbytesleft = strlen(input);
1020 const char *inp = input;
1021 size_t outbytesleft = cvt->size - 1;
1022 char *outp = cvt->buf;
1023 size_t r = yaz_iconv(cvt->cd, (char**) &inp, &inbytesleft,
1024 &outp, &outbytesleft);
1025 if (r == (size_t) (-1)) {
1026 int e = yaz_iconv_error(cvt->cd);
1027 if (e != YAZ_ICONV_E2BIG || cvt->size > 200000)
1032 cvt->size = cvt->size * 2 + 30;
1033 cvt->buf = (char*) odr_malloc(cvt->odr, cvt->size);
1035 cvt->buf[outp - cvt->buf] = '\0';
1042 static void retval_array3_grs1(zval *return_value, Z_GenericRecord *p,
1043 struct cvt_handle *cvt)
1049 struct tag_list *next;
1051 NMEM nmem = nmem_create();
1053 array_init(return_value);
1054 for (i = 0; i<p->num_elements; i++)
1056 struct tag_list *tl;
1059 Z_TaggedElement *e = p->elements[i];
1060 char tagstr[32], *tag = 0;
1062 if (e->tagValue->which == Z_StringOrNumeric_numeric)
1064 sprintf(tagstr, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1067 else if (e->tagValue->which == Z_StringOrNumeric_string)
1068 tag = e->tagValue->u.string, zval_element;
1073 for (tl = all_tags; tl; tl = tl->next)
1074 if (!strcmp(tl->tag, tag))
1077 zval_list = tl->zval_list;
1080 MAKE_STD_ZVAL(zval_list);
1081 array_init(zval_list);
1082 add_assoc_zval(return_value, tag, zval_list);
1084 tl = nmem_malloc(nmem, sizeof(*tl));
1085 tl->tag = nmem_strdup(nmem, tag);
1086 tl->zval_list = zval_list;
1087 tl->next = all_tags;
1090 MAKE_STD_ZVAL(zval_element);
1091 array_init(zval_element);
1092 add_next_index_zval(zval_list, zval_element);
1093 if (e->content->which == Z_ElementData_subtree)
1095 /* we have a subtree. Move to first child */
1096 Z_GenericRecord *sub = e->content->u.subtree;
1097 if (sub->num_elements >= 1)
1098 e = sub->elements[0];
1104 const char *tag = 0;
1105 if (e->tagValue->which == Z_StringOrNumeric_numeric)
1107 sprintf(tagstr, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1110 else if (e->tagValue->which == Z_StringOrNumeric_string)
1111 tag = e->tagValue->u.string;
1112 if (tag && e->content->which == Z_ElementData_subtree)
1115 Z_GenericRecord *sub = e->content->u.subtree;
1117 for (i = 0; tag[i]; i++)
1122 sprintf(ind_idx, "ind%d", i+1);
1123 ind_val[0] = tag[i];
1126 add_assoc_string(zval_element, ind_idx, ind_val, 1);
1128 for (i = 0; i<sub->num_elements; i++)
1130 Z_TaggedElement *e = sub->elements[i];
1131 const char *tag = 0;
1132 if (e->tagValue->which == Z_StringOrNumeric_numeric)
1134 sprintf(tagstr, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1137 else if (e->tagValue->which == Z_StringOrNumeric_string)
1138 tag = e->tagValue->u.string, zval_element;
1140 if (tag && e->content->which == Z_ElementData_string)
1142 const char *v = cvt_string(e->content->u.string, cvt);
1143 add_assoc_string(zval_element, (char*) tag, (char*) v,
1148 else if (tag && e->content->which == Z_ElementData_string)
1150 /* Leader or control field */
1151 const char *v = cvt_string(e->content->u.string, cvt);
1152 ZVAL_STRING(zval_element, (char*) v, 1);
1159 static void retval_array2_grs1(zval *return_value, Z_GenericRecord *p,
1160 struct cvt_handle *cvt)
1164 array_init(return_value);
1166 for (i = 0; i<p->num_elements; i++)
1170 Z_TaggedElement *e = p->elements[i];
1172 MAKE_STD_ZVAL(zval_element);
1173 array_init(zval_element);
1176 add_assoc_long(zval_element, "tagType", (long) *e->tagType);
1178 if (e->tagValue->which == Z_StringOrNumeric_string)
1179 add_assoc_string(zval_element, "tag", e->tagValue->u.string, 1);
1180 else if (e->tagValue->which == Z_StringOrNumeric_numeric)
1181 add_assoc_long(zval_element, "tag", (long) *e->tagValue->u.numeric);
1183 switch (e->content->which) {
1184 case Z_ElementData_string:
1187 const char *v = cvt_string(e->content->u.string, cvt);
1188 add_assoc_string(zval_element, "content", (char*) v, 1);
1191 case Z_ElementData_numeric:
1192 add_assoc_long(zval_element, "content", (long) *e->content->u.numeric);
1194 case Z_ElementData_trueOrFalse:
1195 add_assoc_bool(zval_element, "content",*e->content->u.trueOrFalse);
1197 case Z_ElementData_subtree:
1198 MAKE_STD_ZVAL(zval_sub);
1199 retval_array2_grs1(zval_sub, e->content->u.subtree, cvt);
1200 add_assoc_zval(zval_element, "content", zval_sub);
1202 add_next_index_zval(return_value, zval_element);
1206 static void retval_array1_grs1(zval *return_value, Z_GenericRecord *p,
1207 struct cvt_handle *cvt)
1209 Z_GenericRecord *grs[20];
1213 array_init(return_value);
1217 while (level >= 0) {
1219 Z_TaggedElement *e = 0;
1220 Z_GenericRecord *p = grs[level];
1225 if (eno[level] >= p->num_elements) {
1232 for (i = 0; i <= level; i++) {
1234 e = grs[i]->elements[eno[i]];
1237 tag_type = (long) *e->tagType;
1239 taglen = strlen(tag);
1240 sprintf(tag + taglen, "(%ld,", tag_type);
1241 taglen = strlen(tag);
1243 if (e->tagValue->which == Z_StringOrNumeric_string) {
1244 int len = strlen(e->tagValue->u.string);
1246 memcpy(tag + taglen, e->tagValue->u.string, len);
1247 tag[taglen+len] = '\0';
1248 } else if (e->tagValue->which == Z_StringOrNumeric_numeric) {
1249 sprintf(tag + taglen, ODR_INT_PRINTF, *e->tagValue->u.numeric);
1251 taglen = strlen(tag);
1252 strcpy(tag + taglen, ")");
1255 ALLOC_ZVAL(my_zval);
1256 array_init(my_zval);
1257 INIT_PZVAL(my_zval);
1259 add_next_index_string(my_zval, tag, 1);
1261 switch (e->content->which) {
1262 case Z_ElementData_string:
1265 const char *v = cvt_string(e->content->u.string, cvt);
1266 add_next_index_string(my_zval, (char*) v, 1);
1269 case Z_ElementData_numeric:
1270 add_next_index_long(my_zval, (long) *e->content->u.numeric);
1272 case Z_ElementData_trueOrFalse:
1273 add_next_index_long(my_zval, *e->content->u.trueOrFalse);
1275 case Z_ElementData_subtree:
1278 grs[level] = e->content->u.subtree;
1282 zend_hash_next_index_insert(return_value->value.ht, (void *) &my_zval, sizeof(zval *), NULL);
1287 static void ext_grs1(zval *return_value, char type_args[][60],
1289 void (*array_func)(zval *, Z_GenericRecord *,
1290 struct cvt_handle *))
1292 Z_External *ext = (Z_External *) ZOOM_record_get(r, "ext", 0);
1293 if (ext && ext->which == Z_External_OPAC)
1294 ext = ext->u.opac->bibliographicRecord;
1296 struct cvt_handle *cvt = 0;
1297 if (type_args[2][0])
1298 cvt = cvt_open(type_args[3], type_args[2]);
1300 cvt = cvt_open(0, 0);
1302 if (ext->which == Z_External_grs1) {
1303 retval_array1_grs1(return_value, ext->u.grs1, cvt);
1304 } else if (ext->which == Z_External_octet) {
1305 Z_GenericRecord *rec = 0;
1306 if (yaz_oid_is_iso2709(ext->direct_reference))
1308 char *buf = (char *) (ext->u.octet_aligned->buf);
1309 rec = marc_to_grs1(buf, cvt->odr);
1312 (*array_func)(return_value, rec, cvt);
1320 /* {{{ proto string yaz_record(resource id, int pos, string type)
1321 Return record information at given result set position */
1322 PHP_FUNCTION(yaz_record)
1330 if (ZEND_NUM_ARGS() != 3) {
1334 if (zend_parse_parameters(3 TSRMLS_CC, "zls", &pval_id, &pos,
1335 &type, &type_len) == FAILURE) {
1339 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1341 if (p && p->zoom_set) {
1343 r = ZOOM_resultset_record(p->zoom_set, pos-1);
1346 char type_args[4][60]; /* 0; 1=2,3 (1 is assumed charset) */
1347 type_args[0][0] = 0;
1348 type_args[1][0] = 0;
1349 type_args[2][0] = 0;
1350 type_args[3][0] = 0;
1351 sscanf(type, "%59[^;];%59[^=]=%59[^,],%59[^,]", type_args[0],
1352 type_args[1], type_args[2], type_args[3]);
1354 if (!strcmp(type_args[0], "string")) {
1355 type_tmp = xstrdup(type);
1356 strcpy(type_tmp, "render");
1357 strcat(type_tmp, type + 6);
1360 if (!strcmp(type_args[0], "array") ||
1361 !strcmp(type_args[0], "array1"))
1363 ext_grs1(return_value, type_args, r, retval_array1_grs1);
1364 } else if (!strcmp(type_args[0], "array2")) {
1365 ext_grs1(return_value, type_args, r, retval_array2_grs1);
1366 } else if (!strcmp(type_args[0], "array3")) {
1367 ext_grs1(return_value, type_args, r, retval_array3_grs1);
1370 const char *info = ZOOM_record_get(r, type, &rlen);
1372 return_value->value.str.len = (rlen > 0) ? rlen : 0;
1373 return_value->value.str.val =
1374 estrndup(info, return_value->value.str.len);
1375 return_value->type = IS_STRING;
1379 php_error_docref(NULL TSRMLS_CC, E_WARNING,
1380 "Bad yaz_record type %s - or unable "
1381 "to return record with type given", type);
1391 /* {{{ proto void yaz_syntax(resource id, string syntax)
1392 Set record syntax for retrieval */
1393 PHP_FUNCTION(yaz_syntax)
1400 if (ZEND_NUM_ARGS() != 2 ||
1401 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1402 &syntax, &syntax_len) == FAILURE) {
1406 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1407 option_set(p, "preferredRecordSyntax", syntax);
1412 /* {{{ proto void yaz_element(resource id, string elementsetname)
1413 Set Element-Set-Name for retrieval */
1414 PHP_FUNCTION(yaz_element)
1417 const char *element;
1421 if (ZEND_NUM_ARGS() != 2 ||
1422 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1423 &element, &element_len) == FAILURE) {
1426 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1428 option_set(p, "elementSetName", element);
1433 /* {{{ proto void yaz_schema(resource id, string schema)
1434 Set Schema for retrieval */
1435 PHP_FUNCTION(yaz_schema)
1442 if (ZEND_NUM_ARGS() != 2 ||
1443 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1444 &schema, &schema_len) == FAILURE) {
1448 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1449 option_set(p, "schema", schema);
1454 /* {{{ proto void yaz_set_option(resource id, mixed options)
1455 Set Option(s) for connection */
1456 PHP_FUNCTION(yaz_set_option)
1460 if (ZEND_NUM_ARGS() == 2) {
1461 zval *pval_ar, *pval_id;
1462 if (zend_parse_parameters(2 TSRMLS_CC, "za",
1463 &pval_id, &pval_ar) == FAILURE) {
1466 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1472 ht = Z_ARRVAL_PP(&pval_ar);
1473 for(zend_hash_internal_pointer_reset_ex(ht, &pos);
1474 zend_hash_get_current_data_ex(ht, (void**) &ent, &pos) == SUCCESS;
1475 zend_hash_move_forward_ex(ht, &pos)
1479 #if PHP_API_VERSION > 20010101
1480 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, 0, &pos);
1482 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, &pos);
1484 if (type != HASH_KEY_IS_STRING || Z_TYPE_PP(ent) != IS_STRING) {
1487 option_set(p, key, (*ent)->value.str.val);
1491 } else if (ZEND_NUM_ARGS() == 3) {
1494 int name_len, value_len;
1495 if (zend_parse_parameters(3 TSRMLS_CC, "zss",
1496 &pval_id, &name, &name_len,
1497 &value, &value_len) == FAILURE) {
1500 get_assoc (INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1501 option_set(p, name, value);
1509 /* {{{ proto string yaz_get_option(resource id, string name)
1510 Set Option(s) for connection */
1511 PHP_FUNCTION(yaz_get_option)
1518 if (ZEND_NUM_ARGS() != 2 ||
1519 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id, &name, &name_len)
1523 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1525 const char *name_str, *v;
1526 v = option_get(p, name);
1530 return_value->value.str.len = strlen(v);
1531 return_value->value.str.val = estrndup(v, return_value->value.str.len);
1532 return_value->type = IS_STRING;
1540 /* {{{ proto void yaz_range(resource id, int start, int number)
1541 Set result set start point and number of records to request */
1542 PHP_FUNCTION(yaz_range)
1548 if (ZEND_NUM_ARGS() != 3 ||
1549 zend_parse_parameters(3 TSRMLS_CC, "zll", &pval_id, &start, &number)
1554 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1555 option_set_int(p, "start", start > 0 ? start - 1 : 0);
1556 option_set_int(p, "count", number);
1561 /* {{{ proto void yaz_sort(resource id, string sortspec)
1562 Set result set sorting criteria */
1563 PHP_FUNCTION(yaz_sort)
1566 const char *criteria;
1570 if (ZEND_NUM_ARGS() != 2 ||
1571 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id, &criteria,
1572 &criteria_len) == FAILURE) {
1576 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1578 xfree(p->sort_criteria);
1579 p->sort_criteria = xstrdup(criteria);
1581 ZOOM_resultset_sort(p->zoom_set, "yaz", criteria);
1587 const char *ill_array_lookup(void *handle, const char *name)
1589 return array_lookup_string((HashTable *) handle, name);
1592 /* {{{ proto void yaz_itemorder(resource id, array package)
1593 Sends Item Order request */
1594 PHP_FUNCTION(yaz_itemorder)
1596 zval *pval_id, *pval_package;
1599 if (ZEND_NUM_ARGS() != 2 ||
1600 zend_parse_parameters(2 TSRMLS_CC, "za", &pval_id, &pval_package) ==
1604 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1606 ZOOM_options options = ZOOM_options_create();
1608 ZOOM_options_set_callback(options,
1609 ill_array_lookup, Z_ARRVAL_PP(&pval_package));
1610 ZOOM_package_destroy(p->zoom_package);
1611 p->zoom_package = ZOOM_connection_package(p->zoom_conn, options);
1612 ZOOM_package_send(p->zoom_package, "itemorder");
1613 ZOOM_options_set_callback(options, 0, 0);
1614 ZOOM_options_destroy(options);
1620 /* {{{ proto void yaz_es(resource id, string type, array package)
1621 Sends Extended Services Request */
1622 PHP_FUNCTION(yaz_es)
1624 zval *pval_id, *pval_package;
1629 if (ZEND_NUM_ARGS() != 3 ||
1630 zend_parse_parameters(3 TSRMLS_CC, "zsa", &pval_id,
1631 &type, &type_len, &pval_package) == FAILURE) {
1634 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1636 ZOOM_options options = ZOOM_options_create();
1638 ZOOM_options_set_callback(options, ill_array_lookup,
1639 Z_ARRVAL_PP(&pval_package));
1640 ZOOM_package_destroy(p->zoom_package);
1641 p->zoom_package = ZOOM_connection_package(p->zoom_conn, options);
1642 ZOOM_package_send(p->zoom_package, type);
1643 ZOOM_options_set_callback(options, 0, 0);
1644 ZOOM_options_destroy(options);
1650 /* {{{ proto void yaz_scan(resource id, type, query [, flags])
1651 Sends Scan Request */
1652 PHP_FUNCTION(yaz_scan)
1654 zval *pval_id, *pval_flags;
1656 int type_len, query_len;
1657 HashTable *flags_ht = 0;
1660 if (ZEND_NUM_ARGS() == 3) {
1661 if (zend_parse_parameters(3 TSRMLS_CC, "zss",
1662 &pval_id, &type, &type_len,
1663 &query, &query_len) == FAILURE) {
1666 } else if (ZEND_NUM_ARGS() == 4) {
1667 if (zend_parse_parameters(4 TSRMLS_CC, "zssa",
1668 &pval_id, &type, &type_len,
1669 &query, &query_len, &pval_flags) == FAILURE) {
1672 flags_ht = Z_ARRVAL_PP(&pval_flags);
1676 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1677 ZOOM_scanset_destroy(p->zoom_scan);
1680 option_set(p, "number", array_lookup_string(flags_ht, "number"));
1681 option_set(p, "position", array_lookup_string(flags_ht, "position"));
1682 option_set(p, "stepSize", array_lookup_string(flags_ht, "stepsize"));
1683 p->zoom_scan = ZOOM_connection_scan(p->zoom_conn, query);
1689 /* {{{ proto array yaz_es_result(resource id)
1690 Inspects Extended Services Result */
1691 PHP_FUNCTION(yaz_es_result)
1696 if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters(1 TSRMLS_CC, "z",
1697 &pval_id) == FAILURE) {
1701 array_init(return_value);
1703 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1704 if (p && p->zoom_package) {
1705 const char *str = ZOOM_package_option_get(p->zoom_package,
1709 add_assoc_string(return_value, "targetReference", (char *) str, 1);
1711 str = ZOOM_package_option_get(p->zoom_package,
1714 add_assoc_string(return_value, "xmlUpdateDoc", (char *) str, 1);
1721 /* {{{ proto array yaz_scan_result(resource id [, array options])
1722 Inspects Scan Result */
1723 PHP_FUNCTION(yaz_scan_result)
1725 zval *pval_id, *pval_opt = 0;
1728 if (ZEND_NUM_ARGS() == 2) {
1729 if (zend_parse_parameters(2 TSRMLS_CC, "zz",
1730 &pval_id, &pval_opt) == FAILURE) {
1733 } else if (ZEND_NUM_ARGS() == 1) {
1734 if (zend_parse_parameters(1 TSRMLS_CC, "z",
1735 &pval_id) == FAILURE) {
1742 array_init(return_value);
1744 if (pval_opt && array_init(pval_opt) == FAILURE) {
1748 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1749 if (p && p->zoom_scan) {
1751 /* ZOOM_scanset_term changed from YAZ 3 to YAZ 4 */
1752 #if YAZ_VERSIONL >= 0x040000
1757 int size = ZOOM_scanset_size(p->zoom_scan);
1759 for (pos = 0; pos < size; pos++) {
1760 const char *term = ZOOM_scanset_term(p->zoom_scan, pos, &occ, &len);
1763 ALLOC_ZVAL(my_zval);
1764 array_init(my_zval);
1765 INIT_PZVAL(my_zval);
1767 add_next_index_string(my_zval, "term", 1);
1770 add_next_index_stringl(my_zval, (char*) term, len, 1);
1772 add_next_index_string(my_zval, "?", 1);
1774 add_next_index_long(my_zval, occ);
1776 term = ZOOM_scanset_display_term(p->zoom_scan, pos, &occ, &len);
1779 add_next_index_stringl(my_zval, (char*) term, len, 1);
1781 add_next_index_string(my_zval, "?", 1);
1784 zend_hash_next_index_insert(return_value->value.ht, (void *) &my_zval, sizeof(zval *), NULL);
1790 add_assoc_long(pval_opt, "number", size);
1792 v = ZOOM_scanset_option_get(p->zoom_scan, "stepSize");
1794 add_assoc_long(pval_opt, "stepsize", atoi(v));
1796 v = ZOOM_scanset_option_get(p->zoom_scan, "position");
1798 add_assoc_long(pval_opt, "position", atoi(v));
1800 v = ZOOM_scanset_option_get(p->zoom_scan, "scanStatus");
1802 add_assoc_long(pval_opt, "status", atoi(v));
1810 /* {{{ proto void yaz_ccl_conf(resource id, array package)
1811 Configure CCL package */
1812 PHP_FUNCTION(yaz_ccl_conf)
1814 zval *pval_id, *pval_package;
1817 if (ZEND_NUM_ARGS() != 2 ||
1818 zend_parse_parameters(2 TSRMLS_CC, "za", &pval_id, &pval_package)
1822 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1824 HashTable *ht = Z_ARRVAL_PP(&pval_package);
1829 ccl_qual_rm(&p->bibset);
1830 p->bibset = ccl_qual_mk();
1832 for (zend_hash_internal_pointer_reset_ex(ht, &pos);
1833 zend_hash_get_current_data_ex(ht, (void**) &ent, &pos) == SUCCESS;
1834 zend_hash_move_forward_ex(ht, &pos)
1837 #if PHP_API_VERSION > 20010101
1838 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, 0, &pos);
1840 int type = zend_hash_get_current_key_ex(ht, &key, 0, &idx, &pos);
1842 if (type != HASH_KEY_IS_STRING || Z_TYPE_PP(ent) != IS_STRING) {
1845 ccl_qual_fitem(p->bibset, (*ent)->value.str.val, key);
1852 /* {{{ proto bool yaz_ccl_parse(resource id, string query, array res)
1853 Parse a CCL query */
1854 PHP_FUNCTION(yaz_ccl_parse)
1856 zval *pval_id, *pval_res = 0;
1861 if (ZEND_NUM_ARGS() != 3 ||
1862 zend_parse_parameters(3 TSRMLS_CC, "zsz",
1863 &pval_id, &query, &query_len, &pval_res)
1868 zval_dtor(pval_res);
1869 array_init(pval_res);
1870 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1872 struct ccl_rpn_node *rpn;
1875 CCL_parser ccl_parser = ccl_parser_create(p->bibset);
1877 rpn = ccl_parser_find_str(ccl_parser, query);
1879 error_code = ccl_parser_get_error(ccl_parser, &error_pos);
1880 add_assoc_long(pval_res, "errorcode", error_code);
1884 add_assoc_string(pval_res, "errorstring",
1885 (char *) ccl_err_msg(error_code), 1);
1886 add_assoc_long(pval_res, "errorpos", error_pos);
1891 WRBUF wrbuf_pqf = wrbuf_alloc();
1892 ccl_stop_words_t csw = ccl_stop_words_create();
1893 int r = ccl_stop_words_tree(csw, p->bibset, &rpn);
1897 /* stop words were removed. Return stopwords info */
1898 zval *zval_stopwords;
1901 MAKE_STD_ZVAL(zval_stopwords);
1902 array_init(zval_stopwords);
1903 for (idx = 0; ; idx++)
1905 zval *zval_stopword;
1909 if (!ccl_stop_words_info(csw, idx, &qname, &term))
1912 MAKE_STD_ZVAL(zval_stopword);
1913 array_init(zval_stopword);
1915 add_assoc_string(zval_stopword, "field", (char *) qname, 1);
1916 add_assoc_string(zval_stopword, "term", (char *) term, 1);
1917 add_next_index_zval(zval_stopwords, zval_stopword);
1919 add_assoc_zval(pval_res, "stopwords", zval_stopwords);
1921 ccl_pquery(wrbuf_pqf, rpn);
1922 add_assoc_stringl(pval_res, "rpn",
1923 wrbuf_buf(wrbuf_pqf), wrbuf_len(wrbuf_pqf), 1);
1924 wrbuf_destroy(wrbuf_pqf);
1925 ccl_stop_words_destroy(csw);
1928 ccl_rpn_delete(rpn);
1936 /* {{{ proto bool yaz_database (resource id, string databases)
1937 Specify the databases within a session */
1938 PHP_FUNCTION(yaz_database)
1945 if (ZEND_NUM_ARGS() != 2 ||
1946 zend_parse_parameters(2 TSRMLS_CC, "zs", &pval_id,
1947 &database, &database_len) == FAILURE) {
1951 get_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU, pval_id, &p);
1952 option_set(p, "databaseName", database);
1958 /* {{{ php_yaz_init_globals
1960 static void php_yaz_init_globals(zend_yaz_globals *yaz_globals)
1962 yaz_globals->assoc_seq = 0;
1963 yaz_globals->max_links = 100;
1964 yaz_globals->keepalive = 120;
1965 yaz_globals->log_file = NULL;
1966 yaz_globals->log_mask = NULL;
1970 static void yaz_close_session(Yaz_Association *as TSRMLS_DC)
1972 if (*as && (*as)->order == YAZSG(assoc_seq)) {
1973 if ((*as)->persistent) {
1976 yaz_association_destroy(*as);
1982 static void yaz_close_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1984 Yaz_Association *as = (Yaz_Association *) rsrc->ptr;
1985 yaz_close_session(as TSRMLS_CC);
1988 /* {{{ PHP_INI_BEGIN
1991 #if PHP_MAJOR_VERSION >= 5
1992 STD_PHP_INI_ENTRY("yaz.max_links", "100", PHP_INI_ALL, OnUpdateLong, max_links, zend_yaz_globals, yaz_globals)
1994 STD_PHP_INI_ENTRY("yaz.max_links", "100", PHP_INI_ALL, OnUpdateInt, max_links, zend_yaz_globals, yaz_globals)
1996 #if PHP_MAJOR_VERSION >= 5
1997 STD_PHP_INI_ENTRY("yaz.keepalive", "120", PHP_INI_ALL, OnUpdateLong, keepalive, zend_yaz_globals, yaz_globals)
1999 STD_PHP_INI_ENTRY("yaz.keepalive", "120", PHP_INI_ALL, OnUpdateInt, keepalive, zend_yaz_globals, yaz_globals)
2001 STD_PHP_INI_ENTRY("yaz.log_file", NULL, PHP_INI_ALL, OnUpdateString, log_file, zend_yaz_globals, yaz_globals)
2002 STD_PHP_INI_ENTRY("yaz.log_mask", NULL, PHP_INI_ALL, OnUpdateString, log_mask, zend_yaz_globals, yaz_globals)
2006 PHP_MINIT_FUNCTION(yaz)
2012 yaz_mutex = tsrm_mutex_alloc();
2015 ZEND_INIT_MODULE_GLOBALS(yaz, php_yaz_init_globals, NULL);
2017 REGISTER_INI_ENTRIES();
2019 REGISTER_LONG_CONSTANT("ZOOM_EVENT_NONE", ZOOM_EVENT_NONE,
2020 CONST_CS|CONST_PERSISTENT);
2021 REGISTER_LONG_CONSTANT("ZOOM_EVENT_CONNECT", ZOOM_EVENT_CONNECT,
2022 CONST_CS|CONST_PERSISTENT);
2023 REGISTER_LONG_CONSTANT("ZOOM_EVENT_SEND_DATA", ZOOM_EVENT_SEND_DATA,
2024 CONST_CS|CONST_PERSISTENT);
2025 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_DATA", ZOOM_EVENT_RECV_DATA,
2026 CONST_CS|CONST_PERSISTENT);
2027 REGISTER_LONG_CONSTANT("ZOOM_EVENT_TIMEOUT", ZOOM_EVENT_TIMEOUT,
2028 CONST_CS|CONST_PERSISTENT);
2029 REGISTER_LONG_CONSTANT("ZOOM_EVENT_UNKNOWN", ZOOM_EVENT_UNKNOWN,
2030 CONST_CS|CONST_PERSISTENT);
2031 REGISTER_LONG_CONSTANT("ZOOM_EVENT_SEND_APDU", ZOOM_EVENT_SEND_APDU,
2032 CONST_CS|CONST_PERSISTENT);
2033 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_APDU", ZOOM_EVENT_RECV_APDU,
2034 CONST_CS|CONST_PERSISTENT);
2035 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_RECORD", ZOOM_EVENT_RECV_RECORD,
2036 CONST_CS|CONST_PERSISTENT);
2037 REGISTER_LONG_CONSTANT("ZOOM_EVENT_RECV_SEARCH", ZOOM_EVENT_RECV_SEARCH,
2038 CONST_CS|CONST_PERSISTENT);
2040 fname = YAZSG(log_file);
2041 mask = YAZSG(log_mask);
2042 if (fname && *fname)
2044 yaz_log_init_file(fname);
2047 yaz_log_init_level(yaz_log_mask_str(mask));
2050 yaz_log_init_level(0);
2052 le_link = zend_register_list_destructors_ex(yaz_close_link, 0, "YAZ link", module_number);
2054 order_associations = 1;
2055 shared_associations = xmalloc(sizeof(*shared_associations) * MAX_ASSOC);
2056 for (i = 0; i < MAX_ASSOC; i++) {
2057 shared_associations[i] = 0;
2062 PHP_MSHUTDOWN_FUNCTION(yaz)
2066 if (shared_associations) {
2067 for (i = 0; i < MAX_ASSOC; i++) {
2068 yaz_association_destroy (shared_associations[i]);
2070 xfree(shared_associations);
2071 shared_associations = 0;
2074 tsrm_mutex_free(yaz_mutex);
2077 yaz_log_init_file(0);
2079 UNREGISTER_INI_ENTRIES();
2084 PHP_MINFO_FUNCTION(yaz)
2086 char version_str[20];
2088 strcpy(version_str, "unknown");
2089 yaz_version(version_str, 0);
2090 php_info_print_table_start();
2091 php_info_print_table_row(2, "YAZ Support", "enabled");
2092 php_info_print_table_row(2, "PHP/YAZ Version", PHP_YAZ_VERSION);
2093 php_info_print_table_row(2, "YAZ Version", version_str);
2094 php_info_print_table_row(2, "Compiled with YAZ version", YAZ_VERSION);
2095 php_info_print_table_end();
2098 PHP_RSHUTDOWN_FUNCTION(yaz)
2104 tsrm_mutex_lock(yaz_mutex);
2106 for (i = 0; i < YAZSG(max_links); i++) {
2107 Yaz_Association *as = shared_associations + i;
2110 if (now - (*as)->time_stamp > YAZSG(keepalive))
2112 yaz_association_destroy(*as);
2118 tsrm_mutex_unlock(yaz_mutex);
2123 PHP_RINIT_FUNCTION(yaz)
2127 sprintf(pidstr, "%ld", (long) getpid());
2129 tsrm_mutex_lock(yaz_mutex);
2131 YAZSG(assoc_seq) = order_associations++;
2133 tsrm_mutex_unlock(yaz_mutex);
2135 yaz_log_init_prefix(pidstr);
2139 zend_module_entry yaz_module_entry = {
2140 #if ZEND_MODULE_API_NO >= 20010901
2141 STANDARD_MODULE_HEADER,
2150 #if ZEND_MODULE_API_NO >= 20010901
2153 STANDARD_MODULE_PROPERTIES
2164 * vim600: sw=4 ts=4 fdm=marker
2165 * vim<600: sw=4 ts=4