Skip to content

Commit

Permalink
fix: usage of '@' in connStrings
Browse files Browse the repository at this point in the history
  • Loading branch information
MitchellWeg committed Oct 31, 2022
1 parent b08f617 commit e89c590
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 10 deletions.
102 changes: 92 additions & 10 deletions src/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"regexp"
"strconv"
"strings"
)

func init() {
Expand Down Expand Up @@ -37,22 +38,87 @@ func (*Driver) Open(name string) (driver.Conn, error) {
}

func parseDSN(name string) (config, error) {
re := regexp.MustCompile(`^((?P<username>[^:]+?)(:(?P<password>[^@]+?))?@)?(?P<hostname>[a-zA-Z0-9.]+?)(:(?P<port>\d+?))?/(?P<database>.+?)$`)
ipv6_re := regexp.MustCompile(`^((?P<username>[^:]+?)(:(?P<password>[^@]+?))?@)?\[(?P<hostname>(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))+?)\](:(?P<port>\d+?))?\/(?P<database>.+?)$`)
m := make([]string, 0)
n := make([]string, 0)

if re.MatchString(name) {
m = re.FindAllStringSubmatch(name, -1)[0]
n = re.SubexpNames()
return getConfig(m, n, false), nil
} else if ipv6_re.MatchString(name) {

if ipv6_re.MatchString(name) {
m := make([]string, 0)
n := make([]string, 0)
m = ipv6_re.FindAllStringSubmatch(name, -1)[0]
n = ipv6_re.SubexpNames()
return getConfig(m, n, true), nil
}

return config{}, fmt.Errorf("Invalid DSN")
c := config{
Hostname: "localhost",
Port: 50000,
}

reversed := reverse(name)

host, creds, _ := Cut(reversed, "@") // host, creds, found

configWithHost, err := parseHost(reverse(host), c)

if err != nil {
return config{}, fmt.Errorf("Invalid DSN")
}

newConfig, err := parseCreds(reverse(creds), configWithHost)

if err != nil {
return config{}, fmt.Errorf("Invalid DSN")
}

return newConfig, nil
}

func parseCreds(creds string, c config) (config, error) {
username, password, found := Cut(creds, ":")

c.Username = username
c.Password = ""

if found {
if username == "" {
return c, fmt.Errorf("Invalid DSN")
}

c.Password = password
}

return c, nil
}

func parseHost(host string, c config) (config, error) {
host, dbName, found := Cut(host, "/")

if !found {
return c, fmt.Errorf("Invalid DSN")
}

if host == "" {
return c, fmt.Errorf("Invalid DSN")
}

c.Database = dbName

hostname, port, found := Cut(host, ":")

if !found {
return c, nil
}

c.Hostname = hostname

port_num, err := strconv.Atoi(port)

if err != nil {
return c, fmt.Errorf("Invalid DSN")
}

c.Port = port_num

return c, nil
}

func getConfig(m []string, n []string, ipv6 bool) config {
Expand Down Expand Up @@ -81,3 +147,19 @@ func getConfig(m []string, n []string, ipv6 bool) config {

return c
}

func reverse(in string) string {
var sb strings.Builder
runes := []rune(in)
for i := len(runes) - 1; 0 <= i; i-- {
sb.WriteRune(runes[i])
}
return sb.String()
}

func Cut(s, sep string) (before, after string, found bool) {
if i := strings.Index(s, sep); i >= 0 {
return s[:i], s[i+len(sep):], true
}
return s, "", false
}
1 change: 1 addition & 0 deletions src/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func TestParseDSN(t *testing.T) {
[]string{"me:secret@localhost:1234/testdb", "me", "secret", "localhost", "1234", "testdb"},
[]string{"me@localhost:1234/testdb", "me", "", "localhost", "1234", "testdb"},
[]string{"localhost:1234/testdb", "", "", "localhost", "1234", "testdb"},
[]string{"user:P@sswordWith@@localhost:50000/db", "user", "P@sswordWith@", "localhost", "50000", "db"},
[]string{"localhost/testdb", "", "", "localhost", "50000", "testdb"},
[]string{"localhost"},
[]string{"/testdb"},
Expand Down

0 comments on commit e89c590

Please sign in to comment.