xref: /PHP-7.0/ext/interbase/interbase.c (revision e6aea3dc)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2017 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 <jouni.ahto@exdec.fi>                            |
16    |          Andrew Avdeev <andy@rsc.mv.ru>                              |
17    |          Ard Biesheuvel <a.k.biesheuvel@ewi.tudelft.nl>              |
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 <time.h>
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 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 */
PHP_FUNCTION(ibase_errmsg)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 */
PHP_FUNCTION(ibase_errcode)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() */
_php_ibase_error(void)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() */
_php_ibase_module_error(char * msg,...)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. */
_php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS,zval * link_id,ibase_db_link ** ib_link,ibase_trans ** trans)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 
_php_ibase_commit_link(ibase_db_link * link)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 
php_ibase_commit_link_rsrc(zend_resource * rsrc)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 
_php_ibase_close_link(zend_resource * rsrc)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 
_php_ibase_close_plink(zend_resource * rsrc)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 
_php_ibase_free_trans(zend_resource * rsrc)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 */
PHP_INI_DISP(php_ibase_password_displayer_cb)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("<i>no value</i>");
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)
PHP_INI_END()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 
PHP_MINIT_FUNCTION(ibase)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 
PHP_MSHUTDOWN_FUNCTION(ibase)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 
PHP_RSHUTDOWN_FUNCTION(ibase)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 
PHP_MINFO_FUNCTION(ibase)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 #ifdef FB_API_VER
813 	snprintf( (s = tmp), sizeof(tmp), "Firebird API version %d", FB_API_VER);
814 #elif (SQLDA_CURRENT_VERSION > 1)
815 	s =  "Interbase 7.0 and up";
816 #endif
817 	php_info_print_table_row(2, "Compile-time Client Library Version", s);
818 
819 #if defined(__GNUC__) || defined(PHP_WIN32)
820 	do {
821 		info_func_t info_func = NULL;
822 #ifdef __GNUC__
823 		info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version");
824 #else
825 		HMODULE l = GetModuleHandle("fbclient");
826 
827 		if (!l && !(l = GetModuleHandle("gds32"))) {
828 			break;
829 		}
830 		info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version");
831 #endif
832 		if (info_func) {
833 			info_func(s = tmp);
834 		}
835 		php_info_print_table_row(2, "Run-time Client Library Version", s);
836 	} while (0);
837 #endif
838 	php_info_print_table_end();
839 
840 	DISPLAY_INI_ENTRIES();
841 
842 }
843 /* }}} */
844 
845 enum connect_args { DB = 0, USER = 1, PASS = 2, CSET = 3, ROLE = 4, BUF = 0, DLECT = 1, SYNC = 2 };
846 
847 static char const dpb_args[] = {
848 	0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name, 0
849 };
850 
_php_ibase_attach_db(char ** args,size_t * len,zend_long * largs,isc_db_handle * db)851 int _php_ibase_attach_db(char **args, size_t *len, zend_long *largs, isc_db_handle *db) /* {{{ */
852 {
853 	short i, dpb_len, buf_len = 257-2;  /* version byte at the front, and a null at the end */
854 	char dpb_buffer[257] = { isc_dpb_version1, 0 }, *dpb;
855 
856 	dpb = dpb_buffer + 1;
857 
858 	for (i = 0; i < sizeof(dpb_args); ++i) {
859 		if (dpb_args[i] && args[i] && len[i] && buf_len > 0) {
860 			dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]);
861 			dpb += dpb_len;
862 			buf_len -= dpb_len;
863 		}
864 	}
865 	if (largs[BUF] && buf_len > 0) {
866 		dpb_len = slprintf(dpb, buf_len, "%c\2%c%c", isc_dpb_num_buffers,
867 			(char)(largs[BUF] >> 8), (char)(largs[BUF] & 0xff));
868 		dpb += dpb_len;
869 		buf_len -= dpb_len;
870 	}
871 	if (largs[SYNC] && buf_len > 0) {
872 		dpb_len = slprintf(dpb, buf_len, "%c\1%c", isc_dpb_force_write, largs[SYNC] == isc_spb_prp_wm_sync ? 1 : 0);
873 		dpb += dpb_len;
874 		buf_len -= dpb_len;
875 	}
876 	if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) {
877 		_php_ibase_error();
878 		return FAILURE;
879 	}
880 	return SUCCESS;
881 }
882 /* }}} */
883 
_php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent)884 static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */
885 {
886 	char *c, hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL };
887 	int i;
888 	size_t len[] = { 0, 0, 0, 0, 0 };
889 	zend_long largs[] = { 0, 0, 0 };
890 	PHP_MD5_CTX hash_context;
891 	zend_resource new_index_ptr, *le;
892 	isc_db_handle db_handle = 0;
893 	ibase_db_link *ib_link;
894 
895 	RESET_ERRMSG;
896 
897 	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|ssssllsl",
898 			&args[DB], &len[DB], &args[USER], &len[USER], &args[PASS], &len[PASS],
899 			&args[CSET], &len[CSET], &largs[BUF], &largs[DLECT], &args[ROLE], &len[ROLE],
900 			&largs[SYNC])) {
901 		RETURN_FALSE;
902 	}
903 
904 	/* restrict to the server/db in the .ini if in safe mode */
905 	if ((!len[DB] || PG(sql_safe_mode)) && (c = INI_STR("ibase.default_db"))) {
906 		args[DB] = c;
907 		len[DB] = strlen(c);
908 	}
909 	if (!len[USER] && (c = INI_STR("ibase.default_user"))) {
910 		args[USER] = c;
911 		len[USER] = strlen(c);
912 	}
913 	if (!len[PASS] && (c = INI_STR("ibase.default_password"))) {
914 		args[PASS] = c;
915 		len[PASS] = strlen(c);
916 	}
917 	if (!len[CSET] && (c = INI_STR("ibase.default_charset"))) {
918 		args[CSET] = c;
919 		len[CSET] = strlen(c);
920 	}
921 
922 	/* don't want usernames and passwords floating around */
923 	PHP_MD5Init(&hash_context);
924 	for (i = 0; i < sizeof(args)/sizeof(char*); ++i) {
925 		PHP_MD5Update(&hash_context,args[i],len[i]);
926 	}
927 	for (i = 0; i < sizeof(largs)/sizeof(zend_long); ++i) {
928 		PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(zend_long));
929 	}
930 	PHP_MD5Final((unsigned char*)hash, &hash_context);
931 
932 	/* try to reuse a connection */
933 	if ((le = zend_hash_str_find_ptr(&EG(regular_list), hash, sizeof(hash)-1)) != NULL) {
934 		zend_resource *xlink;
935 
936 		if (le->type != le_index_ptr) {
937 			RETURN_FALSE;
938 		}
939 
940 		xlink = (zend_resource*) le->ptr;
941 		if ((!persistent && xlink->type == le_link) || xlink->type == le_plink) {
942 			if (IBG(default_link)) {
943 				zend_list_close(IBG(default_link));
944 			}
945 			xlink->gc.refcount++;
946 			xlink->gc.refcount++;
947 			IBG(default_link) = xlink;
948 			RETVAL_RES(xlink);
949 		} else {
950 			zend_hash_str_del(&EG(regular_list), hash, sizeof(hash)-1);
951 		}
952 	}
953 
954 	/* ... or a persistent one */
955 	do {
956 		zend_long l;
957 		static char info[] = { isc_info_base_level, isc_info_end };
958 		char result[8];
959 		ISC_STATUS status[20];
960 
961 		if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hash, sizeof(hash)-1)) != NULL) {
962 			if (le->type != le_plink) {
963 				RETURN_FALSE;
964 			}
965 			/* check if connection has timed out */
966 			ib_link = (ibase_db_link *) le->ptr;
967 			if (!isc_database_info(status, &ib_link->handle, sizeof(info), info, sizeof(result), result)) {
968 				RETVAL_RES(zend_register_resource(ib_link, le_plink));
969 				break;
970 			}
971 			zend_hash_str_del(&EG(persistent_list), hash, sizeof(hash)-1);
972 		}
973 
974 		/* no link found, so we have to open one */
975 
976 		if ((l = INI_INT("ibase.max_links")) != -1 && IBG(num_links) >= l) {
977 			_php_ibase_module_error("Too many open links (%ld)", IBG(num_links));
978 			RETURN_FALSE;
979 		}
980 
981 		/* create the ib_link */
982 		if (FAILURE == _php_ibase_attach_db(args, len, largs, &db_handle)) {
983 			RETURN_FALSE;
984 		}
985 
986 		/* use non-persistent if allowed number of persistent links is exceeded */
987 		if (!persistent || ((l = INI_INT("ibase.max_persistent") != -1) && IBG(num_persistent) >= l)) {
988 			ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link));
989 			RETVAL_RES(zend_register_resource(ib_link, le_link));
990 		} else {
991 			zend_resource new_le;
992 
993 			ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link));
994 			if (!ib_link) {
995 				RETURN_FALSE;
996 			}
997 
998 			/* hash it up */
999 			new_le.type = le_plink;
1000 			new_le.ptr = ib_link;
1001 			if (zend_hash_str_update_mem(&EG(persistent_list), hash, sizeof(hash)-1,
1002 					(void *) &new_le, sizeof(zend_resource)) == NULL) {
1003 				free(ib_link);
1004 				RETURN_FALSE;
1005 			}
1006 			RETVAL_RES(zend_register_resource(ib_link, le_plink));
1007 			++IBG(num_persistent);
1008 		}
1009 		ib_link->handle = db_handle;
1010 		ib_link->dialect = largs[DLECT] ? (unsigned short)largs[DLECT] : SQL_DIALECT_CURRENT;
1011 		ib_link->tr_list = NULL;
1012 		ib_link->event_head = NULL;
1013 
1014 		++IBG(num_links);
1015 	} while (0);
1016 
1017 	/* add it to the hash */
1018 	new_index_ptr.ptr = (void *) Z_RES_P(return_value);
1019 	new_index_ptr.type = le_index_ptr;
1020 	if (zend_hash_str_update_mem(&EG(regular_list), hash, sizeof(hash)-1,
1021 			(void *) &new_index_ptr, sizeof(zend_resource)) == NULL) {
1022 		RETURN_FALSE;
1023 	}
1024 	if (IBG(default_link)) {
1025 		zend_list_delete(IBG(default_link));
1026 	}
1027 	IBG(default_link) = Z_RES_P(return_value);
1028 	Z_TRY_ADDREF_P(return_value);
1029 	Z_TRY_ADDREF_P(return_value);
1030 }
1031 /* }}} */
1032 
1033 /* {{{ proto resource ibase_connect([string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]])
1034    Open a connection to an InterBase database */
PHP_FUNCTION(ibase_connect)1035 PHP_FUNCTION(ibase_connect)
1036 {
1037 	_php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1038 }
1039 /* }}} */
1040 
1041 /* {{{ proto resource ibase_pconnect([string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]])
1042    Open a persistent connection to an InterBase database */
PHP_FUNCTION(ibase_pconnect)1043 PHP_FUNCTION(ibase_pconnect)
1044 {
1045 	_php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INI_INT("ibase.allow_persistent"));
1046 }
1047 /* }}} */
1048 
1049 /* {{{ proto bool ibase_close([resource link_identifier])
1050    Close an InterBase connection */
PHP_FUNCTION(ibase_close)1051 PHP_FUNCTION(ibase_close)
1052 {
1053 	zval *link_arg = NULL;
1054 	zend_resource *link_res;
1055 
1056 	RESET_ERRMSG;
1057 
1058 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &link_arg) == FAILURE) {
1059 		return;
1060 	}
1061 
1062 	if (ZEND_NUM_ARGS() == 0) {
1063 		link_res = IBG(default_link);
1064 		CHECK_LINK(link_res);
1065 		IBG(default_link) = NULL;
1066 	} else {
1067 		link_res = Z_RES_P(link_arg);
1068 	}
1069 
1070 	/* we have at least 3 additional references to this resource ??? */
1071 	if (GC_REFCOUNT(link_res) < 4) {
1072 		zend_list_close(link_res);
1073 	} else {
1074 		zend_list_delete(link_res);
1075 	}
1076 	RETURN_TRUE;
1077 }
1078 /* }}} */
1079 
1080 /* {{{ proto bool ibase_drop_db([resource link_identifier])
1081    Drop an InterBase database */
PHP_FUNCTION(ibase_drop_db)1082 PHP_FUNCTION(ibase_drop_db)
1083 {
1084 	zval *link_arg = NULL;
1085 	ibase_db_link *ib_link;
1086 	ibase_tr_list *l;
1087 	zend_resource *link_res;
1088 
1089 	RESET_ERRMSG;
1090 
1091 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &link_arg) == FAILURE) {
1092 		return;
1093 	}
1094 
1095 	if (ZEND_NUM_ARGS() == 0) {
1096 		link_res = IBG(default_link);
1097 		CHECK_LINK(link_res);
1098 		IBG(default_link) = NULL;
1099 	} else {
1100 		link_res = Z_RES_P(link_arg);
1101 	}
1102 
1103 	ib_link = (ibase_db_link *)zend_fetch_resource2(link_res, LE_LINK, le_link, le_plink);
1104 
1105 	if (!ib_link) {
1106 		RETURN_FALSE;
1107 	}
1108 
1109 	if (isc_drop_database(IB_STATUS, &ib_link->handle)) {
1110 		_php_ibase_error();
1111 		RETURN_FALSE;
1112 	}
1113 
1114 	/* isc_drop_database() doesn't invalidate the transaction handles */
1115 	for (l = ib_link->tr_list; l != NULL; l = l->next) {
1116 		if (l->trans != NULL) l->trans->handle = 0;
1117 	}
1118 
1119 	zend_list_delete(link_res);
1120 
1121 	RETURN_TRUE;
1122 }
1123 /* }}} */
1124 
1125 /* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]])
1126    Start a transaction over one or several databases */
1127 
1128 #define TPB_MAX_SIZE (8*sizeof(char))
1129 
PHP_FUNCTION(ibase_trans)1130 PHP_FUNCTION(ibase_trans)
1131 {
1132 	unsigned short i, link_cnt = 0, tpb_len = 0;
1133 	int argn;
1134 	char last_tpb[TPB_MAX_SIZE];
1135 	ibase_db_link **ib_link = NULL;
1136 	ibase_trans *ib_trans;
1137 	isc_tr_handle tr_handle = 0;
1138 	ISC_STATUS result;
1139 
1140 	RESET_ERRMSG;
1141 
1142 	argn = ZEND_NUM_ARGS();
1143 
1144 	/* (1+argn) is an upper bound for the number of links this trans connects to */
1145 	ib_link = (ibase_db_link **) safe_emalloc(sizeof(ibase_db_link *),1+argn,0);
1146 
1147 	if (argn > 0) {
1148 		zend_long trans_argl = 0;
1149 		char *tpb;
1150 		ISC_TEB *teb;
1151 		zval *args = NULL;
1152 
1153 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argn) == FAILURE) {
1154 			efree(ib_link);
1155 			RETURN_FALSE;
1156 		}
1157 
1158 		teb = (ISC_TEB *) safe_emalloc(sizeof(ISC_TEB),argn,0);
1159 		tpb = (char *) safe_emalloc(TPB_MAX_SIZE,argn,0);
1160 
1161 		/* enumerate all the arguments: assume every non-resource argument
1162 		   specifies modifiers for the link ids that follow it */
1163 		for (i = 0; i < argn; ++i) {
1164 
1165 			if (Z_TYPE(args[i]) == IS_RESOURCE) {
1166 
1167 				if ((ib_link[link_cnt] = (ibase_db_link *)zend_fetch_resource2_ex(&args[i], LE_LINK, le_link, le_plink)) == NULL) {
1168 					efree(teb);
1169 					efree(tpb);
1170 					efree(ib_link);
1171 					RETURN_FALSE;
1172 				}
1173 
1174 				/* copy the most recent modifier string into tbp[] */
1175 				memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE);
1176 
1177 				/* add a database handle to the TEB with the most recently specified set of modifiers */
1178 				teb[link_cnt].db_ptr = &ib_link[link_cnt]->handle;
1179 				teb[link_cnt].tpb_len = tpb_len;
1180 				teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt];
1181 
1182 				++link_cnt;
1183 
1184 			} else {
1185 
1186 				tpb_len = 0;
1187 
1188 				convert_to_long_ex(&args[i]);
1189 				trans_argl = Z_LVAL(args[i]);
1190 
1191 				if (trans_argl != PHP_IBASE_DEFAULT) {
1192 					last_tpb[tpb_len++] = isc_tpb_version3;
1193 
1194 					/* access mode */
1195 					if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) {
1196 						last_tpb[tpb_len++] = isc_tpb_read;
1197 					} else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) {
1198 						last_tpb[tpb_len++] = isc_tpb_write;
1199 					}
1200 
1201 					/* isolation level */
1202 					if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) {
1203 						last_tpb[tpb_len++] = isc_tpb_read_committed;
1204 						if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) {
1205 							last_tpb[tpb_len++] = isc_tpb_rec_version;
1206 						} else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) {
1207 							last_tpb[tpb_len++] = isc_tpb_no_rec_version;
1208 						}
1209 					} else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) {
1210 						last_tpb[tpb_len++] = isc_tpb_consistency;
1211 					} else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) {
1212 						last_tpb[tpb_len++] = isc_tpb_concurrency;
1213 					}
1214 
1215 					/* lock resolution */
1216 					if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) {
1217 						last_tpb[tpb_len++] = isc_tpb_nowait;
1218 					} else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) {
1219 						last_tpb[tpb_len++] = isc_tpb_wait;
1220 					}
1221 				}
1222 			}
1223 		}
1224 
1225 		if (link_cnt > 0) {
1226 			result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb);
1227 		}
1228 
1229 		efree(tpb);
1230 		efree(teb);
1231 	}
1232 
1233 	if (link_cnt == 0) {
1234 		link_cnt = 1;
1235 		if ((ib_link[0] = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink)) == NULL) {
1236 			efree(ib_link);
1237 			RETURN_FALSE;
1238 		}
1239 		result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->handle, tpb_len, last_tpb);
1240 	}
1241 
1242 	/* start the transaction */
1243 	if (result) {
1244 		_php_ibase_error();
1245 		efree(ib_link);
1246 		RETURN_FALSE;
1247 	}
1248 
1249 	/* register the transaction in our own data structures */
1250 	ib_trans = (ibase_trans *) safe_emalloc(link_cnt-1, sizeof(ibase_db_link *), sizeof(ibase_trans));
1251 	ib_trans->handle = tr_handle;
1252 	ib_trans->link_cnt = link_cnt;
1253 	ib_trans->affected_rows = 0;
1254 	for (i = 0; i < link_cnt; ++i) {
1255 		ibase_tr_list **l;
1256 		ib_trans->db_link[i] = ib_link[i];
1257 
1258 		/* the first item in the connection-transaction list is reserved for the default transaction */
1259 		if (ib_link[i]->tr_list == NULL) {
1260 			ib_link[i]->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1261 			ib_link[i]->tr_list->trans = NULL;
1262 			ib_link[i]->tr_list->next = NULL;
1263 		}
1264 
1265 		/* link the transaction into the connection-transaction list */
1266 		for (l = &ib_link[i]->tr_list; *l != NULL; l = &(*l)->next);
1267 		*l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1268 		(*l)->trans = ib_trans;
1269 		(*l)->next = NULL;
1270 	}
1271 	efree(ib_link);
1272 	RETVAL_RES(zend_register_resource(ib_trans, le_trans));
1273 	Z_TRY_ADDREF_P(return_value);
1274 }
1275 /* }}} */
1276 
_php_ibase_def_trans(ibase_db_link * ib_link,ibase_trans ** trans)1277 int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans) /* {{{ */
1278 {
1279 	if (ib_link == NULL) {
1280 		php_error_docref(NULL, E_WARNING, "Invalid database link");
1281 		return FAILURE;
1282 	}
1283 
1284 	/* the first item in the connection-transaction list is reserved for the default transaction */
1285 	if (ib_link->tr_list == NULL) {
1286 		ib_link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1287 		ib_link->tr_list->trans = NULL;
1288 		ib_link->tr_list->next = NULL;
1289 	}
1290 
1291 	if (*trans == NULL) {
1292 		ibase_trans *tr = ib_link->tr_list->trans;
1293 
1294 		if (tr == NULL) {
1295 			tr = (ibase_trans *) emalloc(sizeof(ibase_trans));
1296 			tr->handle = 0;
1297 			tr->link_cnt = 1;
1298 			tr->affected_rows = 0;
1299 			tr->db_link[0] = ib_link;
1300 			ib_link->tr_list->trans = tr;
1301 		}
1302 		if (tr->handle == 0) {
1303 			if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) {
1304 				_php_ibase_error();
1305 				return FAILURE;
1306 			}
1307 		}
1308 		*trans = tr;
1309 	}
1310 	return SUCCESS;
1311 }
1312 /* }}} */
1313 
_php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS,int commit)1314 static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{{ */
1315 {
1316 	ibase_trans *trans = NULL;
1317 	int res_id = 0;
1318 	ISC_STATUS result;
1319 	ibase_db_link *ib_link;
1320 	zval *arg = NULL;
1321 
1322 	RESET_ERRMSG;
1323 
1324 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &arg) == FAILURE) {
1325 		return;
1326 	}
1327 
1328 	if (ZEND_NUM_ARGS() == 0) {
1329 		ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink);
1330 		if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
1331 			/* this link doesn't have a default transaction */
1332 			_php_ibase_module_error("Default link has no default transaction");
1333 			RETURN_FALSE;
1334 		}
1335 		trans = ib_link->tr_list->trans;
1336 	} else {
1337 		/* one id was passed, could be db or trans id */
1338 		if (Z_RES_P(arg)->type == le_trans) {
1339 			trans = (ibase_trans *)zend_fetch_resource_ex(arg, LE_TRANS, le_trans);
1340 			res_id = Z_RES_P(arg)->handle;
1341 		} else {
1342 			ib_link = (ibase_db_link *)zend_fetch_resource2_ex(arg, LE_LINK, le_link, le_plink);
1343 
1344 			if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
1345 				/* this link doesn't have a default transaction */
1346 				_php_ibase_module_error("Link has no default transaction");
1347 				RETURN_FALSE;
1348 			}
1349 			trans = ib_link->tr_list->trans;
1350 		}
1351 	}
1352 
1353 	switch (commit) {
1354 		default: /* == case ROLLBACK: */
1355 			result = isc_rollback_transaction(IB_STATUS, &trans->handle);
1356 			break;
1357 		case COMMIT:
1358 			result = isc_commit_transaction(IB_STATUS, &trans->handle);
1359 			break;
1360 		case (ROLLBACK | RETAIN):
1361 			result = isc_rollback_retaining(IB_STATUS, &trans->handle);
1362 			break;
1363 		case (COMMIT | RETAIN):
1364 			result = isc_commit_retaining(IB_STATUS, &trans->handle);
1365 			break;
1366 	}
1367 
1368 	if (result) {
1369 		_php_ibase_error();
1370 		RETURN_FALSE;
1371 	}
1372 
1373 	/* Don't try to destroy implicitly opened transaction from list... */
1374 	if ((commit & RETAIN) == 0 && res_id != 0) {
1375 		zend_list_delete(Z_RES_P(arg));
1376 	}
1377 	RETURN_TRUE;
1378 }
1379 /* }}} */
1380 
1381 /* {{{ proto bool ibase_commit( resource link_identifier )
1382    Commit transaction */
PHP_FUNCTION(ibase_commit)1383 PHP_FUNCTION(ibase_commit)
1384 {
1385 	_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT);
1386 }
1387 /* }}} */
1388 
1389 /* {{{ proto bool ibase_rollback( resource link_identifier )
1390    Rollback transaction */
PHP_FUNCTION(ibase_rollback)1391 PHP_FUNCTION(ibase_rollback)
1392 {
1393 	_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK);
1394 }
1395 /* }}} */
1396 
1397 /* {{{ proto bool ibase_commit_ret( resource link_identifier )
1398    Commit transaction and retain the transaction context */
PHP_FUNCTION(ibase_commit_ret)1399 PHP_FUNCTION(ibase_commit_ret)
1400 {
1401 	_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT | RETAIN);
1402 }
1403 /* }}} */
1404 
1405 /* {{{ proto bool ibase_rollback_ret( resource link_identifier )
1406    Rollback transaction and retain the transaction context */
PHP_FUNCTION(ibase_rollback_ret)1407 PHP_FUNCTION(ibase_rollback_ret)
1408 {
1409 	_php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK | RETAIN);
1410 }
1411 /* }}} */
1412 
1413 /* {{{ proto int ibase_gen_id(string generator [, int increment [, resource link_identifier ]])
1414    Increments the named generator and returns its new value */
PHP_FUNCTION(ibase_gen_id)1415 PHP_FUNCTION(ibase_gen_id)
1416 {
1417 	zval *link = NULL;
1418 	char query[128], *generator;
1419 	size_t gen_len;
1420 	zend_long inc = 1;
1421 	ibase_db_link *ib_link;
1422 	ibase_trans *trans = NULL;
1423 	XSQLDA out_sqlda;
1424 	ISC_INT64 result;
1425 
1426 	RESET_ERRMSG;
1427 
1428 	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|lr", &generator, &gen_len,
1429 			&inc, &link)) {
1430 		RETURN_FALSE;
1431 	}
1432 
1433 	if (gen_len > 31) {
1434 		php_error_docref(NULL, E_WARNING, "Invalid generator name");
1435 		RETURN_FALSE;
1436 	}
1437 
1438 	PHP_IBASE_LINK_TRANS(link, ib_link, trans);
1439 
1440 	snprintf(query, sizeof(query), "SELECT GEN_ID(%s,%ld) FROM rdb$database", generator, inc);
1441 
1442 	/* allocate a minimal descriptor area */
1443 	out_sqlda.sqln = out_sqlda.sqld = 1;
1444 	out_sqlda.version = SQLDA_CURRENT_VERSION;
1445 
1446 	/* allocate the field for the result */
1447 	out_sqlda.sqlvar[0].sqltype = SQL_INT64;
1448 	out_sqlda.sqlvar[0].sqlscale = 0;
1449 	out_sqlda.sqlvar[0].sqllen = sizeof(result);
1450 	out_sqlda.sqlvar[0].sqldata = (void*) &result;
1451 
1452 	/* execute the query */
1453 	if (isc_dsql_exec_immed2(IB_STATUS, &ib_link->handle, &trans->handle, 0, query,
1454 			SQL_DIALECT_CURRENT, NULL, &out_sqlda)) {
1455 		_php_ibase_error();
1456 		RETURN_FALSE;
1457 	}
1458 
1459 	/* don't return the generator value as a string unless it doesn't fit in a long */
1460 #if SIZEOF_ZEND_LONG < 8
1461 	if (result < ZEND_LONG_MIN || result > ZEND_LONG_MAX) {
1462 		char *res;
1463 		int l;
1464 
1465 		l = spprintf(&res, 0, "%" LL_MASK "d", result);
1466 		RETURN_STRINGL(res, l);
1467 	}
1468 #endif
1469 	RETURN_LONG((zend_long)result);
1470 }
1471 
1472 /* }}} */
1473 
1474 #endif /* HAVE_IBASE */
1475 
1476 /*
1477  * Local variables:
1478  * tab-width: 4
1479  * c-basic-offset: 4
1480  * End:
1481  * vim600: sw=4 ts=4 fdm=marker
1482  * vim<600: sw=4 ts=4
1483  */
1484