├── CREDITS
├── tests
├── skipif.inc
├── ibase_trans_001.phpt
├── ibase_close_001.phpt
├── ibase_errmsg_001.phpt
├── ibase_num_fields_001.phpt
├── bug45575.phpt
├── 002.phpt
├── ibase_trans_002.phpt
├── ibase_affected_rows_001.phpt
├── ibase_free_query_001.phpt
├── ibase_drop_db_001.phpt
├── ibase_num_params_001.phpt
├── bug46543.phpt
├── ibase_rollback_001.phpt
├── ibase_param_info_001.phpt
├── 008.phpt
├── bug46247.phpt
├── bug45373.phpt
├── interbase.inc
├── 007.phpt
├── 003.phpt
├── 005.phpt
├── 006.phpt
└── 004.phpt
├── config.w32
├── .gitignore
├── config.m4
├── LICENSE
├── php_interbase.h
├── php_ibase_includes.h
├── ibase_events.c
├── php_ibase_udf.c
├── ibase_blobs.c
├── ibase_service.c
└── interbase.c
/CREDITS:
--------------------------------------------------------------------------------
1 | InterBase
2 | Jouni Ahto, Andrew Avdeev, Ard Biesheuvel
3 |
--------------------------------------------------------------------------------
/tests/skipif.inc:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/tests/ibase_trans_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_trans(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
17 | --EXPECTF--
18 | resource(%d) of type (Firebird/InterBase transaction)
19 | resource(%d) of type (Firebird/InterBase transaction)
20 | bool(true)
21 | bool(true)
22 |
--------------------------------------------------------------------------------
/tests/ibase_close_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_close(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
17 | --EXPECTF--
18 | bool(true)
19 | bool(true)
20 | bool(true)
21 |
22 | Warning: ibase_close() expects parameter 1 to be resource, string given in %s on line %d
23 | NULL
24 |
--------------------------------------------------------------------------------
/tests/ibase_errmsg_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_errmsg(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
19 | --EXPECTF--
20 | Warning: ibase_query(): Dynamic SQL Error SQL error code = -104 %s on line %d
21 | string(%d) "Dynamic SQL Error SQL error code = -104 %s"
22 | bool(false)
23 |
--------------------------------------------------------------------------------
/tests/ibase_num_fields_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_num_fields(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
18 | --EXPECTF--
19 | int(2)
20 |
21 | Warning: ibase_num_fields() expects parameter 1 to be resource, int given in %s on line %d
22 | NULL
23 |
24 | Warning: ibase_num_fields() expects exactly 1 parameter, 0 given in %s on line %d
25 | NULL
26 |
--------------------------------------------------------------------------------
/tests/bug45575.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Bug #45575 (Segfault with invalid non-string as event handler callback)
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
19 | --EXPECTF--
20 | Warning: ibase_set_event_handler(): Callback argument is not a callable function in %s on line %d
21 |
22 | Warning: ibase_set_event_handler(): Callback argument 1 is not a callable function in %s on line %d
23 |
--------------------------------------------------------------------------------
/tests/002.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | InterBase: connect, close and pconnect
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
27 | --EXPECT--
28 | --- test1 ---
29 | 1 test table not created with isql
30 | ---
31 | --- test1 ---
32 | 1 test table not created with isql
33 | ---
34 |
--------------------------------------------------------------------------------
/tests/ibase_trans_002.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_trans(): Basic operations
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
27 | --EXPECT--
28 | int(1)
29 | array(2) {
30 | ["I"]=>
31 | int(100)
32 | ["C"]=>
33 | string(3) "100"
34 | }
35 |
--------------------------------------------------------------------------------
/tests/ibase_affected_rows_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_affected_rows(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
27 | --EXPECTF--
28 | int(3)
29 | int(0)
30 |
31 | Warning: ibase_query(): Dynamic SQL Error SQL error code = -104 %s on line %d
32 | int(0)
33 |
--------------------------------------------------------------------------------
/config.w32:
--------------------------------------------------------------------------------
1 | // vim:ft=javascript
2 |
3 | ARG_WITH("interbase", "InterBase support", "no");
4 |
5 | if (PHP_INTERBASE != "no") {
6 |
7 | if (CHECK_HEADER_ADD_INCLUDE("ibase.h", "CFLAGS_INTERBASE",
8 | PHP_PHP_BUILD + "\\include\\interbase;" + PHP_PHP_BUILD + "\\interbase\\include;" + PHP_INTERBASE) &&
9 | (CHECK_LIB("fbclient_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE) ||
10 | CHECK_LIB("gds32_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE))) {
11 |
12 | EXTENSION("interbase", "interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c", PHP_INTERBASE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
13 | AC_DEFINE('HAVE_IBASE', 1, 'Have interbase library');
14 | } else {
15 | WARNING("interbase not enabled; libraries and headers not found");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/ibase_free_query_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_free_query(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
21 | --EXPECTF--
22 | bool(true)
23 |
24 | Warning: ibase_free_query(): supplied resource is not a valid Firebird/InterBase query resource in %s on line %d
25 | bool(false)
26 |
27 | Warning: ibase_free_query(): supplied resource is not a valid Firebird/InterBase query resource in %s on line %d
28 | bool(false)
29 |
--------------------------------------------------------------------------------
/tests/ibase_drop_db_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_drop_db(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
23 | --EXPECTF--
24 | resource(%d) of type (Firebird/InterBase link)
25 | bool(true)
26 |
27 | Warning: ibase_drop_db() expects parameter 1 to be resource, int given in %s on line %d
28 | NULL
29 |
30 | Warning: ibase_drop_db() expects parameter 1 to be resource, null given in %s on line %d
31 | NULL
32 |
--------------------------------------------------------------------------------
/tests/ibase_num_params_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_num_params(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
23 | --EXPECTF--
24 | int(2)
25 |
26 | Warning: ibase_num_params() expects exactly 1 parameter, 0 given in %s on line %d
27 | NULL
28 |
29 | Warning: ibase_prepare(): Dynamic SQL Error SQL error code = -206 %s in %s on line %d
30 |
31 | Warning: ibase_num_params() expects parameter 1 to be resource, bool given in %s on line %d
32 | NULL
33 |
--------------------------------------------------------------------------------
/tests/bug46543.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Bug #46543 (ibase_trans() memory leaks when using wrong parameters)
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
21 | --EXPECTF--
22 | Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d
23 |
24 | Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d
25 |
26 | Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d
27 |
28 | Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d
29 |
--------------------------------------------------------------------------------
/tests/ibase_rollback_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_rollback(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
28 | --EXPECTF--
29 | array(1) {
30 | [0]=>
31 | int(3)
32 | }
33 | bool(true)
34 | array(1) {
35 | [0]=>
36 | int(0)
37 | }
38 | bool(true)
39 |
40 | Warning: ibase_rollback(): invalid transaction handle (expecting explicit transaction start) in %s on line %d
41 | bool(false)
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .deps
2 | .libs
3 | .php-version
4 | .rbenv-version
5 | acinclude.m4
6 | aclocal.m4
7 | autom4te.cache
8 | build
9 | config.guess
10 | config.h
11 | config.h.in
12 | config.log
13 | config.nice
14 | config.status
15 | config.sub
16 | configure
17 | configure.in
18 | configure.ac
19 | extras
20 | include
21 | install-sh
22 | libtool
23 | ltmain.sh
24 | ltmain.sh.backup
25 | Makefile
26 | Makefile.fragments
27 | Makefile.global
28 | Makefile.objects
29 | missing
30 | mkinstalldirs
31 | modules
32 | run-tests.php
33 | tmp-php.ini
34 | yaml.loT
35 |
36 | # General Ignores
37 | *~
38 | .#*
39 | *.
40 | *.slo
41 | *.mk
42 | *.mem
43 | *.gcda
44 | *.gcno
45 | *.la
46 | *.lo
47 | *.o
48 | *.a
49 | *.ncb
50 | *.opt
51 | *.plg
52 | *swp
53 | *.patch
54 | *.tgz
55 | *.tar.gz
56 | *.tar.bz2
57 | .FBCIndex
58 | .FBCLockFolder
59 | core
60 |
61 | # Test specific Ignores
62 | tests/*.diff
63 | tests/*.exp
64 | tests/*.log
65 | tests/*.out
66 | tests/*.php
67 | tests/*.sh
68 |
69 | # coverage
70 | /coverage.info
71 | /reports
72 |
--------------------------------------------------------------------------------
/tests/ibase_param_info_001.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | ibase_param_info(): Basic test
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
25 | --EXPECTF--
26 | array(10) {
27 | [0]=>
28 | string(0) ""
29 | ["name"]=>
30 | string(0) ""
31 | [1]=>
32 | string(0) ""
33 | ["alias"]=>
34 | string(0) ""
35 | [2]=>
36 | string(0) ""
37 | ["relation"]=>
38 | string(0) ""
39 | [3]=>
40 | string(1) "4"
41 | ["length"]=>
42 | string(1) "4"
43 | [4]=>
44 | string(7) "INTEGER"
45 | ["type"]=>
46 | string(7) "INTEGER"
47 | }
48 | ---
49 | bool(false)
50 | ---
51 |
52 | Warning: ibase_param_info() expects exactly 2 parameters, 1 given in %s on line %d
53 | NULL
54 |
--------------------------------------------------------------------------------
/tests/008.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | InterBase: event handling
3 | --SKIPIF--
4 |
8 | --FILE--
9 | 5) echo "FAIL ($count)\n";
44 | echo "end of test\n";
45 |
46 | ?>
47 | --EXPECT--
48 | end of test
49 |
--------------------------------------------------------------------------------
/tests/bug46247.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Bug #46247 (ibase_set_event_handler() is allowing to pass callback without event)
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
26 | --EXPECTF--
27 | Warning: Wrong parameter count for ibase_set_event_handler() in %s on line %d
28 |
29 | Warning: ibase_set_event_handler(): supplied argument is not a valid InterBase link resource in %s on line %d
30 |
31 | Warning: ibase_set_event_handler(): Callback argument foo is not a callable function in %s on line %d
32 |
33 | Warning: ibase_set_event_handler(): Callback argument foo is not a callable function in %s on line %d
34 |
35 | Warning: ibase_set_event_handler(): supplied argument is not a valid InterBase link resource in %s on line %d
36 |
--------------------------------------------------------------------------------
/tests/bug45373.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | Bug #45373 (php crash on query with errors in params)
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
28 | --EXPECTF--
29 | array(2) {
30 | ["I"]=>
31 | int(1)
32 | ["C"]=>
33 | string(32) "test table not created with isql"
34 | }
35 |
36 | Notice: ibase_execute(): Statement expects 2 arguments, 3 given in %s on line %d
37 | array(2) {
38 | ["I"]=>
39 | int(1)
40 | ["C"]=>
41 | string(32) "test table not created with isql"
42 | }
43 |
44 | Warning: ibase_execute(): Statement expects 2 arguments, 1 given in %s on line %d
45 |
46 | Warning: ibase_fetch_assoc() expects parameter 1 to be resource, bool given in %s on line %d
47 | NULL
48 |
--------------------------------------------------------------------------------
/config.m4:
--------------------------------------------------------------------------------
1 | PHP_ARG_WITH([interbase],
2 | [for Firebird support],
3 | [AS_HELP_STRING([[--with-interbase[=DIR]]],
4 | [Include Firebird support. DIR is the Firebird base install directory
5 | [/opt/firebird]])])
6 |
7 | if test "$PHP_INTERBASE" != "no"; then
8 |
9 | AC_PATH_PROG(FB_CONFIG, fb_config, no)
10 |
11 | if test -x "$FB_CONFIG" && test "$PHP_INTERBASE" = "yes"; then
12 | AC_MSG_CHECKING(for libfbconfig)
13 | FB_CFLAGS=`$FB_CONFIG --cflags`
14 | FB_LIBDIR=`$FB_CONFIG --libs`
15 | FB_VERSION=`$FB_CONFIG --version`
16 | AC_MSG_RESULT(version $FB_VERSION)
17 | PHP_EVAL_LIBLINE($FB_LIBDIR, INTERBASE_SHARED_LIBADD)
18 | PHP_EVAL_INCLINE($FB_CFLAGS)
19 |
20 | else
21 | if test "$PHP_INTERBASE" = "yes"; then
22 | IBASE_INCDIR=/opt/firebird/include
23 | IBASE_LIBDIR=/opt/firebird/lib
24 | else
25 | IBASE_INCDIR=$PHP_INTERBASE/include
26 | IBASE_LIBDIR=$PHP_INTERBASE/$PHP_LIBDIR
27 | fi
28 |
29 | PHP_CHECK_LIBRARY(fbclient, isc_detach_database,
30 | [
31 | IBASE_LIBNAME=fbclient
32 | ], [
33 | PHP_CHECK_LIBRARY(gds, isc_detach_database,
34 | [
35 | IBASE_LIBNAME=gds
36 | ], [
37 | PHP_CHECK_LIBRARY(ib_util, isc_detach_database,
38 | [
39 | IBASE_LIBNAME=ib_util
40 | ], [
41 | AC_MSG_ERROR([libfbclient, libgds or libib_util not found! Check config.log for more information.])
42 | ], [
43 | -L$IBASE_LIBDIR
44 | ])
45 | ], [
46 | -L$IBASE_LIBDIR
47 | ])
48 | ], [
49 | -L$IBASE_LIBDIR
50 | ])
51 |
52 | PHP_ADD_LIBRARY_WITH_PATH($IBASE_LIBNAME, $IBASE_LIBDIR, INTERBASE_SHARED_LIBADD)
53 | PHP_ADD_INCLUDE($IBASE_INCDIR)
54 | fi
55 |
56 | AC_DEFINE(HAVE_IBASE,1,[ ])
57 | PHP_NEW_EXTENSION(interbase, interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
58 | PHP_SUBST(INTERBASE_SHARED_LIBADD)
59 | fi
60 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | The PHP License, version 3.01
3 | Copyright (c) 1999 - 2019 The PHP Group. All rights reserved.
4 | --------------------------------------------------------------------
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, is permitted provided that the following conditions
8 | are met:
9 |
10 | 1. Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 |
13 | 2. Redistributions in binary form must reproduce the above copyright
14 | notice, this list of conditions and the following disclaimer in
15 | the documentation and/or other materials provided with the
16 | distribution.
17 |
18 | 3. The name "PHP" must not be used to endorse or promote products
19 | derived from this software without prior written permission. For
20 | written permission, please contact group@php.net.
21 |
22 | 4. Products derived from this software may not be called "PHP", nor
23 | may "PHP" appear in their name, without prior written permission
24 | from group@php.net. You may indicate that your software works in
25 | conjunction with PHP by saying "Foo for PHP" instead of calling
26 | it "PHP Foo" or "phpfoo"
27 |
28 | 5. The PHP Group may publish revised and/or new versions of the
29 | license from time to time. Each version will be given a
30 | distinguishing version number.
31 | Once covered code has been published under a particular version
32 | of the license, you may always continue to use it under the terms
33 | of that version. You may also choose to use such covered code
34 | under the terms of any subsequent version of the license
35 | published by the PHP Group. No one other than the PHP Group has
36 | the right to modify the terms applicable to covered code created
37 | under this License.
38 |
39 | 6. Redistributions of any form whatsoever must retain the following
40 | acknowledgment:
41 | "This product includes PHP software, freely available from
42 | ".
43 |
44 | THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
45 | ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
46 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
48 | DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55 | OF THE POSSIBILITY OF SUCH DAMAGE.
56 |
57 | --------------------------------------------------------------------
58 |
59 | This software consists of voluntary contributions made by many
60 | individuals on behalf of the PHP Group.
61 |
62 | The PHP Group can be contacted via Email at group@php.net.
63 |
64 | For more information on the PHP Group and the PHP project,
65 | please see .
66 |
67 | PHP includes the Zend Engine, freely available at
68 | .
69 |
--------------------------------------------------------------------------------
/tests/interbase.inc:
--------------------------------------------------------------------------------
1 |
121 |
--------------------------------------------------------------------------------
/php_interbase.h:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHP Version 7 |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 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 | | Authors: Jouni Ahto |
16 | | Andrew Avdeev |
17 | | Ard Biesheuvel |
18 | +----------------------------------------------------------------------+
19 | */
20 |
21 | #ifndef PHP_INTERBASE_H
22 | #define PHP_INTERBASE_H
23 |
24 | extern zend_module_entry ibase_module_entry;
25 | #define phpext_interbase_ptr &ibase_module_entry
26 |
27 | #include "php_version.h"
28 | #define PHP_INTERBASE_VERSION "1.0.0-dev"
29 |
30 | PHP_MINIT_FUNCTION(ibase);
31 | PHP_RINIT_FUNCTION(ibase);
32 | PHP_MSHUTDOWN_FUNCTION(ibase);
33 | PHP_RSHUTDOWN_FUNCTION(ibase);
34 | PHP_MINFO_FUNCTION(ibase);
35 |
36 | PHP_FUNCTION(ibase_connect);
37 | PHP_FUNCTION(ibase_pconnect);
38 | PHP_FUNCTION(ibase_close);
39 | PHP_FUNCTION(ibase_drop_db);
40 | PHP_FUNCTION(ibase_query);
41 | PHP_FUNCTION(ibase_fetch_row);
42 | PHP_FUNCTION(ibase_fetch_assoc);
43 | PHP_FUNCTION(ibase_fetch_object);
44 | PHP_FUNCTION(ibase_free_result);
45 | PHP_FUNCTION(ibase_name_result);
46 | PHP_FUNCTION(ibase_prepare);
47 | PHP_FUNCTION(ibase_execute);
48 | PHP_FUNCTION(ibase_free_query);
49 |
50 | PHP_FUNCTION(ibase_timefmt);
51 |
52 | PHP_FUNCTION(ibase_gen_id);
53 | PHP_FUNCTION(ibase_num_fields);
54 | PHP_FUNCTION(ibase_num_params);
55 | #if abies_0
56 | PHP_FUNCTION(ibase_num_rows);
57 | #endif
58 | PHP_FUNCTION(ibase_affected_rows);
59 | PHP_FUNCTION(ibase_field_info);
60 | PHP_FUNCTION(ibase_param_info);
61 |
62 | PHP_FUNCTION(ibase_trans);
63 | PHP_FUNCTION(ibase_commit);
64 | PHP_FUNCTION(ibase_rollback);
65 | PHP_FUNCTION(ibase_commit_ret);
66 | PHP_FUNCTION(ibase_rollback_ret);
67 |
68 | PHP_FUNCTION(ibase_blob_create);
69 | PHP_FUNCTION(ibase_blob_add);
70 | PHP_FUNCTION(ibase_blob_cancel);
71 | PHP_FUNCTION(ibase_blob_open);
72 | PHP_FUNCTION(ibase_blob_get);
73 | PHP_FUNCTION(ibase_blob_close);
74 | PHP_FUNCTION(ibase_blob_echo);
75 | PHP_FUNCTION(ibase_blob_info);
76 | PHP_FUNCTION(ibase_blob_import);
77 |
78 | PHP_FUNCTION(ibase_add_user);
79 | PHP_FUNCTION(ibase_modify_user);
80 | PHP_FUNCTION(ibase_delete_user);
81 |
82 | PHP_FUNCTION(ibase_service_attach);
83 | PHP_FUNCTION(ibase_service_detach);
84 | PHP_FUNCTION(ibase_backup);
85 | PHP_FUNCTION(ibase_restore);
86 | PHP_FUNCTION(ibase_maintain_db);
87 | PHP_FUNCTION(ibase_db_info);
88 | PHP_FUNCTION(ibase_server_info);
89 |
90 | PHP_FUNCTION(ibase_errmsg);
91 | PHP_FUNCTION(ibase_errcode);
92 |
93 | PHP_FUNCTION(ibase_wait_event);
94 | PHP_FUNCTION(ibase_set_event_handler);
95 | PHP_FUNCTION(ibase_free_event_handler);
96 |
97 | #else
98 |
99 | #define phpext_interbase_ptr NULL
100 |
101 | #endif /* PHP_INTERBASE_H */
102 |
--------------------------------------------------------------------------------
/tests/007.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | InterBase: array handling
3 | --SKIPIF--
4 |
5 | --FILE--
6 | V_CHAR[$i],$v_char[$i],strlen($v_char[$i])) != 0) {
78 | echo " CHAR[$i] fail:\n";
79 | echo " in: ".$v_char[$i]."\n";
80 | echo " out: ".$row->V_CHAR[$i]."\n";
81 | }
82 | if($row->V_DATE[$i] != $v_date[$i]) {
83 | echo " DATE[$i] fail\n";
84 | echo " in: ".$v_date[$i]."\n";
85 | echo " out: ".$row->V_DATE[$i]."\n";
86 | }
87 | if($row->V_DECIMAL[$i] != $v_decimal[$i]) {
88 | echo " DECIMAL[$i] fail\n";
89 | echo " in: ".$v_decimal[$i]."\n";
90 | echo " out: ".$row->V_DECIMAL[$i]."\n";
91 | }
92 | if(abs($row->V_DOUBLE[$i] - $v_double[$i]) > abs($v_double[$i] / 1E15)) {
93 | echo " DOUBLE[$i] fail\n";
94 | echo " in: ".$v_double[$i]."\n";
95 | echo " out: ".$row->V_DOUBLE[$i]."\n";
96 | }
97 | if(abs($row->V_FLOAT[$i] - $v_float[$i]) > abs($v_float[$i] / 1E7)) {
98 | echo " FLOAT[$i] fail\n";
99 | echo " in: ".$v_float[$i]."\n";
100 | echo " out: ".$row->V_FLOAT[$i]."\n";
101 | }
102 | if($row->V_INTEGER[$i] != $v_integer[$i]) {
103 | echo " INTEGER[$i] fail\n";
104 | echo " in: ".$v_integer[$i]."\n";
105 | echo " out: ".$row->V_INTEGER[$i]."\n";
106 | }
107 | if ($row->V_NUMERIC[$i] != $v_numeric[$i]) {
108 | echo " NUMERIC[$i] fail\n";
109 | echo " in: ".$v_numeric[$i]."\n";
110 | echo " out: ".$row->V_NUMERIC[$i]."\n";
111 | }
112 | if ($row->V_SMALLINT[$i] != $v_smallint[$i]) {
113 | echo " SMALLINT[$i] fail\n";
114 | echo " in: ".$v_smallint[$i]."\n";
115 | echo " out: ".$row->V_SMALLINT[$i]."\n";
116 | }
117 | if ($row->V_VARCHAR[$i] != $v_varchar[$i]) {
118 | echo " VARCHAR[$i] fail:\n";
119 | echo " in: ".$v_varchar[$i]."\n";
120 | echo " out: ".$row->V_VARCHAR[$i]."\n";
121 | }
122 | }
123 | ibase_free_result($sel);
124 | }/* for($iter) */
125 |
126 | echo "select\n";
127 |
128 | $sel = ibase_query("SELECT v_multi[5,5,5],v_multi[10,10,10] FROM test7 WHERE iter = 0");
129 | print_r(ibase_fetch_row($sel));
130 | ibase_free_result($sel);
131 |
132 | for($iter = 1; $iter <= 3; $iter++) {
133 |
134 | if(!($sel = ibase_query(
135 | "select iter from test7 where v_char[$iter] LIKE ?", $v_char[$iter]."%")) ||
136 | !ibase_fetch_row($sel)) {
137 | echo "CHAR fail\n";
138 | }
139 | ibase_free_result($sel);
140 |
141 | if(!($sel = ibase_query(
142 | "select iter from test7 where v_date[$iter] = ?", $v_date[$iter])) ||
143 | !ibase_fetch_row($sel)) {
144 | echo "DATE fail\n";
145 | }
146 | ibase_free_result($sel);
147 | if(!($sel = ibase_query(
148 | "select iter from test7 where v_decimal[$iter] = ?", $v_decimal[$iter])) ||
149 | !ibase_fetch_row($sel)) {
150 | echo "DECIMAL fail\n";
151 | }
152 | ibase_free_result($sel);
153 | if(!($sel = ibase_query(
154 | "select iter from test7 where v_integer[$iter] = ?", $v_integer[$iter])) ||
155 | !ibase_fetch_row($sel)) {
156 | echo "INTEGER fail\n";
157 | }
158 | ibase_free_result($sel);
159 | if(!($sel = ibase_query(
160 | "select iter from test7 where v_numeric[$iter] = ?", $v_numeric[$iter])) ||
161 | !ibase_fetch_row($sel)) {
162 | echo "NUMERIC fail\n";
163 | }
164 | ibase_free_result($sel);
165 | if(!($sel = ibase_query(
166 | "select iter from test7 where v_smallint[$iter] = ?", $v_smallint[$iter])) ||
167 | !ibase_fetch_row($sel)) {
168 | echo "SMALLINT fail\n";
169 | }
170 | ibase_free_result($sel);
171 | }
172 | ibase_close();
173 | echo "end of test\n";
174 | ?>
175 | --EXPECT--
176 | insert
177 | select
178 | Array
179 | (
180 | [0] => 125
181 | [1] => 1000
182 | )
183 | end of test
184 |
--------------------------------------------------------------------------------
/tests/003.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | InterBase: misc sql types (may take a while)
3 | --SKIPIF--
4 |
5 | --FILE--
6 | V_CHAR,0,strlen($v_char)) != $v_char){
58 | echo " CHAR fail:\n";
59 | echo " in: $v_char\n";
60 | echo " out: $row->V_CHAR\n";
61 | }
62 | if($row->V_DATE != $v_date){
63 | echo " DATE fail\n";
64 | echo " in: $v_date\n";
65 | echo " out: $row->V_DATE\n";
66 | }
67 | if($row->V_DECIMAL4_2 != $v_decimal4_2){
68 | echo " DECIMAL4_2 fail\n";
69 | echo " in: $v_decimal4_2\n";
70 | echo " out: $row->V_DECIMAL4_2\n";
71 | }
72 | if($row->V_DECIMAL4_0 != $v_decimal4_0){
73 | echo " DECIMAL4_0 fail\n";
74 | echo " in: $v_decimal4_0\n";
75 | echo " out: $row->V_DECIMAL4_0\n";
76 | }
77 | if($row->V_DECIMAL7_2 != $v_decimal7_2){
78 | echo " DECIMAL7_2 fail\n";
79 | echo " in: $v_decimal7_2\n";
80 | echo " out: $row->V_DECIMAL7_2\n";
81 | }
82 | if($row->V_DECIMAL7_0 != $v_decimal7_0){
83 | echo " DECIMAL7_0 fail\n";
84 | echo " in: $v_decimal7_0\n";
85 | echo " out: $row->V_DECIMAL7_0\n";
86 | }
87 | if($row->V_NUMERIC15_15 != $v_numeric15_15){
88 | echo " NUMERIC15_15 fail\n";
89 | echo " in: $v_numeric15_15\n";
90 | echo " out: $row->V_NUMERIC15_15\n";
91 | }
92 | if($row->V_NUMERIC15_0 != (string)$v_numeric15_0){
93 | echo " NUMERIC15_0 fail\n";
94 | echo " in: $v_numeric15_0\n";
95 | echo " out: $row->V_NUMERIC15_0\n";
96 | }
97 |
98 | if(abs($row->V_DOUBLE - $v_double) > abs($v_double / 1E15)){
99 | echo " DOUBLE fail\n";
100 | echo " in: $v_double\n";
101 | echo " out: $row->V_DOUBLE\n";
102 | }
103 | if(abs($row->V_FLOAT - $v_float) > abs($v_float / 1E7)){
104 | echo " FLOAT fail\n";
105 | echo " in: $v_float\n";
106 | echo " out: $row->V_FLOAT\n";
107 | }
108 | if($row->V_INTEGER != $v_integer){
109 | echo " INTEGER fail\n";
110 | echo " in: $v_integer\n";
111 | echo " out: $row->V_INTEGER\n";
112 | }
113 | if($row->V_SMALLINT != $v_smallint){
114 | echo " SMALLINT fail\n";
115 | echo " in: $v_smallint\n";
116 | echo " out: $row->V_SMALLINT\n";
117 | }
118 |
119 | if(substr($row->V_VARCHAR,0,strlen($v_varchar)) != $v_varchar){
120 | echo " VARCHAR fail:\n";
121 | echo " in: $v_varchar\n";
122 | echo " out: $row->V_VARCHAR\n";
123 | }
124 |
125 | ibase_free_result($sel);
126 | } /* for($iter) */
127 |
128 | /* check for correct handling of duplicate field names */
129 | $q = ibase_query('SELECT 1 AS id, 2 AS id, 3 AS id, 4 AS id, 5 AS id, 6 AS id, 7 AS id, 8 AS id, 9 AS id,
130 | 10 AS id, 11 AS id, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 FROM rdb$database');
131 | var_dump(ibase_fetch_assoc($q));
132 |
133 | ibase_close();
134 | echo "end of test\n";
135 | ?>
136 | --EXPECT--
137 | array(22) {
138 | ["ID"]=>
139 | int(1)
140 | ["ID_01"]=>
141 | int(2)
142 | ["ID_02"]=>
143 | int(3)
144 | ["ID_03"]=>
145 | int(4)
146 | ["ID_04"]=>
147 | int(5)
148 | ["ID_05"]=>
149 | int(6)
150 | ["ID_06"]=>
151 | int(7)
152 | ["ID_07"]=>
153 | int(8)
154 | ["ID_08"]=>
155 | int(9)
156 | ["ID_09"]=>
157 | int(10)
158 | ["ID_10"]=>
159 | int(11)
160 | ["CONSTANT"]=>
161 | int(12)
162 | ["CONSTANT_01"]=>
163 | int(13)
164 | ["CONSTANT_02"]=>
165 | int(14)
166 | ["CONSTANT_03"]=>
167 | int(15)
168 | ["CONSTANT_04"]=>
169 | int(16)
170 | ["CONSTANT_05"]=>
171 | int(17)
172 | ["CONSTANT_06"]=>
173 | int(18)
174 | ["CONSTANT_07"]=>
175 | int(19)
176 | ["CONSTANT_08"]=>
177 | int(20)
178 | ["CONSTANT_09"]=>
179 | int(21)
180 | ["CONSTANT_10"]=>
181 | int(22)
182 | }
183 | end of test
184 |
--------------------------------------------------------------------------------
/php_ibase_includes.h:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHP Version 7 |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 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 | | Authors: Jouni Ahto |
16 | | Andrew Avdeev |
17 | | Ard Biesheuvel |
18 | +----------------------------------------------------------------------+
19 | */
20 |
21 | #ifndef PHP_IBASE_INCLUDES_H
22 | #define PHP_IBASE_INCLUDES_H
23 |
24 | #include
25 |
26 | #ifndef SQLDA_CURRENT_VERSION
27 | #define SQLDA_CURRENT_VERSION SQLDA_VERSION1
28 | #endif
29 |
30 | #ifndef METADATALENGTH
31 | #define METADATALENGTH 68
32 | #endif
33 |
34 | #define RESET_ERRMSG do { IBG(errmsg)[0] = '\0'; IBG(sql_code) = 0; } while (0)
35 |
36 | #define IB_STATUS (IBG(status))
37 |
38 | #ifdef IBASE_DEBUG
39 | #define IBDEBUG(a) php_printf("::: %s (%d)\n", a, __LINE__);
40 | #endif
41 |
42 | #ifndef IBDEBUG
43 | #define IBDEBUG(a)
44 | #endif
45 |
46 | extern int le_link, le_plink, le_trans;
47 |
48 | #define LE_LINK "Firebird/InterBase link"
49 | #define LE_PLINK "Firebird/InterBase persistent link"
50 | #define LE_TRANS "Firebird/InterBase transaction"
51 |
52 | #define IBASE_MSGSIZE 512
53 | #define MAX_ERRMSG (IBASE_MSGSIZE*2)
54 |
55 | #define IB_DEF_DATE_FMT "%Y-%m-%d"
56 | #define IB_DEF_TIME_FMT "%H:%M:%S"
57 |
58 | /* this value should never be > USHRT_MAX */
59 | #define IBASE_BLOB_SEG 4096
60 |
61 | ZEND_BEGIN_MODULE_GLOBALS(ibase)
62 | ISC_STATUS status[20];
63 | zend_resource *default_link;
64 | zend_long num_links, num_persistent;
65 | char errmsg[MAX_ERRMSG];
66 | zend_long sql_code;
67 | ZEND_END_MODULE_GLOBALS(ibase)
68 |
69 | ZEND_EXTERN_MODULE_GLOBALS(ibase)
70 |
71 | typedef struct {
72 | isc_db_handle handle;
73 | struct tr_list *tr_list;
74 | unsigned short dialect;
75 | struct event *event_head;
76 | } ibase_db_link;
77 |
78 | typedef struct {
79 | isc_tr_handle handle;
80 | unsigned short link_cnt;
81 | unsigned long affected_rows;
82 | ibase_db_link *db_link[1]; /* last member */
83 | } ibase_trans;
84 |
85 | typedef struct tr_list {
86 | ibase_trans *trans;
87 | struct tr_list *next;
88 | } ibase_tr_list;
89 |
90 | typedef struct {
91 | isc_blob_handle bl_handle;
92 | unsigned short type;
93 | ISC_QUAD bl_qd;
94 | } ibase_blob;
95 |
96 | typedef struct event {
97 | ibase_db_link *link;
98 | zend_resource* link_res;
99 | ISC_LONG event_id;
100 | unsigned short event_count;
101 | char **events;
102 | char *event_buffer, *result_buffer;
103 | zval callback;
104 | void *thread_ctx;
105 | struct event *event_next;
106 | enum event_state { NEW, ACTIVE, DEAD } state;
107 | } ibase_event;
108 |
109 | enum php_interbase_option {
110 | PHP_IBASE_DEFAULT = 0,
111 | PHP_IBASE_CREATE = 0,
112 | /* fetch flags */
113 | PHP_IBASE_FETCH_BLOBS = 1,
114 | PHP_IBASE_FETCH_ARRAYS = 2,
115 | PHP_IBASE_UNIXTIME = 4,
116 | /* transaction access mode */
117 | PHP_IBASE_WRITE = 1,
118 | PHP_IBASE_READ = 2,
119 | /* transaction isolation level */
120 | PHP_IBASE_CONCURRENCY = 4,
121 | PHP_IBASE_COMMITTED = 8,
122 | PHP_IBASE_REC_NO_VERSION = 32,
123 | PHP_IBASE_REC_VERSION = 64,
124 | PHP_IBASE_CONSISTENCY = 16,
125 | /* transaction lock resolution */
126 | PHP_IBASE_WAIT = 128,
127 | PHP_IBASE_NOWAIT = 256
128 | };
129 |
130 | #define IBG(v) ZEND_MODULE_GLOBALS_ACCESSOR(ibase, v)
131 |
132 | #if defined(ZTS) && defined(COMPILE_DL_INTERBASE)
133 | ZEND_TSRMLS_CACHE_EXTERN()
134 | #endif
135 |
136 | #define BLOB_ID_LEN 18
137 | #define BLOB_ID_MASK "0x%" LL_MASK "x"
138 |
139 | #define BLOB_INPUT 1
140 | #define BLOB_OUTPUT 2
141 |
142 | #ifdef PHP_WIN32
143 | #define LL_MASK "I64"
144 | #define LL_LIT(lit) lit ## I64
145 | typedef void (__stdcall *info_func_t)(char*);
146 | #else
147 | #define LL_MASK "ll"
148 | #define LL_LIT(lit) lit ## ll
149 | typedef void (*info_func_t)(char*);
150 | #endif
151 |
152 | void _php_ibase_error(void);
153 | void _php_ibase_module_error(char *, ...)
154 | PHP_ATTRIBUTE_FORMAT(printf,1,2);
155 |
156 | /* determine if a resource is a link or transaction handle */
157 | #define PHP_IBASE_LINK_TRANS(zv, lh, th) \
158 | do { \
159 | if (!zv) { \
160 | lh = (ibase_db_link *)zend_fetch_resource2( \
161 | IBG(default_link), "InterBase link", le_link, le_plink); \
162 | } else { \
163 | _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, zv, &lh, &th); \
164 | } \
165 | if (SUCCESS != _php_ibase_def_trans(lh, &th)) { RETURN_FALSE; } \
166 | } while (0)
167 |
168 | int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans);
169 | void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, zval *link_id,
170 | ibase_db_link **ib_link, ibase_trans **trans);
171 |
172 | /* provided by ibase_query.c */
173 | void php_ibase_query_minit(INIT_FUNC_ARGS);
174 |
175 | /* provided by ibase_blobs.c */
176 | void php_ibase_blobs_minit(INIT_FUNC_ARGS);
177 | int _php_ibase_string_to_quad(char const *id, ISC_QUAD *qd);
178 | zend_string *_php_ibase_quad_to_string(ISC_QUAD const qd);
179 | int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, zend_ulong max_len);
180 | int _php_ibase_blob_add(zval *string_arg, ibase_blob *ib_blob);
181 |
182 | /* provided by ibase_events.c */
183 | void php_ibase_events_minit(INIT_FUNC_ARGS);
184 | void _php_ibase_free_event(ibase_event *event);
185 |
186 | /* provided by ibase_service.c */
187 | void php_ibase_service_minit(INIT_FUNC_ARGS);
188 |
189 | #ifndef max
190 | #define max(a,b) ((a)>(b)?(a):(b))
191 | #endif
192 |
193 | #endif /* PHP_IBASE_INCLUDES_H */
194 |
--------------------------------------------------------------------------------
/tests/005.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | InterBase: transactions
3 | --SKIPIF--
4 |
5 | --FILE--
6 |
210 | --EXPECTF--
211 | default transaction:
212 | empty table
213 | --- test5 ---
214 | ---
215 | one row
216 | --- test5 ---
217 | 1
218 | ---
219 | after rollback table empty again
220 | --- test5 ---
221 | ---
222 | one row
223 | --- test5 ---
224 | 2
225 | ---
226 | one row
227 | --- test5 ---
228 | 2
229 | ---
230 | one row... again.
231 | --- test5 ---
232 | 2
233 | ---
234 | one row.
235 | --- test5 ---
236 | 2
237 | ---
238 | one row
239 | --- test5 ---
240 | 2
241 | ---
242 | two rows
243 | --- test5 ---
244 | 2
245 | 3
246 | ---
247 | two rows again
248 | --- test5 ---
249 | 2
250 | 4
251 | ---
252 | one row in second transaction
253 | --- test5 ---
254 | 2
255 | ---
256 | three rows in third transaction
257 | --- test5 ---
258 | 2
259 | 3
260 | 4
261 | ---
262 | three rows in fourth transaction with deadlock
263 | --- test5 ---
264 | 2
265 | 3
266 | 4
267 | errmsg [lock conflict on no wait transaction deadlock %a]
268 | ---
269 | three rows
270 | --- test5 ---
271 | 2
272 | 3
273 | 4
274 | ---
275 | four rows
276 | --- test5 ---
277 | 2
278 | 3
279 | 4
280 | 5
281 | ---
282 | four rows again
283 | --- test5 ---
284 | 2
285 | 3
286 | 4
287 | 5
288 | ---
289 | end of test
290 |
--------------------------------------------------------------------------------
/tests/006.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | InterBase: binding (may take a while)
3 | --SKIPIF--
4 |
5 | --FILE--
6 | V_CHAR,0,strlen($v_char)) != $v_char) {
61 | echo " CHAR fail:\n";
62 | echo " in: $v_char\n";
63 | echo " out: $row->V_CHAR\n";
64 | }
65 | if($row->V_DATE != $v_date) {
66 | echo " DATE fail\n";
67 | echo " in: $v_date\n";
68 | echo " out: $row->V_DATE\n";
69 | }
70 | if($row->V_DECIMAL != $v_decimal) {
71 | echo " DECIMAL fail\n";
72 | echo " in: $v_decimal\n";
73 | echo " out: $row->V_DECIMAL\n";
74 | }
75 | if(abs($row->V_DOUBLE - $v_double) > abs($v_double / 1E15)) {
76 | echo " DOUBLE fail\n";
77 | echo " in: $v_double\n";
78 | echo " out: $row->V_DOUBLE\n";
79 | }
80 | if(abs($row->V_FLOAT - $v_float) > abs($v_float / 1E7)) {
81 | echo " FLOAT fail\n";
82 | echo " in: $v_float\n";
83 | echo " out: $row->V_FLOAT\n";
84 | }
85 | if($row->V_INTEGER != $v_integer) {
86 | echo " INTEGER fail\n";
87 | echo " in: $v_integer\n";
88 | echo " out: $row->V_INTEGER\n";
89 | }
90 | if ($row->V_NUMERIC != $v_numeric) {
91 | echo " NUMERIC fail\n";
92 | echo " in: $v_numeric\n";
93 | echo " out: $row->V_NUMERIC\n";
94 | }
95 | if ($row->V_SMALLINT != $v_smallint) {
96 | echo " SMALLINT fail\n";
97 | echo " in: $v_smallint\n";
98 | echo " out: $row->V_SMALLINT\n";
99 | }
100 | if ($row->V_VARCHAR != $v_varchar) {
101 | echo " VARCHAR fail:\n";
102 | echo " in: $v_varchar\n";
103 | echo " out: $row->V_VARCHAR\n";
104 | }
105 | ibase_free_result($sel);
106 | }/* for($iter)*/
107 |
108 | echo "select\n";
109 | for($iter = 0; $iter < 3; $iter++) {
110 | /* prepare data */
111 | $v_char = rand_str(1000);
112 | $v_date = (int)rand_number(10,0,0);
113 | $v_decimal = rand_number(12,3);
114 | $v_double = rand_number(20);
115 | $v_float = rand_number(7);
116 | $v_integer = rand_number(9,0);
117 | $v_numeric = rand_number(4,2);
118 | $v_smallint = rand_number(5) % 32767;
119 | $v_varchar = rand_str(10000);
120 |
121 | /* clear table*/
122 | ibase_query("delete from test6");
123 |
124 | /* make one record */
125 | ibase_query("insert into test6
126 | (iter, v_char,v_date,v_decimal,
127 | v_integer,v_numeric,v_smallint,v_varchar)
128 | values (666, '$v_char',?,$v_decimal, $v_integer,
129 | $v_numeric, $v_smallint, '$v_varchar')",$v_date);
130 |
131 | /* test all types */
132 | if(!($sel = ibase_query(
133 | "select iter from test6 where v_char = ?", $v_char)) ||
134 | !ibase_fetch_row($sel)) {
135 | echo "CHAR fail\n";
136 | }
137 | ibase_free_result($sel);
138 | if(!($sel = ibase_query(
139 | "select iter from test6 where v_date = ?", $v_date)) ||
140 | !ibase_fetch_row($sel)) {
141 | echo "DATE fail\n";
142 | }
143 | ibase_free_result($sel);
144 | if(!($sel = ibase_query(
145 | "select iter from test6 where v_decimal = ?", $v_decimal)) ||
146 | !ibase_fetch_row($sel)) {
147 | echo "DECIMAL fail\n";
148 | }
149 | ibase_free_result($sel);
150 | if(!($sel = ibase_query(
151 | "select iter from test6 where v_integer = ?", $v_integer)) ||
152 | !ibase_fetch_row($sel)) {
153 | echo "INTEGER fail\n";
154 | }
155 | ibase_free_result($sel);
156 | if(!($sel = ibase_query(
157 | "select iter from test6 where v_numeric = ?", $v_numeric)) ||
158 | !ibase_fetch_row($sel)) {
159 | echo "NUMERIC fail\n";
160 | }
161 | ibase_free_result($sel);
162 | if(!($sel = ibase_query(
163 | "select iter from test6 where v_smallint = ?", $v_smallint)) ||
164 | !ibase_fetch_row($sel)) {
165 | echo "SMALLINT fail\n";
166 | }
167 | ibase_free_result($sel);
168 | if(!($sel = ibase_query(
169 | "select iter from test6 where v_varchar = ?", $v_varchar)) ||
170 | !ibase_fetch_row($sel)) {
171 | echo "VARCHAR fail\n";
172 | }
173 | ibase_free_result($sel);
174 |
175 | } /*for iter*/
176 |
177 | echo "prepare and exec insert\n";
178 |
179 | /* prepare table */
180 | ibase_query("delete from test6");
181 |
182 | /* prepare query */
183 | $query = ibase_prepare(
184 | "insert into test6 (v_integer) values (?)");
185 |
186 | for($i = 0; $i < 10; $i++) {
187 | ibase_execute($query, $i);
188 | }
189 |
190 | out_table("test6");
191 |
192 | ibase_free_query($query);
193 |
194 | echo "prepare and exec select\n";
195 |
196 | /* prepare query */
197 | $query = ibase_prepare("select * from test6
198 | where v_integer between ? and ?");
199 |
200 | $low_border = 2;
201 | $high_border = 6;
202 |
203 | $res = ibase_execute($query, $low_border, $high_border);
204 | out_result($res, "test6");
205 | ibase_free_result($res);
206 |
207 | $low_border = 0;
208 | $high_border = 4;
209 | $res = ibase_execute($query, $low_border, $high_border);
210 | out_result($res, "test6");
211 | ibase_free_result($res);
212 |
213 | $res = ibase_execute($query, "5", 7.499);
214 | out_result($res, "test6");
215 | ibase_free_result($res);
216 |
217 | ibase_free_query($query);
218 |
219 | /* test execute procedure */
220 | $query = ibase_prepare("execute procedure add1(?)");
221 | $res = array();
222 | for ($i = 0; $i < 10; $i++) {
223 | $res[] = ibase_execute($query,$i);
224 | }
225 | ibase_free_query($query);
226 | foreach ($res as $r) {
227 | out_result($r, "proc add1");
228 | ibase_free_result($r);
229 | }
230 |
231 | ibase_close();
232 | echo "end of test\n";
233 | ?>
234 | --EXPECT--
235 | insert
236 | select
237 | prepare and exec insert
238 | --- test6 ---
239 | 0
240 | 1
241 | 2
242 | 3
243 | 4
244 | 5
245 | 6
246 | 7
247 | 8
248 | 9
249 | ---
250 | prepare and exec select
251 | --- test6 ---
252 | 2
253 | 3
254 | 4
255 | 5
256 | 6
257 | ---
258 | --- test6 ---
259 | 0
260 | 1
261 | 2
262 | 3
263 | 4
264 | ---
265 | --- test6 ---
266 | 5
267 | 6
268 | 7
269 | ---
270 | --- proc add1 ---
271 | 1
272 | ---
273 | --- proc add1 ---
274 | 2
275 | ---
276 | --- proc add1 ---
277 | 3
278 | ---
279 | --- proc add1 ---
280 | 4
281 | ---
282 | --- proc add1 ---
283 | 5
284 | ---
285 | --- proc add1 ---
286 | 6
287 | ---
288 | --- proc add1 ---
289 | 7
290 | ---
291 | --- proc add1 ---
292 | 8
293 | ---
294 | --- proc add1 ---
295 | 9
296 | ---
297 | --- proc add1 ---
298 | 10
299 | ---
300 | end of test
301 |
--------------------------------------------------------------------------------
/tests/004.phpt:
--------------------------------------------------------------------------------
1 | --TEST--
2 | InterBase: BLOB test
3 | --SKIPIF--
4 |
5 | --FILE--
6 | V_BLOB);
40 |
41 | $blob = '';
42 | while($piece = ibase_blob_get($bl_h, 1 + rand() % 1024))
43 | $blob .= $piece;
44 | if($blob != $blob_str)
45 | echo " BLOB 1 fail (1)\n";
46 | ibase_blob_close($bl_h);
47 |
48 | $bl_h = ibase_blob_open($link,$row->V_BLOB);
49 |
50 | $blob = '';
51 | while($piece = ibase_blob_get($bl_h, 100 * 1024))
52 | $blob .= $piece;
53 | if($blob != $blob_str)
54 | echo " BLOB 1 fail (2)\n";
55 | ibase_blob_close($bl_h);
56 | ibase_free_result($q);
57 | unset($blob);
58 |
59 | echo "create blob 2\n";
60 |
61 | ibase_query("INSERT INTO test4 (v_integer, v_blob) VALUES (2, ?)", $blob_str);
62 |
63 | echo "test blob 2\n";
64 |
65 | $q = ibase_query("SELECT v_blob FROM test4 WHERE v_integer = 2");
66 | $row = ibase_fetch_object($q,IBASE_TEXT);
67 |
68 | if($row->V_BLOB != $blob_str)
69 | echo " BLOB 2 fail\n";
70 | ibase_free_result($q);
71 | unset($blob);
72 |
73 |
74 | echo "create blob 3\n";
75 |
76 | $bl_h = ibase_blob_create($link);
77 |
78 | ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n");
79 | ibase_blob_add($bl_h, "| PHP HTML Embedded Scripting Language Version 3.0 |\n");
80 | ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n");
81 | ibase_blob_add($bl_h, "| Copyright (c) 1997-2000 PHP Development Team (See Credits file) |\n");
82 | ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n");
83 | ibase_blob_add($bl_h, "| This program is free software; you can redistribute it and/or modify |\n");
84 | ibase_blob_add($bl_h, "| it under the terms of one of the following licenses: |\n");
85 | ibase_blob_add($bl_h, "| |\n");
86 | ibase_blob_add($bl_h, "| A) the GNU General Public License as published by the Free Software |\n");
87 | ibase_blob_add($bl_h, "| Foundation; either version 2 of the License, or (at your option) |\n");
88 | ibase_blob_add($bl_h, "| any later version. |\n");
89 | ibase_blob_add($bl_h, "| |\n");
90 | ibase_blob_add($bl_h, "| B) the PHP License as published by the PHP Development Team and |\n");
91 | ibase_blob_add($bl_h, "| included in the distribution in the file: LICENSE |\n");
92 | ibase_blob_add($bl_h, "| |\n");
93 | ibase_blob_add($bl_h, "| This program is distributed in the hope that it will be useful, |\n");
94 | ibase_blob_add($bl_h, "| but WITHOUT ANY WARRANTY; without even the implied warranty of |\n");
95 | ibase_blob_add($bl_h, "| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |\n");
96 | ibase_blob_add($bl_h, "| GNU General Public License for more details. |\n");
97 | ibase_blob_add($bl_h, "| |\n");
98 | ibase_blob_add($bl_h, "| You should have received a copy of both licenses referred to here. |\n");
99 | ibase_blob_add($bl_h, "| If you did not, or have any questions about PHP licensing, please |\n");
100 | ibase_blob_add($bl_h, "| contact core@php.net. |\n");
101 | ibase_blob_add($bl_h, "+----------------------------------------------------------------------+\n");
102 | $bl_s = ibase_blob_close($bl_h);
103 | ibase_query("INSERT INTO test4 (v_integer, v_blob) VALUES (3, ?)", $bl_s);
104 | ibase_commit();
105 | echo "echo blob 3\n";
106 |
107 | $q = ibase_query("SELECT v_blob FROM test4 WHERE v_integer = 3");
108 | $row = ibase_fetch_object($q);
109 | ibase_commit();
110 | ibase_close();
111 |
112 | $link = ibase_connect($test_base);
113 | ibase_blob_echo($link, $row->V_BLOB);
114 | ibase_free_result($q);
115 |
116 | echo "fetch blob 3\n";
117 | $q = ibase_query("SELECT v_blob FROM test4 WHERE v_integer = 3");
118 | $row = ibase_fetch_object($q,IBASE_TEXT);
119 | echo $row->V_BLOB;
120 | ibase_free_result($q);
121 |
122 | ibase_close();
123 | unlink($name);
124 | echo "end of test\n";
125 | ?>
126 | --EXPECT--
127 | import blob 1
128 | test blob 1
129 | create blob 2
130 | test blob 2
131 | create blob 3
132 | echo blob 3
133 | +----------------------------------------------------------------------+
134 | | PHP HTML Embedded Scripting Language Version 3.0 |
135 | +----------------------------------------------------------------------+
136 | | Copyright (c) 1997-2000 PHP Development Team (See Credits file) |
137 | +----------------------------------------------------------------------+
138 | | This program is free software; you can redistribute it and/or modify |
139 | | it under the terms of one of the following licenses: |
140 | | |
141 | | A) the GNU General Public License as published by the Free Software |
142 | | Foundation; either version 2 of the License, or (at your option) |
143 | | any later version. |
144 | | |
145 | | B) the PHP License as published by the PHP Development Team and |
146 | | included in the distribution in the file: LICENSE |
147 | | |
148 | | This program is distributed in the hope that it will be useful, |
149 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
150 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
151 | | GNU General Public License for more details. |
152 | | |
153 | | You should have received a copy of both licenses referred to here. |
154 | | If you did not, or have any questions about PHP licensing, please |
155 | | contact core@php.net. |
156 | +----------------------------------------------------------------------+
157 | fetch blob 3
158 | +----------------------------------------------------------------------+
159 | | PHP HTML Embedded Scripting Language Version 3.0 |
160 | +----------------------------------------------------------------------+
161 | | Copyright (c) 1997-2000 PHP Development Team (See Credits file) |
162 | +----------------------------------------------------------------------+
163 | | This program is free software; you can redistribute it and/or modify |
164 | | it under the terms of one of the following licenses: |
165 | | |
166 | | A) the GNU General Public License as published by the Free Software |
167 | | Foundation; either version 2 of the License, or (at your option) |
168 | | any later version. |
169 | | |
170 | | B) the PHP License as published by the PHP Development Team and |
171 | | included in the distribution in the file: LICENSE |
172 | | |
173 | | This program is distributed in the hope that it will be useful, |
174 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
175 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
176 | | GNU General Public License for more details. |
177 | | |
178 | | You should have received a copy of both licenses referred to here. |
179 | | If you did not, or have any questions about PHP licensing, please |
180 | | contact core@php.net. |
181 | +----------------------------------------------------------------------+
182 | end of test
183 |
--------------------------------------------------------------------------------
/ibase_events.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHP Version 7 |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 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 | | Authors: Ard Biesheuvel |
16 | +----------------------------------------------------------------------+
17 | */
18 |
19 | #ifdef HAVE_CONFIG_H
20 | #include "config.h"
21 | #endif
22 |
23 | #include "php.h"
24 |
25 | #if HAVE_IBASE
26 |
27 | #include "php_interbase.h"
28 | #include "php_ibase_includes.h"
29 |
30 | static int le_event;
31 |
32 | static void _php_ibase_event_free(char *event_buf, char *result_buf) /* {{{ */
33 | {
34 | isc_free(event_buf);
35 | isc_free(result_buf);
36 | }
37 | /* }}} */
38 |
39 | void _php_ibase_free_event(ibase_event *event) /* {{{ */
40 | {
41 | unsigned short i;
42 |
43 | event->state = DEAD;
44 |
45 | if (event->link != NULL) {
46 | ibase_event **node;
47 |
48 | zend_list_delete(event->link_res);
49 | if (event->link->handle != 0 &&
50 | isc_cancel_events(IB_STATUS, &event->link->handle, &event->event_id)) {
51 | _php_ibase_error();
52 | }
53 |
54 | /* delete this event from the link struct */
55 | for (node = &event->link->event_head; *node != event; node = &(*node)->event_next);
56 | *node = event->event_next;
57 | }
58 |
59 | if (Z_TYPE(event->callback) != IS_UNDEF) {
60 | zval_ptr_dtor(&event->callback);
61 | ZVAL_UNDEF(&event->callback);
62 |
63 | _php_ibase_event_free(event->event_buffer,event->result_buffer);
64 |
65 | for (i = 0; i < event->event_count; ++i) {
66 | if (event->events[i]) {
67 | efree(event->events[i]);
68 | }
69 | }
70 | efree(event->events);
71 | }
72 | }
73 | /* }}} */
74 |
75 | static void _php_ibase_free_event_rsrc(zend_resource *rsrc) /* {{{ */
76 | {
77 | ibase_event *e = (ibase_event *) rsrc->ptr;
78 |
79 | _php_ibase_free_event(e);
80 |
81 | efree(e);
82 | }
83 | /* }}} */
84 |
85 | void php_ibase_events_minit(INIT_FUNC_ARGS) /* {{{ */
86 | {
87 | le_event = zend_register_list_destructors_ex(_php_ibase_free_event_rsrc, NULL,
88 | "interbase event", module_number);
89 | }
90 | /* }}} */
91 |
92 | static void _php_ibase_event_block(ibase_db_link *ib_link, unsigned short count, /* {{{ */
93 | char **events, unsigned short *l, char **event_buf, char **result_buf)
94 | {
95 | ISC_STATUS dummy_result[20];
96 | ISC_ULONG dummy_count[15];
97 |
98 | /**
99 | * Unfortunately, there's no clean and portable way in C to pass arguments to
100 | * a variadic function if you don't know the number of arguments at compile time.
101 | * (And even if there were a way, the Interbase API doesn't provide a version of
102 | * this function that takes a va_list as an argument)
103 | *
104 | * In this case, the number of arguments is limited to 18 by the underlying API,
105 | * so we can work around it.
106 | */
107 |
108 | *l = (unsigned short) isc_event_block(event_buf, result_buf, count, events[0],
109 | events[1], events[2], events[3], events[4], events[5], events[6], events[7],
110 | events[8], events[9], events[10], events[11], events[12], events[13], events[14]);
111 |
112 | /**
113 | * Currently, this is the only way to correctly initialize an event buffer.
114 | * This is clearly something that should be fixed, cause the semantics of
115 | * isc_wait_for_event() indicate that it blocks until an event occurs.
116 | * If the Firebird people ever fix this, these lines should be removed,
117 | * otherwise, events will have to fire twice before ibase_wait_event() returns.
118 | */
119 |
120 | isc_wait_for_event(dummy_result, &ib_link->handle, *l, *event_buf, *result_buf);
121 | isc_event_counts(dummy_count, *l, *event_buf, *result_buf);
122 | }
123 | /* }}} */
124 |
125 | /* {{{ proto string ibase_wait_event([resource link_identifier,] string event [, string event [, ...]])
126 | Waits for any one of the passed Interbase events to be posted by the database, and returns its name */
127 | PHP_FUNCTION(ibase_wait_event)
128 | {
129 | zval *args;
130 | ibase_db_link *ib_link;
131 | int num_args;
132 | char *event_buffer, *result_buffer, *events[15];
133 | unsigned short i = 0, event_count = 0, buffer_size;
134 | ISC_ULONG occurred_event[15];
135 |
136 | RESET_ERRMSG;
137 |
138 | /* no more than 15 events */
139 | if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 16) {
140 | WRONG_PARAM_COUNT;
141 | }
142 |
143 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &num_args) == FAILURE) {
144 | return;
145 | }
146 |
147 | if (Z_TYPE(args[0]) == IS_RESOURCE) {
148 | if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(&args[0], "InterBase link", le_link, le_plink)) == NULL) {
149 | RETURN_FALSE;
150 | }
151 | i = 1;
152 | } else {
153 | if (ZEND_NUM_ARGS() > 15) {
154 | WRONG_PARAM_COUNT;
155 | }
156 | if ((ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) {
157 | RETURN_FALSE;
158 | }
159 | }
160 |
161 | for (; i < ZEND_NUM_ARGS(); ++i) {
162 | convert_to_string_ex(&args[i]);
163 | events[event_count++] = Z_STRVAL(args[i]);
164 | }
165 |
166 | /* fills the required data structure with information about the events */
167 | _php_ibase_event_block(ib_link, event_count, events, &buffer_size, &event_buffer, &result_buffer);
168 |
169 | /* now block until an event occurs */
170 | if (isc_wait_for_event(IB_STATUS, &ib_link->handle, buffer_size, event_buffer, result_buffer)) {
171 | _php_ibase_error();
172 | _php_ibase_event_free(event_buffer,result_buffer);
173 | RETURN_FALSE;
174 | }
175 |
176 | /* find out which event occurred */
177 | isc_event_counts(occurred_event, buffer_size, event_buffer, result_buffer);
178 | for (i = 0; i < event_count; ++i) {
179 | if (occurred_event[i]) {
180 | zend_string *result = zend_string_init(events[i], strlen(events[i]), 0);
181 | _php_ibase_event_free(event_buffer,result_buffer);
182 | RETURN_STR(result);
183 | }
184 | }
185 |
186 | /* If we reach this line, isc_wait_for_event() did return, but we don't know
187 | which event fired. */
188 | _php_ibase_event_free(event_buffer,result_buffer);
189 | RETURN_FALSE;
190 | }
191 | /* }}} */
192 |
193 | #if FB_API_VER >= 20
194 | #define PHP_ISC_CALLBACK ISC_EVENT_CALLBACK
195 | static ISC_EVENT_CALLBACK _php_ibase_callback(ibase_event *event, /* {{{ */
196 | ISC_USHORT buffer_size, ISC_UCHAR *result_buf)
197 | #else
198 | #define PHP_ISC_CALLBACK isc_callback
199 | static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */
200 | unsigned short buffer_size, char *result_buf)
201 | #endif
202 | {
203 | /* this function is called asynchronously by the Interbase client library. */
204 | TSRMLS_FETCH_FROM_CTX(event->thread_ctx);
205 |
206 | /**
207 | * The callback function is called when the event is first registered and when the event
208 | * is cancelled. I consider this is a bug. By clearing event->callback first and setting
209 | * it to -1 later, we make sure nothing happens if no event was actually posted.
210 | */
211 | switch (event->state) {
212 | unsigned short i;
213 | ISC_ULONG occurred_event[15];
214 | zval return_value, args[2];
215 |
216 | default: /* == DEAD */
217 | break;
218 | case ACTIVE:
219 | /* copy the updated results into the result buffer */
220 | memcpy(event->result_buffer, result_buf, buffer_size);
221 |
222 | ZVAL_RES(&args[1], event->link_res);
223 |
224 | /* find out which event occurred */
225 | isc_event_counts(occurred_event, buffer_size, event->event_buffer, event->result_buffer);
226 | for (i = 0; i < event->event_count; ++i) {
227 | if (occurred_event[i]) {
228 | ZVAL_STRING(&args[0], event->events[i]);
229 | //efree(event->events[i]);
230 | break;
231 | }
232 | }
233 |
234 | /* call the callback provided by the user */
235 | if (SUCCESS != call_user_function(NULL, NULL,
236 | &event->callback, &return_value, 2, args)) {
237 | _php_ibase_module_error("Error calling callback %s", Z_STRVAL(event->callback));
238 | break;
239 | }
240 |
241 | if (Z_TYPE(return_value) == IS_FALSE) {
242 | event->state = DEAD;
243 | break;
244 | }
245 | case NEW:
246 | /* re-register the event */
247 | if (isc_que_events(IB_STATUS, &event->link->handle, &event->event_id, buffer_size,
248 | event->event_buffer,(PHP_ISC_CALLBACK)_php_ibase_callback, (void *)event)) {
249 |
250 | _php_ibase_error();
251 | }
252 | event->state = ACTIVE;
253 | }
254 | return 0;
255 | }
256 | /* }}} */
257 |
258 | /* {{{ proto resource ibase_set_event_handler([resource link_identifier,] callback handler, string event [, string event [, ...]])
259 | Register the callback for handling each of the named events */
260 | PHP_FUNCTION(ibase_set_event_handler)
261 | {
262 | /**
263 | * The callback passed to this function should take an event name (string) and a
264 | * link resource id (int) as arguments. The value returned from the function is
265 | * used to determine if the event handler should remain set.
266 | */
267 | zval *args, *cb_arg;
268 | ibase_db_link *ib_link;
269 | ibase_event *event;
270 | unsigned short i = 1, buffer_size;
271 | int num_args;
272 | zend_resource *link_res;
273 |
274 | RESET_ERRMSG;
275 |
276 | /* Minimum and maximum number of arguments allowed */
277 | if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 17) {
278 | WRONG_PARAM_COUNT;
279 | }
280 |
281 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &num_args) == FAILURE) {
282 | return;
283 | }
284 |
285 | /* get a working link */
286 | if (Z_TYPE(args[0]) != IS_STRING) {
287 | /* resource, callback, event_1 [, ... event_15]
288 | * No more than 15 events
289 | */
290 | if (ZEND_NUM_ARGS() < 3 || ZEND_NUM_ARGS() > 17) {
291 | WRONG_PARAM_COUNT;
292 | }
293 |
294 | cb_arg = &args[1];
295 | i = 2;
296 |
297 | if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(&args[0], "InterBase link", le_link, le_plink)) == NULL) {
298 | RETURN_FALSE;
299 | }
300 |
301 | link_res = Z_RES(args[0]);
302 |
303 | } else {
304 | /* callback, event_1 [, ... event_15]
305 | * No more than 15 events
306 | */
307 | if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 16) {
308 | WRONG_PARAM_COUNT;
309 | }
310 |
311 | cb_arg = &args[0];
312 |
313 | if ((ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) {
314 | RETURN_FALSE;
315 | }
316 | link_res = IBG(default_link);
317 | }
318 |
319 | /* get the callback */
320 | if (!zend_is_callable(cb_arg, 0, NULL)) {
321 | zend_string *cb_name = zend_get_callable_name(cb_arg);
322 | _php_ibase_module_error("Callback argument %s is not a callable function", ZSTR_VAL(cb_name));
323 | zend_string_release_ex(cb_name, 0);
324 | RETURN_FALSE;
325 | }
326 |
327 | /* allocate the event resource */
328 | event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0);
329 | TSRMLS_SET_CTX(event->thread_ctx);
330 | event->link_res = link_res;
331 | GC_ADDREF(link_res);
332 | event->link = ib_link;
333 | event->event_count = 0;
334 | event->state = NEW;
335 | event->events = (char **) safe_emalloc(sizeof(char *), 15, 0);
336 |
337 | ZVAL_DUP(&event->callback, cb_arg);
338 |
339 | for (; i < 15; ++i) {
340 | if (i < ZEND_NUM_ARGS()) {
341 | convert_to_string_ex(&args[i]);
342 | event->events[event->event_count++] = estrdup(Z_STRVAL(args[i]));
343 | } else {
344 | event->events[i] = NULL;
345 | }
346 | }
347 |
348 | /* fills the required data structure with information about the events */
349 | _php_ibase_event_block(ib_link, event->event_count, event->events,
350 | &buffer_size, &event->event_buffer, &event->result_buffer);
351 |
352 | /* now register the events with the Interbase API */
353 | if (isc_que_events(IB_STATUS, &ib_link->handle, &event->event_id, buffer_size,
354 | event->event_buffer,(PHP_ISC_CALLBACK)_php_ibase_callback, (void *)event)) {
355 |
356 | _php_ibase_error();
357 | efree(event);
358 | RETURN_FALSE;
359 | }
360 |
361 | event->event_next = ib_link->event_head;
362 | ib_link->event_head = event;
363 |
364 | RETVAL_RES(zend_register_resource(event, le_event));
365 | Z_TRY_ADDREF_P(return_value);
366 | }
367 | /* }}} */
368 |
369 | /* {{{ proto bool ibase_free_event_handler(resource event)
370 | Frees the event handler set by ibase_set_event_handler() */
371 | PHP_FUNCTION(ibase_free_event_handler)
372 | {
373 | zval *event_arg;
374 |
375 | RESET_ERRMSG;
376 |
377 | if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "r", &event_arg)) {
378 | ibase_event *event;
379 |
380 | event = (ibase_event *)zend_fetch_resource_ex(event_arg, "Interbase event", le_event);
381 |
382 | event->state = DEAD;
383 |
384 | zend_list_delete(Z_RES_P(event_arg));
385 | RETURN_TRUE;
386 | } else {
387 | RETURN_FALSE;
388 | }
389 | }
390 | /* }}} */
391 |
392 | #endif /* HAVE_IBASE */
393 |
--------------------------------------------------------------------------------
/php_ibase_udf.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHP Version 7 |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 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: Ard Biesheuvel |
16 | +----------------------------------------------------------------------+
17 | */
18 |
19 | /**
20 | * This UDF library adds the ability to call PHP functions from SQL
21 | * statements. Because of SQL's strong typing, you will have to declare
22 | * an external function for every combination { output type, #args } that
23 | * your application requires.
24 | *
25 | * Declare the functions like this:
26 | *
27 | * DECLARE EXTERNAL FUNCTION CALL_PHP1
28 | * CSTRING(xx),
29 | * BY DESCRIPTOR,
30 | * INTEGER BY DESCRIPTOR
31 | * RETURNS PARAMETER 2
32 | * ENTRY_POINT 'udf_call_php1' MODULE_NAME 'php_ibase_udf'
33 | *
34 | * DECLARE EXTERNAL FUNCTION CALL_PHP2
35 | * CSTRING(xx),
36 | * BY DESCRIPTOR,
37 | * INTEGER BY DESCRIPTOR,
38 | * INTEGER BY DESCRIPTOR
39 | * RETURNS PARAMETER 2
40 | * ENTRY_POINT 'udf_call_php2' MODULE_NAME 'php_ibase_udf'
41 | *
42 | * ... and so on. [for up to 8 input arguments]
43 | *
44 | * The first input parameter contains the name of the PHP function you want
45 | * to call. The second argument is the result. (omit this argument when calling
46 | * the function) The return type of the function is the declared type of the
47 | * result. The value returned from the PHP function being called will
48 | * automatically be converted if necessary.
49 | * The arguments should have their types declared as well, but you're free
50 | * to pass arguments of other types instead. They will be converted to the
51 | * best matching PHP type before being passed to the PHP function.
52 | *
53 | * The declared functions can be called from SQL like:
54 | *
55 | * SELECT * FROM WHERE CALL_PHP1('soundex',) NOT LIKE ?
56 | * or
57 | * UPDATE SET = CALL_PHP1('ucwords',)
58 | *
59 | * Additionally, there's a function 'exec_php' which allows the contents
60 | * of text BLOB fields to be parsed and executed by PHP. This is most useful
61 | * for declaring functions that can then be called with CALL_PHPx.
62 | *
63 | * DECLARE EXTERNAL FUNCTION EXEC_PHP
64 | * BLOB,
65 | * INTEGER BY DESCRIPTOR,
66 | * SMALLINT
67 | * RETURNS PARAMETER 2
68 | * ENTRY_POINT 'exec_php' MODULE_NAME 'php_ibase_udf'
69 | *
70 | * The function will return 1 if execution succeeded and 0 if an error
71 | * occurred. The result that is returned from the executed PHP code is
72 | * ignored. You can pass a non-zero value as second argument to force
73 | * the embedded PHP engine to re-initialise.
74 | *
75 | * There are several ways to build this library, depending on which way the
76 | * database is accessed. If you're using the classic server on a local
77 | * connection, you should compile the library like this:
78 | *
79 | * gcc -shared `php-config --includes` `php-config --ldflags` \
80 | * `php-config --libs` -o php_ibase_udf.so php_ibase_udf.c
81 | *
82 | * If you connect to the classic server by TCP/IP, you should build the
83 | * PHP embedded static library and link against that.
84 | *
85 | * gcc -shared `php-config --includes` `php-config --ldflags` \
86 | * `php-config --libs` -o php_ibase_udf.so php_ibase_udf.c \
87 | * /usr/lib/libphp7.a
88 | *
89 | * If you use the super server, you should also link against the embedded
90 | * library, but be sure to enable thread safety, as the super server is
91 | * multi-threaded. After building, copy the resulting file to the folder
92 | * where your database expects to find its UDFs.
93 | */
94 |
95 | #include "zend.h"
96 | #include "zend_API.h"
97 |
98 | #include "php.h"
99 | #include "php_ini.h"
100 |
101 | #include "ibase.h"
102 |
103 | #define min(a,b) ((a)<(b)?(a):(b))
104 |
105 | #ifdef PHP_WIN32
106 | #define LL_LIT(lit) lit ## I64
107 | #else
108 | #define LL_LIT(lit) lit ## ll
109 | #endif
110 |
111 | #ifdef ZTS
112 | # include
113 |
114 | static void ***tsrm_ls;
115 | pthread_mutex_t mtx_res = PTHREAD_MUTEX_INITIALIZER;
116 |
117 | #define LOCK() do { pthread_mutex_lock(&mtx_res); } while (0)
118 | #define UNLOCK() do { pthread_mutex_unlock(&mtx_res); } while (0)
119 | #else
120 | #define LOCK()
121 | #define UNLOCK()
122 | #endif
123 |
124 | #ifdef PHP_EMBED
125 | # include "php_main.h"
126 | # include "sapi/embed/php_embed.h"
127 |
128 | static void __attribute__((constructor)) init()
129 | {
130 | php_embed_init(0, NULL P);
131 | }
132 |
133 | static void __attribute__((destructor)) fini()
134 | {
135 | php_embed_shutdown();
136 | }
137 |
138 | #endif
139 |
140 | /**
141 | * Gets the contents of the BLOB b and offers it to Zend for parsing/execution
142 | */
143 | void exec_php(BLOBCALLBACK b, PARAMDSC *res, ISC_SHORT *init)
144 | {
145 | int result, remaining = b->blob_total_length, i = 0;
146 | char *code = pemalloc(remaining+1, 1);
147 | ISC_USHORT read;
148 |
149 | for (code[remaining] = '\0'; remaining > 0; remaining -= read)
150 | b->blob_get_segment(b->blob_handle, &code[i++<<16],min(0x10000,remaining), &read);
151 |
152 | LOCK();
153 |
154 | switch (init && *init) {
155 |
156 | default:
157 | #ifdef PHP_EMBED
158 | php_request_shutdown(NULL);
159 | if (FAILURE == (result = php_request_startup())) {
160 | break;
161 | }
162 | case 0:
163 | #endif
164 | /* feed it to the parser */
165 | zend_first_try {
166 | result = zend_eval_stringl(code, b->blob_total_length, NULL, "Firebird Embedded PHP engine");
167 | } zend_end_try();
168 | }
169 |
170 | UNLOCK();
171 |
172 | free(code);
173 |
174 | res->dsc_dtype = dtype_long;
175 | *(ISC_LONG*)res->dsc_address = (result == SUCCESS);
176 | }
177 |
178 | static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 100000000, 1000000000,
179 | 1000000000, LL_LIT(10000000000),LL_LIT(100000000000),LL_LIT(10000000000000),LL_LIT(100000000000000),
180 | LL_LIT(1000000000000000),LL_LIT(1000000000000000),LL_LIT(1000000000000000000) };
181 |
182 |
183 | static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv)
184 | {
185 | do {
186 | zval callback, args[4], return_value;
187 | PARAMVARY *res = (PARAMVARY*)r->dsc_address;
188 | int i;
189 |
190 | ZVAL_STRING(&callback, name);
191 |
192 | LOCK();
193 |
194 | /* check if the requested function exists */
195 | if (!zend_is_callable(&callback, 0, NULL)) {
196 | break;
197 | }
198 |
199 | UNLOCK();
200 |
201 | /* create the argument array */
202 | for (i = 0; i < argc; ++i) {
203 |
204 | /* test arg for null */
205 | if (argv[i]->dsc_flags & DSC_null) {
206 | ZVAL_NULL(&args[i]);
207 | continue;
208 | }
209 |
210 | switch (argv[i]->dsc_dtype) {
211 | ISC_INT64 l;
212 | struct tm t;
213 | char const *fmt;
214 | char d[64];
215 |
216 | case dtype_cstring:
217 | //???
218 | ZVAL_STRING(&args[i], (char*)argv[i]->dsc_address);
219 | break;
220 |
221 | case dtype_text:
222 | //???
223 | ZVAL_STRINGL(&args[i], (char*)argv[i]->dsc_address, argv[i]->dsc_length);
224 | break;
225 |
226 | case dtype_varying:
227 | //???
228 | ZVAL_STRINGL(&args[i], ((PARAMVARY*)argv[i]->dsc_address)->vary_string,
229 | ((PARAMVARY*)argv[i]->dsc_address)->vary_length);
230 | break;
231 |
232 | case dtype_short:
233 | if (argv[i]->dsc_scale == 0) {
234 | ZVAL_LONG(&args[i], *(short*)argv[i]->dsc_address);
235 | } else {
236 | ZVAL_DOUBLE(&args[i],
237 | ((double)*(short*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]);
238 | }
239 | break;
240 |
241 | case dtype_long:
242 | if (argv[i]->dsc_scale == 0) {
243 | ZVAL_LONG(&args[i], *(ISC_LONG*)argv[i]->dsc_address);
244 | } else {
245 | ZVAL_DOUBLE(&args[i],
246 | ((double)*(ISC_LONG*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]);
247 | }
248 | break;
249 |
250 | case dtype_int64:
251 | l = *(ISC_INT64*)argv[i]->dsc_address;
252 |
253 | if (argv[i]->dsc_scale == 0 && l <= ZEND_LONG_MAX && l >= ZEND_LONG_MIN) {
254 | ZVAL_LONG(&args[i], (zend_long)l);
255 | } else {
256 | ZVAL_DOUBLE(&args[i], ((double)l)/scales[-argv[i]->dsc_scale]);
257 | }
258 | break;
259 |
260 | case dtype_real:
261 | ZVAL_DOUBLE(&args[i], *(float*)argv[i]->dsc_address);
262 | break;
263 |
264 | case dtype_double:
265 | ZVAL_DOUBLE(&args[i], *(double*)argv[i]->dsc_address);
266 | break;
267 |
268 | case dtype_sql_date:
269 | isc_decode_sql_date((ISC_DATE*)argv[i]->dsc_address, &t);
270 | ZVAL_STRINGL(&args[i], d, strftime(d, sizeof(d), INI_STR("ibase.dateformat"), &t),1);
271 | break;
272 |
273 | case dtype_sql_time:
274 | isc_decode_sql_time((ISC_TIME*)argv[i]->dsc_address, &t);
275 | ZVAL_STRINGL(&args[i], d, strftime(d, sizeof(d), INI_STR("ibase.timeformat"), &t),1);
276 | break;
277 |
278 | case dtype_timestamp:
279 | isc_decode_timestamp((ISC_TIMESTAMP*)argv[i]->dsc_address, &t);
280 | ZVAL_STRINGL(&args[i], d, strftime(d, sizeof(d), INI_STR("ibase.timestampformat"), &t));
281 | break;
282 | }
283 | }
284 |
285 | LOCK();
286 |
287 | /* now call the function */
288 | if (FAILURE == call_user_function(NULL, NULL,
289 | &callback, &return_value, argc, args)) {
290 | UNLOCK();
291 | break;
292 | }
293 |
294 | UNLOCK();
295 |
296 | for (i = 0; i < argc; ++i) {
297 | switch (argv[i]->dsc_dtype) {
298 | case dtype_sql_date:
299 | case dtype_sql_time:
300 | case dtype_timestamp:
301 | zval_ptr_dtor_nogc(&args[i]);
302 | }
303 | }
304 |
305 | zval_ptr_dtor_str(&callback);
306 |
307 | /* return whatever type we got back from the callback: let DB handle conversion */
308 | switch (Z_TYPE(return_value)) {
309 |
310 | case IS_LONG:
311 | r->dsc_dtype = dtype_long;
312 | *(zend_long*)r->dsc_address = Z_LVAL(return_value);
313 | r->dsc_length = sizeof(zend_long);
314 | break;
315 |
316 | case IS_DOUBLE:
317 | r->dsc_dtype = dtype_double;
318 | *(double*)r->dsc_address = Z_DVAL(return_value);
319 | r->dsc_length = sizeof(double);
320 | break;
321 |
322 | case IS_NULL:
323 | r->dsc_flags |= DSC_null;
324 | break;
325 |
326 | default:
327 | convert_to_string(&return_value);
328 |
329 | case IS_STRING:
330 | r->dsc_dtype = dtype_varying;
331 | memcpy(res->vary_string, Z_STRVAL(return_value),
332 | (res->vary_length = min(r->dsc_length-2,Z_STRLEN(return_value))));
333 | r->dsc_length = res->vary_length+2;
334 | break;
335 | }
336 |
337 | zval_ptr_dtor(&return_value);
338 |
339 | return;
340 |
341 | } while (0);
342 |
343 | /**
344 | * If we end up here, we should report an error back to the DB engine, but
345 | * that's not possible. We can however report it back to PHP.
346 | */
347 | LOCK();
348 | php_error_docref(NULL, E_WARNING, "Error calling function '%s' from database", name);
349 | UNLOCK();
350 | }
351 |
352 |
353 | /* Entry points for the DB engine */
354 |
355 | void udf_call_php1(char *name, PARAMDSC *r, PARAMDSC *arg1)
356 | {
357 | PARAMDSC *args[1] = { arg1 };
358 | call_php(name, r, 1, args);
359 | }
360 |
361 | void udf_call_php2(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2)
362 | {
363 | PARAMDSC *args[2] = { arg1, arg2 };
364 | call_php(name, r, 2, args);
365 | }
366 |
367 | void udf_call_php3(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3)
368 | {
369 | PARAMDSC *args[3] = { arg1, arg2, arg3 };
370 | call_php(name, r, 3, args);
371 | }
372 |
373 | void udf_call_php4(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3,
374 | PARAMDSC *arg4)
375 | {
376 | PARAMDSC *args[4] = { arg1, arg2, arg3, arg4 };
377 | call_php(name, r, 4, args);
378 | }
379 |
380 | void udf_call_php5(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3,
381 | PARAMDSC *arg4, PARAMDSC *arg5)
382 | {
383 | PARAMDSC *args[5] = { arg1, arg2, arg3, arg4, arg5 };
384 | call_php(name, r, 5, args);
385 | }
386 |
387 | void udf_call_php6(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3,
388 | PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6)
389 | {
390 | PARAMDSC *args[6] = { arg1, arg2, arg3, arg4, arg5, arg6 };
391 | call_php(name, r, 6, args);
392 | }
393 |
394 | void udf_call_php7(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3,
395 | PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6, PARAMDSC *arg7)
396 | {
397 | PARAMDSC *args[7] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
398 | call_php(name, r, 7, args);
399 | }
400 |
401 | void udf_call_php8(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3,
402 | PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6, PARAMDSC *arg7, PARAMDSC *arg8)
403 | {
404 | PARAMDSC *args[8] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
405 | call_php(name, r, 8, args);
406 | }
407 |
--------------------------------------------------------------------------------
/ibase_blobs.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHP Version 7 |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 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 | | Authors: Ard Biesheuvel |
16 | +----------------------------------------------------------------------+
17 | */
18 |
19 | #ifdef HAVE_CONFIG_H
20 | #include "config.h"
21 | #endif
22 |
23 | #include "php.h"
24 |
25 | #if HAVE_IBASE
26 |
27 | #include "php_interbase.h"
28 | #include "php_ibase_includes.h"
29 |
30 | #define BLOB_CLOSE 1
31 | #define BLOB_CANCEL 2
32 |
33 | #define PARSE_PARAMETERS \
34 | switch (ZEND_NUM_ARGS()) { \
35 | default: \
36 | WRONG_PARAM_COUNT; \
37 | case 1: \
38 | if (FAILURE == zend_parse_parameters(1, "s", &blob_id, &blob_id_len)) { \
39 | RETURN_FALSE; \
40 | } \
41 | break; \
42 | case 2: \
43 | if (FAILURE == zend_parse_parameters(2, "rs", &link, &blob_id, &blob_id_len)) { \
44 | RETURN_FALSE; \
45 | } \
46 | break; \
47 | } \
48 |
49 | static int le_blob;
50 |
51 | static void _php_ibase_free_blob(zend_resource *rsrc) /* {{{ */
52 | {
53 | ibase_blob *ib_blob = (ibase_blob *)rsrc->ptr;
54 |
55 | if (ib_blob->bl_handle != 0) { /* blob open*/
56 | if (isc_cancel_blob(IB_STATUS, &ib_blob->bl_handle)) {
57 | _php_ibase_module_error("You can lose data. Close any blob after reading from or "
58 | "writing to it. Use ibase_blob_close() before calling ibase_close()");
59 | }
60 | }
61 | efree(ib_blob);
62 | }
63 | /* }}} */
64 |
65 | void php_ibase_blobs_minit(INIT_FUNC_ARGS) /* {{{ */
66 | {
67 | le_blob = zend_register_list_destructors_ex(_php_ibase_free_blob, NULL,
68 | "interbase blob", module_number);
69 | }
70 | /* }}} */
71 |
72 | int _php_ibase_string_to_quad(char const *id, ISC_QUAD *qd) /* {{{ */
73 | {
74 | /* shortcut for most common case */
75 | if (sizeof(ISC_QUAD) == sizeof(ISC_UINT64)) {
76 | return sscanf(id, BLOB_ID_MASK, (ISC_UINT64 *) qd);
77 | } else {
78 | ISC_UINT64 res;
79 | if (sscanf(id, BLOB_ID_MASK, &res)) {
80 | qd->gds_quad_high = (ISC_LONG) (res >> 0x20);
81 | qd->gds_quad_low = (ISC_LONG) (res & 0xFFFFFFFF);
82 | return 1;
83 | }
84 | return 0;
85 | }
86 | }
87 | /* }}} */
88 |
89 | zend_string *_php_ibase_quad_to_string(ISC_QUAD const qd) /* {{{ */
90 | {
91 | /* shortcut for most common case */
92 | if (sizeof(ISC_QUAD) == sizeof(ISC_UINT64)) {
93 | return strpprintf(BLOB_ID_LEN+1, "0x%0*" LL_MASK "x", 16, *(ISC_UINT64*)(void *) &qd);
94 | } else {
95 | ISC_UINT64 res = ((ISC_UINT64) qd.gds_quad_high << 0x20) | qd.gds_quad_low;
96 | return strpprintf(BLOB_ID_LEN+1, "0x%0*" LL_MASK "x", 16, res);
97 | }
98 | }
99 | /* }}} */
100 |
101 | typedef struct { /* {{{ */
102 | ISC_LONG max_segment; /* Length of longest segment */
103 | ISC_LONG num_segments; /* Total number of segments */
104 | ISC_LONG total_length; /* Total length of blob */
105 | int bl_stream; /* blob is stream ? */
106 | /* }}} */
107 | } IBASE_BLOBINFO;
108 |
109 | int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, zend_ulong max_len) /* {{{ */
110 | {
111 | if (ib_blob->bl_qd.gds_quad_high || ib_blob->bl_qd.gds_quad_low) { /*not null ?*/
112 |
113 | ISC_STATUS stat;
114 | zend_string *bl_data;
115 | zend_ulong cur_len;
116 | unsigned short seg_len;
117 |
118 | bl_data = zend_string_safe_alloc(1, max_len, 0, 0);
119 |
120 | for (cur_len = stat = 0; (stat == 0 || stat == isc_segment) && cur_len < max_len; cur_len += seg_len) {
121 |
122 | unsigned short chunk_size = (max_len-cur_len) > USHRT_MAX ? USHRT_MAX
123 | : (unsigned short)(max_len-cur_len);
124 |
125 | stat = isc_get_segment(IB_STATUS, &ib_blob->bl_handle, &seg_len, chunk_size, &ZSTR_VAL(bl_data)[cur_len]);
126 | }
127 |
128 | if (IB_STATUS[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
129 | zend_string_free(bl_data);
130 | _php_ibase_error();
131 | return FAILURE;
132 | }
133 | ZSTR_VAL(bl_data)[cur_len] = '\0';
134 | ZSTR_LEN(bl_data) = cur_len;
135 | RETVAL_NEW_STR(bl_data);
136 | } else { /* null blob */
137 | RETVAL_EMPTY_STRING(); /* empty string */
138 | }
139 | return SUCCESS;
140 | }
141 | /* }}} */
142 |
143 | int _php_ibase_blob_add(zval *string_arg, ibase_blob *ib_blob) /* {{{ */
144 | {
145 | zend_ulong put_cnt = 0, rem_cnt;
146 | unsigned short chunk_size;
147 |
148 | convert_to_string_ex(string_arg);
149 |
150 | for (rem_cnt = Z_STRLEN_P(string_arg); rem_cnt > 0; rem_cnt -= chunk_size) {
151 |
152 | chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
153 |
154 | if (isc_put_segment(IB_STATUS, &ib_blob->bl_handle, chunk_size, &Z_STRVAL_P(string_arg)[put_cnt] )) {
155 | _php_ibase_error();
156 | return FAILURE;
157 | }
158 | put_cnt += chunk_size;
159 | }
160 | return SUCCESS;
161 | }
162 | /* }}} */
163 |
164 | static int _php_ibase_blob_info(isc_blob_handle bl_handle, IBASE_BLOBINFO *bl_info) /* {{{ */
165 | {
166 | static char bl_items[] = {
167 | isc_info_blob_num_segments,
168 | isc_info_blob_max_segment,
169 | isc_info_blob_total_length,
170 | isc_info_blob_type
171 | };
172 |
173 | char bl_inf[sizeof(zend_long)*8], *p;
174 |
175 | bl_info->max_segment = 0;
176 | bl_info->num_segments = 0;
177 | bl_info->total_length = 0;
178 | bl_info->bl_stream = 0;
179 |
180 | if (isc_blob_info(IB_STATUS, &bl_handle, sizeof(bl_items), bl_items, sizeof(bl_inf), bl_inf)) {
181 | _php_ibase_error();
182 | return FAILURE;
183 | }
184 |
185 | for (p = bl_inf; *p != isc_info_end && p < bl_inf + sizeof(bl_inf);) {
186 | unsigned short item_len;
187 | int item = *p++;
188 |
189 | item_len = (short) isc_vax_integer(p, 2);
190 | p += 2;
191 | switch (item) {
192 | case isc_info_blob_num_segments:
193 | bl_info->num_segments = isc_vax_integer(p, item_len);
194 | break;
195 | case isc_info_blob_max_segment:
196 | bl_info->max_segment = isc_vax_integer(p, item_len);
197 | break;
198 | case isc_info_blob_total_length:
199 | bl_info->total_length = isc_vax_integer(p, item_len);
200 | break;
201 | case isc_info_blob_type:
202 | bl_info->bl_stream = isc_vax_integer(p, item_len);
203 | break;
204 | case isc_info_end:
205 | break;
206 | case isc_info_truncated:
207 | case isc_info_error: /* hmm. don't think so...*/
208 | _php_ibase_module_error("PHP module internal error");
209 | return FAILURE;
210 | } /* switch */
211 | p += item_len;
212 | } /* for */
213 | return SUCCESS;
214 | }
215 | /* }}} */
216 |
217 | /* {{{ proto resource ibase_blob_create([resource link_identifier])
218 | Create blob for adding data */
219 | PHP_FUNCTION(ibase_blob_create)
220 | {
221 | zval *link = NULL;
222 | ibase_db_link *ib_link;
223 | ibase_trans *trans = NULL;
224 | ibase_blob *ib_blob;
225 |
226 | RESET_ERRMSG;
227 |
228 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &link)) {
229 | RETURN_FALSE;
230 | }
231 |
232 | PHP_IBASE_LINK_TRANS(link, ib_link, trans);
233 |
234 | ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob));
235 | ib_blob->bl_handle = 0;
236 | ib_blob->type = BLOB_INPUT;
237 |
238 | if (isc_create_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob->bl_handle, &ib_blob->bl_qd)) {
239 | _php_ibase_error();
240 | efree(ib_blob);
241 | RETURN_FALSE;
242 | }
243 |
244 | RETVAL_RES(zend_register_resource(ib_blob, le_blob));
245 | Z_TRY_ADDREF_P(return_value);
246 | }
247 | /* }}} */
248 |
249 | /* {{{ proto resource ibase_blob_open([ resource link_identifier, ] string blob_id)
250 | Open blob for retrieving data parts */
251 | PHP_FUNCTION(ibase_blob_open)
252 | {
253 | char *blob_id;
254 | size_t blob_id_len;
255 | zval *link = NULL;
256 | ibase_db_link *ib_link;
257 | ibase_trans *trans = NULL;
258 | ibase_blob *ib_blob;
259 |
260 | RESET_ERRMSG;
261 | PARSE_PARAMETERS;
262 |
263 | PHP_IBASE_LINK_TRANS(link, ib_link, trans);
264 |
265 | ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob));
266 | ib_blob->bl_handle = 0;
267 | ib_blob->type = BLOB_OUTPUT;
268 |
269 | do {
270 | if (! _php_ibase_string_to_quad(blob_id, &ib_blob->bl_qd)) {
271 | _php_ibase_module_error("String is not a BLOB ID");
272 | break;
273 | }
274 |
275 | if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob->bl_handle,
276 | &ib_blob->bl_qd)) {
277 | _php_ibase_error();
278 | break;
279 | }
280 |
281 | RETVAL_RES(zend_register_resource(ib_blob, le_blob));
282 | Z_TRY_ADDREF_P(return_value);
283 | return;
284 |
285 | } while (0);
286 |
287 | efree(ib_blob);
288 | RETURN_FALSE;
289 | }
290 | /* }}} */
291 |
292 | /* {{{ proto bool ibase_blob_add(resource blob_handle, string data)
293 | Add data into created blob */
294 | PHP_FUNCTION(ibase_blob_add)
295 | {
296 | zval *blob_arg, *string_arg;
297 | ibase_blob *ib_blob;
298 |
299 | RESET_ERRMSG;
300 |
301 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &blob_arg, &string_arg)) {
302 | return;
303 | }
304 |
305 | ib_blob = (ibase_blob *)zend_fetch_resource_ex(blob_arg, "Interbase blob", le_blob);
306 |
307 | if (ib_blob->type != BLOB_INPUT) {
308 | _php_ibase_module_error("BLOB is not open for input");
309 | RETURN_FALSE;
310 | }
311 |
312 | if (_php_ibase_blob_add(string_arg, ib_blob) != SUCCESS) {
313 | RETURN_FALSE;
314 | }
315 | }
316 | /* }}} */
317 |
318 | /* {{{ proto string ibase_blob_get(resource blob_handle, int len)
319 | Get len bytes data from open blob */
320 | PHP_FUNCTION(ibase_blob_get)
321 | {
322 | zval *blob_arg;
323 | zend_ulong len_arg;
324 | ibase_blob *ib_blob;
325 |
326 | RESET_ERRMSG;
327 |
328 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &blob_arg, &len_arg)) {
329 | return;
330 | }
331 |
332 | ib_blob = (ibase_blob *)zend_fetch_resource_ex(blob_arg, "Interbase blob", le_blob);
333 |
334 | if (ib_blob->type != BLOB_OUTPUT) {
335 | _php_ibase_module_error("BLOB is not open for output");
336 | RETURN_FALSE;
337 | }
338 |
339 | if (_php_ibase_blob_get(return_value, ib_blob, len_arg) != SUCCESS) {
340 | RETURN_FALSE;
341 | }
342 | }
343 | /* }}} */
344 |
345 | static void _php_ibase_blob_end(INTERNAL_FUNCTION_PARAMETERS, int bl_end) /* {{{ */
346 | {
347 | zval *blob_arg;
348 | ibase_blob *ib_blob;
349 |
350 | RESET_ERRMSG;
351 |
352 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "r", &blob_arg)) {
353 | return;
354 | }
355 |
356 | ib_blob = (ibase_blob *)zend_fetch_resource_ex(blob_arg, "Interbase blob", le_blob);
357 |
358 | if (bl_end == BLOB_CLOSE) { /* return id here */
359 |
360 | if (ib_blob->bl_qd.gds_quad_high || ib_blob->bl_qd.gds_quad_low) { /*not null ?*/
361 | if (isc_close_blob(IB_STATUS, &ib_blob->bl_handle)) {
362 | _php_ibase_error();
363 | RETURN_FALSE;
364 | }
365 | }
366 | ib_blob->bl_handle = 0;
367 |
368 | RETVAL_NEW_STR(_php_ibase_quad_to_string(ib_blob->bl_qd));
369 | } else { /* discard created blob */
370 | if (isc_cancel_blob(IB_STATUS, &ib_blob->bl_handle)) {
371 | _php_ibase_error();
372 | RETURN_FALSE;
373 | }
374 | ib_blob->bl_handle = 0;
375 | RETVAL_TRUE;
376 | }
377 | zend_list_delete(Z_RES_P(blob_arg));
378 | }
379 | /* }}} */
380 |
381 | /* {{{ proto string ibase_blob_close(resource blob_handle)
382 | Close blob */
383 | PHP_FUNCTION(ibase_blob_close)
384 | {
385 | _php_ibase_blob_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, BLOB_CLOSE);
386 | }
387 | /* }}} */
388 |
389 | /* {{{ proto bool ibase_blob_cancel(resource blob_handle)
390 | Cancel creating blob */
391 | PHP_FUNCTION(ibase_blob_cancel)
392 | {
393 | _php_ibase_blob_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, BLOB_CANCEL);
394 | }
395 | /* }}} */
396 |
397 | /* {{{ proto array ibase_blob_info([ resource link_identifier, ] string blob_id)
398 | Return blob length and other useful info */
399 | PHP_FUNCTION(ibase_blob_info)
400 | {
401 | char *blob_id;
402 | size_t blob_id_len;
403 | zval *link = NULL;
404 | ibase_db_link *ib_link;
405 | ibase_trans *trans = NULL;
406 | ibase_blob ib_blob = { 0, BLOB_INPUT };
407 | IBASE_BLOBINFO bl_info;
408 |
409 | RESET_ERRMSG;
410 | PARSE_PARAMETERS;
411 |
412 | PHP_IBASE_LINK_TRANS(link, ib_link, trans);
413 |
414 | if (! _php_ibase_string_to_quad(blob_id, &ib_blob.bl_qd)) {
415 | _php_ibase_module_error("Unrecognized BLOB ID");
416 | RETURN_FALSE;
417 | }
418 |
419 | if (ib_blob.bl_qd.gds_quad_high || ib_blob.bl_qd.gds_quad_low) { /* not null ? */
420 | if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob.bl_handle,
421 | &ib_blob.bl_qd)) {
422 | _php_ibase_error();
423 | RETURN_FALSE;
424 | }
425 |
426 | if (_php_ibase_blob_info(ib_blob.bl_handle, &bl_info)) {
427 | RETURN_FALSE;
428 | }
429 | if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
430 | _php_ibase_error();
431 | RETURN_FALSE;
432 | }
433 | } else { /* null blob, all values to zero */
434 | bl_info.max_segment = 0;
435 | bl_info.num_segments = 0;
436 | bl_info.total_length = 0;
437 | bl_info.bl_stream = 0;
438 | }
439 |
440 | array_init(return_value);
441 |
442 | add_index_long(return_value, 0, bl_info.total_length);
443 | add_assoc_long(return_value, "length", bl_info.total_length);
444 |
445 | add_index_long(return_value, 1, bl_info.num_segments);
446 | add_assoc_long(return_value, "numseg", bl_info.num_segments);
447 |
448 | add_index_long(return_value, 2, bl_info.max_segment);
449 | add_assoc_long(return_value, "maxseg", bl_info.max_segment);
450 |
451 | add_index_bool(return_value, 3, bl_info.bl_stream);
452 | add_assoc_bool(return_value, "stream", bl_info.bl_stream);
453 |
454 | add_index_bool(return_value, 4, (!ib_blob.bl_qd.gds_quad_high && !ib_blob.bl_qd.gds_quad_low));
455 | add_assoc_bool(return_value, "isnull", (!ib_blob.bl_qd.gds_quad_high && !ib_blob.bl_qd.gds_quad_low));
456 | }
457 | /* }}} */
458 |
459 | /* {{{ proto bool ibase_blob_echo([ resource link_identifier, ] string blob_id)
460 | Output blob contents to browser */
461 | PHP_FUNCTION(ibase_blob_echo)
462 | {
463 | char *blob_id;
464 | size_t blob_id_len;
465 | zval *link = NULL;
466 | ibase_db_link *ib_link;
467 | ibase_trans *trans = NULL;
468 | ibase_blob ib_blob_id = { 0, BLOB_OUTPUT };
469 | char bl_data[IBASE_BLOB_SEG];
470 | unsigned short seg_len;
471 |
472 | RESET_ERRMSG;
473 | PARSE_PARAMETERS;
474 |
475 | PHP_IBASE_LINK_TRANS(link, ib_link, trans);
476 |
477 | if (! _php_ibase_string_to_quad(blob_id, &ib_blob_id.bl_qd)) {
478 | _php_ibase_module_error("Unrecognized BLOB ID");
479 | RETURN_FALSE;
480 | }
481 |
482 | do {
483 | if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob_id.bl_handle,
484 | &ib_blob_id.bl_qd)) {
485 | break;
486 | }
487 |
488 | while (!isc_get_segment(IB_STATUS, &ib_blob_id.bl_handle, &seg_len, sizeof(bl_data), bl_data)
489 | || IB_STATUS[1] == isc_segment) {
490 | PHPWRITE(bl_data, seg_len);
491 | }
492 |
493 | if (IB_STATUS[0] && (IB_STATUS[1] != isc_segstr_eof)) {
494 | break;
495 | }
496 |
497 | if (isc_close_blob(IB_STATUS, &ib_blob_id.bl_handle)) {
498 | break;
499 | }
500 | RETURN_TRUE;
501 | } while (0);
502 |
503 | _php_ibase_error();
504 | RETURN_FALSE;
505 | }
506 | /* }}} */
507 |
508 | /* {{{ proto string ibase_blob_import([ resource link_identifier, ] resource file)
509 | Create blob, copy file in it, and close it */
510 | PHP_FUNCTION(ibase_blob_import)
511 | {
512 | zval *link = NULL, *file;
513 | int size;
514 | unsigned short b;
515 | ibase_blob ib_blob = { 0, 0 };
516 | ibase_db_link *ib_link;
517 | ibase_trans *trans = NULL;
518 | char bl_data[IBASE_BLOB_SEG];
519 | php_stream *stream;
520 |
521 | RESET_ERRMSG;
522 |
523 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "r|r",
524 | (ZEND_NUM_ARGS()-1) ? &link : &file, &file)) {
525 | RETURN_FALSE;
526 | }
527 |
528 | PHP_IBASE_LINK_TRANS(link, ib_link, trans);
529 |
530 | php_stream_from_zval(stream, file);
531 |
532 | do {
533 | if (isc_create_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob.bl_handle,
534 | &ib_blob.bl_qd)) {
535 | break;
536 | }
537 |
538 | for (size = 0; (b = php_stream_read(stream, bl_data, sizeof(bl_data))); size += b) {
539 | if (isc_put_segment(IB_STATUS, &ib_blob.bl_handle, b, bl_data)) {
540 | break;
541 | }
542 | }
543 |
544 | if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
545 | break;
546 | }
547 | RETURN_NEW_STR(_php_ibase_quad_to_string(ib_blob.bl_qd));
548 | } while (0);
549 |
550 | _php_ibase_error();
551 | RETURN_FALSE;
552 | }
553 | /* }}} */
554 |
555 | #endif /* HAVE_IBASE */
556 |
--------------------------------------------------------------------------------
/ibase_service.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHP Version 7 |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 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 | | Authors: Ard Biesheuvel |
16 | +----------------------------------------------------------------------+
17 | */
18 |
19 | #ifdef HAVE_CONFIG_H
20 | #include "config.h"
21 | #endif
22 |
23 | #include "php.h"
24 |
25 | #if HAVE_IBASE
26 |
27 | #include "php_interbase.h"
28 | #include "php_ibase_includes.h"
29 |
30 | typedef struct {
31 | isc_svc_handle handle;
32 | char *hostname;
33 | char *username;
34 | zend_resource *res;
35 | } ibase_service;
36 |
37 | static int le_service;
38 |
39 | static void _php_ibase_free_service(zend_resource *rsrc) /* {{{ */
40 | {
41 | ibase_service *sv = (ibase_service *) rsrc->ptr;
42 |
43 | if (isc_service_detach(IB_STATUS, &sv->handle)) {
44 | _php_ibase_error();
45 | }
46 |
47 | if (sv->hostname) {
48 | efree(sv->hostname);
49 | }
50 | if (sv->username) {
51 | efree(sv->username);
52 | }
53 |
54 | efree(sv);
55 | }
56 | /* }}} */
57 |
58 | /* the svc api seems to get confused after an error has occurred,
59 | so invalidate the handle on errors */
60 | #define IBASE_SVC_ERROR(svm) \
61 | do { zend_list_delete(svm->res); _php_ibase_error(); } while (0)
62 |
63 |
64 | void php_ibase_service_minit(INIT_FUNC_ARGS) /* {{{ */
65 | {
66 | le_service = zend_register_list_destructors_ex(_php_ibase_free_service, NULL,
67 | "interbase service manager handle", module_number);
68 |
69 | /* backup options */
70 | REGISTER_LONG_CONSTANT("IBASE_BKP_IGNORE_CHECKSUMS", isc_spb_bkp_ignore_checksums, CONST_PERSISTENT);
71 | REGISTER_LONG_CONSTANT("IBASE_BKP_IGNORE_LIMBO", isc_spb_bkp_ignore_limbo, CONST_PERSISTENT);
72 | REGISTER_LONG_CONSTANT("IBASE_BKP_METADATA_ONLY", isc_spb_bkp_metadata_only, CONST_PERSISTENT);
73 | REGISTER_LONG_CONSTANT("IBASE_BKP_NO_GARBAGE_COLLECT", isc_spb_bkp_no_garbage_collect, CONST_PERSISTENT);
74 | REGISTER_LONG_CONSTANT("IBASE_BKP_OLD_DESCRIPTIONS", isc_spb_bkp_old_descriptions, CONST_PERSISTENT);
75 | REGISTER_LONG_CONSTANT("IBASE_BKP_NON_TRANSPORTABLE", isc_spb_bkp_non_transportable, CONST_PERSISTENT);
76 | REGISTER_LONG_CONSTANT("IBASE_BKP_CONVERT", isc_spb_bkp_convert, CONST_PERSISTENT);
77 |
78 | /* restore options */
79 | REGISTER_LONG_CONSTANT("IBASE_RES_DEACTIVATE_IDX", isc_spb_res_deactivate_idx, CONST_PERSISTENT);
80 | REGISTER_LONG_CONSTANT("IBASE_RES_NO_SHADOW", isc_spb_res_no_shadow, CONST_PERSISTENT);
81 | REGISTER_LONG_CONSTANT("IBASE_RES_NO_VALIDITY", isc_spb_res_no_validity, CONST_PERSISTENT);
82 | REGISTER_LONG_CONSTANT("IBASE_RES_ONE_AT_A_TIME", isc_spb_res_one_at_a_time, CONST_PERSISTENT);
83 | REGISTER_LONG_CONSTANT("IBASE_RES_REPLACE", isc_spb_res_replace, CONST_PERSISTENT);
84 | REGISTER_LONG_CONSTANT("IBASE_RES_CREATE", isc_spb_res_create, CONST_PERSISTENT);
85 | REGISTER_LONG_CONSTANT("IBASE_RES_USE_ALL_SPACE", isc_spb_res_use_all_space, CONST_PERSISTENT);
86 |
87 | /* manage options */
88 | REGISTER_LONG_CONSTANT("IBASE_PRP_PAGE_BUFFERS", isc_spb_prp_page_buffers, CONST_PERSISTENT);
89 | REGISTER_LONG_CONSTANT("IBASE_PRP_SWEEP_INTERVAL", isc_spb_prp_sweep_interval, CONST_PERSISTENT);
90 | REGISTER_LONG_CONSTANT("IBASE_PRP_SHUTDOWN_DB", isc_spb_prp_shutdown_db, CONST_PERSISTENT);
91 | REGISTER_LONG_CONSTANT("IBASE_PRP_DENY_NEW_TRANSACTIONS", isc_spb_prp_deny_new_transactions, CONST_PERSISTENT);
92 | REGISTER_LONG_CONSTANT("IBASE_PRP_DENY_NEW_ATTACHMENTS", isc_spb_prp_deny_new_attachments, CONST_PERSISTENT);
93 | REGISTER_LONG_CONSTANT("IBASE_PRP_RESERVE_SPACE", isc_spb_prp_reserve_space, CONST_PERSISTENT);
94 | REGISTER_LONG_CONSTANT("IBASE_PRP_RES_USE_FULL", isc_spb_prp_res_use_full, CONST_PERSISTENT);
95 | REGISTER_LONG_CONSTANT("IBASE_PRP_RES", isc_spb_prp_res, CONST_PERSISTENT);
96 | REGISTER_LONG_CONSTANT("IBASE_PRP_WRITE_MODE", isc_spb_prp_write_mode, CONST_PERSISTENT);
97 | REGISTER_LONG_CONSTANT("IBASE_PRP_WM_ASYNC", isc_spb_prp_wm_async, CONST_PERSISTENT);
98 | REGISTER_LONG_CONSTANT("IBASE_PRP_WM_SYNC", isc_spb_prp_wm_sync, CONST_PERSISTENT);
99 | REGISTER_LONG_CONSTANT("IBASE_PRP_ACCESS_MODE", isc_spb_prp_access_mode, CONST_PERSISTENT);
100 | REGISTER_LONG_CONSTANT("IBASE_PRP_AM_READONLY", isc_spb_prp_am_readonly, CONST_PERSISTENT);
101 | REGISTER_LONG_CONSTANT("IBASE_PRP_AM_READWRITE", isc_spb_prp_am_readwrite, CONST_PERSISTENT);
102 | REGISTER_LONG_CONSTANT("IBASE_PRP_SET_SQL_DIALECT", isc_spb_prp_set_sql_dialect, CONST_PERSISTENT);
103 | REGISTER_LONG_CONSTANT("IBASE_PRP_ACTIVATE", isc_spb_prp_activate, CONST_PERSISTENT);
104 | REGISTER_LONG_CONSTANT("IBASE_PRP_DB_ONLINE", isc_spb_prp_db_online, CONST_PERSISTENT);
105 |
106 | /* repair options */
107 | REGISTER_LONG_CONSTANT("IBASE_RPR_CHECK_DB", isc_spb_rpr_check_db, CONST_PERSISTENT);
108 | REGISTER_LONG_CONSTANT("IBASE_RPR_IGNORE_CHECKSUM", isc_spb_rpr_ignore_checksum, CONST_PERSISTENT);
109 | REGISTER_LONG_CONSTANT("IBASE_RPR_KILL_SHADOWS", isc_spb_rpr_kill_shadows, CONST_PERSISTENT);
110 | REGISTER_LONG_CONSTANT("IBASE_RPR_MEND_DB", isc_spb_rpr_mend_db, CONST_PERSISTENT);
111 | REGISTER_LONG_CONSTANT("IBASE_RPR_VALIDATE_DB", isc_spb_rpr_validate_db, CONST_PERSISTENT);
112 | REGISTER_LONG_CONSTANT("IBASE_RPR_FULL", isc_spb_rpr_full, CONST_PERSISTENT);
113 | REGISTER_LONG_CONSTANT("IBASE_RPR_SWEEP_DB", isc_spb_rpr_sweep_db, CONST_PERSISTENT);
114 |
115 | /* db info arguments */
116 | REGISTER_LONG_CONSTANT("IBASE_STS_DATA_PAGES", isc_spb_sts_data_pages, CONST_PERSISTENT);
117 | REGISTER_LONG_CONSTANT("IBASE_STS_DB_LOG", isc_spb_sts_db_log, CONST_PERSISTENT);
118 | REGISTER_LONG_CONSTANT("IBASE_STS_HDR_PAGES", isc_spb_sts_hdr_pages, CONST_PERSISTENT);
119 | REGISTER_LONG_CONSTANT("IBASE_STS_IDX_PAGES", isc_spb_sts_idx_pages, CONST_PERSISTENT);
120 | REGISTER_LONG_CONSTANT("IBASE_STS_SYS_RELATIONS", isc_spb_sts_sys_relations, CONST_PERSISTENT);
121 |
122 | /* server info arguments */
123 | REGISTER_LONG_CONSTANT("IBASE_SVC_SERVER_VERSION", isc_info_svc_server_version, CONST_PERSISTENT);
124 | REGISTER_LONG_CONSTANT("IBASE_SVC_IMPLEMENTATION", isc_info_svc_implementation, CONST_PERSISTENT);
125 | REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV", isc_info_svc_get_env, CONST_PERSISTENT);
126 | REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV_LOCK", isc_info_svc_get_env_lock, CONST_PERSISTENT);
127 | REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV_MSG", isc_info_svc_get_env_msg, CONST_PERSISTENT);
128 | REGISTER_LONG_CONSTANT("IBASE_SVC_USER_DBPATH", isc_info_svc_user_dbpath, CONST_PERSISTENT);
129 | REGISTER_LONG_CONSTANT("IBASE_SVC_SVR_DB_INFO", isc_info_svc_svr_db_info, CONST_PERSISTENT);
130 | REGISTER_LONG_CONSTANT("IBASE_SVC_GET_USERS", isc_info_svc_get_users, CONST_PERSISTENT);
131 | }
132 | /* }}} */
133 |
134 | static void _php_ibase_user(INTERNAL_FUNCTION_PARAMETERS, char operation) /* {{{ */
135 | {
136 | /* user = 0, password = 1, first_name = 2, middle_name = 3, last_name = 4 */
137 | static char const user_flags[] = { isc_spb_sec_username, isc_spb_sec_password,
138 | isc_spb_sec_firstname, isc_spb_sec_middlename, isc_spb_sec_lastname };
139 | char buf[128], *args[] = { NULL, NULL, NULL, NULL, NULL };
140 | int i, args_len[] = { 0, 0, 0, 0, 0 };
141 | unsigned short spb_len = 1;
142 | zval *res;
143 | ibase_service *svm;
144 |
145 | RESET_ERRMSG;
146 |
147 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
148 | (operation == isc_action_svc_delete_user) ? "rs" : "rss|sss",
149 | &res, &args[0], &args_len[0], &args[1], &args_len[1], &args[2], &args_len[2],
150 | &args[3], &args_len[3], &args[4], &args_len[4])) {
151 | RETURN_FALSE;
152 | }
153 |
154 | svm = (ibase_service *)zend_fetch_resource_ex(res, "Interbase service manager handle",
155 | le_service);
156 |
157 | buf[0] = operation;
158 |
159 | for (i = 0; i < sizeof(user_flags); ++i) {
160 | if (args[i] != NULL) {
161 | int chunk = slprintf(&buf[spb_len], sizeof(buf) - spb_len, "%c%c%c%s",
162 | user_flags[i], (char)args_len[i], (char)(args_len[i] >> 8), args[i]);
163 |
164 | if ((spb_len + chunk) > sizeof(buf) || chunk <= 0) {
165 | _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)", spb_len);
166 | RETURN_FALSE;
167 | }
168 | spb_len += chunk;
169 | }
170 | }
171 |
172 | /* now start the job */
173 | if (isc_service_start(IB_STATUS, &svm->handle, NULL, spb_len, buf)) {
174 | IBASE_SVC_ERROR(svm);
175 | RETURN_FALSE;
176 | }
177 |
178 | RETURN_TRUE;
179 | }
180 | /* }}} */
181 |
182 | /* {{{ proto bool ibase_add_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]])
183 | Add a user to security database */
184 | PHP_FUNCTION(ibase_add_user)
185 | {
186 | _php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_add_user);
187 | }
188 | /* }}} */
189 |
190 | /* {{{ proto bool ibase_modify_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]])
191 | Modify a user in security database */
192 | PHP_FUNCTION(ibase_modify_user)
193 | {
194 | _php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_modify_user);
195 | }
196 | /* }}} */
197 |
198 | /* {{{ proto bool ibase_delete_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]])
199 | Delete a user from security database */
200 | PHP_FUNCTION(ibase_delete_user)
201 | {
202 | _php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_delete_user);
203 | }
204 | /* }}} */
205 |
206 | /* {{{ proto resource ibase_service_attach(string host, string dba_username, string dba_password)
207 | Connect to the service manager */
208 | PHP_FUNCTION(ibase_service_attach)
209 | {
210 | size_t hlen, ulen, plen, spb_len;
211 | ibase_service *svm;
212 | char buf[128], *host, *user, *pass, *loc;
213 | isc_svc_handle handle = 0;
214 |
215 | RESET_ERRMSG;
216 |
217 | if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
218 | &host, &hlen, &user, &ulen, &pass, &plen)) {
219 |
220 | RETURN_FALSE;
221 | }
222 |
223 | /* construct the spb, hack the service name into it as well */
224 | spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%s" "%s:service_mgr",
225 | isc_spb_version, isc_spb_current_version, isc_spb_user_name, (char)ulen,
226 | user, isc_spb_password, (char)plen, pass, host);
227 |
228 | if (spb_len > sizeof(buf) || spb_len == -1) {
229 | _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%zd)", spb_len);
230 | RETURN_FALSE;
231 | }
232 |
233 | spb_len -= hlen + 12;
234 | loc = buf + spb_len; /* points to %s:service_mgr part */
235 |
236 | /* attach to the service manager */
237 | if (isc_service_attach(IB_STATUS, 0, loc, &handle, (unsigned short)spb_len, buf)) {
238 | _php_ibase_error();
239 | RETURN_FALSE;
240 | }
241 |
242 | svm = (ibase_service*)emalloc(sizeof(ibase_service));
243 | svm->handle = handle;
244 | svm->hostname = estrdup(host);
245 | svm->username = estrdup(user);
246 |
247 | RETVAL_RES(zend_register_resource(svm, le_service));
248 | Z_TRY_ADDREF_P(return_value);
249 | svm->res = Z_RES_P(return_value);
250 | }
251 | /* }}} */
252 |
253 | /* {{{ proto bool ibase_service_detach(resource service_handle)
254 | Disconnect from the service manager */
255 | PHP_FUNCTION(ibase_service_detach)
256 | {
257 | zval *res;
258 |
259 | RESET_ERRMSG;
260 |
261 | if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res)) {
262 | RETURN_FALSE;
263 | }
264 |
265 | zend_list_delete(Z_RES_P(res));
266 |
267 | RETURN_TRUE;
268 | }
269 | /* }}} */
270 |
271 | static void _php_ibase_service_query(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */
272 | ibase_service *svm, char info_action)
273 | {
274 | static char spb[] = { isc_info_svc_timeout, 10, 0, 0, 0 };
275 |
276 | char res_buf[400], *result, *heap_buf = NULL, *heap_p;
277 | zend_long heap_buf_size = 200, line_len;
278 |
279 | /* info about users requires an action first */
280 | if (info_action == isc_info_svc_get_users) {
281 | static char action[] = { isc_action_svc_display_user };
282 |
283 | if (isc_service_start(IB_STATUS, &svm->handle, NULL, sizeof(action), action)) {
284 | IBASE_SVC_ERROR(svm);
285 | RETURN_FALSE;
286 | }
287 | }
288 |
289 | query_loop:
290 | result = res_buf;
291 |
292 | if (isc_service_query(IB_STATUS, &svm->handle, NULL, sizeof(spb), spb,
293 | 1, &info_action, sizeof(res_buf), res_buf)) {
294 |
295 | IBASE_SVC_ERROR(svm);
296 | RETURN_FALSE;
297 | }
298 | while (*result != isc_info_end) {
299 | switch (*result++) {
300 | default:
301 | RETURN_FALSE;
302 |
303 | case isc_info_svc_line:
304 | if (! (line_len = isc_vax_integer(result, 2))) {
305 | /* done */
306 | if (heap_buf) {
307 | RETVAL_STRING(heap_buf);
308 | efree(heap_buf);
309 | return;
310 | } else {
311 | RETURN_TRUE;
312 | }
313 | }
314 | if (!heap_buf || (heap_p - heap_buf + line_len +2) > heap_buf_size) {
315 | zend_long res_size = heap_buf ? heap_p - heap_buf : 0;
316 |
317 | while (heap_buf_size < (res_size + line_len +2)) {
318 | heap_buf_size *= 2;
319 | }
320 | heap_buf = (char*) erealloc(heap_buf, heap_buf_size);
321 | heap_p = heap_buf + res_size;
322 | }
323 | result += 2;
324 | *(result+line_len) = 0;
325 | snprintf(heap_p, heap_buf_size - (heap_p - heap_buf), "%s\n", result);
326 | heap_p += line_len +1;
327 | goto query_loop; /* repeat until result is exhausted */
328 |
329 | case isc_info_svc_server_version:
330 | case isc_info_svc_implementation:
331 | case isc_info_svc_get_env:
332 | case isc_info_svc_get_env_lock:
333 | case isc_info_svc_get_env_msg:
334 | case isc_info_svc_user_dbpath:
335 | RETURN_STRINGL(result + 2, isc_vax_integer(result, 2));
336 |
337 | case isc_info_svc_svr_db_info:
338 | array_init(return_value);
339 |
340 | do {
341 | switch (*result++) {
342 | int len;
343 |
344 | case isc_spb_num_att:
345 | add_assoc_long(return_value, "attachments", isc_vax_integer(result,4));
346 | result += 4;
347 | break;
348 |
349 | case isc_spb_num_db:
350 | add_assoc_long(return_value, "databases", isc_vax_integer(result,4));
351 | result += 4;
352 | break;
353 |
354 | case isc_spb_dbname:
355 | len = isc_vax_integer(result,2);
356 | add_next_index_stringl(return_value, result +2, len);
357 | result += len+2;
358 | }
359 | } while (*result != isc_info_flag_end);
360 | return;
361 |
362 | case isc_info_svc_get_users: {
363 | zval user;
364 | array_init(return_value);
365 |
366 | while (*result != isc_info_end) {
367 |
368 | switch (*result++) {
369 | int len;
370 |
371 | case isc_spb_sec_username:
372 | /* it appears that the username is always first */
373 | array_init(&user);
374 | add_next_index_zval(return_value, &user);
375 |
376 | len = isc_vax_integer(result,2);
377 | add_assoc_stringl(&user, "user_name", result +2, len);
378 | result += len+2;
379 | break;
380 |
381 | case isc_spb_sec_firstname:
382 | len = isc_vax_integer(result,2);
383 | add_assoc_stringl(&user, "first_name", result +2, len);
384 | result += len+2;
385 | break;
386 |
387 | case isc_spb_sec_middlename:
388 | len = isc_vax_integer(result,2);
389 | add_assoc_stringl(&user, "middle_name", result +2, len);
390 | result += len+2;
391 | break;
392 |
393 | case isc_spb_sec_lastname:
394 | len = isc_vax_integer(result,2);
395 | add_assoc_stringl(&user, "last_name", result +2, len);
396 | result += len+2;
397 | break;
398 |
399 | case isc_spb_sec_userid:
400 | add_assoc_long(&user, "user_id", isc_vax_integer(result, 4));
401 | result += 4;
402 | break;
403 |
404 | case isc_spb_sec_groupid:
405 | add_assoc_long(&user, "group_id", isc_vax_integer(result, 4));
406 | result += 4;
407 | break;
408 | }
409 | }
410 | return;
411 | }
412 | }
413 | }
414 | }
415 | /* }}} */
416 |
417 | static void _php_ibase_backup_restore(INTERNAL_FUNCTION_PARAMETERS, char operation) /* {{{ */
418 | {
419 | /**
420 | * It appears that the service API is a little bit confused about which flag
421 | * to use for the source and destination in the case of a restore operation.
422 | * When passing the backup file as isc_spb_dbname and the destination db as
423 | * bpk_file, things work well.
424 | */
425 | zval *res;
426 | char *db, *bk, buf[200];
427 | size_t dblen, bklen, spb_len;
428 | zend_long opts = 0;
429 | zend_bool verbose = 0;
430 | ibase_service *svm;
431 |
432 | RESET_ERRMSG;
433 |
434 | if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rss|lb",
435 | &res, &db, &dblen, &bk, &bklen, &opts, &verbose)) {
436 | RETURN_FALSE;
437 | }
438 |
439 | svm = (ibase_service *)zend_fetch_resource_ex(res,
440 | "Interbase service manager handle", le_service);
441 |
442 | /* fill the param buffer */
443 | spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%c%s%c%c%c%c%c",
444 | operation, isc_spb_dbname, (char)dblen, (char)(dblen >> 8), db,
445 | isc_spb_bkp_file, (char)bklen, (char)(bklen >> 8), bk, isc_spb_options,
446 | (char)opts,(char)(opts >> 8), (char)(opts >> 16), (char)(opts >> 24));
447 |
448 | if (verbose) {
449 | buf[spb_len++] = isc_spb_verbose;
450 | }
451 |
452 | if (spb_len > sizeof(buf) || spb_len <= 0) {
453 | _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%zd)", spb_len);
454 | RETURN_FALSE;
455 | }
456 |
457 | /* now start the backup/restore job */
458 | if (isc_service_start(IB_STATUS, &svm->handle, NULL, (unsigned short)spb_len, buf)) {
459 | IBASE_SVC_ERROR(svm);
460 | RETURN_FALSE;
461 | }
462 |
463 | if (!verbose) {
464 | RETURN_TRUE;
465 | } else {
466 | _php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, isc_info_svc_line);
467 | }
468 | }
469 | /* }}} */
470 |
471 | /* {{{ proto mixed ibase_backup(resource service_handle, string source_db, string dest_file [, int options [, bool verbose]])
472 | Initiates a backup task in the service manager and returns immediately */
473 | PHP_FUNCTION(ibase_backup)
474 | {
475 | _php_ibase_backup_restore(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_backup);
476 | }
477 | /* }}} */
478 |
479 | /* {{{ proto mixed ibase_restore(resource service_handle, string source_file, string dest_db [, int options [, bool verbose]])
480 | Initiates a restore task in the service manager and returns immediately */
481 | PHP_FUNCTION(ibase_restore)
482 | {
483 | _php_ibase_backup_restore(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_restore);
484 | }
485 | /* }}} */
486 |
487 | static void _php_ibase_service_action(INTERNAL_FUNCTION_PARAMETERS, char svc_action) /* {{{ */
488 | {
489 | zval *res;
490 | char buf[128], *db;
491 | size_t dblen;
492 | int spb_len;
493 | zend_long action, argument = 0;
494 | ibase_service *svm;
495 |
496 | RESET_ERRMSG;
497 |
498 | if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rsl|l",
499 | &res, &db, &dblen, &action, &argument)) {
500 | RETURN_FALSE;
501 | }
502 |
503 | svm = (ibase_service *)zend_fetch_resource_ex(res,
504 | "Interbase service manager handle", le_service);
505 |
506 | if (svc_action == isc_action_svc_db_stats) {
507 | switch (action) {
508 | default:
509 | goto unknown_option;
510 |
511 | case isc_spb_sts_data_pages:
512 | case isc_spb_sts_db_log:
513 | case isc_spb_sts_hdr_pages:
514 | case isc_spb_sts_idx_pages:
515 | case isc_spb_sts_sys_relations:
516 | goto options_argument;
517 | }
518 | } else {
519 | /* these actions all expect different types of arguments */
520 | switch (action) {
521 | default:
522 | unknown_option:
523 | _php_ibase_module_error("Unrecognised option (" ZEND_LONG_FMT ")", action);
524 | RETURN_FALSE;
525 |
526 | case isc_spb_rpr_check_db:
527 | case isc_spb_rpr_ignore_checksum:
528 | case isc_spb_rpr_kill_shadows:
529 | case isc_spb_rpr_mend_db:
530 | case isc_spb_rpr_validate_db:
531 | case isc_spb_rpr_sweep_db:
532 | svc_action = isc_action_svc_repair;
533 |
534 | case isc_spb_prp_activate:
535 | case isc_spb_prp_db_online:
536 | options_argument:
537 | argument |= action;
538 | action = isc_spb_options;
539 |
540 | case isc_spb_prp_page_buffers:
541 | case isc_spb_prp_sweep_interval:
542 | case isc_spb_prp_shutdown_db:
543 | case isc_spb_prp_deny_new_transactions:
544 | case isc_spb_prp_deny_new_attachments:
545 | case isc_spb_prp_set_sql_dialect:
546 | spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%c%c%c",
547 | svc_action, isc_spb_dbname, (char)dblen, (char)(dblen >> 8), db,
548 | (char)action, (char)argument, (char)(argument >> 8), (char)(argument >> 16),
549 | (char)(argument >> 24));
550 | break;
551 |
552 | case isc_spb_prp_reserve_space:
553 | case isc_spb_prp_write_mode:
554 | case isc_spb_prp_access_mode:
555 | spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c",
556 | isc_action_svc_properties, isc_spb_dbname, (char)dblen, (char)(dblen >> 8),
557 | db, (char)action, (char)argument);
558 | }
559 | }
560 |
561 | if (spb_len > sizeof(buf) || spb_len == -1) {
562 | _php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)", spb_len);
563 | RETURN_FALSE;
564 | }
565 |
566 | if (isc_service_start(IB_STATUS, &svm->handle, NULL, (unsigned short)spb_len, buf)) {
567 | IBASE_SVC_ERROR(svm);
568 | RETURN_FALSE;
569 | }
570 |
571 | if (svc_action == isc_action_svc_db_stats) {
572 | _php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, isc_info_svc_line);
573 | } else {
574 | RETURN_TRUE;
575 | }
576 | }
577 | /* }}} */
578 |
579 | /* {{{ proto bool ibase_maintain_db(resource service_handle, string db, int action [, int argument])
580 | Execute a maintenance command on the database server */
581 | PHP_FUNCTION(ibase_maintain_db)
582 | {
583 | _php_ibase_service_action(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_properties);
584 | }
585 | /* }}} */
586 |
587 | /* {{{ proto string ibase_db_info(resource service_handle, string db, int action [, int argument])
588 | Request statistics about a database */
589 | PHP_FUNCTION(ibase_db_info)
590 | {
591 | _php_ibase_service_action(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_db_stats);
592 | }
593 | /* }}} */
594 |
595 | /* {{{ proto string ibase_server_info(resource service_handle, int action)
596 | Request information about a database server */
597 | PHP_FUNCTION(ibase_server_info)
598 | {
599 | zval *res;
600 | zend_long action;
601 | ibase_service *svm;
602 |
603 | RESET_ERRMSG;
604 |
605 | if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &res, &action)) {
606 | RETURN_FALSE;
607 | }
608 |
609 | svm = (ibase_service *)zend_fetch_resource_ex(res,
610 | "Interbase service manager handle", le_service);
611 |
612 | _php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, (char)action);
613 | }
614 | /* }}} */
615 |
616 | #else
617 |
618 | void php_ibase_register_service_constants(INIT_FUNC_ARGS) { /* nop */ }
619 |
620 | #endif /* HAVE_IBASE */
621 |
--------------------------------------------------------------------------------
/interbase.c:
--------------------------------------------------------------------------------
1 | /*
2 | +----------------------------------------------------------------------+
3 | | PHP Version 7 |
4 | +----------------------------------------------------------------------+
5 | | Copyright (c) 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 | | Authors: Jouni Ahto |
16 | | Andrew Avdeev |
17 | | Ard Biesheuvel |
18 | +----------------------------------------------------------------------+
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h"
23 | #endif
24 |
25 | #define _GNU_SOURCE
26 |
27 | #include "php.h"
28 |
29 | #if HAVE_IBASE
30 |
31 | #include "php_ini.h"
32 | #include "ext/standard/php_standard.h"
33 | #include "ext/standard/md5.h"
34 | #include "php_interbase.h"
35 | #include "php_ibase_includes.h"
36 | #include "SAPI.h"
37 |
38 | #include
39 |
40 | #define ROLLBACK 0
41 | #define COMMIT 1
42 | #define RETAIN 2
43 |
44 | #define CHECK_LINK(link) { if (link==NULL) { php_error_docref(NULL, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } }
45 |
46 | ZEND_DECLARE_MODULE_GLOBALS(ibase)
47 | static PHP_GINIT_FUNCTION(ibase);
48 |
49 | /* {{{ arginfo */
50 | ZEND_BEGIN_ARG_INFO(arginfo_ibase_errmsg, 0)
51 | ZEND_END_ARG_INFO()
52 |
53 | ZEND_BEGIN_ARG_INFO(arginfo_ibase_errcode, 0)
54 | ZEND_END_ARG_INFO()
55 |
56 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_connect, 0, 0, 0)
57 | ZEND_ARG_INFO(0, database)
58 | ZEND_ARG_INFO(0, username)
59 | ZEND_ARG_INFO(0, password)
60 | ZEND_ARG_INFO(0, charset)
61 | ZEND_ARG_INFO(0, buffers)
62 | ZEND_ARG_INFO(0, dialect)
63 | ZEND_ARG_INFO(0, role)
64 | ZEND_END_ARG_INFO()
65 |
66 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_pconnect, 0, 0, 0)
67 | ZEND_ARG_INFO(0, database)
68 | ZEND_ARG_INFO(0, username)
69 | ZEND_ARG_INFO(0, password)
70 | ZEND_ARG_INFO(0, charset)
71 | ZEND_ARG_INFO(0, buffers)
72 | ZEND_ARG_INFO(0, dialect)
73 | ZEND_ARG_INFO(0, role)
74 | ZEND_END_ARG_INFO()
75 |
76 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_close, 0, 0, 0)
77 | ZEND_ARG_INFO(0, link_identifier)
78 | ZEND_END_ARG_INFO()
79 |
80 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_drop_db, 0, 0, 0)
81 | ZEND_ARG_INFO(0, link_identifier)
82 | ZEND_END_ARG_INFO()
83 |
84 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_trans, 0, 0, 0)
85 | ZEND_ARG_INFO(0, trans_args)
86 | ZEND_ARG_INFO(0, link_identifier)
87 | ZEND_ARG_INFO(0, trans_args)
88 | ZEND_ARG_INFO(0, link_identifier)
89 | ZEND_END_ARG_INFO()
90 |
91 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit, 0, 0, 1)
92 | ZEND_ARG_INFO(0, link_identifier)
93 | ZEND_END_ARG_INFO()
94 |
95 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback, 0, 0, 1)
96 | ZEND_ARG_INFO(0, link_identifier)
97 | ZEND_END_ARG_INFO()
98 |
99 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit_ret, 0, 0, 1)
100 | ZEND_ARG_INFO(0, link_identifier)
101 | ZEND_END_ARG_INFO()
102 |
103 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback_ret, 0, 0, 1)
104 | ZEND_ARG_INFO(0, link_identifier)
105 | ZEND_END_ARG_INFO()
106 |
107 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_gen_id, 0, 0, 1)
108 | ZEND_ARG_INFO(0, generator)
109 | ZEND_ARG_INFO(0, increment)
110 | ZEND_ARG_INFO(0, link_identifier)
111 | ZEND_END_ARG_INFO()
112 |
113 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_create, 0, 0, 0)
114 | ZEND_ARG_INFO(0, link_identifier)
115 | ZEND_END_ARG_INFO()
116 |
117 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_open, 0, 0, 0)
118 | ZEND_ARG_INFO(0, link_identifier)
119 | ZEND_ARG_INFO(0, blob_id)
120 | ZEND_END_ARG_INFO()
121 |
122 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_add, 0, 0, 2)
123 | ZEND_ARG_INFO(0, blob_handle)
124 | ZEND_ARG_INFO(0, data)
125 | ZEND_END_ARG_INFO()
126 |
127 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_get, 0, 0, 2)
128 | ZEND_ARG_INFO(0, blob_handle)
129 | ZEND_ARG_INFO(0, len)
130 | ZEND_END_ARG_INFO()
131 |
132 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_close, 0, 0, 1)
133 | ZEND_ARG_INFO(0, blob_handle)
134 | ZEND_END_ARG_INFO()
135 |
136 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_cancel, 0, 0, 1)
137 | ZEND_ARG_INFO(0, blob_handle)
138 | ZEND_END_ARG_INFO()
139 |
140 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_info, 0, 0, 0)
141 | ZEND_ARG_INFO(0, link_identifier)
142 | ZEND_ARG_INFO(0, blob_id)
143 | ZEND_END_ARG_INFO()
144 |
145 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_echo, 0, 0, 0)
146 | ZEND_ARG_INFO(0, link_identifier)
147 | ZEND_ARG_INFO(0, blob_id)
148 | ZEND_END_ARG_INFO()
149 |
150 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_import, 0, 0, 0)
151 | ZEND_ARG_INFO(0, link_identifier)
152 | ZEND_ARG_INFO(0, file)
153 | ZEND_END_ARG_INFO()
154 |
155 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_query, 0, 0, 0)
156 | ZEND_ARG_INFO(0, link_identifier)
157 | ZEND_ARG_INFO(0, link_identifier)
158 | ZEND_ARG_INFO(0, query)
159 | ZEND_ARG_INFO(0, bind_arg)
160 | ZEND_ARG_INFO(0, bind_arg)
161 | ZEND_END_ARG_INFO()
162 |
163 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_affected_rows, 0, 0, 0)
164 | ZEND_ARG_INFO(0, link_identifier)
165 | ZEND_END_ARG_INFO()
166 |
167 | #if abies_0
168 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_rows, 0, 0, 1)
169 | ZEND_ARG_INFO(0, result_identifier)
170 | ZEND_END_ARG_INFO()
171 | #endif
172 |
173 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_row, 0, 0, 1)
174 | ZEND_ARG_INFO(0, result)
175 | ZEND_ARG_INFO(0, fetch_flags)
176 | ZEND_END_ARG_INFO()
177 |
178 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_assoc, 0, 0, 1)
179 | ZEND_ARG_INFO(0, result)
180 | ZEND_ARG_INFO(0, fetch_flags)
181 | ZEND_END_ARG_INFO()
182 |
183 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_object, 0, 0, 1)
184 | ZEND_ARG_INFO(0, result)
185 | ZEND_ARG_INFO(0, fetch_flags)
186 | ZEND_END_ARG_INFO()
187 |
188 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_name_result, 0, 0, 2)
189 | ZEND_ARG_INFO(0, result)
190 | ZEND_ARG_INFO(0, name)
191 | ZEND_END_ARG_INFO()
192 |
193 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_result, 0, 0, 1)
194 | ZEND_ARG_INFO(0, result)
195 | ZEND_END_ARG_INFO()
196 |
197 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_prepare, 0, 0, 0)
198 | ZEND_ARG_INFO(0, link_identifier)
199 | ZEND_ARG_INFO(0, query)
200 | ZEND_END_ARG_INFO()
201 |
202 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_execute, 0, 0, 1)
203 | ZEND_ARG_INFO(0, query)
204 | ZEND_ARG_INFO(0, bind_arg)
205 | ZEND_ARG_INFO(0, bind_arg)
206 | ZEND_END_ARG_INFO()
207 |
208 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_query, 0, 0, 1)
209 | ZEND_ARG_INFO(0, query)
210 | ZEND_END_ARG_INFO()
211 |
212 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_fields, 0, 0, 1)
213 | ZEND_ARG_INFO(0, query_result)
214 | ZEND_END_ARG_INFO()
215 |
216 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_field_info, 0, 0, 2)
217 | ZEND_ARG_INFO(0, query_result)
218 | ZEND_ARG_INFO(0, field_number)
219 | ZEND_END_ARG_INFO()
220 |
221 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_params, 0, 0, 1)
222 | ZEND_ARG_INFO(0, query)
223 | ZEND_END_ARG_INFO()
224 |
225 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_param_info, 0, 0, 2)
226 | ZEND_ARG_INFO(0, query)
227 | ZEND_ARG_INFO(0, field_number)
228 | ZEND_END_ARG_INFO()
229 |
230 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_add_user, 0, 0, 3)
231 | ZEND_ARG_INFO(0, service_handle)
232 | ZEND_ARG_INFO(0, user_name)
233 | ZEND_ARG_INFO(0, password)
234 | ZEND_ARG_INFO(0, first_name)
235 | ZEND_ARG_INFO(0, middle_name)
236 | ZEND_ARG_INFO(0, last_name)
237 | ZEND_END_ARG_INFO()
238 |
239 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_modify_user, 0, 0, 3)
240 | ZEND_ARG_INFO(0, service_handle)
241 | ZEND_ARG_INFO(0, user_name)
242 | ZEND_ARG_INFO(0, password)
243 | ZEND_ARG_INFO(0, first_name)
244 | ZEND_ARG_INFO(0, middle_name)
245 | ZEND_ARG_INFO(0, last_name)
246 | ZEND_END_ARG_INFO()
247 |
248 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_delete_user, 0, 0, 3)
249 | ZEND_ARG_INFO(0, service_handle)
250 | ZEND_ARG_INFO(0, user_name)
251 | ZEND_ARG_INFO(0, password)
252 | ZEND_ARG_INFO(0, first_name)
253 | ZEND_ARG_INFO(0, middle_name)
254 | ZEND_ARG_INFO(0, last_name)
255 | ZEND_END_ARG_INFO()
256 |
257 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_attach, 0, 0, 3)
258 | ZEND_ARG_INFO(0, host)
259 | ZEND_ARG_INFO(0, dba_username)
260 | ZEND_ARG_INFO(0, dba_password)
261 | ZEND_END_ARG_INFO()
262 |
263 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_detach, 0, 0, 1)
264 | ZEND_ARG_INFO(0, service_handle)
265 | ZEND_END_ARG_INFO()
266 |
267 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_backup, 0, 0, 3)
268 | ZEND_ARG_INFO(0, service_handle)
269 | ZEND_ARG_INFO(0, source_db)
270 | ZEND_ARG_INFO(0, dest_file)
271 | ZEND_ARG_INFO(0, options)
272 | ZEND_ARG_INFO(0, verbose)
273 | ZEND_END_ARG_INFO()
274 |
275 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_restore, 0, 0, 3)
276 | ZEND_ARG_INFO(0, service_handle)
277 | ZEND_ARG_INFO(0, source_file)
278 | ZEND_ARG_INFO(0, dest_db)
279 | ZEND_ARG_INFO(0, options)
280 | ZEND_ARG_INFO(0, verbose)
281 | ZEND_END_ARG_INFO()
282 |
283 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_maintain_db, 0, 0, 3)
284 | ZEND_ARG_INFO(0, service_handle)
285 | ZEND_ARG_INFO(0, db)
286 | ZEND_ARG_INFO(0, action)
287 | ZEND_ARG_INFO(0, argument)
288 | ZEND_END_ARG_INFO()
289 |
290 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_db_info, 0, 0, 3)
291 | ZEND_ARG_INFO(0, service_handle)
292 | ZEND_ARG_INFO(0, db)
293 | ZEND_ARG_INFO(0, action)
294 | ZEND_ARG_INFO(0, argument)
295 | ZEND_END_ARG_INFO()
296 |
297 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_server_info, 0, 0, 2)
298 | ZEND_ARG_INFO(0, service_handle)
299 | ZEND_ARG_INFO(0, action)
300 | ZEND_END_ARG_INFO()
301 |
302 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_wait_event, 0, 0, 1)
303 | ZEND_ARG_INFO(0, link_identifier)
304 | ZEND_ARG_INFO(0, event)
305 | ZEND_ARG_INFO(0, event2)
306 | ZEND_END_ARG_INFO()
307 |
308 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_set_event_handler, 0, 0, 2)
309 | ZEND_ARG_INFO(0, link_identifier)
310 | ZEND_ARG_INFO(0, handler)
311 | ZEND_ARG_INFO(0, event)
312 | ZEND_ARG_INFO(0, event2)
313 | ZEND_END_ARG_INFO()
314 |
315 | ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_event_handler, 0, 0, 1)
316 | ZEND_ARG_INFO(0, event)
317 | ZEND_END_ARG_INFO()
318 | /* }}} */
319 |
320 | /* {{{ extension definition structures */
321 | static const zend_function_entry ibase_functions[] = {
322 | PHP_FE(ibase_connect, arginfo_ibase_connect)
323 | PHP_FE(ibase_pconnect, arginfo_ibase_pconnect)
324 | PHP_FE(ibase_close, arginfo_ibase_close)
325 | PHP_FE(ibase_drop_db, arginfo_ibase_drop_db)
326 | PHP_FE(ibase_query, arginfo_ibase_query)
327 | PHP_FE(ibase_fetch_row, arginfo_ibase_fetch_row)
328 | PHP_FE(ibase_fetch_assoc, arginfo_ibase_fetch_assoc)
329 | PHP_FE(ibase_fetch_object, arginfo_ibase_fetch_object)
330 | PHP_FE(ibase_free_result, arginfo_ibase_free_result)
331 | PHP_FE(ibase_name_result, arginfo_ibase_name_result)
332 | PHP_FE(ibase_prepare, arginfo_ibase_prepare)
333 | PHP_FE(ibase_execute, arginfo_ibase_execute)
334 | PHP_FE(ibase_free_query, arginfo_ibase_free_query)
335 | PHP_FE(ibase_gen_id, arginfo_ibase_gen_id)
336 | PHP_FE(ibase_num_fields, arginfo_ibase_num_fields)
337 | PHP_FE(ibase_num_params, arginfo_ibase_num_params)
338 | #if abies_0
339 | PHP_FE(ibase_num_rows, arginfo_ibase_num_rows)
340 | #endif
341 | PHP_FE(ibase_affected_rows, arginfo_ibase_affected_rows)
342 | PHP_FE(ibase_field_info, arginfo_ibase_field_info)
343 | PHP_FE(ibase_param_info, arginfo_ibase_param_info)
344 |
345 | PHP_FE(ibase_trans, arginfo_ibase_trans)
346 | PHP_FE(ibase_commit, arginfo_ibase_commit)
347 | PHP_FE(ibase_rollback, arginfo_ibase_rollback)
348 | PHP_FE(ibase_commit_ret, arginfo_ibase_commit_ret)
349 | PHP_FE(ibase_rollback_ret, arginfo_ibase_rollback_ret)
350 |
351 | PHP_FE(ibase_blob_info, arginfo_ibase_blob_info)
352 | PHP_FE(ibase_blob_create, arginfo_ibase_blob_create)
353 | PHP_FE(ibase_blob_add, arginfo_ibase_blob_add)
354 | PHP_FE(ibase_blob_cancel, arginfo_ibase_blob_cancel)
355 | PHP_FE(ibase_blob_close, arginfo_ibase_blob_close)
356 | PHP_FE(ibase_blob_open, arginfo_ibase_blob_open)
357 | PHP_FE(ibase_blob_get, arginfo_ibase_blob_get)
358 | PHP_FE(ibase_blob_echo, arginfo_ibase_blob_echo)
359 | PHP_FE(ibase_blob_import, arginfo_ibase_blob_import)
360 | PHP_FE(ibase_errmsg, arginfo_ibase_errmsg)
361 | PHP_FE(ibase_errcode, arginfo_ibase_errcode)
362 |
363 | PHP_FE(ibase_add_user, arginfo_ibase_add_user)
364 | PHP_FE(ibase_modify_user, arginfo_ibase_modify_user)
365 | PHP_FE(ibase_delete_user, arginfo_ibase_delete_user)
366 |
367 | PHP_FE(ibase_service_attach, arginfo_ibase_service_attach)
368 | PHP_FE(ibase_service_detach, arginfo_ibase_service_detach)
369 | PHP_FE(ibase_backup, arginfo_ibase_backup)
370 | PHP_FE(ibase_restore, arginfo_ibase_restore)
371 | PHP_FE(ibase_maintain_db, arginfo_ibase_maintain_db)
372 | PHP_FE(ibase_db_info, arginfo_ibase_db_info)
373 | PHP_FE(ibase_server_info, arginfo_ibase_server_info)
374 |
375 | PHP_FE(ibase_wait_event, arginfo_ibase_wait_event)
376 | PHP_FE(ibase_set_event_handler, arginfo_ibase_set_event_handler)
377 | PHP_FE(ibase_free_event_handler, arginfo_ibase_free_event_handler)
378 |
379 | /**
380 | * These aliases are provided in order to maintain forward compatibility. As Firebird
381 | * and InterBase are developed independently, functionality might be different between
382 | * the two branches in future versions.
383 | * Firebird users should use the aliases, so future InterBase-specific changes will
384 | * not affect their code
385 | */
386 | PHP_FALIAS(fbird_connect, ibase_connect, arginfo_ibase_connect)
387 | PHP_FALIAS(fbird_pconnect, ibase_pconnect, arginfo_ibase_pconnect)
388 | PHP_FALIAS(fbird_close, ibase_close, arginfo_ibase_close)
389 | PHP_FALIAS(fbird_drop_db, ibase_drop_db, arginfo_ibase_drop_db)
390 | PHP_FALIAS(fbird_query, ibase_query, arginfo_ibase_query)
391 | PHP_FALIAS(fbird_fetch_row, ibase_fetch_row, arginfo_ibase_fetch_row)
392 | PHP_FALIAS(fbird_fetch_assoc, ibase_fetch_assoc, arginfo_ibase_fetch_assoc)
393 | PHP_FALIAS(fbird_fetch_object, ibase_fetch_object, arginfo_ibase_fetch_object)
394 | PHP_FALIAS(fbird_free_result, ibase_free_result, arginfo_ibase_free_result)
395 | PHP_FALIAS(fbird_name_result, ibase_name_result, arginfo_ibase_name_result)
396 | PHP_FALIAS(fbird_prepare, ibase_prepare, arginfo_ibase_prepare)
397 | PHP_FALIAS(fbird_execute, ibase_execute, arginfo_ibase_execute)
398 | PHP_FALIAS(fbird_free_query, ibase_free_query, arginfo_ibase_free_query)
399 | PHP_FALIAS(fbird_gen_id, ibase_gen_id, arginfo_ibase_gen_id)
400 | PHP_FALIAS(fbird_num_fields, ibase_num_fields, arginfo_ibase_num_fields)
401 | PHP_FALIAS(fbird_num_params, ibase_num_params, arginfo_ibase_num_params)
402 | #if abies_0
403 | PHP_FALIAS(fbird_num_rows, ibase_num_rows, arginfo_ibase_num_rows)
404 | #endif
405 | PHP_FALIAS(fbird_affected_rows, ibase_affected_rows, arginfo_ibase_affected_rows)
406 | PHP_FALIAS(fbird_field_info, ibase_field_info, arginfo_ibase_field_info)
407 | PHP_FALIAS(fbird_param_info, ibase_param_info, arginfo_ibase_param_info)
408 |
409 | PHP_FALIAS(fbird_trans, ibase_trans, arginfo_ibase_trans)
410 | PHP_FALIAS(fbird_commit, ibase_commit, arginfo_ibase_commit)
411 | PHP_FALIAS(fbird_rollback, ibase_rollback, arginfo_ibase_rollback)
412 | PHP_FALIAS(fbird_commit_ret, ibase_commit_ret, arginfo_ibase_commit_ret)
413 | PHP_FALIAS(fbird_rollback_ret, ibase_rollback_ret, arginfo_ibase_rollback_ret)
414 |
415 | PHP_FALIAS(fbird_blob_info, ibase_blob_info, arginfo_ibase_blob_info)
416 | PHP_FALIAS(fbird_blob_create, ibase_blob_create, arginfo_ibase_blob_create)
417 | PHP_FALIAS(fbird_blob_add, ibase_blob_add, arginfo_ibase_blob_add)
418 | PHP_FALIAS(fbird_blob_cancel, ibase_blob_cancel, arginfo_ibase_blob_cancel)
419 | PHP_FALIAS(fbird_blob_close, ibase_blob_close, arginfo_ibase_blob_close)
420 | PHP_FALIAS(fbird_blob_open, ibase_blob_open, arginfo_ibase_blob_open)
421 | PHP_FALIAS(fbird_blob_get, ibase_blob_get, arginfo_ibase_blob_get)
422 | PHP_FALIAS(fbird_blob_echo, ibase_blob_echo, arginfo_ibase_blob_echo)
423 | PHP_FALIAS(fbird_blob_import, ibase_blob_import, arginfo_ibase_blob_import)
424 | PHP_FALIAS(fbird_errmsg, ibase_errmsg, arginfo_ibase_errmsg)
425 | PHP_FALIAS(fbird_errcode, ibase_errcode, arginfo_ibase_errcode)
426 |
427 | PHP_FALIAS(fbird_add_user, ibase_add_user, arginfo_ibase_add_user)
428 | PHP_FALIAS(fbird_modify_user, ibase_modify_user, arginfo_ibase_modify_user)
429 | PHP_FALIAS(fbird_delete_user, ibase_delete_user, arginfo_ibase_delete_user)
430 |
431 | PHP_FALIAS(fbird_service_attach, ibase_service_attach, arginfo_ibase_service_attach)
432 | PHP_FALIAS(fbird_service_detach, ibase_service_detach, arginfo_ibase_service_detach)
433 | PHP_FALIAS(fbird_backup, ibase_backup, arginfo_ibase_backup)
434 | PHP_FALIAS(fbird_restore, ibase_restore, arginfo_ibase_restore)
435 | PHP_FALIAS(fbird_maintain_db, ibase_maintain_db, arginfo_ibase_maintain_db)
436 | PHP_FALIAS(fbird_db_info, ibase_db_info, arginfo_ibase_db_info)
437 | PHP_FALIAS(fbird_server_info, ibase_server_info, arginfo_ibase_server_info)
438 |
439 | PHP_FALIAS(fbird_wait_event, ibase_wait_event, arginfo_ibase_wait_event)
440 | PHP_FALIAS(fbird_set_event_handler, ibase_set_event_handler, arginfo_ibase_set_event_handler)
441 | PHP_FALIAS(fbird_free_event_handler, ibase_free_event_handler, arginfo_ibase_free_event_handler)
442 | PHP_FE_END
443 | };
444 |
445 | zend_module_entry ibase_module_entry = {
446 | STANDARD_MODULE_HEADER,
447 | "interbase",
448 | ibase_functions,
449 | PHP_MINIT(ibase),
450 | PHP_MSHUTDOWN(ibase),
451 | NULL,
452 | PHP_RSHUTDOWN(ibase),
453 | PHP_MINFO(ibase),
454 | PHP_INTERBASE_VERSION,
455 | PHP_MODULE_GLOBALS(ibase),
456 | PHP_GINIT(ibase),
457 | NULL,
458 | NULL,
459 | STANDARD_MODULE_PROPERTIES_EX
460 | };
461 |
462 | #ifdef COMPILE_DL_INTERBASE
463 | #ifdef ZTS
464 | ZEND_TSRMLS_CACHE_DEFINE()
465 | #endif
466 | ZEND_GET_MODULE(ibase)
467 | #endif
468 |
469 | /* True globals, no need for thread safety */
470 | int le_link, le_plink, le_trans;
471 |
472 | /* }}} */
473 |
474 | /* error handling ---------------------------- */
475 |
476 | /* {{{ proto string ibase_errmsg(void)
477 | Return error message */
478 | PHP_FUNCTION(ibase_errmsg)
479 | {
480 | if (zend_parse_parameters_none() == FAILURE) {
481 | return;
482 | }
483 |
484 | if (IBG(sql_code) != 0) {
485 | RETURN_STRING(IBG(errmsg));
486 | }
487 |
488 | RETURN_FALSE;
489 | }
490 | /* }}} */
491 |
492 | /* {{{ proto int ibase_errcode(void)
493 | Return error code */
494 | PHP_FUNCTION(ibase_errcode)
495 | {
496 | if (zend_parse_parameters_none() == FAILURE) {
497 | return;
498 | }
499 |
500 | if (IBG(sql_code) != 0) {
501 | RETURN_LONG(IBG(sql_code));
502 | }
503 | RETURN_FALSE;
504 | }
505 | /* }}} */
506 |
507 | /* print interbase error and save it for ibase_errmsg() */
508 | void _php_ibase_error(void) /* {{{ */
509 | {
510 | char *s = IBG(errmsg);
511 | const ISC_STATUS *statusp = IB_STATUS;
512 |
513 | IBG(sql_code) = isc_sqlcode(IB_STATUS);
514 |
515 | while ((s - IBG(errmsg)) < MAX_ERRMSG && fb_interpret(s, MAX_ERRMSG - strlen(IBG(errmsg)) - 1, &statusp)) {
516 | strcat(IBG(errmsg), " ");
517 | s = IBG(errmsg) + strlen(IBG(errmsg));
518 | }
519 |
520 | php_error_docref(NULL, E_WARNING, "%s", IBG(errmsg));
521 | }
522 | /* }}} */
523 |
524 | /* print php interbase module error and save it for ibase_errmsg() */
525 | void _php_ibase_module_error(char *msg, ...) /* {{{ */
526 | {
527 | va_list ap;
528 |
529 | va_start(ap, msg);
530 |
531 | /* vsnprintf NUL terminates the buf and writes at most n-1 chars+NUL */
532 | vsnprintf(IBG(errmsg), MAX_ERRMSG, msg, ap);
533 | va_end(ap);
534 |
535 | IBG(sql_code) = -999; /* no SQL error */
536 |
537 | php_error_docref(NULL, E_WARNING, "%s", IBG(errmsg));
538 | }
539 | /* }}} */
540 |
541 | /* {{{ internal macros, functions and structures */
542 | typedef struct {
543 | isc_db_handle *db_ptr;
544 | zend_long tpb_len;
545 | char *tpb_ptr;
546 | } ISC_TEB;
547 |
548 | /* }}} */
549 |
550 | /* Fill ib_link and trans with the correct database link and transaction. */
551 | void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */
552 | zval *link_id, ibase_db_link **ib_link, ibase_trans **trans)
553 | {
554 | IBDEBUG("Transaction or database link?");
555 | if (Z_RES_P(link_id)->type == le_trans) {
556 | /* Transaction resource: make sure it refers to one link only, then
557 | fetch it; database link is stored in ib_trans->db_link[]. */
558 | IBDEBUG("Type is le_trans");
559 | *trans = (ibase_trans *)zend_fetch_resource_ex(link_id, LE_TRANS, le_trans);
560 | if ((*trans)->link_cnt > 1) {
561 | _php_ibase_module_error("Link id is ambiguous: transaction spans multiple connections."
562 | );
563 | return;
564 | }
565 | *ib_link = (*trans)->db_link[0];
566 | return;
567 | }
568 | IBDEBUG("Type is le_[p]link or id not found");
569 | /* Database link resource, use default transaction. */
570 | *trans = NULL;
571 | *ib_link = (ibase_db_link *)zend_fetch_resource2_ex(link_id, LE_LINK, le_link, le_plink);
572 | }
573 | /* }}} */
574 |
575 | /* destructors ---------------------- */
576 |
577 | static void _php_ibase_commit_link(ibase_db_link *link) /* {{{ */
578 | {
579 | unsigned short i = 0, j;
580 | ibase_tr_list *l;
581 | ibase_event *e;
582 | IBDEBUG("Checking transactions to close...");
583 |
584 | for (l = link->tr_list; l != NULL; ++i) {
585 | ibase_tr_list *p = l;
586 | if (p->trans != 0) {
587 | if (i == 0) {
588 | if (p->trans->handle != 0) {
589 | IBDEBUG("Committing default transaction...");
590 | if (isc_commit_transaction(IB_STATUS, &p->trans->handle)) {
591 | _php_ibase_error();
592 | }
593 | }
594 | efree(p->trans); /* default transaction is not a registered resource: clean up */
595 | } else {
596 | if (p->trans->handle != 0) {
597 | /* non-default trans might have been rolled back by other call of this dtor */
598 | IBDEBUG("Rolling back other transactions...");
599 | if (isc_rollback_transaction(IB_STATUS, &p->trans->handle)) {
600 | _php_ibase_error();
601 | }
602 | }
603 | /* set this link pointer to NULL in the transaction */
604 | for (j = 0; j < p->trans->link_cnt; ++j) {
605 | if (p->trans->db_link[j] == link) {
606 | p->trans->db_link[j] = NULL;
607 | break;
608 | }
609 | }
610 | }
611 | }
612 | l = l->next;
613 | efree(p);
614 | }
615 | link->tr_list = NULL;
616 |
617 | for (e = link->event_head; e; e = e->event_next) {
618 | _php_ibase_free_event(e);
619 | e->link = NULL;
620 | }
621 | }
622 |
623 | /* }}} */
624 |
625 | static void php_ibase_commit_link_rsrc(zend_resource *rsrc) /* {{{ */
626 | {
627 | ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
628 |
629 | _php_ibase_commit_link(link);
630 | }
631 | /* }}} */
632 |
633 | static void _php_ibase_close_link(zend_resource *rsrc) /* {{{ */
634 | {
635 | ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
636 |
637 | _php_ibase_commit_link(link);
638 | if (link->handle != 0) {
639 | IBDEBUG("Closing normal link...");
640 | isc_detach_database(IB_STATUS, &link->handle);
641 | }
642 | IBG(num_links)--;
643 | efree(link);
644 | }
645 | /* }}} */
646 |
647 | static void _php_ibase_close_plink(zend_resource *rsrc) /* {{{ */
648 | {
649 | ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
650 |
651 | _php_ibase_commit_link(link);
652 | IBDEBUG("Closing permanent link...");
653 | if (link->handle != 0) {
654 | isc_detach_database(IB_STATUS, &link->handle);
655 | }
656 | IBG(num_persistent)--;
657 | IBG(num_links)--;
658 | free(link);
659 | }
660 | /* }}} */
661 |
662 | static void _php_ibase_free_trans(zend_resource *rsrc) /* {{{ */
663 | {
664 | ibase_trans *trans = (ibase_trans *)rsrc->ptr;
665 | unsigned short i;
666 |
667 | IBDEBUG("Cleaning up transaction resource...");
668 | if (trans->handle != 0) {
669 | IBDEBUG("Rolling back unhandled transaction...");
670 | if (isc_rollback_transaction(IB_STATUS, &trans->handle)) {
671 | _php_ibase_error();
672 | }
673 | }
674 |
675 | /* now remove this transaction from all the connection-transaction lists */
676 | for (i = 0; i < trans->link_cnt; ++i) {
677 | if (trans->db_link[i] != NULL) {
678 | ibase_tr_list **l;
679 | for (l = &trans->db_link[i]->tr_list; *l != NULL; l = &(*l)->next) {
680 | if ( (*l)->trans == trans) {
681 | ibase_tr_list *p = *l;
682 | *l = p->next;
683 | efree(p);
684 | break;
685 | }
686 | }
687 | }
688 | }
689 | efree(trans);
690 | }
691 | /* }}} */
692 |
693 | /* TODO this function should be part of either Zend or PHP API */
694 | static PHP_INI_DISP(php_ibase_password_displayer_cb)
695 | {
696 |
697 | if ((type == PHP_INI_DISPLAY_ORIG && ini_entry->orig_value)
698 | || (type == PHP_INI_DISPLAY_ACTIVE && ini_entry->value)) {
699 | PUTS("********");
700 | } else if (!sapi_module.phpinfo_as_text) {
701 | PUTS("no value");
702 | } else {
703 | PUTS("no value");
704 | }
705 | }
706 |
707 | /* {{{ startup, shutdown and info functions */
708 | PHP_INI_BEGIN()
709 | PHP_INI_ENTRY_EX("ibase.allow_persistent", "1", PHP_INI_SYSTEM, NULL, zend_ini_boolean_displayer_cb)
710 | PHP_INI_ENTRY_EX("ibase.max_persistent", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers)
711 | PHP_INI_ENTRY_EX("ibase.max_links", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers)
712 | PHP_INI_ENTRY("ibase.default_db", NULL, PHP_INI_SYSTEM, NULL)
713 | PHP_INI_ENTRY("ibase.default_user", NULL, PHP_INI_ALL, NULL)
714 | PHP_INI_ENTRY_EX("ibase.default_password", NULL, PHP_INI_ALL, NULL, php_ibase_password_displayer_cb)
715 | PHP_INI_ENTRY("ibase.default_charset", NULL, PHP_INI_ALL, NULL)
716 | PHP_INI_ENTRY("ibase.timestampformat", IB_DEF_DATE_FMT " " IB_DEF_TIME_FMT, PHP_INI_ALL, NULL)
717 | PHP_INI_ENTRY("ibase.dateformat", IB_DEF_DATE_FMT, PHP_INI_ALL, NULL)
718 | PHP_INI_ENTRY("ibase.timeformat", IB_DEF_TIME_FMT, PHP_INI_ALL, NULL)
719 | PHP_INI_END()
720 |
721 | static PHP_GINIT_FUNCTION(ibase)
722 | {
723 | #if defined(COMPILE_DL_INTERBASE) && defined(ZTS)
724 | ZEND_TSRMLS_CACHE_UPDATE();
725 | #endif
726 | ibase_globals->num_persistent = ibase_globals->num_links = 0;
727 | ibase_globals->sql_code = *ibase_globals->errmsg = 0;
728 | ibase_globals->default_link = NULL;
729 | }
730 |
731 | PHP_MINIT_FUNCTION(ibase)
732 | {
733 | REGISTER_INI_ENTRIES();
734 |
735 | le_link = zend_register_list_destructors_ex(_php_ibase_close_link, NULL, LE_LINK, module_number);
736 | le_plink = zend_register_list_destructors_ex(php_ibase_commit_link_rsrc, _php_ibase_close_plink, LE_PLINK, module_number);
737 | le_trans = zend_register_list_destructors_ex(_php_ibase_free_trans, NULL, LE_TRANS, module_number);
738 |
739 | REGISTER_LONG_CONSTANT("IBASE_DEFAULT", PHP_IBASE_DEFAULT, CONST_PERSISTENT);
740 | REGISTER_LONG_CONSTANT("IBASE_CREATE", PHP_IBASE_CREATE, CONST_PERSISTENT);
741 | REGISTER_LONG_CONSTANT("IBASE_TEXT", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); /* deprecated, for BC only */
742 | REGISTER_LONG_CONSTANT("IBASE_FETCH_BLOBS", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT);
743 | REGISTER_LONG_CONSTANT("IBASE_FETCH_ARRAYS", PHP_IBASE_FETCH_ARRAYS, CONST_PERSISTENT);
744 | REGISTER_LONG_CONSTANT("IBASE_UNIXTIME", PHP_IBASE_UNIXTIME, CONST_PERSISTENT);
745 |
746 | /* transactions */
747 | REGISTER_LONG_CONSTANT("IBASE_WRITE", PHP_IBASE_WRITE, CONST_PERSISTENT);
748 | REGISTER_LONG_CONSTANT("IBASE_READ", PHP_IBASE_READ, CONST_PERSISTENT);
749 | REGISTER_LONG_CONSTANT("IBASE_COMMITTED", PHP_IBASE_COMMITTED, CONST_PERSISTENT);
750 | REGISTER_LONG_CONSTANT("IBASE_CONSISTENCY", PHP_IBASE_CONSISTENCY, CONST_PERSISTENT);
751 | REGISTER_LONG_CONSTANT("IBASE_CONCURRENCY", PHP_IBASE_CONCURRENCY, CONST_PERSISTENT);
752 | REGISTER_LONG_CONSTANT("IBASE_REC_VERSION", PHP_IBASE_REC_VERSION, CONST_PERSISTENT);
753 | REGISTER_LONG_CONSTANT("IBASE_REC_NO_VERSION", PHP_IBASE_REC_NO_VERSION, CONST_PERSISTENT);
754 | REGISTER_LONG_CONSTANT("IBASE_NOWAIT", PHP_IBASE_NOWAIT, CONST_PERSISTENT);
755 | REGISTER_LONG_CONSTANT("IBASE_WAIT", PHP_IBASE_WAIT, CONST_PERSISTENT);
756 |
757 | php_ibase_query_minit(INIT_FUNC_ARGS_PASSTHRU);
758 | php_ibase_blobs_minit(INIT_FUNC_ARGS_PASSTHRU);
759 | php_ibase_events_minit(INIT_FUNC_ARGS_PASSTHRU);
760 | php_ibase_service_minit(INIT_FUNC_ARGS_PASSTHRU);
761 |
762 | return SUCCESS;
763 | }
764 |
765 | PHP_MSHUTDOWN_FUNCTION(ibase)
766 | {
767 | #ifndef PHP_WIN32
768 | /**
769 | * When the Interbase client API library libgds.so is first loaded, it registers a call to
770 | * gds__cleanup() with atexit(), in order to clean up after itself when the process exits.
771 | * This means that the library is called at process shutdown, and cannot be unloaded beforehand.
772 | * PHP tries to unload modules after every request [dl()'ed modules], and right before the
773 | * process shuts down [modules loaded from php.ini]. This results in a segfault for this module.
774 | * By NULLing the dlopen() handle in the module entry, Zend omits the call to dlclose(),
775 | * ensuring that the module will remain present until the process exits. However, the functions
776 | * and classes exported by the module will not be available until the module is 'reloaded'.
777 | * When reloaded, dlopen() will return the handle of the already loaded module. The module will
778 | * be unloaded automatically when the process exits.
779 | */
780 | zend_module_entry *ibase_entry;
781 | if ((ibase_entry = zend_hash_str_find_ptr(&module_registry, ibase_module_entry.name,
782 | strlen(ibase_module_entry.name))) != NULL) {
783 | ibase_entry->handle = 0;
784 | }
785 | #endif
786 | UNREGISTER_INI_ENTRIES();
787 | return SUCCESS;
788 | }
789 |
790 | PHP_RSHUTDOWN_FUNCTION(ibase)
791 | {
792 | IBG(num_links) = IBG(num_persistent);
793 | IBG(default_link)= NULL;
794 |
795 | RESET_ERRMSG;
796 |
797 | return SUCCESS;
798 | }
799 |
800 | PHP_MINFO_FUNCTION(ibase)
801 | {
802 | char tmp[64], *s;
803 |
804 | php_info_print_table_start();
805 | php_info_print_table_row(2, "Firebird/InterBase Support",
806 | #ifdef COMPILE_DL_INTERBASE
807 | "dynamic");
808 | #else
809 | "static");
810 | #endif
811 |
812 | php_info_print_table_row(2, "Interbase extension version", PHP_INTERBASE_VERSION);
813 |
814 | #ifdef FB_API_VER
815 | snprintf( (s = tmp), sizeof(tmp), "Firebird API version %d", FB_API_VER);
816 | #elif (SQLDA_CURRENT_VERSION > 1)
817 | s = "Interbase 7.0 and up";
818 | #endif
819 | php_info_print_table_row(2, "Compile-time Client Library Version", s);
820 |
821 | #if defined(__GNUC__) || defined(PHP_WIN32)
822 | do {
823 | info_func_t info_func = NULL;
824 | #ifdef __GNUC__
825 | info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version");
826 | #else
827 | HMODULE l = GetModuleHandle("fbclient");
828 |
829 | if (!l && !(l = GetModuleHandle("gds32"))) {
830 | break;
831 | }
832 | info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version");
833 | #endif
834 | if (info_func) {
835 | info_func(s = tmp);
836 | }
837 | php_info_print_table_row(2, "Run-time Client Library Version", s);
838 | } while (0);
839 | #endif
840 | php_info_print_table_end();
841 |
842 | DISPLAY_INI_ENTRIES();
843 |
844 | }
845 | /* }}} */
846 |
847 | enum connect_args { DB = 0, USER = 1, PASS = 2, CSET = 3, ROLE = 4, BUF = 0, DLECT = 1, SYNC = 2 };
848 |
849 | static char const dpb_args[] = {
850 | 0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name, 0
851 | };
852 |
853 | int _php_ibase_attach_db(char **args, size_t *len, zend_long *largs, isc_db_handle *db) /* {{{ */
854 | {
855 | short i, dpb_len, buf_len = 257-2; /* version byte at the front, and a null at the end */
856 | char dpb_buffer[257] = { isc_dpb_version1, 0 }, *dpb;
857 |
858 | dpb = dpb_buffer + 1;
859 |
860 | for (i = 0; i < sizeof(dpb_args); ++i) {
861 | if (dpb_args[i] && args[i] && len[i] && buf_len > 0) {
862 | dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]);
863 | dpb += dpb_len;
864 | buf_len -= dpb_len;
865 | }
866 | }
867 | if (largs[BUF] && buf_len > 0) {
868 | dpb_len = slprintf(dpb, buf_len, "%c\2%c%c", isc_dpb_num_buffers,
869 | (char)(largs[BUF] >> 8), (char)(largs[BUF] & 0xff));
870 | dpb += dpb_len;
871 | buf_len -= dpb_len;
872 | }
873 | if (largs[SYNC] && buf_len > 0) {
874 | dpb_len = slprintf(dpb, buf_len, "%c\1%c", isc_dpb_force_write, largs[SYNC] == isc_spb_prp_wm_sync);
875 | dpb += dpb_len;
876 | buf_len -= dpb_len;
877 | }
878 | if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) {
879 | _php_ibase_error();
880 | return FAILURE;
881 | }
882 | return SUCCESS;
883 | }
884 | /* }}} */
885 |
886 | static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */
887 | {
888 | char *c, hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL };
889 | int i;
890 | size_t len[] = { 0, 0, 0, 0, 0 };
891 | zend_long largs[] = { 0, 0, 0 };
892 | PHP_MD5_CTX hash_context;
893 | zend_resource new_index_ptr, *le;
894 | isc_db_handle db_handle = 0;
895 | ibase_db_link *ib_link;
896 |
897 | RESET_ERRMSG;
898 |
899 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|ssssllsl",
900 | &args[DB], &len[DB], &args[USER], &len[USER], &args[PASS], &len[PASS],
901 | &args[CSET], &len[CSET], &largs[BUF], &largs[DLECT], &args[ROLE], &len[ROLE],
902 | &largs[SYNC])) {
903 | RETURN_FALSE;
904 | }
905 |
906 | /* restrict to the server/db in the .ini if in safe mode */
907 | if (!len[DB] && (c = INI_STR("ibase.default_db"))) {
908 | args[DB] = c;
909 | len[DB] = strlen(c);
910 | }
911 | if (!len[USER] && (c = INI_STR("ibase.default_user"))) {
912 | args[USER] = c;
913 | len[USER] = strlen(c);
914 | }
915 | if (!len[PASS] && (c = INI_STR("ibase.default_password"))) {
916 | args[PASS] = c;
917 | len[PASS] = strlen(c);
918 | }
919 | if (!len[CSET] && (c = INI_STR("ibase.default_charset"))) {
920 | args[CSET] = c;
921 | len[CSET] = strlen(c);
922 | }
923 |
924 | /* don't want usernames and passwords floating around */
925 | PHP_MD5Init(&hash_context);
926 | for (i = 0; i < sizeof(args)/sizeof(char*); ++i) {
927 | PHP_MD5Update(&hash_context,args[i],len[i]);
928 | }
929 | for (i = 0; i < sizeof(largs)/sizeof(zend_long); ++i) {
930 | PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(zend_long));
931 | }
932 | PHP_MD5Final((unsigned char*)hash, &hash_context);
933 |
934 | /* try to reuse a connection */
935 | if ((le = zend_hash_str_find_ptr(&EG(regular_list), hash, sizeof(hash)-1)) != NULL) {
936 | zend_resource *xlink;
937 |
938 | if (le->type != le_index_ptr) {
939 | RETURN_FALSE;
940 | }
941 |
942 | xlink = (zend_resource*) le->ptr;
943 | if ((!persistent && xlink->type == le_link) || xlink->type == le_plink) {
944 | if (IBG(default_link) != xlink) {
945 | GC_ADDREF(xlink);
946 | if (IBG(default_link)) {
947 | zend_list_delete(IBG(default_link));
948 | }
949 | IBG(default_link) = xlink;
950 | }
951 | GC_ADDREF(xlink);
952 | RETURN_RES(xlink);
953 | } else {
954 | zend_hash_str_del(&EG(regular_list), hash, sizeof(hash)-1);
955 | }
956 | }
957 |
958 | /* ... or a persistent one */
959 | do {
960 | zend_long l;
961 | static char info[] = { isc_info_base_level, isc_info_end };
962 | char result[8];
963 | ISC_STATUS status[20];
964 |
965 | if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hash, sizeof(hash)-1)) != NULL) {
966 | if (le->type != le_plink) {
967 | RETURN_FALSE;
968 | }
969 | /* check if connection has timed out */
970 | ib_link = (ibase_db_link *) le->ptr;
971 | if (!isc_database_info(status, &ib_link->handle, sizeof(info), info, sizeof(result), result)) {
972 | RETVAL_RES(zend_register_resource(ib_link, le_plink));
973 | break;
974 | }
975 | zend_hash_str_del(&EG(persistent_list), hash, sizeof(hash)-1);
976 | }
977 |
978 | /* no link found, so we have to open one */
979 |
980 | if ((l = INI_INT("ibase.max_links")) != -1 && IBG(num_links) >= l) {
981 | _php_ibase_module_error("Too many open links (%ld)", IBG(num_links));
982 | RETURN_FALSE;
983 | }
984 |
985 | /* create the ib_link */
986 | if (FAILURE == _php_ibase_attach_db(args, len, largs, &db_handle)) {
987 | RETURN_FALSE;
988 | }
989 |
990 | /* use non-persistent if allowed number of persistent links is exceeded */
991 | if (!persistent || ((l = INI_INT("ibase.max_persistent") != -1) && IBG(num_persistent) >= l)) {
992 | ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link));
993 | RETVAL_RES(zend_register_resource(ib_link, le_link));
994 | } else {
995 | ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link));
996 | if (!ib_link) {
997 | RETURN_FALSE;
998 | }
999 |
1000 | /* hash it up */
1001 | if (zend_register_persistent_resource(hash, sizeof(hash)-1, ib_link, le_plink) == NULL) {
1002 | free(ib_link);
1003 | RETURN_FALSE;
1004 | }
1005 | RETVAL_RES(zend_register_resource(ib_link, le_plink));
1006 | ++IBG(num_persistent);
1007 | }
1008 | ib_link->handle = db_handle;
1009 | ib_link->dialect = largs[DLECT] ? (unsigned short)largs[DLECT] : SQL_DIALECT_CURRENT;
1010 | ib_link->tr_list = NULL;
1011 | ib_link->event_head = NULL;
1012 |
1013 | ++IBG(num_links);
1014 | } while (0);
1015 |
1016 | /* add it to the hash */
1017 | new_index_ptr.ptr = (void *) Z_RES_P(return_value);
1018 | new_index_ptr.type = le_index_ptr;
1019 | zend_hash_str_update_mem(&EG(regular_list), hash, sizeof(hash)-1,
1020 | (void *) &new_index_ptr, sizeof(zend_resource));
1021 | if (IBG(default_link)) {
1022 | zend_list_delete(IBG(default_link));
1023 | }
1024 | IBG(default_link) = Z_RES_P(return_value);
1025 | Z_TRY_ADDREF_P(return_value);
1026 | Z_TRY_ADDREF_P(return_value);
1027 | }
1028 | /* }}} */
1029 |
1030 | /* {{{ proto resource ibase_connect([string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]])
1031 | Open a connection to an InterBase database */
1032 | PHP_FUNCTION(ibase_connect)
1033 | {
1034 | _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1035 | }
1036 | /* }}} */
1037 |
1038 | /* {{{ proto resource ibase_pconnect([string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]])
1039 | Open a persistent connection to an InterBase database */
1040 | PHP_FUNCTION(ibase_pconnect)
1041 | {
1042 | _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INI_INT("ibase.allow_persistent"));
1043 | }
1044 | /* }}} */
1045 |
1046 | /* {{{ proto bool ibase_close([resource link_identifier])
1047 | Close an InterBase connection */
1048 | PHP_FUNCTION(ibase_close)
1049 | {
1050 | zval *link_arg = NULL;
1051 | zend_resource *link_res;
1052 |
1053 | RESET_ERRMSG;
1054 |
1055 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &link_arg) == FAILURE) {
1056 | return;
1057 | }
1058 |
1059 | if (ZEND_NUM_ARGS() == 0) {
1060 | link_res = IBG(default_link);
1061 | CHECK_LINK(link_res);
1062 | IBG(default_link) = NULL;
1063 | } else {
1064 | link_res = Z_RES_P(link_arg);
1065 | }
1066 |
1067 | /* we have at least 3 additional references to this resource ??? */
1068 | if (GC_REFCOUNT(link_res) < 4) {
1069 | zend_list_close(link_res);
1070 | } else {
1071 | zend_list_delete(link_res);
1072 | }
1073 | RETURN_TRUE;
1074 | }
1075 | /* }}} */
1076 |
1077 | /* {{{ proto bool ibase_drop_db([resource link_identifier])
1078 | Drop an InterBase database */
1079 | PHP_FUNCTION(ibase_drop_db)
1080 | {
1081 | zval *link_arg = NULL;
1082 | ibase_db_link *ib_link;
1083 | ibase_tr_list *l;
1084 | zend_resource *link_res;
1085 |
1086 | RESET_ERRMSG;
1087 |
1088 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &link_arg) == FAILURE) {
1089 | return;
1090 | }
1091 |
1092 | if (ZEND_NUM_ARGS() == 0) {
1093 | link_res = IBG(default_link);
1094 | CHECK_LINK(link_res);
1095 | IBG(default_link) = NULL;
1096 | } else {
1097 | link_res = Z_RES_P(link_arg);
1098 | }
1099 |
1100 | ib_link = (ibase_db_link *)zend_fetch_resource2(link_res, LE_LINK, le_link, le_plink);
1101 |
1102 | if (!ib_link) {
1103 | RETURN_FALSE;
1104 | }
1105 |
1106 | if (isc_drop_database(IB_STATUS, &ib_link->handle)) {
1107 | _php_ibase_error();
1108 | RETURN_FALSE;
1109 | }
1110 |
1111 | /* isc_drop_database() doesn't invalidate the transaction handles */
1112 | for (l = ib_link->tr_list; l != NULL; l = l->next) {
1113 | if (l->trans != NULL) l->trans->handle = 0;
1114 | }
1115 |
1116 | zend_list_delete(link_res);
1117 |
1118 | RETURN_TRUE;
1119 | }
1120 | /* }}} */
1121 |
1122 | /* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]])
1123 | Start a transaction over one or several databases */
1124 |
1125 | #define TPB_MAX_SIZE (8*sizeof(char))
1126 |
1127 | PHP_FUNCTION(ibase_trans)
1128 | {
1129 | unsigned short i, link_cnt = 0, tpb_len = 0;
1130 | int argn = ZEND_NUM_ARGS();
1131 | char last_tpb[TPB_MAX_SIZE];
1132 | ibase_db_link **ib_link = NULL;
1133 | ibase_trans *ib_trans;
1134 | isc_tr_handle tr_handle = 0;
1135 | ISC_STATUS result;
1136 |
1137 | RESET_ERRMSG;
1138 |
1139 | /* (1+argn) is an upper bound for the number of links this trans connects to */
1140 | ib_link = (ibase_db_link **) safe_emalloc(sizeof(ibase_db_link *),1+argn,0);
1141 |
1142 | if (argn > 0) {
1143 | zend_long trans_argl = 0;
1144 | char *tpb;
1145 | ISC_TEB *teb;
1146 | zval *args = NULL;
1147 |
1148 | if (zend_parse_parameters(argn, "+", &args, &argn) == FAILURE) {
1149 | efree(ib_link);
1150 | RETURN_FALSE;
1151 | }
1152 |
1153 | teb = (ISC_TEB *) safe_emalloc(sizeof(ISC_TEB),argn,0);
1154 | tpb = (char *) safe_emalloc(TPB_MAX_SIZE,argn,0);
1155 |
1156 | /* enumerate all the arguments: assume every non-resource argument
1157 | specifies modifiers for the link ids that follow it */
1158 | for (i = 0; i < argn; ++i) {
1159 |
1160 | if (Z_TYPE(args[i]) == IS_RESOURCE) {
1161 |
1162 | if ((ib_link[link_cnt] = (ibase_db_link *)zend_fetch_resource2_ex(&args[i], LE_LINK, le_link, le_plink)) == NULL) {
1163 | efree(teb);
1164 | efree(tpb);
1165 | efree(ib_link);
1166 | RETURN_FALSE;
1167 | }
1168 |
1169 | /* copy the most recent modifier string into tbp[] */
1170 | memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE);
1171 |
1172 | /* add a database handle to the TEB with the most recently specified set of modifiers */
1173 | teb[link_cnt].db_ptr = &ib_link[link_cnt]->handle;
1174 | teb[link_cnt].tpb_len = tpb_len;
1175 | teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt];
1176 |
1177 | ++link_cnt;
1178 |
1179 | } else {
1180 |
1181 | tpb_len = 0;
1182 |
1183 | convert_to_long_ex(&args[i]);
1184 | trans_argl = Z_LVAL(args[i]);
1185 |
1186 | if (trans_argl != PHP_IBASE_DEFAULT) {
1187 | last_tpb[tpb_len++] = isc_tpb_version3;
1188 |
1189 | /* access mode */
1190 | if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) {
1191 | last_tpb[tpb_len++] = isc_tpb_read;
1192 | } else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) {
1193 | last_tpb[tpb_len++] = isc_tpb_write;
1194 | }
1195 |
1196 | /* isolation level */
1197 | if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) {
1198 | last_tpb[tpb_len++] = isc_tpb_read_committed;
1199 | if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) {
1200 | last_tpb[tpb_len++] = isc_tpb_rec_version;
1201 | } else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) {
1202 | last_tpb[tpb_len++] = isc_tpb_no_rec_version;
1203 | }
1204 | } else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) {
1205 | last_tpb[tpb_len++] = isc_tpb_consistency;
1206 | } else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) {
1207 | last_tpb[tpb_len++] = isc_tpb_concurrency;
1208 | }
1209 |
1210 | /* lock resolution */
1211 | if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) {
1212 | last_tpb[tpb_len++] = isc_tpb_nowait;
1213 | } else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) {
1214 | last_tpb[tpb_len++] = isc_tpb_wait;
1215 | }
1216 | }
1217 | }
1218 | }
1219 |
1220 | if (link_cnt > 0) {
1221 | result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb);
1222 | }
1223 |
1224 | efree(tpb);
1225 | efree(teb);
1226 | }
1227 |
1228 | if (link_cnt == 0) {
1229 | link_cnt = 1;
1230 | if ((ib_link[0] = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink)) == NULL) {
1231 | efree(ib_link);
1232 | RETURN_FALSE;
1233 | }
1234 | result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->handle, tpb_len, last_tpb);
1235 | }
1236 |
1237 | /* start the transaction */
1238 | if (result) {
1239 | _php_ibase_error();
1240 | efree(ib_link);
1241 | RETURN_FALSE;
1242 | }
1243 |
1244 | /* register the transaction in our own data structures */
1245 | ib_trans = (ibase_trans *) safe_emalloc(link_cnt-1, sizeof(ibase_db_link *), sizeof(ibase_trans));
1246 | ib_trans->handle = tr_handle;
1247 | ib_trans->link_cnt = link_cnt;
1248 | ib_trans->affected_rows = 0;
1249 | for (i = 0; i < link_cnt; ++i) {
1250 | ibase_tr_list **l;
1251 | ib_trans->db_link[i] = ib_link[i];
1252 |
1253 | /* the first item in the connection-transaction list is reserved for the default transaction */
1254 | if (ib_link[i]->tr_list == NULL) {
1255 | ib_link[i]->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1256 | ib_link[i]->tr_list->trans = NULL;
1257 | ib_link[i]->tr_list->next = NULL;
1258 | }
1259 |
1260 | /* link the transaction into the connection-transaction list */
1261 | for (l = &ib_link[i]->tr_list; *l != NULL; l = &(*l)->next);
1262 | *l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1263 | (*l)->trans = ib_trans;
1264 | (*l)->next = NULL;
1265 | }
1266 | efree(ib_link);
1267 | RETVAL_RES(zend_register_resource(ib_trans, le_trans));
1268 | Z_TRY_ADDREF_P(return_value);
1269 | }
1270 | /* }}} */
1271 |
1272 | int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans) /* {{{ */
1273 | {
1274 | if (ib_link == NULL) {
1275 | php_error_docref(NULL, E_WARNING, "Invalid database link");
1276 | return FAILURE;
1277 | }
1278 |
1279 | /* the first item in the connection-transaction list is reserved for the default transaction */
1280 | if (ib_link->tr_list == NULL) {
1281 | ib_link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1282 | ib_link->tr_list->trans = NULL;
1283 | ib_link->tr_list->next = NULL;
1284 | }
1285 |
1286 | if (*trans == NULL) {
1287 | ibase_trans *tr = ib_link->tr_list->trans;
1288 |
1289 | if (tr == NULL) {
1290 | tr = (ibase_trans *) emalloc(sizeof(ibase_trans));
1291 | tr->handle = 0;
1292 | tr->link_cnt = 1;
1293 | tr->affected_rows = 0;
1294 | tr->db_link[0] = ib_link;
1295 | ib_link->tr_list->trans = tr;
1296 | }
1297 | if (tr->handle == 0) {
1298 | if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) {
1299 | _php_ibase_error();
1300 | return FAILURE;
1301 | }
1302 | }
1303 | *trans = tr;
1304 | }
1305 | return SUCCESS;
1306 | }
1307 | /* }}} */
1308 |
1309 | static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{{ */
1310 | {
1311 | ibase_trans *trans = NULL;
1312 | int res_id = 0;
1313 | ISC_STATUS result;
1314 | ibase_db_link *ib_link;
1315 | zval *arg = NULL;
1316 |
1317 | RESET_ERRMSG;
1318 |
1319 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &arg) == FAILURE) {
1320 | return;
1321 | }
1322 |
1323 | if (ZEND_NUM_ARGS() == 0) {
1324 | ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink);
1325 | if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
1326 | /* this link doesn't have a default transaction */
1327 | _php_ibase_module_error("Default link has no default transaction");
1328 | RETURN_FALSE;
1329 | }
1330 | trans = ib_link->tr_list->trans;
1331 | } else {
1332 | /* one id was passed, could be db or trans id */
1333 | if (Z_RES_P(arg)->type == le_trans) {
1334 | trans = (ibase_trans *)zend_fetch_resource_ex(arg, LE_TRANS, le_trans);
1335 | res_id = Z_RES_P(arg)->handle;
1336 | } else {
1337 | ib_link = (ibase_db_link *)zend_fetch_resource2_ex(arg, LE_LINK, le_link, le_plink);
1338 |
1339 | if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
1340 | /* this link doesn't have a default transaction */
1341 | _php_ibase_module_error("Link has no default transaction");
1342 | RETURN_FALSE;
1343 | }
1344 | trans = ib_link->tr_list->trans;
1345 | }
1346 | }
1347 |
1348 | switch (commit) {
1349 | default: /* == case ROLLBACK: */
1350 | result = isc_rollback_transaction(IB_STATUS, &trans->handle);
1351 | break;
1352 | case COMMIT:
1353 | result = isc_commit_transaction(IB_STATUS, &trans->handle);
1354 | break;
1355 | case (ROLLBACK | RETAIN):
1356 | result = isc_rollback_retaining(IB_STATUS, &trans->handle);
1357 | break;
1358 | case (COMMIT | RETAIN):
1359 | result = isc_commit_retaining(IB_STATUS, &trans->handle);
1360 | break;
1361 | }
1362 |
1363 | if (result) {
1364 | _php_ibase_error();
1365 | RETURN_FALSE;
1366 | }
1367 |
1368 | /* Don't try to destroy implicitly opened transaction from list... */
1369 | if ((commit & RETAIN) == 0 && res_id != 0) {
1370 | zend_list_delete(Z_RES_P(arg));
1371 | }
1372 | RETURN_TRUE;
1373 | }
1374 | /* }}} */
1375 |
1376 | /* {{{ proto bool ibase_commit( resource link_identifier )
1377 | Commit transaction */
1378 | PHP_FUNCTION(ibase_commit)
1379 | {
1380 | _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT);
1381 | }
1382 | /* }}} */
1383 |
1384 | /* {{{ proto bool ibase_rollback( resource link_identifier )
1385 | Rollback transaction */
1386 | PHP_FUNCTION(ibase_rollback)
1387 | {
1388 | _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK);
1389 | }
1390 | /* }}} */
1391 |
1392 | /* {{{ proto bool ibase_commit_ret( resource link_identifier )
1393 | Commit transaction and retain the transaction context */
1394 | PHP_FUNCTION(ibase_commit_ret)
1395 | {
1396 | _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT | RETAIN);
1397 | }
1398 | /* }}} */
1399 |
1400 | /* {{{ proto bool ibase_rollback_ret( resource link_identifier )
1401 | Rollback transaction and retain the transaction context */
1402 | PHP_FUNCTION(ibase_rollback_ret)
1403 | {
1404 | _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK | RETAIN);
1405 | }
1406 | /* }}} */
1407 |
1408 | /* {{{ proto int ibase_gen_id(string generator [, int increment [, resource link_identifier ]])
1409 | Increments the named generator and returns its new value */
1410 | PHP_FUNCTION(ibase_gen_id)
1411 | {
1412 | zval *link = NULL;
1413 | char query[128], *generator;
1414 | size_t gen_len;
1415 | zend_long inc = 1;
1416 | ibase_db_link *ib_link;
1417 | ibase_trans *trans = NULL;
1418 | XSQLDA out_sqlda;
1419 | ISC_INT64 result;
1420 |
1421 | RESET_ERRMSG;
1422 |
1423 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|lr", &generator, &gen_len,
1424 | &inc, &link)) {
1425 | RETURN_FALSE;
1426 | }
1427 |
1428 | if (gen_len > 31) {
1429 | php_error_docref(NULL, E_WARNING, "Invalid generator name");
1430 | RETURN_FALSE;
1431 | }
1432 |
1433 | PHP_IBASE_LINK_TRANS(link, ib_link, trans);
1434 |
1435 | snprintf(query, sizeof(query), "SELECT GEN_ID(%s,%ld) FROM rdb$database", generator, inc);
1436 |
1437 | /* allocate a minimal descriptor area */
1438 | out_sqlda.sqln = out_sqlda.sqld = 1;
1439 | out_sqlda.version = SQLDA_CURRENT_VERSION;
1440 |
1441 | /* allocate the field for the result */
1442 | out_sqlda.sqlvar[0].sqltype = SQL_INT64;
1443 | out_sqlda.sqlvar[0].sqlscale = 0;
1444 | out_sqlda.sqlvar[0].sqllen = sizeof(result);
1445 | out_sqlda.sqlvar[0].sqldata = (void*) &result;
1446 |
1447 | /* execute the query */
1448 | if (isc_dsql_exec_immed2(IB_STATUS, &ib_link->handle, &trans->handle, 0, query,
1449 | SQL_DIALECT_CURRENT, NULL, &out_sqlda)) {
1450 | _php_ibase_error();
1451 | RETURN_FALSE;
1452 | }
1453 |
1454 | /* don't return the generator value as a string unless it doesn't fit in a long */
1455 | #if SIZEOF_ZEND_LONG < 8
1456 | if (result < ZEND_LONG_MIN || result > ZEND_LONG_MAX) {
1457 | char *res;
1458 | int l;
1459 |
1460 | l = spprintf(&res, 0, "%" LL_MASK "d", result);
1461 | RETURN_STRINGL(res, l);
1462 | }
1463 | #endif
1464 | RETURN_LONG((zend_long)result);
1465 | }
1466 |
1467 | /* }}} */
1468 |
1469 | #endif /* HAVE_IBASE */
1470 |
--------------------------------------------------------------------------------