mysqli_warning.c 9.5 KB

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