diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index 79b22569..2e10b05b 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -1,3 +1,5 @@
+
+name: Test on Ubuntu
on: [push, pull_request]
jobs:
@@ -7,14 +9,14 @@ jobs:
strategy:
fail-fast: false
matrix:
- php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
+ php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
experimental: [false]
include:
- - php: '8.2'
+ - php: '8.4'
experimental: true
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: true
- name: Install PHP ${{ matrix.php }}
@@ -25,7 +27,9 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
- sudo apt-get install libmemcached-dev memcached libsasl2-dev sasl2-bin zlib1g-dev
+ sudo apt-get install cmake memcached libsasl2-dev sasl2-bin zlib1g-dev
+ - name: Install libmemcached-dev
+ run: sudo apt-get install libmemcached-dev
- name: Start memcached daemons
run: |
export SASL_CONF_PATH="/tmp/sasl2"
@@ -66,7 +70,7 @@ jobs:
define ("MEMC_SASL_SERVER_HOST", "127.0.0.1");
define ("MEMC_SASL_SERVER_PORT", 11212);
-
+
define ('MEMC_SASL_USER', 'memcached');
define ('MEMC_SASL_PASS', 'test');
EOF
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
new file mode 100644
index 00000000..15dba3f2
--- /dev/null
+++ b/.github/workflows/build-windows.yml
@@ -0,0 +1,44 @@
+name: Build on Windows
+on: [push, pull_request]
+jobs:
+ windows:
+ defaults:
+ run:
+ shell: cmd
+ strategy:
+ matrix:
+ version: ['8.3', '8.4']
+ arch: [x64, x86]
+ ts: [nts, zts]
+ exclude:
+ - { version: '8.4', arch: x64, ts: zts }
+ - { version: '8.4', arch: x86, ts: nts }
+ - { version: '8.4', arch: x86, ts: zts }
+ runs-on: windows-latest
+ steps:
+ - name: Checkout memcached
+ uses: actions/checkout@v4
+ - name: Setup PHP
+ id: setup-php
+ uses: php/setup-php-sdk@v0.10
+ with:
+ version: ${{matrix.version}}
+ arch: ${{matrix.arch}}
+ ts: ${{matrix.ts}}
+ deps: zlib
+ cache: true
+ - name: Fetch libmemcached
+ run: |
+ set MEMCACHED_FILENAME=libmemcached-1.1.4-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip
+ curl -OLs https://downloads.php.net/~windows/pecl/deps/%MEMCACHED_FILENAME% && 7z x %MEMCACHED_FILENAME% -o..\deps
+ - name: Enable Developer Command Prompt
+ uses: ilammy/msvc-dev-cmd@v1
+ with:
+ arch: ${{matrix.arch}}
+ toolset: ${{steps.setup-php.outputs.toolset}}
+ - name: phpize
+ run: phpize
+ - name: configure
+ run: configure --enable-memcached --enable-memcached-session --enable-memcached-json --with-prefix=${{steps.setup-php.outputs.prefix}}
+ - name: make
+ run: nmake
diff --git a/README.markdown b/README.markdown
index 8819caf9..38dbd5bc 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,6 +1,6 @@
Build Status
------------
-[](https://travis-ci.org/php-memcached-dev/php-memcached)
+
Description
-----------
@@ -23,7 +23,7 @@ Dependencies
------------
php-memcached 3.x:
-* Supports PHP 7.0 - 8.1.
+* Supports PHP 7.0 - 8.3 or higher.
* Requires libmemcached 1.x or higher.
* Optionally supports igbinary 2.0 or higher.
* Optionally supports msgpack 2.0 or higher.
diff --git a/composer.json b/composer.json
new file mode 100644
index 00000000..3356c89d
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,68 @@
+{
+ "name": "php-memcached/php-memcached",
+ "type": "php-ext",
+ "license": "PHP-3.01",
+ "description": "memcached extension based on libmemcached library ",
+ "require": {
+ "php": ">= 7.0.0"
+ },
+ "suggest": {
+ "ext-igbinary": "igbinary is a faster and more compact binary serializer for PHP data structures.",
+ "ext-msgpack": "msgpack is a faster and more compact data structure representation that is interoperable with msgpack implementations for other languages."
+ },
+ "php-ext": {
+ "extension-name": "memcached",
+ "configure-options": [
+ {
+ "name": "enable-memcached",
+ "description": "Enable memcached support"
+ },
+ {
+ "name": "with-libmemcached-dir",
+ "description": "Set the path to libmemcached install prefix.",
+ "needs-value": true
+ },
+ {
+ "name": "enable-memcached-session",
+ "description": "Enable memcached session handler support"
+ },
+ {
+ "name": "enable-memcached-igbinary",
+ "description": "Enable memcached igbinary serializer support"
+ },
+ {
+ "name": "enable-memcached-json",
+ "description": "Enable memcached json serializer support"
+ },
+ {
+ "name": "enable-memcached-msgpack",
+ "description": "Enable memcached msgpack serializer support"
+ },
+ {
+ "name": "enable-memcached-sasl",
+ "description": "Enable memcached sasl support"
+ },
+ {
+ "name": "enable-memcached-protocol",
+ "description": "Enable memcached protocol support"
+ },
+ {
+ "name": "with-system-fastlz",
+ "description": "Use system FastLZ library"
+ },
+ {
+ "name": "with-zstd",
+ "description": "Use system zstd library"
+ },
+ {
+ "name": "with-zlib-dir",
+ "description": "Set the path to ZLIB install prefix.",
+ "needs-value": true
+ },
+ {
+ "name": "enable-debug",
+ "description": "Compile with debugging symbols"
+ }
+ ]
+ }
+}
diff --git a/config.m4 b/config.m4
index c7a15f11..0e4ef8cf 100644
--- a/config.m4
+++ b/config.m4
@@ -27,6 +27,9 @@ PHP_ARG_ENABLE(memcached-protocol, whether to enable memcached protocol support,
PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library,
[ --with-system-fastlz Use system FastLZ library], no, no)
+PHP_ARG_WITH(zstd, whether to use system zstd library,
+[ --with-zstd Use system zstd library], no, no)
+
if test -z "$PHP_ZLIB_DIR"; then
PHP_ARG_WITH(zlib-dir, for ZLIB,
[ --with-zlib-dir=DIR Set the path to ZLIB install prefix.], no)
@@ -345,6 +348,13 @@ if test "$PHP_MEMCACHED" != "no"; then
PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} fastlz/fastlz.c"
fi
+ if test "$PHP_ZSTD" != "no"; then
+ AC_CHECK_HEADERS([zstd.h], [ac_cv_have_zstd="yes"], [ac_cv_have_zstd="no"])
+ PHP_CHECK_LIBRARY(zstd, ZSTD_compress,
+ [PHP_ADD_LIBRARY(zstd, 1, MEMCACHED_SHARED_LIBADD)],
+ [AC_MSG_ERROR(zstd library not found)])
+ fi
+
if test "$PHP_MEMCACHED_SESSION" != "no"; then
PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c"
fi
diff --git a/config.w32 b/config.w32
index 51aa3bd0..76d4ee3c 100644
--- a/config.w32
+++ b/config.w32
@@ -5,6 +5,7 @@ ARG_ENABLE('memcached', 'libmemcached extension', 'no');
ARG_ENABLE('memcached-session', 'whether to enable memcached session handler support', 'no');
ARG_ENABLE('memcached-igbinary', 'whether to enable memcached igbinary serializer support', 'no');
ARG_ENABLE('memcached-json', 'whether to enable memcached json serializer support', 'no');
+ARG_ENABLE('memcached-msgpack', 'whether to enable memcached msgpack serializer support', 'no');
if (PHP_MEMCACHED == "yes") {
@@ -35,7 +36,13 @@ if (PHP_MEMCACHED == "yes") {
ERROR("memcached: header 'igbinary.h' not found");
}
}
-
+ if (PHP_MEMCACHED_MSGPACK != "no"){
+ AC_DEFINE("HAVE_MEMCACHED_MSGPACK",1);
+ ADD_EXTENSION_DEP("memcached", "msgpack", true);
+ if (!CHECK_HEADER_ADD_INCLUDE("php_msgpack.h", "CFLAGS_MEMCACHED")) {
+ ERROR("memcached: header 'php_msgpack.h' not found");
+ }
+ }
EXTENSION("memcached", "php_memcached.c php_libmemcached_compat.c g_fmt.c"+memcached_extra_src, null, " /DHAVE_SSIZE_T");
ADD_SOURCES(configure_module_dirname+"\\fastlz", "fastlz.c", "memcached");
AC_DEFINE("HAVE_MEMCACHED", 1, "memcached support");
diff --git a/memcached.ini b/memcached.ini
index c54e1fd4..5decf399 100644
--- a/memcached.ini
+++ b/memcached.ini
@@ -133,6 +133,12 @@
; the default is 0
;memcached.store_retry_count = 0
+; The maximum payload size in bytes that can be written.
+; Writing a payload larger than the limit will result in RES_E2BIG error.
+; Specifying 0 means no limit is enforced, though the server may still reject with RES_E2BIG.
+; Default is 0.
+;memcached.item_size_limit = 1000000
+
; Sets the default for consistent hashing for new connections.
; (To configure consistent hashing for session connections,
; use memcached.sess_consistent_hash instead)
diff --git a/package.xml b/package.xml
index 761c9584..5565863e 100644
--- a/package.xml
+++ b/package.xml
@@ -33,22 +33,24 @@ http://pear.php.net/dtd/package-2.0.xsd">
remi@php.net
yes
- 2022-03-24
+
+ Michael Wallner
+ mike
+ mike@php.net
+ yes
+
+ 2024-10-17
- 3.2.0
- 3.2.0
+ 3.3.1dev
+ 3.3.0
- stable
+ beta
stable
PHP
-- PHP 8.0 and 8.1 support
-- store_retry_count is no more set explicitly (#452)
-- fix MemcachedServer (libmemcached-awesome is recommended)
-- code cleanup
-- fix windows build
+-
@@ -219,6 +221,50 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+ 2024-10-17
+
+ 3.3.0
+ 3.3.0
+
+
+ stable
+ stable
+
+ PHP
+
+- Add #515 option to locally enforce payload size limit
+- Add #539 zstd support
+- Add #540 compression_level option
+- Mark password as a sensitive param for PHP 8.2
+- Upgrade Windows libmemcached to v1.1.4
+- Fix Windows PHP 8 compatibility
+- Fix #518 Windows msgpack support
+- Fix #522 signed integer overflow
+- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token
+- Fix #546 don't check key automatically, unless client-side verify_key is enabled
+- Fix #555 incompatible pointer types (32-bit)
+
+
+
+ 2022-03-24
+
+ 3.2.0
+ 3.2.0
+
+
+ stable
+ stable
+
+ PHP
+
+- PHP 8.0 and 8.1 support
+- store_retry_count is no more set explicitly (#452)
+- fix MemcachedServer (libmemcached-awesome is recommended)
+- code cleanup
+- fix windows build
+
+
2019-12-03
diff --git a/php_memcached.c b/php_memcached.c
index 73deaf64..c8abb844 100644
--- a/php_memcached.c
+++ b/php_memcached.c
@@ -37,6 +37,10 @@
#endif
#include
+#ifdef HAVE_ZSTD_H
+#include
+#endif
+
#ifdef HAVE_JSON_API
# include "ext/json/php_json.h"
#endif
@@ -77,6 +81,8 @@ static int php_memc_list_entry(void) {
#define MEMC_OPT_COMPRESSION_TYPE -1004
#define MEMC_OPT_STORE_RETRY_COUNT -1005
#define MEMC_OPT_USER_FLAGS -1006
+#define MEMC_OPT_COMPRESSION_LEVEL -1007
+#define MEMC_OPT_ITEM_SIZE_LIMIT -1008
/****************************************
Custom result codes
@@ -86,7 +92,7 @@ static int php_memc_list_entry(void) {
/****************************************
Payload value flags
****************************************/
-#define MEMC_CREATE_MASK(start, n_bits) (((1 << n_bits) - 1) << start)
+#define MEMC_CREATE_MASK(start, n_bits) (((1U << n_bits) - 1) << start)
#define MEMC_MASK_TYPE MEMC_CREATE_MASK(0, 4)
#define MEMC_MASK_INTERNAL MEMC_CREATE_MASK(4, 12)
@@ -107,6 +113,7 @@ static int php_memc_list_entry(void) {
#define MEMC_VAL_COMPRESSED (1<<0)
#define MEMC_VAL_COMPRESSION_ZLIB (1<<1)
#define MEMC_VAL_COMPRESSION_FASTLZ (1<<2)
+#define MEMC_VAL_COMPRESSION_ZSTD (1<<3)
#define MEMC_VAL_GET_FLAGS(internal_flags) (((internal_flags) & MEMC_MASK_INTERNAL) >> 4)
#define MEMC_VAL_SET_FLAG(internal_flags, internal_flag) ((internal_flags) |= (((internal_flag) << 4) & MEMC_MASK_INTERNAL))
@@ -152,9 +159,11 @@ typedef struct {
zend_long serializer;
zend_long compression_type;
+ zend_long compression_level;
zend_long store_retry_count;
zend_long set_udf_flags;
+ zend_long item_size_limit;
#ifdef HAVE_MEMCACHED_SASL
zend_bool has_sasl_data;
@@ -222,24 +231,43 @@ zend_bool s_memc_valid_key_binary(zend_string *key)
}
static
-zend_bool s_memc_valid_key_ascii(zend_string *key)
+uint32_t s_memc_object_key_max_length(php_memc_object_t *intern) {
+ memcached_return retval;
+ char *result;
+
+ result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval);
+ if (retval == MEMCACHED_SUCCESS && result) {
+ return MEMC_OBJECT_KEY_MAX_LENGTH - strlen(result);
+ } else {
+ return MEMC_OBJECT_KEY_MAX_LENGTH;
+ }
+}
+
+zend_bool s_memc_valid_key_ascii(zend_string *key, uint64_t verify_key)
{
const char *str = ZSTR_VAL(key);
size_t i, len = ZSTR_LEN(key);
- for (i = 0; i < len; i++) {
- if (!isgraph(str[i]) || isspace(str[i]))
- return 0;
+ if (verify_key) {
+ for (i = 0; i < len; i++) {
+ if (!isgraph(str[i]) || isspace(str[i]))
+ return 0;
+ }
+ } else { /* if key verification is disabled, only check for spaces to avoid injection issues */
+ for (i = 0; i < len; i++) {
+ if (isspace(str[i]))
+ return 0;
+ }
}
return 1;
}
#define MEMC_CHECK_KEY(intern, key) \
if (UNEXPECTED(ZSTR_LEN(key) == 0 || \
- ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \
+ ZSTR_LEN(key) > s_memc_object_key_max_length(intern) || \
(memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \
? !s_memc_valid_key_binary(key) \
- : !s_memc_valid_key_ascii(key) \
+ : !s_memc_valid_key_ascii(key, memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY)) \
))) { \
intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \
RETURN_FALSE; \
@@ -278,6 +306,10 @@ static PHP_INI_MH(OnUpdateCompressionType)
MEMC_G(compression_type) = COMPRESSION_TYPE_FASTLZ;
} else if (!strcmp(ZSTR_VAL(new_value), "zlib")) {
MEMC_G(compression_type) = COMPRESSION_TYPE_ZLIB;
+#ifdef HAVE_ZSTD_H
+ } else if (!strcmp(ZSTR_VAL(new_value), "zstd")) {
+ MEMC_G(compression_type) = COMPRESSION_TYPE_ZSTD;
+#endif
} else {
return FAILURE;
}
@@ -329,7 +361,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString)
php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1);
return FAILURE;
}
- if (!s_memc_valid_key_ascii(new_value)) {
+ if (!s_memc_valid_key_ascii(new_value, 1)) {
php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters");
return FAILURE;
}
@@ -408,9 +440,11 @@ PHP_INI_BEGIN()
MEMC_INI_ENTRY("compression_type", "fastlz", OnUpdateCompressionType, compression_name)
MEMC_INI_ENTRY("compression_factor", "1.3", OnUpdateReal, compression_factor)
+ MEMC_INI_ENTRY("compression_level", "3", OnUpdateLong, compression_level)
MEMC_INI_ENTRY("compression_threshold", "2000", OnUpdateLong, compression_threshold)
MEMC_INI_ENTRY("serializer", SERIALIZER_DEFAULT_NAME, OnUpdateSerializer, serializer_name)
MEMC_INI_ENTRY("store_retry_count", "0", OnUpdateLong, store_retry_count)
+ MEMC_INI_ENTRY("item_size_limit", "0", OnUpdateLongGEZero, item_size_limit)
MEMC_INI_BOOL ("default_consistent_hash", "0", OnUpdateBool, default_behavior.consistent_hash_enabled)
MEMC_INI_BOOL ("default_binary_protocol", "0", OnUpdateBool, default_behavior.binary_protocol_enabled)
@@ -869,7 +903,7 @@ zend_bool s_invoke_cache_callback(zval *zobject, zend_fcall_info *fci, zend_fcal
****************************************/
static
-zend_bool s_compress_value (php_memc_compression_type compression_type, zend_string **payload_in, uint32_t *flags)
+zend_bool s_compress_value (php_memc_compression_type compression_type, zend_long compression_level, zend_string **payload_in, uint32_t *flags)
{
/* status */
zend_bool compress_status = 0;
@@ -897,12 +931,39 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_str
}
break;
+#ifdef HAVE_ZSTD_H
+ case COMPRESSION_TYPE_ZSTD:
+ {
+ compressed_size = ZSTD_compress((void *)buffer, buffer_size, ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level);
+
+ if (compression_level < -22) {
+ compression_level = -22;
+ } else if (compression_level > 22) {
+ compression_level = 22;
+ }
+
+ if (!ZSTD_isError(compressed_size)) {
+ compress_status = 1;
+ compression_type_flag = MEMC_VAL_COMPRESSION_ZSTD;
+ }
+ }
+ break;
+#endif
+
case COMPRESSION_TYPE_ZLIB:
{
- compressed_size = buffer_size;
- int status = compress((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload));
+ unsigned long cs = compressed_size = buffer_size;
+
+ if (compression_level < 0) {
+ compression_level = 0;
+ } else if (compression_level > 9) {
+ compression_level = 9;
+ }
+
+ int status = compress2((Bytef *) buffer, &cs, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level);
if (status == Z_OK) {
+ compressed_size = cs;
compress_status = 1;
compression_type_flag = MEMC_VAL_COMPRESSION_ZLIB;
}
@@ -1092,7 +1153,7 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t
*
* No need to check the return value because the payload is always valid.
*/
- (void)s_compress_value (memc_user_data->compression_type, &payload, flags);
+ (void)s_compress_value (memc_user_data->compression_type, memc_user_data->compression_level, &payload, flags);
}
if (memc_user_data->set_udf_flags >= 0) {
@@ -1102,6 +1163,21 @@ zend_string *s_zval_to_payload(php_memc_object_t *intern, zval *value, uint32_t
return payload;
}
+static
+zend_bool s_is_payload_too_big(php_memc_object_t *intern, zend_string *payload)
+{
+ php_memc_user_data_t *memc_user_data = memcached_get_user_data(intern->memc);
+
+ /* An item size limit of 0 implies no limit enforced */
+ if (memc_user_data->item_size_limit == 0) {
+ return 0;
+ }
+ if (ZSTR_LEN(payload) > memc_user_data->item_size_limit) {
+ return 1;
+ }
+ return 0;
+}
+
static
zend_bool s_should_retry_write (php_memc_object_t *intern, memcached_return status)
{
@@ -1128,6 +1204,12 @@ zend_bool s_memc_write_zval (php_memc_object_t *intern, php_memc_write_op op, ze
s_memc_set_status(intern, MEMC_RES_PAYLOAD_FAILURE, 0);
return 0;
}
+
+ if (s_is_payload_too_big(intern, payload)) {
+ s_memc_set_status(intern, MEMCACHED_E2BIG, 0);
+ zend_string_release(payload);
+ return 0;
+ }
}
#define memc_write_using_fn(fn_name) payload ? fn_name(intern->memc, ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags) : MEMC_RES_PAYLOAD_FAILURE;
@@ -1276,10 +1358,12 @@ static PHP_METHOD(Memcached, __construct)
memc_user_data = pecalloc (1, sizeof(*memc_user_data), is_persistent);
memc_user_data->serializer = MEMC_G(serializer_type);
memc_user_data->compression_type = MEMC_G(compression_type);
+ memc_user_data->compression_level = MEMC_G(compression_level);
memc_user_data->compression_enabled = 1;
memc_user_data->encoding_enabled = 0;
memc_user_data->store_retry_count = MEMC_G(store_retry_count);
memc_user_data->set_udf_flags = -1;
+ memc_user_data->item_size_limit = MEMC_G(item_size_limit);
memc_user_data->is_persistent = is_persistent;
memcached_set_user_data(intern->memc, memc_user_data);
@@ -2120,6 +2204,12 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
RETURN_FALSE;
}
+ if (s_is_payload_too_big(intern, payload)) {
+ intern->rescode = MEMCACHED_E2BIG;
+ zend_string_release(payload);
+ RETURN_FALSE;
+ }
+
if (by_key) {
status = memcached_cas_by_key(intern->memc, ZSTR_VAL(server_key), ZSTR_LEN(server_key), ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(payload), ZSTR_LEN(payload), expiration, flags, cas);
} else {
@@ -2939,9 +3029,15 @@ static PHP_METHOD(Memcached, getOption)
case MEMC_OPT_COMPRESSION_TYPE:
RETURN_LONG(memc_user_data->compression_type);
+ case MEMC_OPT_COMPRESSION_LEVEL:
+ RETURN_LONG(memc_user_data->compression_level);
+
case MEMC_OPT_COMPRESSION:
RETURN_BOOL(memc_user_data->compression_enabled);
+ case MEMC_OPT_ITEM_SIZE_LIMIT:
+ RETURN_LONG(memc_user_data->item_size_limit);
+
case MEMC_OPT_PREFIX_KEY:
{
memcached_return retval;
@@ -3001,6 +3097,9 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value)
case MEMC_OPT_COMPRESSION_TYPE:
lval = zval_get_long(value);
if (lval == COMPRESSION_TYPE_FASTLZ ||
+#ifdef HAVE_ZSTD_H
+ lval == COMPRESSION_TYPE_ZSTD ||
+#endif
lval == COMPRESSION_TYPE_ZLIB) {
memc_user_data->compression_type = lval;
} else {
@@ -3010,6 +3109,20 @@ int php_memc_set_option(php_memc_object_t *intern, long option, zval *value)
}
break;
+ case MEMC_OPT_COMPRESSION_LEVEL:
+ lval = zval_get_long(value);
+ memc_user_data->compression_level = lval;
+ break;
+
+ case MEMC_OPT_ITEM_SIZE_LIMIT:
+ lval = zval_get_long(value);
+ if (lval < 0) {
+ php_error_docref(NULL, E_WARNING, "ITEM_SIZE_LIMIT must be >= 0");
+ return 0;
+ }
+ memc_user_data->item_size_limit = lval;
+ break;
+
case MEMC_OPT_PREFIX_KEY:
{
zend_string *str;
@@ -3608,16 +3721,24 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32
uint32_t stored_length;
unsigned long length;
zend_bool decompress_status = 0;
- zend_bool is_fastlz = 0, is_zlib = 0;
+ zend_bool is_fastlz = 0, is_zlib = 0, is_zstd = 0;
if (payload_len < sizeof (uint32_t)) {
return NULL;
}
is_fastlz = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_FASTLZ);
+ is_zstd = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZSTD);
is_zlib = MEMC_VAL_HAS_FLAG(flags, MEMC_VAL_COMPRESSION_ZLIB);
- if (!is_fastlz && !is_zlib) {
+#ifndef HAVE_ZSTD_H
+ if (is_zstd) {
+ php_error_docref(NULL, E_WARNING, "could not decompress value: value was compressed with zstd but zstd support has not been compiled in");
+ return NULL;
+ }
+#endif
+
+ if (!is_fastlz && !is_zlib && !is_zstd) {
php_error_docref(NULL, E_WARNING, "could not decompress value: unrecognised compression type");
return NULL;
}
@@ -3629,11 +3750,31 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32
buffer = zend_string_alloc (stored_length, 0);
+#ifdef HAVE_ZSTD_H
+ if (is_zstd) {
+ length = ZSTD_getFrameContentSize(payload, payload_len);
+ if (length == ZSTD_CONTENTSIZE_ERROR) {
+ php_error_docref(NULL, E_WARNING, "value was not compressed by zstd");
+ zend_string_release (buffer);
+ return NULL;
+ } else if (length == ZSTD_CONTENTSIZE_UNKNOWN) {
+ php_error_docref(NULL, E_WARNING, "zstd streaming decompression not supported");
+ zend_string_release (buffer);
+ return NULL;
+ }
+ decompress_status = !ZSTD_isError(ZSTD_decompress(&buffer->val, buffer->len, payload, payload_len));
+
+ }
+ else
+#endif
if (is_fastlz) {
decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0);
}
else if (is_zlib) {
- decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK);
+ unsigned long ds = buffer->len;
+
+ decompress_status = (uncompress((Bytef *) buffer->val, &ds, (Bytef *)payload, payload_len) == Z_OK);
+ buffer->len = ds;
}
ZSTR_VAL(buffer)[stored_length] = '\0';
@@ -3898,6 +4039,7 @@ PHP_METHOD(MemcachedServer, on)
#if PHP_VERSION_ID < 80000
#include "php_memcached_legacy_arginfo.h"
#else
+#include "zend_attributes.h"
#include "php_memcached_arginfo.h"
#endif
@@ -3954,7 +4096,9 @@ PHP_GINIT_FUNCTION(php_memcached)
php_memcached_globals->memc.compression_threshold = 2000;
php_memcached_globals->memc.compression_type = COMPRESSION_TYPE_FASTLZ;
php_memcached_globals->memc.compression_factor = 1.30;
+ php_memcached_globals->memc.compression_level = 6;
php_memcached_globals->memc.store_retry_count = 2;
+ php_memcached_globals->memc.item_size_limit = 0;
php_memcached_globals->memc.sasl_initialised = 0;
php_memcached_globals->no_effect = 0;
@@ -3999,11 +4143,13 @@ static void php_memc_register_constants(INIT_FUNC_ARGS)
REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION, MEMC_OPT_COMPRESSION);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_TYPE, MEMC_OPT_COMPRESSION_TYPE);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_COMPRESSION_LEVEL, MEMC_OPT_COMPRESSION_LEVEL);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_PREFIX_KEY, MEMC_OPT_PREFIX_KEY);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_SERIALIZER, MEMC_OPT_SERIALIZER);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_USER_FLAGS, MEMC_OPT_USER_FLAGS);
REGISTER_MEMC_CLASS_CONST_LONG(OPT_STORE_RETRY_COUNT, MEMC_OPT_STORE_RETRY_COUNT);
+ REGISTER_MEMC_CLASS_CONST_LONG(OPT_ITEM_SIZE_LIMIT, MEMC_OPT_ITEM_SIZE_LIMIT);
/*
* Indicate whether igbinary serializer is available
@@ -4014,6 +4160,15 @@ static void php_memc_register_constants(INIT_FUNC_ARGS)
REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_IGBINARY, 0);
#endif
+ /*
+ * Indicate whether zstd compression is available
+ */
+#ifdef HAVE_ZSTD_H
+ REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 1);
+#else
+ REGISTER_MEMC_CLASS_CONST_BOOL(HAVE_ZSTD, 0);
+#endif
+
/*
* Indicate whether json serializer is available
*/
@@ -4185,6 +4340,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS)
*/
REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_FASTLZ, COMPRESSION_TYPE_FASTLZ);
REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZLIB, COMPRESSION_TYPE_ZLIB);
+ REGISTER_MEMC_CLASS_CONST_LONG(COMPRESSION_ZSTD, COMPRESSION_TYPE_ZSTD);
/*
* Flags.
@@ -4254,8 +4410,7 @@ PHP_MINIT_FUNCTION(memcached)
le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number);
- INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods);
- memcached_ce = zend_register_internal_class(&ce);
+ memcached_ce = register_class_Memcached();
memcached_ce->create_object = php_memc_object_new;
#ifdef HAVE_MEMCACHED_PROTOCOL
@@ -4264,8 +4419,7 @@ PHP_MINIT_FUNCTION(memcached)
memcached_server_object_handlers.clone_obj = NULL;
memcached_server_object_handlers.free_obj = php_memc_server_free_storage;
- INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods);
- memcached_server_ce = zend_register_internal_class(&ce);
+ memcached_server_ce = register_class_MemcachedServer();
memcached_server_ce->create_object = php_memc_server_new;
#endif
@@ -4352,6 +4506,12 @@ PHP_MINFO_FUNCTION(memcached)
php_info_print_table_row(2, "msgpack support", "no");
#endif
+#ifdef HAVE_ZSTD_H
+ php_info_print_table_row(2, "zstd support", "yes");
+#else
+ php_info_print_table_row(2, "zstd support", "no");
+#endif
+
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
diff --git a/php_memcached.h b/php_memcached.h
index dfb3444d..dfd19185 100644
--- a/php_memcached.h
+++ b/php_memcached.h
@@ -30,7 +30,7 @@
# include "config.h"
#endif
-#define PHP_MEMCACHED_VERSION "3.2.0"
+#define PHP_MEMCACHED_VERSION "3.3.1dev"
#if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS)
#define PHP_MEMCACHED_API __declspec(dllexport)
diff --git a/php_memcached.stub.php b/php_memcached.stub.php
index 819186f4..7e85ef32 100644
--- a/php_memcached.stub.php
+++ b/php_memcached.stub.php
@@ -3,9 +3,9 @@
/**
* @generate-function-entries
* @generate-legacy-arginfo
+ * @generate-class-entries
*/
-
class Memcached {
public function __construct(?string $persistent_id=null, ?callable $callback=null, ?string $connection_str=null) {}
@@ -15,12 +15,12 @@ public function getResultMessage(): string {}
public function get(string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {}
public function getByKey(string $server_key, string $key, ?callable $cache_cb=null, int $get_flags=0): mixed {}
- public function getMulti(array $keys, int $get_flags=0): false|array {}
- public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): false|array {}
+ public function getMulti(array $keys, int $get_flags=0): array|false {}
+ public function getMultiByKey(string $server_key, array $keys, int $get_flags=0): array|false {}
public function getDelayed(array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {}
public function getDelayedByKey(string $server_key, array $keys, bool $with_cas=false, ?callable $value_cb=null): bool {}
- public function fetch(): false|array {}
- public function fetchAll(): false|array {}
+ public function fetch(): array|false {}
+ public function fetchAll(): array|false {}
public function set(string $key, mixed $value, int $expiration=0): bool {}
public function setByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {}
@@ -31,8 +31,8 @@ public function touchByKey(string $server_key, string $key, int $expiration=0):
public function setMulti(array $items, int $expiration=0): bool {}
public function setMultiByKey(string $server_key, array $items, int $expiration=0): bool {}
- public function cas(string $cas_token, string $key, mixed $value, int $expiration=0): bool {}
- public function casByKey(string $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {}
+ public function cas(string|int|float $cas_token, string $key, mixed $value, int $expiration=0): bool {}
+ public function casByKey(string|int|float $cas_token, string $server_key, string $key, mixed $value, int $expiration=0): bool {}
public function add(string $key, mixed $value, int $expiration=0): bool {}
public function addByKey(string $server_key, string $key, mixed $value, int $expiration=0): bool {}
public function append(string $key, string $value): ?bool {}
@@ -46,15 +46,15 @@ public function deleteMulti(array $keys, int $time=0): array {}
public function deleteByKey(string $server_key, string $key, int $time=0): bool {}
public function deleteMultiByKey(string $server_key, array $keys, int $time=0): array {}
- public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {}
- public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {}
- public function incrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {}
- public function decrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): false|int {}
+ public function increment(string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {}
+ public function decrement(string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {}
+ public function incrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {}
+ public function decrementByKey(string $server_key, string $key, int $offset=1, int $initial_value=0, int $expiry=0): int|false {}
public function addServer(string $host, int $port, int $weight=0): bool {}
public function addServers(array $servers): bool {}
public function getServerList(): array {}
- public function getServerByKey(string $server_key): false|array {}
+ public function getServerByKey(string $server_key): array|false {}
public function resetServerList(): bool {}
public function quit(): bool {}
public function flushBuffers(): bool {}
@@ -62,11 +62,11 @@ public function flushBuffers(): bool {}
public function getLastErrorMessage(): string {}
public function getLastErrorCode(): int {}
public function getLastErrorErrno(): int {}
- public function getLastDisconnectedServer(): false|array {}
+ public function getLastDisconnectedServer(): array|false {}
- public function getStats(?string $type=null): false|array {}
- public function getVersion(): false|array {}
- public function getAllKeys(): false|array {}
+ public function getStats(?string $type=null): array|false {}
+ public function getVersion(): array|false {}
+ public function getAllKeys(): array|false {}
public function flush(int $delay=0): bool {}
@@ -75,7 +75,7 @@ public function setOption(int $option, mixed $value): bool {}
public function setOptions(array $options): bool {}
public function setBucket(array $host_map, ?array $forward_map, int $replicas): bool {}
#ifdef HAVE_MEMCACHED_SASL
- public function setSaslAuthData(string $username, string $password): bool {}
+ public function setSaslAuthData(string $username, #[\SensitiveParameter] string $password): bool {}
#endif
#ifdef HAVE_MEMCACHED_SET_ENCODING_KEY
@@ -86,7 +86,7 @@ public function isPristine(): bool {}
public function checkKey(string $key): bool {}
}
-#ifdef HAVE_MEMCACHED_PROTOCOL
+#if defined(HAVE_MEMCACHED_PROTOCOL)
class MemcachedServer {
public function run(string $address): bool {}
diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h
index 3373624e..e8b999de 100644
--- a/php_memcached_arginfo.h
+++ b/php_memcached_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */
+ * Stub hash: 75604abd7f58655a9ebda6f0ea579840311c1f08 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent_id, IS_STRING, 1, "null")
@@ -26,12 +26,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getByKey, 0, 2,
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMulti, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMulti, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMultiByKey, 0, 2, MAY_BE_FALSE|MAY_BE_ARRAY)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getMultiByKey, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, keys, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, get_flags, IS_LONG, 0, "0")
@@ -50,7 +50,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getDelayedByKey,
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value_cb, IS_CALLABLE, 1, "null")
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_fetch, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_fetchAll arginfo_class_Memcached_fetch
@@ -91,14 +91,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_setMultiByKey, 0
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_cas, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, cas_token, IS_STRING, 0)
+ ZEND_ARG_TYPE_MASK(0, cas_token, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, expiration, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_casByKey, 0, 4, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, cas_token, IS_STRING, 0)
+ ZEND_ARG_TYPE_MASK(0, cas_token, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0)
@@ -150,7 +150,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_deleteMultiByKey
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, time, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_increment, 0, 1, MAY_BE_FALSE|MAY_BE_LONG)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_increment, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "1")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, initial_value, IS_LONG, 0, "0")
@@ -159,7 +159,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_decrement arginfo_class_Memcached_increment
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_incrementByKey, 0, 2, MAY_BE_FALSE|MAY_BE_LONG)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_incrementByKey, 0, 2, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "1")
@@ -182,7 +182,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_getServerList, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getServerByKey, 0, 1, MAY_BE_FALSE|MAY_BE_ARRAY)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getServerByKey, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, server_key, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -201,7 +201,7 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_getLastDisconnectedServer arginfo_class_Memcached_fetch
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_FALSE|MAY_BE_ARRAY)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Memcached_getStats, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
@@ -406,12 +406,39 @@ static const zend_function_entry class_Memcached_methods[] = {
};
-static const zend_function_entry class_MemcachedServer_methods[] = {
#if defined(HAVE_MEMCACHED_PROTOCOL)
+static const zend_function_entry class_MemcachedServer_methods[] = {
ZEND_ME(MemcachedServer, run, arginfo_class_MemcachedServer_run, ZEND_ACC_PUBLIC)
-#endif
-#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_ME(MemcachedServer, on, arginfo_class_MemcachedServer_on, ZEND_ACC_PUBLIC)
-#endif
ZEND_FE_END
};
+#endif
+
+static zend_class_entry *register_class_Memcached(void)
+{
+ zend_class_entry ce, *class_entry;
+
+ INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods);
+ class_entry = zend_register_internal_class_ex(&ce, NULL);
+#if (PHP_VERSION_ID >= 80200)
+
+#if defined(HAVE_MEMCACHED_SASL)
+
+ zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setsaslauthdata", sizeof("setsaslauthdata") - 1), 1, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0);
+#endif
+#endif
+
+ return class_entry;
+}
+
+#if defined(HAVE_MEMCACHED_PROTOCOL)
+static zend_class_entry *register_class_MemcachedServer(void)
+{
+ zend_class_entry ce, *class_entry;
+
+ INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods);
+ class_entry = zend_register_internal_class_ex(&ce, NULL);
+
+ return class_entry;
+}
+#endif
diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h
index ad6d6562..66d5bb91 100644
--- a/php_memcached_legacy_arginfo.h
+++ b/php_memcached_legacy_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */
+ * Stub hash: 75604abd7f58655a9ebda6f0ea579840311c1f08 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0)
ZEND_ARG_INFO(0, persistent_id)
@@ -402,12 +402,32 @@ static const zend_function_entry class_Memcached_methods[] = {
};
-static const zend_function_entry class_MemcachedServer_methods[] = {
#if defined(HAVE_MEMCACHED_PROTOCOL)
+static const zend_function_entry class_MemcachedServer_methods[] = {
ZEND_ME(MemcachedServer, run, arginfo_class_MemcachedServer_run, ZEND_ACC_PUBLIC)
-#endif
-#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_ME(MemcachedServer, on, arginfo_class_MemcachedServer_on, ZEND_ACC_PUBLIC)
-#endif
ZEND_FE_END
};
+#endif
+
+static zend_class_entry *register_class_Memcached(void)
+{
+ zend_class_entry ce, *class_entry;
+
+ INIT_CLASS_ENTRY(ce, "Memcached", class_Memcached_methods);
+ class_entry = zend_register_internal_class_ex(&ce, NULL);
+
+ return class_entry;
+}
+
+#if defined(HAVE_MEMCACHED_PROTOCOL)
+static zend_class_entry *register_class_MemcachedServer(void)
+{
+ zend_class_entry ce, *class_entry;
+
+ INIT_CLASS_ENTRY(ce, "MemcachedServer", class_MemcachedServer_methods);
+ class_entry = zend_register_internal_class_ex(&ce, NULL);
+
+ return class_entry;
+}
+#endif
diff --git a/php_memcached_private.h b/php_memcached_private.h
index b4b1115b..2c22ecba 100644
--- a/php_memcached_private.h
+++ b/php_memcached_private.h
@@ -48,11 +48,11 @@
#include
#ifdef PHP_WIN32
- # if PHP_VERSION_ID >= 80000
- # include "php_stdint.h"
-#else
-# include "win32/php_stdint.h"
-#endif
+ # if PHP_VERSION_ID >= 80000
+ # include
+ #else
+ # include "win32/php_stdint.h"
+ #endif
#else
/* Used to store the size of the block */
# if defined(HAVE_INTTYPES_H)
@@ -98,7 +98,8 @@ typedef enum {
typedef enum {
COMPRESSION_TYPE_ZLIB = 1,
- COMPRESSION_TYPE_FASTLZ = 2
+ COMPRESSION_TYPE_FASTLZ = 2,
+ COMPRESSION_TYPE_ZSTD = 3
} php_memc_compression_type;
typedef struct {
@@ -186,6 +187,8 @@ ZEND_BEGIN_MODULE_GLOBALS(php_memcached)
zend_long compression_threshold;
double compression_factor;
zend_long store_retry_count;
+ zend_long compression_level;
+ zend_long item_size_limit;
/* Converted values*/
php_memc_serializer_type serializer_type;
diff --git a/tests/experimental/add_bykey.phpt b/tests/add_bykey.phpt
similarity index 84%
rename from tests/experimental/add_bykey.phpt
rename to tests/add_bykey.phpt
index 195fe96d..1c1521d2 100644
--- a/tests/experimental/add_bykey.phpt
+++ b/tests/add_bykey.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::addByKey()
--SKIPIF--
-
+
--FILE--
delete('foo');
@@ -15,7 +15,7 @@ echo $m->getResultMessage(), "\n";
var_dump($m->addByKey('foo', '', 1, 10));
echo $m->getResultMessage(), "\n";
// This is OK for the binary protocol
-$rv = $m->addByKey('foo', ' asd ���', 1, 1);
+$rv = $m->addByKey('foo', ' asd åäö', 1, 1);
if ($m->getOption(Memcached::OPT_BINARY_PROTOCOL)) {
if ($rv !== true and $m->getResultCode() !== Memcached::RES_SUCCESS) {
var_dump($rv);
diff --git a/tests/experimental/addserver_unixdomain.phpt b/tests/addserver_unixdomain.phpt
similarity index 87%
rename from tests/experimental/addserver_unixdomain.phpt
rename to tests/addserver_unixdomain.phpt
index 4848015d..7e16834c 100644
--- a/tests/experimental/addserver_unixdomain.phpt
+++ b/tests/addserver_unixdomain.phpt
@@ -1,7 +1,7 @@
--TEST--
Memcached::addServer() unix doamin socket
--SKIPIF--
-
+
--CLEAN--
+
--FILE--
setOption(Memcached::OPT_COMPRESSION, false);
diff --git a/tests/experimental/cas_bykey.phpt b/tests/cas_bykey.phpt
similarity index 84%
rename from tests/experimental/cas_bykey.phpt
rename to tests/cas_bykey.phpt
index 0a9da94e..32808813 100644
--- a/tests/experimental/cas_bykey.phpt
+++ b/tests/cas_bykey.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::casByKey()
--SKIPIF--
-
+
--FILE--
delete('cas_test');
diff --git a/tests/cas_e2big.phpt b/tests/cas_e2big.phpt
new file mode 100644
index 00000000..99c3562b
--- /dev/null
+++ b/tests/cas_e2big.phpt
@@ -0,0 +1,32 @@
+--TEST--
+set data exceeding size limit
+--SKIPIF--
+
+--FILE--
+ 100,
+));
+
+$m->delete('cas_e2big_test');
+
+$m->set('cas_e2big_test', 'hello');
+$result = $m->get('cas_e2big_test', null, Memcached::GET_EXTENDED);
+var_dump(is_array($result) && isset($result['cas']) && isset($result['value']) && $result['value'] == 'hello');
+
+$value = str_repeat('a large payload', 1024 * 1024);
+
+var_dump($m->cas($result['cas'], 'cas_e2big_test', $value, 360));
+var_dump($m->getResultCode() == Memcached::RES_E2BIG);
+var_dump($m->getResultMessage() == 'ITEM TOO BIG');
+var_dump($m->get('cas_e2big_test') == 'hello');
+var_dump($m->getResultCode() == Memcached::RES_SUCCESS);
+?>
+--EXPECT--
+bool(true)
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/tests/experimental/cas_invalid_key.phpt b/tests/cas_invalid_key.phpt
similarity index 55%
rename from tests/experimental/cas_invalid_key.phpt
rename to tests/cas_invalid_key.phpt
index 6011c4b8..9cb7293c 100644
--- a/tests/experimental/cas_invalid_key.phpt
+++ b/tests/cas_invalid_key.phpt
@@ -1,17 +1,20 @@
--TEST--
Memcached::cas() with strange key
--SKIPIF--
-
+
--FILE--
false,
+ Memcached::OPT_VERIFY_KEY => true
+));
error_reporting(0);
var_dump($m->cas(0, '', true, 10));
echo $m->getResultMessage(), "\n";
-var_dump($m->cas(0, ' �� jas kjjhask d ', true, 10)); # no spaces allowed
+var_dump($m->cas(0, ' äö jas kjjhask d ', true, 10)); # no spaces allowed
echo $m->getResultMessage(), "\n";
--EXPECTF--
diff --git a/tests/compression_conditions.phpt b/tests/compression_conditions.phpt
index 749ebe8a..960058b6 100644
--- a/tests/compression_conditions.phpt
+++ b/tests/compression_conditions.phpt
@@ -21,6 +21,8 @@ function get_compression($name) {
return Memcached::COMPRESSION_ZLIB;
case 'fastlz':
return Memcached::COMPRESSION_FASTLZ;
+ case 'zstd':
+ return Memcached::COMPRESSION_ZSTD;
default:
echo "Strange compression type: $name\n";
return 0;
diff --git a/tests/compression_types.phpt b/tests/compression_types.phpt
index ce07aed5..81d7867c 100644
--- a/tests/compression_types.phpt
+++ b/tests/compression_types.phpt
@@ -15,6 +15,10 @@ function get_compression($name) {
return Memcached::COMPRESSION_ZLIB;
case 'fastlz':
return Memcached::COMPRESSION_FASTLZ;
+ case 'zstd':
+ if (Memcached::HAVE_ZSTD) {
+ return Memcached::COMPRESSION_ZSTD;
+ } else return 0;
default:
echo "Strange compression type: $name\n";
return 0;
@@ -54,6 +58,26 @@ fetch_with_compression($m, 'hello6', $data, '', 'fastlz');
fetch_with_compression($m, 'hello7', $data, 'zlib', '');
fetch_with_compression($m, 'hello8', $data, 'fastlz', '');
fetch_with_compression($m, 'hello9', $data, '', '');
+if (Memcached::HAVE_ZSTD) {
+fetch_with_compression($m, 'hello10', $data, 'zstd', 'zstd');
+fetch_with_compression($m, 'hello11', $data, 'zstd', 'fastlz');
+fetch_with_compression($m, 'hello12', $data, 'fastlz', 'zstd');
+fetch_with_compression($m, 'hello13', $data, '', 'zstd');
+fetch_with_compression($m, 'hello14', $data, 'zstd', '');
+} else {
+ echo <<
--EXPECT--
set=[zlib] get=[zlib]
@@ -74,3 +98,13 @@ set=[fastlz] get=[]
bool(true)
set=[] get=[]
bool(true)
+set=[zstd] get=[zstd]
+bool(true)
+set=[zstd] get=[fastlz]
+bool(true)
+set=[fastlz] get=[zstd]
+bool(true)
+set=[] get=[zstd]
+bool(true)
+set=[zstd] get=[]
+bool(true)
diff --git a/tests/experimental/delete_bykey.phpt b/tests/delete_bykey.phpt
similarity index 76%
rename from tests/experimental/delete_bykey.phpt
rename to tests/delete_bykey.phpt
index 807af8ca..6aa589c5 100644
--- a/tests/experimental/delete_bykey.phpt
+++ b/tests/delete_bykey.phpt
@@ -1,11 +1,14 @@
--TEST--
Memcached::deleteByKey()
--SKIPIF--
-
+
--FILE--
false,
+ Memcached::OPT_VERIFY_KEY => true
+));
$m->setByKey('keffe', 'eisaleeoo', "foo");
var_dump($m->getByKey('keffe', 'eisaleeoo'));
@@ -21,7 +24,7 @@ var_dump($m->deleteByKey('keffe', ''));
echo $m->getResultMessage(), "\n";
var_dump($m->deleteByKey('', 'keffe'));
echo $m->getResultMessage(), "\n";
-var_dump($m->deleteByKey('keffe', '���as�� �a�sd�f asdf')); # no spaces allowed
+var_dump($m->deleteByKey('keffe', 'äöåasäö åaösdäf asdf')); # no spaces allowed
echo $m->getResultMessage(), "\n";
--EXPECTF--
string(3) "foo"
diff --git a/tests/experimental/deletemulti_nonstringkeys.phpt b/tests/deletemulti_nonstringkeys.phpt
similarity index 87%
rename from tests/experimental/deletemulti_nonstringkeys.phpt
rename to tests/deletemulti_nonstringkeys.phpt
index 2dac8920..8e275e9c 100644
--- a/tests/experimental/deletemulti_nonstringkeys.phpt
+++ b/tests/deletemulti_nonstringkeys.phpt
@@ -1,10 +1,10 @@
--TEST--
Delete multi with integer keys
--SKIPIF--
-
+
--FILE--
---FILE--
-set('foo', 1, 10);
-
-$cas = null;
-var_dump($m->getByKey('foo', 'foo', null, $cas));
-var_dump($cas);
-echo $m->getResultMessage(), "\n";
-
-$cas = null;
-var_dump($m->getByKey('', 'foo', null, $cas));
-var_dump($cas);
-echo $m->getResultMessage(), "\n";
-
-$m->set('bar', "asdf", 10);
-
-$cas = null;
-var_dump($m->getByKey('foo', 'bar', null, $cas));
-var_dump($cas);
-echo $m->getResultMessage(), "\n";
-
-$m->delete('foo');
-$cas = null;
-var_dump($m->getByKey(' � foo jkh a s ���', 'foo', null, $cas));
-var_dump($cas);
-echo $m->getResultMessage(), "\n";
-
-$cas = null;
-var_dump($m->getByKey(' � foo jkh a s ���', '', null, $cas));
-var_dump($cas);
-echo $m->getResultMessage(), "\n";
-
-$m->delete('foo');
-$cas = null;
-var_dump($m->getByKey('foo', 'foo', 'the_callback', $cas));
-var_dump($cas);
-var_dump($m->getByKey('foo', 'foo'));
---EXPECTF--
-int(1)
-float(%d)
-SUCCESS
-int(1)
-float(%d)
-SUCCESS
-string(4) "asdf"
-float(%d)
-SUCCESS
-bool(false)
-float(0)
-NOT FOUND
-bool(false)
-NULL
-A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE
-called
-string(4) "1234"
-float(0)
-string(4) "1234"
diff --git a/tests/experimental/fetch.phpt b/tests/fetch.phpt
similarity index 93%
rename from tests/experimental/fetch.phpt
rename to tests/fetch.phpt
index 13136c5b..68977466 100644
--- a/tests/experimental/fetch.phpt
+++ b/tests/fetch.phpt
@@ -1,7 +1,7 @@
--TEST--
Memcached getDelayed() and fetch() with and without cas
--SKIPIF--
-
+
--FILE--
+
--FILE--
serialize_throws) {
+ throw new Exception("1234");
+ }
+ return ["1234"];
+ }
+
+ public function __unserialize($str) {
+ throw new Exception("123456");
+ }
}
$data = new Foo();
diff --git a/tests/experimental/fetchall_badunserialize.phpt b/tests/fetchall_badunserialize.phpt
similarity index 76%
rename from tests/experimental/fetchall_badunserialize.phpt
rename to tests/fetchall_badunserialize.phpt
index 5684763f..815c9e21 100644
--- a/tests/experimental/fetchall_badunserialize.phpt
+++ b/tests/fetchall_badunserialize.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::fetch() with bad unserialize
--SKIPIF--
-
+
--FILE--
serialize_throws) {
+ throw new Exception("1234");
+ }
+ return ["1234"];
+ }
+
+ public function __unserialize($str) {
+ throw new Exception("123456");
+ }
}
$data = new Foo();
diff --git a/tests/experimental/get.phpt b/tests/get.phpt
similarity index 69%
rename from tests/experimental/get.phpt
rename to tests/get.phpt
index 308bda98..722308f0 100644
--- a/tests/experimental/get.phpt
+++ b/tests/get.phpt
@@ -1,11 +1,14 @@
--TEST--
Memcached::get()
--SKIPIF--
-
+
--FILE--
false,
+ Memcached::OPT_VERIFY_KEY => true
+));
$m->delete('foo');
@@ -20,7 +23,7 @@ var_dump($m->get('foo'));
echo $m->getResultMessage(), "\n";
$m->delete('foo');
-var_dump($m->get(' � foo jkh a s ���'));
+var_dump($m->get(' ä foo jkh a s åäö'));
echo $m->getResultMessage(), "\n";
--EXPECT--
bool(false)
diff --git a/tests/experimental/get_bykey.phpt b/tests/get_bykey.phpt
similarity index 75%
rename from tests/experimental/get_bykey.phpt
rename to tests/get_bykey.phpt
index a392aaeb..704e8f04 100644
--- a/tests/experimental/get_bykey.phpt
+++ b/tests/get_bykey.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::getByKey()
--SKIPIF--
-
+
--FILE--
set('foo', 1, 10);
@@ -20,7 +20,7 @@ var_dump($m->getByKey('foo', 'bar'));
echo $m->getResultMessage(), "\n";
$m->delete('foo');
-var_dump($m->getByKey(' � foo jkh a s ���', 'foo'));
+var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo'));
echo $m->getResultMessage(), "\n";
--EXPECTF--
diff --git a/tests/get_bykey_cas.phpt b/tests/get_bykey_cas.phpt
new file mode 100644
index 00000000..90b566c4
--- /dev/null
+++ b/tests/get_bykey_cas.phpt
@@ -0,0 +1,61 @@
+--TEST--
+Memcached::getByKey() with CAS
+--SKIPIF--
+
+--FILE--
+set('foo', 1, 10);
+
+$v = $m->getByKey('foo', 'foo', null, Memcached::GET_EXTENDED);
+var_dump($v['value']);
+var_dump($v['cas']);
+echo $m->getResultMessage(), "\n";
+
+$v = $m->getByKey('', 'foo', null, Memcached::GET_EXTENDED);
+var_dump($v['value']);
+var_dump($v['cas']);
+echo $m->getResultMessage(), "\n";
+
+$m->set('bar', "asdf", 10);
+
+$v = $m->getByKey('foo', 'bar', null, Memcached::GET_EXTENDED);
+var_dump($v['value']);
+var_dump($v['cas']);
+echo $m->getResultMessage(), "\n";
+
+$m->delete('foo');
+var_dump($m->getByKey(' ä foo jkh a s åäö', 'foo', null, Memcached::GET_EXTENDED));
+echo $m->getResultMessage(), "\n";
+
+var_dump($m->getByKey(' ä foo jkh a s åäö', '', null, Memcached::GET_EXTENDED));
+echo $m->getResultMessage(), "\n";
+
+$m->delete('foo');
+var_dump($m->getByKey('foo', 'foo', 'the_callback', Memcached::GET_EXTENDED));
+var_dump($m->getByKey('foo', 'foo'));
+--EXPECTF--
+int(1)
+int(%d)
+SUCCESS
+int(1)
+int(%d)
+SUCCESS
+string(4) "asdf"
+int(%d)
+SUCCESS
+bool(false)
+NOT FOUND
+bool(false)
+A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE
+called
+bool(false)
+bool(false)
\ No newline at end of file
diff --git a/tests/experimental/getdelayed_badserver.phpt b/tests/getdelayed_badserver.phpt
similarity index 87%
rename from tests/experimental/getdelayed_badserver.phpt
rename to tests/getdelayed_badserver.phpt
index c4902174..5d274efb 100644
--- a/tests/experimental/getdelayed_badserver.phpt
+++ b/tests/getdelayed_badserver.phpt
@@ -1,7 +1,7 @@
--TEST--
Memcached::getDelayedByKey() with bad server
--SKIPIF--
-
+
--FILE--
+
--FILE--
serialize_throws) {
+ throw new Exception("1234");
+ }
+ return ["1234"];
+ }
+
+ public function __unserialize($str) {
+ throw new Exception("123456");
+ }
}
function mycb($memc, $key, $value) {
diff --git a/tests/experimental/getdelayed_bykey.phpt b/tests/getdelayed_bykey.phpt
similarity index 89%
rename from tests/experimental/getdelayed_bykey.phpt
rename to tests/getdelayed_bykey.phpt
index a29f646b..442320a2 100644
--- a/tests/experimental/getdelayed_bykey.phpt
+++ b/tests/getdelayed_bykey.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::getDelayedByKey()
--SKIPIF--
-
+
--FILE--
+
--FILE--
getDelayedByKey('kef', array_keys($data), true, 'myfunc');
?>
--EXPECTF--
-array(3) {
+array(4) {
["key"]=>
string(3) "foo"
["value"]=>
string(8) "foo-data"
["cas"]=>
- float(%d)
+ int(%d)
+ ["flags"]=>
+ int(0)
}
-array(3) {
+array(4) {
["key"]=>
string(3) "bar"
["value"]=>
string(8) "bar-data"
["cas"]=>
- float(%d)
+ int(%d)
+ ["flags"]=>
+ int(0)
}
-array(3) {
+array(4) {
["key"]=>
string(3) "baz"
["value"]=>
string(8) "baz-data"
["cas"]=>
- float(%d)
+ int(%d)
+ ["flags"]=>
+ int(0)
}
-array(3) {
+array(4) {
["key"]=>
string(3) "lol"
["value"]=>
string(8) "lol-data"
["cas"]=>
- float(%d)
+ int(%d)
+ ["flags"]=>
+ int(0)
}
-array(3) {
+array(4) {
["key"]=>
string(3) "kek"
["value"]=>
string(8) "kek-data"
["cas"]=>
- float(%d)
+ int(%d)
+ ["flags"]=>
+ int(0)
}
diff --git a/tests/experimental/getdelayed_nonstring_keys.phpt b/tests/getdelayed_nonstring_keys.phpt
similarity index 90%
rename from tests/experimental/getdelayed_nonstring_keys.phpt
rename to tests/getdelayed_nonstring_keys.phpt
index 81363f3b..005d0579 100644
--- a/tests/experimental/getdelayed_nonstring_keys.phpt
+++ b/tests/getdelayed_nonstring_keys.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached getDelayed non string keys
--SKIPIF--
-
+
--FILE--
+
--FILE--
getResultCode()) {
}
--EXPECTF--
-array(0) {
-}
+bool(false)
NO SERVERS DEFINED
-array(0) {
-}
+bool(false)
%d: %s
diff --git a/tests/experimental/getmulti_badunserialize.phpt b/tests/getmulti_badunserialize.phpt
similarity index 77%
rename from tests/experimental/getmulti_badunserialize.phpt
rename to tests/getmulti_badunserialize.phpt
index 963e9730..280feed3 100644
--- a/tests/experimental/getmulti_badunserialize.phpt
+++ b/tests/getmulti_badunserialize.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::getMulti() with bad unserialize
--SKIPIF--
-
+
--FILE--
set('bar', "12", 10));
diff --git a/tests/experimental/getmulti_bykey.phpt b/tests/getmulti_bykey.phpt
similarity index 82%
rename from tests/experimental/getmulti_bykey.phpt
rename to tests/getmulti_bykey.phpt
index 3f7a6f78..b615dc66 100644
--- a/tests/experimental/getmulti_bykey.phpt
+++ b/tests/getmulti_bykey.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::getMultiByKey()
--SKIPIF--
-
+
--FILE--
set('foo', 1, 10);
diff --git a/tests/experimental/getmulti_empty.phpt b/tests/getmulti_empty.phpt
similarity index 60%
rename from tests/experimental/getmulti_empty.phpt
rename to tests/getmulti_empty.phpt
index 6279104d..3550e814 100644
--- a/tests/experimental/getmulti_empty.phpt
+++ b/tests/getmulti_empty.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::getMulti() with empty array
--SKIPIF--
-
+
--FILE--
getMulti(array());
diff --git a/tests/experimental/getmulti_partial_error.phpt b/tests/getmulti_partial_error.phpt
similarity index 84%
rename from tests/experimental/getmulti_partial_error.phpt
rename to tests/getmulti_partial_error.phpt
index fa392e9e..928f49f4 100644
--- a/tests/experimental/getmulti_partial_error.phpt
+++ b/tests/getmulti_partial_error.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::getMulti() partial error
--SKIPIF--
-
+
--FILE--
+
--FILE--
getVersion());
-include dirname(dirname(__FILE__)) . "/config.inc";
+include dirname(__FILE__) . "/config.inc";
$m = memc_get_instance ();
$stats = $m->getVersion();
diff --git a/tests/keys_ascii.phpt b/tests/keys_ascii.phpt
index f7e98894..e7846e99 100644
--- a/tests/keys_ascii.phpt
+++ b/tests/keys_ascii.phpt
@@ -8,11 +8,8 @@ Test valid and invalid keys - ascii
include dirname (__FILE__) . '/config.inc';
$ascii = memc_get_instance (array (
Memcached::OPT_BINARY_PROTOCOL => false,
- Memcached::OPT_VERIFY_KEY => false
+ Memcached::OPT_VERIFY_KEY => true
));
-// libmemcached can verify keys, but these are tests are for our own
-// function s_memc_valid_key_ascii, so explicitly disable the checks
-// that libmemcached can perform.
echo 'ASCII: SPACES' . PHP_EOL;
var_dump ($ascii->set ('ascii key with spaces', 'this is a test'));
diff --git a/tests/experimental/locale_float.phpt b/tests/locale_float.phpt
similarity index 80%
rename from tests/experimental/locale_float.phpt
rename to tests/locale_float.phpt
index c071d974..2f25ea73 100644
--- a/tests/experimental/locale_float.phpt
+++ b/tests/locale_float.phpt
@@ -2,14 +2,14 @@
Float should not consider locale
--SKIPIF--
--FILE--
--FILE--
diff --git a/tests/options.phpt b/tests/options.phpt
index ce895385..a096c8f1 100644
--- a/tests/options.phpt
+++ b/tests/options.phpt
@@ -26,6 +26,26 @@ var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSIO
var_dump($m->setOption(Memcached::OPT_COMPRESSION_TYPE, 0));
var_dump($m->getOption(Memcached::OPT_COMPRESSION_TYPE) == Memcached::COMPRESSION_FASTLZ);
+
+echo "item_size_limit setOption\n";
+var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, 0));
+var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0);
+var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, -1));
+var_dump($m->setOption(Memcached::OPT_ITEM_SIZE_LIMIT, 1000000));
+var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000);
+
+echo "item_size_limit ini\n";
+ini_set('memcached.item_size_limit', '0');
+$m = new Memcached();
+var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0);
+
+ini_set('memcached.item_size_limit', '1000000');
+$m = new Memcached();
+var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000);
+
+ini_set('memcached.item_size_limit', null);
+$m = new Memcached();
+var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) === 0);
?>
--EXPECTF--
bool(true)
@@ -41,3 +61,15 @@ bool(true)
bool(true)
bool(false)
bool(true)
+item_size_limit setOption
+bool(true)
+bool(true)
+
+Warning: Memcached::setOption(): ITEM_SIZE_LIMIT must be >= 0 in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+item_size_limit ini
+bool(true)
+bool(true)
+bool(true)
diff --git a/tests/experimental/prepend_bykey.phpt b/tests/prepend_bykey.phpt
similarity index 78%
rename from tests/experimental/prepend_bykey.phpt
rename to tests/prepend_bykey.phpt
index 87d3fd38..482899de 100644
--- a/tests/experimental/prepend_bykey.phpt
+++ b/tests/prepend_bykey.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::appendByKey()
--SKIPIF--
-
+
--FILE--
setOption(Memcached::OPT_COMPRESSION, false);
diff --git a/tests/experimental/replace_bykey.phpt b/tests/replace_bykey.phpt
similarity index 82%
rename from tests/experimental/replace_bykey.phpt
rename to tests/replace_bykey.phpt
index cddf10f0..b844824c 100644
--- a/tests/experimental/replace_bykey.phpt
+++ b/tests/replace_bykey.phpt
@@ -1,10 +1,10 @@
--TEST--
Memcached::replaceByKey()
--SKIPIF--
-
+
--FILE--
+
--FILE--
setByKey('foo', 'foo', 1, 10));
@@ -14,7 +14,7 @@ echo $m->getResultMessage(), "\n";
var_dump($m->setByKey('foo', '', 1, 10));
echo $m->getResultMessage(), "\n";
// This is OK for the binary protocol
-$rv = $m->setByKey('foo', ' asd ���', 1, 1);
+$rv = $m->setByKey('foo', ' asd åäö', 1, 1);
if ($m->getOption(Memcached::OPT_BINARY_PROTOCOL)) {
if ($rv !== true and $m->getResultCode() !== Memcached::RES_SUCCESS) {
var_dump($rv);
diff --git a/tests/experimental/set_comp_below_factor.phpt b/tests/set_comp_below_factor.phpt
similarity index 74%
rename from tests/experimental/set_comp_below_factor.phpt
rename to tests/set_comp_below_factor.phpt
index 12e6d6a4..80d28006 100644
--- a/tests/experimental/set_comp_below_factor.phpt
+++ b/tests/set_comp_below_factor.phpt
@@ -1,10 +1,10 @@
--TEST--
Compress below factor and fail to plain.
--SKIPIF--
-
+
--FILE--
+
--FILE--
+
--FILE--
0,
+));
$key = 'foobarbazDEADC0DE';
$value = str_repeat("foo bar", 1024 * 1024);
diff --git a/tests/set_large_e2big.phpt b/tests/set_large_e2big.phpt
new file mode 100644
index 00000000..498231e4
--- /dev/null
+++ b/tests/set_large_e2big.phpt
@@ -0,0 +1,27 @@
+--TEST--
+set data exceeding size limit
+--SKIPIF--
+
+--FILE--
+ 100,
+));
+
+$m->delete('set_large_e2big_test');
+
+$value = str_repeat('a large payload', 1024 * 1024);
+
+var_dump($m->set('set_large_e2big_test', $value));
+var_dump($m->getResultCode() == Memcached::RES_E2BIG);
+var_dump($m->getResultMessage() == 'ITEM TOO BIG');
+var_dump($m->get('set_large_e2big_test') === false);
+var_dump($m->getResultCode() == Memcached::RES_NOTFOUND);
+?>
+--EXPECT--
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/tests/experimental/setget_zero_factor.phpt b/tests/setget_zero_factor.phpt
similarity index 70%
rename from tests/experimental/setget_zero_factor.phpt
rename to tests/setget_zero_factor.phpt
index bb5fb0dc..7d7634c2 100644
--- a/tests/experimental/setget_zero_factor.phpt
+++ b/tests/setget_zero_factor.phpt
@@ -1,10 +1,10 @@
--TEST--
Compress with 0 factor and get
--SKIPIF--
-
+
--FILE--
+
--FILE--
setOptions(array(
Memcached::OPT_COMPRESSION => 0,
Memcached::OPT_LIBKETAMA_COMPATIBLE => 1,
Memcached::OPT_CONNECT_TIMEOUT => 5000,
+ Memcached::OPT_ITEM_SIZE_LIMIT => 1000000,
)));
var_dump($m->getOption(Memcached::OPT_PREFIX_KEY) == 'a_prefix');
var_dump($m->getOption(Memcached::OPT_SERIALIZER) == Memcached::SERIALIZER_PHP);
var_dump($m->getOption(Memcached::OPT_COMPRESSION) == 0);
var_dump($m->getOption(Memcached::OPT_LIBKETAMA_COMPATIBLE) == 1);
+var_dump($m->getOption(Memcached::OPT_ITEM_SIZE_LIMIT) == 1000000);
echo "test invalid options\n";
@@ -36,6 +38,7 @@ bool(true)
bool(true)
bool(true)
bool(true)
+bool(true)
test invalid options
Warning: Memcached::setOptions(): invalid configuration option in %s on line %d
diff --git a/tests/touch_binary.phpt b/tests/touch_binary.phpt
index 382c1778..059ec74c 100644
--- a/tests/touch_binary.phpt
+++ b/tests/touch_binary.phpt
@@ -28,12 +28,12 @@ function status_print ($op, $mem, $expected)
$code = $mem->getResultcode();
if ($code == $expected)
- echo "${op} status code as expected" . PHP_EOL;
+ echo "{$op} status code as expected" . PHP_EOL;
else {
$expected = resolve_to_constant ($expected);
$code = resolve_to_constant ($code);
- echo "${op} status code mismatch, expected ${expected} but got ${code}" . PHP_EOL;
+ echo "{$op} status code mismatch, expected {$expected} but got {$code}" . PHP_EOL;
}
}