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