1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 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/* $Id$ */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#define _GNU_SOURCE 28 29#include "php.h" 30 31#if HAVE_IBASE 32 33#include "php_ini.h" 34#include "ext/standard/php_standard.h" 35#include "ext/standard/md5.h" 36#include "php_interbase.h" 37#include "php_ibase_includes.h" 38#include "SAPI.h" 39 40#include <time.h> 41 42#define ROLLBACK 0 43#define COMMIT 1 44#define RETAIN 2 45 46#define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } } 47 48ZEND_DECLARE_MODULE_GLOBALS(ibase) 49static PHP_GINIT_FUNCTION(ibase); 50 51/* {{{ arginfo */ 52ZEND_BEGIN_ARG_INFO(arginfo_ibase_errmsg, 0) 53ZEND_END_ARG_INFO() 54 55ZEND_BEGIN_ARG_INFO(arginfo_ibase_errcode, 0) 56ZEND_END_ARG_INFO() 57 58ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_connect, 0, 0, 1) 59 ZEND_ARG_INFO(0, database) 60 ZEND_ARG_INFO(0, username) 61 ZEND_ARG_INFO(0, password) 62 ZEND_ARG_INFO(0, charset) 63 ZEND_ARG_INFO(0, buffers) 64 ZEND_ARG_INFO(0, dialect) 65 ZEND_ARG_INFO(0, role) 66ZEND_END_ARG_INFO() 67 68ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_pconnect, 0, 0, 1) 69 ZEND_ARG_INFO(0, database) 70 ZEND_ARG_INFO(0, username) 71 ZEND_ARG_INFO(0, password) 72 ZEND_ARG_INFO(0, charset) 73 ZEND_ARG_INFO(0, buffers) 74 ZEND_ARG_INFO(0, dialect) 75 ZEND_ARG_INFO(0, role) 76ZEND_END_ARG_INFO() 77 78ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_close, 0, 0, 0) 79 ZEND_ARG_INFO(0, link_identifier) 80ZEND_END_ARG_INFO() 81 82ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_drop_db, 0, 0, 0) 83 ZEND_ARG_INFO(0, link_identifier) 84ZEND_END_ARG_INFO() 85 86ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_trans, 0, 0, 0) 87 ZEND_ARG_INFO(0, trans_args) 88 ZEND_ARG_INFO(0, link_identifier) 89 ZEND_ARG_INFO(0, trans_args) 90 ZEND_ARG_INFO(0, link_identifier) 91ZEND_END_ARG_INFO() 92 93ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit, 0, 0, 1) 94 ZEND_ARG_INFO(0, link_identifier) 95ZEND_END_ARG_INFO() 96 97ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback, 0, 0, 1) 98 ZEND_ARG_INFO(0, link_identifier) 99ZEND_END_ARG_INFO() 100 101ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit_ret, 0, 0, 1) 102 ZEND_ARG_INFO(0, link_identifier) 103ZEND_END_ARG_INFO() 104 105ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback_ret, 0, 0, 1) 106 ZEND_ARG_INFO(0, link_identifier) 107ZEND_END_ARG_INFO() 108 109ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_gen_id, 0, 0, 1) 110 ZEND_ARG_INFO(0, generator) 111 ZEND_ARG_INFO(0, increment) 112 ZEND_ARG_INFO(0, link_identifier) 113ZEND_END_ARG_INFO() 114 115ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_create, 0, 0, 0) 116 ZEND_ARG_INFO(0, link_identifier) 117ZEND_END_ARG_INFO() 118 119ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_open, 0, 0, 0) 120 ZEND_ARG_INFO(0, link_identifier) 121 ZEND_ARG_INFO(0, blob_id) 122ZEND_END_ARG_INFO() 123 124ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_add, 0, 0, 2) 125 ZEND_ARG_INFO(0, blob_handle) 126 ZEND_ARG_INFO(0, data) 127ZEND_END_ARG_INFO() 128 129ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_get, 0, 0, 2) 130 ZEND_ARG_INFO(0, blob_handle) 131 ZEND_ARG_INFO(0, len) 132ZEND_END_ARG_INFO() 133 134ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_close, 0, 0, 1) 135 ZEND_ARG_INFO(0, blob_handle) 136ZEND_END_ARG_INFO() 137 138ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_cancel, 0, 0, 1) 139 ZEND_ARG_INFO(0, blob_handle) 140ZEND_END_ARG_INFO() 141 142ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_info, 0, 0, 0) 143 ZEND_ARG_INFO(0, link_identifier) 144 ZEND_ARG_INFO(0, blob_id) 145ZEND_END_ARG_INFO() 146 147ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_echo, 0, 0, 0) 148 ZEND_ARG_INFO(0, link_identifier) 149 ZEND_ARG_INFO(0, blob_id) 150ZEND_END_ARG_INFO() 151 152ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_import, 0, 0, 0) 153 ZEND_ARG_INFO(0, link_identifier) 154 ZEND_ARG_INFO(0, file) 155ZEND_END_ARG_INFO() 156 157ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_query, 0, 0, 0) 158 ZEND_ARG_INFO(0, link_identifier) 159 ZEND_ARG_INFO(0, link_identifier) 160 ZEND_ARG_INFO(0, query) 161 ZEND_ARG_INFO(0, bind_arg) 162 ZEND_ARG_INFO(0, bind_arg) 163ZEND_END_ARG_INFO() 164 165ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_affected_rows, 0, 0, 0) 166 ZEND_ARG_INFO(0, link_identifier) 167ZEND_END_ARG_INFO() 168 169#if abies_0 170ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_rows, 0, 0, 1) 171 ZEND_ARG_INFO(0, result_identifier) 172ZEND_END_ARG_INFO() 173#endif 174 175ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_row, 0, 0, 1) 176 ZEND_ARG_INFO(0, result) 177 ZEND_ARG_INFO(0, fetch_flags) 178ZEND_END_ARG_INFO() 179 180ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_assoc, 0, 0, 1) 181 ZEND_ARG_INFO(0, result) 182 ZEND_ARG_INFO(0, fetch_flags) 183ZEND_END_ARG_INFO() 184 185ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_object, 0, 0, 1) 186 ZEND_ARG_INFO(0, result) 187 ZEND_ARG_INFO(0, fetch_flags) 188ZEND_END_ARG_INFO() 189 190ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_name_result, 0, 0, 2) 191 ZEND_ARG_INFO(0, result) 192 ZEND_ARG_INFO(0, name) 193ZEND_END_ARG_INFO() 194 195ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_result, 0, 0, 1) 196 ZEND_ARG_INFO(0, result) 197ZEND_END_ARG_INFO() 198 199ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_prepare, 0, 0, 0) 200 ZEND_ARG_INFO(0, link_identifier) 201 ZEND_ARG_INFO(0, query) 202ZEND_END_ARG_INFO() 203 204ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_execute, 0, 0, 1) 205 ZEND_ARG_INFO(0, query) 206 ZEND_ARG_INFO(0, bind_arg) 207 ZEND_ARG_INFO(0, bind_arg) 208ZEND_END_ARG_INFO() 209 210ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_query, 0, 0, 1) 211 ZEND_ARG_INFO(0, query) 212ZEND_END_ARG_INFO() 213 214ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_fields, 0, 0, 1) 215 ZEND_ARG_INFO(0, query_result) 216ZEND_END_ARG_INFO() 217 218ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_field_info, 0, 0, 2) 219 ZEND_ARG_INFO(0, query_result) 220 ZEND_ARG_INFO(0, field_number) 221ZEND_END_ARG_INFO() 222 223ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_params, 0, 0, 1) 224 ZEND_ARG_INFO(0, query) 225ZEND_END_ARG_INFO() 226 227ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_param_info, 0, 0, 2) 228 ZEND_ARG_INFO(0, query) 229 ZEND_ARG_INFO(0, field_number) 230ZEND_END_ARG_INFO() 231 232ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_add_user, 0, 0, 3) 233 ZEND_ARG_INFO(0, service_handle) 234 ZEND_ARG_INFO(0, user_name) 235 ZEND_ARG_INFO(0, password) 236 ZEND_ARG_INFO(0, first_name) 237 ZEND_ARG_INFO(0, middle_name) 238 ZEND_ARG_INFO(0, last_name) 239ZEND_END_ARG_INFO() 240 241ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_modify_user, 0, 0, 3) 242 ZEND_ARG_INFO(0, service_handle) 243 ZEND_ARG_INFO(0, user_name) 244 ZEND_ARG_INFO(0, password) 245 ZEND_ARG_INFO(0, first_name) 246 ZEND_ARG_INFO(0, middle_name) 247 ZEND_ARG_INFO(0, last_name) 248ZEND_END_ARG_INFO() 249 250ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_delete_user, 0, 0, 3) 251 ZEND_ARG_INFO(0, service_handle) 252 ZEND_ARG_INFO(0, user_name) 253 ZEND_ARG_INFO(0, password) 254 ZEND_ARG_INFO(0, first_name) 255 ZEND_ARG_INFO(0, middle_name) 256 ZEND_ARG_INFO(0, last_name) 257ZEND_END_ARG_INFO() 258 259ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_attach, 0, 0, 3) 260 ZEND_ARG_INFO(0, host) 261 ZEND_ARG_INFO(0, dba_username) 262 ZEND_ARG_INFO(0, dba_password) 263ZEND_END_ARG_INFO() 264 265ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_detach, 0, 0, 1) 266 ZEND_ARG_INFO(0, service_handle) 267ZEND_END_ARG_INFO() 268 269ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_backup, 0, 0, 3) 270 ZEND_ARG_INFO(0, service_handle) 271 ZEND_ARG_INFO(0, source_db) 272 ZEND_ARG_INFO(0, dest_file) 273 ZEND_ARG_INFO(0, options) 274 ZEND_ARG_INFO(0, verbose) 275ZEND_END_ARG_INFO() 276 277ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_restore, 0, 0, 3) 278 ZEND_ARG_INFO(0, service_handle) 279 ZEND_ARG_INFO(0, source_file) 280 ZEND_ARG_INFO(0, dest_db) 281 ZEND_ARG_INFO(0, options) 282 ZEND_ARG_INFO(0, verbose) 283ZEND_END_ARG_INFO() 284 285ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_maintain_db, 0, 0, 3) 286 ZEND_ARG_INFO(0, service_handle) 287 ZEND_ARG_INFO(0, db) 288 ZEND_ARG_INFO(0, action) 289 ZEND_ARG_INFO(0, argument) 290ZEND_END_ARG_INFO() 291 292ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_db_info, 0, 0, 3) 293 ZEND_ARG_INFO(0, service_handle) 294 ZEND_ARG_INFO(0, db) 295 ZEND_ARG_INFO(0, action) 296 ZEND_ARG_INFO(0, argument) 297ZEND_END_ARG_INFO() 298 299ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_server_info, 0, 0, 2) 300 ZEND_ARG_INFO(0, service_handle) 301 ZEND_ARG_INFO(0, action) 302ZEND_END_ARG_INFO() 303 304ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_wait_event, 0, 0, 1) 305 ZEND_ARG_INFO(0, link_identifier) 306 ZEND_ARG_INFO(0, event) 307 ZEND_ARG_INFO(0, event2) 308ZEND_END_ARG_INFO() 309 310ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_set_event_handler, 0, 0, 2) 311 ZEND_ARG_INFO(0, link_identifier) 312 ZEND_ARG_INFO(0, handler) 313 ZEND_ARG_INFO(0, event) 314 ZEND_ARG_INFO(0, event2) 315ZEND_END_ARG_INFO() 316 317ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_event_handler, 0, 0, 1) 318 ZEND_ARG_INFO(0, event) 319ZEND_END_ARG_INFO() 320/* }}} */ 321 322/* {{{ extension definition structures */ 323const zend_function_entry ibase_functions[] = { 324 PHP_FE(ibase_connect, arginfo_ibase_connect) 325 PHP_FE(ibase_pconnect, arginfo_ibase_pconnect) 326 PHP_FE(ibase_close, arginfo_ibase_close) 327 PHP_FE(ibase_drop_db, arginfo_ibase_drop_db) 328 PHP_FE(ibase_query, arginfo_ibase_query) 329 PHP_FE(ibase_fetch_row, arginfo_ibase_fetch_row) 330 PHP_FE(ibase_fetch_assoc, arginfo_ibase_fetch_assoc) 331 PHP_FE(ibase_fetch_object, arginfo_ibase_fetch_object) 332 PHP_FE(ibase_free_result, arginfo_ibase_free_result) 333 PHP_FE(ibase_name_result, arginfo_ibase_name_result) 334 PHP_FE(ibase_prepare, arginfo_ibase_prepare) 335 PHP_FE(ibase_execute, arginfo_ibase_execute) 336 PHP_FE(ibase_free_query, arginfo_ibase_free_query) 337 PHP_FE(ibase_gen_id, arginfo_ibase_gen_id) 338 PHP_FE(ibase_num_fields, arginfo_ibase_num_fields) 339 PHP_FE(ibase_num_params, arginfo_ibase_num_params) 340#if abies_0 341 PHP_FE(ibase_num_rows, arginfo_ibase_num_rows) 342#endif 343 PHP_FE(ibase_affected_rows, arginfo_ibase_affected_rows) 344 PHP_FE(ibase_field_info, arginfo_ibase_field_info) 345 PHP_FE(ibase_param_info, arginfo_ibase_param_info) 346 347 PHP_FE(ibase_trans, arginfo_ibase_trans) 348 PHP_FE(ibase_commit, arginfo_ibase_commit) 349 PHP_FE(ibase_rollback, arginfo_ibase_rollback) 350 PHP_FE(ibase_commit_ret, arginfo_ibase_commit_ret) 351 PHP_FE(ibase_rollback_ret, arginfo_ibase_rollback_ret) 352 353 PHP_FE(ibase_blob_info, arginfo_ibase_blob_info) 354 PHP_FE(ibase_blob_create, arginfo_ibase_blob_create) 355 PHP_FE(ibase_blob_add, arginfo_ibase_blob_add) 356 PHP_FE(ibase_blob_cancel, arginfo_ibase_blob_cancel) 357 PHP_FE(ibase_blob_close, arginfo_ibase_blob_close) 358 PHP_FE(ibase_blob_open, arginfo_ibase_blob_open) 359 PHP_FE(ibase_blob_get, arginfo_ibase_blob_get) 360 PHP_FE(ibase_blob_echo, arginfo_ibase_blob_echo) 361 PHP_FE(ibase_blob_import, arginfo_ibase_blob_import) 362 PHP_FE(ibase_errmsg, arginfo_ibase_errmsg) 363 PHP_FE(ibase_errcode, arginfo_ibase_errcode) 364 365 PHP_FE(ibase_add_user, arginfo_ibase_add_user) 366 PHP_FE(ibase_modify_user, arginfo_ibase_modify_user) 367 PHP_FE(ibase_delete_user, arginfo_ibase_delete_user) 368 369 PHP_FE(ibase_service_attach, arginfo_ibase_service_attach) 370 PHP_FE(ibase_service_detach, arginfo_ibase_service_detach) 371 PHP_FE(ibase_backup, arginfo_ibase_backup) 372 PHP_FE(ibase_restore, arginfo_ibase_restore) 373 PHP_FE(ibase_maintain_db, arginfo_ibase_maintain_db) 374 PHP_FE(ibase_db_info, arginfo_ibase_db_info) 375 PHP_FE(ibase_server_info, arginfo_ibase_server_info) 376 377 PHP_FE(ibase_wait_event, arginfo_ibase_wait_event) 378 PHP_FE(ibase_set_event_handler, arginfo_ibase_set_event_handler) 379 PHP_FE(ibase_free_event_handler, arginfo_ibase_free_event_handler) 380 381 /** 382 * These aliases are provided in order to maintain forward compatibility. As Firebird 383 * and InterBase are developed independently, functionality might be different between 384 * the two branches in future versions. 385 * Firebird users should use the aliases, so future InterBase-specific changes will 386 * not affect their code 387 */ 388 PHP_FALIAS(fbird_connect, ibase_connect, arginfo_ibase_connect) 389 PHP_FALIAS(fbird_pconnect, ibase_pconnect, arginfo_ibase_pconnect) 390 PHP_FALIAS(fbird_close, ibase_close, arginfo_ibase_close) 391 PHP_FALIAS(fbird_drop_db, ibase_drop_db, arginfo_ibase_drop_db) 392 PHP_FALIAS(fbird_query, ibase_query, arginfo_ibase_query) 393 PHP_FALIAS(fbird_fetch_row, ibase_fetch_row, arginfo_ibase_fetch_row) 394 PHP_FALIAS(fbird_fetch_assoc, ibase_fetch_assoc, arginfo_ibase_fetch_assoc) 395 PHP_FALIAS(fbird_fetch_object, ibase_fetch_object, arginfo_ibase_fetch_object) 396 PHP_FALIAS(fbird_free_result, ibase_free_result, arginfo_ibase_free_result) 397 PHP_FALIAS(fbird_name_result, ibase_name_result, arginfo_ibase_name_result) 398 PHP_FALIAS(fbird_prepare, ibase_prepare, arginfo_ibase_prepare) 399 PHP_FALIAS(fbird_execute, ibase_execute, arginfo_ibase_execute) 400 PHP_FALIAS(fbird_free_query, ibase_free_query, arginfo_ibase_free_query) 401 PHP_FALIAS(fbird_gen_id, ibase_gen_id, arginfo_ibase_gen_id) 402 PHP_FALIAS(fbird_num_fields, ibase_num_fields, arginfo_ibase_num_fields) 403 PHP_FALIAS(fbird_num_params, ibase_num_params, arginfo_ibase_num_params) 404#if abies_0 405 PHP_FALIAS(fbird_num_rows, ibase_num_rows, arginfo_ibase_num_rows) 406#endif 407 PHP_FALIAS(fbird_affected_rows, ibase_affected_rows, arginfo_ibase_affected_rows) 408 PHP_FALIAS(fbird_field_info, ibase_field_info, arginfo_ibase_field_info) 409 PHP_FALIAS(fbird_param_info, ibase_param_info, arginfo_ibase_param_info) 410 411 PHP_FALIAS(fbird_trans, ibase_trans, arginfo_ibase_trans) 412 PHP_FALIAS(fbird_commit, ibase_commit, arginfo_ibase_commit) 413 PHP_FALIAS(fbird_rollback, ibase_rollback, arginfo_ibase_rollback) 414 PHP_FALIAS(fbird_commit_ret, ibase_commit_ret, arginfo_ibase_commit_ret) 415 PHP_FALIAS(fbird_rollback_ret, ibase_rollback_ret, arginfo_ibase_rollback_ret) 416 417 PHP_FALIAS(fbird_blob_info, ibase_blob_info, arginfo_ibase_blob_info) 418 PHP_FALIAS(fbird_blob_create, ibase_blob_create, arginfo_ibase_blob_create) 419 PHP_FALIAS(fbird_blob_add, ibase_blob_add, arginfo_ibase_blob_add) 420 PHP_FALIAS(fbird_blob_cancel, ibase_blob_cancel, arginfo_ibase_blob_cancel) 421 PHP_FALIAS(fbird_blob_close, ibase_blob_close, arginfo_ibase_blob_close) 422 PHP_FALIAS(fbird_blob_open, ibase_blob_open, arginfo_ibase_blob_open) 423 PHP_FALIAS(fbird_blob_get, ibase_blob_get, arginfo_ibase_blob_get) 424 PHP_FALIAS(fbird_blob_echo, ibase_blob_echo, arginfo_ibase_blob_echo) 425 PHP_FALIAS(fbird_blob_import, ibase_blob_import, arginfo_ibase_blob_import) 426 PHP_FALIAS(fbird_errmsg, ibase_errmsg, arginfo_ibase_errmsg) 427 PHP_FALIAS(fbird_errcode, ibase_errcode, arginfo_ibase_errcode) 428 429 PHP_FALIAS(fbird_add_user, ibase_add_user, arginfo_ibase_add_user) 430 PHP_FALIAS(fbird_modify_user, ibase_modify_user, arginfo_ibase_modify_user) 431 PHP_FALIAS(fbird_delete_user, ibase_delete_user, arginfo_ibase_delete_user) 432 433 PHP_FALIAS(fbird_service_attach, ibase_service_attach, arginfo_ibase_service_attach) 434 PHP_FALIAS(fbird_service_detach, ibase_service_detach, arginfo_ibase_service_detach) 435 PHP_FALIAS(fbird_backup, ibase_backup, arginfo_ibase_backup) 436 PHP_FALIAS(fbird_restore, ibase_restore, arginfo_ibase_restore) 437 PHP_FALIAS(fbird_maintain_db, ibase_maintain_db, arginfo_ibase_maintain_db) 438 PHP_FALIAS(fbird_db_info, ibase_db_info, arginfo_ibase_db_info) 439 PHP_FALIAS(fbird_server_info, ibase_server_info, arginfo_ibase_server_info) 440 441 PHP_FALIAS(fbird_wait_event, ibase_wait_event, arginfo_ibase_wait_event) 442 PHP_FALIAS(fbird_set_event_handler, ibase_set_event_handler, arginfo_ibase_set_event_handler) 443 PHP_FALIAS(fbird_free_event_handler, ibase_free_event_handler, arginfo_ibase_free_event_handler) 444 PHP_FE_END 445}; 446 447zend_module_entry ibase_module_entry = { 448 STANDARD_MODULE_HEADER, 449 "interbase", 450 ibase_functions, 451 PHP_MINIT(ibase), 452 PHP_MSHUTDOWN(ibase), 453 NULL, 454 PHP_RSHUTDOWN(ibase), 455 PHP_MINFO(ibase), 456 NO_VERSION_YET, 457 PHP_MODULE_GLOBALS(ibase), 458 PHP_GINIT(ibase), 459 NULL, 460 NULL, 461 STANDARD_MODULE_PROPERTIES_EX 462}; 463 464#ifdef COMPILE_DL_INTERBASE 465ZEND_GET_MODULE(ibase) 466#endif 467 468/* True globals, no need for thread safety */ 469int le_link, le_plink, le_trans; 470 471/* }}} */ 472 473/* error handling ---------------------------- */ 474 475/* {{{ proto string ibase_errmsg(void) 476 Return error message */ 477PHP_FUNCTION(ibase_errmsg) 478{ 479 if (zend_parse_parameters_none() == FAILURE) { 480 return; 481 } 482 483 if (IBG(sql_code) != 0) { 484 RETURN_STRING(IBG(errmsg), 1); 485 } 486 487 RETURN_FALSE; 488} 489/* }}} */ 490 491/* {{{ proto int ibase_errcode(void) 492 Return error code */ 493PHP_FUNCTION(ibase_errcode) 494{ 495 if (zend_parse_parameters_none() == FAILURE) { 496 return; 497 } 498 499 if (IBG(sql_code) != 0) { 500 RETURN_LONG(IBG(sql_code)); 501 } 502 RETURN_FALSE; 503} 504/* }}} */ 505 506/* print interbase error and save it for ibase_errmsg() */ 507void _php_ibase_error(TSRMLS_D) /* {{{ */ 508{ 509 char *s = IBG(errmsg); 510 ISC_STATUS *statusp = IB_STATUS; 511 512 IBG(sql_code) = isc_sqlcode(IB_STATUS); 513 514 while ((s - IBG(errmsg)) < MAX_ERRMSG - (IBASE_MSGSIZE + 2) && isc_interprete(s, &statusp)) { 515 strcat(IBG(errmsg), " "); 516 s = IBG(errmsg) + strlen(IBG(errmsg)); 517 } 518 519 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg)); 520} 521/* }}} */ 522 523/* print php interbase module error and save it for ibase_errmsg() */ 524void _php_ibase_module_error(char *msg TSRMLS_DC, ...) /* {{{ */ 525{ 526 va_list ap; 527 528#ifdef ZTS 529 va_start(ap, TSRMLS_C); 530#else 531 va_start(ap, msg); 532#endif 533 534 /* vsnprintf NUL terminates the buf and writes at most n-1 chars+NUL */ 535 vsnprintf(IBG(errmsg), MAX_ERRMSG, msg, ap); 536 va_end(ap); 537 538 IBG(sql_code) = -999; /* no SQL error */ 539 540 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg)); 541} 542/* }}} */ 543 544/* {{{ internal macros, functions and structures */ 545typedef struct { 546 isc_db_handle *db_ptr; 547 long tpb_len; 548 char *tpb_ptr; 549} ISC_TEB; 550 551/* }}} */ 552 553/* Fill ib_link and trans with the correct database link and transaction. */ 554void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */ 555 zval **link_id, ibase_db_link **ib_link, ibase_trans **trans) 556{ 557 int type; 558 559 IBDEBUG("Transaction or database link?"); 560 if (zend_list_find(Z_LVAL_PP(link_id), &type)) { 561 if (type == le_trans) { 562 /* Transaction resource: make sure it refers to one link only, then 563 fetch it; database link is stored in ib_trans->db_link[]. */ 564 IBDEBUG("Type is le_trans"); 565 ZEND_FETCH_RESOURCE(*trans, ibase_trans *, link_id, -1, LE_TRANS, le_trans); 566 if ((*trans)->link_cnt > 1) { 567 _php_ibase_module_error("Link id is ambiguous: transaction spans multiple connections." 568 TSRMLS_CC); 569 return; 570 } 571 *ib_link = (*trans)->db_link[0]; 572 return; 573 } 574 } 575 IBDEBUG("Type is le_[p]link or id not found"); 576 /* Database link resource, use default transaction. */ 577 *trans = NULL; 578 ZEND_FETCH_RESOURCE2(*ib_link, ibase_db_link *, link_id, -1, LE_LINK, le_link, le_plink); 579} 580/* }}} */ 581 582/* destructors ---------------------- */ 583 584static void _php_ibase_commit_link(ibase_db_link *link TSRMLS_DC) /* {{{ */ 585{ 586 unsigned short i = 0, j; 587 ibase_tr_list *l; 588 ibase_event *e; 589 IBDEBUG("Checking transactions to close..."); 590 591 for (l = link->tr_list; l != NULL; ++i) { 592 ibase_tr_list *p = l; 593 if (p->trans != NULL) { 594 if (i == 0) { 595 if (p->trans->handle != NULL) { 596 IBDEBUG("Committing default transaction..."); 597 if (isc_commit_transaction(IB_STATUS, &p->trans->handle)) { 598 _php_ibase_error(TSRMLS_C); 599 } 600 } 601 efree(p->trans); /* default transaction is not a registered resource: clean up */ 602 } else { 603 if (p->trans->handle != NULL) { 604 /* non-default trans might have been rolled back by other call of this dtor */ 605 IBDEBUG("Rolling back other transactions..."); 606 if (isc_rollback_transaction(IB_STATUS, &p->trans->handle)) { 607 _php_ibase_error(TSRMLS_C); 608 } 609 } 610 /* set this link pointer to NULL in the transaction */ 611 for (j = 0; j < p->trans->link_cnt; ++j) { 612 if (p->trans->db_link[j] == link) { 613 p->trans->db_link[j] = NULL; 614 break; 615 } 616 } 617 } 618 } 619 l = l->next; 620 efree(p); 621 } 622 link->tr_list = NULL; 623 624 for (e = link->event_head; e; e = e->event_next) { 625 _php_ibase_free_event(e TSRMLS_CC); 626 e->link = NULL; 627 } 628} 629 630/* }}} */ 631 632static void php_ibase_commit_link_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ 633{ 634 ibase_db_link *link = (ibase_db_link *) rsrc->ptr; 635 636 _php_ibase_commit_link(link TSRMLS_CC); 637} 638/* }}} */ 639 640static void _php_ibase_close_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ 641{ 642 ibase_db_link *link = (ibase_db_link *) rsrc->ptr; 643 644 _php_ibase_commit_link(link TSRMLS_CC); 645 if (link->handle != NULL) { 646 IBDEBUG("Closing normal link..."); 647 isc_detach_database(IB_STATUS, &link->handle); 648 } 649 IBG(num_links)--; 650 efree(link); 651} 652/* }}} */ 653 654static void _php_ibase_close_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ 655{ 656 ibase_db_link *link = (ibase_db_link *) rsrc->ptr; 657 658 _php_ibase_commit_link(link TSRMLS_CC); 659 IBDEBUG("Closing permanent link..."); 660 if (link->handle != NULL) { 661 isc_detach_database(IB_STATUS, &link->handle); 662 } 663 IBG(num_persistent)--; 664 IBG(num_links)--; 665 free(link); 666} 667/* }}} */ 668 669static void _php_ibase_free_trans(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ 670{ 671 ibase_trans *trans = (ibase_trans *)rsrc->ptr; 672 unsigned short i; 673 674 IBDEBUG("Cleaning up transaction resource..."); 675 if (trans->handle != NULL) { 676 IBDEBUG("Rolling back unhandled transaction..."); 677 if (isc_rollback_transaction(IB_STATUS, &trans->handle)) { 678 _php_ibase_error(TSRMLS_C); 679 } 680 } 681 682 /* now remove this transaction from all the connection-transaction lists */ 683 for (i = 0; i < trans->link_cnt; ++i) { 684 if (trans->db_link[i] != NULL) { 685 ibase_tr_list **l; 686 for (l = &trans->db_link[i]->tr_list; *l != NULL; l = &(*l)->next) { 687 if ( (*l)->trans == trans) { 688 ibase_tr_list *p = *l; 689 *l = p->next; 690 efree(p); 691 break; 692 } 693 } 694 } 695 } 696 efree(trans); 697} 698/* }}} */ 699 700/* TODO this function should be part of either Zend or PHP API */ 701static PHP_INI_DISP(php_ibase_password_displayer_cb) 702{ 703 TSRMLS_FETCH(); 704 705 if ((type == PHP_INI_DISPLAY_ORIG && ini_entry->orig_value) 706 || (type == PHP_INI_DISPLAY_ACTIVE && ini_entry->value)) { 707 PUTS("********"); 708 } else if (!sapi_module.phpinfo_as_text) { 709 PUTS("<i>no value</i>"); 710 } else { 711 PUTS("no value"); 712 } 713} 714 715/* {{{ startup, shutdown and info functions */ 716PHP_INI_BEGIN() 717 PHP_INI_ENTRY_EX("ibase.allow_persistent", "1", PHP_INI_SYSTEM, NULL, zend_ini_boolean_displayer_cb) 718 PHP_INI_ENTRY_EX("ibase.max_persistent", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers) 719 PHP_INI_ENTRY_EX("ibase.max_links", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers) 720 PHP_INI_ENTRY("ibase.default_db", NULL, PHP_INI_SYSTEM, NULL) 721 PHP_INI_ENTRY("ibase.default_user", NULL, PHP_INI_ALL, NULL) 722 PHP_INI_ENTRY_EX("ibase.default_password", NULL, PHP_INI_ALL, NULL, php_ibase_password_displayer_cb) 723 PHP_INI_ENTRY("ibase.default_charset", NULL, PHP_INI_ALL, NULL) 724 PHP_INI_ENTRY("ibase.timestampformat", IB_DEF_DATE_FMT " " IB_DEF_TIME_FMT, PHP_INI_ALL, NULL) 725 PHP_INI_ENTRY("ibase.dateformat", IB_DEF_DATE_FMT, PHP_INI_ALL, NULL) 726 PHP_INI_ENTRY("ibase.timeformat", IB_DEF_TIME_FMT, PHP_INI_ALL, NULL) 727PHP_INI_END() 728 729static PHP_GINIT_FUNCTION(ibase) 730{ 731 ibase_globals->num_persistent = ibase_globals->num_links = 0; 732 ibase_globals->sql_code = *ibase_globals->errmsg = 0; 733 ibase_globals->default_link = -1; 734} 735 736PHP_MINIT_FUNCTION(ibase) 737{ 738 REGISTER_INI_ENTRIES(); 739 740 le_link = zend_register_list_destructors_ex(_php_ibase_close_link, NULL, LE_LINK, module_number); 741 le_plink = zend_register_list_destructors_ex(php_ibase_commit_link_rsrc, _php_ibase_close_plink, LE_PLINK, module_number); 742 le_trans = zend_register_list_destructors_ex(_php_ibase_free_trans, NULL, LE_TRANS, module_number); 743 744 REGISTER_LONG_CONSTANT("IBASE_DEFAULT", PHP_IBASE_DEFAULT, CONST_PERSISTENT); 745 REGISTER_LONG_CONSTANT("IBASE_CREATE", PHP_IBASE_CREATE, CONST_PERSISTENT); 746 REGISTER_LONG_CONSTANT("IBASE_TEXT", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); /* deprecated, for BC only */ 747 REGISTER_LONG_CONSTANT("IBASE_FETCH_BLOBS", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); 748 REGISTER_LONG_CONSTANT("IBASE_FETCH_ARRAYS", PHP_IBASE_FETCH_ARRAYS, CONST_PERSISTENT); 749 REGISTER_LONG_CONSTANT("IBASE_UNIXTIME", PHP_IBASE_UNIXTIME, CONST_PERSISTENT); 750 751 /* transactions */ 752 REGISTER_LONG_CONSTANT("IBASE_WRITE", PHP_IBASE_WRITE, CONST_PERSISTENT); 753 REGISTER_LONG_CONSTANT("IBASE_READ", PHP_IBASE_READ, CONST_PERSISTENT); 754 REGISTER_LONG_CONSTANT("IBASE_COMMITTED", PHP_IBASE_COMMITTED, CONST_PERSISTENT); 755 REGISTER_LONG_CONSTANT("IBASE_CONSISTENCY", PHP_IBASE_CONSISTENCY, CONST_PERSISTENT); 756 REGISTER_LONG_CONSTANT("IBASE_CONCURRENCY", PHP_IBASE_CONCURRENCY, CONST_PERSISTENT); 757 REGISTER_LONG_CONSTANT("IBASE_REC_VERSION", PHP_IBASE_REC_VERSION, CONST_PERSISTENT); 758 REGISTER_LONG_CONSTANT("IBASE_REC_NO_VERSION", PHP_IBASE_REC_NO_VERSION, CONST_PERSISTENT); 759 REGISTER_LONG_CONSTANT("IBASE_NOWAIT", PHP_IBASE_NOWAIT, CONST_PERSISTENT); 760 REGISTER_LONG_CONSTANT("IBASE_WAIT", PHP_IBASE_WAIT, CONST_PERSISTENT); 761 762 php_ibase_query_minit(INIT_FUNC_ARGS_PASSTHRU); 763 php_ibase_blobs_minit(INIT_FUNC_ARGS_PASSTHRU); 764 php_ibase_events_minit(INIT_FUNC_ARGS_PASSTHRU); 765 php_ibase_service_minit(INIT_FUNC_ARGS_PASSTHRU); 766 767 return SUCCESS; 768} 769 770PHP_MSHUTDOWN_FUNCTION(ibase) 771{ 772#ifndef PHP_WIN32 773 /** 774 * When the Interbase client API library libgds.so is first loaded, it registers a call to 775 * gds__cleanup() with atexit(), in order to clean up after itself when the process exits. 776 * This means that the library is called at process shutdown, and cannot be unloaded beforehand. 777 * PHP tries to unload modules after every request [dl()'ed modules], and right before the 778 * process shuts down [modules loaded from php.ini]. This results in a segfault for this module. 779 * By NULLing the dlopen() handle in the module entry, Zend omits the call to dlclose(), 780 * ensuring that the module will remain present until the process exits. However, the functions 781 * and classes exported by the module will not be available until the module is 'reloaded'. 782 * When reloaded, dlopen() will return the handle of the already loaded module. The module will 783 * be unloaded automatically when the process exits. 784 */ 785 zend_module_entry *ibase_entry; 786 if (SUCCESS == zend_hash_find(&module_registry, ibase_module_entry.name, 787 strlen(ibase_module_entry.name) +1, (void*) &ibase_entry)) { 788 ibase_entry->handle = NULL; 789 } 790#endif 791 UNREGISTER_INI_ENTRIES(); 792 return SUCCESS; 793} 794 795PHP_RSHUTDOWN_FUNCTION(ibase) 796{ 797 IBG(num_links) = IBG(num_persistent); 798 IBG(default_link)= -1; 799 800 RESET_ERRMSG; 801 802 return SUCCESS; 803} 804 805PHP_MINFO_FUNCTION(ibase) 806{ 807 char tmp[64], *s; 808 809 php_info_print_table_start(); 810 php_info_print_table_row(2, "Firebird/InterBase Support", 811#ifdef COMPILE_DL_INTERBASE 812 "dynamic"); 813#else 814 "static"); 815#endif 816 817#ifdef FB_API_VER 818 snprintf( (s = tmp), sizeof(tmp), "Firebird API version %d", FB_API_VER); 819#elif (SQLDA_CURRENT_VERSION > 1) 820 s = "Interbase 7.0 and up"; 821#elif !defined(DSC_null) 822 s = "Interbase 6"; 823#else 824 s = "Firebird 1.0"; 825#endif 826 php_info_print_table_row(2, "Compile-time Client Library Version", s); 827 828#if defined(__GNUC__) || defined(PHP_WIN32) 829 do { 830 info_func_t info_func = NULL; 831#ifdef __GNUC__ 832 info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version"); 833#else 834 HMODULE l = GetModuleHandle("fbclient"); 835 836 if (!l && !(l = GetModuleHandle("gds32"))) { 837 break; 838 } 839 info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version"); 840#endif 841 if (info_func) { 842 info_func(s = tmp); 843 } else { 844 s = "Firebird 1.0/Interbase 6"; 845 } 846 php_info_print_table_row(2, "Run-time Client Library Version", s); 847 } while (0); 848#endif 849 php_info_print_table_end(); 850 851 DISPLAY_INI_ENTRIES(); 852 853} 854/* }}} */ 855 856enum connect_args { DB = 0, USER = 1, PASS = 2, CSET = 3, ROLE = 4, BUF = 0, DLECT = 1, SYNC = 2 }; 857 858static char const dpb_args[] = { 859 0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name, 0 860}; 861 862int _php_ibase_attach_db(char **args, int *len, long *largs, isc_db_handle *db TSRMLS_DC) 863{ 864 short i, dpb_len, buf_len = 257-2; /* version byte at the front, and a null at the end */ 865 char dpb_buffer[257] = { isc_dpb_version1, 0 }, *dpb; 866 867 dpb = dpb_buffer + 1; 868 869 for (i = 0; i < sizeof(dpb_args); ++i) { 870 if (dpb_args[i] && args[i] && len[i] && buf_len > 0) { 871 dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]); 872 dpb += dpb_len; 873 buf_len -= dpb_len; 874 } 875 } 876 if (largs[BUF] && buf_len > 0) { 877 dpb_len = slprintf(dpb, buf_len, "%c\2%c%c", isc_dpb_num_buffers, 878 (char)(largs[BUF] >> 8), (char)(largs[BUF] & 0xff)); 879 dpb += dpb_len; 880 buf_len -= dpb_len; 881 } 882 if (largs[SYNC] && buf_len > 0) { 883 dpb_len = slprintf(dpb, buf_len, "%c\1%c", isc_dpb_force_write, largs[SYNC] == isc_spb_prp_wm_sync ? 1 : 0); 884 dpb += dpb_len; 885 buf_len -= dpb_len; 886 } 887 if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) { 888 _php_ibase_error(TSRMLS_C); 889 return FAILURE; 890 } 891 return SUCCESS; 892} 893/* }}} */ 894 895static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */ 896{ 897 char *c, hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL }; 898 int i, len[] = { 0, 0, 0, 0, 0 }; 899 long largs[] = { 0, 0, 0 }; 900 PHP_MD5_CTX hash_context; 901 zend_rsrc_list_entry new_index_ptr, *le; 902 isc_db_handle db_handle = NULL; 903 ibase_db_link *ib_link; 904 905 RESET_ERRMSG; 906 907 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ssssllsl", 908 &args[DB], &len[DB], &args[USER], &len[USER], &args[PASS], &len[PASS], 909 &args[CSET], &len[CSET], &largs[BUF], &largs[DLECT], &args[ROLE], &len[ROLE], 910 &largs[SYNC])) { 911 RETURN_FALSE; 912 } 913 914 /* restrict to the server/db in the .ini if in safe mode */ 915 if ((!len[DB] || PG(sql_safe_mode)) && (c = INI_STR("ibase.default_db"))) { 916 args[DB] = c; 917 len[DB] = strlen(c); 918 } 919 if (!len[USER] && (c = INI_STR("ibase.default_user"))) { 920 args[USER] = c; 921 len[USER] = strlen(c); 922 } 923 if (!len[PASS] && (c = INI_STR("ibase.default_password"))) { 924 args[PASS] = c; 925 len[PASS] = strlen(c); 926 } 927 if (!len[CSET] && (c = INI_STR("ibase.default_charset"))) { 928 args[CSET] = c; 929 len[CSET] = strlen(c); 930 } 931 932 /* don't want usernames and passwords floating around */ 933 PHP_MD5Init(&hash_context); 934 for (i = 0; i < sizeof(args)/sizeof(char*); ++i) { 935 PHP_MD5Update(&hash_context,args[i],len[i]); 936 } 937 for (i = 0; i < sizeof(largs)/sizeof(long); ++i) { 938 PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(long)); 939 } 940 PHP_MD5Final(hash, &hash_context); 941 942 /* try to reuse a connection */ 943 if (SUCCESS == zend_hash_find(&EG(regular_list), hash, sizeof(hash), (void *) &le)) { 944 long xlink; 945 int type; 946 947 if (Z_TYPE_P(le) != le_index_ptr) { 948 RETURN_FALSE; 949 } 950 951 xlink = (long) le->ptr; 952 if (zend_list_find(xlink, &type) && ((!persistent && type == le_link) || type == le_plink)) { 953 zend_list_addref(xlink); 954 RETURN_RESOURCE(IBG(default_link) = xlink); 955 } else { 956 zend_hash_del(&EG(regular_list), hash, sizeof(hash)); 957 } 958 } 959 960 /* ... or a persistent one */ 961 switch (zend_hash_find(&EG(persistent_list), hash, sizeof(hash), (void *) &le)) { 962 long l; 963 964 static char info[] = { isc_info_base_level, isc_info_end }; 965 char result[8]; 966 ISC_STATUS status[20]; 967 968 case SUCCESS: 969 970 if (Z_TYPE_P(le) != le_plink) { 971 RETURN_FALSE; 972 } 973 /* check if connection has timed out */ 974 ib_link = (ibase_db_link *) le->ptr; 975 if (!isc_database_info(status, &ib_link->handle, sizeof(info), info, sizeof(result), result)) { 976 ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink); 977 break; 978 } 979 zend_hash_del(&EG(persistent_list), hash, sizeof(hash)); 980 981 default: 982 983 /* no link found, so we have to open one */ 984 985 if ((l = INI_INT("ibase.max_links")) != -1 && IBG(num_links) >= l) { 986 _php_ibase_module_error("Too many open links (%ld)" TSRMLS_CC, IBG(num_links)); 987 RETURN_FALSE; 988 } 989 990 /* create the ib_link */ 991 if (FAILURE == _php_ibase_attach_db(args, len, largs, &db_handle TSRMLS_CC)) { 992 RETURN_FALSE; 993 } 994 995 /* use non-persistent if allowed number of persistent links is exceeded */ 996 if (!persistent || ((l = INI_INT("ibase.max_persistent") != -1) && IBG(num_persistent) >= l)) { 997 ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link)); 998 ZEND_REGISTER_RESOURCE(return_value, ib_link, le_link); 999 } else { 1000 zend_rsrc_list_entry new_le; 1001 1002 ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link)); 1003 if (!ib_link) { 1004 RETURN_FALSE; 1005 } 1006 1007 /* hash it up */ 1008 Z_TYPE(new_le) = le_plink; 1009 new_le.ptr = ib_link; 1010 if (FAILURE == zend_hash_update(&EG(persistent_list), hash, sizeof(hash), 1011 (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)) { 1012 free(ib_link); 1013 RETURN_FALSE; 1014 } 1015 ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink); 1016 ++IBG(num_persistent); 1017 } 1018 ib_link->handle = db_handle; 1019 ib_link->dialect = largs[DLECT] ? (unsigned short)largs[DLECT] : SQL_DIALECT_CURRENT; 1020 ib_link->tr_list = NULL; 1021 ib_link->event_head = NULL; 1022 1023 ++IBG(num_links); 1024 } 1025 1026 /* add it to the hash */ 1027 new_index_ptr.ptr = (void *) Z_LVAL_P(return_value); 1028 Z_TYPE(new_index_ptr) = le_index_ptr; 1029 if (FAILURE == zend_hash_update(&EG(regular_list), hash, sizeof(hash), 1030 (void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)) { 1031 RETURN_FALSE; 1032 } 1033 zend_list_addref(IBG(default_link) = Z_LVAL_P(return_value)); 1034} 1035/* }}} */ 1036 1037/* {{{ proto resource ibase_connect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]) 1038 Open a connection to an InterBase database */ 1039PHP_FUNCTION(ibase_connect) 1040{ 1041 _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); 1042} 1043/* }}} */ 1044 1045/* {{{ proto resource ibase_pconnect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]]) 1046 Open a persistent connection to an InterBase database */ 1047PHP_FUNCTION(ibase_pconnect) 1048{ 1049 _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INI_INT("ibase.allow_persistent")); 1050} 1051/* }}} */ 1052 1053/* {{{ proto bool ibase_close([resource link_identifier]) 1054 Close an InterBase connection */ 1055PHP_FUNCTION(ibase_close) 1056{ 1057 zval *link_arg = NULL; 1058 ibase_db_link *ib_link; 1059 int link_id; 1060 1061 RESET_ERRMSG; 1062 1063 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) { 1064 return; 1065 } 1066 1067 if (ZEND_NUM_ARGS() == 0) { 1068 link_id = IBG(default_link); 1069 CHECK_LINK(link_id); 1070 IBG(default_link) = -1; 1071 } else { 1072 link_id = Z_RESVAL_P(link_arg); 1073 } 1074 1075 ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink); 1076 zend_list_delete(link_id); 1077 RETURN_TRUE; 1078} 1079/* }}} */ 1080 1081/* {{{ proto bool ibase_drop_db([resource link_identifier]) 1082 Drop an InterBase database */ 1083PHP_FUNCTION(ibase_drop_db) 1084{ 1085 zval *link_arg = NULL; 1086 ibase_db_link *ib_link; 1087 ibase_tr_list *l; 1088 int link_id; 1089 1090 RESET_ERRMSG; 1091 1092 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) { 1093 return; 1094 } 1095 1096 if (ZEND_NUM_ARGS() == 0) { 1097 link_id = IBG(default_link); 1098 CHECK_LINK(link_id); 1099 IBG(default_link) = -1; 1100 } else { 1101 link_id = Z_RESVAL_P(link_arg); 1102 } 1103 1104 ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink); 1105 1106 if (isc_drop_database(IB_STATUS, &ib_link->handle)) { 1107 _php_ibase_error(TSRMLS_C); 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 = NULL; 1114 } 1115 1116 zend_list_delete(link_id); 1117 RETURN_TRUE; 1118} 1119/* }}} */ 1120 1121/* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]]) 1122 Start a transaction over one or several databases */ 1123 1124#define TPB_MAX_SIZE (8*sizeof(char)) 1125 1126PHP_FUNCTION(ibase_trans) 1127{ 1128 unsigned short i, link_cnt = 0, tpb_len = 0; 1129 int argn; 1130 char last_tpb[TPB_MAX_SIZE]; 1131 ibase_db_link **ib_link = NULL; 1132 ibase_trans *ib_trans; 1133 isc_tr_handle tr_handle = NULL; 1134 ISC_STATUS result; 1135 1136 RESET_ERRMSG; 1137 1138 argn = ZEND_NUM_ARGS(); 1139 1140 /* (1+argn) is an upper bound for the number of links this trans connects to */ 1141 ib_link = (ibase_db_link **) safe_emalloc(sizeof(ibase_db_link *),1+argn,0); 1142 1143 if (argn > 0) { 1144 long trans_argl = 0; 1145 char *tpb; 1146 ISC_TEB *teb; 1147 zval ***args = NULL; 1148 1149 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argn) == FAILURE) { 1150 efree(args); 1151 efree(ib_link); 1152 RETURN_FALSE; 1153 } 1154 1155 teb = (ISC_TEB *) safe_emalloc(sizeof(ISC_TEB),argn,0); 1156 tpb = (char *) safe_emalloc(TPB_MAX_SIZE,argn,0); 1157 1158 /* enumerate all the arguments: assume every non-resource argument 1159 specifies modifiers for the link ids that follow it */ 1160 for (i = 0; i < argn; ++i) { 1161 1162 if (Z_TYPE_PP(args[i]) == IS_RESOURCE) { 1163 1164 if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[link_cnt], ibase_db_link *, args[i], -1, LE_LINK, le_link, le_plink)) { 1165 efree(teb); 1166 efree(tpb); 1167 efree(ib_link); 1168 efree(args); 1169 RETURN_FALSE; 1170 } 1171 1172 /* copy the most recent modifier string into tbp[] */ 1173 memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE); 1174 1175 /* add a database handle to the TEB with the most recently specified set of modifiers */ 1176 teb[link_cnt].db_ptr = &ib_link[link_cnt]->handle; 1177 teb[link_cnt].tpb_len = tpb_len; 1178 teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt]; 1179 1180 ++link_cnt; 1181 1182 } else { 1183 1184 tpb_len = 0; 1185 1186 convert_to_long_ex(args[i]); 1187 trans_argl = Z_LVAL_PP(args[i]); 1188 1189 if (trans_argl != PHP_IBASE_DEFAULT) { 1190 last_tpb[tpb_len++] = isc_tpb_version3; 1191 1192 /* access mode */ 1193 if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) { 1194 last_tpb[tpb_len++] = isc_tpb_read; 1195 } else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) { 1196 last_tpb[tpb_len++] = isc_tpb_write; 1197 } 1198 1199 /* isolation level */ 1200 if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) { 1201 last_tpb[tpb_len++] = isc_tpb_read_committed; 1202 if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) { 1203 last_tpb[tpb_len++] = isc_tpb_rec_version; 1204 } else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) { 1205 last_tpb[tpb_len++] = isc_tpb_no_rec_version; 1206 } 1207 } else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) { 1208 last_tpb[tpb_len++] = isc_tpb_consistency; 1209 } else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) { 1210 last_tpb[tpb_len++] = isc_tpb_concurrency; 1211 } 1212 1213 /* lock resolution */ 1214 if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) { 1215 last_tpb[tpb_len++] = isc_tpb_nowait; 1216 } else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) { 1217 last_tpb[tpb_len++] = isc_tpb_wait; 1218 } 1219 } 1220 } 1221 } 1222 1223 if (link_cnt > 0) { 1224 result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb); 1225 } 1226 1227 efree(args); 1228 efree(tpb); 1229 efree(teb); 1230 } 1231 1232 if (link_cnt == 0) { 1233 link_cnt = 1; 1234 if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[0], ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink)) { 1235 efree(ib_link); 1236 RETURN_FALSE; 1237 } 1238 result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->handle, tpb_len, last_tpb); 1239 } 1240 1241 /* start the transaction */ 1242 if (result) { 1243 _php_ibase_error(TSRMLS_C); 1244 efree(ib_link); 1245 RETURN_FALSE; 1246 } 1247 1248 /* register the transaction in our own data structures */ 1249 ib_trans = (ibase_trans *) safe_emalloc(link_cnt-1, sizeof(ibase_db_link *), sizeof(ibase_trans)); 1250 ib_trans->handle = tr_handle; 1251 ib_trans->link_cnt = link_cnt; 1252 ib_trans->affected_rows = 0; 1253 for (i = 0; i < link_cnt; ++i) { 1254 ibase_tr_list **l; 1255 ib_trans->db_link[i] = ib_link[i]; 1256 1257 /* the first item in the connection-transaction list is reserved for the default transaction */ 1258 if (ib_link[i]->tr_list == NULL) { 1259 ib_link[i]->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); 1260 ib_link[i]->tr_list->trans = NULL; 1261 ib_link[i]->tr_list->next = NULL; 1262 } 1263 1264 /* link the transaction into the connection-transaction list */ 1265 for (l = &ib_link[i]->tr_list; *l != NULL; l = &(*l)->next); 1266 *l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); 1267 (*l)->trans = ib_trans; 1268 (*l)->next = NULL; 1269 } 1270 efree(ib_link); 1271 ZEND_REGISTER_RESOURCE(return_value, ib_trans, le_trans); 1272} 1273/* }}} */ 1274 1275int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans TSRMLS_DC) /* {{{ */ 1276{ 1277 if (ib_link == NULL) { 1278 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid database link"); 1279 return FAILURE; 1280 } 1281 1282 /* the first item in the connection-transaction list is reserved for the default transaction */ 1283 if (ib_link->tr_list == NULL) { 1284 ib_link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list)); 1285 ib_link->tr_list->trans = NULL; 1286 ib_link->tr_list->next = NULL; 1287 } 1288 1289 if (*trans == NULL) { 1290 ibase_trans *tr = ib_link->tr_list->trans; 1291 1292 if (tr == NULL) { 1293 tr = (ibase_trans *) emalloc(sizeof(ibase_trans)); 1294 tr->handle = NULL; 1295 tr->link_cnt = 1; 1296 tr->affected_rows = 0; 1297 tr->db_link[0] = ib_link; 1298 ib_link->tr_list->trans = tr; 1299 } 1300 if (tr->handle == NULL) { 1301 if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) { 1302 _php_ibase_error(TSRMLS_C); 1303 return FAILURE; 1304 } 1305 } 1306 *trans = tr; 1307 } 1308 return SUCCESS; 1309} 1310/* }}} */ 1311 1312static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{{ */ 1313{ 1314 ibase_trans *trans = NULL; 1315 int res_id = 0; 1316 ISC_STATUS result; 1317 ibase_db_link *ib_link; 1318 zval *arg = NULL; 1319 int type; 1320 1321 RESET_ERRMSG; 1322 1323 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg) == FAILURE) { 1324 return; 1325 } 1326 1327 if (ZEND_NUM_ARGS() == 0) { 1328 ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink); 1329 if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { 1330 /* this link doesn't have a default transaction */ 1331 _php_ibase_module_error("Default link has no default transaction" TSRMLS_CC); 1332 RETURN_FALSE; 1333 } 1334 trans = ib_link->tr_list->trans; 1335 } else { 1336 /* one id was passed, could be db or trans id */ 1337 if (zend_list_find(Z_RESVAL_P(arg), &type) && type == le_trans) { 1338 ZEND_FETCH_RESOURCE(trans, ibase_trans *, &arg, -1, LE_TRANS, le_trans); 1339 res_id = Z_RESVAL_P(arg); 1340 } else { 1341 ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &arg, -1, LE_LINK, le_link, le_plink); 1342 1343 if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { 1344 /* this link doesn't have a default transaction */ 1345 _php_ibase_module_error("Link has no default transaction" TSRMLS_CC); 1346 RETURN_FALSE; 1347 } 1348 trans = ib_link->tr_list->trans; 1349 } 1350 } 1351 1352 switch (commit) { 1353 default: /* == case ROLLBACK: */ 1354 result = isc_rollback_transaction(IB_STATUS, &trans->handle); 1355 break; 1356 case COMMIT: 1357 result = isc_commit_transaction(IB_STATUS, &trans->handle); 1358 break; 1359 case (ROLLBACK | RETAIN): 1360 result = isc_rollback_retaining(IB_STATUS, &trans->handle); 1361 break; 1362 case (COMMIT | RETAIN): 1363 result = isc_commit_retaining(IB_STATUS, &trans->handle); 1364 break; 1365 } 1366 1367 if (result) { 1368 _php_ibase_error(TSRMLS_C); 1369 RETURN_FALSE; 1370 } 1371 1372 /* Don't try to destroy implicitly opened transaction from list... */ 1373 if ((commit & RETAIN) == 0 && res_id != 0) { 1374 zend_list_delete(res_id); 1375 } 1376 RETURN_TRUE; 1377} 1378/* }}} */ 1379 1380/* {{{ proto bool ibase_commit( resource link_identifier ) 1381 Commit transaction */ 1382PHP_FUNCTION(ibase_commit) 1383{ 1384 _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT); 1385} 1386/* }}} */ 1387 1388/* {{{ proto bool ibase_rollback( resource link_identifier ) 1389 Rollback transaction */ 1390PHP_FUNCTION(ibase_rollback) 1391{ 1392 _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK); 1393} 1394/* }}} */ 1395 1396/* {{{ proto bool ibase_commit_ret( resource link_identifier ) 1397 Commit transaction and retain the transaction context */ 1398PHP_FUNCTION(ibase_commit_ret) 1399{ 1400 _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT | RETAIN); 1401} 1402/* }}} */ 1403 1404/* {{{ proto bool ibase_rollback_ret( resource link_identifier ) 1405 Rollback transaction and retain the transaction context */ 1406PHP_FUNCTION(ibase_rollback_ret) 1407{ 1408 _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK | RETAIN); 1409} 1410/* }}} */ 1411 1412/* {{{ proto int ibase_gen_id(string generator [, int increment [, resource link_identifier ]]) 1413 Increments the named generator and returns its new value */ 1414PHP_FUNCTION(ibase_gen_id) 1415{ 1416 zval *link = NULL; 1417 char query[128], *generator; 1418 int gen_len; 1419 long inc = 1; 1420 ibase_db_link *ib_link; 1421 ibase_trans *trans = NULL; 1422 XSQLDA out_sqlda; 1423 ISC_INT64 result; 1424 1425 RESET_ERRMSG; 1426 1427 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &generator, &gen_len, 1428 &inc, &link)) { 1429 RETURN_FALSE; 1430 } 1431 1432 if (gen_len > 31) { 1433 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid generator name"); 1434 RETURN_FALSE; 1435 } 1436 1437 PHP_IBASE_LINK_TRANS(link, ib_link, trans); 1438 1439 snprintf(query, sizeof(query), "SELECT GEN_ID(%s,%ld) FROM rdb$database", generator, inc); 1440 1441 /* allocate a minimal descriptor area */ 1442 out_sqlda.sqln = out_sqlda.sqld = 1; 1443 out_sqlda.version = SQLDA_CURRENT_VERSION; 1444 1445 /* allocate the field for the result */ 1446 out_sqlda.sqlvar[0].sqltype = SQL_INT64; 1447 out_sqlda.sqlvar[0].sqlscale = 0; 1448 out_sqlda.sqlvar[0].sqllen = sizeof(result); 1449 out_sqlda.sqlvar[0].sqldata = (void*) &result; 1450 1451 /* execute the query */ 1452 if (isc_dsql_exec_immed2(IB_STATUS, &ib_link->handle, &trans->handle, 0, query, 1453 SQL_DIALECT_CURRENT, NULL, &out_sqlda)) { 1454 _php_ibase_error(TSRMLS_C); 1455 RETURN_FALSE; 1456 } 1457 1458 /* don't return the generator value as a string unless it doesn't fit in a long */ 1459#if SIZEOF_LONG < 8 1460 if (result < LONG_MIN || result > LONG_MAX) { 1461 char *res; 1462 int l; 1463 1464 l = spprintf(&res, 0, "%" LL_MASK "d", result); 1465 RETURN_STRINGL(res, l, 0); 1466 } 1467#endif 1468 RETURN_LONG((long)result); 1469} 1470 1471/* }}} */ 1472 1473#endif /* HAVE_IBASE */ 1474 1475/* 1476 * Local variables: 1477 * tab-width: 4 1478 * c-basic-offset: 4 1479 * End: 1480 * vim600: sw=4 ts=4 fdm=marker 1481 * vim<600: sw=4 ts=4 1482 */ 1483