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