@@ -4257,87 +4257,100 @@ redis_geosearchstore_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
42574257 return SUCCESS ;
42584258}
42594259
4260+ /* MIGRATE host port <key | ""> destination-db timeout [COPY] [REPLACE]
4261+ [[AUTH password] | [AUTH2 username password]] [KEYS key [key ...]]
4262+
4263+ Starting with Redis version 3.0.0: Added the COPY and REPLACE options.
4264+ Starting with Redis version 3.0.6: Added the KEYS option.
4265+ Starting with Redis version 4.0.7: Added the AUTH option.
4266+ Starting with Redis version 6.0.0: Added the AUTH2 option.
4267+ */
4268+
42604269/* MIGRATE */
42614270int redis_migrate_cmd (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
42624271 char * * cmd , int * cmd_len , short * slot , void * * ctx )
42634272{
4264- smart_string cmdstr = {0 };
4265- char * host , * key ;
4266- int argc , keyfree ;
4267- zval * z_keys , * z_key ;
4268- size_t hostlen , keylen ;
4269- zend_long destdb , port , timeout ;
4273+ zend_string * host = NULL , * key = NULL , * user = NULL , * pass = NULL ;
4274+ zend_long destdb = 0 , port = 0 , timeout = 0 ;
4275+ zval * zkeys = NULL , * zkey , * zauth = NULL ;
42704276 zend_bool copy = 0 , replace = 0 ;
4271- zend_string * zstr ;
4277+ smart_string cmdstr = {0 };
4278+ int argc ;
42724279
4273- if (zend_parse_parameters (ZEND_NUM_ARGS (), "slzll|bb" , & host , & hostlen , & port ,
4274- & z_keys , & destdb , & timeout , & copy , & replace ) == FAILURE )
4275- {
4276- return FAILURE ;
4280+ ZEND_PARSE_PARAMETERS_START (5 , 8 )
4281+ Z_PARAM_STR (host )
4282+ Z_PARAM_LONG (port )
4283+ Z_PARAM_ZVAL (zkeys )
4284+ Z_PARAM_LONG (destdb )
4285+ Z_PARAM_LONG (timeout )
4286+ Z_PARAM_OPTIONAL
4287+ Z_PARAM_BOOL (copy )
4288+ Z_PARAM_BOOL (replace )
4289+ Z_PARAM_ZVAL_OR_NULL (zauth )
4290+ ZEND_PARSE_PARAMETERS_END_EX (return FAILURE );
4291+
4292+ /* Sanity check on our optional AUTH argument */
4293+ if (zauth && redis_extract_auth_info (zauth , & user , & pass ) == FAILURE ) {
4294+ php_error_docref (NULL , E_WARNING , "AUTH must be a string or an array with one or two strings" );
4295+ user = pass = NULL ;
42774296 }
42784297
42794298 /* Protect against being passed an array with zero elements */
4280- if (Z_TYPE_P (z_keys ) == IS_ARRAY && zend_hash_num_elements (Z_ARRVAL_P (z_keys )) == 0 ) {
4299+ if (Z_TYPE_P (zkeys ) == IS_ARRAY && zend_hash_num_elements (Z_ARRVAL_P (zkeys )) == 0 ) {
42814300 php_error_docref (NULL , E_WARNING , "Keys array cannot be empty" );
42824301 return FAILURE ;
42834302 }
42844303
42854304 /* host, port, key|"", dest-db, timeout, [copy, replace] [KEYS key1..keyN] */
4286- argc = 5 + copy + replace ;
4287- if (Z_TYPE_P (z_keys ) == IS_ARRAY ) {
4305+ argc = 5 + copy + replace + ( user || pass ? 1 : 0 ) + ( user != NULL ) + ( pass != NULL ) ;
4306+ if (Z_TYPE_P (zkeys ) == IS_ARRAY ) {
42884307 /* +1 for the "KEYS" argument itself */
4289- argc += 1 + zend_hash_num_elements (Z_ARRVAL_P (z_keys ));
4308+ argc += 1 + zend_hash_num_elements (Z_ARRVAL_P (zkeys ));
42904309 }
42914310
42924311 /* Initialize MIGRATE command with host and port */
42934312 REDIS_CMD_INIT_SSTR_STATIC (& cmdstr , argc , "MIGRATE" );
4294- redis_cmd_append_sstr (& cmdstr , host , hostlen );
4313+ redis_cmd_append_sstr_zstr (& cmdstr , host );
42954314 redis_cmd_append_sstr_long (& cmdstr , port );
42964315
42974316 /* If passed a keys array the keys come later, otherwise pass the key to
42984317 * migrate here */
4299- if (Z_TYPE_P (z_keys ) == IS_ARRAY ) {
4318+ if (Z_TYPE_P (zkeys ) == IS_ARRAY ) {
43004319 REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "" );
43014320 } else {
4302- /* Grab passed value as a string */
4303- zstr = zval_get_string (z_keys );
4304-
4305- /* We may need to prefix our string */
4306- key = ZSTR_VAL (zstr );
4307- keylen = ZSTR_LEN (zstr );
4308- keyfree = redis_key_prefix (redis_sock , & key , & keylen );
4309-
4310- /* Add key to migrate */
4311- redis_cmd_append_sstr (& cmdstr , key , keylen );
4312-
4313- zend_string_release (zstr );
4314- if (keyfree ) efree (key );
4321+ key = redis_key_prefix_zval (redis_sock , zkeys );
4322+ redis_cmd_append_sstr_zstr (& cmdstr , key );
4323+ zend_string_release (key );
43154324 }
43164325
43174326 redis_cmd_append_sstr_long (& cmdstr , destdb );
43184327 redis_cmd_append_sstr_long (& cmdstr , timeout );
43194328 REDIS_CMD_APPEND_SSTR_OPT_STATIC (& cmdstr , copy , "COPY" );
43204329 REDIS_CMD_APPEND_SSTR_OPT_STATIC (& cmdstr , replace , "REPLACE" );
43214330
4331+ if (user && pass ) {
4332+ REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "AUTH2" );
4333+ redis_cmd_append_sstr_zstr (& cmdstr , user );
4334+ redis_cmd_append_sstr_zstr (& cmdstr , pass );
4335+ } else if (pass ) {
4336+ REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "AUTH" );
4337+ redis_cmd_append_sstr_zstr (& cmdstr , pass );
4338+ }
4339+
43224340 /* Append actual keys if we've got a keys array */
4323- if (Z_TYPE_P (z_keys ) == IS_ARRAY ) {
4341+ if (Z_TYPE_P (zkeys ) == IS_ARRAY ) {
43244342 REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "KEYS" );
43254343
4326- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (z_keys ), z_key ) {
4327- zstr = zval_get_string (z_key );
4328-
4329- key = ZSTR_VAL (zstr );
4330- keylen = ZSTR_LEN (zstr );
4331- keyfree = redis_key_prefix (redis_sock , & key , & keylen );
4332-
4333- /* Append the key */
4334- redis_cmd_append_sstr (& cmdstr , key , keylen );
4335-
4336- zend_string_release (zstr );
4337- if (keyfree ) efree (key );
4344+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (zkeys ), zkey ) {
4345+ key = redis_key_prefix_zval (redis_sock , zkey );
4346+ redis_cmd_append_sstr_zstr (& cmdstr , key );
4347+ zend_string_release (key );
43384348 } ZEND_HASH_FOREACH_END ();
43394349 }
43404350
4351+ if (user ) zend_string_release (user );
4352+ if (pass ) zend_string_release (pass );
4353+
43414354 * cmd = cmdstr .c ;
43424355 * cmd_len = cmdstr .len ;
43434356 return SUCCESS ;
0 commit comments