mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-12 14:18:32 +00:00
Use regex to split DSN parts to allow commas in values.
This commit is contained in:
@@ -32,6 +32,17 @@ use Data::Dumper;
|
|||||||
$Data::Dumper::Indent = 0;
|
$Data::Dumper::Indent = 0;
|
||||||
$Data::Dumper::Quotekeys = 0;
|
$Data::Dumper::Quotekeys = 0;
|
||||||
|
|
||||||
|
# Passwords may contain commas.
|
||||||
|
# https://bugs.launchpad.net/percona-toolkit/+bug/886077
|
||||||
|
my $dsn_sep = qr/ # Separate DSN parts by
|
||||||
|
, # comma
|
||||||
|
(?= # followed by either
|
||||||
|
(?:\Z # the end of the string, or
|
||||||
|
|[a-zA-Z]= # start of another DSN part
|
||||||
|
)
|
||||||
|
)
|
||||||
|
/x;
|
||||||
|
|
||||||
eval {
|
eval {
|
||||||
require DBI;
|
require DBI;
|
||||||
};
|
};
|
||||||
@@ -126,7 +137,7 @@ sub parse {
|
|||||||
my $opts = $self->{opts};
|
my $opts = $self->{opts};
|
||||||
|
|
||||||
# Parse given props
|
# Parse given props
|
||||||
foreach my $dsn_part ( split(/,/, $dsn) ) {
|
foreach my $dsn_part ( split($dsn_sep, $dsn) ) {
|
||||||
if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) {
|
if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) {
|
||||||
# Handle the typical DSN parts like h=host, P=3306, etc.
|
# Handle the typical DSN parts like h=host, P=3306, etc.
|
||||||
$given_props{$prop_key} = $prop_val;
|
$given_props{$prop_key} = $prop_val;
|
||||||
|
@@ -9,12 +9,14 @@ BEGIN {
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings FATAL => 'all';
|
use warnings FATAL => 'all';
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use Test::More tests => 27;
|
use Test::More tests => 33;
|
||||||
|
|
||||||
use DSNParser;
|
use DSNParser;
|
||||||
use OptionParser;
|
use OptionParser;
|
||||||
use PerconaTest;
|
use PerconaTest;
|
||||||
|
|
||||||
|
use Data::Dumper;
|
||||||
|
|
||||||
my $opts = [
|
my $opts = [
|
||||||
{
|
{
|
||||||
key => 'A',
|
key => 'A',
|
||||||
@@ -82,6 +84,20 @@ is_deeply(
|
|||||||
'Basic DSN'
|
'Basic DSN'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
is_deeply(
|
||||||
|
$dp->parse('S=/tmp/sock'),
|
||||||
|
{ u => undef,
|
||||||
|
p => undef,
|
||||||
|
S => '/tmp/sock',
|
||||||
|
h => undef,
|
||||||
|
P => undef,
|
||||||
|
F => undef,
|
||||||
|
D => undef,
|
||||||
|
A => undef,
|
||||||
|
},
|
||||||
|
'Basic DSN with one part'
|
||||||
|
);
|
||||||
|
|
||||||
is_deeply(
|
is_deeply(
|
||||||
$dp->parse('u=a,p=b,A=utf8'),
|
$dp->parse('u=a,p=b,A=utf8'),
|
||||||
{ u => 'a',
|
{ u => 'a',
|
||||||
@@ -392,6 +408,8 @@ is_deeply(
|
|||||||
'Copy DSN and overwrite destination'
|
'Copy DSN and overwrite destination'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
pop @$opts; # Remove t part.
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Issue 93: DBI error messages can include full SQL
|
# Issue 93: DBI error messages can include full SQL
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
@@ -461,6 +479,41 @@ SKIP: {
|
|||||||
diag(`$trunk/sandbox/stop-sandbox 12348 >/dev/null`);
|
diag(`$trunk/sandbox/stop-sandbox 12348 >/dev/null`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# #############################################################################
|
||||||
|
# Passwords with commas don't work, expose part of password
|
||||||
|
# https://bugs.launchpad.net/percona-toolkit/+bug/886077
|
||||||
|
# #############################################################################
|
||||||
|
$dp = new DSNParser(opts => $opts);
|
||||||
|
|
||||||
|
sub test_password_comma {
|
||||||
|
my ($dsn_string, $pass, $port, $name) = @_;
|
||||||
|
my $dsn = $dp->parse($dsn_string);
|
||||||
|
is_deeply(
|
||||||
|
$dsn,
|
||||||
|
{ u => 'a',
|
||||||
|
p => $pass,
|
||||||
|
S => undef,
|
||||||
|
h => undef,
|
||||||
|
P => $port,
|
||||||
|
F => undef,
|
||||||
|
D => undef,
|
||||||
|
A => undef,
|
||||||
|
},
|
||||||
|
"$name (bug 886077)"
|
||||||
|
) or diag(Dumper($dsn));
|
||||||
|
}
|
||||||
|
|
||||||
|
my @password_commas = (
|
||||||
|
['u=a,p=foo,xxx,P=12345', 'foo,xxx', 12345, 'Pass with comma'],
|
||||||
|
['u=a,p=foo,xxx', 'foo,xxx', undef, 'Pass with comma, last part'],
|
||||||
|
['u=a,p=foo,,P=12345', 'foo,', 12345, 'Pass ends with comma'],
|
||||||
|
['u=a,p=foo,,', 'foo,', undef, 'Pass ends with comma, last part'],
|
||||||
|
['u=a,p=,,P=12345', ',', 12345, 'Pass is a comma'],
|
||||||
|
);
|
||||||
|
foreach my $password_comma ( @password_commas ) {
|
||||||
|
test_password_comma(@$password_comma);
|
||||||
|
}
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Done.
|
# Done.
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
Reference in New Issue
Block a user