From ae1d50d19a4ffe1b527429978ebff6fdd35b71e8 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Tue, 4 Apr 2017 19:40:46 -0400 Subject: [PATCH] models/mirror: escape credentials before write mirror address (#4014) Special characters such as '@', ';', '#' and ':' could occur in password portion of credentials, which breaks the interpretation and saves 'config' file in with extra characters that are not recognized by Git (due to INI library). --- gogs.go | 2 +- models/mirror.go | 30 +++++++++++++++++++++++++++++- models/mirror_test.go | 28 ++++++++++++++++++++++++++++ templates/.VERSION | 2 +- 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 models/mirror_test.go diff --git a/gogs.go b/gogs.go index ccf1b6ab..dfdbe528 100644 --- a/gogs.go +++ b/gogs.go @@ -16,7 +16,7 @@ import ( "github.com/gogits/gogs/pkg/setting" ) -const APP_VER = "0.11.2.0404" +const APP_VER = "0.11.3.0404" func init() { setting.AppVer = APP_VER diff --git a/models/mirror.go b/models/mirror.go index 4820520e..46ef7452 100644 --- a/models/mirror.go +++ b/models/mirror.go @@ -6,6 +6,7 @@ package models import ( "fmt" + "net/url" "strings" "time" @@ -119,6 +120,33 @@ func (m *Mirror) FullAddress() string { return m.address } +// escapeCredentials returns mirror address with escaped credentials. +func escapeMirrorCredentials(addr string) string { + // Find end of credentials (start of path) + end := strings.LastIndex(addr, "@") + if end == -1 { + return addr + } + + // Find delimiter of credentials (end of username) + start := strings.Index(addr, "://") + if start == -1 { + return addr + } + start += 3 + delim := strings.Index(addr[:start], ":") + if delim == -1 { + return addr + } + delim += 1 + + if start+delim > end { + return addr // No password portion presented + } + + return addr[:start+delim] + url.QueryEscape(addr[start+delim:end]) + addr[end:] +} + // SaveAddress writes new address to Git repository config. func (m *Mirror) SaveAddress(addr string) error { configPath := m.Repo.GitConfigPath() @@ -127,7 +155,7 @@ func (m *Mirror) SaveAddress(addr string) error { return fmt.Errorf("Load: %v", err) } - cfg.Section("remote \"origin\"").Key("url").SetValue(addr) + cfg.Section("remote \"origin\"").Key("url").SetValue(escapeMirrorCredentials(addr)) return cfg.SaveToIndent(configPath, "\t") } diff --git a/models/mirror_test.go b/models/mirror_test.go new file mode 100644 index 00000000..6b23df1c --- /dev/null +++ b/models/mirror_test.go @@ -0,0 +1,28 @@ +// Copyright 2017 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func Test_escapeMirrorCredentials(t *testing.T) { + Convey("Escape credentials in mirror address", t, func() { + testCases := []string{ + "http://localhost:3000/user/repo.git", "http://localhost:3000/user/repo.git", + "http://user@localhost:3000/user/repo.git", "http://user@localhost:3000/user/repo.git", + "http://user:@localhost:3000/user/repo.git", "http://user:@localhost:3000/user/repo.git", + "http://user:password@localhost:3000/user/repo.git", "http://user:password@localhost:3000/user/repo.git", + "http://user:my:secure;password@localhost:3000/user/repo.git", "http://user:my%3Asecure%3Bpassword@localhost:3000/user/repo.git", + "http://user:my@secure#password@localhost:3000/user/repo.git", "http://user:my%40secure%23password@localhost:3000/user/repo.git", + } + + for i := 0; i < len(testCases); i += 2 { + So(escapeMirrorCredentials(testCases[i]), ShouldEqual, testCases[i+1]) + } + }) +} diff --git a/templates/.VERSION b/templates/.VERSION index d4ec5cbc..0e095302 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.11.2.0404 \ No newline at end of file +0.11.3.0404 \ No newline at end of file