Annotation of embedaddon/php/ext/oci8/oci8.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 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: Stig Sæther Bakken <ssb@php.net>                            |
                     16:    |          Thies C. Arntzen <thies@thieso.net>                         |
                     17:    |          Maxim Maletsky <maxim@maxim.cx>                             |
                     18:    |                                                                      |
                     19:    | Collection support by Andy Sautins <asautins@veripost.net>           |
                     20:    | Temporary LOB support by David Benson <dbenson@mancala.com>          |
                     21:    | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at>        |
                     22:    |                                                                      |
                     23:    | Redesigned by: Antony Dovgal <antony@zend.com>                       |
                     24:    |                Andi Gutmans <andi@zend.com>                          |
                     25:    |                Wez Furlong <wez@omniti.com>                          |
                     26:    +----------------------------------------------------------------------+
                     27: */
                     28: 
1.1.1.2 ! misho      29: /* $Id: bf2eaf558b050b6d2e6d098bed6345af7e842ea4 $ */
1.1       misho      30: 
                     31: #ifdef HAVE_CONFIG_H
                     32: #include "config.h"
                     33: #endif
                     34: 
                     35: #include "php.h"
                     36: #include "ext/standard/info.h"
                     37: #include "php_ini.h"
                     38: #include "ext/standard/php_smart_str.h"
                     39: 
                     40: #ifdef HAVE_STDINT_H
                     41: #include <stdint.h>
                     42: #endif
                     43: #ifdef PHP_WIN32
                     44: #include "win32/php_stdint.h"
                     45: #endif
                     46: 
                     47: #if HAVE_OCI8
                     48: 
                     49: #if PHP_MAJOR_VERSION > 5
                     50: #error This version of the PHP OCI8 extension is not compatible with PHP 6 or later
                     51: #elif PHP_MAJOR_VERSION < 5
                     52: #ifdef ZTS
                     53: #error The PHP OCI8 extension does not support ZTS mode in PHP 4
                     54: #endif
                     55: #endif
                     56: 
                     57: #include "php_oci8.h"
                     58: #include "php_oci8_int.h"
                     59: #include "zend_hash.h"
                     60: 
                     61: #if defined(HAVE_STDINT_H) || defined(PHP_WIN32)
                     62: #define OCI8_INT_TO_PTR(I)  ((void *)(intptr_t)(I))
                     63: #define OCI8_PTR_TO_INT(P)  ((int)(intptr_t)(P))
                     64: #else
                     65: #define OCI8_INT_TO_PTR(I)  ((void *)(I))
                     66: #define OCI8_PTR_TO_INT(P)  ((int)(P))
                     67: #endif
                     68: 
                     69: ZEND_DECLARE_MODULE_GLOBALS(oci)
                     70: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
                     71: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
                     72: static PHP_GINIT_FUNCTION(oci);
                     73: static PHP_GSHUTDOWN_FUNCTION(oci);
                     74: #endif
                     75: 
                     76: /* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */
                     77: #ifndef Z_ADDREF_P
                     78: #define Z_ADDREF_P(x) ZVAL_ADDREF(x)
                     79: #endif
                     80: 
                     81: /* For a user friendly message about environment setup */
                     82: #if defined(PHP_WIN32)
                     83: #define PHP_OCI8_LIB_PATH_MSG "PATH"
                     84: #elif defined(__APPLE__)
                     85: #define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
                     86: #elif defined(_AIX)
                     87: #define PHP_OCI8_LIB_PATH_MSG "LIBPATH"
                     88: #elif defined(__hpux)
                     89: #define PHP_OCI8_LIB_PATH_MSG "SHLIB_PATH"
                     90: #else
                     91: #define PHP_OCI8_LIB_PATH_MSG "LD_LIBRARY_PATH"
                     92: #endif
                     93: 
                     94: /* True globals, no need for thread safety */
                     95: int le_connection;
                     96: int le_pconnection;
                     97: int le_statement;
                     98: int le_descriptor;
                     99: int le_psessionpool;
                    100: int le_collection;
                    101: 
                    102: zend_class_entry *oci_lob_class_entry_ptr;
                    103: zend_class_entry *oci_coll_class_entry_ptr;
                    104: 
                    105: #ifndef SQLT_BFILEE
                    106: #define SQLT_BFILEE 114
                    107: #endif
                    108: #ifndef SQLT_CFILEE
                    109: #define SQLT_CFILEE 115
                    110: #endif
                    111: 
                    112: #ifdef OCI_ERROR_MAXMSG_SIZE2
                    113: /* Bigger size is defined from 11.2.0.3 onwards */
                    114: #define PHP_OCI_ERRBUF_LEN OCI_ERROR_MAXMSG_SIZE2
                    115: #else
                    116: #define PHP_OCI_ERRBUF_LEN OCI_ERROR_MAXMSG_SIZE
                    117: #endif 
                    118: 
                    119: #if ZEND_MODULE_API_NO > 20020429
                    120: #define ONUPDATELONGFUNC OnUpdateLong
                    121: #else
                    122: #define ONUPDATELONGFUNC OnUpdateInt
                    123: #endif
                    124: 
                    125: #ifdef ZTS
                    126: #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
                    127: #else
                    128: #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
                    129: #endif
                    130: 
                    131: /* static protos {{{ */
                    132: static void php_oci_connection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
                    133: static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
                    134: static void php_oci_pconnection_list_np_dtor (zend_rsrc_list_entry * TSRMLS_DC);
                    135: static void php_oci_statement_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
                    136: static void php_oci_descriptor_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
                    137: static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC);
                    138: static void php_oci_collection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
                    139: 
                    140: static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC);
                    141: static int php_oci_connection_ping(php_oci_connection * TSRMLS_DC);
                    142: static int php_oci_connection_status(php_oci_connection * TSRMLS_DC);
                    143: static int php_oci_connection_close(php_oci_connection * TSRMLS_DC);
                    144: static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC);
                    145: 
                    146: static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC);
                    147: static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
                    148: static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
                    149: static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC);
                    150: static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC);
                    151: static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC);
                    152: /* }}} */
                    153: 
                    154: /* {{{ dynamically loadable module stuff */
                    155: #if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G)
                    156: ZEND_GET_MODULE(oci8)
                    157: #endif /* COMPILE_DL */
                    158: /* }}} */
                    159: 
                    160: #ifdef ZEND_ENGINE_2
                    161: 
                    162: /* {{{ Function arginfo */
                    163: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_define_by_name, 0, 0, 3)
                    164:        ZEND_ARG_INFO(0, statement_resource)
                    165:        ZEND_ARG_INFO(0, column_name)
                    166:        ZEND_ARG_INFO(1, variable)
                    167:        ZEND_ARG_INFO(0, type)
                    168: ZEND_END_ARG_INFO()
                    169: 
                    170: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_by_name, 0, 0, 3)
                    171:        ZEND_ARG_INFO(0, statement_resource)
                    172:        ZEND_ARG_INFO(0, column_name)
                    173:        ZEND_ARG_INFO(1, variable)
                    174:        ZEND_ARG_INFO(0, maximum_length)
                    175:        ZEND_ARG_INFO(0, type)
                    176: ZEND_END_ARG_INFO()
                    177: 
                    178: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_array_by_name, 0, 0, 4)
                    179:        ZEND_ARG_INFO(0, statement_resource)
                    180:        ZEND_ARG_INFO(0, column_name)
                    181:        ZEND_ARG_INFO(1, variable)
                    182:        ZEND_ARG_INFO(0, maximum_array_length)
                    183:        ZEND_ARG_INFO(0, maximum_item_length)
                    184:        ZEND_ARG_INFO(0, type)
                    185: ZEND_END_ARG_INFO()
                    186: 
                    187: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_descriptor, 0, 0, 1)
                    188:        ZEND_ARG_INFO(0, lob_descriptor)
                    189: ZEND_END_ARG_INFO()
                    190: 
                    191: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save, 0, 0, 2)
                    192:        ZEND_ARG_INFO(0, lob_descriptor)
                    193:        ZEND_ARG_INFO(0, data)
                    194:        ZEND_ARG_INFO(0, offset)
                    195: ZEND_END_ARG_INFO()
                    196: 
                    197: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import, 0, 0, 2)
                    198:        ZEND_ARG_INFO(0, lob_descriptor)
                    199:        ZEND_ARG_INFO(0, filename)
                    200: ZEND_END_ARG_INFO()
                    201: 
                    202: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_load, 0, 0, 1)
                    203:        ZEND_ARG_INFO(0, lob_descriptor)
                    204: ZEND_END_ARG_INFO()
                    205: 
                    206: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read, 0, 0, 2)
                    207:        ZEND_ARG_INFO(0, lob_descriptor)
                    208:        ZEND_ARG_INFO(0, length)
                    209: ZEND_END_ARG_INFO()
                    210: 
                    211: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_eof, 0, 0, 1)
                    212:        ZEND_ARG_INFO(0, lob_descriptor)
                    213: ZEND_END_ARG_INFO()
                    214: 
                    215: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_tell, 0, 0, 1)
                    216:        ZEND_ARG_INFO(0, lob_descriptor)
                    217: ZEND_END_ARG_INFO()
                    218: 
                    219: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_rewind, 0, 0, 1)
                    220:        ZEND_ARG_INFO(0, lob_descriptor)
                    221: ZEND_END_ARG_INFO()
                    222: 
                    223: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek, 0, 0, 2)
                    224:        ZEND_ARG_INFO(0, lob_descriptor)
                    225:        ZEND_ARG_INFO(0, offset)
                    226:        ZEND_ARG_INFO(0, whence)
                    227: ZEND_END_ARG_INFO()
                    228: 
                    229: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_size, 0, 0, 1)
                    230:        ZEND_ARG_INFO(0, lob_descriptor)
                    231: ZEND_END_ARG_INFO()
                    232: 
                    233: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write, 0, 0, 2)
                    234:        ZEND_ARG_INFO(0, lob_descriptor)
                    235:        ZEND_ARG_INFO(0, string)
                    236:        ZEND_ARG_INFO(0, length)
                    237: ZEND_END_ARG_INFO()
                    238: 
                    239: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append, 0, 0, 2)
                    240:        ZEND_ARG_INFO(0, lob_descriptor_to)
                    241:        ZEND_ARG_INFO(0, lob_descriptor_from)
                    242: ZEND_END_ARG_INFO()
                    243: 
                    244: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate, 0, 0, 1)
                    245:        ZEND_ARG_INFO(0, lob_descriptor)
                    246:        ZEND_ARG_INFO(0, length)
                    247: ZEND_END_ARG_INFO()
                    248: 
                    249: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase, 0, 0, 1)
                    250:        ZEND_ARG_INFO(0, lob_descriptor)
                    251:        ZEND_ARG_INFO(0, offset)
                    252:        ZEND_ARG_INFO(0, length)
                    253: ZEND_END_ARG_INFO()
                    254: 
                    255: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush, 0, 0, 1)
                    256:        ZEND_ARG_INFO(0, lob_descriptor)
                    257:        ZEND_ARG_INFO(0, flag)
                    258: ZEND_END_ARG_INFO()
                    259: 
                    260: ZEND_BEGIN_ARG_INFO_EX(arginfo_ocisetbufferinglob, 0, 0, 2)
                    261:        ZEND_ARG_INFO(0, lob_descriptor)
                    262:        ZEND_ARG_INFO(0, mode)
                    263: ZEND_END_ARG_INFO()
                    264: 
                    265: ZEND_BEGIN_ARG_INFO_EX(arginfo_ocigetbufferinglob, 0, 0, 1)
                    266:        ZEND_ARG_INFO(0, lob_descriptor)
                    267: ZEND_END_ARG_INFO()
                    268: 
                    269: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_copy, 0, 0, 2)
                    270:        ZEND_ARG_INFO(0, lob_descriptor_to)
                    271:        ZEND_ARG_INFO(0, lob_descriptor_from)
                    272:        ZEND_ARG_INFO(0, length)
                    273: ZEND_END_ARG_INFO()
                    274: 
                    275: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_is_equal, 0, 0, 2)
                    276:        ZEND_ARG_INFO(0, lob_descriptor)
                    277:        ZEND_ARG_INFO(0, lob_descriptor)
                    278: ZEND_END_ARG_INFO()
                    279: 
                    280: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export, 0, 0, 2)
                    281:        ZEND_ARG_INFO(0, lob_descriptor)
                    282:        ZEND_ARG_INFO(0, filename)
                    283:        ZEND_ARG_INFO(0, start)
                    284:        ZEND_ARG_INFO(0, length)
                    285: ZEND_END_ARG_INFO()
                    286: 
                    287: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_descriptor, 0, 0, 1)
                    288:        ZEND_ARG_INFO(0, connection_resource)
                    289:        ZEND_ARG_INFO(0, type)
                    290: ZEND_END_ARG_INFO()
                    291: 
                    292: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_rollback, 0, 0, 1)
                    293:        ZEND_ARG_INFO(0, connection_resource)
                    294: ZEND_END_ARG_INFO()
                    295: 
                    296: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_commit, 0, 0, 1)
                    297:        ZEND_ARG_INFO(0, connection_resource)
                    298: ZEND_END_ARG_INFO()
                    299: 
                    300: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_name, 0, 0, 2)
                    301:        ZEND_ARG_INFO(0, statement_resource)
                    302:        ZEND_ARG_INFO(0, column_number)
                    303: ZEND_END_ARG_INFO()
                    304: 
                    305: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_size, 0, 0, 2)
                    306:        ZEND_ARG_INFO(0, statement_resource)
                    307:        ZEND_ARG_INFO(0, column_number_or_name)
                    308: ZEND_END_ARG_INFO()
                    309: 
                    310: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_scale, 0, 0, 2)
                    311:        ZEND_ARG_INFO(0, statement_resource)
                    312:        ZEND_ARG_INFO(0, column_number)
                    313: ZEND_END_ARG_INFO()
                    314: 
                    315: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_precision, 0, 0, 2)
                    316:        ZEND_ARG_INFO(0, statement_resource)
                    317:        ZEND_ARG_INFO(0, column_number)
                    318: ZEND_END_ARG_INFO()
                    319: 
                    320: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type, 0, 0, 2)
                    321:        ZEND_ARG_INFO(0, statement_resource)
                    322:        ZEND_ARG_INFO(0, column_number)
                    323: ZEND_END_ARG_INFO()
                    324: 
                    325: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type_raw, 0, 0, 2)
                    326:        ZEND_ARG_INFO(0, statement_resource)
                    327:        ZEND_ARG_INFO(0, column_number)
                    328: ZEND_END_ARG_INFO()
                    329: 
                    330: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_is_null, 0, 0, 2)
                    331:        ZEND_ARG_INFO(0, statement_resource)
                    332:        ZEND_ARG_INFO(0, column_number_or_name)
                    333: ZEND_END_ARG_INFO()
                    334: 
                    335: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_internal_debug, 0, 0, 1)
                    336:        ZEND_ARG_INFO(0, mode)
                    337: ZEND_END_ARG_INFO()
                    338: 
                    339: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_execute, 0, 0, 1)
                    340:        ZEND_ARG_INFO(0, statement_resource)
                    341:        ZEND_ARG_INFO(0, mode)
                    342: ZEND_END_ARG_INFO()
                    343: 
                    344: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_cancel, 0, 0, 1)
                    345:        ZEND_ARG_INFO(0, statement_resource)
                    346: ZEND_END_ARG_INFO()
                    347: 
                    348: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch, 0, 0, 1)
                    349:        ZEND_ARG_INFO(0, statement_resource)
                    350: ZEND_END_ARG_INFO()
                    351: 
                    352: ZEND_BEGIN_ARG_INFO_EX(arginfo_ocifetchinto, 0, 0, 2)
                    353:        ZEND_ARG_INFO(0, statement_resource)
                    354:        ZEND_ARG_INFO(1, result)
                    355:        ZEND_ARG_INFO(0, mode)
                    356: ZEND_END_ARG_INFO()
                    357: 
                    358: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_all, 0, 0, 2)
                    359:        ZEND_ARG_INFO(0, statement_resource)
                    360:        ZEND_ARG_INFO(1, output)
                    361:        ZEND_ARG_INFO(0, skip)
                    362:        ZEND_ARG_INFO(0, maximum_rows)
                    363:        ZEND_ARG_INFO(0, flags)
                    364: ZEND_END_ARG_INFO()
                    365: 
                    366: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_object, 0, 0, 1)
                    367:        ZEND_ARG_INFO(0, statement_resource)
                    368: ZEND_END_ARG_INFO()
                    369: 
                    370: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_row, 0, 0, 1)
                    371:        ZEND_ARG_INFO(0, statement_resource)
                    372: ZEND_END_ARG_INFO()
                    373: 
                    374: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_assoc, 0, 0, 1)
                    375:        ZEND_ARG_INFO(0, statement_resource)
                    376: ZEND_END_ARG_INFO()
                    377: 
                    378: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_array, 0, 0, 1)
                    379:        ZEND_ARG_INFO(0, statement_resource)
                    380:        ZEND_ARG_INFO(0, mode)
                    381: ZEND_END_ARG_INFO()
                    382: 
                    383: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_statement, 0, 0, 1)
                    384:        ZEND_ARG_INFO(0, statement_resource)
                    385: ZEND_END_ARG_INFO()
                    386: 
                    387: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_close, 0, 0, 1)
                    388:        ZEND_ARG_INFO(0, connection_resource)
                    389: ZEND_END_ARG_INFO()
                    390: 
                    391: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_connect, 0, 0, 2)
                    392:        ZEND_ARG_INFO(0, username)
                    393:        ZEND_ARG_INFO(0, password)
                    394:        ZEND_ARG_INFO(0, connection_string)
                    395:        ZEND_ARG_INFO(0, character_set)
                    396:        ZEND_ARG_INFO(0, session_mode)
                    397: ZEND_END_ARG_INFO()
                    398: 
                    399: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_connect, 0, 0, 2)
                    400:        ZEND_ARG_INFO(0, username)
                    401:        ZEND_ARG_INFO(0, password)
                    402:        ZEND_ARG_INFO(0, connection_string)
                    403:        ZEND_ARG_INFO(0, character_set)
                    404:        ZEND_ARG_INFO(0, session_mode)
                    405: ZEND_END_ARG_INFO()
                    406: 
                    407: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_pconnect, 0, 0, 2)
                    408:        ZEND_ARG_INFO(0, username)
                    409:        ZEND_ARG_INFO(0, password)
                    410:        ZEND_ARG_INFO(0, connection_string)
                    411:        ZEND_ARG_INFO(0, character_set)
                    412:        ZEND_ARG_INFO(0, session_mode)
                    413: ZEND_END_ARG_INFO()
                    414: 
                    415: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_error, 0, 0, 0)
                    416:        ZEND_ARG_INFO(0, connection_or_statement_resource)
                    417: ZEND_END_ARG_INFO()
                    418: 
                    419: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_fields, 0, 0, 1)
                    420:        ZEND_ARG_INFO(0, statement_resource)
                    421: ZEND_END_ARG_INFO()
                    422: 
                    423: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_parse, 0, 0, 2)
                    424:        ZEND_ARG_INFO(0, connection_resource)
                    425:        ZEND_ARG_INFO(0, sql_text)
                    426: ZEND_END_ARG_INFO()
                    427: 
                    428: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_prefetch, 0, 0, 2)
                    429:        ZEND_ARG_INFO(0, statement_resource)
                    430:        ZEND_ARG_INFO(0, number_of_rows)
                    431: ZEND_END_ARG_INFO()
                    432: 
                    433: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_identifier, 0, 0, 2)
                    434:        ZEND_ARG_INFO(0, connection_resource)
                    435:        ZEND_ARG_INFO(0, client_identifier)
                    436: ZEND_END_ARG_INFO()
                    437: 
                    438: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_edition, 0, 0, 1)
                    439:        ZEND_ARG_INFO(0, edition_name)
                    440: ZEND_END_ARG_INFO()
                    441: 
                    442: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_module_name, 0, 0, 2)
                    443:        ZEND_ARG_INFO(0, connection_resource)
                    444:        ZEND_ARG_INFO(0, module_name)
                    445: ZEND_END_ARG_INFO()
                    446: 
                    447: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_action, 0, 0, 2)
                    448:        ZEND_ARG_INFO(0, connection_resource)
                    449:        ZEND_ARG_INFO(0, action)
                    450: ZEND_END_ARG_INFO()
                    451: 
                    452: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_info, 0, 0, 2)
                    453:        ZEND_ARG_INFO(0, connection_resource)
                    454:        ZEND_ARG_INFO(0, client_information)
                    455: ZEND_END_ARG_INFO()
                    456: 
                    457: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_password_change, 0, 0, 4)
                    458:        ZEND_ARG_INFO(0, connection_resource_or_connection_string)
                    459:        ZEND_ARG_INFO(0, username)
                    460:        ZEND_ARG_INFO(0, old_password)
                    461:        ZEND_ARG_INFO(0, new_password)
                    462: ZEND_END_ARG_INFO()
                    463: 
                    464: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_cursor, 0, 0, 1)
                    465:        ZEND_ARG_INFO(0, connection_resource)
                    466: ZEND_END_ARG_INFO()
                    467: 
                    468: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_result, 0, 0, 2)
                    469:        ZEND_ARG_INFO(0, statement_resource)
                    470:        ZEND_ARG_INFO(0, column_number_or_name)
                    471: ZEND_END_ARG_INFO()
                    472: 
                    473: ZEND_BEGIN_ARG_INFO(arginfo_oci_client_version, 0)
                    474: ZEND_END_ARG_INFO()
                    475: 
                    476: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_server_version, 0, 0, 1)
                    477:        ZEND_ARG_INFO(0, connection_resource)
                    478: ZEND_END_ARG_INFO()
                    479: 
                    480: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_statement_type, 0, 0, 1)
                    481:        ZEND_ARG_INFO(0, statement_resource)
                    482: ZEND_END_ARG_INFO()
                    483: 
                    484: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_rows, 0, 0, 1)
                    485:        ZEND_ARG_INFO(0, statement_resource)
                    486: ZEND_END_ARG_INFO()
                    487: 
                    488: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_collection, 0, 0, 1)
                    489:        ZEND_ARG_INFO(0, collection)
                    490: ZEND_END_ARG_INFO()
                    491: 
                    492: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append, 0, 0, 2)
                    493:        ZEND_ARG_INFO(0, collection)
                    494:        ZEND_ARG_INFO(0, value)
                    495: ZEND_END_ARG_INFO()
                    496: 
                    497: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get, 0, 0, 2)
                    498:        ZEND_ARG_INFO(0, collection)
                    499:        ZEND_ARG_INFO(0, index)
                    500: ZEND_END_ARG_INFO()
                    501: 
                    502: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign, 0, 0, 2)
                    503:        ZEND_ARG_INFO(0, collection_to)
                    504:        ZEND_ARG_INFO(0, collection_from)
                    505: ZEND_END_ARG_INFO()
                    506: 
                    507: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign, 0, 0, 3)
                    508:        ZEND_ARG_INFO(0, collection)
                    509:        ZEND_ARG_INFO(0, index)
                    510:        ZEND_ARG_INFO(0, value)
                    511: ZEND_END_ARG_INFO()
                    512: 
                    513: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_size, 0, 0, 1)
                    514:        ZEND_ARG_INFO(0, collection)
                    515: ZEND_END_ARG_INFO()
                    516: 
                    517: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_max, 0, 0, 1)
                    518:        ZEND_ARG_INFO(0, collection)
                    519: ZEND_END_ARG_INFO()
                    520: 
                    521: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim, 0, 0, 2)
                    522:        ZEND_ARG_INFO(0, collection)
                    523:        ZEND_ARG_INFO(0, number)
                    524: ZEND_END_ARG_INFO()
                    525: 
                    526: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_collection, 0, 0, 2)
                    527:        ZEND_ARG_INFO(0, connection_resource)
                    528:        ZEND_ARG_INFO(0, type_name)
                    529:        ZEND_ARG_INFO(0, schema_name)
                    530: ZEND_END_ARG_INFO()
                    531: /* }}} */
                    532: 
                    533: /* {{{ LOB Method arginfo */
                    534: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save_method, 0, 0, 1)
                    535:        ZEND_ARG_INFO(0, data)
                    536:        ZEND_ARG_INFO(0, offset)
                    537: ZEND_END_ARG_INFO()
                    538: 
                    539: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import_method, 0, 0, 1)
                    540:        ZEND_ARG_INFO(0, filename)
                    541: ZEND_END_ARG_INFO()
                    542: 
                    543: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_load_method, 0)
                    544: ZEND_END_ARG_INFO()
                    545: 
                    546: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read_method, 0, 0, 1)
                    547:        ZEND_ARG_INFO(0, length)
                    548: ZEND_END_ARG_INFO()
                    549: 
                    550: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_eof_method, 0)
                    551: ZEND_END_ARG_INFO()
                    552: 
                    553: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_tell_method, 0)
                    554: ZEND_END_ARG_INFO()
                    555: 
                    556: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_rewind_method, 0)
                    557: ZEND_END_ARG_INFO()
                    558: 
                    559: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek_method, 0, 0, 1)
                    560:        ZEND_ARG_INFO(0, offset)
                    561:        ZEND_ARG_INFO(0, whence)
                    562: ZEND_END_ARG_INFO()
                    563: 
                    564: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_size_method, 0)
                    565: ZEND_END_ARG_INFO()
                    566: 
                    567: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_method, 0, 0, 1)
                    568:        ZEND_ARG_INFO(0, string)
                    569:        ZEND_ARG_INFO(0, length)
                    570: ZEND_END_ARG_INFO()
                    571: 
                    572: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append_method, 0, 0, 1)
                    573:        ZEND_ARG_INFO(0, lob_descriptor_from)
                    574: ZEND_END_ARG_INFO()
                    575: 
                    576: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate_method, 0, 0, 0)
                    577:        ZEND_ARG_INFO(0, length)
                    578: ZEND_END_ARG_INFO()
                    579: 
                    580: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase_method, 0, 0, 0)
                    581:        ZEND_ARG_INFO(0, offset)
                    582:        ZEND_ARG_INFO(0, length)
                    583: ZEND_END_ARG_INFO()
                    584: 
                    585: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush_method, 0, 0, 0)
                    586:        ZEND_ARG_INFO(0, flag)
                    587: ZEND_END_ARG_INFO()
                    588: 
                    589: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_setbuffering_method, 0, 0, 1)
                    590:        ZEND_ARG_INFO(0, mode)
                    591: ZEND_END_ARG_INFO()
                    592: 
                    593: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_getbuffering_method, 0)
                    594: ZEND_END_ARG_INFO()
                    595: 
                    596: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export_method, 0, 0, 1)
                    597:        ZEND_ARG_INFO(0, filename)
                    598:        ZEND_ARG_INFO(0, start)
                    599:        ZEND_ARG_INFO(0, length)
                    600: ZEND_END_ARG_INFO()
                    601: 
                    602: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_temporary_method, 0, 0, 1)
                    603:        ZEND_ARG_INFO(0, data)
                    604:        ZEND_ARG_INFO(0, type)
                    605: ZEND_END_ARG_INFO()
                    606: 
                    607: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_close_method, 0)
                    608: ZEND_END_ARG_INFO()
                    609: 
                    610: ZEND_BEGIN_ARG_INFO(arginfo_oci_free_descriptor_method, 0)
                    611: ZEND_END_ARG_INFO()
                    612: /* }}} */
                    613: 
                    614: /* {{{ Collection Method arginfo */
                    615: ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_free_method, 0)
                    616: ZEND_END_ARG_INFO()
                    617: 
                    618: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append_method, 0, 0, 1)
                    619:        ZEND_ARG_INFO(0, value)
                    620: ZEND_END_ARG_INFO()
                    621: 
                    622: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get_method, 0, 0, 1)
                    623:        ZEND_ARG_INFO(0, index)
                    624: ZEND_END_ARG_INFO()
                    625: 
                    626: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign_method, 0, 0, 1)
                    627:        ZEND_ARG_INFO(0, collection_from)
                    628: ZEND_END_ARG_INFO()
                    629: 
                    630: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign_method, 0, 0, 2)
                    631:        ZEND_ARG_INFO(0, index)
                    632:        ZEND_ARG_INFO(0, value)
                    633: ZEND_END_ARG_INFO()
                    634: 
                    635: ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_size_method, 0)
                    636: ZEND_END_ARG_INFO()
                    637: 
                    638: ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_max_method, 0)
                    639: ZEND_END_ARG_INFO()
                    640: 
                    641: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim_method, 0, 0, 1)
                    642:        ZEND_ARG_INFO(0, number)
                    643: ZEND_END_ARG_INFO()
                    644: /* }}} */
                    645: 
                    646: #else /* ZEND_ENGINE_2 */
                    647: /* {{{ Keep the old arginfo behavior when building with PHP 4 */
                    648: 
                    649: static unsigned char arginfo_ocifetchinto[]  = { 2, BYREF_NONE, BYREF_FORCE };
                    650: static unsigned char arginfo_oci_fetch_all[] = { 2, BYREF_NONE, BYREF_FORCE };
                    651: static unsigned char arginfo_oci_define_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
                    652: static unsigned char arginfo_oci_bind_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
                    653: static unsigned char arginfo_oci_bind_array_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
                    654: 
                    655: #define arginfo_oci_free_descriptor                                            NULL
                    656: #define arginfo_oci_lob_save                                                   NULL
                    657: #define arginfo_oci_lob_import                                                 NULL
                    658: #define arginfo_oci_lob_load                                                   NULL
                    659: #define arginfo_oci_lob_read                                                   NULL
                    660: #define arginfo_oci_lob_eof                                                            NULL
                    661: #define arginfo_oci_lob_tell                                                   NULL
                    662: #define arginfo_oci_lob_rewind                                                 NULL
                    663: #define arginfo_oci_lob_seek                                                   NULL
                    664: #define arginfo_oci_lob_size                                                   NULL
                    665: #define arginfo_oci_lob_write                                                  NULL
                    666: #define arginfo_oci_lob_append                                                 NULL
                    667: #define arginfo_oci_lob_truncate                                               NULL
                    668: #define arginfo_oci_lob_erase                                                  NULL
                    669: #define arginfo_oci_lob_flush                                                  NULL
                    670: #define arginfo_ocisetbufferinglob                                             NULL
                    671: #define arginfo_ocigetbufferinglob                                             NULL
                    672: #define arginfo_oci_lob_copy                                                   NULL
                    673: #define arginfo_oci_lob_is_equal                                               NULL
                    674: #define arginfo_oci_lob_export                                                 NULL
                    675: #define arginfo_oci_new_descriptor                                             NULL
                    676: #define arginfo_oci_rollback                                                   NULL
                    677: #define arginfo_oci_commit                                                             NULL
                    678: #define arginfo_oci_field_name                                                 NULL
                    679: #define arginfo_oci_field_size                                                 NULL
                    680: #define arginfo_oci_field_scale                                                        NULL
                    681: #define arginfo_oci_field_precision                                            NULL
                    682: #define arginfo_oci_field_type                                                 NULL
                    683: #define arginfo_oci_field_type_raw                                             NULL
                    684: #define arginfo_oci_field_is_null                                              NULL
                    685: #define arginfo_oci_internal_debug                                             NULL
                    686: #define arginfo_oci_execute                                                            NULL
                    687: #define arginfo_oci_cancel                                                             NULL
                    688: #define arginfo_oci_fetch                                                              NULL
                    689: #define arginfo_oci_fetch_object                                               NULL
                    690: #define arginfo_oci_fetch_row                                                  NULL
                    691: #define arginfo_oci_fetch_assoc                                                        NULL
                    692: #define arginfo_oci_fetch_array                                                        NULL
                    693: #define arginfo_oci_free_statement                                             NULL
                    694: #define arginfo_oci_close                                                              NULL
                    695: #define arginfo_oci_new_connect                                                        NULL
                    696: #define arginfo_oci_connect                                                            NULL
                    697: #define arginfo_oci_pconnect                                                   NULL
                    698: #define arginfo_oci_error                                                              NULL
                    699: #define arginfo_oci_num_fields                                                 NULL
                    700: #define arginfo_oci_parse                                                              NULL
                    701: #define arginfo_oci_set_prefetch                                               NULL
                    702: #define arginfo_oci_set_client_identifier                              NULL
                    703: #define arginfo_oci_set_edition                                                        NULL
                    704: #define arginfo_oci_set_module_name                                            NULL
                    705: #define arginfo_oci_set_action                                                 NULL
                    706: #define arginfo_oci_set_client_info                                            NULL
                    707: #define arginfo_oci_password_change                                            NULL
                    708: #define arginfo_oci_new_cursor                                                 NULL
                    709: #define arginfo_oci_result                                                             NULL
                    710: #define arginfo_oci_client_version                                             NULL
                    711: #define arginfo_oci_server_version                                             NULL
                    712: #define arginfo_oci_statement_type                                             NULL
                    713: #define arginfo_oci_num_rows                                                   NULL
                    714: #define arginfo_oci_free_collection                                            NULL
                    715: #define arginfo_oci_collection_append                                  NULL
                    716: #define arginfo_oci_collection_element_get                             NULL
                    717: #define arginfo_oci_collection_assign                                  NULL
                    718: #define arginfo_oci_collection_element_assign                  NULL
                    719: #define arginfo_oci_collection_size                                            NULL
                    720: #define arginfo_oci_collection_max                                             NULL
                    721: #define arginfo_oci_collection_trim                                            NULL
                    722: #define arginfo_oci_new_collection                                             NULL
                    723: #define arginfo_oci_lob_size_method                                            NULL
                    724: #define arginfo_oci_lob_getbuffering_method                            NULL
                    725: #define arginfo_oci_lob_close_method                                   NULL
                    726: #define arginfo_oci_lob_save_method                                            NULL
                    727: #define arginfo_oci_lob_import_method                                  NULL
                    728: #define arginfo_oci_lob_read_method                                            NULL
                    729: #define arginfo_oci_lob_seek_method                                            NULL
                    730: #define arginfo_oci_lob_write_method                                   NULL
                    731: #define arginfo_oci_lob_append_method                                  NULL
                    732: #define arginfo_oci_lob_truncate_method                                        NULL
                    733: #define arginfo_oci_lob_erase_method                                   NULL
                    734: #define arginfo_oci_lob_flush_method                                   NULL
                    735: #define arginfo_oci_lob_setbuffering_method                            NULL
                    736: #define arginfo_oci_lob_export_method                                  NULL
                    737: #define arginfo_oci_lob_write_temporary_method                 NULL
                    738: #define arginfo_oci_lob_load_method                                            NULL
                    739: #define arginfo_oci_lob_tell_method                                            NULL
                    740: #define arginfo_oci_lob_rewind_method                                  NULL
                    741: #define arginfo_oci_lob_eof_method                                             NULL
                    742: #define arginfo_oci_free_descriptor_method                             NULL
                    743: #define arginfo_oci_collection_append_method                   NULL
                    744: #define arginfo_oci_collection_element_get_method              NULL
                    745: #define arginfo_oci_collection_assign_method                   NULL
                    746: #define arginfo_oci_collection_size_method                             NULL
                    747: #define arginfo_oci_collection_element_assign_method   NULL
                    748: #define arginfo_oci_collection_max_method                              NULL
                    749: #define arginfo_oci_collection_trim_method                             NULL
                    750: #define arginfo_oci_collection_free_method                             NULL
                    751: /* }}} */
                    752: #endif /* ZEND_ENGINE_2 */
                    753: 
                    754: /* {{{ extension function prototypes
                    755: */
                    756: PHP_FUNCTION(oci_bind_by_name);
                    757: PHP_FUNCTION(oci_bind_array_by_name);
                    758: PHP_FUNCTION(oci_define_by_name);
                    759: PHP_FUNCTION(oci_field_is_null);
                    760: PHP_FUNCTION(oci_field_name);
                    761: PHP_FUNCTION(oci_field_size);
                    762: PHP_FUNCTION(oci_field_scale);
                    763: PHP_FUNCTION(oci_field_precision);
                    764: PHP_FUNCTION(oci_field_type);
                    765: PHP_FUNCTION(oci_field_type_raw);
                    766: PHP_FUNCTION(oci_execute);
                    767: PHP_FUNCTION(oci_fetch);
                    768: PHP_FUNCTION(oci_cancel);
                    769: PHP_FUNCTION(ocifetchinto);
                    770: PHP_FUNCTION(oci_fetch_object);
                    771: PHP_FUNCTION(oci_fetch_row);
                    772: PHP_FUNCTION(oci_fetch_assoc);
                    773: PHP_FUNCTION(oci_fetch_array);
                    774: PHP_FUNCTION(ocifetchstatement);
                    775: PHP_FUNCTION(oci_fetch_all);
                    776: PHP_FUNCTION(oci_free_statement);
                    777: PHP_FUNCTION(oci_internal_debug);
                    778: PHP_FUNCTION(oci_close);
                    779: PHP_FUNCTION(oci_connect);
                    780: PHP_FUNCTION(oci_new_connect);
                    781: PHP_FUNCTION(oci_pconnect);
                    782: PHP_FUNCTION(oci_error);
                    783: PHP_FUNCTION(oci_free_descriptor);
                    784: PHP_FUNCTION(oci_commit);
                    785: PHP_FUNCTION(oci_rollback);
                    786: PHP_FUNCTION(oci_new_descriptor);
                    787: PHP_FUNCTION(oci_num_fields);
                    788: PHP_FUNCTION(oci_parse);
                    789: PHP_FUNCTION(oci_new_cursor);
                    790: PHP_FUNCTION(oci_result);
                    791: PHP_FUNCTION(oci_client_version);
                    792: PHP_FUNCTION(oci_server_version);
                    793: PHP_FUNCTION(oci_statement_type);
                    794: PHP_FUNCTION(oci_num_rows);
                    795: PHP_FUNCTION(oci_set_prefetch);
                    796: PHP_FUNCTION(oci_set_client_identifier);
                    797: PHP_FUNCTION(oci_set_edition);
                    798: PHP_FUNCTION(oci_set_module_name);
                    799: PHP_FUNCTION(oci_set_action);
                    800: PHP_FUNCTION(oci_set_client_info);
                    801: PHP_FUNCTION(oci_password_change);
                    802: PHP_FUNCTION(oci_lob_save);
                    803: PHP_FUNCTION(oci_lob_import);
                    804: PHP_FUNCTION(oci_lob_export);
                    805: PHP_FUNCTION(oci_lob_load);
                    806: PHP_FUNCTION(oci_lob_tell);
                    807: PHP_FUNCTION(oci_lob_write);
                    808: PHP_FUNCTION(oci_lob_append);
                    809: PHP_FUNCTION(oci_lob_copy);
                    810: PHP_FUNCTION(oci_lob_truncate);
                    811: PHP_FUNCTION(oci_lob_erase);
                    812: PHP_FUNCTION(oci_lob_flush);
                    813: PHP_FUNCTION(ocisetbufferinglob);
                    814: PHP_FUNCTION(ocigetbufferinglob);
                    815: PHP_FUNCTION(oci_lob_is_equal);
                    816: PHP_FUNCTION(oci_lob_rewind);
                    817: PHP_FUNCTION(oci_lob_read);
                    818: PHP_FUNCTION(oci_lob_eof);
                    819: PHP_FUNCTION(oci_lob_seek);
                    820: PHP_FUNCTION(oci_lob_size);
                    821: PHP_FUNCTION(oci_lob_write_temporary);
                    822: PHP_FUNCTION(oci_lob_close);
                    823: PHP_FUNCTION(oci_new_collection);
                    824: PHP_FUNCTION(oci_free_collection);
                    825: PHP_FUNCTION(oci_collection_append);
                    826: PHP_FUNCTION(oci_collection_element_get);
                    827: PHP_FUNCTION(oci_collection_element_assign);
                    828: PHP_FUNCTION(oci_collection_assign);
                    829: PHP_FUNCTION(oci_collection_size);
                    830: PHP_FUNCTION(oci_collection_max);
                    831: PHP_FUNCTION(oci_collection_trim);
                    832: /* }}} */
                    833: 
                    834: /* {{{ extension definition structures
                    835: */
                    836: static
                    837: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
                    838: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
                    839: const
                    840: #endif
                    841: zend_function_entry php_oci_functions[] = {
                    842:        PHP_FE(oci_define_by_name,                      arginfo_oci_define_by_name)
                    843:        PHP_FE(oci_bind_by_name,                        arginfo_oci_bind_by_name)
                    844:        PHP_FE(oci_bind_array_by_name,          arginfo_oci_bind_array_by_name)
                    845:        PHP_FE(oci_field_is_null,                       arginfo_oci_field_is_null)
                    846:        PHP_FE(oci_field_name,                          arginfo_oci_field_name)
                    847:        PHP_FE(oci_field_size,                          arginfo_oci_field_size)
                    848:        PHP_FE(oci_field_scale,                         arginfo_oci_field_scale)
                    849:        PHP_FE(oci_field_precision,                     arginfo_oci_field_precision)
                    850:        PHP_FE(oci_field_type,                          arginfo_oci_field_type)
                    851:        PHP_FE(oci_field_type_raw,                      arginfo_oci_field_type_raw)
                    852:        PHP_FE(oci_execute,                                     arginfo_oci_execute)
                    853:        PHP_FE(oci_cancel,                                      arginfo_oci_cancel)
                    854:        PHP_FE(oci_fetch,                                       arginfo_oci_fetch)
                    855:        PHP_FE(oci_fetch_object,                        arginfo_oci_fetch_object)
                    856:        PHP_FE(oci_fetch_row,                           arginfo_oci_fetch_row)
                    857:        PHP_FE(oci_fetch_assoc,                         arginfo_oci_fetch_assoc)
                    858:        PHP_FE(oci_fetch_array,                         arginfo_oci_fetch_array)
                    859:        PHP_FE(ocifetchinto,                            arginfo_ocifetchinto)
                    860:        PHP_FE(oci_fetch_all,                           arginfo_oci_fetch_all)
                    861:        PHP_FE(oci_free_statement,                      arginfo_oci_free_statement)
                    862:        PHP_FE(oci_internal_debug,                      arginfo_oci_internal_debug)
                    863:        PHP_FE(oci_num_fields,                          arginfo_oci_num_fields)
                    864:        PHP_FE(oci_parse,                                       arginfo_oci_parse)
                    865:        PHP_FE(oci_new_cursor,                          arginfo_oci_new_cursor)
                    866:        PHP_FE(oci_result,                                      arginfo_oci_result)
                    867:        PHP_FE(oci_client_version,                      arginfo_oci_client_version)
                    868:        PHP_FE(oci_server_version,                      arginfo_oci_server_version)
                    869:        PHP_FE(oci_statement_type,                      arginfo_oci_statement_type)
                    870:        PHP_FE(oci_num_rows,                            arginfo_oci_num_rows)
                    871:        PHP_FE(oci_close,                                       arginfo_oci_close)
                    872:        PHP_FE(oci_connect,                                     arginfo_oci_connect)
                    873:        PHP_FE(oci_new_connect,                         arginfo_oci_new_connect)
                    874:        PHP_FE(oci_pconnect,                            arginfo_oci_pconnect)
                    875:        PHP_FE(oci_error,                                       arginfo_oci_error)
                    876:        PHP_FE(oci_free_descriptor,                     arginfo_oci_free_descriptor)
                    877:        PHP_FE(oci_lob_save,                            arginfo_oci_lob_save)
                    878:        PHP_FE(oci_lob_import,                          arginfo_oci_lob_import)
                    879:        PHP_FE(oci_lob_size,                            arginfo_oci_lob_size)
                    880:        PHP_FE(oci_lob_load,                            arginfo_oci_lob_load)
                    881:        PHP_FE(oci_lob_read,                            arginfo_oci_lob_read)
                    882:        PHP_FE(oci_lob_eof,                                     arginfo_oci_lob_eof)
                    883:        PHP_FE(oci_lob_tell,                            arginfo_oci_lob_tell)
                    884:        PHP_FE(oci_lob_truncate,                        arginfo_oci_lob_truncate)
                    885:        PHP_FE(oci_lob_erase,                           arginfo_oci_lob_erase)
                    886:        PHP_FE(oci_lob_flush,                           arginfo_oci_lob_flush)
                    887:        PHP_FE(ocisetbufferinglob,                      arginfo_ocisetbufferinglob)
                    888:        PHP_FE(ocigetbufferinglob,                      arginfo_ocigetbufferinglob)
                    889:        PHP_FE(oci_lob_is_equal,                        arginfo_oci_lob_is_equal)
                    890:        PHP_FE(oci_lob_rewind,                          arginfo_oci_lob_rewind)
                    891:        PHP_FE(oci_lob_write,                           arginfo_oci_lob_write)
                    892:        PHP_FE(oci_lob_append,                          arginfo_oci_lob_append)
                    893:        PHP_FE(oci_lob_copy,                            arginfo_oci_lob_copy)
                    894:        PHP_FE(oci_lob_export,                          arginfo_oci_lob_export)
                    895:        PHP_FE(oci_lob_seek,                            arginfo_oci_lob_seek)
                    896:        PHP_FE(oci_commit,                                      arginfo_oci_commit)
                    897:        PHP_FE(oci_rollback,                            arginfo_oci_rollback)
                    898:        PHP_FE(oci_new_descriptor,                      arginfo_oci_new_descriptor)
                    899:        PHP_FE(oci_set_prefetch,                        arginfo_oci_set_prefetch)
                    900:        PHP_FE(oci_set_client_identifier,       arginfo_oci_set_client_identifier)
                    901:        PHP_FE(oci_set_edition,                         arginfo_oci_set_edition)
                    902:        PHP_FE(oci_set_module_name,                     arginfo_oci_set_module_name)
                    903:        PHP_FE(oci_set_action,                          arginfo_oci_set_action)
                    904:        PHP_FE(oci_set_client_info,                     arginfo_oci_set_client_info)
                    905:        PHP_FE(oci_password_change,                     arginfo_oci_password_change)
                    906:        PHP_FE(oci_free_collection,                     arginfo_oci_free_collection)
                    907:        PHP_FE(oci_collection_append,           arginfo_oci_collection_append)
                    908:        PHP_FE(oci_collection_element_get,      arginfo_oci_collection_element_get)
                    909:        PHP_FE(oci_collection_element_assign,   arginfo_oci_collection_element_assign)
                    910:        PHP_FE(oci_collection_assign,           arginfo_oci_collection_assign)
                    911:        PHP_FE(oci_collection_size,                     arginfo_oci_collection_size)
                    912:        PHP_FE(oci_collection_max,                      arginfo_oci_collection_max)
                    913:        PHP_FE(oci_collection_trim,                     arginfo_oci_collection_trim)
                    914:        PHP_FE(oci_new_collection,                      arginfo_oci_new_collection)
                    915: 
                    916:        PHP_FALIAS(oci_free_cursor,             oci_free_statement,             arginfo_oci_free_statement)
                    917:        PHP_FALIAS(ocifreecursor,               oci_free_statement,             arginfo_oci_free_statement)
                    918:        PHP_FALIAS(ocibindbyname,               oci_bind_by_name,               arginfo_oci_bind_by_name)
                    919:        PHP_FALIAS(ocidefinebyname,             oci_define_by_name,             arginfo_oci_define_by_name)
                    920:        PHP_FALIAS(ocicolumnisnull,             oci_field_is_null,              arginfo_oci_field_is_null)
                    921:        PHP_FALIAS(ocicolumnname,               oci_field_name,                 arginfo_oci_field_name)
                    922:        PHP_FALIAS(ocicolumnsize,               oci_field_size,                 arginfo_oci_field_size)
                    923:        PHP_FALIAS(ocicolumnscale,              oci_field_scale,                arginfo_oci_field_scale)
                    924:        PHP_FALIAS(ocicolumnprecision,  oci_field_precision,    arginfo_oci_field_precision)
                    925:        PHP_FALIAS(ocicolumntype,               oci_field_type,                 arginfo_oci_field_type)
                    926:        PHP_FALIAS(ocicolumntyperaw,    oci_field_type_raw,             arginfo_oci_field_type_raw)
                    927:        PHP_FALIAS(ociexecute,                  oci_execute,                    arginfo_oci_execute)
                    928:        PHP_FALIAS(ocicancel,                   oci_cancel,                             arginfo_oci_cancel)
                    929:        PHP_FALIAS(ocifetch,                    oci_fetch,                              arginfo_oci_fetch)
                    930:        PHP_FALIAS(ocifetchstatement,   oci_fetch_all,                  arginfo_oci_fetch_all)
                    931:        PHP_FALIAS(ocifreestatement,    oci_free_statement,             arginfo_oci_free_statement)
                    932:        PHP_FALIAS(ociinternaldebug,    oci_internal_debug,             arginfo_oci_internal_debug)
                    933:        PHP_FALIAS(ocinumcols,                  oci_num_fields,                 arginfo_oci_num_fields)
                    934:        PHP_FALIAS(ociparse,                    oci_parse,                              arginfo_oci_parse)
                    935:        PHP_FALIAS(ocinewcursor,                oci_new_cursor,                 arginfo_oci_new_cursor)
                    936:        PHP_FALIAS(ociresult,                   oci_result,                             arginfo_oci_result)
                    937:        PHP_FALIAS(ociserverversion,    oci_server_version,             arginfo_oci_server_version)
                    938:        PHP_FALIAS(ocistatementtype,    oci_statement_type,             arginfo_oci_statement_type)
                    939:        PHP_FALIAS(ocirowcount,                 oci_num_rows,                   arginfo_oci_num_rows)
                    940:        PHP_FALIAS(ocilogoff,                   oci_close,                              arginfo_oci_close)
                    941:        PHP_FALIAS(ocilogon,                    oci_connect,                    arginfo_oci_connect)
                    942:        PHP_FALIAS(ocinlogon,                   oci_new_connect,                arginfo_oci_new_connect)
                    943:        PHP_FALIAS(ociplogon,                   oci_pconnect,                   arginfo_oci_pconnect)
                    944:        PHP_FALIAS(ocierror,                    oci_error,                              arginfo_oci_error)
                    945:        PHP_FALIAS(ocifreedesc,                 oci_free_descriptor,    arginfo_oci_free_descriptor)
                    946:        PHP_FALIAS(ocisavelob,                  oci_lob_save,                   arginfo_oci_lob_save)
                    947:        PHP_FALIAS(ocisavelobfile,              oci_lob_import,                 arginfo_oci_lob_import)
                    948:        PHP_FALIAS(ociwritelobtofile,   oci_lob_export,                 arginfo_oci_lob_export)
                    949:        PHP_FALIAS(ociloadlob,                  oci_lob_load,                   arginfo_oci_lob_load)
                    950:        PHP_FALIAS(ocicommit,                   oci_commit,                             arginfo_oci_commit)
                    951:        PHP_FALIAS(ocirollback,                 oci_rollback,                   arginfo_oci_rollback)
                    952:        PHP_FALIAS(ocinewdescriptor,    oci_new_descriptor,             arginfo_oci_new_descriptor)
                    953:        PHP_FALIAS(ocisetprefetch,              oci_set_prefetch,               arginfo_oci_set_prefetch)
                    954:        PHP_FALIAS(ocipasswordchange,   oci_password_change,    arginfo_oci_password_change)
                    955:        PHP_FALIAS(ocifreecollection,   oci_free_collection,    arginfo_oci_free_collection)
                    956:        PHP_FALIAS(ocinewcollection,    oci_new_collection,             arginfo_oci_new_collection)
                    957:        PHP_FALIAS(ocicollappend,               oci_collection_append,  arginfo_oci_collection_append)
                    958:        PHP_FALIAS(ocicollgetelem,              oci_collection_element_get,             arginfo_oci_collection_element_get)
                    959:        PHP_FALIAS(ocicollassignelem,   oci_collection_element_assign,  arginfo_oci_collection_element_assign)
                    960:        PHP_FALIAS(ocicollsize,                 oci_collection_size,    arginfo_oci_collection_size)
                    961:        PHP_FALIAS(ocicollmax,                  oci_collection_max,             arginfo_oci_collection_max)
                    962:        PHP_FALIAS(ocicolltrim,                 oci_collection_trim,    arginfo_oci_collection_trim)
                    963: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
                    964:        PHP_FE_END
                    965: #else
                    966:        {NULL,NULL,NULL}
                    967: #endif
                    968: };
                    969: 
                    970: static
                    971: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
                    972: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
                    973: const
                    974: #endif
                    975: zend_function_entry php_oci_lob_class_functions[] = {
                    976:        PHP_FALIAS(load,                oci_lob_load,                   arginfo_oci_lob_load_method)
                    977:        PHP_FALIAS(tell,                oci_lob_tell,                   arginfo_oci_lob_tell_method)
                    978:        PHP_FALIAS(truncate,    oci_lob_truncate,               arginfo_oci_lob_truncate_method)
                    979:        PHP_FALIAS(erase,               oci_lob_erase,                  arginfo_oci_lob_erase_method)
                    980:        PHP_FALIAS(flush,               oci_lob_flush,                  arginfo_oci_lob_flush_method)
                    981:        PHP_FALIAS(setbuffering,ocisetbufferinglob,             arginfo_oci_lob_setbuffering_method)
                    982:        PHP_FALIAS(getbuffering,ocigetbufferinglob,             arginfo_oci_lob_getbuffering_method)
                    983:        PHP_FALIAS(rewind,              oci_lob_rewind,                 arginfo_oci_lob_rewind_method)
                    984:        PHP_FALIAS(read,                oci_lob_read,                   arginfo_oci_lob_read_method)
                    985:        PHP_FALIAS(eof,                 oci_lob_eof,                    arginfo_oci_lob_eof_method)
                    986:        PHP_FALIAS(seek,                oci_lob_seek,                   arginfo_oci_lob_seek_method)
                    987:        PHP_FALIAS(write,               oci_lob_write,                  arginfo_oci_lob_write_method)
                    988:        PHP_FALIAS(append,              oci_lob_append,                 arginfo_oci_lob_append_method)
                    989:        PHP_FALIAS(size,                oci_lob_size,                   arginfo_oci_lob_size_method)
                    990:        PHP_FALIAS(writetofile, oci_lob_export,                 arginfo_oci_lob_export_method)
                    991:        PHP_FALIAS(export,              oci_lob_export,                 arginfo_oci_lob_export_method)
                    992:        PHP_FALIAS(import,              oci_lob_import,                 arginfo_oci_lob_import_method)
                    993:        PHP_FALIAS(writetemporary,      oci_lob_write_temporary,        arginfo_oci_lob_write_temporary_method)
                    994:        PHP_FALIAS(close,                       oci_lob_close,                          arginfo_oci_lob_close_method)
                    995:        PHP_FALIAS(save,                oci_lob_save,                   arginfo_oci_lob_save_method)
                    996:        PHP_FALIAS(savefile,    oci_lob_import,                 arginfo_oci_lob_import_method)
                    997:        PHP_FALIAS(free,                oci_free_descriptor,    arginfo_oci_free_descriptor_method)
                    998: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
                    999:        PHP_FE_END
                   1000: #else
                   1001:        {NULL,NULL,NULL}
                   1002: #endif
                   1003: };
                   1004: 
                   1005: static
                   1006: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
                   1007: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
                   1008: const
                   1009: #endif
                   1010: zend_function_entry php_oci_coll_class_functions[] = {
                   1011:        PHP_FALIAS(append,                oci_collection_append,                        arginfo_oci_collection_append_method)
                   1012:        PHP_FALIAS(getelem,               oci_collection_element_get,           arginfo_oci_collection_element_get_method)
                   1013:        PHP_FALIAS(assignelem,    oci_collection_element_assign,        arginfo_oci_collection_element_assign_method)
                   1014:        PHP_FALIAS(assign,                oci_collection_assign,                        arginfo_oci_collection_assign_method)
                   1015:        PHP_FALIAS(size,                  oci_collection_size,                          arginfo_oci_collection_size_method)
                   1016:        PHP_FALIAS(max,                   oci_collection_max,                           arginfo_oci_collection_max_method)
                   1017:        PHP_FALIAS(trim,                  oci_collection_trim,                          arginfo_oci_collection_trim_method)
                   1018:        PHP_FALIAS(free,                  oci_free_collection,                          arginfo_oci_collection_free_method)
                   1019: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
                   1020:        PHP_FE_END
                   1021: #else
                   1022:        {NULL,NULL,NULL}
                   1023: #endif
                   1024: };
                   1025: 
                   1026: zend_module_entry oci8_module_entry = {
                   1027:        STANDARD_MODULE_HEADER,
                   1028:        "oci8",                           /* extension name */
                   1029:        php_oci_functions,        /* extension function list */
                   1030:        PHP_MINIT(oci),           /* extension-wide startup function */
                   1031:        PHP_MSHUTDOWN(oci),       /* extension-wide shutdown function */
                   1032:        PHP_RINIT(oci),           /* per-request startup function */
                   1033:        PHP_RSHUTDOWN(oci),       /* per-request shutdown function */
                   1034:        PHP_MINFO(oci),           /* information function */
                   1035:        PHP_OCI8_VERSION,
                   1036: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
                   1037:        /* This check allows PECL builds from this file to be portable to older PHP releases */
                   1038:        PHP_MODULE_GLOBALS(oci),  /* globals descriptor */
                   1039:        PHP_GINIT(oci),                   /* globals ctor */
                   1040:        PHP_GSHUTDOWN(oci),               /* globals dtor */
                   1041:        NULL,                                     /* post deactivate */
                   1042:        STANDARD_MODULE_PROPERTIES_EX
                   1043: #else
                   1044:        STANDARD_MODULE_PROPERTIES
                   1045: #endif
                   1046: };
                   1047: /* }}} */
                   1048: 
                   1049: /* {{{ PHP_INI */
                   1050: PHP_INI_BEGIN()
                   1051:        STD_PHP_INI_ENTRY(      "oci8.max_persistent",                  "-1",   PHP_INI_SYSTEM, ONUPDATELONGFUNC,       max_persistent,                 zend_oci_globals,       oci_globals)
                   1052:        STD_PHP_INI_ENTRY(      "oci8.persistent_timeout",              "-1",   PHP_INI_SYSTEM, ONUPDATELONGFUNC,       persistent_timeout,             zend_oci_globals,       oci_globals)
                   1053:        STD_PHP_INI_ENTRY(      "oci8.ping_interval",                   "60",   PHP_INI_SYSTEM, ONUPDATELONGFUNC,       ping_interval,                  zend_oci_globals,       oci_globals)
                   1054:        STD_PHP_INI_BOOLEAN("oci8.privileged_connect",          "0",    PHP_INI_SYSTEM, OnUpdateBool,           privileged_connect,             zend_oci_globals,       oci_globals)
                   1055:        STD_PHP_INI_ENTRY(      "oci8.statement_cache_size",    "20",   PHP_INI_SYSTEM, ONUPDATELONGFUNC,       statement_cache_size,   zend_oci_globals,       oci_globals)
                   1056:        STD_PHP_INI_ENTRY(      "oci8.default_prefetch",                "100",  PHP_INI_SYSTEM, ONUPDATELONGFUNC,       default_prefetch,               zend_oci_globals,       oci_globals)
                   1057:        STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics",     "0",    PHP_INI_SYSTEM, OnUpdateBool,           old_oci_close_semantics,zend_oci_globals,       oci_globals)
                   1058:        STD_PHP_INI_ENTRY(      "oci8.connection_class",                "",             PHP_INI_ALL,    OnUpdateString,         connection_class,               zend_oci_globals,       oci_globals)
                   1059:        STD_PHP_INI_BOOLEAN("oci8.events",                                      "0",    PHP_INI_SYSTEM, OnUpdateBool,           events,                                 zend_oci_globals,       oci_globals)
                   1060: PHP_INI_END()
                   1061: /* }}} */
                   1062: 
                   1063: /* {{{ startup, shutdown and info functions
                   1064: */
                   1065: 
                   1066: /* {{{ php_oci_init_global_handles()
                   1067:  *
                   1068:  * Initialize global handles only when they are needed
                   1069:  */
                   1070: static void php_oci_init_global_handles(TSRMLS_D)
                   1071: {
                   1072:        sword errstatus;
                   1073:        sb4   ora_error_code = 0;
                   1074:        text  tmp_buf[OCI_ERROR_MAXMSG_SIZE];  /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
                   1075: 
                   1076:        errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
                   1077: 
                   1078:        if (errstatus == OCI_ERROR) {
                   1079: #ifdef HAVE_OCI_INSTANT_CLIENT
                   1080:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
                   1081: #else
                   1082:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
                   1083: #endif
                   1084:                if (OCI_G(env)
                   1085:                        && OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
                   1086:                        && *tmp_buf) {
                   1087:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tmp_buf);
                   1088:                }
                   1089:                
                   1090:                OCI_G(env) = NULL;
                   1091:                OCI_G(err) = NULL;
                   1092:                return;
                   1093:        }
                   1094: 
                   1095:        errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
                   1096: 
                   1097:        if (errstatus == OCI_SUCCESS) {
                   1098: #if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
                   1099:                /* This fixes PECL bug 15988 (sqlnet.ora not being read).  The
                   1100:                 * root cause was fixed in Oracle 10.2.0.4 but there is no
                   1101:                 * compile time method to check for that precise patch level,
                   1102:                 * nor can it be guaranteed that runtime will use the same
                   1103:                 * patch level the code was compiled with.  So, we do this
                   1104:                 * code for all non 11g versions.
                   1105:                 */
                   1106:                OCICPool *cpoolh;
                   1107:                ub4 cpoolmode = 0x80000000;     /* Pass invalid mode to OCIConnectionPoolCreate */
                   1108:                PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
                   1109:                PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
                   1110:                PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
                   1111:                PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
                   1112: #endif
                   1113:        } else {
                   1114:                OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ERROR);
                   1115: 
                   1116:                if (ora_error_code) {
                   1117:                        int tmp_buf_len = strlen((char *)tmp_buf);
                   1118:                        
                   1119:                        if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
                   1120:                                tmp_buf[tmp_buf_len - 1] = '\0';
                   1121:                        }
                   1122:                        
                   1123:                        if (errstatus == OCI_SUCCESS_WITH_INFO) {
                   1124:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
                   1125:                        } else {
                   1126:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
                   1127:                                
                   1128:                                OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
                   1129:                                
                   1130:                                OCI_G(env) = NULL;
                   1131:                                OCI_G(err) = NULL;
                   1132:                        }
                   1133:                }
                   1134:        }
                   1135: } /* }}} */
                   1136: 
                   1137: /* {{{ php_oci_cleanup_global_handles()
                   1138:  *
                   1139:  * Free global handles (if they were initialized before)
                   1140:  */
                   1141: static void php_oci_cleanup_global_handles(TSRMLS_D)
                   1142: {
                   1143:        if (OCI_G(err)) {
                   1144:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR));
                   1145:                OCI_G(err) = NULL;
                   1146:        }
                   1147: 
                   1148:        if (OCI_G(env)) {
                   1149:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV));
                   1150:                OCI_G(env) = NULL;
                   1151:        }
                   1152: } /* }}} */
                   1153: 
                   1154: /* {{{ PHP_GINIT_FUNCTION
                   1155:  *
                   1156:  * Zerofill globals during module init
                   1157:  */
                   1158: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
                   1159: /* This check allows PECL builds from this file to be portable to older PHP releases */
                   1160: static PHP_GINIT_FUNCTION(oci)
                   1161: #else
                   1162: static void php_oci_init_globals(zend_oci_globals *oci_globals TSRMLS_DC)
                   1163: #endif
                   1164: {
                   1165:        memset(oci_globals, 0, sizeof(zend_oci_globals));
                   1166: }
                   1167: /* }}} */
                   1168: 
                   1169: /* {{{ PHP_GSHUTDOWN_FUNCTION
                   1170:  *
                   1171:  * Called for thread shutdown in ZTS, after module shutdown for non-ZTS
                   1172:  */
                   1173: /* This check allows PECL builds from this file to be portable to older PHP releases */
                   1174: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
                   1175: static PHP_GSHUTDOWN_FUNCTION(oci)
                   1176: #else
                   1177: static void php_oci_shutdown_globals(zend_oci_globals *oci_globals TSRMLS_DC)
                   1178: #endif
                   1179: {
                   1180:        php_oci_cleanup_global_handles(TSRMLS_C);
                   1181: }
                   1182: /* }}} */
                   1183: 
                   1184: PHP_MINIT_FUNCTION(oci)
                   1185: {
                   1186:        zend_class_entry oci_lob_class_entry;
                   1187:        zend_class_entry oci_coll_class_entry;
                   1188: 
                   1189: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
                   1190:        /* This check allows PECL builds from this file to be portable to older PHP releases */
                   1191:        /* this is handled by new globals management code */
                   1192: #else
                   1193:        ZEND_INIT_MODULE_GLOBALS(oci, php_oci_init_globals, php_oci_shutdown_globals);
                   1194: #endif
                   1195:        REGISTER_INI_ENTRIES();
                   1196: 
                   1197:        le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number);
                   1198:        le_connection = zend_register_list_destructors_ex(php_oci_connection_list_dtor, NULL, "oci8 connection", module_number);
                   1199:        le_pconnection = zend_register_list_destructors_ex(php_oci_pconnection_list_np_dtor, php_oci_pconnection_list_dtor, "oci8 persistent connection", module_number);
                   1200:        le_psessionpool = zend_register_list_destructors_ex(NULL, php_oci_spool_list_dtor, "oci8 persistent session pool", module_number);
                   1201:        le_descriptor = zend_register_list_destructors_ex(php_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
                   1202:        le_collection = zend_register_list_destructors_ex(php_oci_collection_list_dtor, NULL, "oci8 collection", module_number);
                   1203: 
                   1204:        INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions);
                   1205:        INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions);
                   1206: 
                   1207:        oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry TSRMLS_CC);
                   1208:        oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry TSRMLS_CC);
                   1209: 
                   1210: /* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
                   1211:        REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
                   1212:        REGISTER_LONG_CONSTANT("OCI_SYSOPER",OCI_SYSOPER, CONST_CS | CONST_PERSISTENT);
                   1213:        REGISTER_LONG_CONSTANT("OCI_SYSDBA",OCI_SYSDBA, CONST_CS | CONST_PERSISTENT);
                   1214:        REGISTER_LONG_CONSTANT("OCI_CRED_EXT",PHP_OCI_CRED_EXT, CONST_CS | CONST_PERSISTENT);
                   1215:        REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
                   1216:        REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
                   1217:        REGISTER_LONG_CONSTANT("OCI_NO_AUTO_COMMIT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
                   1218:        REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
                   1219: 
                   1220: /* for $LOB->seek() */
                   1221:        REGISTER_LONG_CONSTANT("OCI_SEEK_SET",PHP_OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
                   1222:        REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",PHP_OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
                   1223:        REGISTER_LONG_CONSTANT("OCI_SEEK_END",PHP_OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
                   1224: 
                   1225: /*     for $LOB->flush() */
                   1226:        REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
                   1227: 
                   1228: /* for OCIBindByName (real "oci" names + short "php" names */
                   1229:        REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
                   1230:        REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
                   1231:        REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
                   1232:        REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
                   1233:        REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
                   1234:        REGISTER_LONG_CONSTANT("SQLT_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
                   1235:        REGISTER_LONG_CONSTANT("SQLT_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
                   1236:        REGISTER_LONG_CONSTANT("SQLT_RSET",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
                   1237:        REGISTER_LONG_CONSTANT("SQLT_AFC",SQLT_AFC, CONST_CS | CONST_PERSISTENT);
                   1238:        REGISTER_LONG_CONSTANT("SQLT_CHR",SQLT_CHR, CONST_CS | CONST_PERSISTENT);
                   1239:        REGISTER_LONG_CONSTANT("SQLT_VCS",SQLT_VCS, CONST_CS | CONST_PERSISTENT);
                   1240:        REGISTER_LONG_CONSTANT("SQLT_AVC",SQLT_AVC, CONST_CS | CONST_PERSISTENT);
                   1241:        REGISTER_LONG_CONSTANT("SQLT_STR",SQLT_STR, CONST_CS | CONST_PERSISTENT);
                   1242:        REGISTER_LONG_CONSTANT("SQLT_LVC",SQLT_LVC, CONST_CS | CONST_PERSISTENT);
                   1243:        REGISTER_LONG_CONSTANT("SQLT_FLT",SQLT_FLT, CONST_CS | CONST_PERSISTENT);
                   1244:        REGISTER_LONG_CONSTANT("SQLT_UIN",SQLT_UIN, CONST_CS | CONST_PERSISTENT);
                   1245:        REGISTER_LONG_CONSTANT("SQLT_LNG",SQLT_LNG, CONST_CS | CONST_PERSISTENT);
                   1246:        REGISTER_LONG_CONSTANT("SQLT_LBI",SQLT_LBI, CONST_CS | CONST_PERSISTENT);
                   1247:        REGISTER_LONG_CONSTANT("SQLT_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
                   1248:        REGISTER_LONG_CONSTANT("SQLT_ODT",SQLT_ODT, CONST_CS | CONST_PERSISTENT);
                   1249: #if defined(HAVE_OCI_INSTANT_CLIENT) || (defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 10)
                   1250:        REGISTER_LONG_CONSTANT("SQLT_BDOUBLE",SQLT_BDOUBLE, CONST_CS | CONST_PERSISTENT);
                   1251:        REGISTER_LONG_CONSTANT("SQLT_BFLOAT",SQLT_BFLOAT, CONST_CS | CONST_PERSISTENT);
                   1252: #endif
                   1253: 
                   1254:        REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
                   1255:        REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
                   1256:        REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE", CONST_CS | CONST_PERSISTENT);
                   1257: 
                   1258:        REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
                   1259:        REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
                   1260:        REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
                   1261:        REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
                   1262:        REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
                   1263:        REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
                   1264:        REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
                   1265:        REGISTER_LONG_CONSTANT("OCI_B_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
                   1266:        REGISTER_LONG_CONSTANT("OCI_B_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
                   1267: 
                   1268: /* for OCIFetchStatement */
                   1269:        REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", PHP_OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
                   1270:        REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", PHP_OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
                   1271: 
                   1272: /* for OCIFetchInto & OCIResult */
                   1273:        REGISTER_LONG_CONSTANT("OCI_ASSOC",PHP_OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
                   1274:        REGISTER_LONG_CONSTANT("OCI_NUM",PHP_OCI_NUM, CONST_CS | CONST_PERSISTENT);
                   1275:        REGISTER_LONG_CONSTANT("OCI_BOTH",PHP_OCI_BOTH, CONST_CS | CONST_PERSISTENT);
                   1276:        REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",PHP_OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
                   1277:        REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",PHP_OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
                   1278: 
                   1279: /* for OCINewDescriptor (real "oci" names + short "php" names */
                   1280:        REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
                   1281:        REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
                   1282:        REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
                   1283: 
                   1284:        REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
                   1285:        REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
                   1286:        REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
                   1287: 
                   1288: /* for OCIWriteTemporaryLob */
                   1289:        REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
                   1290:        REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
                   1291: 
                   1292:        return SUCCESS;
                   1293: }
                   1294: 
                   1295: PHP_RINIT_FUNCTION(oci)
                   1296: {
                   1297:        OCI_G(debug_mode) = 0; /* start "fresh" */
                   1298:        OCI_G(num_links) = OCI_G(num_persistent);
                   1299:        OCI_G(errcode) = 0;
                   1300:        OCI_G(edition) = NULL;
                   1301: 
                   1302:        return SUCCESS;
                   1303: }
                   1304: 
                   1305: PHP_MSHUTDOWN_FUNCTION(oci)
                   1306: {
                   1307: /* Work around PHP_GSHUTDOWN_FUNCTION not being called in older versions of PHP */
                   1308: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) || (PHP_MAJOR_VERSION < 5)
                   1309: #ifndef ZTS
                   1310:        php_oci_cleanup_global_handles(TSRMLS_C);
                   1311: #endif
                   1312: #endif
                   1313: 
                   1314:        OCI_G(shutdown) = 1;
                   1315: 
                   1316:        UNREGISTER_INI_ENTRIES();
                   1317: 
                   1318:        return SUCCESS;
                   1319: }
                   1320: 
                   1321: PHP_RSHUTDOWN_FUNCTION(oci)
                   1322: {
                   1323:        /* Check persistent connections and do the necessary actions if needed. If persistent_helper is
                   1324:         * unable to process a pconnection because of a refcount, the processing would happen from
                   1325:         * np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
                   1326:         */
                   1327:        zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
                   1328: 
                   1329:        if (OCI_G(edition)) {
                   1330:                efree(OCI_G(edition));
                   1331:        }
                   1332: 
                   1333:        return SUCCESS;
                   1334: }
                   1335: 
                   1336: PHP_MINFO_FUNCTION(oci)
                   1337: {
                   1338:        char buf[32];
                   1339:        char *ver;
                   1340: 
                   1341:        php_info_print_table_start();
                   1342:        php_info_print_table_row(2, "OCI8 Support", "enabled");
                   1343:        php_info_print_table_row(2, "Version", PHP_OCI8_VERSION);
1.1.1.2 ! misho    1344:        php_info_print_table_row(2, "Revision", "$Id: bf2eaf558b050b6d2e6d098bed6345af7e842ea4 $");
1.1       misho    1345: 
                   1346:        snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent));
                   1347:        php_info_print_table_row(2, "Active Persistent Connections", buf);
                   1348:        snprintf(buf, sizeof(buf), "%ld", OCI_G(num_links));
                   1349:        php_info_print_table_row(2, "Active Connections", buf);
                   1350: 
                   1351: #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
                   1352:        php_oci_client_get_version(&ver TSRMLS_CC);
                   1353:        php_info_print_table_row(2, "Oracle Run-time Client Library Version", ver);
                   1354:        efree(ver);
                   1355: #endif
                   1356: #if    defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
                   1357:        snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
                   1358: #elif defined(PHP_OCI8_ORACLE_VERSION)
                   1359:        snprintf(buf, sizeof(buf), "%s", PHP_OCI8_ORACLE_VERSION);
                   1360: #else
                   1361:        snprintf(buf, sizeof(buf), "Unknown");
                   1362: #endif
                   1363: #if defined(HAVE_OCI_INSTANT_CLIENT)
                   1364:        php_info_print_table_row(2, "Oracle Instant Client Version", buf);
                   1365: #else
                   1366:        php_info_print_table_row(2, "Oracle Version", buf);
                   1367: #endif
                   1368: 
                   1369: #if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
                   1370: #if defined(PHP_OCI8_DEF_DIR)
                   1371:        php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
                   1372: #endif
                   1373: #if defined(PHP_OCI8_DEF_SHARED_LIBADD)
                   1374:        php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
                   1375: #endif
                   1376: #endif
                   1377: 
                   1378:        php_info_print_table_row(2, "Temporary Lob support", "enabled");
                   1379:        php_info_print_table_row(2, "Collections support", "enabled");
                   1380:        php_info_print_table_end();
                   1381:        DISPLAY_INI_ENTRIES();
                   1382: }
                   1383: /* }}} */
                   1384: 
                   1385: /* list destructors {{{ */
                   1386: 
                   1387: /* {{{ php_oci_connection_list_dtor()
                   1388:  *
                   1389:  * Non-persistent connection destructor
                   1390:  */
                   1391: static void php_oci_connection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
                   1392: {
                   1393:        php_oci_connection *connection = (php_oci_connection *)entry->ptr;
                   1394: 
                   1395:        if (connection) {
                   1396:                php_oci_connection_close(connection TSRMLS_CC);
                   1397:                OCI_G(num_links)--;
                   1398:        }
                   1399: } /* }}} */
                   1400: 
                   1401: /* {{{ php_oci_pconnection_list_dtor()
                   1402:  *
                   1403:  * Persistent connection destructor
                   1404:  */
                   1405: static void php_oci_pconnection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
                   1406: {
                   1407:        php_oci_connection *connection = (php_oci_connection *)entry->ptr;
                   1408: 
                   1409:        if (connection) {
                   1410:                php_oci_connection_close(connection TSRMLS_CC);
                   1411:                OCI_G(num_persistent)--;
                   1412:                OCI_G(num_links)--;
                   1413:        }
                   1414: } /* }}} */
                   1415: 
                   1416: /* {{{ php_oci_pconnection_list_np_dtor()
                   1417:  *
                   1418:  * Non-Persistent destructor for persistent connection - This gets invoked when
                   1419:  * the refcount of this goes to zero in the regular list
                   1420:  */
                   1421: static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
                   1422: {
                   1423:        php_oci_connection *connection = (php_oci_connection *)entry->ptr;
                   1424:        zend_rsrc_list_entry *le;
                   1425: 
                   1426:        /*
                   1427:         * We cannot get connection as NULL or as a stub in this function. This is the function that
                   1428:         * turns a pconnection to a stub
                   1429:         *
                   1430:         * If oci_password_change() changed the password of a persistent connection, close the
                   1431:         * connection and remove it from the persistent connection cache.  This means subsequent scripts
                   1432:         * will be prevented from being able to present the old (now invalid) password to a usable
                   1433:         * connection to the database; they must use the new password.
                   1434:         *
                   1435:         * Check for conditions that warrant removal of the hash entry
                   1436:         */
                   1437: 
                   1438:        if (!connection->is_open ||
                   1439:                connection->passwd_changed ||
                   1440:                (PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
                   1441:                OCI_G(in_call)) {
                   1442: 
                   1443:                /* Remove the hash entry if present */
                   1444:                if ((zend_hash_find(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void **) &le)== SUCCESS) && (le->type == le_pconnection) && (le->ptr == connection)) {
                   1445:                        zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
                   1446:                }
                   1447:                else {
                   1448:                        php_oci_connection_close(connection TSRMLS_CC);
                   1449:                        OCI_G(num_persistent)--;
                   1450:                }
                   1451: 
                   1452:                if (OCI_G(debug_mode)) {
                   1453:                        php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
                   1454:                }
                   1455:        }
                   1456:        else {
                   1457:                /*
                   1458:                 * Release the connection to underlying pool.  We do this unconditionally so that
                   1459:                 * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
                   1460:                 * semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
                   1461:                 * takes the refcount to zero.
                   1462:                 *
                   1463:                 * If oci_old_close_semantics is set, we artifically bump up the refcount and decremented
                   1464:                 * only at request shutdown.
                   1465:                 */
                   1466:                php_oci_connection_release(connection TSRMLS_CC);
                   1467: 
                   1468:                if (OCI_G(debug_mode)) {
                   1469:                        php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
                   1470:                }
                   1471:        }
                   1472: } /* }}} */
                   1473: 
                   1474: /* {{{ php_oci_statement_list_dtor()
                   1475:  *
                   1476:  * Statement destructor
                   1477:  */
                   1478: static void php_oci_statement_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
                   1479: {
                   1480:        php_oci_statement *statement = (php_oci_statement *)entry->ptr;
                   1481:        php_oci_statement_free(statement TSRMLS_CC);
                   1482: } /* }}} */
                   1483: 
                   1484: /* {{{ php_oci_descriptor_list_dtor()
                   1485:  *
                   1486:  *     Descriptor destructor
                   1487:  */
                   1488: static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
                   1489: {
                   1490:        php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
                   1491:        php_oci_lob_free(descriptor TSRMLS_CC);
                   1492: } /* }}} */
                   1493: 
                   1494: /* {{{ php_oci_collection_list_dtor()
                   1495:  *
                   1496:  * Collection destructor
                   1497:  */
                   1498: static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
                   1499: {
                   1500:        php_oci_collection *collection = (php_oci_collection *)entry->ptr;
                   1501:        php_oci_collection_close(collection TSRMLS_CC);
                   1502: } /* }}} */
                   1503: 
                   1504: /* }}} */
                   1505: 
                   1506: /* Hash Destructors {{{ */
                   1507: 
                   1508: /* {{{ php_oci_define_hash_dtor()
                   1509:  *
                   1510:  * Define hash destructor
                   1511:  */
                   1512: void php_oci_define_hash_dtor(void *data)
                   1513: {
                   1514:        php_oci_define *define = (php_oci_define *) data;
                   1515: 
                   1516:        zval_ptr_dtor(&define->zval);
                   1517: 
                   1518:        if (define->name) {
                   1519:                efree(define->name);
                   1520:                define->name = NULL;
                   1521:        }
                   1522: }
                   1523: /* }}} */
                   1524: 
                   1525: /* {{{ php_oci_bind_hash_dtor()
                   1526:  *
                   1527:  * Bind hash destructor
                   1528:  */
                   1529: void php_oci_bind_hash_dtor(void *data)
                   1530: {
                   1531:        php_oci_bind *bind = (php_oci_bind *) data;
                   1532: 
                   1533:        if (bind->array.elements) {
                   1534:                efree(bind->array.elements);
                   1535:        }
                   1536: 
                   1537:        if (bind->array.element_lengths) {
                   1538:                efree(bind->array.element_lengths);
                   1539:        }
                   1540: 
                   1541:        if (bind->array.indicators) {
                   1542:                efree(bind->array.indicators);
                   1543:        }
                   1544: 
                   1545:        zval_ptr_dtor(&bind->zval);
                   1546: }
                   1547: /* }}} */
                   1548: 
                   1549: /* {{{ php_oci_column_hash_dtor()
                   1550:  *
                   1551:  * Column hash destructor
                   1552:  */
                   1553: void php_oci_column_hash_dtor(void *data)
                   1554: {
                   1555:        php_oci_out_column *column = (php_oci_out_column *) data;
                   1556:        TSRMLS_FETCH();
                   1557: 
                   1558:        if (column->stmtid) {
                   1559:                zend_list_delete(column->stmtid);
                   1560:        }
                   1561: 
                   1562:        if (column->is_descr) {
                   1563:                zend_list_delete(column->descid);
                   1564:        }
                   1565: 
                   1566:        if (column->data) {
                   1567:                efree(column->data);
                   1568:        }
                   1569: 
                   1570:        if (column->name) {
                   1571:                efree(column->name);
                   1572:        }
                   1573: }
                   1574: /* }}} */
                   1575: 
                   1576: /* {{{ php_oci_descriptor_flush_hash_dtor()
                   1577:  *
                   1578:  * Flush descriptors on commit
                   1579:  */
                   1580: void php_oci_descriptor_flush_hash_dtor(void *data)
                   1581: {
                   1582:        php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
                   1583:        TSRMLS_FETCH();
                   1584: 
                   1585:        if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
                   1586:                php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
                   1587:                descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
                   1588:        }
                   1589:        data = NULL;
                   1590: }
                   1591: /* }}} */
                   1592: 
                   1593: /* }}} */
                   1594: 
                   1595: /* {{{ php_oci_connection_descriptors_free()
                   1596:  *
                   1597:  * Free descriptors for a connection
                   1598:  */
                   1599: void php_oci_connection_descriptors_free(php_oci_connection *connection TSRMLS_DC)
                   1600: {
                   1601:        zend_hash_destroy(connection->descriptors);
                   1602:        efree(connection->descriptors);
                   1603:        connection->descriptors = NULL;
                   1604:        connection->descriptor_count = 0;
                   1605: }
                   1606: /* }}} */
                   1607: 
                   1608: 
                   1609: /* {{{ php_oci_error()
                   1610:  *
                   1611:  * Fetch & print out error message if we get an error
                   1612:  * Returns an Oracle error number
                   1613:  */
                   1614: sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC)
                   1615: {
                   1616:        text *errbuf = (text *)NULL;
                   1617:        sb4 errcode = 0;
                   1618: 
                   1619:        switch (status) {
                   1620:                case OCI_SUCCESS:
                   1621:                        break;
                   1622:                case OCI_SUCCESS_WITH_INFO:
                   1623:                        errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
                   1624:                        if (errbuf) {
                   1625:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
                   1626:                                efree(errbuf);
                   1627:                        } else {
                   1628:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
                   1629:                        }
                   1630:                        break;
                   1631:                case OCI_NEED_DATA:
                   1632:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NEED_DATA");
                   1633:                        break;
                   1634:                case OCI_NO_DATA:
                   1635:                        errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
                   1636:                        if (errbuf) {
                   1637:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
                   1638:                                efree(errbuf);
                   1639:                        } else {
                   1640:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
                   1641:                        }
                   1642:                        break;
                   1643:                case OCI_ERROR:
                   1644:                        errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
                   1645:                        if (errbuf) {
                   1646:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
                   1647:                                efree(errbuf);
                   1648:                        } else {
                   1649:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to fetch error message");
                   1650:                        }
                   1651:                        break;
                   1652:                case OCI_INVALID_HANDLE:
                   1653:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_INVALID_HANDLE");
                   1654:                        break;
                   1655:                case OCI_STILL_EXECUTING:
                   1656:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_STILL_EXECUTING");
                   1657:                        break;
                   1658:                case OCI_CONTINUE:
                   1659:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CONTINUE");
                   1660:                        break;
                   1661:                default:
                   1662:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown OCI error code: %d", status);
                   1663:                        break;
                   1664:        }
                   1665:        return errcode;
                   1666: }
                   1667: /* }}} */
                   1668: 
                   1669: /* {{{ php_oci_fetch_errmsg()
                   1670:  *
                   1671:  * Fetch error message into the buffer from the error handle provided
                   1672:  */
                   1673: sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC)
                   1674: {
                   1675:        sb4 error_code = 0;
                   1676:        text err_buf[PHP_OCI_ERRBUF_LEN];
                   1677: 
                   1678:        memset(err_buf, 0, sizeof(err_buf));
                   1679:        PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, err_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR));
                   1680: 
                   1681:        if (error_code) {
                   1682:                int err_buf_len = strlen((char *)err_buf);
                   1683: 
                   1684:                if (err_buf_len && err_buf[err_buf_len - 1] == '\n') {
                   1685:                        err_buf[err_buf_len - 1] = '\0';
                   1686:                }
                   1687:                if (err_buf_len && error_buf) {
                   1688:                        *error_buf = NULL;
                   1689:                        *error_buf = (text *)estrndup((char *)err_buf, err_buf_len);
                   1690:                }
                   1691:        }
                   1692:        return error_code;
                   1693: } /* }}} */
                   1694: 
                   1695: /* {{{ php_oci_fetch_sqltext_offset()
                   1696:  *
                   1697:  * Compute offset in the SQL statement
                   1698:  */
                   1699: int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset TSRMLS_DC)
                   1700: {
                   1701:        sword errstatus;
                   1702: 
                   1703:        *sqltext = NULL;
                   1704:        *error_offset = 0;
                   1705:        PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
                   1706: 
                   1707:        if (errstatus != OCI_SUCCESS) {
                   1708:                statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
                   1709:                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
                   1710:                return 1;
                   1711:        }
                   1712: 
                   1713:        PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
                   1714: 
                   1715:        if (errstatus != OCI_SUCCESS) {
                   1716:                statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
                   1717:                PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
                   1718:                return 1;
                   1719:        }
                   1720:        return 0;
                   1721: } /* }}} */
                   1722: 
                   1723: /* {{{ php_oci_do_connect()
                   1724:  *
                   1725:  * Connect wrapper
                   1726:  */
                   1727: void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
                   1728: {
                   1729:        php_oci_connection *connection;
                   1730:        char *username, *password;
                   1731:        char *dbname = NULL, *charset = NULL;
                   1732:        int username_len = 0, password_len = 0;
                   1733:        int dbname_len = 0, charset_len = 0;
                   1734:        long session_mode = OCI_DEFAULT;
                   1735: 
                   1736:        /* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
                   1737:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ssl", &username, &username_len, &password, &password_len, &dbname, &dbname_len, &charset, &charset_len, &session_mode) == FAILURE) {
                   1738:                return;
                   1739:        }
                   1740: 
                   1741:        if (!charset_len) {
                   1742:                charset = NULL;
                   1743:        }
                   1744: 
                   1745:        connection = php_oci_do_connect_ex(username, username_len, password, password_len, NULL, 0, dbname, dbname_len, charset, session_mode, persistent, exclusive TSRMLS_CC);
                   1746: 
                   1747:        if (!connection) {
                   1748:                RETURN_FALSE;
                   1749:        }
                   1750:        RETURN_RESOURCE(connection->rsrc_id);
                   1751: 
                   1752: } /* }}} */
                   1753: 
                   1754: /* {{{ php_oci_do_connect_ex()
                   1755:  *
                   1756:  * The real connect function. Allocates all the resources needed, establishes the connection and
                   1757:  * returns the result handle (or NULL)
                   1758:  */
                   1759: php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC)
                   1760: {
                   1761:        zend_rsrc_list_entry *le;
                   1762:        zend_rsrc_list_entry new_le;
                   1763:        php_oci_connection *connection = NULL;
                   1764:        smart_str hashed_details = {0};
                   1765:        time_t timestamp;
                   1766:        php_oci_spool *session_pool = NULL;
                   1767:        zend_bool use_spool = 1;           /* Default is to use client-side session pool */
                   1768:        zend_bool ping_done = 0;
                   1769: 
                   1770:        ub2 charsetid = 0;
                   1771:        ub2 charsetid_nls_lang = 0;
                   1772: 
                   1773:        if (session_mode & ~(OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
                   1774:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid session mode specified (%ld)", session_mode);
                   1775:                return NULL;
                   1776:        }
                   1777:        if (session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
                   1778:                if ((session_mode & OCI_SYSOPER) && (session_mode & OCI_SYSDBA)) {
                   1779:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SYSDBA and OCI_SYSOPER cannot be used together");
                   1780:                        return NULL;
                   1781:                }
                   1782:                if (session_mode & PHP_OCI_CRED_EXT) {
                   1783: #ifdef PHP_WIN32
                   1784:                        /* Disable external authentication on Windows as Impersonation is not yet handled.
                   1785:                         * TODO: Re-enable this once OCI provides capability.
                   1786:                         */
                   1787:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "External Authentication is not supported on Windows");
                   1788:                        return NULL;
                   1789: #endif
                   1790:                        if (username_len != 1 || username[0] != '/' || password_len != 0) {
                   1791:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CRED_EXT can only be used with a username of \"/\" and a NULL password");
                   1792:                                return NULL;
                   1793:                        }
                   1794:                }
                   1795:                if (session_mode & (OCI_SYSOPER | OCI_SYSDBA)) {
                   1796:                        /* Increase security by not caching privileged oci_pconnect() connections. The
                   1797:                         * connection becomes equivalent to oci_connect() or oci_new_connect().
                   1798:                         */
                   1799:                        persistent = 0;
                   1800:                        if (!OCI_G(privileged_connect)) {
                   1801:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
                   1802:                                return NULL;
                   1803:                        }
                   1804: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
                   1805:                        /* Safe mode has been removed in PHP 5.4 */
                   1806:                        if (PG(safe_mode)) {
                   1807:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled in Safe Mode");
                   1808:                                return NULL;
                   1809:                        }
                   1810: #endif
                   1811:                }
                   1812:        }
                   1813: 
                   1814:        /* Initialize global handles if they weren't initialized before */
                   1815:        if (OCI_G(env) == NULL) {
                   1816:                php_oci_init_global_handles(TSRMLS_C);
                   1817:                if (OCI_G(env) == NULL) {
                   1818:                        return NULL;
                   1819:                }
                   1820:        }
                   1821: 
                   1822:        /* We cannot use the new session create logic (OCISessionGet from
                   1823:         * client-side session pool) when privileged connect or password
                   1824:         * change is attempted or OCI_CRED_EXT mode is specified.
                   1825:         * TODO: Re-enable this when OCI provides support.
                   1826:         */
                   1827:        if ((session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) || (new_password_len)) {
                   1828:                use_spool = 0;
                   1829:        }
                   1830: 
                   1831:        smart_str_appendl_ex(&hashed_details, "oci8***", sizeof("oci8***") - 1, 0);
                   1832:        smart_str_appendl_ex(&hashed_details, username, username_len, 0);
                   1833:        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
                   1834: 
                   1835:        /* DRCP: connection_class is an attribute of a connection */
                   1836:        if (OCI_G(connection_class)){
                   1837:                smart_str_appendl_ex(&hashed_details, OCI_G(connection_class), strlen(OCI_G(connection_class)), 0);
                   1838:        }
                   1839:        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
                   1840: 
                   1841:        /* Add edition attribute to the hash */
                   1842:        if (OCI_G(edition)){
                   1843:                smart_str_appendl_ex(&hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
                   1844:        }
                   1845:        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
                   1846: 
                   1847:        if (password_len) {
                   1848:                ulong password_hash;
                   1849:                password_hash = zend_inline_hash_func(password, password_len);
                   1850:                smart_str_append_unsigned_ex(&hashed_details, password_hash, 0);
                   1851:        }
                   1852:        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
                   1853: 
                   1854:        if (dbname) {
                   1855:                smart_str_appendl_ex(&hashed_details, dbname, dbname_len, 0);
                   1856:        }
                   1857:        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
                   1858: 
                   1859:        if (charset && *charset) {
                   1860:                PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
                   1861:                if (!charsetid) {
                   1862:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid character set name: %s", charset);
                   1863:                } else {
                   1864:                        smart_str_append_unsigned_ex(&hashed_details, charsetid, 0);
                   1865:                }
                   1866:        }
                   1867: 
                   1868:        /* use NLS_LANG if no or invalid charset specified */
                   1869:        if (!charsetid) {
                   1870:                size_t rsize = 0;
                   1871:                sword result;
                   1872: 
                   1873:                PHP_OCI_CALL_RETURN(result, OCINlsEnvironmentVariableGet, (&charsetid_nls_lang, 0, OCI_NLS_CHARSET_ID, 0, &rsize));
                   1874:                if (result != OCI_SUCCESS) {
                   1875:                        charsetid_nls_lang = 0;
                   1876:                }
                   1877:                smart_str_append_unsigned_ex(&hashed_details, charsetid_nls_lang, 0);
                   1878:        }
                   1879: 
                   1880:        timestamp = time(NULL);
                   1881: 
                   1882:        smart_str_append_unsigned_ex(&hashed_details, session_mode, 0);
                   1883:        smart_str_0(&hashed_details);
                   1884: 
                   1885:        /* make it lowercase */
                   1886:        php_strtolower(hashed_details.c, hashed_details.len);
                   1887: 
                   1888:        if (!exclusive && !new_password) {
                   1889:                zend_bool found = 0;
                   1890: 
                   1891:                if (persistent && zend_hash_find(&EG(persistent_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
                   1892:                        found = 1;
                   1893:                        /* found */
                   1894:                        if (le->type == le_pconnection) {
                   1895:                                connection = (php_oci_connection *)le->ptr;
                   1896:                        }
                   1897:                } else if (!persistent && zend_hash_find(&EG(regular_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
                   1898:                        found = 1;
                   1899:                        if (le->type == le_index_ptr) {
                   1900:                                int type, link;
                   1901:                                void *ptr;
                   1902: 
                   1903:                                link = OCI8_PTR_TO_INT(le->ptr);
                   1904:                                ptr = zend_list_find(link,&type);
                   1905:                                if (ptr && (type == le_connection)) {
                   1906:                                        connection = (php_oci_connection *)ptr;
                   1907:                                }
                   1908:                        }
                   1909:                }
                   1910: 
                   1911:                /* Debug statements {{{ */
                   1912:                if (OCI_G(debug_mode)) {
                   1913:                        if (connection && connection->is_stub) {
                   1914:                                php_printf ("OCI8 DEBUG L1: Got a cached stub: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
                   1915:                        } else if (connection) {
                   1916:                                php_printf ("OCI8 DEBUG L1: Got a cached connection: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
                   1917:                        } else {
                   1918:                                php_printf ("OCI8 DEBUG L1: Got NO cached connection at (%s:%d) \n", __FILE__, __LINE__);
                   1919:                        }
                   1920:                } /* }}} */
                   1921: 
                   1922:                /* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its
                   1923:                 * private spool A connection is a stub if it is only a cached structure and the real
                   1924:                 * connection is released to its underlying private session pool.  We currently do not have
                   1925:                 * stub support for non-persistent conns.
                   1926:                 *
                   1927:                 * TODO: put in negative code for non-persistent stubs
                   1928:                 */
                   1929:                if (connection && connection->is_persistent && connection->is_stub) {
                   1930:                        if (php_oci_create_session(connection, NULL, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
                   1931:                                smart_str_free_ex(&hashed_details, 0);
                   1932:                                zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
                   1933: 
                   1934:                                return NULL;
                   1935:                        }
                   1936:                        /* We do the ping in php_oci_create_session, no need to ping again below */
                   1937:                        ping_done = 1;
                   1938:                }
                   1939: 
                   1940:                if (connection) {
                   1941:                        if (connection->is_open) {
                   1942:                                /* found an open connection. now ping it */
                   1943:                                if (connection->is_persistent) {
                   1944:                                        int rsrc_type;
                   1945: 
                   1946:                                        /* Check connection liveness in the following order:
                   1947:                                         * 1) always check OCI_ATTR_SERVER_STATUS
                   1948:                                         * 2) see if it's time to ping it
                   1949:                                         * 3) ping it if needed
                   1950:                                         */
                   1951:                                        if (php_oci_connection_status(connection TSRMLS_CC)) {
                   1952:                                                /* Only ping if:
                   1953:                                                 *
                   1954:                                                 * 1) next_ping > 0, which means that ping_interval is not -1 (aka "Off")
                   1955:                                                 *
                   1956:                                                 * 2) current_timestamp > next_ping, which means "it's time to check if it's
                   1957:                                                 * still alive"
                   1958:                                                 */
                   1959:                                                if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection TSRMLS_CC)) {
                   1960:                                                        /* server died */
                   1961:                                                } else {
                   1962:                                                        php_oci_connection *tmp;
                   1963: 
                   1964:                                                        /* okay, the connection is open and the server is still alive */
                   1965:                                                        connection->used_this_request = 1;
                   1966:                                                        tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type);
                   1967: 
                   1968:                                                        if (tmp != NULL && rsrc_type == le_pconnection && strlen(tmp->hash_key) == hashed_details.len &&
                   1969:                                                                memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) {
                   1970:                                                                /* do nothing */
                   1971:                                                        } else {
                   1972: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
                   1973:                                                                connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC);
                   1974: #else
                   1975:                                                                connection->rsrc_id = zend_list_insert(connection, le_pconnection);
                   1976: #endif
                   1977:                                                                /* Persistent connections: For old close semantics we artificially
                   1978:                                                                 * bump up the refcount to prevent the non-persistent destructor
                   1979:                                                                 * from getting called until request shutdown. The refcount is
                   1980:                                                                 * decremented in the persistent helper
                   1981:                                                                 */
                   1982:                                                                if (OCI_G(old_oci_close_semantics)) {
                   1983:                                                                        zend_list_addref(connection->rsrc_id);
                   1984:                                                                }
                   1985:                                                        }
                   1986:                                                        smart_str_free_ex(&hashed_details, 0);
                   1987:                                                        return connection;
                   1988:                                                }
                   1989:                                        }
                   1990:                                        /* server died */
                   1991:                                } else {
                   1992:                                        /* we do not ping non-persistent connections */
                   1993:                                        smart_str_free_ex(&hashed_details, 0);
                   1994:                                        zend_list_addref(connection->rsrc_id);
                   1995:                                        return connection;
                   1996:                                }
                   1997:                        } /* is_open is true? */
                   1998: 
                   1999:                        /* Server died - connection not usable. The is_open=true can also fall through to here,
                   2000:                         * if ping fails
                   2001:                         */
                   2002:                        if (persistent){
                   2003:                                int rsrc_type;
                   2004: 
                   2005:                                connection->is_open = 0;
                   2006:                                connection->used_this_request = 1;
                   2007: 
                   2008:                                /* We have to do a hash_del but need to preserve the resource if there is a positive
                   2009:                                 * refcount. Set the data pointer in the list entry to NULL
                   2010:                                 */
                   2011:                                if (connection == zend_list_find(connection->rsrc_id, &rsrc_type) && rsrc_type == le_pconnection) {
                   2012:                                        le->ptr = NULL;
                   2013:                                }
                   2014: 
                   2015:                                zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
                   2016:                        } else {
                   2017:                                /* We only remove the hash entry. The resource and the list entry with its pointer
                   2018:                                 * to the resource are still intact
                   2019:                                 */
                   2020:                                zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
                   2021:                        }
                   2022: 
                   2023:                        connection = NULL;
                   2024:                } else if (found) {
                   2025:                        /* found something, but it's not a connection, delete it */
                   2026:                        if (persistent) {
                   2027:                                zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
                   2028:                        } else {
                   2029:                                zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
                   2030:                        }
                   2031:                }
                   2032:        }
                   2033: 
                   2034:        /* Check if we have reached max_persistent. If so, try to remove a few timed-out connections. As
                   2035:         * a last resort, return a non-persistent connection.
                   2036:         */
                   2037:        if (persistent) {
                   2038:                zend_bool alloc_non_persistent = 0;
                   2039: 
                   2040:                if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
                   2041:                        /* try to find an idle connection and kill it */
                   2042:                        zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
                   2043: 
                   2044:                        if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
                   2045:                                /* all persistent connactions are in use, fallback to non-persistent connection creation */
                   2046:                                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Too many open persistent connections (%ld)", OCI_G(num_persistent));
                   2047:                                alloc_non_persistent = 1;
                   2048:                        }
                   2049:                }
                   2050: 
                   2051:                if (alloc_non_persistent) {
                   2052:                        connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
                   2053:                        connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
                   2054:                        connection->is_persistent = 0;
                   2055:                } else {
                   2056:                        connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
                   2057:                        if (connection == NULL) {
                   2058:                                return NULL;
                   2059:                        }
                   2060:                        connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
                   2061:                        if (connection->hash_key == NULL) {
                   2062:                                free(connection);
                   2063:                                return NULL;
                   2064:                        }
                   2065:                        connection->is_persistent = 1;
                   2066:                }
                   2067:        } else {
                   2068:                connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
                   2069:                connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
                   2070:                connection->is_persistent = 0;
                   2071:        }
                   2072: 
                   2073:        /* {{{ Get the session pool that suits this connection request from the persistent list. This
                   2074:         * step is only for non-persistent connections as persistent connections have private session
                   2075:         * pools. Non-persistent conns use shared session pool to allow for optimizations such as
                   2076:         * caching the physical connection (for DRCP) even when the non-persistent php connection is
                   2077:         * destroyed.
                   2078:         *
                   2079:         * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
                   2080:         */
                   2081:        if (use_spool && !connection->is_persistent) {
                   2082:                if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang TSRMLS_CC))==NULL)
                   2083:                {
                   2084:                        php_oci_connection_close(connection TSRMLS_CC);
                   2085:                        smart_str_free_ex(&hashed_details, 0);
                   2086:                        return NULL;
                   2087:                }
                   2088:        } /* }}} */
                   2089: 
                   2090:        connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
                   2091: 
                   2092:        /* Mark password as unchanged by PHP during the duration of the database session */
                   2093:        connection->passwd_changed = 0;
                   2094: 
                   2095:        smart_str_free_ex(&hashed_details, 0);
                   2096: 
                   2097:        if (charsetid) {
                   2098:                connection->charset = charsetid;
                   2099:        } else {
                   2100:                connection->charset = charsetid_nls_lang;
                   2101:        }
                   2102: 
                   2103:        /* Old session creation semantics when session pool cannot be used Eg: privileged
                   2104:         * connect/password change
                   2105:         */
                   2106:        if (!use_spool) {
                   2107:                if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
                   2108:                        php_oci_connection_close(connection TSRMLS_CC);
                   2109:                        return NULL;
                   2110:                }
                   2111:        } else {
                   2112:                /* create using the client-side session pool */
                   2113:                if (php_oci_create_session(connection, session_pool, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
                   2114:                        php_oci_connection_close(connection TSRMLS_CC);
                   2115:                        return NULL;
                   2116:                }
                   2117:        }
                   2118: 
                   2119:        /* Mark it as open */
                   2120:        connection->is_open = 1;
                   2121: 
                   2122:        /* add to the appropriate hash */
                   2123:        if (connection->is_persistent) {
                   2124:                new_le.ptr = connection;
                   2125:                new_le.type = le_pconnection;
                   2126:                connection->used_this_request = 1;
                   2127: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
                   2128:                connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC);
                   2129: #else
                   2130:                connection->rsrc_id = zend_list_insert(connection, le_pconnection);
                   2131: #endif
                   2132: 
                   2133:                /* Persistent connections: For old close semantics we artificially bump up the refcount to
                   2134:                 * prevent the non-persistent destructor from getting called until request shutdown. The
                   2135:                 * refcount is decremented in the persistent helper
                   2136:                 */
                   2137:                if (OCI_G(old_oci_close_semantics)) {
                   2138:                        zend_list_addref(connection->rsrc_id);
                   2139:                }
                   2140:                zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
                   2141:                OCI_G(num_persistent)++;
                   2142:                OCI_G(num_links)++;
                   2143:        } else if (!exclusive) {
                   2144: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
                   2145:                connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC);
                   2146: #else
                   2147:                connection->rsrc_id = zend_list_insert(connection, le_connection);
                   2148: #endif
                   2149:                new_le.ptr = OCI8_INT_TO_PTR(connection->rsrc_id);
                   2150:                new_le.type = le_index_ptr;
                   2151:                zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
                   2152:                OCI_G(num_links)++;
                   2153:        } else {
                   2154: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
                   2155:                connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC);
                   2156: #else
                   2157:                connection->rsrc_id = zend_list_insert(connection, le_connection);
                   2158: #endif
                   2159:                OCI_G(num_links)++;
                   2160:        }
                   2161: 
                   2162:        /* Debug statements {{{ */
                   2163:        if (OCI_G(debug_mode)) {
                   2164:                if (connection->is_persistent) {
                   2165:                        php_printf ("OCI8 DEBUG L1: New Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
                   2166:                } else {
                   2167:                        php_printf ("OCI8 DEBUG L1: New Non-Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
                   2168:                }
                   2169:                php_printf ("OCI8 DEBUG L1: num_persistent=(%ld), num_links=(%ld) at (%s:%d) \n", OCI_G(num_persistent), OCI_G(num_links), __FILE__, __LINE__);
                   2170:        } /* }}} */
                   2171: 
                   2172:        return connection;
                   2173: }
                   2174: /* }}} */
                   2175: 
                   2176: /* {{{ php_oci_connection_ping()
                   2177:  *
                   2178:  * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
                   2179:  */
                   2180: static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC)
                   2181: {
                   2182:        /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
                   2183:         * such as from Pre-10.1 servers, the error is still from the server and we would have
                   2184:         * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
                   2185:         * Pre-10.2 clients
                   2186:         */
                   2187: #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))      /* OCIPing available 10.2 onwards */
                   2188:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
                   2189: #else
                   2190:        char version[256];
                   2191:        /* use good old OCIServerVersion() */
                   2192:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
                   2193: #endif
                   2194: 
                   2195:        if (OCI_G(errcode) == OCI_SUCCESS) {
                   2196:                return 1;
                   2197:        } else {
                   2198:                sb4 error_code = 0;
                   2199:                text tmp_buf[OCI_ERROR_MAXMSG_SIZE];
                   2200: 
                   2201:                /* Treat ORA-1010 as a successful Ping */
                   2202:                OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ERROR);
                   2203:                if (error_code == 1010) {
                   2204:                        return 1;
                   2205:                }
                   2206:        }
                   2207: 
                   2208:        /* ignore errors here, just return failure
                   2209:         * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
                   2210:        return 0;
                   2211: }
                   2212: /* }}} */
                   2213: 
                   2214: /* {{{ php_oci_connection_status()
                   2215:  *
                   2216:  * Check connection status (pre-ping check)
                   2217:  */
                   2218: static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC)
                   2219: {
                   2220:        ub4 ss = 0;
                   2221: 
                   2222:        /* get OCI_ATTR_SERVER_STATUS */
                   2223:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err)));
                   2224: 
                   2225:        if (OCI_G(errcode) == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
                   2226:                return 1;
                   2227:        }
                   2228: 
                   2229:        /* ignore errors here, just return failure
                   2230:         * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
                   2231:        return 0;
                   2232: }
                   2233: /* }}} */
                   2234: 
                   2235: /* {{{ php_oci_connection_rollback()
                   2236:  *
                   2237:  * Rollback connection
                   2238:  */
                   2239: int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC)
                   2240: {
                   2241:        PHP_OCI_CALL_RETURN(connection->errcode, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
                   2242:        connection->needs_commit = 0;
                   2243: 
                   2244:        if (connection->errcode != OCI_SUCCESS) {
                   2245:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                   2246:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                   2247:                return 1;
                   2248:        }
                   2249:        return 0;
                   2250: } /* }}} */
                   2251: 
                   2252: /* {{{ php_oci_connection_commit()
                   2253:  *
                   2254:  * Commit connection
                   2255:  */
                   2256: int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
                   2257: {
                   2258:        PHP_OCI_CALL_RETURN(connection->errcode, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
                   2259:        connection->needs_commit = 0;
                   2260: 
                   2261:        if (connection->errcode != OCI_SUCCESS) {
                   2262:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                   2263:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                   2264:                return 1;
                   2265:        }
                   2266:        return 0;
                   2267: } /* }}} */
                   2268: 
                   2269: /* {{{ php_oci_connection_close()
                   2270:  *
                   2271:  * Close the connection and free all its resources
                   2272:  */
                   2273: static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
                   2274: {
                   2275:        int result = 0;
                   2276:        zend_bool in_call_save = OCI_G(in_call);
                   2277: 
                   2278:        if (!connection->is_stub) {
                   2279:                /* Release resources associated with connection */
                   2280:                php_oci_connection_release(connection TSRMLS_CC);
                   2281:        }
                   2282: 
                   2283:        if (!connection->using_spool && connection->svc) {
                   2284:                        PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
                   2285:        }
                   2286: 
                   2287:        if (connection->err) {
                   2288:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
                   2289:        }
                   2290:        if (connection->authinfo) {
                   2291:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->authinfo, (ub4) OCI_HTYPE_AUTHINFO));
                   2292:        }
                   2293: 
                   2294:        /* No Handlefrees for session pool connections */
                   2295:        if (!connection->using_spool) {
                   2296:                if (connection->session) {
                   2297:                        PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->session, OCI_HTYPE_SESSION));
                   2298:                }
                   2299: 
                   2300:                if (connection->is_attached) {
                   2301:                        PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
                   2302:                }
                   2303: 
                   2304:                if (connection->svc) {
                   2305:                        PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
                   2306:                }
                   2307: 
                   2308:                if (connection->server) {
                   2309:                        PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
                   2310:                }
                   2311: 
                   2312:                if (connection->env) {
                   2313:                        PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
                   2314:                }
                   2315:        } else if (connection->private_spool) {
                   2316:        /* Keep this as the last member to be freed, as there are dependencies
                   2317:         * (like env) on the session pool
                   2318:         */
                   2319:                php_oci_spool_close(connection->private_spool TSRMLS_CC);
                   2320:        }
                   2321: 
                   2322:        if (connection->is_persistent) {
                   2323:                if (connection->hash_key) {
                   2324:                        free(connection->hash_key);
                   2325:                }
                   2326:                free(connection);
                   2327:        } else {
                   2328:                if (connection->hash_key) {
                   2329:                        efree(connection->hash_key);
                   2330:                }
                   2331:                efree(connection);
                   2332:        }
                   2333:        connection = NULL;
                   2334:        OCI_G(in_call) = in_call_save;
                   2335:        return result;
                   2336: } /* }}} */
                   2337: 
                   2338: /* {{{ php_oci_connection_release()
                   2339:  *
                   2340:  * Release the connection's resources. This involves freeing descriptors and rolling back
                   2341:  * transactions, setting timeout-related parameters etc. For session-pool using connections, the
                   2342:  * underlying connection is released to its session pool.
                   2343:  */
                   2344: int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
                   2345: {
                   2346:        int result = 0;
                   2347:        zend_bool in_call_save = OCI_G(in_call);
                   2348:        time_t timestamp = time(NULL);
                   2349: 
                   2350:        if (connection->is_stub) {
                   2351:                return 0;
                   2352:        }
                   2353: 
                   2354:        if (connection->descriptors) {
                   2355:                php_oci_connection_descriptors_free(connection TSRMLS_CC);
                   2356:        }
                   2357: 
                   2358:        if (connection->svc) {
                   2359:                /* rollback outstanding transactions */
                   2360:                if (connection->needs_commit) {
                   2361:                        if (php_oci_connection_rollback(connection TSRMLS_CC)) {
                   2362:                                /* rollback failed */
                   2363:                                result = 1;
                   2364:                        }
                   2365:                }
                   2366:        }
                   2367: 
                   2368:        if (OCI_G(persistent_timeout) > 0) {
                   2369:                connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
                   2370:        }
                   2371: 
                   2372:        /* We may have half-cooked connections to clean up */
                   2373:        if (connection->next_pingp) {
                   2374:                if (OCI_G(ping_interval) >= 0) {
                   2375:                        *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
                   2376:                } else {
                   2377:                        /* ping_interval is -1 */
                   2378:                        *(connection->next_pingp) = 0;
                   2379:                }
                   2380:        }
                   2381: 
                   2382:        /* Release the session (stubs are filtered out at the beginning)*/
                   2383:        if (connection->using_spool) {
                   2384:                ub4 rlsMode = OCI_DEFAULT;
                   2385: 
                   2386:                if (result) {
                   2387:                        rlsMode |= OCI_SESSRLS_DROPSESS;
                   2388:                }
                   2389: 
                   2390:                /* Sessions for non-persistent connections should be dropped.  For 11 and above, the session
                   2391:                 * pool has its own mechanism for doing so for purity NEW connections. We need to do so
                   2392:                 * explicitly for 10.2 and earlier.
                   2393:                 */
                   2394: #if (!(OCI_MAJOR_VERSION >= 11))
                   2395:                if (!connection->is_persistent) {
                   2396:                        rlsMode |= OCI_SESSRLS_DROPSESS;
                   2397:                }
                   2398: #endif
                   2399: 
                   2400:                if (connection->svc) {
                   2401:                        PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
                   2402:                                                                                 0, rlsMode));
                   2403:                }
                   2404:                /* It no longer has relation with the database session. However authinfo and env are
                   2405:                 * cached
                   2406:                 */
                   2407:                connection->svc = NULL;
                   2408:                connection->server = NULL;
                   2409:                connection->session = NULL;
                   2410: 
                   2411:                connection->is_attached = connection->is_open = connection->needs_commit = connection->used_this_request = 0;
                   2412:                connection->is_stub = 1;
                   2413: 
                   2414:                /* Cut the link between the connection structure and the time_t structure allocated within
                   2415:                 * the OCI session
                   2416:                 */
                   2417:                connection->next_pingp = NULL;
                   2418:        }
                   2419: 
                   2420:        OCI_G(in_call) = in_call_save;
                   2421:        return result;
                   2422: } /* }}} */
                   2423: 
                   2424: /* {{{ php_oci_password_change()
                   2425:  *
                   2426:  * Change password for the user with the username given
                   2427:  */
                   2428: int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len TSRMLS_DC)
                   2429: {
                   2430:        PHP_OCI_CALL_RETURN(connection->errcode, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT));
                   2431: 
                   2432:        if (connection->errcode != OCI_SUCCESS) {
                   2433:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                   2434:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                   2435:                return 1;
                   2436:        }
                   2437:        connection->passwd_changed = 1;
                   2438:        return 0;
                   2439: } /* }}} */
                   2440: 
                   2441: 
                   2442: /* {{{ php_oci_client_get_version()
                   2443:  *
                   2444:  * Get Oracle client library version
                   2445:  */
                   2446: void php_oci_client_get_version(char **version TSRMLS_DC)
                   2447: {
                   2448:        char  version_buff[256];
                   2449:        sword major_version = 0;
                   2450:        sword minor_version = 0; 
                   2451:        sword update_num = 0;
                   2452:        sword patch_num = 0;
                   2453:        sword port_update_num = 0;
                   2454: 
                   2455: #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))      /* OCIClientVersion only available 10.2 onwards */
                   2456:        PHP_OCI_CALL(OCIClientVersion, (&major_version, &minor_version, &update_num, &patch_num, &port_update_num));
                   2457:        snprintf(version_buff, sizeof(version_buff), "%d.%d.%d.%d.%d", major_version, minor_version, update_num, patch_num, port_update_num);
                   2458: #else
                   2459:        memcpy(version_buff, "Unknown", sizeof("Unknown"));
                   2460: #endif
                   2461:        *version = estrdup(version_buff);
                   2462: } /* }}} */
                   2463: 
                   2464: 
                   2465: /* {{{ php_oci_server_get_version()
                   2466:  *
                   2467:  * Get Oracle server version
                   2468:  */
                   2469: int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
                   2470: {
                   2471:        char version_buff[256];
                   2472: 
                   2473:        PHP_OCI_CALL_RETURN(connection->errcode, OCIServerVersion, (connection->svc, connection->err, (text *)version_buff, sizeof(version_buff), OCI_HTYPE_SVCCTX));
                   2474: 
                   2475:        if (connection->errcode != OCI_SUCCESS) {
                   2476:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                   2477:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                   2478:                return 1;
                   2479:        }
                   2480: 
                   2481:        *version = estrdup(version_buff);
                   2482:        return 0;
                   2483: } /* }}} */
                   2484: 
                   2485: /* {{{ php_oci_column_to_zval()
                   2486:  *
                   2487:  * Convert php_oci_out_column struct into zval
                   2488:  */
                   2489: int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC)
                   2490: {
                   2491:        php_oci_descriptor *descriptor;
                   2492:        ub4 lob_length;
                   2493:        int column_size;
                   2494:        char *lob_buffer;
                   2495:        int lob_fetch_status;
                   2496: 
                   2497:        if (column->indicator == -1) { /* column is NULL */
                   2498:                ZVAL_NULL(value);
                   2499:                return 0;
                   2500:        }
                   2501: 
                   2502:        if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
                   2503:                ZVAL_RESOURCE(value, column->stmtid);
                   2504:                zend_list_addref(column->stmtid);
                   2505:        } else if (column->is_descr) {
                   2506: 
                   2507:                if (column->data_type != SQLT_RDD) {
                   2508:                        int rsrc_type;
                   2509: 
                   2510:                        /* reset descriptor's length */
                   2511:                        descriptor = (php_oci_descriptor *) zend_list_find(column->descid, &rsrc_type);
                   2512: 
                   2513:                        if (!descriptor || rsrc_type != le_descriptor) {
                   2514:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find LOB descriptor #%d", column->descid);
                   2515:                                return 1;
                   2516:                        }
                   2517: 
                   2518:                        descriptor->lob_size = -1;
                   2519:                        descriptor->lob_current_position = 0;
                   2520:                        descriptor->buffering = 0;
                   2521:                }
                   2522: 
                   2523:                if (column->data_type != SQLT_RDD && (mode & PHP_OCI_RETURN_LOBS)) {
                   2524:                        /* PHP_OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
                   2525: 
                   2526:                        lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length TSRMLS_CC);
                   2527:                        php_oci_temp_lob_close(descriptor TSRMLS_CC);
                   2528:                        if (lob_fetch_status) {
                   2529:                                ZVAL_FALSE(value);
                   2530:                                return 1;
                   2531:                        } else {
                   2532:                                if (lob_length > 0) {
                   2533:                                        ZVAL_STRINGL(value, lob_buffer, lob_length, 0);
                   2534:                                } else {
                   2535:                                        ZVAL_EMPTY_STRING(value);
                   2536:                                }
                   2537:                                return 0;
                   2538:                        }
                   2539:                } else {
                   2540:                        /* return the locator */
                   2541:                        object_init_ex(value, oci_lob_class_entry_ptr);
                   2542:                        add_property_resource(value, "descriptor", column->descid);
                   2543:                        zend_list_addref(column->descid);
                   2544:                }
                   2545:        } else {
                   2546:                switch (column->retcode) {
                   2547:                        case 0:
                   2548:                                /* intact value */
                   2549:                                if (column->piecewise) {
                   2550:                                        column_size = column->retlen4;
                   2551:                                } else {
                   2552:                                        column_size = column->retlen;
                   2553:                                }
                   2554:                                break;
                   2555: 
                   2556:                        default:
                   2557:                                ZVAL_FALSE(value);
                   2558:                                return 0;
                   2559:                }
                   2560: 
                   2561:                ZVAL_STRINGL(value, column->data, column_size, 1);
                   2562:        }
                   2563:        return 0;
                   2564: }
                   2565: /* }}} */
                   2566: 
                   2567: /* {{{ php_oci_fetch_row()
                   2568:  *
                   2569:  * Fetch the next row from the given statement
                   2570:  */
                   2571: void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
                   2572: {
                   2573:        zval *z_statement, *array;
                   2574:        php_oci_statement *statement;
                   2575:        php_oci_out_column *column;
                   2576:        ub4 nrows = 1;
                   2577:        int i;
                   2578:        long fetch_mode = 0;
                   2579: 
                   2580:        if (expected_args > 2) {
                   2581:                /* only for ocifetchinto BC */
                   2582: 
                   2583:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|l", &z_statement, &array, &fetch_mode) == FAILURE) {
                   2584:                        return;
                   2585:                }
                   2586: 
                   2587:                if (ZEND_NUM_ARGS() == 2) {
                   2588:                        fetch_mode = mode;
                   2589:                }
                   2590:        } else if (expected_args == 2) {
                   2591:                /* only for oci_fetch_array() */
                   2592: 
                   2593:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_statement, &fetch_mode) == FAILURE) {
                   2594:                        return;
                   2595:                }
                   2596: 
                   2597:                if (ZEND_NUM_ARGS() == 1) {
                   2598:                        fetch_mode = mode;
                   2599:                }
                   2600:        } else {
                   2601:                /* for all oci_fetch_*() */
                   2602: 
                   2603:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
                   2604:                        return;
                   2605:                }
                   2606: 
                   2607:                fetch_mode = mode;
                   2608:        }
                   2609: 
                   2610:        if (!(fetch_mode & PHP_OCI_NUM) && !(fetch_mode & PHP_OCI_ASSOC)) {
                   2611:                /* none of the modes present, use the default one */
                   2612:                if (mode & PHP_OCI_ASSOC) {
                   2613:                        fetch_mode |= PHP_OCI_ASSOC;
                   2614:                }
                   2615:                if (mode & PHP_OCI_NUM) {
                   2616:                        fetch_mode |= PHP_OCI_NUM;
                   2617:                }
                   2618:        }
                   2619: 
                   2620:        PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
                   2621: 
                   2622:        if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
                   2623:                RETURN_FALSE;
                   2624:        }
                   2625: 
                   2626:        array_init(return_value);
                   2627: 
                   2628:        for (i = 0; i < statement->ncolumns; i++) {
                   2629: 
                   2630:                column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
                   2631: 
                   2632:                if (column == NULL) {
                   2633:                        continue;
                   2634:                }
                   2635:                if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
                   2636:                        continue;
                   2637:                }
                   2638: 
                   2639:                if (!(column->indicator == -1)) {
                   2640:                        zval *element;
                   2641: 
                   2642:                        MAKE_STD_ZVAL(element);
                   2643:                        php_oci_column_to_zval(column, element, fetch_mode TSRMLS_CC);
                   2644: 
                   2645:                        if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
                   2646:                                add_index_zval(return_value, i, element);
                   2647:                        }
                   2648:                        if (fetch_mode & PHP_OCI_ASSOC) {
                   2649:                                if (fetch_mode & PHP_OCI_NUM) {
                   2650:                                        Z_ADDREF_P(element);
                   2651:                                }
                   2652:                                add_assoc_zval(return_value, column->name, element);
                   2653:                        }
                   2654: 
                   2655:                } else {
                   2656:                        if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
                   2657:                                add_index_null(return_value, i);
                   2658:                        }
                   2659:                        if (fetch_mode & PHP_OCI_ASSOC) {
                   2660:                                add_assoc_null(return_value, column->name);
                   2661:                        }
                   2662:                }
                   2663:        }
                   2664: 
                   2665:        if (expected_args > 2) {
                   2666:                /* Only for ocifetchinto BC.  In all other cases we return array, not long */
                   2667:                REPLACE_ZVAL_VALUE(&array, return_value, 1); /* copy return_value to given reference */
                   2668:                zval_dtor(return_value);
                   2669:                RETURN_LONG(statement->ncolumns);
                   2670:        }
                   2671: }
                   2672: /* }}} */
                   2673: 
                   2674: /* {{{ php_oci_persistent_helper()
                   2675:  *
                   2676:  * Helper function to close/rollback persistent connections at the end of request. A return value of
                   2677:  * 1 indicates that the connection is to be destroyed
                   2678:  */
                   2679: static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
                   2680: {
                   2681:        time_t timestamp;
                   2682:        php_oci_connection *connection;
                   2683: 
                   2684:        timestamp = time(NULL);
                   2685: 
                   2686:        /* Persistent connection stubs are also counted as they have private session pools */
                   2687:        if (le->type == le_pconnection) {
                   2688:                connection = (php_oci_connection *)le->ptr;
                   2689: 
                   2690:                if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
                   2691:                        if (OCI_G(debug_mode)) {
                   2692:                                php_printf ("OCI8 DEBUG L1: persistent_helper processing for timeout: (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__);
                   2693:                        }
                   2694:                        if (connection->idle_expiry < timestamp) {
                   2695:                                /* connection has timed out */
                   2696:                                return ZEND_HASH_APPLY_REMOVE;
                   2697:                        }
                   2698:                }
                   2699:        }
                   2700:        return ZEND_HASH_APPLY_KEEP;
                   2701: } /* }}} */
                   2702: 
                   2703: /* {{{ php_oci_create_spool()
                   2704:  *
                   2705:  *      Create(alloc + Init) Session pool for the given dbname and charsetid
                   2706:  */
                   2707: static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC)
                   2708: {
                   2709:        php_oci_spool *session_pool = NULL;
                   2710:        zend_bool iserror = 0;
                   2711:        ub4 poolmode = OCI_DEFAULT;     /* Mode to be passed to OCISessionPoolCreate */
                   2712:        OCIAuthInfo *spoolAuth = NULL;
                   2713: 
                   2714:        /* Allocate sessionpool out of persistent memory */
                   2715:        session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
                   2716:        if (session_pool == NULL) {
                   2717:                iserror = 1;
                   2718:                goto exit_create_spool;
                   2719:        }
                   2720: 
                   2721:        /* Populate key if passed */
                   2722:        if (hash_key_len) {
                   2723:                session_pool->spool_hash_key = zend_strndup(hash_key, hash_key_len);
                   2724:                if (session_pool->spool_hash_key == NULL) {
                   2725:                        iserror = 1;
                   2726:                        goto exit_create_spool;
                   2727:                }
                   2728:        }
                   2729: 
                   2730:        /* Create the session pool's env */
                   2731:        if (!(session_pool->env = php_oci_create_env(charsetid TSRMLS_CC))) {
                   2732:                iserror = 1;
                   2733:                goto exit_create_spool;
                   2734:        }
                   2735: 
                   2736:        /* Allocate the pool handle */
                   2737:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
                   2738: 
                   2739:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2740:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2741:                iserror = 1;
                   2742:                goto exit_create_spool;
                   2743:        }
                   2744: 
                   2745:        /* Allocate the session pool error handle - This only for use in the destructor, as there is a
                   2746:         * generic bug which can free up the OCI_G(err) variable before destroying connections. We
                   2747:         * cannot use this for other roundtrip calls as there is no way the user can access this error
                   2748:         */
                   2749:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
                   2750: 
                   2751:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2752:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2753:                iserror = 1;
                   2754:                goto exit_create_spool;
                   2755:        }
                   2756: 
                   2757: /* Disable RLB as we mostly have single-connection pools */
                   2758: #if (OCI_MAJOR_VERSION > 10)
                   2759:        poolmode = OCI_SPC_NO_RLB | OCI_SPC_HOMOGENEOUS;
                   2760: #else
                   2761:        poolmode = OCI_SPC_HOMOGENEOUS;
                   2762: #endif
                   2763: 
                   2764: #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
                   2765:        /* Allocate auth handle for session pool {{{ */
                   2766:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
                   2767: 
                   2768:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2769:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2770:                iserror = 1;
                   2771:                goto exit_create_spool;
                   2772:        } /* }}} */
                   2773: 
                   2774:        /* Set the edition attribute on the auth handle {{{ */
                   2775:        if (OCI_G(edition)) {
                   2776:                PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err)));
                   2777: 
                   2778:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   2779:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2780:                        iserror = 1;
                   2781:                        goto exit_create_spool;
                   2782:                }
                   2783:        } /* }}} */
                   2784: 
                   2785:        /* Set the driver name attribute on the auth handle {{{ */
                   2786:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
                   2787: 
                   2788:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2789:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2790:                iserror = 1;
                   2791:                goto exit_create_spool;
                   2792:        } /* }}} */
                   2793: 
                   2794:        /* Set the auth handle on the session pool {{{ */
                   2795:        PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err)));
                   2796: 
                   2797:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2798:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2799:                iserror = 1;
                   2800:                goto exit_create_spool;
                   2801:        } /* }}} */
                   2802: #endif
                   2803: 
                   2804:        /* Create the homogeneous session pool - We have different session pools for every different
                   2805:         * username, password, charset and dbname.
                   2806:         */
                   2807:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode));
                   2808: 
                   2809:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2810:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2811:                iserror = 1;
                   2812:        }
                   2813: 
                   2814: exit_create_spool:
                   2815:        if (iserror && session_pool) {
                   2816:                php_oci_spool_close(session_pool TSRMLS_CC);
                   2817:                session_pool = NULL;
                   2818:        }
                   2819: 
                   2820:        if (spoolAuth) {
                   2821:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
                   2822:        }
                   2823: 
                   2824:        if (OCI_G(debug_mode)) {
                   2825:                php_printf ("OCI8 DEBUG L1: create_spool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
                   2826:        }
                   2827: 
                   2828:        return session_pool;
                   2829: } /* }}} */
                   2830: 
                   2831: /* {{{ php_oci_get_spool()
                   2832:  *
                   2833:  * Get Session pool for the given dbname and charsetid from the persistent list. Function called for
                   2834:  * non-persistent connections.
                   2835:  */
                   2836: static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC)
                   2837: {
                   2838:        smart_str spool_hashed_details = {0};
                   2839:        php_oci_spool *session_pool = NULL;
                   2840:        zend_rsrc_list_entry spool_le = {0};
                   2841:        zend_rsrc_list_entry *spool_out_le = NULL;
                   2842:        zend_bool iserror = 0;
                   2843: 
                   2844:        /* Create the spool hash key {{{ */
                   2845:        smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0);
                   2846:        smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0);
                   2847:        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
                   2848:        /* Add edition attribute to the hash */
                   2849:        if (OCI_G(edition)){
                   2850:                smart_str_appendl_ex(&spool_hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
                   2851:        }
                   2852:        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
                   2853:        if (password_len) {
                   2854:                ulong password_hash;
                   2855:                password_hash = zend_inline_hash_func(password, password_len);
                   2856:                smart_str_append_unsigned_ex(&spool_hashed_details, password_hash, 0);
                   2857:        }
                   2858:        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
                   2859: 
                   2860:        if (dbname_len) {
                   2861:                smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 0);
                   2862:        }
                   2863:        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
                   2864: 
                   2865:        smart_str_append_unsigned_ex(&spool_hashed_details, charsetid, 0);
                   2866: 
                   2867:        /* Session Pool Hash Key : oci8spool***username**edition**hashedpassword**dbname**charset */
                   2868: 
                   2869:        smart_str_0(&spool_hashed_details);
                   2870:        php_strtolower(spool_hashed_details.c, spool_hashed_details.len);
                   2871:        /* }}} */
                   2872: 
                   2873:        if (zend_hash_find(&EG(persistent_list),spool_hashed_details.c, spool_hashed_details.len+1, (void **)&spool_out_le) == FAILURE) {
                   2874: 
                   2875:                session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.c, spool_hashed_details.len, charsetid TSRMLS_CC);
                   2876: 
                   2877:                if (session_pool == NULL) {
                   2878:                        iserror = 1;
                   2879:                        goto exit_get_spool;
                   2880:                }
                   2881:                spool_le.ptr  = session_pool;
                   2882:                spool_le.type = le_psessionpool;
                   2883: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
                   2884:                zend_list_insert(session_pool, le_psessionpool TSRMLS_CC);
                   2885: #else
                   2886:                zend_list_insert(session_pool, le_psessionpool);
                   2887: #endif
                   2888:                zend_hash_update(&EG(persistent_list), session_pool->spool_hash_key, strlen(session_pool->spool_hash_key)+1,(void *)&spool_le, sizeof(zend_rsrc_list_entry),NULL);
                   2889:        } else if (spool_out_le->type == le_psessionpool &&
                   2890:                strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len &&
                   2891:                memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0) {
                   2892:                /* retrieve the cached session pool */
                   2893:                session_pool = (php_oci_spool *)(spool_out_le->ptr);
                   2894:        }
                   2895: 
                   2896: exit_get_spool:
                   2897:        smart_str_free_ex(&spool_hashed_details, 0);
                   2898:        if (iserror && session_pool) {
                   2899:                php_oci_spool_close(session_pool TSRMLS_CC);
                   2900:                session_pool = NULL;
                   2901:        }
                   2902: 
                   2903:        return session_pool;
                   2904: 
                   2905: } /* }}} */
                   2906: 
                   2907: /* {{{ php_oci_create_env()
                   2908:  *
                   2909:  * Create the OCI environment choosing the correct function for the OCI version
                   2910:  */
                   2911: static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC)
                   2912: {
                   2913:        OCIEnv *retenv = NULL;
                   2914: 
                   2915:        /* create an environment using the character set id */
                   2916:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIEnvNlsCreate, (&retenv, OCI_G(events) ? PHP_OCI_INIT_MODE | OCI_EVENTS : PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, charsetid, charsetid));
                   2917: 
                   2918:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2919:                sb4   ora_error_code = 0;
                   2920:                text  ora_msg_buf[OCI_ERROR_MAXMSG_SIZE];  /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
                   2921: 
                   2922: #ifdef HAVE_OCI_INSTANT_CLIENT
                   2923:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
                   2924: #else
                   2925:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
                   2926: #endif
                   2927:                if (retenv
                   2928:                        && OCIErrorGet(retenv, (ub4)1, NULL, &ora_error_code, ora_msg_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
                   2929:                        && *ora_msg_buf) {
                   2930:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ora_msg_buf);
                   2931:                }
                   2932:                
                   2933:                return NULL;
                   2934:        }
                   2935:        return retenv;
                   2936: }/* }}} */
                   2937: 
                   2938: /* {{{ php_oci_old_create_session()
                   2939:  *
                   2940:  * This function is to be deprecated in future in favour of OCISessionGet which is used in
                   2941:  * php_oci_do_connect_ex
                   2942:  */
                   2943: static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
                   2944: {
                   2945:        ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
                   2946: 
                   2947:        if (OCI_G(debug_mode)) {
                   2948:                php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create at (%s:%d) \n", __FILE__, __LINE__);
                   2949:        }
                   2950: 
                   2951:        /* Create the OCI environment separate for each connection */
                   2952:        if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))) {
                   2953:                return 1;
                   2954:        }
                   2955: 
                   2956:        /* Allocate our server handle {{{ */
                   2957:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL));
                   2958: 
                   2959:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2960:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2961:                return 1;
                   2962:        } /* }}} */
                   2963: 
                   2964:        /* Attach to the server {{{ */
                   2965:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT));
                   2966: 
                   2967:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2968:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2969:                return 1;
                   2970:        } /* }}} */
                   2971:        connection->is_attached = 1;
                   2972: 
                   2973:        /* Allocate our session handle {{{ */
                   2974:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL));
                   2975: 
                   2976:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2977:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2978:                return 1;
                   2979:        } /* }}} */
                   2980: 
                   2981:        /* Allocate our private error-handle {{{ */
                   2982:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
                   2983: 
                   2984:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2985:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2986:                return 1;
                   2987:        } /* }}} */
                   2988: 
                   2989:        /* Allocate our service-context {{{ */
                   2990:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL));
                   2991: 
                   2992:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   2993:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   2994:                return 1;
                   2995:        } /* }}} */
                   2996: 
                   2997:        /* Set the username {{{ */
                   2998:        if (username) {
                   2999:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) username, (ub4) username_len, (ub4) OCI_ATTR_USERNAME, OCI_G(err)));
                   3000: 
                   3001:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3002:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3003:                        return 1;
                   3004:                }
                   3005:        }/* }}} */
                   3006: 
                   3007:        /* Set the password {{{ */
                   3008:        if (password) {
                   3009:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) password, (ub4) password_len, (ub4) OCI_ATTR_PASSWORD, OCI_G(err)));
                   3010: 
                   3011:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3012:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3013:                        return 1;
                   3014:                }
                   3015:        }/* }}} */
                   3016: 
                   3017:        /* Set the edition attribute on the session handle {{{ */
                   3018: #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
                   3019:        if (OCI_G(edition)) {
                   3020:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(edition), (ub4) (strlen(OCI_G(edition))), (ub4) OCI_ATTR_EDITION, OCI_G(err)));
                   3021: 
                   3022:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3023:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3024:                        return 1;
                   3025:                }
                   3026:        }
                   3027: #endif /* }}} */
                   3028: 
                   3029:        /* Set the driver name attribute on the session handle {{{ */
                   3030: #if (OCI_MAJOR_VERSION >= 11)
                   3031:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
                   3032: 
                   3033:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   3034:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3035:                return 1;
                   3036:        }
                   3037: #endif /* }}} */
                   3038: 
                   3039:        /* Set the server handle in the service handle {{{ */
                   3040:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err)));
                   3041: 
                   3042:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   3043:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3044:                return 1;
                   3045:        } /* }}} */
                   3046: 
                   3047:        /* Set the authentication handle in the service handle {{{ */
                   3048:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err)));
                   3049: 
                   3050:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   3051:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3052:                return 1;
                   3053:        } /* }}} */
                   3054: 
                   3055:        if (new_password) {
                   3056:                /* Try to change password if new one was provided {{{ */
                   3057:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPasswordChange, (connection->svc, OCI_G(err), (text *)username, username_len, (text *)password, password_len, (text *)new_password, new_password_len, OCI_AUTH));
                   3058: 
                   3059:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3060:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3061:                        return 1;
                   3062:                }
                   3063: 
                   3064:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err)));
                   3065: 
                   3066:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3067:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3068:                        return 1;
                   3069:                } /* }}} */
                   3070:        } else {
                   3071:                /* start the session {{{ */
                   3072:                ub4 cred_type = OCI_CRED_RDBMS;
                   3073: 
                   3074:                /* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */
                   3075:                if (session_mode & PHP_OCI_CRED_EXT) {
                   3076:                        cred_type = OCI_CRED_EXT;
                   3077:                        session_mode ^= PHP_OCI_CRED_EXT;
                   3078:                }
                   3079: 
                   3080:                session_mode |= OCI_STMT_CACHE;
                   3081: 
                   3082:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionBegin, (connection->svc, OCI_G(err), connection->session, (ub4) cred_type, (ub4) session_mode));
                   3083: 
                   3084:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3085:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3086:                        /* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
                   3087:                         * user's password has expired, but is still usable.
                   3088:                         */
                   3089:                        if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
                   3090:                                return 1;
                   3091:                        }
                   3092:                } /* }}} */
                   3093:        }
                   3094: 
                   3095:        /* Brand new connection: Init and update the next_ping in the connection */
                   3096:        if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
                   3097:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3098:                return 1;
                   3099:        }
                   3100: 
                   3101:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
                   3102: 
                   3103:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   3104:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3105:                return 1;
                   3106:        }
                   3107: 
                   3108:        /* Successfully created session */
                   3109:        return 0;
                   3110: } /* }}} */
                   3111: 
                   3112: /* {{{ php_oci_create_session()
                   3113:  *
                   3114:  * Create session using client-side session pool - new norm
                   3115:  */
                   3116: static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
                   3117: {
                   3118:        php_oci_spool *actual_spool = NULL;
                   3119: #if (OCI_MAJOR_VERSION > 10)
                   3120:        ub4 purity = -2;                                /* Illegal value to initialize */
                   3121: #endif
                   3122:        time_t timestamp = time(NULL);
                   3123:        ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
                   3124: 
                   3125:        /* Persistent connections have private session pools */
                   3126:        if (connection->is_persistent && !connection->private_spool &&
                   3127:                !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, 0, connection->charset TSRMLS_CC))) {
                   3128:                        return 1;
                   3129:        }
                   3130:        actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
                   3131: 
                   3132:        connection->env = actual_spool->env;
                   3133: 
                   3134:        /* Do this upfront so that connection close on an error would know that this is a session pool
                   3135:         * connection. Failure to do this would result in crashes in error scenarios
                   3136:         */
                   3137:        if (!connection->using_spool) {
                   3138:                connection->using_spool = 1;
                   3139:        }
                   3140: 
                   3141:        if (OCI_G(debug_mode)) {
                   3142:                if (session_pool) {
                   3143:                        php_printf ("OCI8 DEBUG L1: using shared pool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
                   3144:                } else {
                   3145:                        php_printf ("OCI8 DEBUG L1: using private pool: (%p) at (%s:%d) \n", connection->private_spool, __FILE__, __LINE__);
                   3146:                }
                   3147:        }
                   3148: 
                   3149:        /* The passed in "connection" can be a cached stub from plist or freshly created. In the former
                   3150:         * case, we do not have to allocate any handles
                   3151:         */
                   3152: 
                   3153:        if (!connection->err) {
                   3154:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
                   3155: 
                   3156:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3157:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3158:                        return 1;
                   3159:                }
                   3160:        }
                   3161: 
                   3162:        /* {{{ Allocate and initialize the connection-private authinfo handle if not allocated yet */
                   3163:        if (!connection->authinfo) {
                   3164:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
                   3165: 
                   3166:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3167:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3168:                        return 1;
                   3169:                }
                   3170: 
                   3171:                /* Set the Connection class and purity if OCI client version >= 11g */
                   3172: #if (OCI_MAJOR_VERSION > 10)
                   3173:                PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(connection_class), (ub4)(strlen(OCI_G(connection_class))), (ub4)OCI_ATTR_CONNECTION_CLASS, OCI_G(err)));
                   3174: 
                   3175:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3176:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3177:                        return 1;
                   3178:                }
                   3179: 
                   3180:                if (connection->is_persistent)
                   3181:                        purity = OCI_ATTR_PURITY_SELF;
                   3182:                else
                   3183:                        purity = OCI_ATTR_PURITY_NEW;
                   3184: 
                   3185:                PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_AUTHINFO, (dvoid *) &purity, (ub4)0, (ub4)OCI_ATTR_PURITY, OCI_G(err)));
                   3186: 
                   3187:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3188:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3189:                        return 1;
                   3190:                }
                   3191: #endif
                   3192:        } /* }}} */
                   3193: 
                   3194:        /* Debug statements {{{ */
                   3195:        if (OCI_G(debug_mode)) {
                   3196:                ub4 numfree = 0, numbusy = 0, numopen = 0;
                   3197:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numopen, (ub4 *)0, OCI_ATTR_SPOOL_OPEN_COUNT, OCI_G(err)));
                   3198:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numbusy, (ub4 *)0, OCI_ATTR_SPOOL_BUSY_COUNT, OCI_G(err)));
                   3199:                numfree = numopen - numbusy;    /* number of free connections in the pool */
                   3200:                php_printf ("OCI8 DEBUG L1: (numopen=%d)(numbusy=%d) at (%s:%d) \n", numopen, numbusy, __FILE__, __LINE__);
                   3201:        } /* }}} */
                   3202: 
                   3203:                /* Ping loop: Ping and loop till we get a good connection. When a database instance goes
                   3204:                 * down, it can leave several bad connections that need to be flushed out before getting a
                   3205:                 * good one. In non-RAC, we always get a brand new connection at the end of the loop and in
                   3206:                 * RAC, we can get a good connection from a different instance before flushing out all bad
                   3207:                 * ones. We do not need to ping brand new connections.
                   3208:                 */
                   3209:        do {
                   3210:                /* Continue to use the global error handle as the connection is closed when an error occurs */
                   3211:                PHP_OCI_CALL_RETURN(OCI_G(errcode),OCISessionGet, (connection->env, OCI_G(err), &(connection->svc), (OCIAuthInfo *)connection->authinfo, (OraText *)actual_spool->poolname, (ub4)actual_spool->poolname_len, NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL));
                   3212: 
                   3213:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3214:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3215: 
                   3216:                        /* Session creation returns OCI_SUCCESS_WITH_INFO when user's password has expired, but
                   3217:                         * is still usable.
                   3218:                         */
                   3219: 
                   3220:                        if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
                   3221:                                return 1;
                   3222:                        }
                   3223:                }
                   3224: 
                   3225:                /* {{{ Populate the session and server fields of the connection */
                   3226:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->server), (ub4 *)0, OCI_ATTR_SERVER, OCI_G(err)));
                   3227: 
                   3228:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err))); /* }}} */
                   3229: 
                   3230:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp)));
                   3231:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3232:                        php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3233:                        return 1;
                   3234:                }
                   3235: 
                   3236:                if (!(connection->next_pingp)){
                   3237:                        /* This is a brand new connection, we need not ping, but have to initialize ping */
                   3238:                        if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
                   3239:                                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3240:                                return 1;
                   3241:                        }
                   3242:                } else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
                   3243:                        if (php_oci_connection_ping(connection TSRMLS_CC)) {
                   3244:                                /* Got a good connection - update next_ping and get out of ping loop */
                   3245:                                *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
                   3246:                        } else {
                   3247:                                /* Bad connection - remove from pool */
                   3248:                                PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) OCI_SESSRLS_DROPSESS));
                   3249:                                connection->svc = NULL;
                   3250:                                connection->server = NULL;
                   3251:                                connection->session = NULL;
                   3252:                        }
                   3253:                }       /* If ping applicable */
                   3254:        } while (!(connection->svc));
                   3255: 
                   3256:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
                   3257: 
                   3258:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   3259:                php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                   3260:                return 1;
                   3261:        }
                   3262: 
                   3263:        /* Session is now taken from the session pool and attached and open */
                   3264:        connection->is_stub = 0;
                   3265:        connection->is_attached = connection->is_open = 1;
                   3266: 
                   3267:        return 0;
                   3268: } /* }}} */
                   3269: 
                   3270: /* {{{ php_oci_spool_list_dtor()
                   3271:  *
                   3272:  * Session pool destructor function
                   3273:  */
                   3274: static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
                   3275: {
                   3276:        php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
                   3277: 
                   3278:        if (session_pool) {
                   3279:                php_oci_spool_close(session_pool TSRMLS_CC);
                   3280:        }
                   3281: 
                   3282:        return;
                   3283: } /* }}} */
                   3284: 
                   3285: /* {{{ php_oci_spool_close()
                   3286:  *
                   3287:  * Destroys the OCI Session Pool
                   3288:  */
                   3289: static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC)
                   3290: {
                   3291:        if (session_pool->poolname_len) {
                   3292:                PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
                   3293:                        (dvoid *) session_pool->err, OCI_SPD_FORCE));
                   3294:        }
                   3295: 
                   3296:        if (session_pool->poolh) {
                   3297:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
                   3298:        }
                   3299: 
                   3300:        if (session_pool->err) {
                   3301:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
                   3302:        }
                   3303: 
                   3304:        if (session_pool->env) {
                   3305:                PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->env, OCI_HTYPE_ENV));
                   3306:        }
                   3307: 
                   3308:        if (session_pool->spool_hash_key) {
                   3309:                free(session_pool->spool_hash_key);
                   3310:        }
                   3311: 
                   3312:        free(session_pool);
                   3313: } /* }}} */
                   3314: 
                   3315: /* {{{ php_oci_ping_init()
                   3316:  *
                   3317:  * Initializes the next_ping time as a context value in the connection.         We now use
                   3318:  * OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
                   3319:  * non-persistent DRCP connections
                   3320:  */
                   3321: static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC)
                   3322: {
                   3323:        time_t *next_pingp = NULL;
                   3324: 
                   3325:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, errh, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&next_pingp));
                   3326:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   3327:                return OCI_G(errcode);
                   3328:        }
                   3329: 
                   3330:        /* This must be a brand-new connection. Allocate memory for the ping */
                   3331:        if (!next_pingp) {
                   3332:                PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIMemoryAlloc, (connection->session, errh, (void **)&next_pingp, OCI_DURATION_SESSION, sizeof(time_t), OCI_MEMORY_CLEARED));
                   3333:                if (OCI_G(errcode) != OCI_SUCCESS) {
                   3334:                        return OCI_G(errcode);
                   3335:                }
                   3336:        }
                   3337: 
                   3338:        if (OCI_G(ping_interval) >= 0) {
                   3339:                time_t timestamp = time(NULL);
                   3340:                *next_pingp = timestamp + OCI_G(ping_interval);
                   3341:        } else {
                   3342:                *next_pingp = 0;
                   3343:        }
                   3344: 
                   3345:        /* Set the new ping value into the connection */
                   3346:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextSetValue, (connection->session, errh, OCI_DURATION_SESSION, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), next_pingp));
                   3347:        if (OCI_G(errcode) != OCI_SUCCESS) {
                   3348:                OCIMemoryFree(connection->session, errh, next_pingp);
                   3349:                return OCI_G(errcode);
                   3350:        }
                   3351: 
                   3352:        /* Cache the pointer so we do not have to do OCIContextGetValue repeatedly */
                   3353:        connection->next_pingp = next_pingp;
                   3354: 
                   3355:        return OCI_SUCCESS;
                   3356: } /* }}} */
                   3357: 
                   3358: #endif /* HAVE_OCI8 */
                   3359: 
                   3360: /*
                   3361:  * Local variables:
                   3362:  * tab-width: 4
                   3363:  * c-basic-offset: 4
                   3364:  * End:
                   3365:  * vim600: noet sw=4 ts=4 fdm=marker
                   3366:  * vim<600: noet sw=4 ts=4
                   3367:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>