diff --git a/package.xml b/package.xml
index ec44bd1b..519de583 100644
--- a/package.xml
+++ b/package.xml
@@ -87,6 +87,7 @@ Fixes
+
diff --git a/php_memcached.c b/php_memcached.c
index 1e218a00..8e4fa41d 100644
--- a/php_memcached.c
+++ b/php_memcached.c
@@ -228,7 +228,7 @@ zend_bool s_memc_valid_key_ascii(zend_string *key)
size_t i, len = ZSTR_LEN(key);
for (i = 0; i < len; i++) {
- if (iscntrl(str[i]) || isspace(str[i]))
+ if (!isgraph(str[i]) || isspace(str[i]))
return 0;
}
return 1;
@@ -3450,6 +3450,24 @@ static PHP_METHOD(Memcached, isPristine)
}
/* }}} */
+/* {{{ bool Memcached::checkKey(string key)
+ Checks if a key is valid */
+PHP_METHOD(Memcached, checkKey)
+{
+ zend_string *key;
+ MEMC_METHOD_INIT_VARS;
+
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_STR(key)
+ ZEND_PARSE_PARAMETERS_END();
+
+ MEMC_METHOD_FETCH_OBJECT;
+ s_memc_set_status(intern, MEMCACHED_SUCCESS, 0);
+ MEMC_CHECK_KEY(intern, key);
+ RETURN_TRUE;
+}
+/* }}} */
+
/****************************************
Internal support code
****************************************/
diff --git a/php_memcached.stub.php b/php_memcached.stub.php
index 5a735b57..819186f4 100644
--- a/php_memcached.stub.php
+++ b/php_memcached.stub.php
@@ -8,17 +8,17 @@
class Memcached {
- public function __construct(string $persistent_id=null, callable $callback=null, string $connection_str=null) {}
+ public function __construct(?string $persistent_id=null, ?callable $callback=null, ?string $connection_str=null) {}
public function getResultCode(): int {}
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 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 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 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 {}
@@ -64,7 +64,7 @@ public function getLastErrorCode(): int {}
public function getLastErrorErrno(): int {}
public function getLastDisconnectedServer(): false|array {}
- public function getStats(string $type=null): false|array {}
+ public function getStats(?string $type=null): false|array {}
public function getVersion(): false|array {}
public function getAllKeys(): false|array {}
@@ -83,6 +83,7 @@ public function setEncodingKey(string $key): bool {}
#endif
public function isPersistent(): bool {}
public function isPristine(): bool {}
+ public function checkKey(string $key): bool {}
}
#ifdef HAVE_MEMCACHED_PROTOCOL
diff --git a/php_memcached_arginfo.h b/php_memcached_arginfo.h
index 4c8a6845..3373624e 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: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */
+ * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */
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")
@@ -249,6 +249,10 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_isPristine arginfo_class_Memcached_resetServerList
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Memcached_checkKey, 0, 1, _IS_BOOL, 0)
+ ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_MemcachedServer_run, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, address, IS_STRING, 0)
@@ -325,6 +329,7 @@ ZEND_METHOD(Memcached, setEncodingKey);
#endif
ZEND_METHOD(Memcached, isPersistent);
ZEND_METHOD(Memcached, isPristine);
+ZEND_METHOD(Memcached, checkKey);
#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_METHOD(MemcachedServer, run);
#endif
@@ -396,6 +401,7 @@ static const zend_function_entry class_Memcached_methods[] = {
#endif
ZEND_ME(Memcached, isPersistent, arginfo_class_Memcached_isPersistent, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, isPristine, arginfo_class_Memcached_isPristine, ZEND_ACC_PUBLIC)
+ ZEND_ME(Memcached, checkKey, arginfo_class_Memcached_checkKey, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
diff --git a/php_memcached_legacy_arginfo.h b/php_memcached_legacy_arginfo.h
index a615e3a6..ad6d6562 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: 573d35c5c6b6c397943e0f8ab9c505e2f4ce9e34 */
+ * Stub hash: 3f4694d4e1f3d1647a832acd8539b056b2ab5e7a */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached___construct, 0, 0, 0)
ZEND_ARG_INFO(0, persistent_id)
@@ -245,6 +245,10 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Memcached_isPristine arginfo_class_Memcached_getResultCode
+ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Memcached_checkKey, 0, 0, 1)
+ ZEND_ARG_INFO(0, key)
+ZEND_END_ARG_INFO()
+
#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_MemcachedServer_run, 0, 0, 1)
ZEND_ARG_INFO(0, address)
@@ -321,6 +325,7 @@ ZEND_METHOD(Memcached, setEncodingKey);
#endif
ZEND_METHOD(Memcached, isPersistent);
ZEND_METHOD(Memcached, isPristine);
+ZEND_METHOD(Memcached, checkKey);
#if defined(HAVE_MEMCACHED_PROTOCOL)
ZEND_METHOD(MemcachedServer, run);
#endif
@@ -392,6 +397,7 @@ static const zend_function_entry class_Memcached_methods[] = {
#endif
ZEND_ME(Memcached, isPersistent, arginfo_class_Memcached_isPersistent, ZEND_ACC_PUBLIC)
ZEND_ME(Memcached, isPristine, arginfo_class_Memcached_isPristine, ZEND_ACC_PUBLIC)
+ ZEND_ME(Memcached, checkKey, arginfo_class_Memcached_checkKey, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
diff --git a/tests/check_key.phpt b/tests/check_key.phpt
new file mode 100644
index 00000000..74ec6214
--- /dev/null
+++ b/tests/check_key.phpt
@@ -0,0 +1,132 @@
+--TEST--
+Memcached::checkKey()
+--SKIPIF--
+
+--FILE--
+ false,
+ Memcached::OPT_VERIFY_KEY => true
+ ));
+
+$keys = [
+ 'foo',
+ 'foo bar',
+ str_repeat('a',65),
+ str_repeat('b',250),
+ str_repeat('c',251),
+ 'Montréal',
+ 'København',
+ 'Düsseldorf',
+ 'Kraków',
+ 'İstanbul',
+ 'ﺎﺨﺘﺑﺍﺭ PHP',
+ '測試',
+ 'Тестирование',
+ 'پی ایچ پی کی جانچ ہو رہی ہے',
+ 'Testataan PHP: tä',
+ 'Að prófa PHP',
+ 'د پی ایچ پی ازمول',
+ 'Pruvà PHP'
+];
+foreach($keys as $key) {
+ echo "Checking \"$key\"" . PHP_EOL;
+ echo "MEMC_CHECK_KEY: ";
+ var_dump($m->checkKey($key));
+ echo "libmemcached: ";
+ var_dump($m->set($key, "this is a test"));
+ var_dump($m->getResultMessage());
+ echo "\n";
+}
+--EXPECT--
+Checking "foo"
+MEMC_CHECK_KEY: bool(true)
+libmemcached: bool(true)
+string(7) "SUCCESS"
+
+Checking "foo bar"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+MEMC_CHECK_KEY: bool(true)
+libmemcached: bool(true)
+string(7) "SUCCESS"
+
+Checking "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+MEMC_CHECK_KEY: bool(true)
+libmemcached: bool(true)
+string(7) "SUCCESS"
+
+Checking "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "Montréal"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "København"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "Düsseldorf"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "Kraków"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "İstanbul"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "ﺎﺨﺘﺑﺍﺭ PHP"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "測試"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "Тестирование"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "پی ایچ پی کی جانچ ہو رہی ہے"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "Testataan PHP: tä"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "Að prófa PHP"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "د پی ایچ پی ازمول"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+
+Checking "Pruvà PHP"
+MEMC_CHECK_KEY: bool(false)
+libmemcached: bool(false)
+string(46) "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE"
+