summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS12
-rw-r--r--README.PARAMETER_PARSING_API21
-rw-r--r--UPGRADING.INTERNALS11
-rw-r--r--Zend/zend_API.c57
-rw-r--r--Zend/zend_API.h2
-rw-r--r--Zend/zend_qsort.c12
-rw-r--r--Zend/zend_qsort.h2
-rw-r--r--ext/date/php_date.c44
-rw-r--r--ext/dba/dba_flatfile.c19
-rw-r--r--ext/dba/dba_gdbm.c17
-rw-r--r--ext/dba/dba_inifile.c1
-rw-r--r--ext/dba/dba_qdbm.c10
-rw-r--r--ext/dba/tests/dba_db1.phpt4
-rw-r--r--ext/dba/tests/dba_db2.phpt4
-rw-r--r--ext/dba/tests/dba_db3.phpt4
-rw-r--r--ext/dba/tests/dba_db4_000.phpt4
-rw-r--r--ext/dba/tests/dba_dbm.phpt4
-rw-r--r--ext/dba/tests/dba_flatfile.phpt4
-rw-r--r--ext/dba/tests/dba_gdbm.phpt2
-rw-r--r--ext/dba/tests/dba_handler.inc12
-rw-r--r--ext/dba/tests/dba_inifile.phpt4
-rw-r--r--ext/dba/tests/dba_ndbm.phpt4
-rw-r--r--ext/dba/tests/dba_qdbm.phpt2
-rw-r--r--ext/dba/tests/dba_tcadb.phpt4
-rw-r--r--ext/mysqlnd/mysqlnd.c108
-rw-r--r--ext/mysqlnd/mysqlnd.h1
-rw-r--r--ext/mysqlnd/mysqlnd_auth.c5
-rw-r--r--ext/mysqlnd/mysqlnd_enum_n_def.h3
-rw-r--r--ext/mysqlnd/mysqlnd_libmysql_compat.h3
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h6
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c66
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.h2
-rw-r--r--ext/standard/file.c3
-rw-r--r--ext/standard/file.h3
-rw-r--r--ext/standard/proc_open.c20
-rw-r--r--ext/standard/string.c66
36 files changed, 416 insertions, 130 deletions
diff --git a/NEWS b/NEWS
index 9e8cd8502b..6395b34f53 100644
--- a/NEWS
+++ b/NEWS
@@ -27,12 +27,19 @@ PHP NEWS
- DateTime
. Added DateTimeImmutable - a variant of DateTime that only returns the
- modified state instead of changing itself. (Derick)
+ modified state instead of changing itself. (Derick)
+
+- FPM:
+ . Fixed bug #63999 (php with fpm fails to build on Solaris 10 or 11). (Adam)
- pgsql:
. Bug #46408: Locale number format settings can cause pg_query_params to
break with numerics. (asmecher, Lars)
+- dba:
+ . Bug #62489: dba_insert not working as expected.
+ (marc-bennewitz at arcor dot de, Lars)
+
18 Dec 2012, PHP 5.5.0 Alpha 2
- General improvements:
@@ -243,4 +250,7 @@ PHP NEWS
. Fixed bug #63248 (Load multiple magic files from a directory under Windows).
(Anatoliy)
+- General improvements:
+ . Implemented FR #46487 (Dereferencing process-handles no longer waits on those processes). (Jille Timmermans)
+
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
diff --git a/README.PARAMETER_PARSING_API b/README.PARAMETER_PARSING_API
index 927e48188c..edcee0f2ea 100644
--- a/README.PARAMETER_PARSING_API
+++ b/README.PARAMETER_PARSING_API
@@ -28,6 +28,17 @@ Both functions return SUCCESS or FAILURE depending on the result.
The auto-conversions are performed as necessary. Arrays, objects, and
resources cannot be auto-converted.
+PHP 5.5 includes a new function:
+
+int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...);
+
+This function behaves like zend_parse_parameters_ex() except that instead of
+reading the arguments from the stack, it receives a single zval to convert
+(passed with double indirection). The passed zval may be changed in place as
+part of the conversion process.
+
+See also https://wiki.php.net/rfc/zpp_improv#expose_zend_parse_arg_as_zend_parse_parameter
+
Type specifiers
---------------
@@ -65,9 +76,13 @@ Type specifiers
will not be touched by the parsing function if they are not
passed to it.
/ - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
- ! - the parameter it follows can be of specified type or NULL (applies
- to all specifiers except for 'b', 'l', and 'd'). If NULL is passed, the
- results pointer is set to NULL as well.
+ ! - the parameter it follows can be of specified type or NULL. If NULL is
+ passed and the output for such type is a pointer, then the output
+ pointer is set to a native NULL pointer.
+ For 'b', 'l' and 'd', an extra argument of type zend_bool* must be
+ passed after the corresponding bool*, long* or double* arguments,
+ respectively. A non-zero value will be written to the zend_bool iif a
+ PHP NULL is passed.
Note on 64bit compatibility
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index 90c7a4394f..44cdfaee6c 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -5,6 +5,7 @@ UPGRADE NOTES - PHP X.Y
1. Internal API changes
a. Streams pooling API
b. Lowercasing and locales
+ c. zend_qsort_r
2. Build system changes
a. Unix build system changes
@@ -53,6 +54,16 @@ such as strcasecmp, will be using locale rules.
Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as
locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp.
+ c. zend_qsort_r
+
+Added the function zend_qsort_r():
+
+typedef int (*compare_r_func_t)(const void *, const void * TSRMLS_DC, void *);
+void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare, void *arg TSRMLS_DC);
+
+The extra argument it has (relatively to zend_qsort()) is passed to the
+comparison function.
+
========================
2. Build system changes
========================
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index eec4ab0bb1..95c90ea753 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -306,16 +306,14 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
{
const char *spec_walk = *spec;
char c = *spec_walk++;
- int return_null = 0;
+ int check_null = 0;
/* scan through modifiers */
while (1) {
if (*spec_walk == '/') {
SEPARATE_ZVAL_IF_NOT_REF(arg);
} else if (*spec_walk == '!') {
- if (Z_TYPE_PP(arg) == IS_NULL) {
- return_null = 1;
- }
+ check_null = 1;
} else {
break;
}
@@ -327,6 +325,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'L':
{
long *p = va_arg(*va, long *);
+
+ if (check_null) {
+ zend_bool *p = va_arg(*va, zend_bool *);
+ *p = (Z_TYPE_PP(arg) == IS_NULL);
+ }
+
switch (Z_TYPE_PP(arg)) {
case IS_STRING:
{
@@ -380,6 +384,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'd':
{
double *p = va_arg(*va, double *);
+
+ if (check_null) {
+ zend_bool *p = va_arg(*va, zend_bool *);
+ *p = (Z_TYPE_PP(arg) == IS_NULL);
+ }
+
switch (Z_TYPE_PP(arg)) {
case IS_STRING:
{
@@ -418,7 +428,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
int *pl = va_arg(*va, int *);
switch (Z_TYPE_PP(arg)) {
case IS_NULL:
- if (return_null) {
+ if (check_null) {
*p = NULL;
*pl = 0;
break;
@@ -462,6 +472,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'b':
{
zend_bool *p = va_arg(*va, zend_bool *);
+
+ if (check_null) {
+ zend_bool *p = va_arg(*va, zend_bool *);
+ *p = (Z_TYPE_PP(arg) == IS_NULL);
+ }
+
switch (Z_TYPE_PP(arg)) {
case IS_NULL:
case IS_STRING:
@@ -484,7 +500,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'r':
{
zval **p = va_arg(*va, zval **);
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@@ -499,7 +515,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'a':
{
zval **p = va_arg(*va, zval **);
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@@ -514,7 +530,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'h':
{
HashTable **p = va_arg(*va, HashTable **);
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@@ -534,7 +550,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'o':
{
zval **p = va_arg(*va, zval **);
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@@ -551,7 +567,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zval **p = va_arg(*va, zval **);
zend_class_entry *ce = va_arg(*va, zend_class_entry *);
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@@ -573,7 +589,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
zend_class_entry *ce_base = *pce;
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*pce = NULL;
break;
}
@@ -607,7 +623,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
char *is_callable_error = NULL;
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
fci->size = 0;
fcc->initialized = 0;
break;
@@ -637,7 +653,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'z':
{
zval **p = va_arg(*va, zval **);
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
} else {
*p = *arg;
@@ -648,7 +664,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'Z':
{
zval ***p = va_arg(*va, zval ***);
- if (return_null) {
+ if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
} else {
*p = arg;
@@ -697,6 +713,19 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spe
}
/* }}} */
+ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)
+{
+ va_list va;
+ int ret;
+ int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
+
+ va_start(va, spec);
+ ret = zend_parse_arg(arg_num, arg, &va, &spec, quiet TSRMLS_CC);
+ va_end(va);
+
+ return ret;
+}
+
static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
{
const char *spec_walk;
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 4a3985e0f4..8574f90eb5 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -258,6 +258,8 @@ ZEND_API char *zend_zval_type_name(const zval *arg);
ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
+ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...);
+
/* End of parameter parsing API -- andrei */
ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC);
diff --git a/Zend/zend_qsort.c b/Zend/zend_qsort.c
index bf179904ef..128c48dfc8 100644
--- a/Zend/zend_qsort.c
+++ b/Zend/zend_qsort.c
@@ -19,6 +19,7 @@
/* $Id$ */
#include "zend.h"
+#include "zend_qsort.h"
#include <limits.h>
@@ -53,7 +54,7 @@ static void _zend_qsort_swap(void *a, void *b, size_t siz)
}
}
-ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t compare TSRMLS_DC)
+ZEND_API void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare, void *arg TSRMLS_DC)
{
void *begin_stack[QSORT_STACK_SIZE];
void *end_stack[QSORT_STACK_SIZE];
@@ -80,10 +81,10 @@ ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t co
seg2 = end;
while (1) {
- for (; seg1 < seg2 && compare(begin, seg1 TSRMLS_CC) > 0;
+ for (; seg1 < seg2 && compare(begin, seg1 TSRMLS_CC, arg) > 0;
seg1 += siz);
- for (; seg2 >= seg1 && compare(seg2, begin TSRMLS_CC) > 0;
+ for (; seg2 >= seg1 && compare(seg2, begin TSRMLS_CC, arg) > 0;
seg2 -= siz);
if (seg1 >= seg2)
@@ -117,6 +118,11 @@ ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t co
}
}
+ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t compare TSRMLS_DC)
+{
+ zend_qsort_r(base, nmemb, siz, (compare_r_func_t)compare, NULL TSRMLS_CC);
+}
+
/*
* Local Variables:
* c-basic-offset: 4
diff --git a/Zend/zend_qsort.h b/Zend/zend_qsort.h
index 58c99f26c2..0ce32a77c1 100644
--- a/Zend/zend_qsort.h
+++ b/Zend/zend_qsort.h
@@ -22,7 +22,9 @@
#define ZEND_QSORT_H
BEGIN_EXTERN_C()
+typedef int (*compare_r_func_t)(const void *, const void * TSRMLS_DC, void *);
ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t compare TSRMLS_DC);
+ZEND_API void zend_qsort_r(void *base, size_t nmemb, size_t siz, compare_r_func_t compare, void *arg TSRMLS_DC);
END_EXTERN_C()
#endif /* ZEND_QSORT_H */
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index cc83130e1c..f4115dc7e1 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -2066,12 +2066,12 @@ static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC)
return new_ov;
}
-static zval* date_clone_immutable(zval *object)
+static zval* date_clone_immutable(zval *object TSRMLS_DC)
{
zval *new_object;
ALLOC_ZVAL(new_object);
- Z_OBJVAL_P(new_object) = date_object_clone_date(object);
+ Z_OBJVAL_P(new_object) = date_object_clone_date(object TSRMLS_CC);
Z_SET_REFCOUNT_P(new_object, 1);
Z_SET_ISREF_P(new_object);
Z_TYPE_P(new_object) = IS_OBJECT;
@@ -2883,14 +2883,18 @@ PHP_FUNCTION(date_format)
}
/* }}} */
-static void php_date_modify(zval *object, char *modify, int modify_len, zval *return_value TSRMLS_DC)
+static int php_date_modify(zval *object, char *modify, int modify_len TSRMLS_DC)
{
php_date_obj *dateobj;
timelib_time *tmp_time;
timelib_error_container *err = NULL;
dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC);
- DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
+
+ if (!(dateobj->time)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The DateTime object has not been correctly initialized by its constructor");
+ return 0;
+ }
tmp_time = timelib_strtotime(modify, modify_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
@@ -2901,7 +2905,7 @@ static void php_date_modify(zval *object, char *modify, int modify_len, zval *re
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse time string (%s) at position %d (%c): %s", modify,
err->error_messages[0].position, err->error_messages[0].character, err->error_messages[0].message);
timelib_time_dtor(tmp_time);
- RETURN_FALSE;
+ return 0;
}
memcpy(&dateobj->time->relative, &tmp_time->relative, sizeof(struct timelib_rel_time));
@@ -2937,6 +2941,8 @@ static void php_date_modify(zval *object, char *modify, int modify_len, zval *re
timelib_update_ts(dateobj->time, NULL);
timelib_update_from_sse(dateobj->time);
dateobj->time->have_relative = 0;
+
+ return 1;
}
/* {{{ proto DateTime date_modify(DateTime object, string modify)
@@ -2952,9 +2958,11 @@ PHP_FUNCTION(date_modify)
RETURN_FALSE;
}
- php_date_modify(object, modify, modify_len, return_value TSRMLS_CC);
+ if (php_date_modify(object, modify, modify_len TSRMLS_CC)) {
+ RETURN_ZVAL(object, 1, 0);
+ }
- RETURN_ZVAL(object, 1, 0);
+ RETURN_FALSE;
}
/* }}} */
@@ -2970,10 +2978,12 @@ PHP_METHOD(DateTimeImmutable, modify)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
- php_date_modify(new_object, modify, modify_len, return_value TSRMLS_CC);
+ new_object = date_clone_immutable(object TSRMLS_CC);
+ if (php_date_modify(new_object, modify, modify_len TSRMLS_CC)) {
+ RETURN_ZVAL(new_object, 0, 1);
+ }
- RETURN_ZVAL(new_object, 0, 1);
+ RETURN_FALSE;
}
/* }}} */
@@ -3037,7 +3047,7 @@ PHP_METHOD(DateTimeImmutable, add)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
+ new_object = date_clone_immutable(object TSRMLS_CC);
php_date_add(new_object, interval, return_value TSRMLS_CC);
RETURN_ZVAL(new_object, 0, 1);
@@ -3107,7 +3117,7 @@ PHP_METHOD(DateTimeImmutable, sub)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
+ new_object = date_clone_immutable(object TSRMLS_CC);
php_date_sub(new_object, interval, return_value TSRMLS_CC);
RETURN_ZVAL(new_object, 0, 1);
@@ -3197,7 +3207,7 @@ PHP_METHOD(DateTimeImmutable, setTimezone)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
+ new_object = date_clone_immutable(object TSRMLS_CC);
php_date_timezone_set(new_object, timezone_object, return_value TSRMLS_CC);
RETURN_ZVAL(new_object, 0, 1);
@@ -3280,7 +3290,7 @@ PHP_METHOD(DateTimeImmutable, setTime)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
+ new_object = date_clone_immutable(object TSRMLS_CC);
php_date_time_set(new_object, h, i, s, return_value TSRMLS_CC);
RETURN_ZVAL(new_object, 0, 1);
@@ -3328,7 +3338,7 @@ PHP_METHOD(DateTimeImmutable, setDate)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
+ new_object = date_clone_immutable(object TSRMLS_CC);
php_date_date_set(new_object, y, m, d, return_value TSRMLS_CC);
RETURN_ZVAL(new_object, 0, 1);
@@ -3380,7 +3390,7 @@ PHP_METHOD(DateTimeImmutable, setISODate)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
+ new_object = date_clone_immutable(object TSRMLS_CC);
php_date_isodate_set(new_object, y, w, d, return_value TSRMLS_CC);
RETURN_ZVAL(new_object, 0, 1);
@@ -3426,7 +3436,7 @@ PHP_METHOD(DateTimeImmutable, setTimestamp)
RETURN_FALSE;
}
- new_object = date_clone_immutable(object);
+ new_object = date_clone_immutable(object TSRMLS_CC);
php_date_timestamp_set(new_object, timestamp, return_value TSRMLS_CC);
RETURN_ZVAL(new_object, 0, 1);
diff --git a/ext/dba/dba_flatfile.c b/ext/dba/dba_flatfile.c
index 082aa5cdb6..34aa635a54 100644
--- a/ext/dba/dba_flatfile.c
+++ b/ext/dba/dba_flatfile.c
@@ -88,15 +88,16 @@ DBA_UPDATE_FUNC(flatfile)
gval.dsize = vallen;
switch(flatfile_store(dba, gkey, gval, mode==1 ? FLATFILE_INSERT : FLATFILE_REPLACE TSRMLS_CC)) {
- case -1:
- php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Operation not possible");
- return FAILURE;
- default:
- case 0:
- return SUCCESS;
- case 1:
- php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Key already exists");
- return FAILURE;
+ case 0:
+ return SUCCESS;
+ case 1:
+ return FAILURE;
+ case -1:
+ php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Operation not possible");
+ return FAILURE;
+ default:
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "Unknown return value");
+ return FAILURE;
}
}
diff --git a/ext/dba/dba_gdbm.c b/ext/dba/dba_gdbm.c
index 7534568d39..47dd576496 100644
--- a/ext/dba/dba_gdbm.c
+++ b/ext/dba/dba_gdbm.c
@@ -104,11 +104,18 @@ DBA_UPDATE_FUNC(gdbm)
gval.dptr = (char *) val;
gval.dsize = vallen;
- if(gdbm_store(dba->dbf, gkey, gval,
- mode == 1 ? GDBM_INSERT : GDBM_REPLACE) == 0)
- return SUCCESS;
- php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "%s", gdbm_strerror(gdbm_errno));
- return FAILURE;
+ switch (gdbm_store(dba->dbf, gkey, gval, mode == 1 ? GDBM_INSERT : GDBM_REPLACE)) {
+ case 0:
+ return SUCCESS;
+ case 1:
+ return FAILURE;
+ case -1:
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "%s", gdbm_strerror(gdbm_errno));
+ return FAILURE;
+ default:
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "Unknown return value");
+ return FAILURE;
+ }
}
DBA_EXISTS_FUNC(gdbm)
diff --git a/ext/dba/dba_inifile.c b/ext/dba/dba_inifile.c
index e1359b65e9..05ee95c0ec 100644
--- a/ext/dba/dba_inifile.c
+++ b/ext/dba/dba_inifile.c
@@ -101,7 +101,6 @@ DBA_UPDATE_FUNC(inifile)
case 0:
return SUCCESS;
case 1:
- php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Key already exists");
return FAILURE;
}
}
diff --git a/ext/dba/dba_qdbm.c b/ext/dba/dba_qdbm.c
index 485b1997e6..eeece57011 100644
--- a/ext/dba/dba_qdbm.c
+++ b/ext/dba/dba_qdbm.c
@@ -96,13 +96,15 @@ DBA_FETCH_FUNC(qdbm)
DBA_UPDATE_FUNC(qdbm)
{
QDBM_DATA;
- int result;
- result = dpput(dba->dbf, key, keylen, val, vallen, mode == 1 ? DP_DKEEP : DP_DOVER);
- if (result)
+ if (dpput(dba->dbf, key, keylen, val, vallen, mode == 1 ? DP_DKEEP : DP_DOVER)) {
return SUCCESS;
+ }
+
+ if (dpecode != DP_EKEEP) {
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "%s", dperrmsg(dpecode));
+ }
- php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "%s", dperrmsg(dpecode));
return FAILURE;
}
diff --git a/ext/dba/tests/dba_db1.phpt b/ext/dba/tests/dba_db1.phpt
index a24600350f..d0e530e026 100644
--- a/ext/dba/tests/dba_db1.phpt
+++ b/ext/dba/tests/dba_db1.phpt
@@ -18,6 +18,8 @@ database handler: db1
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -33,6 +35,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_db2.phpt b/ext/dba/tests/dba_db2.phpt
index 89d8a926e1..1cfbb3e340 100644
--- a/ext/dba/tests/dba_db2.phpt
+++ b/ext/dba/tests/dba_db2.phpt
@@ -18,6 +18,8 @@ database handler: db2
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -33,6 +35,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_db3.phpt b/ext/dba/tests/dba_db3.phpt
index 257c882175..5de7e5a041 100644
--- a/ext/dba/tests/dba_db3.phpt
+++ b/ext/dba/tests/dba_db3.phpt
@@ -18,6 +18,8 @@ database handler: db3
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -33,6 +35,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_db4_000.phpt b/ext/dba/tests/dba_db4_000.phpt
index bbbc52c9f1..17db4bb62d 100644
--- a/ext/dba/tests/dba_db4_000.phpt
+++ b/ext/dba/tests/dba_db4_000.phpt
@@ -22,6 +22,8 @@ database handler: db4
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -37,6 +39,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_dbm.phpt b/ext/dba/tests/dba_dbm.phpt
index dd1fe1e31c..8bea8463da 100644
--- a/ext/dba/tests/dba_dbm.phpt
+++ b/ext/dba/tests/dba_dbm.phpt
@@ -18,6 +18,8 @@ database handler: dbm
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -33,6 +35,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_flatfile.phpt b/ext/dba/tests/dba_flatfile.phpt
index 8e1ca6a933..ac7f86ebda 100644
--- a/ext/dba/tests/dba_flatfile.phpt
+++ b/ext/dba/tests/dba_flatfile.phpt
@@ -22,6 +22,8 @@ database handler: flatfile
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -37,6 +39,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_gdbm.phpt b/ext/dba/tests/dba_gdbm.phpt
index 33d7d20615..e68e8b7409 100644
--- a/ext/dba/tests/dba_gdbm.phpt
+++ b/ext/dba/tests/dba_gdbm.phpt
@@ -21,6 +21,8 @@ database handler: gdbm
Content String 2
Content 2 replaced
Read during write:%sallowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_handler.inc b/ext/dba/tests/dba_handler.inc
index 1c3f5127ef..a950e903af 100644
--- a/ext/dba/tests/dba_handler.inc
+++ b/ext/dba/tests/dba_handler.inc
@@ -46,8 +46,16 @@ do {
echo "Read during write: allowed\n";
}
if ($db_writer!==FALSE) {
- dba_insert("key number 6", "The 6th value", $db_writer);
- @dba_insert("key number 6", "The 6th value inserted again would be an error", $db_writer);
+ if (dba_insert("key number 6", "The 6th value", $db_writer)) {
+ echo '"key number 6" written' . "\n";
+ } else {
+ echo 'Failed to write "key number 6"' . "\n";
+ }
+ if (dba_insert("key number 6", "The 6th value inserted again would be an error", $db_writer)) {
+ echo '"key number 6" written 2nd time' . "\n";
+ } else {
+ echo 'Failed to write "key number 6" 2nd time' . "\n";
+ }
dba_replace("key2", "Content 2 replaced 2nd time", $db_writer);
dba_delete("key4", $db_writer);
echo dba_fetch("key2", $db_writer)."\n";
diff --git a/ext/dba/tests/dba_inifile.phpt b/ext/dba/tests/dba_inifile.phpt
index 81ab738796..5975d25f4d 100644
--- a/ext/dba/tests/dba_inifile.phpt
+++ b/ext/dba/tests/dba_inifile.phpt
@@ -18,6 +18,8 @@ database handler: inifile
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -33,6 +35,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_ndbm.phpt b/ext/dba/tests/dba_ndbm.phpt
index b0f5542de4..193db6f94d 100644
--- a/ext/dba/tests/dba_ndbm.phpt
+++ b/ext/dba/tests/dba_ndbm.phpt
@@ -18,6 +18,8 @@ database handler: ndbm
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -33,6 +35,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_qdbm.phpt b/ext/dba/tests/dba_qdbm.phpt
index ef216d9258..e2205baa26 100644
--- a/ext/dba/tests/dba_qdbm.phpt
+++ b/ext/dba/tests/dba_qdbm.phpt
@@ -19,6 +19,8 @@ database handler: qdbm
Content String 2
Content 2 replaced
Read during write:%sallowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/dba/tests/dba_tcadb.phpt b/ext/dba/tests/dba_tcadb.phpt
index 52dd4de336..28b6dd8f0b 100644
--- a/ext/dba/tests/dba_tcadb.phpt
+++ b/ext/dba/tests/dba_tcadb.phpt
@@ -22,6 +22,8 @@ database handler: tcadb
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
@@ -37,6 +39,8 @@ array(3) {
Content String 2
Content 2 replaced
Read during write: not allowed
+"key number 6" written
+Failed to write "key number 6" 2nd time
Content 2 replaced 2nd time
The 6th value
array(3) {
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index ebc4a774a6..96c420dee9 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -95,6 +95,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn TSRMLS_
mnd_pefree(conn->options->cfg_section, pers);
conn->options->cfg_section = NULL;
}
+ if (conn->options->connect_attr) {
+ zend_hash_destroy(conn->options->connect_attr);
+ mnd_pefree(conn->options->connect_attr, pers);
+ conn->options->connect_attr = NULL;
+ }
}
/* }}} */
@@ -797,13 +802,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
goto err;
}
+ conn->client_flag = mysql_flags;
+ conn->server_capabilities = greet_packet->server_capabilities;
+
if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
greet_packet, conn->options, mysql_flags TSRMLS_CC))
{
goto err;
}
- conn->client_flag = mysql_flags;
- conn->server_capabilities = greet_packet->server_capabilities;
conn->upsert_status->warning_count = 0;
conn->upsert_status->server_status = greet_packet->server_status;
conn->upsert_status->affected_rows = 0;
@@ -811,6 +817,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
PACKET_FREE(greet_packet);
DBG_RETURN(PASS);
err:
+ conn->client_flag = 0;
+ conn->server_capabilities = 0;
PACKET_FREE(greet_packet);
DBG_RETURN(FAIL);
}
@@ -1086,6 +1094,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
DBG_ENTER("mysqlnd_conn::connect");
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ mysqlnd_options4(conn_handle, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_name", "mysqlnd");
ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
@@ -1094,6 +1103,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
}
/* }}} */
+
/* {{{ mysqlnd_connect */
PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn_handle,
const char * host, const char * user,
@@ -2375,6 +2385,19 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
conn->options->flags &= ~CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS;
}
break;
+ case MYSQL_OPT_CONNECT_ATTR_RESET:
+ if (conn->options->connect_attr) {
+ DBG_INF_FMT("Before reset %d attribute(s)", zend_hash_num_elements(conn->options->connect_attr));
+ zend_hash_clean(conn->options->connect_attr);
+ }
+ break;
+ case MYSQL_OPT_CONNECT_ATTR_DELETE:
+ if (conn->options->connect_attr && value) {
+ DBG_INF_FMT("Before delete %d attribute(s)", zend_hash_num_elements(conn->options->connect_attr));
+ zend_hash_del(conn->options->connect_attr, value, strlen(value));
+ DBG_INF_FMT("%d left", zend_hash_num_elements(conn->options->connect_attr));
+ }
+ break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_SHARED_MEMORY_BASE_NAME:
case MYSQL_OPT_USE_RESULT:
@@ -2395,6 +2418,83 @@ end:
/* }}} */
+/* {{{ connect_attr_item_edtor */
+static void
+connect_attr_item_edtor(void * pDest)
+{
+#ifdef ZTS
+ TSRMLS_FETCH();
+#endif
+ DBG_ENTER("connect_attr_item_edtor");
+ mnd_efree(*(char **) pDest);
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ connect_attr_item_pdtor */
+static void
+connect_attr_item_pdtor(void * pDest)
+{
+#ifdef ZTS
+ TSRMLS_FETCH();
+#endif
+ DBG_ENTER("connect_attr_item_pdtor");
+ mnd_pefree(*(char **) pDest, 1);
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::set_client_option_2d */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * const conn,
+ enum mysqlnd_option option,
+ const char * const key,
+ const char * const value
+ TSRMLS_DC)
+{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_client_option_2d);
+ enum_func_status ret = PASS;
+ DBG_ENTER("mysqlnd_conn_data::set_client_option_2d");
+ DBG_INF_FMT("conn=%llu option=%u", conn->thread_id, option);
+
+ if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ goto end;
+ }
+ switch (option) {
+ case MYSQL_OPT_CONNECT_ATTR_ADD:
+ if (!conn->options->connect_attr) {
+ DBG_INF("Initializing connect_attr hash");
+ conn->options->connect_attr = mnd_pemalloc(sizeof(HashTable), conn->persistent);
+ if (!conn->options->connect_attr) {
+ goto oom;
+ }
+ zend_hash_init(conn->options->connect_attr, 0, NULL, conn->persistent? connect_attr_item_pdtor:connect_attr_item_edtor, conn->persistent);
+ }
+ DBG_INF_FMT("Adding [%s][%s]", key, value);
+ {
+ const char * copyv = mnd_pestrdup(value, conn->persistent);
+ if (!copyv) {
+ goto oom;
+ }
+ zend_hash_update(conn->options->connect_attr, key, strlen(key), &copyv, sizeof(char *), NULL);
+ }
+ break;
+ default:
+ ret = FAIL;
+ }
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ DBG_RETURN(ret);
+oom:
+ SET_OOM_ERROR(*conn->error_info);
+ conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
+end:
+ DBG_RETURN(FAIL);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_conn_data::use_result */
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
@@ -2662,7 +2762,9 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags),
MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake),
MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request),
- MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name)
+ MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)
MYSQLND_CLASS_METHODS_END;
diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h
index 7e02126f3b..bf0f70b405 100644
--- a/ext/mysqlnd/mysqlnd.h
+++ b/ext/mysqlnd/mysqlnd.h
@@ -207,6 +207,7 @@ PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, con
#define mysqlnd_set_character_set(conn, cs) ((conn)->data)->m->set_charset((conn)->data, (cs) TSRMLS_CC)
#define mysqlnd_stat(conn, msg, msg_len) ((conn)->data)->m->get_server_statistics(((conn)->data), (msg), (msg_len) TSRMLS_CC)
#define mysqlnd_options(conn, opt, value) ((conn)->data)->m->set_client_option((conn)->data, (opt), (value) TSRMLS_CC)
+#define mysqlnd_options4(conn, opt, k, v) ((conn)->data)->m->set_client_option_2d((conn)->data, (opt), (k), (v) TSRMLS_CC)
#define mysqlnd_set_server_option(conn, op) ((conn)->data)->m->set_server_option((conn)->data, (op) TSRMLS_CC)
/* Escaping */
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
index a3b4f36a2e..8611d99864 100644
--- a/ext/mysqlnd/mysqlnd_auth.c
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -28,7 +28,6 @@
#include "mysqlnd_charset.h"
#include "mysqlnd_debug.h"
-
/* {{{ mysqlnd_auth_handshake */
enum_func_status
mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
@@ -99,6 +98,10 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
auth_packet->auth_data = auth_plugin_data;
auth_packet->auth_data_len = auth_plugin_data_len;
auth_packet->auth_plugin_name = auth_protocol;
+
+ if (conn->server_capabilities & CLIENT_CONNECT_ATTRS) {
+ auth_packet->connect_attr = conn->options->connect_attr;
+ }
if (!PACKET_WRITE(auth_packet, conn)) {
goto end;
diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h
index abaaf1f43e..cf5b02728b 100644
--- a/ext/mysqlnd/mysqlnd_enum_n_def.h
+++ b/ext/mysqlnd/mysqlnd_enum_n_def.h
@@ -168,6 +168,9 @@ typedef enum mysqlnd_option
MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
MYSQL_PLUGIN_DIR,
MYSQL_DEFAULT_AUTH,
+ MYSQL_OPT_CONNECT_ATTR_RESET,
+ MYSQL_OPT_CONNECT_ATTR_ADD,
+ MYSQL_OPT_CONNECT_ATTR_DELETE,
MYSQL_SERVER_PUBLIC_KEY,
MYSQL_ENABLE_CLEARTEXT_PLUGIN,
MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
diff --git a/ext/mysqlnd/mysqlnd_libmysql_compat.h b/ext/mysqlnd/mysqlnd_libmysql_compat.h
index c967fb3a9f..e3ab9eefa9 100644
--- a/ext/mysqlnd/mysqlnd_libmysql_compat.h
+++ b/ext/mysqlnd/mysqlnd_libmysql_compat.h
@@ -106,7 +106,8 @@
#define mysql_stmt_more_results(s) mysqlnd_stmt_more_results((s))
#define mysql_thread_safe() mysqlnd_thread_safe()
#define mysql_info(r) mysqlnd_info((r))
-#define mysql_options(r,a,b) mysqlnd_options((r), (a), (b))
+#define mysql_options(c,a,v) mysqlnd_options((c), (a), (v))
+#define mysql_options4(c,a,k,v) mysqlnd_options4((c), (a), (k), (v))
#define mysql_stmt_init(r) mysqlnd_stmt_init((r))
#define mysql_free_result(r) mysqlnd_free_result((r), FALSE)
#define mysql_store_result(r) mysqlnd_store_result((r))
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 6302c81c6a..ecb1d89216 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -172,7 +172,7 @@ typedef struct st_mysqlnd_options
The ABI will be broken and the methods structure will be somewhere else
in the memory which can crash external code. Feel free to reuse these.
*/
- char * unused2;
+ HashTable * connect_attr;
char * unused3;
char * unused4;
char * unused5;
@@ -489,6 +489,8 @@ typedef enum_func_status (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CO
typedef enum_func_status (*func_mysqlnd_conn_data__simple_command_send_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC);
typedef struct st_mysqlnd_authentication_plugin * (*func_mysqlnd_conn_data__fetch_auth_plugin_by_name)(const char * const requested_protocol TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_option option, const char * const key, const char * const value TSRMLS_DC);
+
struct st_mysqlnd_conn_data_methods
{
func_mysqlnd_conn_data__init init;
@@ -573,6 +575,8 @@ struct st_mysqlnd_conn_data_methods
func_mysqlnd_conn_data__connect_handshake connect_handshake;
func_mysqlnd_conn_data__simple_command_send_request simple_command_send_request;
func_mysqlnd_conn_data__fetch_auth_plugin_by_name fetch_auth_plugin_by_name;
+
+ func_mysqlnd_conn_data__set_client_option_2d set_client_option_2d;
};
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 7c3bf1395f..669970789b 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -212,6 +212,24 @@ php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length)
/* }}} */
+/* {{{ php_mysqlnd_net_store_length_size */
+size_t
+php_mysqlnd_net_store_length_size(uint64_t length)
+{
+ if (length < (uint64_t) L64(251)) {
+ return 1;
+ }
+ if (length < (uint64_t) L64(65536)) {
+ return 3;
+ }
+ if (length < (uint64_t) L64(16777216)) {
+ return 4;
+ }
+ return 8;
+}
+/* }}} */
+
+
/* {{{ php_mysqlnd_read_error_from_line */
static enum_func_status
php_mysqlnd_read_error_from_line(zend_uchar *buf, size_t buf_len,
@@ -459,7 +477,7 @@ void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation TSRML
/* }}} */
-#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 1024)
+#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 4096)
/* {{{ php_mysqlnd_auth_write */
static
@@ -540,6 +558,52 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC
p+= len;
*p++= '\0';
}
+
+ if (packet->connect_attr && zend_hash_num_elements(packet->connect_attr)) {
+ HashPosition pos_value;
+ const char ** entry_value;
+ size_t ca_payload_len = 0;
+ zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
+ while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
+ char *s_key;
+ unsigned int s_len;
+ unsigned long num_key;
+ size_t value_len = strlen(*entry_value);
+
+ if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, 0, &pos_value)) {
+ ca_payload_len += php_mysqlnd_net_store_length_size(s_len);
+ ca_payload_len += s_len;
+ ca_payload_len += php_mysqlnd_net_store_length_size(value_len);
+ ca_payload_len += value_len;
+ }
+ zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
+ }
+
+ if ((sizeof(buffer) - (p - buffer)) >= (ca_payload_len + php_mysqlnd_net_store_length_size(ca_payload_len))) {
+ p = php_mysqlnd_net_store_length(p, ca_payload_len);
+
+ zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
+ while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
+ char *s_key;
+ unsigned int s_len;
+ unsigned long num_key;
+ size_t value_len = strlen(*entry_value);
+ if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, 0, &pos_value)) {
+ /* copy key */
+ p = php_mysqlnd_net_store_length(p, s_len);
+ memcpy(p, s_key, s_len);
+ p+= s_len;
+ /* copy value */
+ p = php_mysqlnd_net_store_length(p, value_len);
+ memcpy(p, *entry_value, value_len);
+ p+= value_len;
+ }
+ zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
+ }
+ } else {
+ /* cannot put the data - skip */
+ }
+ }
}
if (packet->is_change_user_packet) {
if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h
index e9c9024d04..26dd4c65ae 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.h
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.h
@@ -103,7 +103,7 @@ typedef struct st_mysqlnd_packet_auth {
zend_bool send_auth_data;
zend_bool is_change_user_packet;
zend_bool silent;
-
+ HashTable *connect_attr;
} MYSQLND_PACKET_AUTH;
/* Auth response packet */
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 74577ac495..cf8b159556 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -159,6 +159,7 @@ static ZEND_RSRC_DTOR_FUNC(file_context_dtor)
static void file_globals_ctor(php_file_globals *file_globals_p TSRMLS_DC)
{
FG(pclose_ret) = 0;
+ FG(pclose_wait) = 0;
FG(user_stream_current_filename) = NULL;
FG(def_chunk_size) = PHP_SOCK_CHUNK_SIZE;
FG(wrapper_errors) = NULL;
@@ -960,7 +961,9 @@ PHP_FUNCTION(pclose)
PHP_STREAM_TO_ZVAL(stream, &arg1);
+ FG(pclose_wait) = 1;
zend_list_delete(stream->rsrc_id);
+ FG(pclose_wait) = 0;
RETURN_LONG(FG(pclose_ret));
}
/* }}} */
diff --git a/ext/standard/file.h b/ext/standard/file.h
index 0a4512ecd4..2bcdfd64bf 100644
--- a/ext/standard/file.h
+++ b/ext/standard/file.h
@@ -115,7 +115,7 @@ typedef struct _php_meta_tags_data {
php_meta_tags_token php_next_meta_token(php_meta_tags_data * TSRMLS_DC);
typedef struct {
- int pclose_ret;
+ int pclose_ret;
size_t def_chunk_size;
long auto_detect_line_endings;
long default_socket_timeout;
@@ -126,6 +126,7 @@ typedef struct {
HashTable *stream_wrappers; /* per-request copy of url_stream_wrappers_hash */
HashTable *stream_filters; /* per-request copy of stream_filters_hash */
HashTable *wrapper_errors; /* key: wrapper address; value: linked list of char* */
+ int pclose_wait;
} php_file_globals;
#ifdef ZTS
diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
index 1edfe78849..4e39a40be4 100644
--- a/ext/standard/proc_open.c
+++ b/ext/standard/proc_open.c
@@ -208,6 +208,7 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
DWORD wstatus;
#elif HAVE_SYS_WAIT_H
int wstatus;
+ int waitpid_options = 0;
pid_t wait_pid;
#endif
@@ -220,18 +221,27 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
}
#ifdef PHP_WIN32
- WaitForSingleObject(proc->childHandle, INFINITE);
+ if (FG(pclose_wait)) {
+ WaitForSingleObject(proc->childHandle, INFINITE);
+ }
GetExitCodeProcess(proc->childHandle, &wstatus);
- FG(pclose_ret) = wstatus;
+ if (wstatus == STILL_ACTIVE) {
+ FG(pclose_ret) = -1;
+ } else {
+ FG(pclose_ret) = wstatus;
+ }
CloseHandle(proc->childHandle);
#elif HAVE_SYS_WAIT_H
+ if (!FG(pclose_wait)) {
+ waitpid_options = WNOHANG;
+ }
do {
- wait_pid = waitpid(proc->child, &wstatus, 0);
+ wait_pid = waitpid(proc->child, &wstatus, waitpid_options);
} while (wait_pid == -1 && errno == EINTR);
- if (wait_pid == -1) {
+ if (wait_pid <= 0) {
FG(pclose_ret) = -1;
} else {
if (WIFEXITED(wstatus))
@@ -300,7 +310,9 @@ PHP_FUNCTION(proc_close)
ZEND_FETCH_RESOURCE(proc, struct php_process_handle *, &zproc, -1, "process", le_proc_open);
+ FG(pclose_wait) = 1;
zend_list_delete(Z_LVAL_P(zproc));
+ FG(pclose_wait) = 0;
RETURN_LONG(FG(pclose_ret));
}
/* }}} */
diff --git a/ext/standard/string.c b/ext/standard/string.c
index b4f4fcbd2d..e245ce3fb6 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -2851,7 +2851,7 @@ static inline void php_strtr_populate_shift(PATNREPL *patterns, int patnum, int
}
/* }}} */
/* {{{ php_strtr_compare_hash_suffix */
-static int php_strtr_compare_hash_suffix(const void *a, const void *b, void *ctx_g)
+static int php_strtr_compare_hash_suffix(const void *a, const void *b TSRMLS_DC, void *ctx_g)
{
const PPRES *res = ctx_g;
const PATNREPL *pnr_a = a,
@@ -2877,62 +2877,6 @@ static int php_strtr_compare_hash_suffix(const void *a, const void *b, void *ctx
}
}
/* }}} */
-/* {{{ Sorting (no zend_qsort_r in this PHP version) */
-#define HS_LEFT(i) ((i) * 2 + 1)
-#define HS_RIGHT(i) ((i) * 2 + 2)
-#define HS_PARENT(i) (((i) - 1) / 2);
-#define HS_OFF(data, i) ((void *)(&((data)->arr)[i]))
-#define HS_CMP_CALL(data, i1, i2) \
- (php_strtr_compare_hash_suffix(HS_OFF((data), (i1)), HS_OFF((data), (i2)), (data)->res))
-struct hs_data {
- PATNREPL *arr;
- size_t nel;
- size_t heapel;
- PPRES *res;
-};
-static inline void php_strtr_swap(PATNREPL *a, PATNREPL *b)
-{
- PATNREPL tmp = *a;
- *a = *b;
- *b = tmp;
-}
-static inline void php_strtr_fix_heap(struct hs_data *data, size_t i)
-{
- size_t li = HS_LEFT(i),
- ri = HS_RIGHT(i),
- largei;
- if (li < data->heapel && HS_CMP_CALL(data, li, i) > 0) {
- largei = li;
- } else {
- largei = i;
- }
- if (ri < data->heapel && HS_CMP_CALL(data, ri, largei) > 0) {
- largei = ri;
- }
- if (largei != i) {
- php_strtr_swap(HS_OFF(data, i), HS_OFF(data, largei));
- php_strtr_fix_heap(data, largei);
- }
-}
-static inline void php_strtr_build_heap(struct hs_data *data)
-{
- size_t i;
- for (i = data->nel / 2; i > 0; i--) {
- php_strtr_fix_heap(data, i - 1);
- }
-}
-static inline void php_strtr_heapsort(PATNREPL *arr, size_t nel, PPRES *res)
-{
- struct hs_data data = { arr, nel, nel, res };
- size_t i;
- php_strtr_build_heap(&data);
- for (i = nel; i > 1; i--) {
- php_strtr_swap(arr, HS_OFF(&data, i - 1));
- data.heapel--;
- php_strtr_fix_heap(&data, 0);
- }
-}
-/* }}} */
/* {{{ php_strtr_free_strp */
static void php_strtr_free_strp(void *strp)
{
@@ -3030,7 +2974,13 @@ static PPRES *php_strtr_array_prepare(STR *text, PATNREPL *patterns, int patnum,
res->patterns = safe_emalloc(patnum, sizeof(*res->patterns), 0);
memcpy(res->patterns, patterns, sizeof(*patterns) * patnum);
- php_strtr_heapsort(res->patterns, patnum, res);
+#ifdef ZTS
+ zend_qsort_r(res->patterns, patnum, sizeof(*res->patterns),
+ php_strtr_compare_hash_suffix, res, NULL); /* tsrmls not needed */
+#else
+ zend_qsort_r(res->patterns, patnum, sizeof(*res->patterns),
+ php_strtr_compare_hash_suffix, res);
+#endif
res->prefix = safe_emalloc(patnum, sizeof(*res->prefix), 0);
for (i = 0; i < patnum; i++) {