Back to index

php5  5.3.10
interbase.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Jouni Ahto <jouni.ahto@exdec.fi>                            |
00016    |          Andrew Avdeev <andy@rsc.mv.ru>                              |
00017    |          Ard Biesheuvel <a.k.biesheuvel@ewi.tudelft.nl>              |
00018    +----------------------------------------------------------------------+
00019  */
00020 
00021 /* $Id: interbase.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 #define _GNU_SOURCE
00028 
00029 #include "php.h"
00030 
00031 #if HAVE_IBASE
00032 
00033 #include "php_ini.h"
00034 #include "ext/standard/php_standard.h"
00035 #include "ext/standard/md5.h"
00036 #include "php_interbase.h"
00037 #include "php_ibase_includes.h"
00038 #include "SAPI.h"
00039 
00040 #include <time.h>
00041 
00042 #define ROLLBACK            0
00043 #define COMMIT                     1
00044 #define RETAIN                     2
00045 
00046 #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; } }
00047 
00048 ZEND_DECLARE_MODULE_GLOBALS(ibase)
00049 static PHP_GINIT_FUNCTION(ibase);
00050 
00051 /* {{{ arginfo */
00052 ZEND_BEGIN_ARG_INFO(arginfo_ibase_errmsg, 0)
00053 ZEND_END_ARG_INFO()
00054 
00055 ZEND_BEGIN_ARG_INFO(arginfo_ibase_errcode, 0)
00056 ZEND_END_ARG_INFO()
00057 
00058 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_connect, 0, 0, 1)
00059        ZEND_ARG_INFO(0, database)
00060        ZEND_ARG_INFO(0, username)
00061        ZEND_ARG_INFO(0, password)
00062        ZEND_ARG_INFO(0, charset)
00063        ZEND_ARG_INFO(0, buffers)
00064        ZEND_ARG_INFO(0, dialect)
00065        ZEND_ARG_INFO(0, role)
00066 ZEND_END_ARG_INFO()
00067 
00068 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_pconnect, 0, 0, 1)
00069        ZEND_ARG_INFO(0, database)
00070        ZEND_ARG_INFO(0, username)
00071        ZEND_ARG_INFO(0, password)
00072        ZEND_ARG_INFO(0, charset)
00073        ZEND_ARG_INFO(0, buffers)
00074        ZEND_ARG_INFO(0, dialect)
00075        ZEND_ARG_INFO(0, role)
00076 ZEND_END_ARG_INFO()
00077 
00078 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_close, 0, 0, 0)
00079        ZEND_ARG_INFO(0, link_identifier)
00080 ZEND_END_ARG_INFO()
00081 
00082 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_drop_db, 0, 0, 0)
00083        ZEND_ARG_INFO(0, link_identifier)
00084 ZEND_END_ARG_INFO()
00085 
00086 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_trans, 0, 0, 0)
00087        ZEND_ARG_INFO(0, trans_args)
00088        ZEND_ARG_INFO(0, link_identifier)
00089        ZEND_ARG_INFO(0, trans_args)
00090        ZEND_ARG_INFO(0, link_identifier)
00091 ZEND_END_ARG_INFO()
00092 
00093 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit, 0, 0, 1)
00094        ZEND_ARG_INFO(0, link_identifier)
00095 ZEND_END_ARG_INFO()
00096 
00097 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback, 0, 0, 1)
00098        ZEND_ARG_INFO(0, link_identifier)
00099 ZEND_END_ARG_INFO()
00100 
00101 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit_ret, 0, 0, 1)
00102        ZEND_ARG_INFO(0, link_identifier)
00103 ZEND_END_ARG_INFO()
00104 
00105 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback_ret, 0, 0, 1)
00106        ZEND_ARG_INFO(0, link_identifier)
00107 ZEND_END_ARG_INFO()
00108 
00109 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_gen_id, 0, 0, 1)
00110        ZEND_ARG_INFO(0, generator)
00111        ZEND_ARG_INFO(0, increment)
00112        ZEND_ARG_INFO(0, link_identifier)
00113 ZEND_END_ARG_INFO()
00114 
00115 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_create, 0, 0, 0)
00116        ZEND_ARG_INFO(0, link_identifier)
00117 ZEND_END_ARG_INFO()
00118 
00119 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_open, 0, 0, 0)
00120        ZEND_ARG_INFO(0, link_identifier)
00121        ZEND_ARG_INFO(0, blob_id)
00122 ZEND_END_ARG_INFO()
00123 
00124 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_add, 0, 0, 2)
00125        ZEND_ARG_INFO(0, blob_handle)
00126        ZEND_ARG_INFO(0, data)
00127 ZEND_END_ARG_INFO()
00128 
00129 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_get, 0, 0, 2)
00130        ZEND_ARG_INFO(0, blob_handle)
00131        ZEND_ARG_INFO(0, len)
00132 ZEND_END_ARG_INFO()
00133 
00134 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_close, 0, 0, 1)
00135        ZEND_ARG_INFO(0, blob_handle)
00136 ZEND_END_ARG_INFO()
00137 
00138 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_cancel, 0, 0, 1)
00139        ZEND_ARG_INFO(0, blob_handle)
00140 ZEND_END_ARG_INFO()
00141 
00142 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_info, 0, 0, 0)
00143        ZEND_ARG_INFO(0, link_identifier)
00144        ZEND_ARG_INFO(0, blob_id)
00145 ZEND_END_ARG_INFO()
00146 
00147 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_echo, 0, 0, 0)
00148        ZEND_ARG_INFO(0, link_identifier)
00149        ZEND_ARG_INFO(0, blob_id)
00150 ZEND_END_ARG_INFO()
00151 
00152 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_import, 0, 0, 0)
00153        ZEND_ARG_INFO(0, link_identifier)
00154        ZEND_ARG_INFO(0, file)
00155 ZEND_END_ARG_INFO()
00156 
00157 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_query, 0, 0, 0)
00158        ZEND_ARG_INFO(0, link_identifier)
00159        ZEND_ARG_INFO(0, link_identifier)
00160        ZEND_ARG_INFO(0, query)
00161        ZEND_ARG_INFO(0, bind_arg)
00162        ZEND_ARG_INFO(0, bind_arg)
00163 ZEND_END_ARG_INFO()
00164 
00165 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_affected_rows, 0, 0, 0)
00166        ZEND_ARG_INFO(0, link_identifier)
00167 ZEND_END_ARG_INFO()
00168 
00169 #if abies_0
00170 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_rows, 0, 0, 1)
00171        ZEND_ARG_INFO(0, result_identifier)
00172 ZEND_END_ARG_INFO()
00173 #endif
00174 
00175 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_row, 0, 0, 1)
00176        ZEND_ARG_INFO(0, result)
00177        ZEND_ARG_INFO(0, fetch_flags)
00178 ZEND_END_ARG_INFO()
00179 
00180 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_assoc, 0, 0, 1)
00181        ZEND_ARG_INFO(0, result)
00182        ZEND_ARG_INFO(0, fetch_flags)
00183 ZEND_END_ARG_INFO()
00184 
00185 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_object, 0, 0, 1)
00186        ZEND_ARG_INFO(0, result)
00187        ZEND_ARG_INFO(0, fetch_flags)
00188 ZEND_END_ARG_INFO()
00189 
00190 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_name_result, 0, 0, 2)
00191        ZEND_ARG_INFO(0, result)
00192        ZEND_ARG_INFO(0, name)
00193 ZEND_END_ARG_INFO()
00194 
00195 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_result, 0, 0, 1)
00196        ZEND_ARG_INFO(0, result)
00197 ZEND_END_ARG_INFO()
00198 
00199 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_prepare, 0, 0, 0)
00200        ZEND_ARG_INFO(0, link_identifier)
00201        ZEND_ARG_INFO(0, query)
00202 ZEND_END_ARG_INFO()
00203 
00204 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_execute, 0, 0, 1)
00205        ZEND_ARG_INFO(0, query)
00206        ZEND_ARG_INFO(0, bind_arg)
00207        ZEND_ARG_INFO(0, bind_arg)
00208 ZEND_END_ARG_INFO()
00209 
00210 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_query, 0, 0, 1)
00211        ZEND_ARG_INFO(0, query)
00212 ZEND_END_ARG_INFO()
00213 
00214 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_fields, 0, 0, 1)
00215        ZEND_ARG_INFO(0, query_result)
00216 ZEND_END_ARG_INFO()
00217 
00218 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_field_info, 0, 0, 2)
00219        ZEND_ARG_INFO(0, query_result)
00220        ZEND_ARG_INFO(0, field_number)
00221 ZEND_END_ARG_INFO()
00222 
00223 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_params, 0, 0, 1)
00224        ZEND_ARG_INFO(0, query)
00225 ZEND_END_ARG_INFO()
00226 
00227 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_param_info, 0, 0, 2)
00228        ZEND_ARG_INFO(0, query)
00229        ZEND_ARG_INFO(0, field_number)
00230 ZEND_END_ARG_INFO()
00231 
00232 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_add_user, 0, 0, 3)
00233        ZEND_ARG_INFO(0, service_handle)
00234        ZEND_ARG_INFO(0, user_name)
00235        ZEND_ARG_INFO(0, password)
00236        ZEND_ARG_INFO(0, first_name)
00237        ZEND_ARG_INFO(0, middle_name)
00238        ZEND_ARG_INFO(0, last_name)
00239 ZEND_END_ARG_INFO()
00240 
00241 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_modify_user, 0, 0, 3)
00242        ZEND_ARG_INFO(0, service_handle)
00243        ZEND_ARG_INFO(0, user_name)
00244        ZEND_ARG_INFO(0, password)
00245        ZEND_ARG_INFO(0, first_name)
00246        ZEND_ARG_INFO(0, middle_name)
00247        ZEND_ARG_INFO(0, last_name)
00248 ZEND_END_ARG_INFO()
00249 
00250 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_delete_user, 0, 0, 3)
00251        ZEND_ARG_INFO(0, service_handle)
00252        ZEND_ARG_INFO(0, user_name)
00253        ZEND_ARG_INFO(0, password)
00254        ZEND_ARG_INFO(0, first_name)
00255        ZEND_ARG_INFO(0, middle_name)
00256        ZEND_ARG_INFO(0, last_name)
00257 ZEND_END_ARG_INFO()
00258 
00259 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_attach, 0, 0, 3)
00260        ZEND_ARG_INFO(0, host)
00261        ZEND_ARG_INFO(0, dba_username)
00262        ZEND_ARG_INFO(0, dba_password)
00263 ZEND_END_ARG_INFO()
00264 
00265 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_detach, 0, 0, 1)
00266        ZEND_ARG_INFO(0, service_handle)
00267 ZEND_END_ARG_INFO()
00268 
00269 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_backup, 0, 0, 3)
00270        ZEND_ARG_INFO(0, service_handle)
00271        ZEND_ARG_INFO(0, source_db)
00272        ZEND_ARG_INFO(0, dest_file)
00273        ZEND_ARG_INFO(0, options)
00274        ZEND_ARG_INFO(0, verbose)
00275 ZEND_END_ARG_INFO()
00276 
00277 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_restore, 0, 0, 3)
00278        ZEND_ARG_INFO(0, service_handle)
00279        ZEND_ARG_INFO(0, source_file)
00280        ZEND_ARG_INFO(0, dest_db)
00281        ZEND_ARG_INFO(0, options)
00282        ZEND_ARG_INFO(0, verbose)
00283 ZEND_END_ARG_INFO()
00284 
00285 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_maintain_db, 0, 0, 3)
00286        ZEND_ARG_INFO(0, service_handle)
00287        ZEND_ARG_INFO(0, db)
00288        ZEND_ARG_INFO(0, action)
00289        ZEND_ARG_INFO(0, argument)
00290 ZEND_END_ARG_INFO()
00291 
00292 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_db_info, 0, 0, 3)
00293        ZEND_ARG_INFO(0, service_handle)
00294        ZEND_ARG_INFO(0, db)
00295        ZEND_ARG_INFO(0, action)
00296        ZEND_ARG_INFO(0, argument)
00297 ZEND_END_ARG_INFO()
00298 
00299 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_server_info, 0, 0, 2)
00300        ZEND_ARG_INFO(0, service_handle)
00301        ZEND_ARG_INFO(0, action)
00302 ZEND_END_ARG_INFO()
00303 
00304 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_wait_event, 0, 0, 1)
00305        ZEND_ARG_INFO(0, link_identifier)
00306        ZEND_ARG_INFO(0, event)
00307        ZEND_ARG_INFO(0, event2)
00308 ZEND_END_ARG_INFO()
00309 
00310 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_set_event_handler, 0, 0, 2)
00311        ZEND_ARG_INFO(0, link_identifier)
00312        ZEND_ARG_INFO(0, handler)
00313        ZEND_ARG_INFO(0, event)
00314        ZEND_ARG_INFO(0, event2)
00315 ZEND_END_ARG_INFO()
00316 
00317 ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_event_handler, 0, 0, 1)
00318        ZEND_ARG_INFO(0, event)
00319 ZEND_END_ARG_INFO()
00320 /* }}} */
00321 
00322 /* {{{ extension definition structures */
00323 const zend_function_entry ibase_functions[] = {
00324        PHP_FE(ibase_connect,              arginfo_ibase_connect)
00325        PHP_FE(ibase_pconnect,             arginfo_ibase_pconnect)
00326        PHP_FE(ibase_close,         arginfo_ibase_close)
00327        PHP_FE(ibase_drop_db,              arginfo_ibase_drop_db)
00328        PHP_FE(ibase_query,         arginfo_ibase_query)
00329        PHP_FE(ibase_fetch_row,     arginfo_ibase_fetch_row)
00330        PHP_FE(ibase_fetch_assoc,   arginfo_ibase_fetch_assoc)
00331        PHP_FE(ibase_fetch_object,  arginfo_ibase_fetch_object)
00332        PHP_FE(ibase_free_result,   arginfo_ibase_free_result)
00333        PHP_FE(ibase_name_result,   arginfo_ibase_name_result)
00334        PHP_FE(ibase_prepare,              arginfo_ibase_prepare)
00335        PHP_FE(ibase_execute,              arginfo_ibase_execute)
00336        PHP_FE(ibase_free_query,    arginfo_ibase_free_query)
00337        PHP_FE(ibase_gen_id,               arginfo_ibase_gen_id)
00338        PHP_FE(ibase_num_fields,    arginfo_ibase_num_fields)
00339        PHP_FE(ibase_num_params,    arginfo_ibase_num_params)
00340 #if abies_0
00341        PHP_FE(ibase_num_rows,             arginfo_ibase_num_rows)
00342 #endif
00343        PHP_FE(ibase_affected_rows, arginfo_ibase_affected_rows)
00344        PHP_FE(ibase_field_info,    arginfo_ibase_field_info)
00345        PHP_FE(ibase_param_info,    arginfo_ibase_param_info)
00346 
00347        PHP_FE(ibase_trans,         arginfo_ibase_trans)
00348        PHP_FE(ibase_commit,               arginfo_ibase_commit)
00349        PHP_FE(ibase_rollback,             arginfo_ibase_rollback)
00350        PHP_FE(ibase_commit_ret,    arginfo_ibase_commit_ret)
00351        PHP_FE(ibase_rollback_ret,  arginfo_ibase_rollback_ret)
00352 
00353        PHP_FE(ibase_blob_info,     arginfo_ibase_blob_info)
00354        PHP_FE(ibase_blob_create,   arginfo_ibase_blob_create)
00355        PHP_FE(ibase_blob_add,             arginfo_ibase_blob_add)
00356        PHP_FE(ibase_blob_cancel,   arginfo_ibase_blob_cancel)
00357        PHP_FE(ibase_blob_close,    arginfo_ibase_blob_close)
00358        PHP_FE(ibase_blob_open,     arginfo_ibase_blob_open)
00359        PHP_FE(ibase_blob_get,             arginfo_ibase_blob_get)
00360        PHP_FE(ibase_blob_echo,     arginfo_ibase_blob_echo)
00361        PHP_FE(ibase_blob_import,   arginfo_ibase_blob_import)
00362        PHP_FE(ibase_errmsg,               arginfo_ibase_errmsg)
00363        PHP_FE(ibase_errcode,              arginfo_ibase_errcode)
00364 
00365        PHP_FE(ibase_add_user,             arginfo_ibase_add_user)
00366        PHP_FE(ibase_modify_user,   arginfo_ibase_modify_user)
00367        PHP_FE(ibase_delete_user,   arginfo_ibase_delete_user)
00368 
00369        PHP_FE(ibase_service_attach, arginfo_ibase_service_attach)
00370        PHP_FE(ibase_service_detach, arginfo_ibase_service_detach)
00371        PHP_FE(ibase_backup,               arginfo_ibase_backup)
00372        PHP_FE(ibase_restore,              arginfo_ibase_restore)
00373        PHP_FE(ibase_maintain_db,   arginfo_ibase_maintain_db)
00374        PHP_FE(ibase_db_info,              arginfo_ibase_db_info)
00375        PHP_FE(ibase_server_info,   arginfo_ibase_server_info)
00376 
00377        PHP_FE(ibase_wait_event,                  arginfo_ibase_wait_event)
00378        PHP_FE(ibase_set_event_handler,    arginfo_ibase_set_event_handler)
00379        PHP_FE(ibase_free_event_handler,   arginfo_ibase_free_event_handler)
00380 
00381        
00388        PHP_FALIAS(fbird_connect,          ibase_connect,              arginfo_ibase_connect)
00389        PHP_FALIAS(fbird_pconnect,         ibase_pconnect,      arginfo_ibase_pconnect)
00390        PHP_FALIAS(fbird_close,                   ibase_close,         arginfo_ibase_close)
00391        PHP_FALIAS(fbird_drop_db,          ibase_drop_db,              arginfo_ibase_drop_db)
00392        PHP_FALIAS(fbird_query,                   ibase_query,         arginfo_ibase_query)
00393        PHP_FALIAS(fbird_fetch_row,        ibase_fetch_row,     arginfo_ibase_fetch_row)
00394        PHP_FALIAS(fbird_fetch_assoc,      ibase_fetch_assoc,   arginfo_ibase_fetch_assoc)
00395        PHP_FALIAS(fbird_fetch_object,     ibase_fetch_object, arginfo_ibase_fetch_object)
00396        PHP_FALIAS(fbird_free_result,      ibase_free_result,   arginfo_ibase_free_result)
00397        PHP_FALIAS(fbird_name_result,      ibase_name_result,   arginfo_ibase_name_result)
00398        PHP_FALIAS(fbird_prepare,          ibase_prepare,              arginfo_ibase_prepare)
00399        PHP_FALIAS(fbird_execute,          ibase_execute,              arginfo_ibase_execute)
00400        PHP_FALIAS(fbird_free_query,       ibase_free_query,    arginfo_ibase_free_query)
00401        PHP_FALIAS(fbird_gen_id,           ibase_gen_id,               arginfo_ibase_gen_id)
00402        PHP_FALIAS(fbird_num_fields,       ibase_num_fields,    arginfo_ibase_num_fields)
00403        PHP_FALIAS(fbird_num_params,       ibase_num_params,    arginfo_ibase_num_params)
00404 #if abies_0
00405        PHP_FALIAS(fbird_num_rows,         ibase_num_rows,      arginfo_ibase_num_rows)
00406 #endif
00407        PHP_FALIAS(fbird_affected_rows,    ibase_affected_rows, arginfo_ibase_affected_rows)
00408        PHP_FALIAS(fbird_field_info,       ibase_field_info,    arginfo_ibase_field_info)
00409        PHP_FALIAS(fbird_param_info,       ibase_param_info,    arginfo_ibase_param_info)
00410 
00411        PHP_FALIAS(fbird_trans,                   ibase_trans,         arginfo_ibase_trans)
00412        PHP_FALIAS(fbird_commit,           ibase_commit,               arginfo_ibase_commit)
00413        PHP_FALIAS(fbird_rollback,         ibase_rollback,      arginfo_ibase_rollback)
00414        PHP_FALIAS(fbird_commit_ret,       ibase_commit_ret,    arginfo_ibase_commit_ret)
00415        PHP_FALIAS(fbird_rollback_ret,     ibase_rollback_ret, arginfo_ibase_rollback_ret)
00416 
00417        PHP_FALIAS(fbird_blob_info,        ibase_blob_info,     arginfo_ibase_blob_info)
00418        PHP_FALIAS(fbird_blob_create,      ibase_blob_create,   arginfo_ibase_blob_create)
00419        PHP_FALIAS(fbird_blob_add,         ibase_blob_add,      arginfo_ibase_blob_add)
00420        PHP_FALIAS(fbird_blob_cancel,      ibase_blob_cancel,   arginfo_ibase_blob_cancel)
00421        PHP_FALIAS(fbird_blob_close,       ibase_blob_close,    arginfo_ibase_blob_close)
00422        PHP_FALIAS(fbird_blob_open,        ibase_blob_open,     arginfo_ibase_blob_open)
00423        PHP_FALIAS(fbird_blob_get,         ibase_blob_get,      arginfo_ibase_blob_get)
00424        PHP_FALIAS(fbird_blob_echo,        ibase_blob_echo,     arginfo_ibase_blob_echo)
00425        PHP_FALIAS(fbird_blob_import,      ibase_blob_import,   arginfo_ibase_blob_import)
00426        PHP_FALIAS(fbird_errmsg,           ibase_errmsg,               arginfo_ibase_errmsg)
00427        PHP_FALIAS(fbird_errcode,          ibase_errcode,              arginfo_ibase_errcode)
00428 
00429        PHP_FALIAS(fbird_add_user,         ibase_add_user,      arginfo_ibase_add_user)
00430        PHP_FALIAS(fbird_modify_user,      ibase_modify_user,   arginfo_ibase_modify_user)
00431        PHP_FALIAS(fbird_delete_user,      ibase_delete_user,   arginfo_ibase_delete_user)
00432 
00433        PHP_FALIAS(fbird_service_attach,   ibase_service_attach, arginfo_ibase_service_attach)
00434        PHP_FALIAS(fbird_service_detach,   ibase_service_detach, arginfo_ibase_service_detach)
00435        PHP_FALIAS(fbird_backup,           ibase_backup,               arginfo_ibase_backup)
00436        PHP_FALIAS(fbird_restore,          ibase_restore,              arginfo_ibase_restore)
00437        PHP_FALIAS(fbird_maintain_db,      ibase_maintain_db,   arginfo_ibase_maintain_db)
00438        PHP_FALIAS(fbird_db_info,          ibase_db_info,              arginfo_ibase_db_info)
00439        PHP_FALIAS(fbird_server_info,      ibase_server_info,   arginfo_ibase_server_info)
00440 
00441        PHP_FALIAS(fbird_wait_event,       ibase_wait_event,    arginfo_ibase_wait_event)
00442        PHP_FALIAS(fbird_set_event_handler,       ibase_set_event_handler,    arginfo_ibase_set_event_handler)
00443        PHP_FALIAS(fbird_free_event_handler,      ibase_free_event_handler, arginfo_ibase_free_event_handler)
00444        PHP_FE_END
00445 };
00446 
00447 zend_module_entry ibase_module_entry = {
00448        STANDARD_MODULE_HEADER,
00449        "interbase",
00450        ibase_functions,
00451        PHP_MINIT(ibase),
00452        PHP_MSHUTDOWN(ibase),
00453        NULL,
00454        PHP_RSHUTDOWN(ibase),
00455        PHP_MINFO(ibase),
00456        NO_VERSION_YET,
00457        PHP_MODULE_GLOBALS(ibase),
00458        PHP_GINIT(ibase),
00459        NULL,
00460        NULL,
00461        STANDARD_MODULE_PROPERTIES_EX
00462 };
00463 
00464 #ifdef COMPILE_DL_INTERBASE
00465 ZEND_GET_MODULE(ibase)
00466 #endif
00467 
00468 /* True globals, no need for thread safety */
00469 int le_link, le_plink, le_trans;
00470 
00471 /* }}} */
00472 
00473 /* error handling ---------------------------- */
00474 
00475 /* {{{ proto string ibase_errmsg(void) 
00476    Return error message */
00477 PHP_FUNCTION(ibase_errmsg)
00478 {
00479        if (zend_parse_parameters_none() == FAILURE) {
00480               return;
00481        }
00482 
00483        if (IBG(sql_code) != 0) {
00484               RETURN_STRING(IBG(errmsg), 1);
00485        }
00486 
00487        RETURN_FALSE;
00488 }
00489 /* }}} */
00490 
00491 /* {{{ proto int ibase_errcode(void) 
00492    Return error code */
00493 PHP_FUNCTION(ibase_errcode)
00494 {
00495        if (zend_parse_parameters_none() == FAILURE) {
00496               return;
00497        }
00498 
00499        if (IBG(sql_code) != 0) {
00500               RETURN_LONG(IBG(sql_code));
00501        }
00502        RETURN_FALSE;
00503 }
00504 /* }}} */
00505 
00506 /* print interbase error and save it for ibase_errmsg() */
00507 void _php_ibase_error(TSRMLS_D) /* {{{ */
00508 {
00509        char *s = IBG(errmsg);
00510        ISC_STATUS *statusp = IB_STATUS;
00511 
00512        IBG(sql_code) = isc_sqlcode(IB_STATUS);
00513        
00514        while ((s - IBG(errmsg)) < MAX_ERRMSG - (IBASE_MSGSIZE + 2) && isc_interprete(s, &statusp)) {
00515               strcat(IBG(errmsg), " ");
00516               s = IBG(errmsg) + strlen(IBG(errmsg));
00517        }
00518 
00519        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg));
00520 }
00521 /* }}} */
00522 
00523 /* print php interbase module error and save it for ibase_errmsg() */
00524 void _php_ibase_module_error(char *msg TSRMLS_DC, ...) /* {{{ */
00525 {
00526        va_list ap;
00527 
00528 #ifdef ZTS
00529        va_start(ap, TSRMLS_C);
00530 #else
00531        va_start(ap, msg);
00532 #endif
00533 
00534        /* vsnprintf NUL terminates the buf and writes at most n-1 chars+NUL */
00535        vsnprintf(IBG(errmsg), MAX_ERRMSG, msg, ap);
00536        va_end(ap);
00537 
00538        IBG(sql_code) = -999; /* no SQL error */
00539 
00540        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg));
00541 }
00542 /* }}} */
00543 
00544 /* {{{ internal macros, functions and structures */
00545 typedef struct {
00546        isc_db_handle *db_ptr;
00547        long tpb_len;
00548        char *tpb_ptr;
00549 } ISC_TEB;
00550 
00551 /* }}} */
00552 
00553 /* Fill ib_link and trans with the correct database link and transaction. */
00554 void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */
00555        zval **link_id, ibase_db_link **ib_link, ibase_trans **trans)
00556 {
00557        int type;
00558 
00559        IBDEBUG("Transaction or database link?");
00560        if (zend_list_find(Z_LVAL_PP(link_id), &type)) {
00561               if (type == le_trans) {
00562                      /* Transaction resource: make sure it refers to one link only, then 
00563                         fetch it; database link is stored in ib_trans->db_link[]. */
00564                      IBDEBUG("Type is le_trans");
00565                      ZEND_FETCH_RESOURCE(*trans, ibase_trans *, link_id, -1, LE_TRANS, le_trans);
00566                      if ((*trans)->link_cnt > 1) {
00567                             _php_ibase_module_error("Link id is ambiguous: transaction spans multiple connections."
00568                                    TSRMLS_CC);
00569                             return;
00570                      }                           
00571                      *ib_link = (*trans)->db_link[0];
00572                      return;
00573               }
00574        } 
00575        IBDEBUG("Type is le_[p]link or id not found");
00576        /* Database link resource, use default transaction. */
00577        *trans = NULL;
00578        ZEND_FETCH_RESOURCE2(*ib_link, ibase_db_link *, link_id, -1, LE_LINK, le_link, le_plink);
00579 }
00580 /* }}} */     
00581 
00582 /* destructors ---------------------- */
00583 
00584 static void _php_ibase_commit_link(ibase_db_link *link TSRMLS_DC) /* {{{ */
00585 {
00586        unsigned short i = 0, j;
00587        ibase_tr_list *l;
00588        ibase_event *e;
00589        IBDEBUG("Checking transactions to close...");
00590 
00591        for (l = link->tr_list; l != NULL; ++i) {
00592               ibase_tr_list *p = l;
00593               if (p->trans != NULL) {
00594                      if (i == 0) {
00595                             if (p->trans->handle != NULL) {
00596                                    IBDEBUG("Committing default transaction...");
00597                                    if (isc_commit_transaction(IB_STATUS, &p->trans->handle)) {
00598                                           _php_ibase_error(TSRMLS_C);
00599                                    }
00600                             }
00601                             efree(p->trans); /* default transaction is not a registered resource: clean up */
00602                      } else {
00603                             if (p->trans->handle != NULL) { 
00604                                    /* non-default trans might have been rolled back by other call of this dtor */
00605                                    IBDEBUG("Rolling back other transactions...");
00606                                    if (isc_rollback_transaction(IB_STATUS, &p->trans->handle)) {
00607                                           _php_ibase_error(TSRMLS_C);
00608                                    }
00609                             }
00610                             /* set this link pointer to NULL in the transaction */
00611                             for (j = 0; j < p->trans->link_cnt; ++j) {
00612                                    if (p->trans->db_link[j] == link) {
00613                                           p->trans->db_link[j] = NULL;
00614                                           break;
00615                                    }
00616                             }
00617                      }
00618               }
00619               l = l->next;
00620               efree(p);
00621        }
00622        link->tr_list = NULL;
00623        
00624        for (e = link->event_head; e; e = e->event_next) {
00625               _php_ibase_free_event(e TSRMLS_CC);
00626               e->link = NULL;
00627        }
00628 }
00629 
00630 /* }}} */
00631 
00632 static void php_ibase_commit_link_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
00633 {
00634        ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
00635 
00636        _php_ibase_commit_link(link TSRMLS_CC);
00637 }
00638 /* }}} */
00639 
00640 static void _php_ibase_close_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
00641 {
00642        ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
00643 
00644        _php_ibase_commit_link(link TSRMLS_CC);
00645        if (link->handle != NULL) {
00646               IBDEBUG("Closing normal link...");
00647               isc_detach_database(IB_STATUS, &link->handle);
00648        }
00649        IBG(num_links)--;
00650        efree(link);
00651 }
00652 /* }}} */
00653 
00654 static void _php_ibase_close_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
00655 {
00656        ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
00657 
00658        _php_ibase_commit_link(link TSRMLS_CC);
00659        IBDEBUG("Closing permanent link...");
00660        if (link->handle != NULL) {
00661               isc_detach_database(IB_STATUS, &link->handle);
00662        }
00663        IBG(num_persistent)--;
00664        IBG(num_links)--;
00665        free(link);
00666 }
00667 /* }}} */
00668 
00669 static void _php_ibase_free_trans(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
00670 {
00671        ibase_trans *trans = (ibase_trans *)rsrc->ptr;
00672        unsigned short i;
00673        
00674        IBDEBUG("Cleaning up transaction resource...");
00675        if (trans->handle != NULL) {
00676               IBDEBUG("Rolling back unhandled transaction...");
00677               if (isc_rollback_transaction(IB_STATUS, &trans->handle)) {
00678                      _php_ibase_error(TSRMLS_C);
00679               }
00680        }
00681 
00682        /* now remove this transaction from all the connection-transaction lists */
00683        for (i = 0; i < trans->link_cnt; ++i) {
00684               if (trans->db_link[i] != NULL) {
00685                      ibase_tr_list **l;
00686                      for (l = &trans->db_link[i]->tr_list; *l != NULL; l = &(*l)->next) {
00687                             if ( (*l)->trans == trans) {
00688                                    ibase_tr_list *p = *l;
00689                                    *l = p->next;
00690                                    efree(p);
00691                                    break;
00692                             }
00693                      }
00694               }
00695        }
00696        efree(trans);
00697 }
00698 /* }}} */
00699 
00700 /* TODO this function should be part of either Zend or PHP API */
00701 static PHP_INI_DISP(php_ibase_password_displayer_cb)
00702 {
00703        TSRMLS_FETCH();
00704 
00705        if ((type == PHP_INI_DISPLAY_ORIG && ini_entry->orig_value) 
00706                      || (type == PHP_INI_DISPLAY_ACTIVE && ini_entry->value)) {
00707               PUTS("********");
00708        } else if (!sapi_module.phpinfo_as_text) {
00709               PUTS("<i>no value</i>");
00710        } else {
00711               PUTS("no value");
00712        }
00713 }
00714 
00715 /* {{{ startup, shutdown and info functions */
00716 PHP_INI_BEGIN()
00717        PHP_INI_ENTRY_EX("ibase.allow_persistent", "1", PHP_INI_SYSTEM, NULL, zend_ini_boolean_displayer_cb)
00718        PHP_INI_ENTRY_EX("ibase.max_persistent", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers)
00719        PHP_INI_ENTRY_EX("ibase.max_links", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers)
00720        PHP_INI_ENTRY("ibase.default_db", NULL, PHP_INI_SYSTEM, NULL)
00721        PHP_INI_ENTRY("ibase.default_user", NULL, PHP_INI_ALL, NULL)
00722        PHP_INI_ENTRY_EX("ibase.default_password", NULL, PHP_INI_ALL, NULL, php_ibase_password_displayer_cb)
00723        PHP_INI_ENTRY("ibase.default_charset", NULL, PHP_INI_ALL, NULL)
00724        PHP_INI_ENTRY("ibase.timestampformat", IB_DEF_DATE_FMT " " IB_DEF_TIME_FMT, PHP_INI_ALL, NULL)
00725        PHP_INI_ENTRY("ibase.dateformat", IB_DEF_DATE_FMT, PHP_INI_ALL, NULL)
00726        PHP_INI_ENTRY("ibase.timeformat", IB_DEF_TIME_FMT, PHP_INI_ALL, NULL)
00727 PHP_INI_END()
00728 
00729 static PHP_GINIT_FUNCTION(ibase)
00730 {
00731        ibase_globals->num_persistent = ibase_globals->num_links = 0;
00732        ibase_globals->sql_code = *ibase_globals->errmsg = 0;
00733        ibase_globals->default_link = -1;
00734 }
00735 
00736 PHP_MINIT_FUNCTION(ibase)
00737 {
00738        REGISTER_INI_ENTRIES();
00739 
00740        le_link = zend_register_list_destructors_ex(_php_ibase_close_link, NULL, LE_LINK, module_number);
00741        le_plink = zend_register_list_destructors_ex(php_ibase_commit_link_rsrc, _php_ibase_close_plink, LE_PLINK, module_number);
00742        le_trans = zend_register_list_destructors_ex(_php_ibase_free_trans, NULL, LE_TRANS, module_number);
00743 
00744        REGISTER_LONG_CONSTANT("IBASE_DEFAULT", PHP_IBASE_DEFAULT, CONST_PERSISTENT);
00745        REGISTER_LONG_CONSTANT("IBASE_CREATE", PHP_IBASE_CREATE, CONST_PERSISTENT);
00746        REGISTER_LONG_CONSTANT("IBASE_TEXT", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); /* deprecated, for BC only */
00747        REGISTER_LONG_CONSTANT("IBASE_FETCH_BLOBS", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT);
00748        REGISTER_LONG_CONSTANT("IBASE_FETCH_ARRAYS", PHP_IBASE_FETCH_ARRAYS, CONST_PERSISTENT);
00749        REGISTER_LONG_CONSTANT("IBASE_UNIXTIME", PHP_IBASE_UNIXTIME, CONST_PERSISTENT);
00750 
00751        /* transactions */
00752        REGISTER_LONG_CONSTANT("IBASE_WRITE", PHP_IBASE_WRITE, CONST_PERSISTENT);
00753        REGISTER_LONG_CONSTANT("IBASE_READ", PHP_IBASE_READ, CONST_PERSISTENT);
00754        REGISTER_LONG_CONSTANT("IBASE_COMMITTED", PHP_IBASE_COMMITTED, CONST_PERSISTENT);
00755        REGISTER_LONG_CONSTANT("IBASE_CONSISTENCY", PHP_IBASE_CONSISTENCY, CONST_PERSISTENT);
00756        REGISTER_LONG_CONSTANT("IBASE_CONCURRENCY", PHP_IBASE_CONCURRENCY, CONST_PERSISTENT);
00757        REGISTER_LONG_CONSTANT("IBASE_REC_VERSION", PHP_IBASE_REC_VERSION, CONST_PERSISTENT);
00758        REGISTER_LONG_CONSTANT("IBASE_REC_NO_VERSION", PHP_IBASE_REC_NO_VERSION, CONST_PERSISTENT);
00759        REGISTER_LONG_CONSTANT("IBASE_NOWAIT", PHP_IBASE_NOWAIT, CONST_PERSISTENT);
00760        REGISTER_LONG_CONSTANT("IBASE_WAIT", PHP_IBASE_WAIT, CONST_PERSISTENT);
00761 
00762        php_ibase_query_minit(INIT_FUNC_ARGS_PASSTHRU);
00763        php_ibase_blobs_minit(INIT_FUNC_ARGS_PASSTHRU);
00764        php_ibase_events_minit(INIT_FUNC_ARGS_PASSTHRU);
00765        php_ibase_service_minit(INIT_FUNC_ARGS_PASSTHRU);
00766        
00767        return SUCCESS;          
00768 }                            
00769                              
00770 PHP_MSHUTDOWN_FUNCTION(ibase)
00771 {
00772 #ifndef PHP_WIN32
00773 
00785        zend_module_entry *ibase_entry;
00786        if (SUCCESS == zend_hash_find(&module_registry, ibase_module_entry.name,
00787                      strlen(ibase_module_entry.name) +1, (void*) &ibase_entry)) {
00788               ibase_entry->handle = NULL;
00789        }
00790 #endif
00791        UNREGISTER_INI_ENTRIES();
00792        return SUCCESS;
00793 }
00794 
00795 PHP_RSHUTDOWN_FUNCTION(ibase)
00796 {
00797        IBG(num_links) = IBG(num_persistent);
00798        IBG(default_link)= -1;
00799 
00800        RESET_ERRMSG;
00801 
00802        return SUCCESS;
00803 } 
00804  
00805 PHP_MINFO_FUNCTION(ibase)
00806 {
00807        char tmp[64], *s;
00808 
00809        php_info_print_table_start();
00810        php_info_print_table_row(2, "Firebird/InterBase Support", 
00811 #ifdef COMPILE_DL_INTERBASE
00812               "dynamic");
00813 #else
00814               "static");
00815 #endif
00816 
00817 #ifdef FB_API_VER
00818        snprintf( (s = tmp), sizeof(tmp), "Firebird API version %d", FB_API_VER);
00819 #elif (SQLDA_CURRENT_VERSION > 1)
00820        s =  "Interbase 7.0 and up";
00821 #elif !defined(DSC_null)
00822        s = "Interbase 6";
00823 #else
00824        s = "Firebird 1.0";
00825 #endif
00826        php_info_print_table_row(2, "Compile-time Client Library Version", s);
00827 
00828 #if defined(__GNUC__) || defined(PHP_WIN32)
00829        do {
00830               info_func_t info_func = NULL;
00831 #ifdef __GNUC__
00832               info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version");
00833 #else
00834               HMODULE l = GetModuleHandle("fbclient");
00835 
00836               if (!l && !(l = GetModuleHandle("gds32"))) {
00837                      break;
00838               }
00839               info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version");
00840 #endif
00841               if (info_func) {
00842                      info_func(s = tmp);
00843               } else {
00844                      s = "Firebird 1.0/Interbase 6";
00845               }
00846               php_info_print_table_row(2, "Run-time Client Library Version", s);
00847        } while (0);
00848 #endif               
00849        php_info_print_table_end();
00850 
00851        DISPLAY_INI_ENTRIES();
00852 
00853 }
00854 /* }}} */
00855 
00856 enum connect_args { DB = 0, USER = 1, PASS = 2, CSET = 3, ROLE = 4, BUF = 0, DLECT = 1, SYNC = 2 };
00857        
00858 static char const dpb_args[] = { 
00859        0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name, 0
00860 };
00861        
00862 int _php_ibase_attach_db(char **args, int *len, long *largs, isc_db_handle *db TSRMLS_DC)
00863 {
00864        short i, dpb_len, buf_len = 257-2;  /* version byte at the front, and a null at the end */
00865        char dpb_buffer[257] = { isc_dpb_version1, 0 }, *dpb;
00866 
00867        dpb = dpb_buffer + 1;
00868 
00869        for (i = 0; i < sizeof(dpb_args); ++i) {
00870               if (dpb_args[i] && args[i] && len[i] && buf_len > 0) {
00871                      dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]);
00872                      dpb += dpb_len;
00873                      buf_len -= dpb_len;
00874               }
00875        }
00876        if (largs[BUF] && buf_len > 0) {
00877               dpb_len = slprintf(dpb, buf_len, "%c\2%c%c", isc_dpb_num_buffers, 
00878                      (char)(largs[BUF] >> 8), (char)(largs[BUF] & 0xff));
00879               dpb += dpb_len;
00880               buf_len -= dpb_len;
00881        }
00882        if (largs[SYNC] && buf_len > 0) {
00883               dpb_len = slprintf(dpb, buf_len, "%c\1%c", isc_dpb_force_write, largs[SYNC] == isc_spb_prp_wm_sync ? 1 : 0);
00884               dpb += dpb_len;
00885               buf_len -= dpb_len;
00886        }
00887        if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) {
00888               _php_ibase_error(TSRMLS_C);
00889               return FAILURE;
00890        }
00891        return SUCCESS;
00892 }
00893 /* }}} */
00894 
00895 static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */
00896 {
00897        char *c, hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL };
00898        int i, len[] = { 0, 0, 0, 0, 0 };
00899        long largs[] = { 0, 0, 0 };
00900        PHP_MD5_CTX hash_context;
00901        zend_rsrc_list_entry new_index_ptr, *le;
00902        isc_db_handle db_handle = NULL;
00903        ibase_db_link *ib_link;
00904 
00905        RESET_ERRMSG;
00906 
00907        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ssssllsl",
00908                      &args[DB], &len[DB], &args[USER], &len[USER], &args[PASS], &len[PASS],
00909                      &args[CSET], &len[CSET], &largs[BUF], &largs[DLECT], &args[ROLE], &len[ROLE],
00910                      &largs[SYNC])) {
00911               RETURN_FALSE;
00912        }
00913        
00914        /* restrict to the server/db in the .ini if in safe mode */
00915        if ((!len[DB] || PG(sql_safe_mode)) && (c = INI_STR("ibase.default_db"))) { 
00916               args[DB] = c;
00917               len[DB] = strlen(c);
00918        }
00919        if (!len[USER] && (c = INI_STR("ibase.default_user"))) {
00920               args[USER] = c;
00921               len[USER] = strlen(c);
00922        }
00923        if (!len[PASS] && (c = INI_STR("ibase.default_password"))) {
00924               args[PASS] = c;
00925               len[PASS] = strlen(c);
00926        }
00927        if (!len[CSET] && (c = INI_STR("ibase.default_charset"))) {
00928               args[CSET] = c;
00929               len[CSET] = strlen(c);
00930        }
00931        
00932        /* don't want usernames and passwords floating around */
00933        PHP_MD5Init(&hash_context);
00934        for (i = 0; i < sizeof(args)/sizeof(char*); ++i) {
00935               PHP_MD5Update(&hash_context,args[i],len[i]);
00936        }
00937        for (i = 0; i < sizeof(largs)/sizeof(long); ++i) {
00938               PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(long));
00939        }
00940        PHP_MD5Final(hash, &hash_context);
00941        
00942        /* try to reuse a connection */
00943        if (SUCCESS == zend_hash_find(&EG(regular_list), hash, sizeof(hash), (void *) &le)) {
00944               long xlink;
00945               int type;
00946 
00947               if (Z_TYPE_P(le) != le_index_ptr) {
00948                      RETURN_FALSE;
00949               }
00950                      
00951               xlink = (long) le->ptr;
00952               if (zend_list_find(xlink, &type) && ((!persistent && type == le_link) || type == le_plink)) {
00953                      zend_list_addref(xlink);
00954                      RETURN_RESOURCE(IBG(default_link) = xlink);
00955               } else {
00956                      zend_hash_del(&EG(regular_list), hash, sizeof(hash));
00957               }
00958        }             
00959 
00960        /* ... or a persistent one */
00961        switch (zend_hash_find(&EG(persistent_list), hash, sizeof(hash), (void *) &le)) {
00962               long l;
00963               
00964               static char info[] = { isc_info_base_level, isc_info_end };
00965               char result[8];
00966               ISC_STATUS status[20];
00967 
00968        case SUCCESS:
00969 
00970               if (Z_TYPE_P(le) != le_plink) {
00971                      RETURN_FALSE;
00972               }
00973               /* check if connection has timed out */
00974               ib_link = (ibase_db_link *) le->ptr;
00975               if (!isc_database_info(status, &ib_link->handle, sizeof(info), info, sizeof(result), result)) {
00976                      ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink);
00977                      break;
00978               }
00979               zend_hash_del(&EG(persistent_list), hash, sizeof(hash));
00980        
00981        default:
00982 
00983               /* no link found, so we have to open one */
00984        
00985               if ((l = INI_INT("ibase.max_links")) != -1 && IBG(num_links) >= l) {
00986                      _php_ibase_module_error("Too many open links (%ld)" TSRMLS_CC, IBG(num_links));
00987                      RETURN_FALSE;
00988               }
00989        
00990               /* create the ib_link */
00991               if (FAILURE == _php_ibase_attach_db(args, len, largs, &db_handle TSRMLS_CC)) {
00992                      RETURN_FALSE;
00993               }
00994        
00995               /* use non-persistent if allowed number of persistent links is exceeded */
00996               if (!persistent || ((l = INI_INT("ibase.max_persistent") != -1) && IBG(num_persistent) >= l)) {
00997                      ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link));
00998                      ZEND_REGISTER_RESOURCE(return_value, ib_link, le_link);
00999               } else {
01000                      zend_rsrc_list_entry new_le;
01001 
01002                      ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link));
01003                      if (!ib_link) {
01004                             RETURN_FALSE;
01005                      }
01006 
01007                      /* hash it up */
01008                      Z_TYPE(new_le) = le_plink;
01009                      new_le.ptr = ib_link;
01010                      if (FAILURE == zend_hash_update(&EG(persistent_list), hash, sizeof(hash),
01011                                    (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)) {
01012                             free(ib_link);
01013                             RETURN_FALSE;
01014                      }
01015                      ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink);
01016                      ++IBG(num_persistent);
01017               }
01018               ib_link->handle = db_handle;
01019               ib_link->dialect = largs[DLECT] ? (unsigned short)largs[DLECT] : SQL_DIALECT_CURRENT;
01020               ib_link->tr_list = NULL;
01021               ib_link->event_head = NULL;
01022        
01023               ++IBG(num_links);
01024        }
01025 
01026        /* add it to the hash */
01027        new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
01028        Z_TYPE(new_index_ptr) = le_index_ptr;
01029        if (FAILURE == zend_hash_update(&EG(regular_list), hash, sizeof(hash),
01030                      (void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)) {
01031               RETURN_FALSE;
01032        }
01033        zend_list_addref(IBG(default_link) = Z_LVAL_P(return_value));
01034 }
01035 /* }}} */
01036 
01037 /* {{{ proto resource ibase_connect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])
01038    Open a connection to an InterBase database */
01039 PHP_FUNCTION(ibase_connect)
01040 {
01041        _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
01042 }
01043 /* }}} */
01044 
01045 /* {{{ proto resource ibase_pconnect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])
01046    Open a persistent connection to an InterBase database */
01047 PHP_FUNCTION(ibase_pconnect)
01048 {
01049        _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INI_INT("ibase.allow_persistent"));
01050 }
01051 /* }}} */
01052 
01053 /* {{{ proto bool ibase_close([resource link_identifier])
01054    Close an InterBase connection */
01055 PHP_FUNCTION(ibase_close)
01056 {
01057        zval *link_arg = NULL;
01058        ibase_db_link *ib_link;
01059        int link_id;
01060 
01061        RESET_ERRMSG;
01062        
01063        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) {
01064               return;
01065        }
01066        
01067        if (ZEND_NUM_ARGS() == 0) {
01068               link_id = IBG(default_link);
01069               CHECK_LINK(link_id);
01070               IBG(default_link) = -1;
01071        } else {
01072               link_id = Z_RESVAL_P(link_arg);
01073        }
01074 
01075        ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink);
01076        zend_list_delete(link_id);
01077        RETURN_TRUE;
01078 }
01079 /* }}} */
01080 
01081 /* {{{ proto bool ibase_drop_db([resource link_identifier])
01082    Drop an InterBase database */
01083 PHP_FUNCTION(ibase_drop_db)
01084 {
01085        zval *link_arg = NULL;
01086        ibase_db_link *ib_link;
01087        ibase_tr_list *l;
01088        int link_id;
01089 
01090        RESET_ERRMSG;
01091        
01092        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) {
01093               return;
01094        }
01095        
01096        if (ZEND_NUM_ARGS() == 0) {
01097               link_id = IBG(default_link);
01098               CHECK_LINK(link_id);
01099               IBG(default_link) = -1;
01100        } else {
01101               link_id = Z_RESVAL_P(link_arg);
01102        }
01103        
01104        ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink);
01105 
01106        if (isc_drop_database(IB_STATUS, &ib_link->handle)) {
01107               _php_ibase_error(TSRMLS_C);
01108               RETURN_FALSE;
01109        }
01110 
01111        /* isc_drop_database() doesn't invalidate the transaction handles */
01112        for (l = ib_link->tr_list; l != NULL; l = l->next) {
01113               if (l->trans != NULL) l->trans->handle = NULL;
01114        }
01115 
01116        zend_list_delete(link_id);
01117        RETURN_TRUE;
01118 }
01119 /* }}} */
01120 
01121 /* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]])
01122    Start a transaction over one or several databases */
01123 
01124 #define TPB_MAX_SIZE (8*sizeof(char))
01125 
01126 PHP_FUNCTION(ibase_trans)
01127 {
01128        unsigned short i, argn, link_cnt = 0, tpb_len = 0;
01129        char last_tpb[TPB_MAX_SIZE];
01130        ibase_db_link **ib_link = NULL;
01131        ibase_trans *ib_trans;
01132        isc_tr_handle tr_handle = NULL;
01133        ISC_STATUS result;
01134        
01135        RESET_ERRMSG;
01136 
01137        argn = ZEND_NUM_ARGS();
01138 
01139        /* (1+argn) is an upper bound for the number of links this trans connects to */
01140        ib_link = (ibase_db_link **) safe_emalloc(sizeof(ibase_db_link *),1+argn,0);
01141        
01142        if (argn > 0) {
01143               long trans_argl = 0;
01144               char *tpb;
01145               ISC_TEB *teb;
01146               zval ***args = NULL;
01147 
01148               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argn) == FAILURE) {
01149                      efree(args);
01150                      efree(ib_link);
01151                      RETURN_FALSE;
01152               }
01153 
01154               teb = (ISC_TEB *) safe_emalloc(sizeof(ISC_TEB),argn,0);
01155               tpb = (char *) safe_emalloc(TPB_MAX_SIZE,argn,0);
01156 
01157               /* enumerate all the arguments: assume every non-resource argument 
01158                  specifies modifiers for the link ids that follow it */
01159               for (i = 0; i < argn; ++i) {
01160                      
01161                      if (Z_TYPE_PP(args[i]) == IS_RESOURCE) {
01162                             
01163                             if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[link_cnt], ibase_db_link *, args[i], -1, LE_LINK, le_link, le_plink)) {
01164                                    efree(teb);
01165                                    efree(tpb);
01166                                    efree(ib_link);
01167                                    efree(args);
01168                                    RETURN_FALSE;
01169                             }
01170        
01171                             /* copy the most recent modifier string into tbp[] */
01172                             memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE);
01173 
01174                             /* add a database handle to the TEB with the most recently specified set of modifiers */
01175                             teb[link_cnt].db_ptr = &ib_link[link_cnt]->handle;
01176                             teb[link_cnt].tpb_len = tpb_len;
01177                             teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt];
01178                             
01179                             ++link_cnt;
01180                             
01181                      } else {
01182                             
01183                             tpb_len = 0;
01184 
01185                             convert_to_long_ex(args[i]);
01186                             trans_argl = Z_LVAL_PP(args[i]);
01187 
01188                             if (trans_argl != PHP_IBASE_DEFAULT) {
01189                                    last_tpb[tpb_len++] = isc_tpb_version3;
01190 
01191                                    /* access mode */
01192                                    if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) {
01193                                           last_tpb[tpb_len++] = isc_tpb_read;
01194                                    } else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) {
01195                                           last_tpb[tpb_len++] = isc_tpb_write;
01196                                    }
01197 
01198                                    /* isolation level */
01199                                    if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) {
01200                                           last_tpb[tpb_len++] = isc_tpb_read_committed;
01201                                           if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) {
01202                                                  last_tpb[tpb_len++] = isc_tpb_rec_version;
01203                                           } else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) {
01204                                                  last_tpb[tpb_len++] = isc_tpb_no_rec_version; 
01205                                           }      
01206                                    } else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) {
01207                                           last_tpb[tpb_len++] = isc_tpb_consistency;
01208                                    } else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) {
01209                                           last_tpb[tpb_len++] = isc_tpb_concurrency;
01210                                    }
01211                                    
01212                                    /* lock resolution */
01213                                    if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) {
01214                                           last_tpb[tpb_len++] = isc_tpb_nowait;
01215                                    } else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) {
01216                                           last_tpb[tpb_len++] = isc_tpb_wait;
01217                                    }
01218                             }
01219                      }
01220               }      
01221                                    
01222               if (link_cnt > 0) {
01223                      result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb);
01224               }
01225 
01226               efree(args);
01227               efree(tpb);
01228               efree(teb);
01229        }
01230 
01231        if (link_cnt == 0) {
01232               link_cnt = 1;
01233               if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[0], ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink)) {
01234                      efree(ib_link);
01235                      RETURN_FALSE;
01236               }
01237               result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->handle, tpb_len, last_tpb);
01238        }
01239        
01240        /* start the transaction */
01241        if (result) {
01242               _php_ibase_error(TSRMLS_C);
01243               efree(ib_link);
01244               RETURN_FALSE;
01245        }
01246 
01247        /* register the transaction in our own data structures */
01248        ib_trans = (ibase_trans *) safe_emalloc(link_cnt-1, sizeof(ibase_db_link *), sizeof(ibase_trans));
01249        ib_trans->handle = tr_handle;
01250        ib_trans->link_cnt = link_cnt;
01251        ib_trans->affected_rows = 0;
01252        for (i = 0; i < link_cnt; ++i) {
01253               ibase_tr_list **l;
01254               ib_trans->db_link[i] = ib_link[i];
01255               
01256               /* the first item in the connection-transaction list is reserved for the default transaction */
01257               if (ib_link[i]->tr_list == NULL) {
01258                      ib_link[i]->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
01259                      ib_link[i]->tr_list->trans = NULL;
01260                      ib_link[i]->tr_list->next = NULL;
01261               }
01262 
01263               /* link the transaction into the connection-transaction list */
01264               for (l = &ib_link[i]->tr_list; *l != NULL; l = &(*l)->next);
01265               *l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
01266               (*l)->trans = ib_trans;
01267               (*l)->next = NULL;
01268        }
01269        efree(ib_link);
01270        ZEND_REGISTER_RESOURCE(return_value, ib_trans, le_trans);
01271 }
01272 /* }}} */
01273 
01274 int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans TSRMLS_DC) /* {{{ */
01275 {
01276        if (ib_link == NULL) {
01277               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid database link");
01278               return FAILURE;
01279        }
01280 
01281        /* the first item in the connection-transaction list is reserved for the default transaction */
01282        if (ib_link->tr_list == NULL) {
01283               ib_link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
01284               ib_link->tr_list->trans = NULL;
01285               ib_link->tr_list->next = NULL;
01286        }
01287 
01288        if (*trans == NULL) {
01289               ibase_trans *tr = ib_link->tr_list->trans;
01290 
01291               if (tr == NULL) {
01292                      tr = (ibase_trans *) emalloc(sizeof(ibase_trans));
01293                      tr->handle = NULL;
01294                      tr->link_cnt = 1;
01295                      tr->affected_rows = 0;
01296                      tr->db_link[0] = ib_link;
01297                      ib_link->tr_list->trans = tr;
01298               }
01299               if (tr->handle == NULL) {
01300                      if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) {
01301                             _php_ibase_error(TSRMLS_C);
01302                             return FAILURE;
01303                      }
01304               }
01305               *trans = tr;
01306        }
01307        return SUCCESS;
01308 }
01309 /* }}} */
01310 
01311 static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{{ */
01312 {
01313        ibase_trans *trans = NULL;
01314        int res_id = 0;
01315        ISC_STATUS result;
01316        ibase_db_link *ib_link;
01317        zval *arg = NULL;
01318        int type;
01319 
01320        RESET_ERRMSG;
01321        
01322        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg) == FAILURE) {
01323               return;
01324        }
01325 
01326        if (ZEND_NUM_ARGS() == 0) {
01327               ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink);
01328               if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
01329                      /* this link doesn't have a default transaction */
01330                      _php_ibase_module_error("Default link has no default transaction" TSRMLS_CC);
01331                      RETURN_FALSE;
01332               }
01333               trans = ib_link->tr_list->trans;
01334        } else {
01335               /* one id was passed, could be db or trans id */
01336               if (zend_list_find(Z_RESVAL_P(arg), &type) && type == le_trans) {
01337                      ZEND_FETCH_RESOURCE(trans, ibase_trans *, &arg, -1, LE_TRANS, le_trans);
01338                      res_id = Z_RESVAL_P(arg);
01339               } else {
01340                      ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &arg, -1, LE_LINK, le_link, le_plink);
01341 
01342                      if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
01343                             /* this link doesn't have a default transaction */
01344                             _php_ibase_module_error("Link has no default transaction" TSRMLS_CC);
01345                             RETURN_FALSE;
01346                      }
01347                      trans = ib_link->tr_list->trans;
01348               }
01349        }
01350 
01351        switch (commit) {
01352               default: /* == case ROLLBACK: */
01353                      result = isc_rollback_transaction(IB_STATUS, &trans->handle);
01354                      break;
01355               case COMMIT:
01356                      result = isc_commit_transaction(IB_STATUS, &trans->handle);
01357                      break;
01358               case (ROLLBACK | RETAIN):
01359                      result = isc_rollback_retaining(IB_STATUS, &trans->handle);
01360                      break;
01361               case (COMMIT | RETAIN):
01362                      result = isc_commit_retaining(IB_STATUS, &trans->handle);
01363                      break;
01364        }
01365        
01366        if (result) {
01367               _php_ibase_error(TSRMLS_C);
01368               RETURN_FALSE;
01369        }
01370 
01371        /* Don't try to destroy implicitly opened transaction from list... */
01372        if ((commit & RETAIN) == 0 && res_id != 0) {
01373               zend_list_delete(res_id);
01374        }
01375        RETURN_TRUE;
01376 }
01377 /* }}} */
01378 
01379 /* {{{ proto bool ibase_commit( resource link_identifier )
01380    Commit transaction */
01381 PHP_FUNCTION(ibase_commit)
01382 {
01383        _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT);
01384 }
01385 /* }}} */
01386 
01387 /* {{{ proto bool ibase_rollback( resource link_identifier )
01388    Rollback transaction */
01389 PHP_FUNCTION(ibase_rollback)
01390 {
01391        _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK);
01392 }
01393 /* }}} */
01394 
01395 /* {{{ proto bool ibase_commit_ret( resource link_identifier )
01396    Commit transaction and retain the transaction context */
01397 PHP_FUNCTION(ibase_commit_ret)
01398 {
01399        _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT | RETAIN);
01400 }
01401 /* }}} */
01402 
01403 /* {{{ proto bool ibase_rollback_ret( resource link_identifier )
01404    Rollback transaction and retain the transaction context */
01405 PHP_FUNCTION(ibase_rollback_ret)
01406 {
01407        _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK | RETAIN);
01408 }
01409 /* }}} */
01410 
01411 /* {{{ proto int ibase_gen_id(string generator [, int increment [, resource link_identifier ]])
01412    Increments the named generator and returns its new value */
01413 PHP_FUNCTION(ibase_gen_id)
01414 {
01415        zval *link = NULL;
01416        char query[128], *generator;
01417        int gen_len;
01418        long inc = 1;
01419        ibase_db_link *ib_link;
01420        ibase_trans *trans = NULL;
01421        XSQLDA out_sqlda;
01422        ISC_INT64 result;
01423 
01424        RESET_ERRMSG;
01425 
01426        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &generator, &gen_len,
01427                      &inc, &link)) {
01428               RETURN_FALSE;
01429        }
01430        
01431        if (gen_len > 31) {
01432               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid generator name");
01433               RETURN_FALSE;
01434        }
01435 
01436        PHP_IBASE_LINK_TRANS(link, ib_link, trans);
01437        
01438        snprintf(query, sizeof(query), "SELECT GEN_ID(%s,%ld) FROM rdb$database", generator, inc);
01439 
01440        /* allocate a minimal descriptor area */
01441        out_sqlda.sqln = out_sqlda.sqld = 1;
01442        out_sqlda.version = SQLDA_CURRENT_VERSION;
01443        
01444        /* allocate the field for the result */
01445        out_sqlda.sqlvar[0].sqltype = SQL_INT64;
01446        out_sqlda.sqlvar[0].sqlscale = 0;
01447        out_sqlda.sqlvar[0].sqllen = sizeof(result);
01448        out_sqlda.sqlvar[0].sqldata = (void*) &result;
01449 
01450        /* execute the query */
01451        if (isc_dsql_exec_immed2(IB_STATUS, &ib_link->handle, &trans->handle, 0, query,
01452                      SQL_DIALECT_CURRENT, NULL, &out_sqlda)) {
01453               _php_ibase_error(TSRMLS_C);
01454               RETURN_FALSE;
01455        }
01456 
01457        /* don't return the generator value as a string unless it doesn't fit in a long */
01458 #if SIZEOF_LONG < 8
01459        if (result < LONG_MIN || result > LONG_MAX) {
01460               char *res;
01461               int l;
01462 
01463               l = spprintf(&res, 0, "%" LL_MASK "d", result);
01464               RETURN_STRINGL(res, l, 0);
01465        }
01466 #endif
01467        RETURN_LONG((long)result);
01468 }
01469 
01470 /* }}} */
01471     
01472 #endif /* HAVE_IBASE */
01473 
01474 /*
01475  * Local variables:
01476  * tab-width: 4
01477  * c-basic-offset: 4
01478  * End:
01479  * vim600: sw=4 ts=4 fdm=marker
01480  * vim<600: sw=4 ts=4
01481  */