xref: /PHP-5.5/ext/mysqli/mysqli_warning.c (revision 73c1be26)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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