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