Skip to content

Commit 6b8b5a7

Browse files
committed
Remove most calls to com, improve vars.Expand
1 parent 671592b commit 6b8b5a7

File tree

14 files changed

+137
-83
lines changed

14 files changed

+137
-83
lines changed

.golangci.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ linters:
1818
- ineffassign
1919
- revive
2020
- gofumpt
21+
- depguard
2122
enable-all: false
2223
disable-all: true
2324
fast: false
@@ -64,7 +65,15 @@ linters-settings:
6465
- name: modifies-value-receiver
6566
gofumpt:
6667
extra-rules: true
67-
lang-version: 1.18
68+
lang-version: "1.18"
69+
depguard:
70+
# TODO: use depguard to replace import checks in gitea-vet
71+
list-type: denylist
72+
# Check the list against standard lib.
73+
include-go-root: true
74+
packages-with-error-message:
75+
- encoding/json: "use gitea's modules/json instead of encoding/json"
76+
- github.com/unknwon/com: "use gitea's util and replacements"
6877

6978
issues:
7079
exclude-rules:
@@ -152,5 +161,6 @@ issues:
152161
- path: models/user/openid.go
153162
linters:
154163
- golint
155-
- linters: staticcheck
164+
- linters:
165+
- staticcheck
156166
text: "strings.Title is deprecated: The rule Title uses for word boundaries does not handle Unicode punctuation properly. Use golang.org/x/text/cases instead."

modules/context/context.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ import (
3131
"code.gitea.io/gitea/modules/setting"
3232
"code.gitea.io/gitea/modules/templates"
3333
"code.gitea.io/gitea/modules/translation"
34+
"code.gitea.io/gitea/modules/util"
3435
"code.gitea.io/gitea/modules/web/middleware"
3536
"code.gitea.io/gitea/services/auth"
3637

3738
"gitea.com/go-chi/cache"
3839
"gitea.com/go-chi/session"
3940
chi "github.com/go-chi/chi/v5"
40-
"github.com/unknwon/com"
4141
"github.com/unrolled/render"
4242
"golang.org/x/crypto/pbkdf2"
4343
)
@@ -452,7 +452,7 @@ func (ctx *Context) CookieDecrypt(secret, val string) (string, bool) {
452452
}
453453

454454
key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
455-
text, err = com.AESGCMDecrypt(key, text)
455+
text, err = util.AESGCMDecrypt(key, text)
456456
return string(text), err == nil
457457
}
458458

@@ -466,7 +466,7 @@ func (ctx *Context) SetSuperSecureCookie(secret, name, value string, expiry int)
466466
// CookieEncrypt encrypts a given value using the provided secret
467467
func (ctx *Context) CookieEncrypt(secret, value string) string {
468468
key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
469-
text, err := com.AESGCMEncrypt(key, []byte(value))
469+
text, err := util.AESGCMEncrypt(key, []byte(value))
470470
if err != nil {
471471
panic("error encrypting cookie: " + err.Error())
472472
}

modules/context/csrf.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919
package context
2020

2121
import (
22+
"encoding/base32"
23+
"fmt"
2224
"net/http"
2325
"time"
2426

2527
"code.gitea.io/gitea/modules/setting"
2628
"code.gitea.io/gitea/modules/util"
2729
"code.gitea.io/gitea/modules/web/middleware"
28-
29-
"github.com/unknwon/com"
3030
)
3131

3232
// CSRF represents a CSRF service and is used to get the current token and validate a suspect token.
@@ -163,7 +163,12 @@ func prepareOptions(options []CsrfOptions) CsrfOptions {
163163

164164
// Defaults.
165165
if len(opt.Secret) == 0 {
166-
opt.Secret = string(com.RandomCreateBytes(10))
166+
randBytes, err := util.CryptoRandomBytes(8)
167+
if err != nil {
168+
// this panic can be handled by the recover() in http handlers
169+
panic(fmt.Errorf("failed to generate random bytes: %w", err))
170+
}
171+
opt.Secret = base32.StdEncoding.EncodeToString(randBytes)
167172
}
168173
if len(opt.Header) == 0 {
169174
opt.Header = "X-CSRFToken"

modules/json/json.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ package json
88
import (
99
"bytes"
1010
"encoding/binary"
11-
"encoding/json"
11+
"encoding/json" //nolint:depguard
1212
"io"
1313

1414
jsoniter "github.com/json-iterator/go"

modules/markup/html.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -840,8 +840,8 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
840840

841841
res, err := vars.Expand(ctx.Metas["format"], ctx.Metas)
842842
if err != nil {
843-
log.Error(err.Error())
844-
return
843+
// here we could just log the error and continue the rendering
844+
log.Error("unable to expand template vars for ref %s, err:%s", ref.Issue, err.Error())
845845
}
846846

847847
link = createLink(res, reftext, "ref-issue ref-external-issue")

modules/repository/init.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
6262
}
6363
res, err := vars.Expand(string(data), match)
6464
if err != nil {
65-
return fmt.Errorf("expand README.md: %v", err)
65+
// here we could just log the error and continue the rendering
66+
log.Error("unable to expand template vars for repo README: %s, err: %s", opts.Readme, err.Error())
6667
}
6768
if err = os.WriteFile(filepath.Join(tmpDir, "README.md"),
6869
[]byte(res), 0o644); err != nil {

modules/setting/setting.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"code.gitea.io/gitea/modules/user"
2828
"code.gitea.io/gitea/modules/util"
2929

30-
"github.com/unknwon/com"
3130
gossh "golang.org/x/crypto/ssh"
3231
ini "gopkg.in/ini.v1"
3332
)
@@ -601,7 +600,7 @@ func loadFromConf(allowEmpty bool, extraConfig string) {
601600

602601
Cfg.NameMapper = ini.SnackCase
603602

604-
homeDir, err := com.HomeDir()
603+
homeDir, err := util.HomeDir()
605604
if err != nil {
606605
log.Fatal("Failed to get home directory: %v", err)
607606
}

modules/templates/vars/vars.go

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -40,67 +40,65 @@ func IsErrNoMatchedVar(err error) bool {
4040
return ok
4141
}
4242

43-
// Expand replaces all variables like {var} to match
44-
func Expand(template string, match map[string]string, subs ...string) (string, error) {
45-
var (
46-
buf strings.Builder
47-
key strings.Builder
48-
enter bool
49-
)
50-
for _, c := range template {
51-
switch {
52-
case c == '{':
53-
if enter {
54-
return "", ErrWrongSyntax{
55-
Template: template,
56-
}
57-
}
58-
enter = true
59-
case c == '}':
60-
if !enter {
61-
return "", ErrWrongSyntax{
62-
Template: template,
63-
}
64-
}
65-
if key.Len() == 0 {
66-
return "", ErrWrongSyntax{
67-
Template: template,
68-
}
69-
}
43+
// Expand replaces all variables like {var} to match, if error occurs, the error part doesn't change and is returned as it is.
44+
// `#' is a reversed char, templates can use `{#{}` to do escape and output char '{'.
45+
func Expand(template string, match map[string]string) (string, error) {
46+
var buf strings.Builder
47+
var err error
7048

71-
if len(match) == 0 {
72-
return "", ErrNoMatchedVar{
73-
Template: template,
74-
Var: key.String(),
75-
}
76-
}
49+
posBegin := 0
50+
strLen := len(template)
51+
for posBegin < strLen {
52+
// find the next `{`
53+
pos := strings.IndexByte(template[posBegin:], '{')
54+
if pos == -1 {
55+
buf.WriteString(template[posBegin:])
56+
break
57+
}
7758

78-
v, ok := match[key.String()]
79-
if !ok {
80-
if len(subs) == 0 {
81-
return "", ErrNoMatchedVar{
82-
Template: template,
83-
Var: key.String(),
84-
}
85-
}
86-
v = subs[0]
87-
}
59+
// copy texts between vars
60+
buf.WriteString(template[posBegin : posBegin+pos])
8861

89-
if _, err := buf.WriteString(v); err != nil {
90-
return "", err
62+
// find the var between `{` and `}`/end
63+
posBegin += pos
64+
posEnd := posBegin + 1
65+
for posEnd < strLen {
66+
if template[posEnd] == '#' {
67+
// escape char, skip next
68+
posEnd += 2
69+
continue
70+
} else if template[posEnd] == '}' {
71+
posEnd++
72+
break
9173
}
92-
key.Reset()
74+
posEnd++
75+
}
9376

94-
enter = false
95-
case enter:
96-
if _, err := key.WriteRune(c); err != nil {
97-
return "", err
98-
}
99-
default:
100-
if _, err := buf.WriteRune(c); err != nil {
101-
return "", err
77+
// the var part, it can be "{", "{}", "{..." or or "{...}"
78+
part := template[posBegin:posEnd]
79+
posBegin = posEnd
80+
if part == "{}" || part[len(part)-1] != '}' {
81+
// treat "{}" or "{..." as error
82+
err = ErrWrongSyntax{Template: template}
83+
buf.WriteString(part)
84+
} else {
85+
// now we get a valid key "{...}"
86+
key := part[1 : len(part)-1]
87+
if key[0] == '#' {
88+
// escaped char
89+
buf.WriteString(key[1:])
90+
} else {
91+
// look up in the map
92+
if val, ok := match[key]; ok {
93+
buf.WriteString(val)
94+
} else {
95+
// write the non-existing var as it is
96+
buf.WriteString(part)
97+
err = ErrNoMatchedVar{Template: template, Var: key}
98+
}
10299
}
103100
}
104101
}
105-
return buf.String(), nil
102+
103+
return buf.String(), err
106104
}

modules/templates/vars/vars_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ func TestExpandVars(t *testing.T) {
2525
expected: "1",
2626
},
2727
{
28-
template: "expand {a}, {b} and {c}",
28+
template: "expand {a}, {b} and {c}, with escaped {#{}",
2929
maps: map[string]string{
3030
"a": "1",
3131
"b": "2",
3232
"c": "3",
3333
},
34-
expected: "expand 1, 2 and 3",
34+
expected: "expand 1, 2 and 3, with escaped {",
3535
},
3636
{
3737
template: "中文内容 {一}, {二} 和 {三} 中文结尾",
@@ -44,14 +44,16 @@ func TestExpandVars(t *testing.T) {
4444
},
4545
{
4646
template: "expand {{a}, {b} and {c}",
47+
maps: map[string]string{
48+
"a": "foo",
49+
"b": "bar",
50+
},
51+
expected: "expand {{a}, bar and {c}",
4752
fail: true,
4853
},
4954
{
50-
template: "expand {}, {b} and {c}",
51-
fail: true,
52-
},
53-
{
54-
template: "expand }, {b} and {c}",
55+
template: "expand } {} and {",
56+
expected: "expand } {} and {",
5557
fail: true,
5658
},
5759
}

modules/util/copy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package util
66

77
import (
8-
"github.com/unknwon/com"
8+
"github.com/unknwon/com" //nolint:depguard
99
)
1010

1111
// CopyFile copies file from source to target path.

modules/util/path.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ func StatDir(rootPath string, includeDir ...bool) ([]string, error) {
154154
return statDir(rootPath, "", isIncludeDir, false, false)
155155
}
156156

157+
func isOSWindows() bool {
158+
return runtime.GOOS == "windows"
159+
}
160+
157161
// FileURLToPath extracts the path information from a file://... url.
158162
func FileURLToPath(u *url.URL) (string, error) {
159163
if u.Scheme != "file" {
@@ -162,7 +166,7 @@ func FileURLToPath(u *url.URL) (string, error) {
162166

163167
path := u.Path
164168

165-
if runtime.GOOS != "windows" {
169+
if !isOSWindows() {
166170
return path, nil
167171
}
168172

@@ -173,3 +177,22 @@ func FileURLToPath(u *url.URL) (string, error) {
173177
}
174178
return path, nil
175179
}
180+
181+
// HomeDir returns path of '~'(in Linux) on Windows,
182+
// it returns error when the variable does not exist.
183+
func HomeDir() (home string, err error) {
184+
if isOSWindows() {
185+
home = os.Getenv("USERPROFILE")
186+
if home == "" {
187+
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
188+
}
189+
} else {
190+
home = os.Getenv("HOME")
191+
}
192+
193+
if home == "" {
194+
return "", errors.New("cannot get home directory")
195+
}
196+
197+
return home, nil
198+
}

modules/util/util.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"strconv"
1313
"strings"
1414

15-
"github.com/unknwon/com"
15+
"github.com/unknwon/com" //nolint:depguard
1616
)
1717

1818
// OptionalBool a boolean that can be "null"
@@ -184,7 +184,22 @@ func ToUpperASCII(s string) string {
184184
return string(b)
185185
}
186186

187-
// ToStr should be replaced
187+
// ToStr (from unknwon/com): should be replaced.
188188
func ToStr(value interface{}, args ...int) string {
189189
return com.ToStr(value, args...)
190190
}
191+
192+
// ToSnakeCase (from unknwon/com): should be replaced.
193+
func ToSnakeCase(str string) string {
194+
return com.ToSnakeCase(str)
195+
}
196+
197+
// AESGCMEncrypt (from unknwon/com): encrypts plaintext with the given key using AES in GCM mode. should be replaced.
198+
func AESGCMEncrypt(key, plaintext []byte) ([]byte, error) {
199+
return com.AESGCMEncrypt(key, plaintext)
200+
}
201+
202+
// AESGCMDecrypt (from unknwon/com): decrypts ciphertext with the given key using AES in GCM mode. should be replaced.
203+
func AESGCMDecrypt(key, ciphertext []byte) ([]byte, error) {
204+
return com.AESGCMDecrypt(key, ciphertext)
205+
}

0 commit comments

Comments
 (0)