From dce78965300e5d39d580e0f318a3849636a3874e Mon Sep 17 00:00:00 2001 From: zhijian Date: Tue, 26 Sep 2023 12:08:15 +0800 Subject: [PATCH 1/5] dont escape for mysql password --- pkg/meta/sql.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/meta/sql.go b/pkg/meta/sql.go index bc686018fde1..62af001893fb 100644 --- a/pkg/meta/sql.go +++ b/pkg/meta/sql.go @@ -215,6 +215,22 @@ func newSQLMeta(driver, addr string, conf *Config) (Meta, error) { } } } + + // escaping is not necessary for mysql password https://github.com/go-sql-driver/mysql#password + if driver == "mysql" { + colonIndex := strings.Index(addr, ":") + atIndex := strings.LastIndex(addr, "@") + pwd := addr[colonIndex+1 : atIndex] + parse, err := url.Parse("mysql://root:" + pwd + "@127.0.0.1") + if err != nil { + return nil, fmt.Errorf("parse url %s failed: %s", addr, err) + } + originPwd, ok := parse.User.Password() + if ok { + addr = fmt.Sprintf("%s:%s%s", addr[:colonIndex], originPwd, addr[atIndex:]) + } + } + engine, err := xorm.NewEngine(driver, addr) if err != nil { return nil, fmt.Errorf("unable to use data source %s: %s", driver, err) From ede82c715836ce6b2bbdc3e2371ec049798195d5 Mon Sep 17 00:00:00 2001 From: zhijian Date: Tue, 26 Sep 2023 13:01:37 +0800 Subject: [PATCH 2/5] improve desc --- cmd/format.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/format.go b/cmd/format.go index 976f12908198..e5f607c125e1 100644 --- a/cmd/format.go +++ b/cmd/format.go @@ -70,6 +70,16 @@ $ juicefs format mysql://jfs:mypassword@(127.0.0.1:3306)/juicefs myjfs # A safer alternative $ META_PASSWORD=mypassword juicefs format mysql://jfs:@(127.0.0.1:3306)/juicefs myjfs +# MySQL password containing special characters +$ juicefs format 'mysql://jfs:123@45@(127.0.0.1:3306)/juicefs' myjfs +# or +$ META_PASSWORD=123@45 juicefs format mysql://jfs:@(127.0.0.1:3306)/juicefs myjfs + +# PostgreSQL password containing special characters +$ juicefs format 'postgres://jfs:123@45@127.0.0.1:5432/juicefs' myjfs +# or +$ META_PASSWORD=123@45 juicefs format 'postgres://jfs:@127.0.0.1:5432/juicefs' myjfs + # Create a volume with "quota" enabled $ juicefs format sqlite3://myjfs.db myjfs --inodes 1000000 --capacity 102400 From d03f36274903e2e04e356879eecc43171c596db9 Mon Sep 17 00:00:00 2001 From: zhijian Date: Wed, 27 Sep 2023 10:39:01 +0800 Subject: [PATCH 3/5] Revert "improve desc" This reverts commit ede82c715836ce6b2bbdc3e2371ec049798195d5. --- cmd/format.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cmd/format.go b/cmd/format.go index e5f607c125e1..976f12908198 100644 --- a/cmd/format.go +++ b/cmd/format.go @@ -70,16 +70,6 @@ $ juicefs format mysql://jfs:mypassword@(127.0.0.1:3306)/juicefs myjfs # A safer alternative $ META_PASSWORD=mypassword juicefs format mysql://jfs:@(127.0.0.1:3306)/juicefs myjfs -# MySQL password containing special characters -$ juicefs format 'mysql://jfs:123@45@(127.0.0.1:3306)/juicefs' myjfs -# or -$ META_PASSWORD=123@45 juicefs format mysql://jfs:@(127.0.0.1:3306)/juicefs myjfs - -# PostgreSQL password containing special characters -$ juicefs format 'postgres://jfs:123@45@127.0.0.1:5432/juicefs' myjfs -# or -$ META_PASSWORD=123@45 juicefs format 'postgres://jfs:@127.0.0.1:5432/juicefs' myjfs - # Create a volume with "quota" enabled $ juicefs format sqlite3://myjfs.db myjfs --inodes 1000000 --capacity 102400 From 46972e12e1c281491992fa90217fe975431cefcf Mon Sep 17 00:00:00 2001 From: zhijian Date: Wed, 27 Sep 2023 12:11:42 +0800 Subject: [PATCH 4/5] add test --- pkg/meta/sql.go | 24 +++++++++++----------- pkg/meta/sql_test.go | 47 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/pkg/meta/sql.go b/pkg/meta/sql.go index 62af001893fb..f8538cc7874b 100644 --- a/pkg/meta/sql.go +++ b/pkg/meta/sql.go @@ -198,6 +198,18 @@ type dbSnap struct { chunk map[string]*chunk } +func recoveryMysqlPwd(addr string) string { + colonIndex := strings.Index(addr, ":") + atIndex := strings.LastIndex(addr, "@") + pwd := addr[colonIndex+1 : atIndex] + if parse, err := url.Parse("mysql://root:" + pwd + "@127.0.0.1"); err == nil { + if originPwd, ok := parse.User.Password(); ok { + addr = fmt.Sprintf("%s:%s%s", addr[:colonIndex], originPwd, addr[atIndex:]) + } + } + return addr +} + func newSQLMeta(driver, addr string, conf *Config) (Meta, error) { var searchPath string if driver == "postgres" { @@ -218,17 +230,7 @@ func newSQLMeta(driver, addr string, conf *Config) (Meta, error) { // escaping is not necessary for mysql password https://github.com/go-sql-driver/mysql#password if driver == "mysql" { - colonIndex := strings.Index(addr, ":") - atIndex := strings.LastIndex(addr, "@") - pwd := addr[colonIndex+1 : atIndex] - parse, err := url.Parse("mysql://root:" + pwd + "@127.0.0.1") - if err != nil { - return nil, fmt.Errorf("parse url %s failed: %s", addr, err) - } - originPwd, ok := parse.User.Password() - if ok { - addr = fmt.Sprintf("%s:%s%s", addr[:colonIndex], originPwd, addr[atIndex:]) - } + addr = recoveryMysqlPwd(addr) } engine, err := xorm.NewEngine(driver, addr) diff --git a/pkg/meta/sql_test.go b/pkg/meta/sql_test.go index 7a3106f707a1..3b74e9f51c8f 100644 --- a/pkg/meta/sql_test.go +++ b/pkg/meta/sql_test.go @@ -57,3 +57,50 @@ func TestPostgreSQLClientWithSearchPath(t *testing.T) { //skip mutate t.Fatalf("TestPostgreSQLClientWithSearchPath error: %s", err) } } + +func TestRecoveryMysqlPwd(t *testing.T) { //skip mutate + testCase := []struct { + addr string + expect string + }{ + // no special char + {"root:password@localhost:3306/db1", + "root:password@localhost:3306/db1", + }, + + // set from env @ + {"root:pass%40word@localhost:3306/db1", + "root:pass@word@localhost:3306/db1", + }, + + // direct pass special char @ + {"root:pass@word@localhost:3306/db1", + "root:pass@word@localhost:3306/db1", + }, + + // set from env | + {"root:pass%7Cword@localhost:3306/db1", + "root:pass|word@localhost:3306/db1", + }, + + // direct pass special char | + {"root:pass|word@localhost:3306/db1", + "root:pass|word@localhost:3306/db1", + }, + + // set from env : + {"root:pass%3Aword@localhost:3306/db1", + "root:pass:word@localhost:3306/db1", + }, + + // direct pass special char : + {"root:pass:word@localhost:3306/db1", + "root:pass:word@localhost:3306/db1", + }, + } + for _, tc := range testCase { + if got := recoveryMysqlPwd(tc.addr); got != tc.expect { + t.Fatalf("recoveryMysqlPwd error: expect %s but got %s", tc.expect, got) + } + } +} From 402df6b65c7d0e8c98e6687a10f2b2250ed5c341 Mon Sep 17 00:00:00 2001 From: zhijian Date: Wed, 27 Sep 2023 15:40:02 +0800 Subject: [PATCH 5/5] fix no password --- pkg/meta/sql.go | 10 ++++++---- pkg/meta/sql_test.go | 45 ++++++++++++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/pkg/meta/sql.go b/pkg/meta/sql.go index f8538cc7874b..6207bb75579b 100644 --- a/pkg/meta/sql.go +++ b/pkg/meta/sql.go @@ -201,10 +201,12 @@ type dbSnap struct { func recoveryMysqlPwd(addr string) string { colonIndex := strings.Index(addr, ":") atIndex := strings.LastIndex(addr, "@") - pwd := addr[colonIndex+1 : atIndex] - if parse, err := url.Parse("mysql://root:" + pwd + "@127.0.0.1"); err == nil { - if originPwd, ok := parse.User.Password(); ok { - addr = fmt.Sprintf("%s:%s%s", addr[:colonIndex], originPwd, addr[atIndex:]) + if colonIndex != -1 && colonIndex < atIndex { + pwd := addr[colonIndex+1 : atIndex] + if parse, err := url.Parse("mysql://root:" + pwd + "@127.0.0.1"); err == nil { + if originPwd, ok := parse.User.Password(); ok { + addr = fmt.Sprintf("%s:%s%s", addr[:colonIndex], originPwd, addr[atIndex:]) + } } } return addr diff --git a/pkg/meta/sql_test.go b/pkg/meta/sql_test.go index 3b74e9f51c8f..ebb39f2ca407 100644 --- a/pkg/meta/sql_test.go +++ b/pkg/meta/sql_test.go @@ -63,39 +63,56 @@ func TestRecoveryMysqlPwd(t *testing.T) { //skip mutate addr string expect string }{ + // no password + {"root@(localhost:3306)/db1", + "root@(localhost:3306)/db1", + }, + // no password + {"root:@(localhost:3306)/db1", + "root:@(localhost:3306)/db1", + }, + + {"root::@@(localhost:3306)/db1", + "root::@@(localhost:3306)/db1", + }, + + {"root:@:@(localhost:3306)/db1", + "root:@:@(localhost:3306)/db1", + }, + // no special char - {"root:password@localhost:3306/db1", - "root:password@localhost:3306/db1", + {"root:password@(localhost:3306)/db1", + "root:password@(localhost:3306)/db1", }, // set from env @ - {"root:pass%40word@localhost:3306/db1", - "root:pass@word@localhost:3306/db1", + {"root:pass%40word@(localhost:3306)/db1", + "root:pass@word@(localhost:3306)/db1", }, // direct pass special char @ - {"root:pass@word@localhost:3306/db1", - "root:pass@word@localhost:3306/db1", + {"root:pass@word@(localhost:3306)/db1", + "root:pass@word@(localhost:3306)/db1", }, // set from env | - {"root:pass%7Cword@localhost:3306/db1", - "root:pass|word@localhost:3306/db1", + {"root:pass%7Cword@(localhost:3306)/db1", + "root:pass|word@(localhost:3306)/db1", }, // direct pass special char | - {"root:pass|word@localhost:3306/db1", - "root:pass|word@localhost:3306/db1", + {"root:pass|word@(localhost:3306)/db1", + "root:pass|word@(localhost:3306)/db1", }, // set from env : - {"root:pass%3Aword@localhost:3306/db1", - "root:pass:word@localhost:3306/db1", + {"root:pass%3Aword@(localhost:3306)/db1", + "root:pass:word@(localhost:3306)/db1", }, // direct pass special char : - {"root:pass:word@localhost:3306/db1", - "root:pass:word@localhost:3306/db1", + {"root:pass:word@(localhost:3306)/db1", + "root:pass:word@(localhost:3306)/db1", }, } for _, tc := range testCase {