1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Georg Richter <georg@php.net> |
16 : +----------------------------------------------------------------------+
17 :
18 : */
19 : #ifdef HAVE_CONFIG_H
20 : #include "config.h"
21 : #endif
22 :
23 : #include <signal.h>
24 :
25 : #include "php.h"
26 : #include "php_ini.h"
27 : #include "ext/standard/info.h"
28 : #include "php_mysqli_structs.h"
29 :
30 : /* Define these in the PHP5 tree to make merging easy process */
31 : #define ZSTR_DUPLICATE (1<<0)
32 : #define ZSTR_AUTOFREE (1<<1)
33 :
34 : #define ZVAL_UTF8_STRING(z, s, flags) ZVAL_STRING((z), (char*)(s), ((flags) & ZSTR_DUPLICATE))
35 : #define ZVAL_UTF8_STRINGL(z, s, l, flags) ZVAL_STRINGL((z), (char*)(s), (l), ((flags) & ZSTR_DUPLICATE))
36 :
37 :
38 : /* {{{ void php_clear_warnings() */
39 : void php_clear_warnings(MYSQLI_WARNING *w)
40 4 : {
41 : MYSQLI_WARNING *n;
42 :
43 13 : while (w) {
44 5 : n = w;
45 5 : zval_dtor(&(w->reason));
46 5 : zval_dtor(&(w->sqlstate));
47 5 : w = w->next;
48 5 : efree(n);
49 : }
50 4 : }
51 : /* }}} */
52 :
53 :
54 : #ifndef MYSQLI_USE_MYSQLND
55 : /* {{{ MYSQLI_WARNING *php_new_warning */
56 : static
57 : MYSQLI_WARNING *php_new_warning(const char *reason, int errorno TSRMLS_DC)
58 : {
59 : MYSQLI_WARNING *w;
60 :
61 : w = (MYSQLI_WARNING *)ecalloc(1, sizeof(MYSQLI_WARNING));
62 :
63 : ZVAL_UTF8_STRING(&(w->reason), reason, ZSTR_DUPLICATE);
64 :
65 : ZVAL_UTF8_STRINGL(&(w->sqlstate), "HY000", sizeof("HY000") - 1, ZSTR_DUPLICATE);
66 :
67 : w->errorno = errorno;
68 :
69 : return w;
70 : }
71 : /* }}} */
72 :
73 :
74 : /* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC) */
75 : MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
76 : {
77 : MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
78 : MYSQL_RES *result;
79 : MYSQL_ROW row;
80 :
81 : if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) {
82 : return NULL;
83 : }
84 :
85 : result = mysql_store_result(mysql);
86 :
87 : while ((row = mysql_fetch_row(result))) {
88 : w = php_new_warning(row[2], atoi(row[1]) TSRMLS_CC);
89 : if (!first) {
90 : first = w;
91 : }
92 : if (prev) {
93 : prev->next = w;
94 : }
95 : prev = w;
96 : }
97 : mysql_free_result(result);
98 : return first;
99 : }
100 : /* }}} */
101 : #else
102 : /* {{{ MYSQLI_WARNING *php_new_warning */
103 : static
104 : MYSQLI_WARNING *php_new_warning(const zval *reason, int errorno TSRMLS_DC)
105 5 : {
106 : MYSQLI_WARNING *w;
107 :
108 5 : w = (MYSQLI_WARNING *)ecalloc(1, sizeof(MYSQLI_WARNING));
109 :
110 5 : w->reason = *reason;
111 5 : zval_copy_ctor(&(w->reason));
112 :
113 5 : ZVAL_UTF8_STRINGL(&(w->reason), Z_STRVAL(w->reason), Z_STRLEN(w->reason), ZSTR_AUTOFREE);
114 :
115 5 : ZVAL_UTF8_STRINGL(&(w->sqlstate), "HY000", sizeof("HY000") - 1, ZSTR_DUPLICATE);
116 :
117 5 : w->errorno = errorno;
118 :
119 5 : return w;
120 : }
121 : /* }}} */
122 :
123 :
124 : /* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC) */
125 : MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
126 4 : {
127 4 : MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
128 : MYSQL_RES *result;
129 : zval *row;
130 :
131 4 : if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) {
132 0 : return NULL;
133 : }
134 :
135 4 : result = mysql_use_result(mysql);
136 :
137 : for (;;) {
138 : zval **entry;
139 : int errno;
140 :
141 9 : MAKE_STD_ZVAL(row);
142 9 : mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, row, MYSQLND_MYSQLI);
143 9 : if (Z_TYPE_P(row) != IS_ARRAY) {
144 4 : zval_ptr_dtor(&row);
145 : break;
146 : }
147 5 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(row));
148 : /* 0. we don't care about the first */
149 5 : zend_hash_move_forward(Z_ARRVAL_P(row));
150 :
151 : /* 1. Here comes the error no */
152 5 : zend_hash_get_current_data(Z_ARRVAL_P(row), (void **)&entry);
153 5 : convert_to_long_ex(entry);
154 5 : errno = Z_LVAL_PP(entry);
155 5 : zend_hash_move_forward(Z_ARRVAL_P(row));
156 :
157 : /* 2. Here comes the reason */
158 5 : zend_hash_get_current_data(Z_ARRVAL_P(row), (void **)&entry);
159 :
160 5 : w = php_new_warning(*entry, errno TSRMLS_CC);
161 : /*
162 : Don't destroy entry, because the row destroy will decrease
163 : the refcounter. Decreased twice then mysqlnd_free_result()
164 : will crash, because it will try to access already freed memory.
165 : */
166 5 : if (!first) {
167 4 : first = w;
168 : }
169 5 : if (prev) {
170 1 : prev->next = (void *)w;
171 : }
172 5 : prev = w;
173 :
174 5 : zval_ptr_dtor(&row);
175 5 : }
176 :
177 4 : mysql_free_result(result);
178 4 : return first;
179 : }
180 : /* }}} */
181 : #endif
182 :
183 :
184 : /* {{{ bool mysqli_warning::next() */
185 : PHP_METHOD(mysqli_warning, next)
186 3 : {
187 : MYSQLI_WARNING *w;
188 : zval *mysqli_warning;
189 3 : mysqli_object *obj = (mysqli_object *)zend_objects_get_address(getThis() TSRMLS_CC);
190 :
191 3 : if (obj->ptr) {
192 3 : if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
193 : &mysqli_warning, mysqli_warning_class_entry) == FAILURE) {
194 0 : return;
195 : }
196 :
197 3 : MYSQLI_FETCH_RESOURCE(w, MYSQLI_WARNING *, &mysqli_warning, "mysqli_warning", MYSQLI_STATUS_VALID);
198 :
199 3 : if (w->next) {
200 1 : w = w->next;
201 1 : ((MYSQLI_RESOURCE *)(obj->ptr))->ptr = w;
202 1 : RETURN_TRUE;
203 : }
204 : }
205 2 : RETURN_FALSE;
206 : }
207 : /* }}} */
208 :
209 :
210 : /* {{{ property mysqli_warning_message */
211 : static
212 : int mysqli_warning_message(mysqli_object *obj, zval **retval TSRMLS_DC)
213 4 : {
214 : MYSQLI_WARNING *w;
215 :
216 4 : if (!obj->ptr || !((MYSQLI_RESOURCE *)(obj->ptr))->ptr) {
217 0 : return FAILURE;
218 : }
219 :
220 4 : w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
221 4 : MAKE_STD_ZVAL(*retval);
222 4 : **retval = w->reason;
223 4 : zval_copy_ctor(*retval);
224 4 : return SUCCESS;
225 : }
226 : /* }}} */
227 :
228 :
229 : /* {{{ property mysqli_warning_sqlstate */
230 : static
231 : int mysqli_warning_sqlstate(mysqli_object *obj, zval **retval TSRMLS_DC)
232 4 : {
233 : MYSQLI_WARNING *w;
234 :
235 4 : if (!obj->ptr || !((MYSQLI_RESOURCE *)(obj->ptr))->ptr) {
236 0 : return FAILURE;
237 : }
238 :
239 4 : w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
240 4 : MAKE_STD_ZVAL(*retval);
241 4 : **retval = w->sqlstate;
242 4 : zval_copy_ctor(*retval);
243 4 : return SUCCESS;
244 : }
245 : /* }}} */
246 :
247 :
248 : /* {{{ property mysqli_warning_error */
249 : static
250 : int mysqli_warning_errno(mysqli_object *obj, zval **retval TSRMLS_DC)
251 4 : {
252 : MYSQLI_WARNING *w;
253 :
254 4 : if (!obj->ptr || !((MYSQLI_RESOURCE *)(obj->ptr))->ptr) {
255 0 : return FAILURE;
256 : }
257 4 : w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
258 4 : MAKE_STD_ZVAL(*retval);
259 4 : ZVAL_LONG(*retval, w->errorno);
260 4 : return SUCCESS;
261 : }
262 : /* }}} */
263 :
264 : /* {{{ mysqli_warning_construct(object obj) */
265 : PHP_METHOD(mysqli_warning, __construct)
266 0 : {
267 : zval *z;
268 : mysqli_object *obj;
269 : MYSQL *hdl;
270 : MYSQLI_WARNING *w;
271 : MYSQLI_RESOURCE *mysqli_resource;
272 :
273 0 : if (ZEND_NUM_ARGS() != 1) {
274 0 : WRONG_PARAM_COUNT;
275 : }
276 0 : if (zend_parse_parameters(1 TSRMLS_CC, "o", &z)==FAILURE) {
277 0 : return;
278 : }
279 0 : obj = (mysqli_object *)zend_object_store_get_object(z TSRMLS_CC);\
280 :
281 0 : if (obj->zo.ce == mysqli_link_class_entry) {
282 : MY_MYSQL *mysql;
283 0 : MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &z, "mysqli_link", MYSQLI_STATUS_VALID);
284 0 : hdl = mysql->mysql;
285 0 : } else if (obj->zo.ce == mysqli_stmt_class_entry) {
286 : MY_STMT *stmt;
287 0 : MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &z, "mysqli_stmt", MYSQLI_STATUS_VALID);
288 0 : hdl = mysqli_stmt_get_connection(stmt->stmt);
289 : } else {
290 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid class argument");
291 0 : RETURN_FALSE;
292 : }
293 :
294 0 : if (mysql_warning_count(hdl)) {
295 0 : w = php_get_warnings(hdl TSRMLS_CC);
296 : } else {
297 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "No warnings found");
298 0 : RETURN_FALSE;
299 : }
300 :
301 0 : mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
302 0 : mysqli_resource->ptr = mysqli_resource->info = (void *)w;
303 0 : mysqli_resource->status = MYSQLI_STATUS_VALID;
304 :
305 0 : if (!getThis() || !instanceof_function(Z_OBJCE_P(getThis()), mysqli_warning_class_entry TSRMLS_CC)) {
306 0 : MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
307 : } else {
308 0 : ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
309 : }
310 :
311 : }
312 : /* }}} */
313 :
314 : /* {{{ mysqli_warning_methods */
315 : const zend_function_entry mysqli_warning_methods[] = {
316 : PHP_ME(mysqli_warning, __construct, NULL, ZEND_ACC_PROTECTED)
317 : PHP_ME(mysqli_warning, next, NULL, ZEND_ACC_PUBLIC)
318 : {NULL, NULL, NULL}
319 : };
320 : /* }}} */
321 :
322 : /* {{{ mysqli_warning_property_entries */
323 : const mysqli_property_entry mysqli_warning_property_entries[] = {
324 : {"message", sizeof("message") - 1, mysqli_warning_message, NULL},
325 : {"sqlstate", sizeof("sqlstate") - 1, mysqli_warning_sqlstate, NULL},
326 : {"errno", sizeof("errno") - 1, mysqli_warning_errno, NULL},
327 : {NULL, 0, NULL, NULL}
328 : };
329 : /* }}} */
330 :
331 : /* {{{ mysqli_warning_property_info_entries */
332 : zend_property_info mysqli_warning_property_info_entries[] = {
333 : {ZEND_ACC_PUBLIC, "message", sizeof("message") - 1, 0, NULL, 0, NULL},
334 : {ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, 0, NULL, 0, NULL},
335 : {ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, 0, NULL, 0, NULL},
336 : {0, NULL, 0, 0, NULL, 0, NULL}
337 : };
338 : /* }}} */
339 :
340 :
341 : /*
342 : * Local variables:
343 : * tab-width: 4
344 : * c-basic-offset: 4
345 : * indent-tabs-mode: t
346 : * End:
347 : * vim600: noet sw=4 ts=4 fdm=marker
348 : * vim<600: noet sw=4 ts=4
349 : */
|