MXS-960: In BRL, accept passwords with "," in them.
strtok_r replaced with a function that ignores delims that appear within any of the MySQL quotes.
This commit is contained in:
		@ -84,6 +84,7 @@
 | 
				
			|||||||
#include <version.h>
 | 
					#include <version.h>
 | 
				
			||||||
#include <zlib.h>
 | 
					#include <zlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char* get_next_token(char *str, const char* delim, char **saveptr);
 | 
				
			||||||
extern int load_mysql_users(SERVICE *service);
 | 
					extern int load_mysql_users(SERVICE *service);
 | 
				
			||||||
extern void blr_master_close(ROUTER_INSTANCE* router);
 | 
					extern void blr_master_close(ROUTER_INSTANCE* router);
 | 
				
			||||||
extern int blr_file_new_binlog(ROUTER_INSTANCE *router, char *file);
 | 
					extern int blr_file_new_binlog(ROUTER_INSTANCE *router, char *file);
 | 
				
			||||||
@ -4282,6 +4283,148 @@ blr_set_master_password(ROUTER_INSTANCE *router, char *password)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get next token
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Works exactly like strtok_t except that a delim character which appears
 | 
				
			||||||
 | 
					 * anywhere within quotes is ignored. For instance, if delim is "," then
 | 
				
			||||||
 | 
					 * a string like "MASTER_USER='maxscale_repl_user',MASTER_PASSWORD='a,a'"
 | 
				
			||||||
 | 
					 * will be tokenized into the following two tokens:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   MASTER_USER='maxscale_repl_user'
 | 
				
			||||||
 | 
					 *   MASTER_PASSWORD='a,a'
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see strtok_r
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static char* get_next_token(char *str, const char* delim, char **saveptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (str)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        *saveptr = str;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!*saveptr)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool delim_found = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Skip any delims in the beginning.
 | 
				
			||||||
 | 
					    while (**saveptr && delim_found)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const char* d = delim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (*d)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (*d == **saveptr)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ++d;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (*d == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            delim_found = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ++*saveptr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!**saveptr)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delim_found = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char *token = *saveptr;
 | 
				
			||||||
 | 
					    char *p = *saveptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char quote = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (*p && !delim_found)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        switch (*p)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        case '\'':
 | 
				
			||||||
 | 
					        case '"':
 | 
				
			||||||
 | 
					        case '`':
 | 
				
			||||||
 | 
					            if (!quote)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                quote = *p;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (quote == *p)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                quote = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            if (!quote)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const char *d = delim;
 | 
				
			||||||
 | 
					                while (*d && !delim_found)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (*p == *d)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        delim_found = true;
 | 
				
			||||||
 | 
					                        *p = 0;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        ++d;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ++p;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*p == 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        *saveptr = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (delim_found)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        *saveptr = p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delim_found = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (**saveptr && delim_found)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const char *d = delim;
 | 
				
			||||||
 | 
					            while (*d)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (**saveptr == *d)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ++d;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (*d == 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                delim_found = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ++*saveptr;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return token;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Parse a CHANGE MASTER TO SQL command
 | 
					 * Parse a CHANGE MASTER TO SQL command
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -4296,7 +4439,7 @@ blr_parse_change_master_command(char *input, char *error_string, CHANGE_MASTER_O
 | 
				
			|||||||
    char *sep = ",";
 | 
					    char *sep = ",";
 | 
				
			||||||
    char *word, *brkb;
 | 
					    char *word, *brkb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((word = strtok_r(input, sep, &brkb)) == NULL)
 | 
					    if ((word = get_next_token(input, sep, &brkb)) == NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        sprintf(error_string, "Unable to parse query [%s]", input);
 | 
					        sprintf(error_string, "Unable to parse query [%s]", input);
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@ -4310,7 +4453,7 @@ blr_parse_change_master_command(char *input, char *error_string, CHANGE_MASTER_O
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while ((word = strtok_r(NULL, sep, &brkb)) != NULL)
 | 
					    while ((word = get_next_token(NULL, sep, &brkb)) != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /* parse options key=val */
 | 
					        /* parse options key=val */
 | 
				
			||||||
        if (blr_handle_change_master_token(word, error_string, config))
 | 
					        if (blr_handle_change_master_token(word, error_string, config))
 | 
				
			||||||
@ -4334,12 +4477,12 @@ static int
 | 
				
			|||||||
blr_handle_change_master_token(char *input, char *error, CHANGE_MASTER_OPTIONS *config)
 | 
					blr_handle_change_master_token(char *input, char *error, CHANGE_MASTER_OPTIONS *config)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* space+TAB+= */
 | 
					    /* space+TAB+= */
 | 
				
			||||||
    char *sep = " 	=";
 | 
					    char *sep = " \t=";
 | 
				
			||||||
    char *word, *brkb;
 | 
					    char *word, *brkb;
 | 
				
			||||||
    char *value = NULL;
 | 
					    char *value = NULL;
 | 
				
			||||||
    char **option_field = NULL;
 | 
					    char **option_field = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((word = strtok_r(input, sep, &brkb)) == NULL)
 | 
					    if ((word = get_next_token(input, sep, &brkb)) == NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        sprintf(error, "error parsing %s", brkb);
 | 
					        sprintf(error, "error parsing %s", brkb);
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@ -4378,7 +4521,7 @@ static char *
 | 
				
			|||||||
blr_get_parsed_command_value(char *input)
 | 
					blr_get_parsed_command_value(char *input)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* space+TAB+= */
 | 
					    /* space+TAB+= */
 | 
				
			||||||
    char *sep = "	 =";
 | 
					    char *sep = " \t=";
 | 
				
			||||||
    char *ret = NULL;
 | 
					    char *ret = NULL;
 | 
				
			||||||
    char *word;
 | 
					    char *word;
 | 
				
			||||||
    char *value = NULL;
 | 
					    char *value = NULL;
 | 
				
			||||||
@ -4392,7 +4535,7 @@ blr_get_parsed_command_value(char *input)
 | 
				
			|||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((word = strtok_r(NULL, sep, &input)) != NULL)
 | 
					    if ((word = get_next_token(NULL, sep, &input)) != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        char *ptr;
 | 
					        char *ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user