com php-src: Merge remote-tracking branch 'origin/PHP-5.6' into str_size_and_int64_56_backport: Zend/zend _ast.c Zend/zend_language_parser.y
ext/fileinfo/l ibmagic/softmagic.c ext/hash/hash.c ext/hash/php_hash .h ext/mcrypt/mcrypt.c ext/mysqlnd/mysqlnd.c ext/my sqlnd/mysqlnd.h
ext/mysqlnd/mysqlnd_priv.h ext/mysqln d/mysqlnd_ps.c ext/mysqlnd/mysqlnd_result.c ext/mys qlnd/mysqlnd_result.h ext/mysqlnd/mysqlnd_result_meta .c
ext/mysqlnd/mysqlnd_structs.h ex
| From: | Anatol Belski | Date: | Sun, 09 Mar 2014 14:00:36 +0000 |
| Subject: | com php-src: Merge remote-tracking branch 'origin/PHP-5.6' into str_size_and_int64_56_backport: Zend/zend _ast.c Zend/zend_language_parser.y ext/fileinfo/l ibmagic/softmagic.c ext/hash/hash.c ext/hash/php_hash .h ext/mcrypt/mcrypt.c ext/mysqlnd/mysqlnd.c ext/my sqlnd/mysqlnd.h ext/mysqlnd/mysqlnd_priv.h ext/mysqln d/mysqlnd_ps.c ext/mysqlnd/mysqlnd_result.c ext/mys qlnd/mysqlnd_result.h ext/mysqlnd/mysqlnd_result_meta .c ext/mysqlnd/mysqlnd_structs.h ex |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-76417@lists.php.net to get a copy of this message | ||
Commit: 7b8ba8e3e3f3ce3f409439ba104e36105bd779ff
Author: Anatol Belski <ab@php.net> Sun, 9 Mar 2014 15:00:36 +0100
Parents: b186b2774abe3e63f7c4b40084a76c5733589493 7d0493219c1690aba8291375b6f8a6e620d809fc
Branches: str_size_and_int64_56_backport
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=7b8ba8e3e3f3ce3f409439ba104e36105bd779ff
Log:
Merge remote-tracking branch 'origin/PHP-5.6' into str_size_and_int64_56_backport
* origin/PHP-5.6: (43 commits)
updated NEWS
removed the libsqlite patch as it's not relevant anymore
updated bundled libsqlite to 3.8.3.1
add OPSYS_Z_CPM missing constant
Update php.ini files (new openssl directives)
Fixed null termination
Updated NEWS for #65545
Updated NEWS for #65545
Add fread(length) method
Updated news for #66822
Allow T_POW in constant expressions
Fix typo
Fix #66698: Add fnv1a32 and fnv1a64 hash options
Fix HTML entity table generation
Add test for bug #62102 / RFC 2144
Whitespace.
Misc cleanup including adding the version number
Fix order in NEWS
Add CVE ref (not known at release time)
Fix NEWS for 5.5.11 fix (really not in 5.5.10)
...
Conflicts:
ext/mcrypt/mcrypt..c
ext/mysqlnd/mysqlnd.h
ext/mysqlnd/mysqlnd_ps.c
ext/mysqlnd/mysqlnd_result.c
ext/mysqlnd/mysqlnd_result.h
ext/mysqlnd/mysqlnd_structs.h
ext/openssl/openssl.c
ext/openssl/xp_ssl.c
ext/zip/php_zip.c
Bugs:
https://bugs.php.net/65545
https://bugs.php.net/66822
https://bugs.php.net/66698
https://bugs.php.net/62102
Changed paths:
MM Zend/zend_ast.c
MM Zend/zend_language_parser.y
MM ext/fileinfo/libmagic/softmagic.c
MM ext/hash/hash.c
MM ext/hash/php_hash.h
MM ext/mcrypt/mcrypt.c
MM ext/mysqlnd/mysqlnd.c
MM ext/mysqlnd/mysqlnd.h
MM ext/mysqlnd/mysqlnd_priv.h
MM ext/mysqlnd/mysqlnd_ps.c
MM ext/mysqlnd/mysqlnd_result.c
MM ext/mysqlnd/mysqlnd_result.h
MM ext/mysqlnd/mysqlnd_result_meta.c
MM ext/mysqlnd/mysqlnd_structs.h
MM ext/openssl/openssl.c
MM ext/openssl/xp_ssl.c
MM ext/spl/spl_directory.c
MM ext/zip/php_zip.c
diff --cc ext/mcrypt/mcrypt.c index ec847d3,70a458d..3a0ce2e --- a/ext/mcrypt/mcrypt.c +++ b/ext/mcrypt/mcrypt.c @@@ -656,12 -615,12 +615,12 @@@ PHP_FUNCTION(mcrypt_generic { zval *mcryptind; char *data; - int data_len; + php_size_t data_len; php_mcrypt *pm; - unsigned char* data_s; - size_t block_size, data_size; + char* data_s; - int block_size, data_size; ++ php_size_t block_size, data_size; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rS", &mcryptind, &data, &data_len) == FAILURE) { return; } @@@ -1165,7 -1124,116 +1124,116 @@@ PHP_FUNCTION(mcrypt_get_cipher_name } /* }}} */ - static void php_mcrypt_do_crypt(char* cipher, const char *key, php_size_t key_len, const char *data, php_size_t data_len, char *mode, const char *iv, php_size_t iv_len, int argc, php_int_t dencrypt, zval* return_value TSRMLS_DC) /* {{{ */ + static char *php_mcrypt_get_key_size_str( - int max_key_size, const int *key_sizes, int key_size_count) /* {{{ */ ++ php_size_t max_key_size, const php_size_t *key_sizes, php_size_t key_size_count) /* {{{ */ + { + if (key_size_count == 0) { + char *str; - spprintf(&str, 0, "Only keys of size 1 to %d supported", max_key_size); ++ spprintf(&str, 0, "Only keys of size 1 to %pd supported", max_key_size); + return str; + } else if (key_size_count == 1) { + char *str; - spprintf(&str, 0, "Only keys of size %d supported", key_sizes[0]); ++ spprintf(&str, 0, "Only keys of size %pd supported", key_sizes[0]); + return str; + } else { - int i; ++ php_size_t i; + smart_str str = {0}; + smart_str_appends(&str, "Only keys of sizes "); + + for (i = 0; i < key_size_count; ++i) { - if (i == key_size_count - 1) { ++ if (i + 1 == key_size_count) { + smart_str_appends(&str, " or "); + } else if (i != 0) { + smart_str_appends(&str, ", "); + } + + smart_str_append_long(&str, key_sizes[i]); + } + + smart_str_appends(&str, " supported"); + smart_str_0(&str); + return str.c; + } + } + /* }}} */ + + static zend_bool php_mcrypt_is_valid_key_size( - int key_size, int max_key_size, int *key_sizes, int key_size_count) /* {{{ */ ++ php_size_t key_size, php_size_t max_key_size, php_size_t *key_sizes, php_size_t key_size_count) /* {{{ */ + { - int i; ++ php_size_t i; + - if (key_size <= 0 || key_size > max_key_size) { ++ if (key_size == 0 || key_size > max_key_size) { + return 0; + } + + if (key_size_count == 0) { + /* All key sizes are valid */ + return 1; + } + + for (i = 0; i < key_size_count; i++) { + if (key_sizes[i] == key_size) { + return 1; + } + } + + return 0; + } + /* }}} */ + -static int php_mcrypt_ensure_valid_key_size(MCRYPT td, int key_size TSRMLS_DC) /* {{{ */ ++static int php_mcrypt_ensure_valid_key_size(MCRYPT td, php_size_t key_size TSRMLS_DC) /* {{{ */ + { - int key_size_count; - int max_key_size = mcrypt_enc_get_key_size(td); - int *key_sizes = mcrypt_enc_get_supported_key_sizes(td, &key_size_count); ++ php_size_t key_size_count; ++ php_size_t max_key_size = mcrypt_enc_get_key_size(td); ++ php_size_t *key_sizes = mcrypt_enc_get_supported_key_sizes(td, &key_size_count); + + zend_bool is_valid_key_size = php_mcrypt_is_valid_key_size( + key_size, max_key_size, key_sizes, key_size_count + ); + if (!is_valid_key_size) { + char *key_size_str = php_mcrypt_get_key_size_str( + max_key_size, key_sizes, key_size_count + ); + php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Key of size %d not supported by this algorithm. %s", key_size, key_size_str ++ "Key of size %pd not supported by this algorithm. %s", key_size, key_size_str + ); + efree(key_size_str); + } + + if (key_sizes) { + mcrypt_free(key_sizes); + } + + return is_valid_key_size ? SUCCESS : FAILURE; + } + /* }}} */ + -static int php_mcrypt_ensure_valid_iv(MCRYPT td, const char *iv, int iv_size TSRMLS_DC) /* {{{ */ ++static int php_mcrypt_ensure_valid_iv(MCRYPT td, const char *iv, php_size_t iv_size TSRMLS_DC) /* {{{ */ + { + if (mcrypt_enc_mode_has_iv(td) == 1) { - int expected_iv_size = mcrypt_enc_get_iv_size(td); ++ php_size_t expected_iv_size = mcrypt_enc_get_iv_size(td); + + if (!iv) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Encryption mode requires an initialization vector of size %d", expected_iv_size ++ "Encryption mode requires an initialization vector of size %pd", expected_iv_size + ); + return FAILURE; + } + + if (iv_size != expected_iv_size) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Received initialization vector of size %d, but size %d is required " ++ "Received initialization vector of size %pd, but size %pd is required " + "for this encryption mode", iv_size, expected_iv_size + ); + return FAILURE; + } + } + + return SUCCESS; + } + /* }}} */ + -static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, const char *data, int data_len, char *mode, const char *iv, int iv_len, int dencrypt, zval* return_value TSRMLS_DC) /* {{{ */ ++static void php_mcrypt_do_crypt(char* cipher, const char *key, php_size_t key_len, const char *data, php_size_t data_len, char *mode, const char *iv, php_size_t iv_len, int dencrypt, zval* return_value TSRMLS_DC) /* {{{ */ { char *cipher_dir_string; char *module_dir_string; @@@ -1237,13 -1261,9 +1261,9 @@@ /* Check blocksize */ if (mcrypt_enc_is_block_mode(td) == 1) { /* It's a block algorithm */ - block_size = mcrypt_enc_get_block_size(td); - if (0 == data_len) { - data_size = block_size; - } else { - data_size = (((data_len - 1) / block_size) + 1) * block_size; - } - data_s = emalloc(data_size); - int block_size = mcrypt_enc_get_block_size(td); ++ php_size_t block_size = mcrypt_enc_get_block_size(td); + data_size = (((data_len - 1) / block_size) + 1) * block_size; + data_s = emalloc(data_size + 1); memset(data_s, 0, data_size); memcpy(data_s, data, data_len); } else { /* It's not a block algorithm */ @@@ -1281,15 -1296,15 +1296,15 @@@ OFB crypt/decrypt data using key key with cipher cipher starting with iv */ PHP_FUNCTION(mcrypt_encrypt) { - zval **mode; - char *cipher, *key, *data, *iv = NULL; - php_size_t data_len, key_len, cipher_len, iv_len = 0; + char *cipher, *key, *data, *mode, *iv = NULL; - int cipher_len, key_len, data_len, mode_len, iv_len = 0; ++ php_size_t cipher_len, key_len, data_len, mode_len, iv_len = 0; - MCRYPT_GET_CRYPT_ARGS - - convert_to_string_ex(mode); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssss|s", &cipher, &cipher_len, + &key, &key_len, &data, &data_len, &mode, &mode_len, &iv, &iv_len) == FAILURE) { + return; + } - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_ENCRYPT, return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, mode, iv, iv_len, MCRYPT_ENCRYPT, return_value TSRMLS_CC); } /* }}} */ @@@ -1297,15 -1312,15 +1312,15 @@@ OFB crypt/decrypt data using key key with cipher cipher starting with iv */ PHP_FUNCTION(mcrypt_decrypt) { - zval **mode; - char *cipher, *key, *data, *iv = NULL; - php_size_t cipher_len, key_len, data_len, iv_len = 0; + char *cipher, *key, *data, *mode, *iv = NULL; - int cipher_len, key_len, data_len, mode_len, iv_len = 0; ++ php_size_t cipher_len, key_len, data_len, mode_len, iv_len = 0; - MCRYPT_GET_CRYPT_ARGS - - convert_to_string_ex(mode); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssss|s", &cipher, &cipher_len, + &key, &key_len, &data, &data_len, &mode, &mode_len, &iv, &iv_len) == FAILURE) { + return; + } - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_DECRYPT, return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, mode, iv, iv_len, MCRYPT_DECRYPT, return_value TSRMLS_CC); } /* }}} */ @@@ -1319,9 -1334,9 +1334,9 @@@ PHP_FUNCTION(mcrypt_ecb MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ecb", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ecb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ @@@ -1335,9 -1350,9 +1350,9 @@@ PHP_FUNCTION(mcrypt_cbc MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cbc", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cbc", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ @@@ -1351,9 -1366,9 +1366,9 @@@ PHP_FUNCTION(mcrypt_cfb MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cfb", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cfb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ @@@ -1367,9 -1382,9 +1382,9 @@@ PHP_FUNCTION(mcrypt_ofb MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ofb", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ofb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ diff --cc ext/mysqlnd/mysqlnd_ps.c index 6f4e2a1,dc97d2d..a988090 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@@ -39,16 -39,8 +39,8 @@@ const char * const mysqlnd_stmt_not_pre /* Exported by mysqlnd_ps_codec.c */ enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC); - enum_func_status mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES *result, void *param, - php_uint_t flags, - zend_bool *fetched_anything TSRMLS_DC); - - enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, - php_uint_t flags, - zend_bool *fetched_anything TSRMLS_DC); - static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC); -static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC); +static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, php_uint_t param_no TSRMLS_DC); /* {{{ mysqlnd_stmt::store_result */ @@@ -729,12 -723,13 +723,13 @@@ MYSQLND_METHOD(mysqlnd_stmt, execute)(M /* {{{ mysqlnd_stmt_fetch_row_buffered */ enum_func_status - mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES *result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { MYSQLND_STMT * s = (MYSQLND_STMT *) param; MYSQLND_STMT_DATA * stmt = s? s->data:NULL; MYSQLND_RES_BUFFERED *set = result->stored_data; - php_uint_t field_count = result->meta->field_count; + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; DBG_ENTER("mysqlnd_stmt_fetch_row_buffered"); *fetched_anything = FALSE; @@@ -746,8 -741,7 +741,7 @@@ { /* The user could have skipped binding - don't crash*/ if (stmt->result_bind) { - unsigned int i; + php_uint_t i; - MYSQLND_RES_METADATA * meta = result->meta; zval **current_row = set->data_cursor; if (NULL == current_row[0]) { @@@ -825,8 -819,8 +819,8 @@@ /* {{{ mysqlnd_stmt_fetch_row_unbuffered */ - static enum_func_status - mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) + enum_func_status -mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; MYSQLND_STMT * s = (MYSQLND_STMT *) param; @@@ -857,13 -852,13 +852,13 @@@ /* If we skip rows (stmt == NULL || stmt->result_bind == NULL) we have to - result->m.unbuffered_free_last_data() before it. The function returns always true. + result->unbuf->m.free_last_data() before it. The function returns always true. */ if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { - unsigned int i, field_count = result->field_count; + php_uint_t i, field_count = result->field_count; if (!row_packet->skip_extraction) { - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@@ -891,8 -886,8 +886,8 @@@ zval_dtor(stmt->result_bind[i].zv); #endif if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) { - if ((Z_TYPE_P(data) == IS_STRING) && (result->meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { - result->meta->fields[i].max_length = Z_STRSIZE_P(data); - if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) { - meta->fields[i].max_length = Z_STRLEN_P(data); ++ if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { ++ meta->fields[i].max_length = Z_STRSIZE_P(data); } stmt->result_bind[i].zv->value = data->value; /* copied data, thus also the ownership. Thus null data */ @@@ -993,7 -988,7 +988,7 @@@ MYSQLND_METHOD(mysqlnd_stmt, use_result /* {{{ mysqlnd_fetch_row_cursor */ enum_func_status - mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; MYSQLND_STMT * s = (MYSQLND_STMT *) param; @@@ -1038,10 -1033,11 +1033,11 @@@ memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status)); if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int i, field_count = result->field_count; + php_uint_t i, field_count = result->field_count; if (!row_packet->skip_extraction) { - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@@ -1072,8 -1068,8 +1068,8 @@@ DBG_INF_FMT("i=%u bound_var=%p type=%u refc=%u", i, stmt->result_bind[i].zv, Z_TYPE_P(data), Z_REFCOUNT_P(stmt->result_bind[i].zv)); if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data))) { - if ((Z_TYPE_P(data) == IS_STRING) && (result->meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { - result->meta->fields[i].max_length = Z_STRSIZE_P(data); - if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) { - meta->fields[i].max_length = Z_STRLEN_P(data); ++ if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { ++ meta->fields[i].max_length = Z_STRSIZE_P(data); } stmt->result_bind[i].zv->value = data->value; /* copied data, thus also the ownership. Thus null data */ diff --cc ext/mysqlnd/mysqlnd_result.c index 67e7d45,75e7456..226ed6e --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@@ -33,30 -33,31 +33,31 @@@ #define MYSQLND_SILENT - /* {{{ mysqlnd_res::initialize_result_set_rest */ + /* {{{ mysqlnd_result_buffered::initialize_result_set_rest */ static enum_func_status - MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta, + MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC) { - unsigned int i; + php_uint_t i; - zval **data_cursor = result->stored_data? result->stored_data->data:NULL; - zval **data_begin = result->stored_data? result->stored_data->data:NULL; - php_uint_t field_count = result->meta? result->meta->field_count : 0; - uint64_t row_count = result->stored_data? result->stored_data->row_count:0; + zval **data_cursor = result->data; + zval **data_begin = result->data; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; + uint64_t row_count = result->row_count; enum_func_status ret = PASS; - DBG_ENTER("mysqlnd_res::initialize_result_set_rest"); + DBG_ENTER("mysqlnd_result_buffered::initialize_result_set_rest"); - if (!data_cursor || row_count == result->stored_data->initialized_rows) { + if (!data_cursor || row_count == result->initialized_rows) { DBG_RETURN(ret); } -- while ((data_cursor - data_begin) < (int)(row_count * field_count)) { ++ while ((data_cursor - data_begin) < (ptrdiff_t)(row_count * field_count)) { if (NULL == data_cursor[0]) { enum_func_status rc = result->m.row_decoder( - result->stored_data->row_buffers[(data_cursor - data_begin) / field_count], + result->row_buffers[(data_cursor - data_begin) / field_count], data_cursor, - result->meta->field_count, - result->meta->fields, - result->conn->options->int_and_float_native, - result->conn->stats TSRMLS_CC); + meta->field_count, + meta->fields, + int_and_float_native, + stats TSRMLS_CC); if (rc != PASS) { ret = FAIL; break; @@@ -69,9 -70,9 +70,9 @@@ Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE_P(data_cursor[i]) >= IS_STRING) { - php_uint_t len = Z_STRSIZE_P(data_cursor[i]); - if (result->meta->fields[i].max_length < len) { - result->meta->fields[i].max_length = len; - unsigned long len = Z_STRLEN_P(data_cursor[i]); ++ php_size_t len = Z_STRSIZE_P(data_cursor[i]); + if (meta->fields[i].max_length < len) { + meta->fields[i].max_length = len; } } } @@@ -139,13 -140,13 +140,13 @@@ MYSQLND_METHOD(mysqlnd_result_unbuffere DBG_VOID_RETURN; } + DBG_INF_FMT("field_count=%u", unbuf->field_count); if (unbuf->last_row_data) { - unsigned int i, ctor_called_count = 0; + php_uint_t i, ctor_called_count = 0; zend_bool copy_ctor_called; - MYSQLND_STATS *global_stats = result->conn? result->conn->stats:NULL; - for (i = 0; i < result->field_count; i++) { - mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, ©_ctor_called TSRMLS_CC); + for (i = 0; i < unbuf->field_count; i++) { + mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), unbuf->ps ? MYSQLND_RES_PS_UNBUF : MYSQLND_RES_NORMAL, ©_ctor_called TSRMLS_CC); if (copy_ctor_called) { ++ctor_called_count; } @@@ -173,12 -175,41 +175,41 @@@ /* }}} */ - /* {{{ mysqlnd_res::free_buffered_data */ + /* {{{ mysqlnd_result_unbuffered::free_result */ static void - MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED * const result, MYSQLND_STATS * const global_stats TSRMLS_DC) { - MYSQLND_RES_BUFFERED *set = result->stored_data; - php_uint_t field_count = result->field_count; + DBG_ENTER("mysqlnd_result_unbuffered, free_result"); + result->m.free_last_data(result, global_stats TSRMLS_CC); + + if (result->lengths) { + mnd_pefree(result->lengths, result->persistent); + result->lengths = NULL; + } + + /* must be free before because references the memory pool */ + if (result->row_packet) { + PACKET_FREE(result->row_packet); + result->row_packet = NULL; + } + + if (result->result_set_memory_pool) { + mysqlnd_mempool_destroy(result->result_set_memory_pool TSRMLS_CC); + result->result_set_memory_pool = NULL; + } + + + mnd_pefree(result, result->persistent); + DBG_VOID_RETURN; + } + /* }}} */ + + + /* {{{ mysqlnd_result_buffered::free_result */ + static void + MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set TSRMLS_DC) + { - unsigned int field_count = set->field_count; ++ php_uint_t field_count = set->field_count; int64_t row; DBG_ENTER("mysqlnd_res::free_buffered_data"); @@@ -559,12 -589,12 +589,12 @@@ mysqlnd_query_read_result_set_header(MY of PHP, to be called as separate function. But let's have it for completeness. */ -static unsigned long * +static php_uint_t * - mysqlnd_fetch_lengths_buffered(MYSQLND_RES * const result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { - unsigned int i; + php_uint_t i; zval **previous_row; - MYSQLND_RES_BUFFERED *set = result->stored_data; + MYSQLND_RES_BUFFERED *set = result; /* If: @@@ -579,9 -609,9 +609,9 @@@ return NULL;/* No rows or no more rows */ } - previous_row = set->data_cursor - result->meta->field_count; - for (i = 0; i < result->meta->field_count; i++) { + previous_row = set->data_cursor - result->field_count; + for (i = 0; i < result->field_count; i++) { - result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRLEN_P(previous_row[i]); + result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRSIZE_P(previous_row[i]); } return result->lengths; @@@ -589,45 -619,52 +619,52 @@@ /* }}} */ - /* {{{ mysqlnd_fetch_lengths_unbuffered */ + /* {{{ mysqlnd_result_unbuffered::fetch_lengths */ -static unsigned long * +static php_uint_t * - mysqlnd_fetch_lengths_unbuffered(MYSQLND_RES * const result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result TSRMLS_DC) { /* simulate output of libmysql */ - return (!result->unbuf || result->unbuf->last_row_data || result->unbuf->eof_reached)? result->lengths:NULL; + return (result->last_row_data || result->eof_reached)? result->lengths : NULL; } /* }}} */ /* {{{ mysqlnd_res::fetch_lengths */ - PHPAPI php_uint_t * _mysqlnd_fetch_lengths(MYSQLND_RES * const result TSRMLS_DC) -static unsigned long * ++static php_uint_t * + MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC) { - return result->m.fetch_lengths? result->m.fetch_lengths(result TSRMLS_CC) : NULL; - unsigned long * ret; ++ php_uint_t * ret; + DBG_ENTER("mysqlnd_res::fetch_lengths"); + ret = result->stored_data && result->stored_data->m.fetch_lengths ? + result->stored_data->m.fetch_lengths(result->stored_data TSRMLS_CC) : + (result->unbuf && result->unbuf->m.fetch_lengths ? + result->unbuf->m.fetch_lengths(result->unbuf TSRMLS_CC) : + NULL + ); + DBG_RETURN(ret); } /* }}} */ - /* {{{ mysqlnd_fetch_row_unbuffered_c */ - static MYSQLND_ROW_C - mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) + /* {{{ mysqlnd_result_unbuffered::fetch_row_c */ + static enum_func_status -MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; - MYSQLND_ROW_C retrow = NULL; - php_uint_t i, - field_count = result->field_count; - MYSQLND_PACKET_ROW *row_packet = result->row_packet; - php_uint_t *lengths = result->lengths; + MYSQLND_ROW_C *row = (MYSQLND_ROW_C *) param; + MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet; + const MYSQLND_RES_METADATA * const meta = result->meta; - DBG_ENTER("mysqlnd_fetch_row_unbuffered_c"); + DBG_ENTER("mysqlnd_result_unbuffered::fetch_row_c"); + *fetched_anything = FALSE; if (result->unbuf->eof_reached) { /* No more rows obviously */ - DBG_RETURN(retrow); + DBG_RETURN(PASS); } if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) { - SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, - UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); - DBG_RETURN(retrow); + SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + DBG_RETURN(FAIL); } if (!row_packet) { /* Not fully initialized object that is being cleaned up */ @@@ -653,46 -688,51 +688,51 @@@ MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF); if (!row_packet->skip_extraction) { - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; - - enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer, - result->unbuf->last_row_data, - row_packet->field_count, - row_packet->fields_metadata, - result->conn->options->int_and_float_native, - result->conn->stats TSRMLS_CC); - unsigned int i, field_count = meta->field_count; ++ php_uint_t i, field_count = meta->field_count; + + enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer, + result->unbuf->last_row_data, + field_count, + row_packet->fields_metadata, + result->conn->options->int_and_float_native, + result->conn->stats TSRMLS_CC); if (PASS != rc) { - DBG_RETURN(retrow); + DBG_RETURN(FAIL); } + { + *row = mnd_malloc(field_count * sizeof(char *)); + if (*row) { + MYSQLND_FIELD * field = meta->fields; - unsigned long * lengths = result->unbuf->lengths; ++ php_uint_t * lengths = result->unbuf->lengths; + + for (i = 0; i < field_count; i++, field++) { + zval * data = result->unbuf->last_row_data[i]; - unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); ++ php_size_t len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data); + + /* BEGIN difference between normal normal fetch and _c */ + if (Z_TYPE_P(data) != IS_NULL) { + convert_to_string(data); + (*row)[i] = Z_STRVAL_P(data); + } else { + (*row)[i] = NULL; + } + /* END difference between normal normal fetch and _c */ - retrow = mnd_malloc(result->field_count * sizeof(char *)); - if (retrow) { - for (i = 0; i < field_count; i++, field++, hash_key++) { - zval *data = result->unbuf->last_row_data[i]; - php_size_t len; - - if (Z_TYPE_P(data) != IS_NULL) { - convert_to_string(data); - retrow[i] = Z_STRVAL_P(data); - len = Z_STRSIZE_P(data); - } else { - retrow[i] = NULL; - len = 0; - } - - if (lengths) { - lengths[i] = len; - } + if (lengths) { + lengths[i] = len; + } - if (field->max_length < len) { - field->max_length = len; + if (field->max_length < len) { + field->max_length = len; + } } + } else { + SET_OOM_ERROR(*result->conn->error_info); } - } else { - SET_OOM_ERROR(*result->conn->error_info); } } + result->unbuf->row_count++; + *fetched_anything = TRUE; } else if (ret == FAIL) { if (row_packet->error_info.error_no) { COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info); @@@ -724,9 -765,9 +765,9 @@@ /* }}} */ - /* {{{ mysqlnd_fetch_row_unbuffered */ + /* {{{ mysqlnd_result_unbuffered::fetch_row */ static enum_func_status - mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; zval *row = (zval *) param; @@@ -765,13 -807,9 +807,9 @@@ MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF); if (!row_packet->skip_extraction) { - HashTable *row_ht = Z_ARRVAL_P(row); - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; - php_uint_t i, field_count = result->field_count; - php_uint_t *lengths = result->lengths; - unsigned int i, field_count = meta->field_count; ++ php_uint_t i, field_count = meta->field_count; - enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer, + enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer, result->unbuf->last_row_data, field_count, row_packet->fields_metadata, @@@ -780,46 -818,51 +818,51 @@@ if (PASS != rc) { DBG_RETURN(FAIL); } - for (i = 0; i < field_count; i++, field++, hash_key++) { - zval *data = result->unbuf->last_row_data[i]; - php_size_t len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data); + { + HashTable * row_ht = Z_ARRVAL_P(row); + MYSQLND_FIELD * field = meta->fields; - unsigned long * lengths = result->unbuf->lengths; ++ php_size_t * lengths = result->unbuf->lengths; + + for (i = 0; i < field_count; i++, field++) { + zval * data = result->unbuf->last_row_data[i]; - unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); ++ php_size_t = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data); + + if (flags & MYSQLND_FETCH_NUM) { + Z_ADDREF_P(data); + zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL); + } + if (flags & MYSQLND_FETCH_ASSOC) { + /* zend_hash_quick_update needs length + trailing zero */ + /* QQ: Error handling ? */ + /* + zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether + the index is a numeric and convert it to it. This however means constant + hashing of the column name, which is not needed as it can be precomputed. + */ + Z_ADDREF_P(data); + if (meta->zend_hash_keys[i].is_numeric == FALSE) { + zend_hash_quick_update(Z_ARRVAL_P(row), + field->name, + field->name_length + 1, + meta->zend_hash_keys[i].key, + (void *) &data, sizeof(zval *), NULL); + } else { + zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, (void *) &data, sizeof(zval *), NULL); + } + } - if (lengths) { - lengths[i] = len; - } + if (lengths) { + lengths[i] = len; + } - if (flags & MYSQLND_FETCH_NUM) { - Z_ADDREF_P(data); - zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL); - } - if (flags & MYSQLND_FETCH_ASSOC) { - /* zend_hash_quick_update needs length + trailing zero */ - /* QQ: Error handling ? */ - /* - zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether - the index is a numeric and convert it to it. This however means constant - hashing of the column name, which is not needed as it can be precomputed. - */ - Z_ADDREF_P(data); - if (hash_key->is_numeric == FALSE) { - zend_hash_quick_update(Z_ARRVAL_P(row), - field->name, - field->name_length + 1, - hash_key->key, - (void *) &data, sizeof(zval *), NULL); - } else { - zend_hash_index_update(Z_ARRVAL_P(row), - hash_key->key, - (void *) &data, sizeof(zval *), NULL); + if (field->max_length < len) { + field->max_length = len; } } - if (field->max_length < len) { - field->max_length = len; - } } } - *fetched_anything = TRUE; result->unbuf->row_count++; + *fetched_anything = TRUE; } else if (ret == FAIL) { if (row_packet->error_info.error_no) { COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info); @@@ -909,30 -939,32 +939,32 @@@ oom /* }}} */ - /* {{{ mysqlnd_fetch_row_buffered_c */ - static MYSQLND_ROW_C - mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC) + /* {{{ mysqlnd_result_buffered::fetch_row_c */ + static enum_func_status -MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { - MYSQLND_ROW_C ret = NULL; - MYSQLND_RES_BUFFERED *set = result->stored_data; + MYSQLND_ROW_C * row = (MYSQLND_ROW_C *) param; + MYSQLND_RES_BUFFERED * set = result->stored_data; + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; + enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_fetch_row_buffered_c"); + DBG_ENTER("mysqlnd_result_buffered::fetch_row_c"); /* If we haven't read everything */ if (set->data_cursor && - (set->data_cursor - set->data) < (set->row_count * result->meta->field_count)) + (set->data_cursor - set->data) < (set->row_count * field_count)) { zval **current_row = set->data_cursor; - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; + MYSQLND_FIELD * field = meta->fields; - unsigned int i; + php_uint_t i; if (NULL == current_row[0]) { - uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count; - enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num], + uint64_t row_num = (set->data_cursor - set->data) / field_count; + enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num], current_row, - result->meta->field_count, - result->meta->fields, + field_count, + meta->fields, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { @@@ -980,31 -1019,32 +1019,32 @@@ /* }}} */ - /* {{{ mysqlnd_fetch_row_buffered */ + /* {{{ mysqlnd_result_buffered::fetch_row */ static enum_func_status - mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { - php_uint_t i; - zval *row = (zval *) param; - MYSQLND_RES_BUFFERED *set = result->stored_data; + zval * row = (zval *) param; + MYSQLND_RES_BUFFERED * set = result->stored_data; + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_fetch_row_buffered"); + DBG_ENTER("mysqlnd_result_buffered::fetch_row"); /* If we haven't read everything */ if (set->data_cursor && - (set->data_cursor - set->data) < (set->row_count * result->meta->field_count)) + (set->data_cursor - set->data) < (set->row_count * field_count)) { zval **current_row = set->data_cursor; - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; + MYSQLND_FIELD * field = meta->fields; - unsigned int i; ++ php_uint_t i; if (NULL == current_row[0]) { - uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count; - enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num], + uint64_t row_num = (set->data_cursor - set->data) / field_count; + enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num], current_row, - result->meta->field_count, - result->meta->fields, + field_count, + meta->fields, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { @@@ -1071,6 -1111,20 +1111,20 @@@ /* }}} */ + /* {{{ mysqlnd_res::fetch_row */ + static enum_func_status -MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool *fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) + { + const mysqlnd_fetch_row_func f = result->stored_data? result->stored_data->m.fetch_row:(result->unbuf? result->unbuf->m.fetch_row:NULL); + if (f) { + return f(result, param, flags, fetched_anything TSRMLS_CC); + } + *fetched_anything = FALSE; + return PASS; + } + /* }}} */ + + #define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2 /* {{{ mysqlnd_res::store_result_fetch_data */ @@@ -1080,8 -1134,8 +1134,8 @@@ MYSQLND_METHOD(mysqlnd_res, store_resul zend_bool binary_protocol TSRMLS_DC) { enum_func_status ret; - MYSQLND_PACKET_ROW *row_packet = NULL; + MYSQLND_PACKET_ROW * row_packet = NULL; - unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1; + php_uint_t next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1; MYSQLND_RES_BUFFERED *set; DBG_ENTER("mysqlnd_res::store_result_fetch_data"); @@@ -1647,10 -1720,10 +1720,10 @@@ MYSQLND_CLASS_METHODS_END /* {{{ mysqlnd_result_init */ PHPAPI MYSQLND_RES * -mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC) +mysqlnd_result_init(php_uint_t field_count, zend_bool persistent TSRMLS_DC) { size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *); - MYSQLND_RES *ret = mnd_pecalloc(1, alloc_size, persistent); + MYSQLND_RES * ret = mnd_pecalloc(1, alloc_size, persistent); DBG_ENTER("mysqlnd_result_init"); @@@ -1667,6 -1740,86 +1740,86 @@@ /* }}} */ + /* {{{ mysqlnd_result_unbuffered_init */ + PHPAPI MYSQLND_RES_UNBUFFERED * -mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) ++mysqlnd_result_unbuffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) + { + size_t alloc_size = sizeof(MYSQLND_RES_UNBUFFERED) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_UNBUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_result_unbuffered_init"); + + if (!ret) { + DBG_RETURN(NULL); + } + - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { ++ if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) { + mnd_efree(ret->lengths); + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + + ret->persistent = persistent; + ret->field_count= field_count; + ret->ps = ps; + + ret->m = *mysqlnd_result_unbuffered_get_methods(); + + if (ps) { + ret->m.fetch_lengths = NULL; /* makes no sense */ + ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; + } else { + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + } + + DBG_RETURN(ret); + } + /* }}} */ + + + /* {{{ mysqlnd_result_buffered_init */ + PHPAPI MYSQLND_RES_BUFFERED * -mysqlnd_result_buffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) ++mysqlnd_result_buffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) + { + size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_BUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_result_buffered_init"); + + if (!ret) { + DBG_RETURN(NULL); + } + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) { + mnd_efree(ret->lengths); + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + + ret->persistent = persistent; + ret->field_count= field_count; + ret->ps = ps; + ret->m = *mysqlnd_result_buffered_get_methods(); + + if (ps) { + ret->m.fetch_lengths = NULL; /* makes no sense */ + ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; + } else { + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + } + + DBG_RETURN(ret); + } + /* }}} */ + + /* * Local variables: * tab-width: 4 diff --cc ext/mysqlnd/mysqlnd_result.h index c647c02,0a54ea0..09e0f81 --- a/ext/mysqlnd/mysqlnd_result.h +++ b/ext/mysqlnd/mysqlnd_result.h @@@ -23,7 -23,9 +23,9 @@@ #ifndef MYSQLND_RESULT_H #define MYSQLND_RESULT_H -PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC); -PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); -PHPAPI MYSQLND_RES_BUFFERED * mysqlnd_result_buffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); +PHPAPI MYSQLND_RES * mysqlnd_result_init(php_uint_t field_count, zend_bool persistent TSRMLS_DC); ++PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); ++PHPAPI MYSQLND_RES_BUFFERED * mysqlnd_result_buffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); enum_func_status mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt TSRMLS_DC); diff --cc ext/mysqlnd/mysqlnd_structs.h index 57f8512,5c035a5..aa6182a --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@@ -243,11 -243,12 +243,12 @@@ typedef struct st_mysqlnd_debug MYSQLND typedef MYSQLND_RES* (*mysqlnd_stmt_use_or_store_func)(MYSQLND_STMT * const TSRMLS_DC); typedef enum_func_status (*mysqlnd_fetch_row_func)(MYSQLND_RES *result, - void *param, + void * param, - unsigned int flags, + php_uint_t flags, - zend_bool *fetched_anything + zend_bool * fetched_anything TSRMLS_DC); + typedef struct st_mysqlnd_stats MYSQLND_STATS; typedef void (*mysqlnd_stat_trigger)(MYSQLND_STATS * stats, enum_mysqlnd_collected_stats stat, int64_t change TSRMLS_DC); @@@ -606,31 -607,31 +607,31 @@@ struct st_mysqlnd_conn_method func_mysqlnd_conn__close close; }; + /* for decoding - binary or text protocol */ + typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - unsigned int field_count, const MYSQLND_FIELD * fields_metadata, ++ php_uint_t field_count, const MYSQLND_FIELD * fields_metadata, + zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); - typedef mysqlnd_fetch_row_func fetch_row; - typedef mysqlnd_fetch_row_func fetch_row_normal_buffered; /* private */ - typedef mysqlnd_fetch_row_func fetch_row_normal_unbuffered; /* private */ typedef MYSQLND_RES * (*func_mysqlnd_res__use_result)(MYSQLND_RES * const result, zend_bool ps_protocol TSRMLS_DC); typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND_CONN_DATA * const conn, zend_bool ps TSRMLS_DC); -typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, unsigned int flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC); +typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, php_uint_t flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC); typedef MYSQLND_ROW_C (*func_mysqlnd_res__fetch_row_c)(MYSQLND_RES *result TSRMLS_DC); -typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC); -typedef void (*func_mysqlnd_res__fetch_field_data)(MYSQLND_RES *result, unsigned int offset, zval *return_value TSRMLS_DC); +typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, php_uint_t flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC); +typedef void (*func_mysqlnd_res__fetch_field_data)(MYSQLND_RES *result, php_uint_t offset, zval *return_value TSRMLS_DC); typedef uint64_t (*func_mysqlnd_res__num_rows)(const MYSQLND_RES * const result TSRMLS_DC); -typedef unsigned int (*func_mysqlnd_res__num_fields)(const MYSQLND_RES * const result TSRMLS_DC); +typedef php_uint_t (*func_mysqlnd_res__num_fields)(const MYSQLND_RES * const result TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_res__skip_result)(MYSQLND_RES * const result TSRMLS_DC); - typedef enum_func_status (*func_mysqlnd_res__seek_data)(MYSQLND_RES * result, uint64_t row TSRMLS_DC); - typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res__seek_field)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET field_offset TSRMLS_DC); + typedef enum_func_status (*func_mysqlnd_res__seek_data)(MYSQLND_RES * const result, const uint64_t row TSRMLS_DC); + typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res__seek_field)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET field_offset TSRMLS_DC); typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res__field_tell)(const MYSQLND_RES * const result TSRMLS_DC); typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field)(MYSQLND_RES * const result TSRMLS_DC); - typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC); + typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field_direct)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC); typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_fields)(MYSQLND_RES * const result TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn TSRMLS_DC); -typedef unsigned long * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC); +typedef php_uint_t * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol TSRMLS_DC); - typedef enum_func_status (*func_mysqlnd_res__initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC); typedef void (*func_mysqlnd_res__free_result_buffers)(MYSQLND_RES * result TSRMLS_DC); /* private */ typedef enum_func_status (*func_mysqlnd_res__free_result)(MYSQLND_RES * result, zend_bool implicit TSRMLS_DC); @@@ -639,12 -640,8 +640,8 @@@ typedef void (*func_mysqlnd_res__fre typedef void (*func_mysqlnd_res__free_buffered_data)(MYSQLND_RES *result TSRMLS_DC); typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *result TSRMLS_DC); - /* for decoding - binary or text protocol */ - typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - php_uint_t field_count, const MYSQLND_FIELD * fields_metadata, - zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); -typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(unsigned int field_count, zend_bool persistent TSRMLS_DC); +typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(php_uint_t field_count, zend_bool persistent TSRMLS_DC); struct st_mysqlnd_res_methods { @@@ -974,9 -999,23 +999,23 @@@ struct st_mysqlnd_buffered_resul uint64_t row_count; uint64_t initialized_rows; + /* + Column lengths of current row - both buffered and unbuffered. + For buffered results it duplicates the data found in **data + */ - unsigned long *lengths; ++ php_uint_t *lengths; + + MYSQLND_MEMORY_POOL *result_set_memory_pool; + - unsigned int references; + php_uint_t references; MYSQLND_ERROR_INFO error_info; + - unsigned int field_count; ++ php_uint_t field_count; + zend_bool ps; + zend_bool persistent; + + struct st_mysqlnd_result_buffered_methods m; }; @@@ -986,8 -1026,24 +1026,24 @@@ struct st_mysqlnd_unbuffered_resul zval **last_row_data; MYSQLND_MEMORY_POOL_CHUNK *last_row_buffer; + /* + Column lengths of current row - both buffered and unbuffered. + For buffered results it duplicates the data found in **data + */ - unsigned long *lengths; ++ php_uint_t *lengths; + + MYSQLND_MEMORY_POOL *result_set_memory_pool; + + struct st_mysqlnd_packet_row * row_packet; + uint64_t row_count; zend_bool eof_reached; + - unsigned int field_count; ++ php_uint_t field_count; + zend_bool ps; + zend_bool persistent; + + struct st_mysqlnd_result_unbuffered_methods m; }; diff --cc ext/openssl/openssl.c index 5d06242,97740d3..b580ee6 mode 100644,100755..100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@@ -630,16 -615,14 +615,14 @@@ struct php_x509_request { /* {{{ * }; /* }}} */ -static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC); -static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * passphrase, int makeresource, long * resourceval TSRMLS_DC); +static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, php_int_t * resourceval TSRMLS_DC); +static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * passphrase, int makeresource, php_int_t * resourceval TSRMLS_DC); static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC); - static X509_STORE * setup_verify(zval * calist TSRMLS_DC); + static X509_STORE * setup_verify(zval * calist TSRMLS_DC); static STACK_OF(X509) * load_all_certs_from_file(char *certfile); -static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC); +static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, php_int_t * resourceval TSRMLS_DC); static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req TSRMLS_DC); - #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i))) - static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */ { zval **data; @@@ -1169,24 -1150,23 +1152,23 @@@ PHP_MINIT_FUNCTION(openssl #endif /* flags for S/MIME */ - REGISTER_LONG_CONSTANT("PKCS7_DETACHED", PKCS7_DETACHED, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_TEXT", PKCS7_TEXT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOINTERN", PKCS7_NOINTERN, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOVERIFY", PKCS7_NOVERIFY, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOCHAIN", PKCS7_NOCHAIN, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOCERTS", PKCS7_NOCERTS, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOATTR", PKCS7_NOATTR, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_BINARY", PKCS7_BINARY, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOSIGS", PKCS7_NOSIGS, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_DETACHED", PKCS7_DETACHED, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_TEXT", PKCS7_TEXT, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOINTERN", PKCS7_NOINTERN, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOVERIFY", PKCS7_NOVERIFY, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOCHAIN", PKCS7_NOCHAIN, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOCERTS", PKCS7_NOCERTS, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOATTR", PKCS7_NOATTR, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_BINARY", PKCS7_BINARY, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOSIGS", PKCS7_NOSIGS, CONST_CS|CONST_PERSISTENT); + + REGISTER_INT_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); /* Informational stream wrapper constants */ - REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", PHP_OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT); - REGISTER_INT_CONSTANT("OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH", PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH, CONST_CS|CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT); /* Ciphers */ #ifndef OPENSSL_NO_RC2 diff --cc ext/openssl/xp_ssl.c index 508c81c,e251d21..4a23764 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@@ -425,7 -718,120 +718,120 @@@ static long load_stream_cafile(X509_STO } /* }}} */ - static const SSL_METHOD *php_select_crypto_method(php_int_t method_value, int is_client TSRMLS_DC) + static int enable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ + { + zval **val = NULL; + char *cafile = NULL; + char *capath = NULL; + + GET_VER_OPT_STRING("cafile", cafile); + GET_VER_OPT_STRING("capath", capath); + + if (!cafile) { + cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0); + cafile = strlen(cafile) ? cafile : NULL; + } + + if (!capath) { + capath = zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0); + capath = strlen(capath) ? capath : NULL; + } + + if (cafile || capath) { + if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) { + if (cafile && !load_stream_cafile(SSL_CTX_get_cert_store(ctx), cafile TSRMLS_CC)) { + return FAILURE; + } + } + } else { + #if defined(PHP_WIN32) && OPENSSL_VERSION_NUMBER >= 0x00907000L + SSL_CTX_set_cert_verify_callback(ctx, win_cert_verify_callback, (void *)stream); + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + #else + php_openssl_netstream_data_t *sslsock; + sslsock = (php_openssl_netstream_data_t*)stream->abstract; + + if (sslsock->is_client && !SSL_CTX_set_default_verify_paths(ctx)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to set default verify locations and no CA settings specified"); + return FAILURE; + } + #endif + } + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); + + return SUCCESS; + } + /* }}} */ + + static void disable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ + { + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); + } + /* }}} */ + + static int set_local_cert(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ + { + zval **val = NULL; + char *certfile = NULL; + + GET_VER_OPT_STRING("local_cert", certfile); + + if (certfile) { + char resolved_path_buff[MAXPATHLEN]; + const char * private_key = NULL; + + if (VCWD_REALPATH(certfile, resolved_path_buff)) { + /* a certificate to use for authentication */ + if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile); + return FAILURE; + } + GET_VER_OPT_STRING("local_pk", private_key); + + if (private_key) { + char resolved_path_buff_pk[MAXPATHLEN]; + if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) { + if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk); + return FAILURE; + } + } + } else { + if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff); + return FAILURE; + } + } + + #if OPENSSL_VERSION_NUMBER < 0x10001001L + do { + /* Unnecessary as of OpenSSLv1.0.1 (will segfault if used with >= 10001001 ) */ + X509 *cert = NULL; + EVP_PKEY *key = NULL; + SSL *tmpssl = SSL_new(ctx); + cert = SSL_get_certificate(tmpssl); + + if (cert) { + key = X509_get_pubkey(cert); + EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); + EVP_PKEY_free(key); + } + SSL_free(tmpssl); + } while (0); + #endif + if (!SSL_CTX_check_private_key(ctx)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Private key does not match certificate!"); + } + } + } + + return SUCCESS; + } + /* }}} */ + -static const SSL_METHOD *php_select_crypto_method(long method_value, int is_client TSRMLS_DC) /* {{{ */ ++static const SSL_METHOD *php_select_crypto_method(php_int_t method_value, int is_client TSRMLS_DC) /* {{{ */ { if (method_value == STREAM_CRYPTO_METHOD_SSLv2) { #ifndef OPENSSL_NO_SSL2 @@@ -461,10 -867,11 +867,11 @@@ return NULL; } } + /* }}} */ - static php_int_t php_get_crypto_method_ctx_flags(php_int_t method_flags TSRMLS_DC) -static long php_get_crypto_method_ctx_flags(long method_flags TSRMLS_DC) /* {{{ */ ++static php_int_t php_get_crypto_method_ctx_flags(php_int_t method_flags TSRMLS_DC) /* {{{ */ { - long ssl_ctx_options = SSL_OP_ALL; + php_int_t ssl_ctx_options = SSL_OP_ALL; #ifndef OPENSSL_NO_SSL2 if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv2)) { @@@ -493,72 -900,238 +900,238 @@@ return ssl_ctx_options; } + /* }}} */ - static inline int php_openssl_setup_crypto(php_stream *stream, - php_openssl_netstream_data_t *sslsock, - php_stream_xport_crypto_param *cparam - TSRMLS_DC) + static void limit_handshake_reneg(const SSL *ssl) /* {{{ */ { - const SSL_METHOD *method; - php_int_t ssl_ctx_options; - php_int_t method_flags; - zval **val; - #ifdef SSL_MODE_RELEASE_BUFFERS - php_int_t mode; - #endif + php_stream *stream; + php_openssl_netstream_data_t *sslsock; + struct timeval now; - long elapsed_time; ++ php_int_t elapsed_time; - if (sslsock->ssl_handle) { - if (sslsock->s.is_blocked) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream"); - return -1; + stream = php_openssl_get_stream_from_ssl_handle(ssl); + sslsock = (php_openssl_netstream_data_t*)stream->abstract; + gettimeofday(&now, NULL); + + /* The initial handshake is never rate-limited */ + if (sslsock->reneg->prev_handshake == 0) { + sslsock->reneg->prev_handshake = now.tv_sec; + return; + } + + elapsed_time = (now.tv_sec - sslsock->reneg->prev_handshake); + sslsock->reneg->prev_handshake = now.tv_sec; + sslsock->reneg->tokens -= (elapsed_time * (sslsock->reneg->limit / sslsock->reneg->window)); + + if (sslsock->reneg->tokens < 0) { + sslsock->reneg->tokens = 0; + } + ++sslsock->reneg->tokens; + + /* The token level exceeds our allowed limit */ + if (sslsock->reneg->tokens > sslsock->reneg->limit) { + zval **val; + + TSRMLS_FETCH(); + + sslsock->reneg->should_close = 1; + + if (stream->context && SUCCESS == php_stream_context_get_option(stream->context, + "ssl", "reneg_limit_callback", &val) + ) { + zval *param, **params[1], *retval; + + MAKE_STD_ZVAL(param); + php_stream_to_zval(stream, param); + params[0] = ¶m; + + /* Closing the stream inside this callback would segfault! */ + stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; + if (FAILURE == call_user_function_ex(EG(function_table), NULL, *val, &retval, 1, params, 0, NULL TSRMLS_CC)) { + php_error(E_WARNING, "SSL: failed invoking reneg limit notification callback"); + } + stream->flags ^= PHP_STREAM_FLAG_NO_FCLOSE; + + /* If the reneg_limit_callback returned true don't auto-close */ + if (retval != NULL && Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval) == 1) { + sslsock->reneg->should_close = 0; + } + + FREE_ZVAL(param); + if (retval != NULL) { + zval_ptr_dtor(&retval); + } } else { - return 0; + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SSL: client-initiated handshake rate limit exceeded by peer"); } } + } + /* }}} */ - /* need to do slightly different things, based on client/server method, - * so lets remember which method was selected */ - sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT; - method_flags = ((cparam->inputs.method >> 1) << 1); + static void info_callback(const SSL *ssl, int where, int ret) /* {{{ */ + { + /* Rate-limit client-initiated handshake renegotiation to prevent DoS */ + if (where & SSL_CB_HANDSHAKE_START) { + limit_handshake_reneg(ssl); + } + } + /* }}} */ - /* Should we use a specific crypto method or is generic SSLv23 okay? */ - if ((method_flags & (method_flags-1)) == 0) { - ssl_ctx_options = SSL_OP_ALL; - method = php_select_crypto_method(method_flags, sslsock->is_client TSRMLS_CC); - if (method == NULL) { - return -1; + static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ + { + zval **val; + long limit = OPENSSL_DEFAULT_RENEG_LIMIT; + long window = OPENSSL_DEFAULT_RENEG_WINDOW; + + if (stream->context && + SUCCESS == php_stream_context_get_option(stream->context, + "ssl", "reneg_limit", &val) + ) { + convert_to_long(*val); + limit = Z_LVAL_PP(val); + } + + /* No renegotiation rate-limiting */ + if (limit < 0) { + return; + } + + if (stream->context && + SUCCESS == php_stream_context_get_option(stream->context, + "ssl", "reneg_window", &val) + ) { + convert_to_long(*val); + window = Z_LVAL_PP(val); + } + + sslsock->reneg = (void*)pemalloc(sizeof(php_openssl_handshake_bucket_t), + php_stream_is_persistent(stream) + ); + + sslsock->reneg->limit = limit; + sslsock->reneg->window = window; + sslsock->reneg->prev_handshake = 0; + sslsock->reneg->tokens = 0; + sslsock->reneg->should_close = 0; + + SSL_set_info_callback(sslsock->ssl_handle, info_callback); + } + /* }}} */ + + static int set_server_rsa_key(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ + { + zval ** val; + int rsa_key_size; + RSA* rsa; + + if (php_stream_context_get_option(stream->context, "ssl", "rsa_key_size", &val) == SUCCESS) { + rsa_key_size = (int) Z_LVAL_PP(val); + if ((rsa_key_size != 1) && (rsa_key_size & (rsa_key_size - 1))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "RSA key size requires a power of 2: %d", rsa_key_size); + rsa_key_size = 2048; } } else { - method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method(); - ssl_ctx_options = php_get_crypto_method_ctx_flags(method_flags TSRMLS_CC); - if (ssl_ctx_options == -1) { - return -1; + rsa_key_size = 2048; + } + + rsa = RSA_generate_key(rsa_key_size, RSA_F4, NULL, NULL); + + if (!SSL_CTX_set_tmp_rsa(ctx, rsa)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting RSA key"); + RSA_free(rsa); + return FAILURE; + } + + RSA_free(rsa); + + return SUCCESS; + } + /* }}} */ + + static int set_server_dh_param(SSL_CTX *ctx, char *dh_path TSRMLS_DC) /* {{{ */ + { + DH *dh; + BIO* bio; + + bio = BIO_new_file(dh_path, "r"); + + if (bio == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid dh_param file: %s", dh_path); + return FAILURE; + } + + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + + if (dh == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed reading DH params from file: %s", dh_path); + return FAILURE; + } + + if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "DH param assignment failed"); + DH_free(dh); + return FAILURE; + } + + DH_free(dh); + + return SUCCESS; + } + /* }}} */ + + #ifdef HAVE_ECDH + static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ + { + zval **val; + int curve_nid; + char *curve_str; + EC_KEY *ecdh; + + if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { + convert_to_string_ex(val); + curve_str = Z_STRVAL_PP(val); + curve_nid = OBJ_sn2nid(curve_str); + if (curve_nid == NID_undef) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid ECDH curve: %s", curve_str); + return FAILURE; } + } else { + curve_nid = NID_X9_62_prime256v1; } - #if OPENSSL_VERSION_NUMBER >= 0x10001001L - sslsock->ctx = SSL_CTX_new(method); - #else - sslsock->ctx = SSL_CTX_new((SSL_METHOD*)method); - #endif - if (sslsock->ctx == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL context"); - return -1; + ecdh = EC_KEY_new_by_curve_name(curve_nid); + if (ecdh == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed generating ECDH curve"); + + return FAILURE; } - #if OPENSSL_VERSION_NUMBER >= 0x0090605fL - ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + + return SUCCESS; + } + /* }}} */ #endif - SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options); - #if OPENSSL_VERSION_NUMBER >= 0x0090806fL - { - if (stream->context && SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "no_ticket", &val) && - zend_is_true(*val) - ) { - SSL_CTX_set_options(sslsock->ctx, SSL_OP_NO_TICKET); - } + static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ + { + zval **val; + long ssl_ctx_options = SSL_CTX_get_options(ctx); + + #ifdef HAVE_ECDH + if (FAILURE == set_server_ecdh_curve(stream, ctx TSRMLS_CC)) { + return FAILURE; + } + #else + if (SUCCESS == php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "ECDH curve support not compiled into the OpenSSL lib against which PHP is linked"); + + return FAILURE; } #endif @@@ -591,241 -1164,347 +1164,347 @@@ stream->context, "ssl", "single_ecdh_use", &val) && zend_is_true(*val) ) { - SSL_CTX_set_options(sslsock->ctx, SSL_OP_SINGLE_ECDH_USE); + ssl_ctx_options |= SSL_OP_SINGLE_ECDH_USE; } - sslsock->ssl_handle = php_SSL_new_from_context(sslsock->ctx, stream TSRMLS_CC); - if (sslsock->ssl_handle == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL handle"); - SSL_CTX_free(sslsock->ctx); - sslsock->ctx = NULL; - return -1; - } + SSL_CTX_set_options(ctx, ssl_ctx_options); - if (!sslsock->is_client && stream->context && SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "honor_cipher_order", &val) && - zend_is_true(*val) - ) { - SSL_CTX_set_options(sslsock->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - } + return SUCCESS; + } + /* }}} */ - #ifdef SSL_MODE_RELEASE_BUFFERS - mode = SSL_get_mode(sslsock->ssl_handle); - SSL_set_mode(sslsock->ssl_handle, mode | SSL_MODE_RELEASE_BUFFERS); - #endif + #ifdef HAVE_SNI + static int server_sni_callback(SSL *ssl_handle, int *al, void *arg) /* {{{ */ + { + php_stream *stream; + php_openssl_netstream_data_t *sslsock; + unsigned i; + const char *server_name; + + server_name = SSL_get_servername(ssl_handle, TLSEXT_NAMETYPE_host_name); - if (!sslsock->is_client) { - init_handshake_limiting(stream, sslsock); + if (!server_name) { + return SSL_TLSEXT_ERR_NOACK; } - if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { - handle_ssl_error(stream, 0, 1 TSRMLS_CC); + stream = (php_stream*)SSL_get_ex_data(ssl_handle, php_openssl_get_ssl_stream_data_index()); + sslsock = (php_openssl_netstream_data_t*)stream->abstract; + + if (!(sslsock->sni_cert_count && sslsock->sni_certs)) { + return SSL_TLSEXT_ERR_NOACK; } - if (cparam->inputs.session) { - if (cparam->inputs.session->ops != &php_openssl_socket_ops) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream"); - } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied SSL session stream is not initialized"); - } else { - SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); + for (i=0; i < sslsock->sni_cert_count; i++) { + if (matches_wildcard_name(server_name, sslsock->sni_certs[i].name)) { + SSL_set_SSL_CTX(ssl_handle, sslsock->sni_certs[i].ctx); + return SSL_TLSEXT_ERR_OK; } } - return 0; + + return SSL_TLSEXT_ERR_NOACK; } + /* }}} */ - static zval *php_capture_ssl_session_meta(SSL *ssl_handle) + static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock TSRMLS_DC) { - zval *meta_arr; - char *proto_str; - php_int_t proto = SSL_version(ssl_handle); - const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle); + zval **val; + zval **current; + char *key; - uint key_len; - ulong key_index; ++ php_size_t key_len; ++ php_uint_t key_index; + int key_type; + HashPosition pos; + int i = 0; + char resolved_path_buff[MAXPATHLEN]; + SSL_CTX *ctx; + + /* If the stream ctx disables SNI we're finished here */ + if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val)) { + return SUCCESS; + } - switch (proto) { - #if OPENSSL_VERSION_NUMBER >= 0x10001001L - case TLS1_2_VERSION: proto_str = "TLSv1.2"; break; - case TLS1_1_VERSION: proto_str = "TLSv1.1"; break; - #endif - case TLS1_VERSION: proto_str = "TLSv1"; break; - case SSL3_VERSION: proto_str = "SSLv3"; break; - case SSL2_VERSION: proto_str = "SSLv2"; break; - default: proto_str = "UNKNOWN"; + /* If no SNI cert array is specified we're finished here */ + if (!GET_VER_OPT("SNI_server_certs")) { + return SUCCESS; } - MAKE_STD_ZVAL(meta_arr); - array_init(meta_arr); - add_assoc_string(meta_arr, "protocol", proto_str, 1); - add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1); - add_assoc_int(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); - add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1); + if (Z_TYPE_PP(val) != IS_ARRAY) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SNI_server_certs requires an array mapping host names to cert paths" + ); + return FAILURE; + } - return meta_arr; - } + sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_PP(val)); + if (sslsock->sni_cert_count == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SNI_server_certs host cert array must not be empty" + ); + return FAILURE; + } - static int php_set_server_rsa_key(php_stream *stream, - php_openssl_netstream_data_t *sslsock - TSRMLS_DC) - { - zval ** val; - int rsa_key_size; - RSA* rsa; - int retval = 1; + sslsock->sni_certs = (php_openssl_sni_cert_t*)safe_pemalloc(sslsock->sni_cert_count, + sizeof(php_openssl_sni_cert_t), 0, php_stream_is_persistent(stream) + ); - if (php_stream_context_get_option(stream->context, "ssl", "rsa_key_size", &val) == SUCCESS) { - rsa_key_size = (int) Z_IVAL_PP(val); - if ((rsa_key_size != 1) && (rsa_key_size & (rsa_key_size - 1))) { + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(val), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_PP(val), (void **)¤t, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_PP(val), &pos) + ) { + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(val), &key, &key_len, &key_index, 0, &pos); + if (key_type != HASH_KEY_IS_STRING) { php_error_docref(NULL TSRMLS_CC, E_WARNING, - "RSA key size requires a power of 2: %d", - rsa_key_size); + "SNI_server_certs array requires string host name keys" + ); + return FAILURE; + } - rsa_key_size = 2048; + if (VCWD_REALPATH(Z_STRVAL_PP(current), resolved_path_buff)) { + /* The hello method is not inherited by SSL structs when assigning a new context + * inside the SNI callback, so the just use SSLv23 */ + ctx = SSL_CTX_new(SSLv23_server_method()); + + if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "failed setting local cert chain file `%s'; " \ + "check that your cafile/capath settings include " \ + "details of your certificate and its issuer", + resolved_path_buff + ); + SSL_CTX_free(ctx); + return FAILURE; + } else if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "failed setting private key from file `%s'", + resolved_path_buff + ); + SSL_CTX_free(ctx); + return FAILURE; + } else { + sslsock->sni_certs[i].name = pestrdup(key, php_stream_is_persistent(stream)); + sslsock->sni_certs[i].ctx = ctx; + ++i; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "failed setting local cert chain file `%s'; file not found", + Z_STRVAL_PP(current) + ); + return FAILURE; } - } else { - rsa_key_size = 2048; } - rsa = RSA_generate_key(rsa_key_size, RSA_F4, NULL, NULL); + SSL_CTX_set_tlsext_servername_callback(sslsock->ctx, server_sni_callback); - if (!SSL_set_tmp_rsa(sslsock->ssl_handle, rsa)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Failed setting RSA key"); - retval = 0; + return SUCCESS; + } + + static void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ + { + zval **val; + char *sni_server_name; + + /* If SNI is explicitly disabled we're finished here */ + if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val)) { + return; } - RSA_free(rsa); + sni_server_name = sslsock->url_name; - return retval; - } + GET_VER_OPT_STRING("peer_name", sni_server_name); + if (GET_VER_OPT("SNI_server_name")) { + GET_VER_OPT_STRING("SNI_server_name", sni_server_name); + php_error(E_DEPRECATED, "SNI_server_name is deprecated in favor of peer_name"); + } - static int php_set_server_dh_param(php_openssl_netstream_data_t *sslsock, - char *dh_path - TSRMLS_DC) + if (sni_server_name) { + SSL_set_tlsext_host_name(sslsock->ssl_handle, sni_server_name); + } + } + /* }}} */ + #endif + + int php_openssl_setup_crypto(php_stream *stream, + php_openssl_netstream_data_t *sslsock, + php_stream_xport_crypto_param *cparam + TSRMLS_DC) /* {{{ */ { - DH *dh; - BIO* bio; + const SSL_METHOD *method; + long ssl_ctx_options; + long method_flags; + char *cipherlist = NULL; + zval **val; - bio = BIO_new_file(dh_path, "r"); + if (sslsock->ssl_handle) { + if (sslsock->s.is_blocked) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream"); + return FAILURE; + } else { + return SUCCESS; + } + } - if (bio == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Invalid dh_param file: %s", - dh_path); + ERR_clear_error(); - return 0; + /* We need to do slightly different things based on client/server method + * so lets remember which method was selected */ + sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT; + method_flags = ((cparam->inputs.method >> 1) << 1); + + /* Should we use a specific crypto method or is generic SSLv23 okay? */ + if ((method_flags & (method_flags-1)) == 0) { + ssl_ctx_options = SSL_OP_ALL; + method = php_select_crypto_method(method_flags, sslsock->is_client TSRMLS_CC); + if (method == NULL) { + return FAILURE; + } + } else { + method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method(); + ssl_ctx_options = php_get_crypto_method_ctx_flags(method_flags TSRMLS_CC); + if (ssl_ctx_options == -1) { + return FAILURE; + } + } + + #if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->ctx = SSL_CTX_new(method); + #else + /* Avoid const warning with old versions */ + sslsock->ctx = SSL_CTX_new((SSL_METHOD*)method); + #endif + + if (sslsock->ctx == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL context creation failure"); + return FAILURE; } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); + #if OPENSSL_VERSION_NUMBER >= 0x0090806fL + if (GET_VER_OPT("no_ticket") && zend_is_true(*val)) { + ssl_ctx_options |= SSL_OP_NO_TICKET; + } + #endif - if (dh == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Failed reading DH params from file: %s", - dh_path); + #if OPENSSL_VERSION_NUMBER >= 0x0090605fL + ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + #endif - return 0; + #if OPENSSL_VERSION_NUMBER >= 0x10000000L + if (!GET_VER_OPT("disable_compression") || zend_is_true(*val)) { + ssl_ctx_options |= SSL_OP_NO_COMPRESSION; } + #endif - if (SSL_set_tmp_dh(sslsock->ssl_handle, dh) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "DH param assignment failed"); - DH_free(dh); - return 0; + if (GET_VER_OPT("verify_peer") && !zend_is_true(*val)) { + disable_peer_verification(sslsock->ctx, stream TSRMLS_CC); + } else if (FAILURE == enable_peer_verification(sslsock->ctx, stream TSRMLS_CC)) { + return FAILURE; } - DH_free(dh); - - return 1; - } + /* callback for the passphrase (for localcert) */ + if (GET_VER_OPT("passphrase")) { + SSL_CTX_set_default_passwd_cb_userdata(sslsock->ctx, stream); + SSL_CTX_set_default_passwd_cb(sslsock->ctx, passwd_callback); + } - static int php_enable_server_crypto_opts(php_stream *stream, - php_openssl_netstream_data_t *sslsock - TSRMLS_DC) - { - zval **val; - #ifdef HAVE_ECDH - int curve_nid; - EC_KEY *ecdh; - #endif + GET_VER_OPT_STRING("ciphers", cipherlist); + if (!cipherlist) { + cipherlist = OPENSSL_DEFAULT_STREAM_CIPHERS; + } + if (SSL_CTX_set_cipher_list(sslsock->ctx, cipherlist) != 1) { + return FAILURE; + } - if (php_stream_context_get_option(stream->context, "ssl", "dh_param", &val) == SUCCESS) { - convert_to_string_ex(val); - if (!php_set_server_dh_param(sslsock, Z_STRVAL_PP(val) TSRMLS_CC)) { - return 0; - } + if (FAILURE == set_local_cert(sslsock->ctx, stream TSRMLS_CC)) { + return FAILURE; } - #ifdef HAVE_ECDH + SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options); - if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { - char *curve_str; - convert_to_string_ex(val); - curve_str = Z_STRVAL_PP(val); - curve_nid = OBJ_sn2nid(curve_str); - if (curve_nid == NID_undef) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Invalid ECDH curve: %s", - curve_str); + if (sslsock->is_client == 0 && + stream->context && + FAILURE == set_server_specific_opts(stream, sslsock->ctx TSRMLS_CC) + ) { + return FAILURE; + } - return 0; - } + sslsock->ssl_handle = SSL_new(sslsock->ctx); + if (sslsock->ssl_handle == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL handle creation failure"); + SSL_CTX_free(sslsock->ctx); + sslsock->ctx = NULL; + return FAILURE; } else { - curve_nid = NID_X9_62_prime256v1; + SSL_set_ex_data(sslsock->ssl_handle, php_openssl_get_ssl_stream_data_index(), stream); } - ecdh = EC_KEY_new_by_curve_name(curve_nid); - if (ecdh == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Failed generating ECDH curve"); - - return 0; + if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { + handle_ssl_error(stream, 0, 1 TSRMLS_CC); } - SSL_set_tmp_ecdh(sslsock->ssl_handle, ecdh); - EC_KEY_free(ecdh); - - #else + #ifdef HAVE_SNI + /* Enable server-side SNI */ + if (sslsock->is_client == 0 && enable_server_sni(stream, sslsock TSRMLS_CC) == FAILURE) { + return FAILURE; + } + #endif - if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "ECDH curve support not compiled into the OpenSSL lib against which PHP is linked"); + /* Enable server-side handshake renegotiation rate-limiting */ + if (sslsock->is_client == 0) { + init_server_reneg_limit(stream, sslsock); } + #ifdef SSL_MODE_RELEASE_BUFFERS + do { + long mode = SSL_get_mode(sslsock->ssl_handle); + SSL_set_mode(sslsock->ssl_handle, mode | SSL_MODE_RELEASE_BUFFERS); + } while (0); #endif - if (!php_set_server_rsa_key(stream, sslsock TSRMLS_CC)) { - return 0; + if (cparam->inputs.session) { + if (cparam->inputs.session->ops != &php_openssl_socket_ops) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream"); + } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied SSL session stream is not initialized"); + } else { + SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); + } } - return 1; + return SUCCESS; } + /* }}} */ - #if OPENSSL_VERSION_NUMBER >= 0x00908070L && !defined(OPENSSL_NO_TLSEXT) - static inline void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ + static zval *capture_session_meta(SSL *ssl_handle) /* {{{ */ { - zval **val; + zval *meta_arr; + char *proto_str; + long proto = SSL_version(ssl_handle); + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle); - if (stream->context && - (php_stream_context_get_option(stream->context, "ssl", "SNI_enabled", &val) == FAILURE - || zend_is_true(*val)) - ) { - if (php_stream_context_get_option(stream->context, "ssl", "SNI_server_name", &val) == SUCCESS) { - convert_to_string_ex(val); - SSL_set_tlsext_host_name(sslsock->ssl_handle, Z_STRVAL_PP(val)); - } else if (sslsock->url_name) { - SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); - } - } else if (!stream->context && sslsock->url_name) { - SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); + switch (proto) { + #if OPENSSL_VERSION_NUMBER >= 0x10001001L + case TLS1_2_VERSION: proto_str = "TLSv1.2"; break; + case TLS1_1_VERSION: proto_str = "TLSv1.1"; break; + #endif + case TLS1_VERSION: proto_str = "TLSv1"; break; + case SSL3_VERSION: proto_str = "SSLv3"; break; + case SSL2_VERSION: proto_str = "SSLv2"; break; + default: proto_str = "UNKNOWN"; } + + MAKE_STD_ZVAL(meta_arr); + array_init(meta_arr); + add_assoc_string(meta_arr, "protocol", proto_str, 1); + add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1); + add_assoc_long(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); + add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1); + + return meta_arr; } /* }}} */ - #endif - static int capture_peer_certs(php_stream *stream, - php_openssl_netstream_data_t *sslsock, - X509 *peer_cert - TSRMLS_DC) + static int capture_peer_certs(php_stream *stream, php_openssl_netstream_data_t *sslsock, X509 *peer_cert TSRMLS_DC) /* {{{ */ { zval **val, *zcert; int cert_captured = 0; diff --cc ext/spl/spl_directory.c index f289cd6,03315b7..28d3e5f --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@@ -2844,12 -2842,34 +2844,34 @@@ SPL_METHOD(SplFileObject, fwrite str_len = MAX(0, MIN(length, str_len)); } if (!str_len) { - RETURN_LONG(0); + RETURN_INT(0); } - RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len)); + RETURN_INT(php_stream_write(intern->u.file.stream, str, str_len)); } /* }}} */ + SPL_METHOD(SplFileObject, fread) + { + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + long length = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) { + return; + } + + if (length <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0"); + RETURN_FALSE; + } + + Z_STRVAL_P(return_value) = emalloc(length + 1); + Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length); + + /* needed because recv/read/gzread doesnt put a null at the end*/ + Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0; + Z_TYPE_P(return_value) = IS_STRING; + } + /* {{{ proto bool SplFileObject::fstat() Stat() on a filehandle */ FileFunction(fstat) diff --cc ext/zip/php_zip.c index dd6fd64,a9db166..37e67f6 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@@ -3052,81 -3049,82 +3052,82 @@@ static PHP_MINIT_FUNCTION(zip php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC); php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC); - REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE); - REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL); - REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS); - REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE); - - REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE); - REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR); - REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED); - REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED); - REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT); - REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4); - REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64); - REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2); - REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA); - REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77); - REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK); - REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD); + REGISTER_ZIP_CLASS_CONST_INT("CREATE", ZIP_CREATE); + REGISTER_ZIP_CLASS_CONST_INT("EXCL", ZIP_EXCL); + REGISTER_ZIP_CLASS_CONST_INT("CHECKCONS", ZIP_CHECKCONS); + REGISTER_ZIP_CLASS_CONST_INT("OVERWRITE", ZIP_OVERWRITE); + + REGISTER_ZIP_CLASS_CONST_INT("FL_NOCASE", ZIP_FL_NOCASE); + REGISTER_ZIP_CLASS_CONST_INT("FL_NODIR", ZIP_FL_NODIR); + REGISTER_ZIP_CLASS_CONST_INT("FL_COMPRESSED", ZIP_FL_COMPRESSED); + REGISTER_ZIP_CLASS_CONST_INT("FL_UNCHANGED", ZIP_FL_UNCHANGED); + REGISTER_ZIP_CLASS_CONST_INT("CM_DEFAULT", ZIP_CM_DEFAULT); + REGISTER_ZIP_CLASS_CONST_INT("CM_STORE", ZIP_CM_STORE); + REGISTER_ZIP_CLASS_CONST_INT("CM_SHRINK", ZIP_CM_SHRINK); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_1", ZIP_CM_REDUCE_1); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_2", ZIP_CM_REDUCE_2); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_3", ZIP_CM_REDUCE_3); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_4", ZIP_CM_REDUCE_4); + REGISTER_ZIP_CLASS_CONST_INT("CM_IMPLODE", ZIP_CM_IMPLODE); + REGISTER_ZIP_CLASS_CONST_INT("CM_DEFLATE", ZIP_CM_DEFLATE); + REGISTER_ZIP_CLASS_CONST_INT("CM_DEFLATE64", ZIP_CM_DEFLATE64); + REGISTER_ZIP_CLASS_CONST_INT("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE); + REGISTER_ZIP_CLASS_CONST_INT("CM_BZIP2", ZIP_CM_BZIP2); + REGISTER_ZIP_CLASS_CONST_INT("CM_LZMA", ZIP_CM_LZMA); + REGISTER_ZIP_CLASS_CONST_INT("CM_TERSE", ZIP_CM_TERSE); + REGISTER_ZIP_CLASS_CONST_INT("CM_LZ77", ZIP_CM_LZ77); + REGISTER_ZIP_CLASS_CONST_INT("CM_WAVPACK", ZIP_CM_WAVPACK); + REGISTER_ZIP_CLASS_CONST_INT("CM_PPMD", ZIP_CM_PPMD); /* Error code */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */ + REGISTER_ZIP_CLASS_CONST_INT("ER_OK", ZIP_ER_OK); /* N No error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */ + REGISTER_ZIP_CLASS_CONST_INT("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_READ", ZIP_ER_READ); /* S Read error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_WRITE", ZIP_ER_WRITE); /* S Write error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_CRC", ZIP_ER_CRC); /* N CRC error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_NOENT", ZIP_ER_NOENT); /* N No such file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */ + REGISTER_ZIP_CLASS_CONST_INT("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */ + REGISTER_ZIP_CLASS_CONST_INT("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */ + REGISTER_ZIP_CLASS_CONST_INT("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */ + REGISTER_ZIP_CLASS_CONST_INT("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */ + REGISTER_ZIP_CLASS_CONST_INT("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */ + REGISTER_ZIP_CLASS_CONST_INT("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */ + REGISTER_ZIP_CLASS_CONST_INT("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */ #ifdef ZIP_OPSYS_DEFAULT - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DOS", ZIP_OPSYS_DOS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_AMIGA", ZIP_OPSYS_AMIGA); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OPENVMS", ZIP_OPSYS_OPENVMS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_UNIX", ZIP_OPSYS_UNIX); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VM_CMS", ZIP_OPSYS_VM_CMS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ATARI_ST", ZIP_OPSYS_ATARI_ST); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_2", ZIP_OPSYS_OS_2); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MACINTOSH", ZIP_OPSYS_MACINTOSH); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_SYSTEM", ZIP_OPSYS_Z_SYSTEM); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_CPM", ZIP_OPSYS_CPM); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_WINDOWS_NTFS", ZIP_OPSYS_WINDOWS_NTFS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MVS", ZIP_OPSYS_MVS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VSE", ZIP_OPSYS_VSE); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ACORN_RISC", ZIP_OPSYS_ACORN_RISC); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VFAT", ZIP_OPSYS_VFAT); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ALTERNATE_MVS", ZIP_OPSYS_ALTERNATE_MVS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_BEOS", ZIP_OPSYS_BEOS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_TANDEM", ZIP_OPSYS_TANDEM); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_400", ZIP_OPSYS_OS_400); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_X", ZIP_OPSYS_OS_X); - - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_DOS", ZIP_OPSYS_DOS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_AMIGA", ZIP_OPSYS_AMIGA); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OPENVMS", ZIP_OPSYS_OPENVMS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_UNIX", ZIP_OPSYS_UNIX); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_VM_CMS", ZIP_OPSYS_VM_CMS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_ATARI_ST", ZIP_OPSYS_ATARI_ST); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OS_2", ZIP_OPSYS_OS_2); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_MACINTOSH", ZIP_OPSYS_MACINTOSH); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_Z_SYSTEM", ZIP_OPSYS_Z_SYSTEM); ++ REGISTER_ZIP_CLASS_CONST_INT("OPSYS_Z_CPM", ZIP_OPSYS_CPM); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_WINDOWS_NTFS", ZIP_OPSYS_WINDOWS_NTFS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_MVS", ZIP_OPSYS_MVS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_VSE", ZIP_OPSYS_VSE); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_ACORN_RISC", ZIP_OPSYS_ACORN_RISC); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_VFAT", ZIP_OPSYS_VFAT); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_ALTERNATE_MVS", ZIP_OPSYS_ALTERNATE_MVS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_BEOS", ZIP_OPSYS_BEOS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_TANDEM", ZIP_OPSYS_TANDEM); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OS_400", ZIP_OPSYS_OS_400); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OS_X", ZIP_OPSYS_OS_X); + + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT); #endif /* ifdef ZIP_OPSYS_DEFAULT */ php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC);
diff --cc ext/mcrypt/mcrypt.c index ec847d3,70a458d..3a0ce2e --- a/ext/mcrypt/mcrypt.c +++ b/ext/mcrypt/mcrypt.c @@@ -656,12 -615,12 +615,12 @@@ PHP_FUNCTION(mcrypt_generic { zval *mcryptind; char *data; - int data_len; + php_size_t data_len; php_mcrypt *pm; - unsigned char* data_s; - size_t block_size, data_size; + char* data_s; - int block_size, data_size; ++ php_size_t block_size, data_size; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rS", &mcryptind, &data, &data_len) == FAILURE) { return; } @@@ -1165,7 -1124,116 +1124,116 @@@ PHP_FUNCTION(mcrypt_get_cipher_name } /* }}} */ - static void php_mcrypt_do_crypt(char* cipher, const char *key, php_size_t key_len, const char *data, php_size_t data_len, char *mode, const char *iv, php_size_t iv_len, int argc, php_int_t dencrypt, zval* return_value TSRMLS_DC) /* {{{ */ + static char *php_mcrypt_get_key_size_str( - int max_key_size, const int *key_sizes, int key_size_count) /* {{{ */ ++ php_size_t max_key_size, const php_size_t *key_sizes, php_size_t key_size_count) /* {{{ */ + { + if (key_size_count == 0) { + char *str; - spprintf(&str, 0, "Only keys of size 1 to %d supported", max_key_size); ++ spprintf(&str, 0, "Only keys of size 1 to %pd supported", max_key_size); + return str; + } else if (key_size_count == 1) { + char *str; - spprintf(&str, 0, "Only keys of size %d supported", key_sizes[0]); ++ spprintf(&str, 0, "Only keys of size %pd supported", key_sizes[0]); + return str; + } else { - int i; ++ php_size_t i; + smart_str str = {0}; + smart_str_appends(&str, "Only keys of sizes "); + + for (i = 0; i < key_size_count; ++i) { - if (i == key_size_count - 1) { ++ if (i + 1 == key_size_count) { + smart_str_appends(&str, " or "); + } else if (i != 0) { + smart_str_appends(&str, ", "); + } + + smart_str_append_long(&str, key_sizes[i]); + } + + smart_str_appends(&str, " supported"); + smart_str_0(&str); + return str.c; + } + } + /* }}} */ + + static zend_bool php_mcrypt_is_valid_key_size( - int key_size, int max_key_size, int *key_sizes, int key_size_count) /* {{{ */ ++ php_size_t key_size, php_size_t max_key_size, php_size_t *key_sizes, php_size_t key_size_count) /* {{{ */ + { - int i; ++ php_size_t i; + - if (key_size <= 0 || key_size > max_key_size) { ++ if (key_size == 0 || key_size > max_key_size) { + return 0; + } + + if (key_size_count == 0) { + /* All key sizes are valid */ + return 1; + } + + for (i = 0; i < key_size_count; i++) { + if (key_sizes[i] == key_size) { + return 1; + } + } + + return 0; + } + /* }}} */ + -static int php_mcrypt_ensure_valid_key_size(MCRYPT td, int key_size TSRMLS_DC) /* {{{ */ ++static int php_mcrypt_ensure_valid_key_size(MCRYPT td, php_size_t key_size TSRMLS_DC) /* {{{ */ + { - int key_size_count; - int max_key_size = mcrypt_enc_get_key_size(td); - int *key_sizes = mcrypt_enc_get_supported_key_sizes(td, &key_size_count); ++ php_size_t key_size_count; ++ php_size_t max_key_size = mcrypt_enc_get_key_size(td); ++ php_size_t *key_sizes = mcrypt_enc_get_supported_key_sizes(td, &key_size_count); + + zend_bool is_valid_key_size = php_mcrypt_is_valid_key_size( + key_size, max_key_size, key_sizes, key_size_count + ); + if (!is_valid_key_size) { + char *key_size_str = php_mcrypt_get_key_size_str( + max_key_size, key_sizes, key_size_count + ); + php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Key of size %d not supported by this algorithm. %s", key_size, key_size_str ++ "Key of size %pd not supported by this algorithm. %s", key_size, key_size_str + ); + efree(key_size_str); + } + + if (key_sizes) { + mcrypt_free(key_sizes); + } + + return is_valid_key_size ? SUCCESS : FAILURE; + } + /* }}} */ + -static int php_mcrypt_ensure_valid_iv(MCRYPT td, const char *iv, int iv_size TSRMLS_DC) /* {{{ */ ++static int php_mcrypt_ensure_valid_iv(MCRYPT td, const char *iv, php_size_t iv_size TSRMLS_DC) /* {{{ */ + { + if (mcrypt_enc_mode_has_iv(td) == 1) { - int expected_iv_size = mcrypt_enc_get_iv_size(td); ++ php_size_t expected_iv_size = mcrypt_enc_get_iv_size(td); + + if (!iv) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Encryption mode requires an initialization vector of size %d", expected_iv_size ++ "Encryption mode requires an initialization vector of size %pd", expected_iv_size + ); + return FAILURE; + } + + if (iv_size != expected_iv_size) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Received initialization vector of size %d, but size %d is required " ++ "Received initialization vector of size %pd, but size %pd is required " + "for this encryption mode", iv_size, expected_iv_size + ); + return FAILURE; + } + } + + return SUCCESS; + } + /* }}} */ + -static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, const char *data, int data_len, char *mode, const char *iv, int iv_len, int dencrypt, zval* return_value TSRMLS_DC) /* {{{ */ ++static void php_mcrypt_do_crypt(char* cipher, const char *key, php_size_t key_len, const char *data, php_size_t data_len, char *mode, const char *iv, php_size_t iv_len, int dencrypt, zval* return_value TSRMLS_DC) /* {{{ */ { char *cipher_dir_string; char *module_dir_string; @@@ -1237,13 -1261,9 +1261,9 @@@ /* Check blocksize */ if (mcrypt_enc_is_block_mode(td) == 1) { /* It's a block algorithm */ - block_size = mcrypt_enc_get_block_size(td); - if (0 == data_len) { - data_size = block_size; - } else { - data_size = (((data_len - 1) / block_size) + 1) * block_size; - } - data_s = emalloc(data_size); - int block_size = mcrypt_enc_get_block_size(td); ++ php_size_t block_size = mcrypt_enc_get_block_size(td); + data_size = (((data_len - 1) / block_size) + 1) * block_size; + data_s = emalloc(data_size + 1); memset(data_s, 0, data_size); memcpy(data_s, data, data_len); } else { /* It's not a block algorithm */ @@@ -1281,15 -1296,15 +1296,15 @@@ OFB crypt/decrypt data using key key with cipher cipher starting with iv */ PHP_FUNCTION(mcrypt_encrypt) { - zval **mode; - char *cipher, *key, *data, *iv = NULL; - php_size_t data_len, key_len, cipher_len, iv_len = 0; + char *cipher, *key, *data, *mode, *iv = NULL; - int cipher_len, key_len, data_len, mode_len, iv_len = 0; ++ php_size_t cipher_len, key_len, data_len, mode_len, iv_len = 0; - MCRYPT_GET_CRYPT_ARGS - - convert_to_string_ex(mode); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssss|s", &cipher, &cipher_len, + &key, &key_len, &data, &data_len, &mode, &mode_len, &iv, &iv_len) == FAILURE) { + return; + } - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_ENCRYPT, return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, mode, iv, iv_len, MCRYPT_ENCRYPT, return_value TSRMLS_CC); } /* }}} */ @@@ -1297,15 -1312,15 +1312,15 @@@ OFB crypt/decrypt data using key key with cipher cipher starting with iv */ PHP_FUNCTION(mcrypt_decrypt) { - zval **mode; - char *cipher, *key, *data, *iv = NULL; - php_size_t cipher_len, key_len, data_len, iv_len = 0; + char *cipher, *key, *data, *mode, *iv = NULL; - int cipher_len, key_len, data_len, mode_len, iv_len = 0; ++ php_size_t cipher_len, key_len, data_len, mode_len, iv_len = 0; - MCRYPT_GET_CRYPT_ARGS - - convert_to_string_ex(mode); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssss|s", &cipher, &cipher_len, + &key, &key_len, &data, &data_len, &mode, &mode_len, &iv, &iv_len) == FAILURE) { + return; + } - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_DECRYPT, return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, mode, iv, iv_len, MCRYPT_DECRYPT, return_value TSRMLS_CC); } /* }}} */ @@@ -1319,9 -1334,9 +1334,9 @@@ PHP_FUNCTION(mcrypt_ecb MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ecb", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ecb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ @@@ -1335,9 -1350,9 +1350,9 @@@ PHP_FUNCTION(mcrypt_cbc MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cbc", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cbc", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ @@@ -1351,9 -1366,9 +1366,9 @@@ PHP_FUNCTION(mcrypt_cfb MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cfb", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "cfb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ @@@ -1367,9 -1382,9 +1382,9 @@@ PHP_FUNCTION(mcrypt_ofb MCRYPT_GET_CRYPT_ARGS - convert_to_long_ex(mode); + convert_to_int_ex(mode); - php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ofb", iv, iv_len, ZEND_NUM_ARGS(), Z_IVAL_PP(mode), return_value TSRMLS_CC); + php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, "ofb", iv, iv_len, Z_LVAL_PP(mode), return_value TSRMLS_CC); } /* }}} */ diff --cc ext/mysqlnd/mysqlnd_ps.c index 6f4e2a1,dc97d2d..a988090 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@@ -39,16 -39,8 +39,8 @@@ const char * const mysqlnd_stmt_not_pre /* Exported by mysqlnd_ps_codec.c */ enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC); - enum_func_status mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES *result, void *param, - php_uint_t flags, - zend_bool *fetched_anything TSRMLS_DC); - - enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, - php_uint_t flags, - zend_bool *fetched_anything TSRMLS_DC); - static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC); -static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC); +static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, php_uint_t param_no TSRMLS_DC); /* {{{ mysqlnd_stmt::store_result */ @@@ -729,12 -723,13 +723,13 @@@ MYSQLND_METHOD(mysqlnd_stmt, execute)(M /* {{{ mysqlnd_stmt_fetch_row_buffered */ enum_func_status - mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES *result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { MYSQLND_STMT * s = (MYSQLND_STMT *) param; MYSQLND_STMT_DATA * stmt = s? s->data:NULL; MYSQLND_RES_BUFFERED *set = result->stored_data; - php_uint_t field_count = result->meta->field_count; + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; DBG_ENTER("mysqlnd_stmt_fetch_row_buffered"); *fetched_anything = FALSE; @@@ -746,8 -741,7 +741,7 @@@ { /* The user could have skipped binding - don't crash*/ if (stmt->result_bind) { - unsigned int i; + php_uint_t i; - MYSQLND_RES_METADATA * meta = result->meta; zval **current_row = set->data_cursor; if (NULL == current_row[0]) { @@@ -825,8 -819,8 +819,8 @@@ /* {{{ mysqlnd_stmt_fetch_row_unbuffered */ - static enum_func_status - mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) + enum_func_status -mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; MYSQLND_STMT * s = (MYSQLND_STMT *) param; @@@ -857,13 -852,13 +852,13 @@@ /* If we skip rows (stmt == NULL || stmt->result_bind == NULL) we have to - result->m.unbuffered_free_last_data() before it. The function returns always true. + result->unbuf->m.free_last_data() before it. The function returns always true. */ if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { - unsigned int i, field_count = result->field_count; + php_uint_t i, field_count = result->field_count; if (!row_packet->skip_extraction) { - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@@ -891,8 -886,8 +886,8 @@@ zval_dtor(stmt->result_bind[i].zv); #endif if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) { - if ((Z_TYPE_P(data) == IS_STRING) && (result->meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { - result->meta->fields[i].max_length = Z_STRSIZE_P(data); - if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) { - meta->fields[i].max_length = Z_STRLEN_P(data); ++ if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { ++ meta->fields[i].max_length = Z_STRSIZE_P(data); } stmt->result_bind[i].zv->value = data->value; /* copied data, thus also the ownership. Thus null data */ @@@ -993,7 -988,7 +988,7 @@@ MYSQLND_METHOD(mysqlnd_stmt, use_result /* {{{ mysqlnd_fetch_row_cursor */ enum_func_status - mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; MYSQLND_STMT * s = (MYSQLND_STMT *) param; @@@ -1038,10 -1033,11 +1033,11 @@@ memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status)); if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int i, field_count = result->field_count; + php_uint_t i, field_count = result->field_count; if (!row_packet->skip_extraction) { - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@@ -1072,8 -1068,8 +1068,8 @@@ DBG_INF_FMT("i=%u bound_var=%p type=%u refc=%u", i, stmt->result_bind[i].zv, Z_TYPE_P(data), Z_REFCOUNT_P(stmt->result_bind[i].zv)); if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data))) { - if ((Z_TYPE_P(data) == IS_STRING) && (result->meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { - result->meta->fields[i].max_length = Z_STRSIZE_P(data); - if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) { - meta->fields[i].max_length = Z_STRLEN_P(data); ++ if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (php_uint_t) Z_STRSIZE_P(data))) { ++ meta->fields[i].max_length = Z_STRSIZE_P(data); } stmt->result_bind[i].zv->value = data->value; /* copied data, thus also the ownership. Thus null data */ diff --cc ext/mysqlnd/mysqlnd_result.c index 67e7d45,75e7456..226ed6e --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@@ -33,30 -33,31 +33,31 @@@ #define MYSQLND_SILENT - /* {{{ mysqlnd_res::initialize_result_set_rest */ + /* {{{ mysqlnd_result_buffered::initialize_result_set_rest */ static enum_func_status - MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta, + MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC) { - unsigned int i; + php_uint_t i; - zval **data_cursor = result->stored_data? result->stored_data->data:NULL; - zval **data_begin = result->stored_data? result->stored_data->data:NULL; - php_uint_t field_count = result->meta? result->meta->field_count : 0; - uint64_t row_count = result->stored_data? result->stored_data->row_count:0; + zval **data_cursor = result->data; + zval **data_begin = result->data; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; + uint64_t row_count = result->row_count; enum_func_status ret = PASS; - DBG_ENTER("mysqlnd_res::initialize_result_set_rest"); + DBG_ENTER("mysqlnd_result_buffered::initialize_result_set_rest"); - if (!data_cursor || row_count == result->stored_data->initialized_rows) { + if (!data_cursor || row_count == result->initialized_rows) { DBG_RETURN(ret); } -- while ((data_cursor - data_begin) < (int)(row_count * field_count)) { ++ while ((data_cursor - data_begin) < (ptrdiff_t)(row_count * field_count)) { if (NULL == data_cursor[0]) { enum_func_status rc = result->m.row_decoder( - result->stored_data->row_buffers[(data_cursor - data_begin) / field_count], + result->row_buffers[(data_cursor - data_begin) / field_count], data_cursor, - result->meta->field_count, - result->meta->fields, - result->conn->options->int_and_float_native, - result->conn->stats TSRMLS_CC); + meta->field_count, + meta->fields, + int_and_float_native, + stats TSRMLS_CC); if (rc != PASS) { ret = FAIL; break; @@@ -69,9 -70,9 +70,9 @@@ Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE_P(data_cursor[i]) >= IS_STRING) { - php_uint_t len = Z_STRSIZE_P(data_cursor[i]); - if (result->meta->fields[i].max_length < len) { - result->meta->fields[i].max_length = len; - unsigned long len = Z_STRLEN_P(data_cursor[i]); ++ php_size_t len = Z_STRSIZE_P(data_cursor[i]); + if (meta->fields[i].max_length < len) { + meta->fields[i].max_length = len; } } } @@@ -139,13 -140,13 +140,13 @@@ MYSQLND_METHOD(mysqlnd_result_unbuffere DBG_VOID_RETURN; } + DBG_INF_FMT("field_count=%u", unbuf->field_count); if (unbuf->last_row_data) { - unsigned int i, ctor_called_count = 0; + php_uint_t i, ctor_called_count = 0; zend_bool copy_ctor_called; - MYSQLND_STATS *global_stats = result->conn? result->conn->stats:NULL; - for (i = 0; i < result->field_count; i++) { - mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, ©_ctor_called TSRMLS_CC); + for (i = 0; i < unbuf->field_count; i++) { + mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), unbuf->ps ? MYSQLND_RES_PS_UNBUF : MYSQLND_RES_NORMAL, ©_ctor_called TSRMLS_CC); if (copy_ctor_called) { ++ctor_called_count; } @@@ -173,12 -175,41 +175,41 @@@ /* }}} */ - /* {{{ mysqlnd_res::free_buffered_data */ + /* {{{ mysqlnd_result_unbuffered::free_result */ static void - MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED * const result, MYSQLND_STATS * const global_stats TSRMLS_DC) { - MYSQLND_RES_BUFFERED *set = result->stored_data; - php_uint_t field_count = result->field_count; + DBG_ENTER("mysqlnd_result_unbuffered, free_result"); + result->m.free_last_data(result, global_stats TSRMLS_CC); + + if (result->lengths) { + mnd_pefree(result->lengths, result->persistent); + result->lengths = NULL; + } + + /* must be free before because references the memory pool */ + if (result->row_packet) { + PACKET_FREE(result->row_packet); + result->row_packet = NULL; + } + + if (result->result_set_memory_pool) { + mysqlnd_mempool_destroy(result->result_set_memory_pool TSRMLS_CC); + result->result_set_memory_pool = NULL; + } + + + mnd_pefree(result, result->persistent); + DBG_VOID_RETURN; + } + /* }}} */ + + + /* {{{ mysqlnd_result_buffered::free_result */ + static void + MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set TSRMLS_DC) + { - unsigned int field_count = set->field_count; ++ php_uint_t field_count = set->field_count; int64_t row; DBG_ENTER("mysqlnd_res::free_buffered_data"); @@@ -559,12 -589,12 +589,12 @@@ mysqlnd_query_read_result_set_header(MY of PHP, to be called as separate function. But let's have it for completeness. */ -static unsigned long * +static php_uint_t * - mysqlnd_fetch_lengths_buffered(MYSQLND_RES * const result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { - unsigned int i; + php_uint_t i; zval **previous_row; - MYSQLND_RES_BUFFERED *set = result->stored_data; + MYSQLND_RES_BUFFERED *set = result; /* If: @@@ -579,9 -609,9 +609,9 @@@ return NULL;/* No rows or no more rows */ } - previous_row = set->data_cursor - result->meta->field_count; - for (i = 0; i < result->meta->field_count; i++) { + previous_row = set->data_cursor - result->field_count; + for (i = 0; i < result->field_count; i++) { - result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRLEN_P(previous_row[i]); + result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRSIZE_P(previous_row[i]); } return result->lengths; @@@ -589,45 -619,52 +619,52 @@@ /* }}} */ - /* {{{ mysqlnd_fetch_lengths_unbuffered */ + /* {{{ mysqlnd_result_unbuffered::fetch_lengths */ -static unsigned long * +static php_uint_t * - mysqlnd_fetch_lengths_unbuffered(MYSQLND_RES * const result TSRMLS_DC) + MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result TSRMLS_DC) { /* simulate output of libmysql */ - return (!result->unbuf || result->unbuf->last_row_data || result->unbuf->eof_reached)? result->lengths:NULL; + return (result->last_row_data || result->eof_reached)? result->lengths : NULL; } /* }}} */ /* {{{ mysqlnd_res::fetch_lengths */ - PHPAPI php_uint_t * _mysqlnd_fetch_lengths(MYSQLND_RES * const result TSRMLS_DC) -static unsigned long * ++static php_uint_t * + MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC) { - return result->m.fetch_lengths? result->m.fetch_lengths(result TSRMLS_CC) : NULL; - unsigned long * ret; ++ php_uint_t * ret; + DBG_ENTER("mysqlnd_res::fetch_lengths"); + ret = result->stored_data && result->stored_data->m.fetch_lengths ? + result->stored_data->m.fetch_lengths(result->stored_data TSRMLS_CC) : + (result->unbuf && result->unbuf->m.fetch_lengths ? + result->unbuf->m.fetch_lengths(result->unbuf TSRMLS_CC) : + NULL + ); + DBG_RETURN(ret); } /* }}} */ - /* {{{ mysqlnd_fetch_row_unbuffered_c */ - static MYSQLND_ROW_C - mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) + /* {{{ mysqlnd_result_unbuffered::fetch_row_c */ + static enum_func_status -MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; - MYSQLND_ROW_C retrow = NULL; - php_uint_t i, - field_count = result->field_count; - MYSQLND_PACKET_ROW *row_packet = result->row_packet; - php_uint_t *lengths = result->lengths; + MYSQLND_ROW_C *row = (MYSQLND_ROW_C *) param; + MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet; + const MYSQLND_RES_METADATA * const meta = result->meta; - DBG_ENTER("mysqlnd_fetch_row_unbuffered_c"); + DBG_ENTER("mysqlnd_result_unbuffered::fetch_row_c"); + *fetched_anything = FALSE; if (result->unbuf->eof_reached) { /* No more rows obviously */ - DBG_RETURN(retrow); + DBG_RETURN(PASS); } if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) { - SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, - UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); - DBG_RETURN(retrow); + SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + DBG_RETURN(FAIL); } if (!row_packet) { /* Not fully initialized object that is being cleaned up */ @@@ -653,46 -688,51 +688,51 @@@ MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF); if (!row_packet->skip_extraction) { - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; - - enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer, - result->unbuf->last_row_data, - row_packet->field_count, - row_packet->fields_metadata, - result->conn->options->int_and_float_native, - result->conn->stats TSRMLS_CC); - unsigned int i, field_count = meta->field_count; ++ php_uint_t i, field_count = meta->field_count; + + enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer, + result->unbuf->last_row_data, + field_count, + row_packet->fields_metadata, + result->conn->options->int_and_float_native, + result->conn->stats TSRMLS_CC); if (PASS != rc) { - DBG_RETURN(retrow); + DBG_RETURN(FAIL); } + { + *row = mnd_malloc(field_count * sizeof(char *)); + if (*row) { + MYSQLND_FIELD * field = meta->fields; - unsigned long * lengths = result->unbuf->lengths; ++ php_uint_t * lengths = result->unbuf->lengths; + + for (i = 0; i < field_count; i++, field++) { + zval * data = result->unbuf->last_row_data[i]; - unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); ++ php_size_t len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data); + + /* BEGIN difference between normal normal fetch and _c */ + if (Z_TYPE_P(data) != IS_NULL) { + convert_to_string(data); + (*row)[i] = Z_STRVAL_P(data); + } else { + (*row)[i] = NULL; + } + /* END difference between normal normal fetch and _c */ - retrow = mnd_malloc(result->field_count * sizeof(char *)); - if (retrow) { - for (i = 0; i < field_count; i++, field++, hash_key++) { - zval *data = result->unbuf->last_row_data[i]; - php_size_t len; - - if (Z_TYPE_P(data) != IS_NULL) { - convert_to_string(data); - retrow[i] = Z_STRVAL_P(data); - len = Z_STRSIZE_P(data); - } else { - retrow[i] = NULL; - len = 0; - } - - if (lengths) { - lengths[i] = len; - } + if (lengths) { + lengths[i] = len; + } - if (field->max_length < len) { - field->max_length = len; + if (field->max_length < len) { + field->max_length = len; + } } + } else { + SET_OOM_ERROR(*result->conn->error_info); } - } else { - SET_OOM_ERROR(*result->conn->error_info); } } + result->unbuf->row_count++; + *fetched_anything = TRUE; } else if (ret == FAIL) { if (row_packet->error_info.error_no) { COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info); @@@ -724,9 -765,9 +765,9 @@@ /* }}} */ - /* {{{ mysqlnd_fetch_row_unbuffered */ + /* {{{ mysqlnd_result_unbuffered::fetch_row */ static enum_func_status - mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; zval *row = (zval *) param; @@@ -765,13 -807,9 +807,9 @@@ MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF); if (!row_packet->skip_extraction) { - HashTable *row_ht = Z_ARRVAL_P(row); - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; - php_uint_t i, field_count = result->field_count; - php_uint_t *lengths = result->lengths; - unsigned int i, field_count = meta->field_count; ++ php_uint_t i, field_count = meta->field_count; - enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer, + enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer, result->unbuf->last_row_data, field_count, row_packet->fields_metadata, @@@ -780,46 -818,51 +818,51 @@@ if (PASS != rc) { DBG_RETURN(FAIL); } - for (i = 0; i < field_count; i++, field++, hash_key++) { - zval *data = result->unbuf->last_row_data[i]; - php_size_t len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data); + { + HashTable * row_ht = Z_ARRVAL_P(row); + MYSQLND_FIELD * field = meta->fields; - unsigned long * lengths = result->unbuf->lengths; ++ php_size_t * lengths = result->unbuf->lengths; + + for (i = 0; i < field_count; i++, field++) { + zval * data = result->unbuf->last_row_data[i]; - unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); ++ php_size_t = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRSIZE_P(data); + + if (flags & MYSQLND_FETCH_NUM) { + Z_ADDREF_P(data); + zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL); + } + if (flags & MYSQLND_FETCH_ASSOC) { + /* zend_hash_quick_update needs length + trailing zero */ + /* QQ: Error handling ? */ + /* + zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether + the index is a numeric and convert it to it. This however means constant + hashing of the column name, which is not needed as it can be precomputed. + */ + Z_ADDREF_P(data); + if (meta->zend_hash_keys[i].is_numeric == FALSE) { + zend_hash_quick_update(Z_ARRVAL_P(row), + field->name, + field->name_length + 1, + meta->zend_hash_keys[i].key, + (void *) &data, sizeof(zval *), NULL); + } else { + zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, (void *) &data, sizeof(zval *), NULL); + } + } - if (lengths) { - lengths[i] = len; - } + if (lengths) { + lengths[i] = len; + } - if (flags & MYSQLND_FETCH_NUM) { - Z_ADDREF_P(data); - zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL); - } - if (flags & MYSQLND_FETCH_ASSOC) { - /* zend_hash_quick_update needs length + trailing zero */ - /* QQ: Error handling ? */ - /* - zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether - the index is a numeric and convert it to it. This however means constant - hashing of the column name, which is not needed as it can be precomputed. - */ - Z_ADDREF_P(data); - if (hash_key->is_numeric == FALSE) { - zend_hash_quick_update(Z_ARRVAL_P(row), - field->name, - field->name_length + 1, - hash_key->key, - (void *) &data, sizeof(zval *), NULL); - } else { - zend_hash_index_update(Z_ARRVAL_P(row), - hash_key->key, - (void *) &data, sizeof(zval *), NULL); + if (field->max_length < len) { + field->max_length = len; } } - if (field->max_length < len) { - field->max_length = len; - } } } - *fetched_anything = TRUE; result->unbuf->row_count++; + *fetched_anything = TRUE; } else if (ret == FAIL) { if (row_packet->error_info.error_no) { COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info); @@@ -909,30 -939,32 +939,32 @@@ oom /* }}} */ - /* {{{ mysqlnd_fetch_row_buffered_c */ - static MYSQLND_ROW_C - mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC) + /* {{{ mysqlnd_result_buffered::fetch_row_c */ + static enum_func_status -MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { - MYSQLND_ROW_C ret = NULL; - MYSQLND_RES_BUFFERED *set = result->stored_data; + MYSQLND_ROW_C * row = (MYSQLND_ROW_C *) param; + MYSQLND_RES_BUFFERED * set = result->stored_data; + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; + enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_fetch_row_buffered_c"); + DBG_ENTER("mysqlnd_result_buffered::fetch_row_c"); /* If we haven't read everything */ if (set->data_cursor && - (set->data_cursor - set->data) < (set->row_count * result->meta->field_count)) + (set->data_cursor - set->data) < (set->row_count * field_count)) { zval **current_row = set->data_cursor; - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; + MYSQLND_FIELD * field = meta->fields; - unsigned int i; + php_uint_t i; if (NULL == current_row[0]) { - uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count; - enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num], + uint64_t row_num = (set->data_cursor - set->data) / field_count; + enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num], current_row, - result->meta->field_count, - result->meta->fields, + field_count, + meta->fields, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { @@@ -980,31 -1019,32 +1019,32 @@@ /* }}} */ - /* {{{ mysqlnd_fetch_row_buffered */ + /* {{{ mysqlnd_result_buffered::fetch_row */ static enum_func_status - mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) -MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool * fetched_anything TSRMLS_DC) { - php_uint_t i; - zval *row = (zval *) param; - MYSQLND_RES_BUFFERED *set = result->stored_data; + zval * row = (zval *) param; + MYSQLND_RES_BUFFERED * set = result->stored_data; + const MYSQLND_RES_METADATA * const meta = result->meta; - unsigned int field_count = meta->field_count; ++ php_uint_t field_count = meta->field_count; enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_fetch_row_buffered"); + DBG_ENTER("mysqlnd_result_buffered::fetch_row"); /* If we haven't read everything */ if (set->data_cursor && - (set->data_cursor - set->data) < (set->row_count * result->meta->field_count)) + (set->data_cursor - set->data) < (set->row_count * field_count)) { zval **current_row = set->data_cursor; - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; + MYSQLND_FIELD * field = meta->fields; - unsigned int i; ++ php_uint_t i; if (NULL == current_row[0]) { - uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count; - enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num], + uint64_t row_num = (set->data_cursor - set->data) / field_count; + enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num], current_row, - result->meta->field_count, - result->meta->fields, + field_count, + meta->fields, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { @@@ -1071,6 -1111,20 +1111,20 @@@ /* }}} */ + /* {{{ mysqlnd_res::fetch_row */ + static enum_func_status -MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool *fetched_anything TSRMLS_DC) ++MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, php_uint_t flags, zend_bool *fetched_anything TSRMLS_DC) + { + const mysqlnd_fetch_row_func f = result->stored_data? result->stored_data->m.fetch_row:(result->unbuf? result->unbuf->m.fetch_row:NULL); + if (f) { + return f(result, param, flags, fetched_anything TSRMLS_CC); + } + *fetched_anything = FALSE; + return PASS; + } + /* }}} */ + + #define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2 /* {{{ mysqlnd_res::store_result_fetch_data */ @@@ -1080,8 -1134,8 +1134,8 @@@ MYSQLND_METHOD(mysqlnd_res, store_resul zend_bool binary_protocol TSRMLS_DC) { enum_func_status ret; - MYSQLND_PACKET_ROW *row_packet = NULL; + MYSQLND_PACKET_ROW * row_packet = NULL; - unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1; + php_uint_t next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1; MYSQLND_RES_BUFFERED *set; DBG_ENTER("mysqlnd_res::store_result_fetch_data"); @@@ -1647,10 -1720,10 +1720,10 @@@ MYSQLND_CLASS_METHODS_END /* {{{ mysqlnd_result_init */ PHPAPI MYSQLND_RES * -mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC) +mysqlnd_result_init(php_uint_t field_count, zend_bool persistent TSRMLS_DC) { size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *); - MYSQLND_RES *ret = mnd_pecalloc(1, alloc_size, persistent); + MYSQLND_RES * ret = mnd_pecalloc(1, alloc_size, persistent); DBG_ENTER("mysqlnd_result_init"); @@@ -1667,6 -1740,86 +1740,86 @@@ /* }}} */ + /* {{{ mysqlnd_result_unbuffered_init */ + PHPAPI MYSQLND_RES_UNBUFFERED * -mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) ++mysqlnd_result_unbuffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) + { + size_t alloc_size = sizeof(MYSQLND_RES_UNBUFFERED) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_UNBUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_result_unbuffered_init"); + + if (!ret) { + DBG_RETURN(NULL); + } + - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { ++ if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) { + mnd_efree(ret->lengths); + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + + ret->persistent = persistent; + ret->field_count= field_count; + ret->ps = ps; + + ret->m = *mysqlnd_result_unbuffered_get_methods(); + + if (ps) { + ret->m.fetch_lengths = NULL; /* makes no sense */ + ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; + } else { + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + } + + DBG_RETURN(ret); + } + /* }}} */ + + + /* {{{ mysqlnd_result_buffered_init */ + PHPAPI MYSQLND_RES_BUFFERED * -mysqlnd_result_buffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) ++mysqlnd_result_buffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) + { + size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_BUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_result_buffered_init"); + + if (!ret) { + DBG_RETURN(NULL); + } + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) { + mnd_efree(ret->lengths); + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + + ret->persistent = persistent; + ret->field_count= field_count; + ret->ps = ps; + ret->m = *mysqlnd_result_buffered_get_methods(); + + if (ps) { + ret->m.fetch_lengths = NULL; /* makes no sense */ + ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; + } else { + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + } + + DBG_RETURN(ret); + } + /* }}} */ + + /* * Local variables: * tab-width: 4 diff --cc ext/mysqlnd/mysqlnd_result.h index c647c02,0a54ea0..09e0f81 --- a/ext/mysqlnd/mysqlnd_result.h +++ b/ext/mysqlnd/mysqlnd_result.h @@@ -23,7 -23,9 +23,9 @@@ #ifndef MYSQLND_RESULT_H #define MYSQLND_RESULT_H -PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC); -PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); -PHPAPI MYSQLND_RES_BUFFERED * mysqlnd_result_buffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); +PHPAPI MYSQLND_RES * mysqlnd_result_init(php_uint_t field_count, zend_bool persistent TSRMLS_DC); ++PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); ++PHPAPI MYSQLND_RES_BUFFERED * mysqlnd_result_buffered_init(php_uint_t field_count, zend_bool ps, zend_bool persistent TSRMLS_DC); enum_func_status mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt TSRMLS_DC); diff --cc ext/mysqlnd/mysqlnd_structs.h index 57f8512,5c035a5..aa6182a --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@@ -243,11 -243,12 +243,12 @@@ typedef struct st_mysqlnd_debug MYSQLND typedef MYSQLND_RES* (*mysqlnd_stmt_use_or_store_func)(MYSQLND_STMT * const TSRMLS_DC); typedef enum_func_status (*mysqlnd_fetch_row_func)(MYSQLND_RES *result, - void *param, + void * param, - unsigned int flags, + php_uint_t flags, - zend_bool *fetched_anything + zend_bool * fetched_anything TSRMLS_DC); + typedef struct st_mysqlnd_stats MYSQLND_STATS; typedef void (*mysqlnd_stat_trigger)(MYSQLND_STATS * stats, enum_mysqlnd_collected_stats stat, int64_t change TSRMLS_DC); @@@ -606,31 -607,31 +607,31 @@@ struct st_mysqlnd_conn_method func_mysqlnd_conn__close close; }; + /* for decoding - binary or text protocol */ + typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - unsigned int field_count, const MYSQLND_FIELD * fields_metadata, ++ php_uint_t field_count, const MYSQLND_FIELD * fields_metadata, + zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); - typedef mysqlnd_fetch_row_func fetch_row; - typedef mysqlnd_fetch_row_func fetch_row_normal_buffered; /* private */ - typedef mysqlnd_fetch_row_func fetch_row_normal_unbuffered; /* private */ typedef MYSQLND_RES * (*func_mysqlnd_res__use_result)(MYSQLND_RES * const result, zend_bool ps_protocol TSRMLS_DC); typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND_CONN_DATA * const conn, zend_bool ps TSRMLS_DC); -typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, unsigned int flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC); +typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, php_uint_t flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC); typedef MYSQLND_ROW_C (*func_mysqlnd_res__fetch_row_c)(MYSQLND_RES *result TSRMLS_DC); -typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC); -typedef void (*func_mysqlnd_res__fetch_field_data)(MYSQLND_RES *result, unsigned int offset, zval *return_value TSRMLS_DC); +typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, php_uint_t flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC); +typedef void (*func_mysqlnd_res__fetch_field_data)(MYSQLND_RES *result, php_uint_t offset, zval *return_value TSRMLS_DC); typedef uint64_t (*func_mysqlnd_res__num_rows)(const MYSQLND_RES * const result TSRMLS_DC); -typedef unsigned int (*func_mysqlnd_res__num_fields)(const MYSQLND_RES * const result TSRMLS_DC); +typedef php_uint_t (*func_mysqlnd_res__num_fields)(const MYSQLND_RES * const result TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_res__skip_result)(MYSQLND_RES * const result TSRMLS_DC); - typedef enum_func_status (*func_mysqlnd_res__seek_data)(MYSQLND_RES * result, uint64_t row TSRMLS_DC); - typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res__seek_field)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET field_offset TSRMLS_DC); + typedef enum_func_status (*func_mysqlnd_res__seek_data)(MYSQLND_RES * const result, const uint64_t row TSRMLS_DC); + typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res__seek_field)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET field_offset TSRMLS_DC); typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res__field_tell)(const MYSQLND_RES * const result TSRMLS_DC); typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field)(MYSQLND_RES * const result TSRMLS_DC); - typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC); + typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field_direct)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC); typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_fields)(MYSQLND_RES * const result TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn TSRMLS_DC); -typedef unsigned long * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC); +typedef php_uint_t * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol TSRMLS_DC); - typedef enum_func_status (*func_mysqlnd_res__initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC); typedef void (*func_mysqlnd_res__free_result_buffers)(MYSQLND_RES * result TSRMLS_DC); /* private */ typedef enum_func_status (*func_mysqlnd_res__free_result)(MYSQLND_RES * result, zend_bool implicit TSRMLS_DC); @@@ -639,12 -640,8 +640,8 @@@ typedef void (*func_mysqlnd_res__fre typedef void (*func_mysqlnd_res__free_buffered_data)(MYSQLND_RES *result TSRMLS_DC); typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *result TSRMLS_DC); - /* for decoding - binary or text protocol */ - typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - php_uint_t field_count, const MYSQLND_FIELD * fields_metadata, - zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); -typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(unsigned int field_count, zend_bool persistent TSRMLS_DC); +typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(php_uint_t field_count, zend_bool persistent TSRMLS_DC); struct st_mysqlnd_res_methods { @@@ -974,9 -999,23 +999,23 @@@ struct st_mysqlnd_buffered_resul uint64_t row_count; uint64_t initialized_rows; + /* + Column lengths of current row - both buffered and unbuffered. + For buffered results it duplicates the data found in **data + */ - unsigned long *lengths; ++ php_uint_t *lengths; + + MYSQLND_MEMORY_POOL *result_set_memory_pool; + - unsigned int references; + php_uint_t references; MYSQLND_ERROR_INFO error_info; + - unsigned int field_count; ++ php_uint_t field_count; + zend_bool ps; + zend_bool persistent; + + struct st_mysqlnd_result_buffered_methods m; }; @@@ -986,8 -1026,24 +1026,24 @@@ struct st_mysqlnd_unbuffered_resul zval **last_row_data; MYSQLND_MEMORY_POOL_CHUNK *last_row_buffer; + /* + Column lengths of current row - both buffered and unbuffered. + For buffered results it duplicates the data found in **data + */ - unsigned long *lengths; ++ php_uint_t *lengths; + + MYSQLND_MEMORY_POOL *result_set_memory_pool; + + struct st_mysqlnd_packet_row * row_packet; + uint64_t row_count; zend_bool eof_reached; + - unsigned int field_count; ++ php_uint_t field_count; + zend_bool ps; + zend_bool persistent; + + struct st_mysqlnd_result_unbuffered_methods m; }; diff --cc ext/openssl/openssl.c index 5d06242,97740d3..b580ee6 mode 100644,100755..100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@@ -630,16 -615,14 +615,14 @@@ struct php_x509_request { /* {{{ * }; /* }}} */ -static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC); -static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * passphrase, int makeresource, long * resourceval TSRMLS_DC); +static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, php_int_t * resourceval TSRMLS_DC); +static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * passphrase, int makeresource, php_int_t * resourceval TSRMLS_DC); static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC); - static X509_STORE * setup_verify(zval * calist TSRMLS_DC); + static X509_STORE * setup_verify(zval * calist TSRMLS_DC); static STACK_OF(X509) * load_all_certs_from_file(char *certfile); -static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC); +static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, php_int_t * resourceval TSRMLS_DC); static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req TSRMLS_DC); - #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i))) - static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */ { zval **data; @@@ -1169,24 -1150,23 +1152,23 @@@ PHP_MINIT_FUNCTION(openssl #endif /* flags for S/MIME */ - REGISTER_LONG_CONSTANT("PKCS7_DETACHED", PKCS7_DETACHED, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_TEXT", PKCS7_TEXT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOINTERN", PKCS7_NOINTERN, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOVERIFY", PKCS7_NOVERIFY, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOCHAIN", PKCS7_NOCHAIN, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOCERTS", PKCS7_NOCERTS, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOATTR", PKCS7_NOATTR, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_BINARY", PKCS7_BINARY, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PKCS7_NOSIGS", PKCS7_NOSIGS, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_DETACHED", PKCS7_DETACHED, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_TEXT", PKCS7_TEXT, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOINTERN", PKCS7_NOINTERN, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOVERIFY", PKCS7_NOVERIFY, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOCHAIN", PKCS7_NOCHAIN, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOCERTS", PKCS7_NOCERTS, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOATTR", PKCS7_NOATTR, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_BINARY", PKCS7_BINARY, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("PKCS7_NOSIGS", PKCS7_NOSIGS, CONST_CS|CONST_PERSISTENT); + + REGISTER_INT_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_INT_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); /* Informational stream wrapper constants */ - REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", PHP_OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT); - REGISTER_INT_CONSTANT("OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH", PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH, CONST_CS|CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT); /* Ciphers */ #ifndef OPENSSL_NO_RC2 diff --cc ext/openssl/xp_ssl.c index 508c81c,e251d21..4a23764 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@@ -425,7 -718,120 +718,120 @@@ static long load_stream_cafile(X509_STO } /* }}} */ - static const SSL_METHOD *php_select_crypto_method(php_int_t method_value, int is_client TSRMLS_DC) + static int enable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ + { + zval **val = NULL; + char *cafile = NULL; + char *capath = NULL; + + GET_VER_OPT_STRING("cafile", cafile); + GET_VER_OPT_STRING("capath", capath); + + if (!cafile) { + cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0); + cafile = strlen(cafile) ? cafile : NULL; + } + + if (!capath) { + capath = zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0); + capath = strlen(capath) ? capath : NULL; + } + + if (cafile || capath) { + if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) { + if (cafile && !load_stream_cafile(SSL_CTX_get_cert_store(ctx), cafile TSRMLS_CC)) { + return FAILURE; + } + } + } else { + #if defined(PHP_WIN32) && OPENSSL_VERSION_NUMBER >= 0x00907000L + SSL_CTX_set_cert_verify_callback(ctx, win_cert_verify_callback, (void *)stream); + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + #else + php_openssl_netstream_data_t *sslsock; + sslsock = (php_openssl_netstream_data_t*)stream->abstract; + + if (sslsock->is_client && !SSL_CTX_set_default_verify_paths(ctx)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to set default verify locations and no CA settings specified"); + return FAILURE; + } + #endif + } + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); + + return SUCCESS; + } + /* }}} */ + + static void disable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ + { + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); + } + /* }}} */ + + static int set_local_cert(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ + { + zval **val = NULL; + char *certfile = NULL; + + GET_VER_OPT_STRING("local_cert", certfile); + + if (certfile) { + char resolved_path_buff[MAXPATHLEN]; + const char * private_key = NULL; + + if (VCWD_REALPATH(certfile, resolved_path_buff)) { + /* a certificate to use for authentication */ + if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile); + return FAILURE; + } + GET_VER_OPT_STRING("local_pk", private_key); + + if (private_key) { + char resolved_path_buff_pk[MAXPATHLEN]; + if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) { + if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk); + return FAILURE; + } + } + } else { + if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff); + return FAILURE; + } + } + + #if OPENSSL_VERSION_NUMBER < 0x10001001L + do { + /* Unnecessary as of OpenSSLv1.0.1 (will segfault if used with >= 10001001 ) */ + X509 *cert = NULL; + EVP_PKEY *key = NULL; + SSL *tmpssl = SSL_new(ctx); + cert = SSL_get_certificate(tmpssl); + + if (cert) { + key = X509_get_pubkey(cert); + EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); + EVP_PKEY_free(key); + } + SSL_free(tmpssl); + } while (0); + #endif + if (!SSL_CTX_check_private_key(ctx)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Private key does not match certificate!"); + } + } + } + + return SUCCESS; + } + /* }}} */ + -static const SSL_METHOD *php_select_crypto_method(long method_value, int is_client TSRMLS_DC) /* {{{ */ ++static const SSL_METHOD *php_select_crypto_method(php_int_t method_value, int is_client TSRMLS_DC) /* {{{ */ { if (method_value == STREAM_CRYPTO_METHOD_SSLv2) { #ifndef OPENSSL_NO_SSL2 @@@ -461,10 -867,11 +867,11 @@@ return NULL; } } + /* }}} */ - static php_int_t php_get_crypto_method_ctx_flags(php_int_t method_flags TSRMLS_DC) -static long php_get_crypto_method_ctx_flags(long method_flags TSRMLS_DC) /* {{{ */ ++static php_int_t php_get_crypto_method_ctx_flags(php_int_t method_flags TSRMLS_DC) /* {{{ */ { - long ssl_ctx_options = SSL_OP_ALL; + php_int_t ssl_ctx_options = SSL_OP_ALL; #ifndef OPENSSL_NO_SSL2 if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv2)) { @@@ -493,72 -900,238 +900,238 @@@ return ssl_ctx_options; } + /* }}} */ - static inline int php_openssl_setup_crypto(php_stream *stream, - php_openssl_netstream_data_t *sslsock, - php_stream_xport_crypto_param *cparam - TSRMLS_DC) + static void limit_handshake_reneg(const SSL *ssl) /* {{{ */ { - const SSL_METHOD *method; - php_int_t ssl_ctx_options; - php_int_t method_flags; - zval **val; - #ifdef SSL_MODE_RELEASE_BUFFERS - php_int_t mode; - #endif + php_stream *stream; + php_openssl_netstream_data_t *sslsock; + struct timeval now; - long elapsed_time; ++ php_int_t elapsed_time; - if (sslsock->ssl_handle) { - if (sslsock->s.is_blocked) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream"); - return -1; + stream = php_openssl_get_stream_from_ssl_handle(ssl); + sslsock = (php_openssl_netstream_data_t*)stream->abstract; + gettimeofday(&now, NULL); + + /* The initial handshake is never rate-limited */ + if (sslsock->reneg->prev_handshake == 0) { + sslsock->reneg->prev_handshake = now.tv_sec; + return; + } + + elapsed_time = (now.tv_sec - sslsock->reneg->prev_handshake); + sslsock->reneg->prev_handshake = now.tv_sec; + sslsock->reneg->tokens -= (elapsed_time * (sslsock->reneg->limit / sslsock->reneg->window)); + + if (sslsock->reneg->tokens < 0) { + sslsock->reneg->tokens = 0; + } + ++sslsock->reneg->tokens; + + /* The token level exceeds our allowed limit */ + if (sslsock->reneg->tokens > sslsock->reneg->limit) { + zval **val; + + TSRMLS_FETCH(); + + sslsock->reneg->should_close = 1; + + if (stream->context && SUCCESS == php_stream_context_get_option(stream->context, + "ssl", "reneg_limit_callback", &val) + ) { + zval *param, **params[1], *retval; + + MAKE_STD_ZVAL(param); + php_stream_to_zval(stream, param); + params[0] = ¶m; + + /* Closing the stream inside this callback would segfault! */ + stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; + if (FAILURE == call_user_function_ex(EG(function_table), NULL, *val, &retval, 1, params, 0, NULL TSRMLS_CC)) { + php_error(E_WARNING, "SSL: failed invoking reneg limit notification callback"); + } + stream->flags ^= PHP_STREAM_FLAG_NO_FCLOSE; + + /* If the reneg_limit_callback returned true don't auto-close */ + if (retval != NULL && Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval) == 1) { + sslsock->reneg->should_close = 0; + } + + FREE_ZVAL(param); + if (retval != NULL) { + zval_ptr_dtor(&retval); + } } else { - return 0; + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SSL: client-initiated handshake rate limit exceeded by peer"); } } + } + /* }}} */ - /* need to do slightly different things, based on client/server method, - * so lets remember which method was selected */ - sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT; - method_flags = ((cparam->inputs.method >> 1) << 1); + static void info_callback(const SSL *ssl, int where, int ret) /* {{{ */ + { + /* Rate-limit client-initiated handshake renegotiation to prevent DoS */ + if (where & SSL_CB_HANDSHAKE_START) { + limit_handshake_reneg(ssl); + } + } + /* }}} */ - /* Should we use a specific crypto method or is generic SSLv23 okay? */ - if ((method_flags & (method_flags-1)) == 0) { - ssl_ctx_options = SSL_OP_ALL; - method = php_select_crypto_method(method_flags, sslsock->is_client TSRMLS_CC); - if (method == NULL) { - return -1; + static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ + { + zval **val; + long limit = OPENSSL_DEFAULT_RENEG_LIMIT; + long window = OPENSSL_DEFAULT_RENEG_WINDOW; + + if (stream->context && + SUCCESS == php_stream_context_get_option(stream->context, + "ssl", "reneg_limit", &val) + ) { + convert_to_long(*val); + limit = Z_LVAL_PP(val); + } + + /* No renegotiation rate-limiting */ + if (limit < 0) { + return; + } + + if (stream->context && + SUCCESS == php_stream_context_get_option(stream->context, + "ssl", "reneg_window", &val) + ) { + convert_to_long(*val); + window = Z_LVAL_PP(val); + } + + sslsock->reneg = (void*)pemalloc(sizeof(php_openssl_handshake_bucket_t), + php_stream_is_persistent(stream) + ); + + sslsock->reneg->limit = limit; + sslsock->reneg->window = window; + sslsock->reneg->prev_handshake = 0; + sslsock->reneg->tokens = 0; + sslsock->reneg->should_close = 0; + + SSL_set_info_callback(sslsock->ssl_handle, info_callback); + } + /* }}} */ + + static int set_server_rsa_key(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ + { + zval ** val; + int rsa_key_size; + RSA* rsa; + + if (php_stream_context_get_option(stream->context, "ssl", "rsa_key_size", &val) == SUCCESS) { + rsa_key_size = (int) Z_LVAL_PP(val); + if ((rsa_key_size != 1) && (rsa_key_size & (rsa_key_size - 1))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "RSA key size requires a power of 2: %d", rsa_key_size); + rsa_key_size = 2048; } } else { - method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method(); - ssl_ctx_options = php_get_crypto_method_ctx_flags(method_flags TSRMLS_CC); - if (ssl_ctx_options == -1) { - return -1; + rsa_key_size = 2048; + } + + rsa = RSA_generate_key(rsa_key_size, RSA_F4, NULL, NULL); + + if (!SSL_CTX_set_tmp_rsa(ctx, rsa)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting RSA key"); + RSA_free(rsa); + return FAILURE; + } + + RSA_free(rsa); + + return SUCCESS; + } + /* }}} */ + + static int set_server_dh_param(SSL_CTX *ctx, char *dh_path TSRMLS_DC) /* {{{ */ + { + DH *dh; + BIO* bio; + + bio = BIO_new_file(dh_path, "r"); + + if (bio == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid dh_param file: %s", dh_path); + return FAILURE; + } + + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + + if (dh == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed reading DH params from file: %s", dh_path); + return FAILURE; + } + + if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "DH param assignment failed"); + DH_free(dh); + return FAILURE; + } + + DH_free(dh); + + return SUCCESS; + } + /* }}} */ + + #ifdef HAVE_ECDH + static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ + { + zval **val; + int curve_nid; + char *curve_str; + EC_KEY *ecdh; + + if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { + convert_to_string_ex(val); + curve_str = Z_STRVAL_PP(val); + curve_nid = OBJ_sn2nid(curve_str); + if (curve_nid == NID_undef) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid ECDH curve: %s", curve_str); + return FAILURE; } + } else { + curve_nid = NID_X9_62_prime256v1; } - #if OPENSSL_VERSION_NUMBER >= 0x10001001L - sslsock->ctx = SSL_CTX_new(method); - #else - sslsock->ctx = SSL_CTX_new((SSL_METHOD*)method); - #endif - if (sslsock->ctx == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL context"); - return -1; + ecdh = EC_KEY_new_by_curve_name(curve_nid); + if (ecdh == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed generating ECDH curve"); + + return FAILURE; } - #if OPENSSL_VERSION_NUMBER >= 0x0090605fL - ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + + return SUCCESS; + } + /* }}} */ #endif - SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options); - #if OPENSSL_VERSION_NUMBER >= 0x0090806fL - { - if (stream->context && SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "no_ticket", &val) && - zend_is_true(*val) - ) { - SSL_CTX_set_options(sslsock->ctx, SSL_OP_NO_TICKET); - } + static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */ + { + zval **val; + long ssl_ctx_options = SSL_CTX_get_options(ctx); + + #ifdef HAVE_ECDH + if (FAILURE == set_server_ecdh_curve(stream, ctx TSRMLS_CC)) { + return FAILURE; + } + #else + if (SUCCESS == php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "ECDH curve support not compiled into the OpenSSL lib against which PHP is linked"); + + return FAILURE; } #endif @@@ -591,241 -1164,347 +1164,347 @@@ stream->context, "ssl", "single_ecdh_use", &val) && zend_is_true(*val) ) { - SSL_CTX_set_options(sslsock->ctx, SSL_OP_SINGLE_ECDH_USE); + ssl_ctx_options |= SSL_OP_SINGLE_ECDH_USE; } - sslsock->ssl_handle = php_SSL_new_from_context(sslsock->ctx, stream TSRMLS_CC); - if (sslsock->ssl_handle == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL handle"); - SSL_CTX_free(sslsock->ctx); - sslsock->ctx = NULL; - return -1; - } + SSL_CTX_set_options(ctx, ssl_ctx_options); - if (!sslsock->is_client && stream->context && SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "honor_cipher_order", &val) && - zend_is_true(*val) - ) { - SSL_CTX_set_options(sslsock->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - } + return SUCCESS; + } + /* }}} */ - #ifdef SSL_MODE_RELEASE_BUFFERS - mode = SSL_get_mode(sslsock->ssl_handle); - SSL_set_mode(sslsock->ssl_handle, mode | SSL_MODE_RELEASE_BUFFERS); - #endif + #ifdef HAVE_SNI + static int server_sni_callback(SSL *ssl_handle, int *al, void *arg) /* {{{ */ + { + php_stream *stream; + php_openssl_netstream_data_t *sslsock; + unsigned i; + const char *server_name; + + server_name = SSL_get_servername(ssl_handle, TLSEXT_NAMETYPE_host_name); - if (!sslsock->is_client) { - init_handshake_limiting(stream, sslsock); + if (!server_name) { + return SSL_TLSEXT_ERR_NOACK; } - if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { - handle_ssl_error(stream, 0, 1 TSRMLS_CC); + stream = (php_stream*)SSL_get_ex_data(ssl_handle, php_openssl_get_ssl_stream_data_index()); + sslsock = (php_openssl_netstream_data_t*)stream->abstract; + + if (!(sslsock->sni_cert_count && sslsock->sni_certs)) { + return SSL_TLSEXT_ERR_NOACK; } - if (cparam->inputs.session) { - if (cparam->inputs.session->ops != &php_openssl_socket_ops) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream"); - } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied SSL session stream is not initialized"); - } else { - SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); + for (i=0; i < sslsock->sni_cert_count; i++) { + if (matches_wildcard_name(server_name, sslsock->sni_certs[i].name)) { + SSL_set_SSL_CTX(ssl_handle, sslsock->sni_certs[i].ctx); + return SSL_TLSEXT_ERR_OK; } } - return 0; + + return SSL_TLSEXT_ERR_NOACK; } + /* }}} */ - static zval *php_capture_ssl_session_meta(SSL *ssl_handle) + static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock TSRMLS_DC) { - zval *meta_arr; - char *proto_str; - php_int_t proto = SSL_version(ssl_handle); - const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle); + zval **val; + zval **current; + char *key; - uint key_len; - ulong key_index; ++ php_size_t key_len; ++ php_uint_t key_index; + int key_type; + HashPosition pos; + int i = 0; + char resolved_path_buff[MAXPATHLEN]; + SSL_CTX *ctx; + + /* If the stream ctx disables SNI we're finished here */ + if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val)) { + return SUCCESS; + } - switch (proto) { - #if OPENSSL_VERSION_NUMBER >= 0x10001001L - case TLS1_2_VERSION: proto_str = "TLSv1.2"; break; - case TLS1_1_VERSION: proto_str = "TLSv1.1"; break; - #endif - case TLS1_VERSION: proto_str = "TLSv1"; break; - case SSL3_VERSION: proto_str = "SSLv3"; break; - case SSL2_VERSION: proto_str = "SSLv2"; break; - default: proto_str = "UNKNOWN"; + /* If no SNI cert array is specified we're finished here */ + if (!GET_VER_OPT("SNI_server_certs")) { + return SUCCESS; } - MAKE_STD_ZVAL(meta_arr); - array_init(meta_arr); - add_assoc_string(meta_arr, "protocol", proto_str, 1); - add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1); - add_assoc_int(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); - add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1); + if (Z_TYPE_PP(val) != IS_ARRAY) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SNI_server_certs requires an array mapping host names to cert paths" + ); + return FAILURE; + } - return meta_arr; - } + sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_PP(val)); + if (sslsock->sni_cert_count == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SNI_server_certs host cert array must not be empty" + ); + return FAILURE; + } - static int php_set_server_rsa_key(php_stream *stream, - php_openssl_netstream_data_t *sslsock - TSRMLS_DC) - { - zval ** val; - int rsa_key_size; - RSA* rsa; - int retval = 1; + sslsock->sni_certs = (php_openssl_sni_cert_t*)safe_pemalloc(sslsock->sni_cert_count, + sizeof(php_openssl_sni_cert_t), 0, php_stream_is_persistent(stream) + ); - if (php_stream_context_get_option(stream->context, "ssl", "rsa_key_size", &val) == SUCCESS) { - rsa_key_size = (int) Z_IVAL_PP(val); - if ((rsa_key_size != 1) && (rsa_key_size & (rsa_key_size - 1))) { + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(val), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_PP(val), (void **)¤t, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_PP(val), &pos) + ) { + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(val), &key, &key_len, &key_index, 0, &pos); + if (key_type != HASH_KEY_IS_STRING) { php_error_docref(NULL TSRMLS_CC, E_WARNING, - "RSA key size requires a power of 2: %d", - rsa_key_size); + "SNI_server_certs array requires string host name keys" + ); + return FAILURE; + } - rsa_key_size = 2048; + if (VCWD_REALPATH(Z_STRVAL_PP(current), resolved_path_buff)) { + /* The hello method is not inherited by SSL structs when assigning a new context + * inside the SNI callback, so the just use SSLv23 */ + ctx = SSL_CTX_new(SSLv23_server_method()); + + if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "failed setting local cert chain file `%s'; " \ + "check that your cafile/capath settings include " \ + "details of your certificate and its issuer", + resolved_path_buff + ); + SSL_CTX_free(ctx); + return FAILURE; + } else if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "failed setting private key from file `%s'", + resolved_path_buff + ); + SSL_CTX_free(ctx); + return FAILURE; + } else { + sslsock->sni_certs[i].name = pestrdup(key, php_stream_is_persistent(stream)); + sslsock->sni_certs[i].ctx = ctx; + ++i; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "failed setting local cert chain file `%s'; file not found", + Z_STRVAL_PP(current) + ); + return FAILURE; } - } else { - rsa_key_size = 2048; } - rsa = RSA_generate_key(rsa_key_size, RSA_F4, NULL, NULL); + SSL_CTX_set_tlsext_servername_callback(sslsock->ctx, server_sni_callback); - if (!SSL_set_tmp_rsa(sslsock->ssl_handle, rsa)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Failed setting RSA key"); - retval = 0; + return SUCCESS; + } + + static void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ + { + zval **val; + char *sni_server_name; + + /* If SNI is explicitly disabled we're finished here */ + if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val)) { + return; } - RSA_free(rsa); + sni_server_name = sslsock->url_name; - return retval; - } + GET_VER_OPT_STRING("peer_name", sni_server_name); + if (GET_VER_OPT("SNI_server_name")) { + GET_VER_OPT_STRING("SNI_server_name", sni_server_name); + php_error(E_DEPRECATED, "SNI_server_name is deprecated in favor of peer_name"); + } - static int php_set_server_dh_param(php_openssl_netstream_data_t *sslsock, - char *dh_path - TSRMLS_DC) + if (sni_server_name) { + SSL_set_tlsext_host_name(sslsock->ssl_handle, sni_server_name); + } + } + /* }}} */ + #endif + + int php_openssl_setup_crypto(php_stream *stream, + php_openssl_netstream_data_t *sslsock, + php_stream_xport_crypto_param *cparam + TSRMLS_DC) /* {{{ */ { - DH *dh; - BIO* bio; + const SSL_METHOD *method; + long ssl_ctx_options; + long method_flags; + char *cipherlist = NULL; + zval **val; - bio = BIO_new_file(dh_path, "r"); + if (sslsock->ssl_handle) { + if (sslsock->s.is_blocked) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream"); + return FAILURE; + } else { + return SUCCESS; + } + } - if (bio == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Invalid dh_param file: %s", - dh_path); + ERR_clear_error(); - return 0; + /* We need to do slightly different things based on client/server method + * so lets remember which method was selected */ + sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT; + method_flags = ((cparam->inputs.method >> 1) << 1); + + /* Should we use a specific crypto method or is generic SSLv23 okay? */ + if ((method_flags & (method_flags-1)) == 0) { + ssl_ctx_options = SSL_OP_ALL; + method = php_select_crypto_method(method_flags, sslsock->is_client TSRMLS_CC); + if (method == NULL) { + return FAILURE; + } + } else { + method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method(); + ssl_ctx_options = php_get_crypto_method_ctx_flags(method_flags TSRMLS_CC); + if (ssl_ctx_options == -1) { + return FAILURE; + } + } + + #if OPENSSL_VERSION_NUMBER >= 0x10001001L + sslsock->ctx = SSL_CTX_new(method); + #else + /* Avoid const warning with old versions */ + sslsock->ctx = SSL_CTX_new((SSL_METHOD*)method); + #endif + + if (sslsock->ctx == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL context creation failure"); + return FAILURE; } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); + #if OPENSSL_VERSION_NUMBER >= 0x0090806fL + if (GET_VER_OPT("no_ticket") && zend_is_true(*val)) { + ssl_ctx_options |= SSL_OP_NO_TICKET; + } + #endif - if (dh == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Failed reading DH params from file: %s", - dh_path); + #if OPENSSL_VERSION_NUMBER >= 0x0090605fL + ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + #endif - return 0; + #if OPENSSL_VERSION_NUMBER >= 0x10000000L + if (!GET_VER_OPT("disable_compression") || zend_is_true(*val)) { + ssl_ctx_options |= SSL_OP_NO_COMPRESSION; } + #endif - if (SSL_set_tmp_dh(sslsock->ssl_handle, dh) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "DH param assignment failed"); - DH_free(dh); - return 0; + if (GET_VER_OPT("verify_peer") && !zend_is_true(*val)) { + disable_peer_verification(sslsock->ctx, stream TSRMLS_CC); + } else if (FAILURE == enable_peer_verification(sslsock->ctx, stream TSRMLS_CC)) { + return FAILURE; } - DH_free(dh); - - return 1; - } + /* callback for the passphrase (for localcert) */ + if (GET_VER_OPT("passphrase")) { + SSL_CTX_set_default_passwd_cb_userdata(sslsock->ctx, stream); + SSL_CTX_set_default_passwd_cb(sslsock->ctx, passwd_callback); + } - static int php_enable_server_crypto_opts(php_stream *stream, - php_openssl_netstream_data_t *sslsock - TSRMLS_DC) - { - zval **val; - #ifdef HAVE_ECDH - int curve_nid; - EC_KEY *ecdh; - #endif + GET_VER_OPT_STRING("ciphers", cipherlist); + if (!cipherlist) { + cipherlist = OPENSSL_DEFAULT_STREAM_CIPHERS; + } + if (SSL_CTX_set_cipher_list(sslsock->ctx, cipherlist) != 1) { + return FAILURE; + } - if (php_stream_context_get_option(stream->context, "ssl", "dh_param", &val) == SUCCESS) { - convert_to_string_ex(val); - if (!php_set_server_dh_param(sslsock, Z_STRVAL_PP(val) TSRMLS_CC)) { - return 0; - } + if (FAILURE == set_local_cert(sslsock->ctx, stream TSRMLS_CC)) { + return FAILURE; } - #ifdef HAVE_ECDH + SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options); - if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { - char *curve_str; - convert_to_string_ex(val); - curve_str = Z_STRVAL_PP(val); - curve_nid = OBJ_sn2nid(curve_str); - if (curve_nid == NID_undef) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Invalid ECDH curve: %s", - curve_str); + if (sslsock->is_client == 0 && + stream->context && + FAILURE == set_server_specific_opts(stream, sslsock->ctx TSRMLS_CC) + ) { + return FAILURE; + } - return 0; - } + sslsock->ssl_handle = SSL_new(sslsock->ctx); + if (sslsock->ssl_handle == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL handle creation failure"); + SSL_CTX_free(sslsock->ctx); + sslsock->ctx = NULL; + return FAILURE; } else { - curve_nid = NID_X9_62_prime256v1; + SSL_set_ex_data(sslsock->ssl_handle, php_openssl_get_ssl_stream_data_index(), stream); } - ecdh = EC_KEY_new_by_curve_name(curve_nid); - if (ecdh == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Failed generating ECDH curve"); - - return 0; + if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { + handle_ssl_error(stream, 0, 1 TSRMLS_CC); } - SSL_set_tmp_ecdh(sslsock->ssl_handle, ecdh); - EC_KEY_free(ecdh); - - #else + #ifdef HAVE_SNI + /* Enable server-side SNI */ + if (sslsock->is_client == 0 && enable_server_sni(stream, sslsock TSRMLS_CC) == FAILURE) { + return FAILURE; + } + #endif - if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "ECDH curve support not compiled into the OpenSSL lib against which PHP is linked"); + /* Enable server-side handshake renegotiation rate-limiting */ + if (sslsock->is_client == 0) { + init_server_reneg_limit(stream, sslsock); } + #ifdef SSL_MODE_RELEASE_BUFFERS + do { + long mode = SSL_get_mode(sslsock->ssl_handle); + SSL_set_mode(sslsock->ssl_handle, mode | SSL_MODE_RELEASE_BUFFERS); + } while (0); #endif - if (!php_set_server_rsa_key(stream, sslsock TSRMLS_CC)) { - return 0; + if (cparam->inputs.session) { + if (cparam->inputs.session->ops != &php_openssl_socket_ops) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream"); + } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied SSL session stream is not initialized"); + } else { + SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); + } } - return 1; + return SUCCESS; } + /* }}} */ - #if OPENSSL_VERSION_NUMBER >= 0x00908070L && !defined(OPENSSL_NO_TLSEXT) - static inline void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ + static zval *capture_session_meta(SSL *ssl_handle) /* {{{ */ { - zval **val; + zval *meta_arr; + char *proto_str; + long proto = SSL_version(ssl_handle); + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle); - if (stream->context && - (php_stream_context_get_option(stream->context, "ssl", "SNI_enabled", &val) == FAILURE - || zend_is_true(*val)) - ) { - if (php_stream_context_get_option(stream->context, "ssl", "SNI_server_name", &val) == SUCCESS) { - convert_to_string_ex(val); - SSL_set_tlsext_host_name(sslsock->ssl_handle, Z_STRVAL_PP(val)); - } else if (sslsock->url_name) { - SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); - } - } else if (!stream->context && sslsock->url_name) { - SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); + switch (proto) { + #if OPENSSL_VERSION_NUMBER >= 0x10001001L + case TLS1_2_VERSION: proto_str = "TLSv1.2"; break; + case TLS1_1_VERSION: proto_str = "TLSv1.1"; break; + #endif + case TLS1_VERSION: proto_str = "TLSv1"; break; + case SSL3_VERSION: proto_str = "SSLv3"; break; + case SSL2_VERSION: proto_str = "SSLv2"; break; + default: proto_str = "UNKNOWN"; } + + MAKE_STD_ZVAL(meta_arr); + array_init(meta_arr); + add_assoc_string(meta_arr, "protocol", proto_str, 1); + add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1); + add_assoc_long(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); + add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1); + + return meta_arr; } /* }}} */ - #endif - static int capture_peer_certs(php_stream *stream, - php_openssl_netstream_data_t *sslsock, - X509 *peer_cert - TSRMLS_DC) + static int capture_peer_certs(php_stream *stream, php_openssl_netstream_data_t *sslsock, X509 *peer_cert TSRMLS_DC) /* {{{ */ { zval **val, *zcert; int cert_captured = 0; diff --cc ext/spl/spl_directory.c index f289cd6,03315b7..28d3e5f --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@@ -2844,12 -2842,34 +2844,34 @@@ SPL_METHOD(SplFileObject, fwrite str_len = MAX(0, MIN(length, str_len)); } if (!str_len) { - RETURN_LONG(0); + RETURN_INT(0); } - RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len)); + RETURN_INT(php_stream_write(intern->u.file.stream, str, str_len)); } /* }}} */ + SPL_METHOD(SplFileObject, fread) + { + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + long length = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) { + return; + } + + if (length <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0"); + RETURN_FALSE; + } + + Z_STRVAL_P(return_value) = emalloc(length + 1); + Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length); + + /* needed because recv/read/gzread doesnt put a null at the end*/ + Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0; + Z_TYPE_P(return_value) = IS_STRING; + } + /* {{{ proto bool SplFileObject::fstat() Stat() on a filehandle */ FileFunction(fstat) diff --cc ext/zip/php_zip.c index dd6fd64,a9db166..37e67f6 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@@ -3052,81 -3049,82 +3052,82 @@@ static PHP_MINIT_FUNCTION(zip php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC); php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC); - REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE); - REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL); - REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS); - REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE); - - REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE); - REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR); - REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED); - REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED); - REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT); - REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3); - REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4); - REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64); - REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2); - REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA); - REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE); - REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77); - REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK); - REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD); + REGISTER_ZIP_CLASS_CONST_INT("CREATE", ZIP_CREATE); + REGISTER_ZIP_CLASS_CONST_INT("EXCL", ZIP_EXCL); + REGISTER_ZIP_CLASS_CONST_INT("CHECKCONS", ZIP_CHECKCONS); + REGISTER_ZIP_CLASS_CONST_INT("OVERWRITE", ZIP_OVERWRITE); + + REGISTER_ZIP_CLASS_CONST_INT("FL_NOCASE", ZIP_FL_NOCASE); + REGISTER_ZIP_CLASS_CONST_INT("FL_NODIR", ZIP_FL_NODIR); + REGISTER_ZIP_CLASS_CONST_INT("FL_COMPRESSED", ZIP_FL_COMPRESSED); + REGISTER_ZIP_CLASS_CONST_INT("FL_UNCHANGED", ZIP_FL_UNCHANGED); + REGISTER_ZIP_CLASS_CONST_INT("CM_DEFAULT", ZIP_CM_DEFAULT); + REGISTER_ZIP_CLASS_CONST_INT("CM_STORE", ZIP_CM_STORE); + REGISTER_ZIP_CLASS_CONST_INT("CM_SHRINK", ZIP_CM_SHRINK); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_1", ZIP_CM_REDUCE_1); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_2", ZIP_CM_REDUCE_2); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_3", ZIP_CM_REDUCE_3); + REGISTER_ZIP_CLASS_CONST_INT("CM_REDUCE_4", ZIP_CM_REDUCE_4); + REGISTER_ZIP_CLASS_CONST_INT("CM_IMPLODE", ZIP_CM_IMPLODE); + REGISTER_ZIP_CLASS_CONST_INT("CM_DEFLATE", ZIP_CM_DEFLATE); + REGISTER_ZIP_CLASS_CONST_INT("CM_DEFLATE64", ZIP_CM_DEFLATE64); + REGISTER_ZIP_CLASS_CONST_INT("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE); + REGISTER_ZIP_CLASS_CONST_INT("CM_BZIP2", ZIP_CM_BZIP2); + REGISTER_ZIP_CLASS_CONST_INT("CM_LZMA", ZIP_CM_LZMA); + REGISTER_ZIP_CLASS_CONST_INT("CM_TERSE", ZIP_CM_TERSE); + REGISTER_ZIP_CLASS_CONST_INT("CM_LZ77", ZIP_CM_LZ77); + REGISTER_ZIP_CLASS_CONST_INT("CM_WAVPACK", ZIP_CM_WAVPACK); + REGISTER_ZIP_CLASS_CONST_INT("CM_PPMD", ZIP_CM_PPMD); /* Error code */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */ - REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */ + REGISTER_ZIP_CLASS_CONST_INT("ER_OK", ZIP_ER_OK); /* N No error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */ + REGISTER_ZIP_CLASS_CONST_INT("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_READ", ZIP_ER_READ); /* S Read error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_WRITE", ZIP_ER_WRITE); /* S Write error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_CRC", ZIP_ER_CRC); /* N CRC error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_NOENT", ZIP_ER_NOENT); /* N No such file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */ + REGISTER_ZIP_CLASS_CONST_INT("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */ + REGISTER_ZIP_CLASS_CONST_INT("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */ + REGISTER_ZIP_CLASS_CONST_INT("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */ + REGISTER_ZIP_CLASS_CONST_INT("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */ + REGISTER_ZIP_CLASS_CONST_INT("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */ + REGISTER_ZIP_CLASS_CONST_INT("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */ + REGISTER_ZIP_CLASS_CONST_INT("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */ + REGISTER_ZIP_CLASS_CONST_INT("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */ + REGISTER_ZIP_CLASS_CONST_INT("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */ + REGISTER_ZIP_CLASS_CONST_INT("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */ #ifdef ZIP_OPSYS_DEFAULT - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DOS", ZIP_OPSYS_DOS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_AMIGA", ZIP_OPSYS_AMIGA); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OPENVMS", ZIP_OPSYS_OPENVMS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_UNIX", ZIP_OPSYS_UNIX); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VM_CMS", ZIP_OPSYS_VM_CMS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ATARI_ST", ZIP_OPSYS_ATARI_ST); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_2", ZIP_OPSYS_OS_2); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MACINTOSH", ZIP_OPSYS_MACINTOSH); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_SYSTEM", ZIP_OPSYS_Z_SYSTEM); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_CPM", ZIP_OPSYS_CPM); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_WINDOWS_NTFS", ZIP_OPSYS_WINDOWS_NTFS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MVS", ZIP_OPSYS_MVS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VSE", ZIP_OPSYS_VSE); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ACORN_RISC", ZIP_OPSYS_ACORN_RISC); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VFAT", ZIP_OPSYS_VFAT); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ALTERNATE_MVS", ZIP_OPSYS_ALTERNATE_MVS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_BEOS", ZIP_OPSYS_BEOS); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_TANDEM", ZIP_OPSYS_TANDEM); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_400", ZIP_OPSYS_OS_400); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_X", ZIP_OPSYS_OS_X); - - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_DOS", ZIP_OPSYS_DOS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_AMIGA", ZIP_OPSYS_AMIGA); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OPENVMS", ZIP_OPSYS_OPENVMS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_UNIX", ZIP_OPSYS_UNIX); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_VM_CMS", ZIP_OPSYS_VM_CMS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_ATARI_ST", ZIP_OPSYS_ATARI_ST); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OS_2", ZIP_OPSYS_OS_2); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_MACINTOSH", ZIP_OPSYS_MACINTOSH); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_Z_SYSTEM", ZIP_OPSYS_Z_SYSTEM); ++ REGISTER_ZIP_CLASS_CONST_INT("OPSYS_Z_CPM", ZIP_OPSYS_CPM); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_WINDOWS_NTFS", ZIP_OPSYS_WINDOWS_NTFS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_MVS", ZIP_OPSYS_MVS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_VSE", ZIP_OPSYS_VSE); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_ACORN_RISC", ZIP_OPSYS_ACORN_RISC); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_VFAT", ZIP_OPSYS_VFAT); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_ALTERNATE_MVS", ZIP_OPSYS_ALTERNATE_MVS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_BEOS", ZIP_OPSYS_BEOS); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_TANDEM", ZIP_OPSYS_TANDEM); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OS_400", ZIP_OPSYS_OS_400); + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_OS_X", ZIP_OPSYS_OS_X); + + REGISTER_ZIP_CLASS_CONST_INT("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT); #endif /* ifdef ZIP_OPSYS_DEFAULT */ php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC);