aboutsummaryrefslogtreecommitdiffstats
path: root/modules/httplib
diff options
context:
space:
mode:
authorsommerf-lf <159693954+sommerf-lf@users.noreply.github.com>2025-03-05 17:29:29 +0100
committerGitHub <noreply@github.com>2025-03-05 16:29:29 +0000
commit7cdde20c737c70e9b11f1ded71ad4b985f4167fd (patch)
tree297e2df1b65887eb8bc5222f0d13d288ce83ecd8 /modules/httplib
parentf0f10413aeaa6970c07cc481ebd22ea2eb626a4c (diff)
downloadgitea-7cdde20c737c70e9b11f1ded71ad4b985f4167fd.tar.gz
gitea-7cdde20c737c70e9b11f1ded71ad4b985f4167fd.zip
Email option to embed images as base64 instead of link (#32061)
ref: #15081 ref: #14037 Documentation: https://gitea.com/gitea/docs/pulls/69 # Example Content: ![image](https://github.com/user-attachments/assets/e73ebfbe-e329-40f6-9c4a-f73832bbb181) Result in Email: ![image](https://github.com/user-attachments/assets/55b7019f-e17a-46c3-a374-3b4769d5c2d6) Result with source code: (first image is external image, 2nd is now embedded) ![image](https://github.com/user-attachments/assets/8e2804a1-580f-4a69-adcb-cc5d16f7da81) --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Diffstat (limited to 'modules/httplib')
-rw-r--r--modules/httplib/url.go78
-rw-r--r--modules/httplib/url_test.go23
2 files changed, 88 insertions, 13 deletions
diff --git a/modules/httplib/url.go b/modules/httplib/url.go
index f543c09190..5d5b64dc0c 100644
--- a/modules/httplib/url.go
+++ b/modules/httplib/url.go
@@ -102,25 +102,77 @@ func MakeAbsoluteURL(ctx context.Context, link string) string {
return GuessCurrentHostURL(ctx) + "/" + strings.TrimPrefix(link, "/")
}
-func IsCurrentGiteaSiteURL(ctx context.Context, s string) bool {
+type urlType int
+
+const (
+ urlTypeGiteaAbsolute urlType = iota + 1 // "http://gitea/subpath"
+ urlTypeGiteaPageRelative // "/subpath"
+ urlTypeGiteaSiteRelative // "?key=val"
+ urlTypeUnknown // "http://other"
+)
+
+func detectURLRoutePath(ctx context.Context, s string) (routePath string, ut urlType) {
u, err := url.Parse(s)
if err != nil {
- return false
+ return "", urlTypeUnknown
}
+ cleanedPath := ""
if u.Path != "" {
- cleanedPath := util.PathJoinRelX(u.Path)
- if cleanedPath == "" || cleanedPath == "." {
- u.Path = "/"
- } else {
- u.Path = "/" + cleanedPath + "/"
- }
+ cleanedPath = util.PathJoinRelX(u.Path)
+ cleanedPath = util.Iif(cleanedPath == ".", "", "/"+cleanedPath)
}
if urlIsRelative(s, u) {
- return u.Path == "" || strings.HasPrefix(strings.ToLower(u.Path), strings.ToLower(setting.AppSubURL+"/"))
- }
- if u.Path == "" {
- u.Path = "/"
+ if u.Path == "" {
+ return "", urlTypeGiteaPageRelative
+ }
+ if strings.HasPrefix(strings.ToLower(cleanedPath+"/"), strings.ToLower(setting.AppSubURL+"/")) {
+ return cleanedPath[len(setting.AppSubURL):], urlTypeGiteaSiteRelative
+ }
+ return "", urlTypeUnknown
}
+ u.Path = cleanedPath + "/"
urlLower := strings.ToLower(u.String())
- return strings.HasPrefix(urlLower, strings.ToLower(setting.AppURL)) || strings.HasPrefix(urlLower, strings.ToLower(GuessCurrentAppURL(ctx)))
+ if strings.HasPrefix(urlLower, strings.ToLower(setting.AppURL)) {
+ return cleanedPath[len(setting.AppSubURL):], urlTypeGiteaAbsolute
+ }
+ guessedCurURL := GuessCurrentAppURL(ctx)
+ if strings.HasPrefix(urlLower, strings.ToLower(guessedCurURL)) {
+ return cleanedPath[len(setting.AppSubURL):], urlTypeGiteaAbsolute
+ }
+ return "", urlTypeUnknown
+}
+
+func IsCurrentGiteaSiteURL(ctx context.Context, s string) bool {
+ _, ut := detectURLRoutePath(ctx, s)
+ return ut != urlTypeUnknown
+}
+
+type GiteaSiteURL struct {
+ RoutePath string
+ OwnerName string
+ RepoName string
+ RepoSubPath string
+}
+
+func ParseGiteaSiteURL(ctx context.Context, s string) *GiteaSiteURL {
+ routePath, ut := detectURLRoutePath(ctx, s)
+ if ut == urlTypeUnknown || ut == urlTypeGiteaPageRelative {
+ return nil
+ }
+ ret := &GiteaSiteURL{RoutePath: routePath}
+ fields := strings.SplitN(strings.TrimPrefix(ret.RoutePath, "/"), "/", 3)
+
+ // TODO: now it only does a quick check for some known reserved paths, should do more strict checks in the future
+ if fields[0] == "attachments" {
+ return ret
+ }
+ if len(fields) < 2 {
+ return ret
+ }
+ ret.OwnerName = fields[0]
+ ret.RepoName = fields[1]
+ if len(fields) == 3 {
+ ret.RepoSubPath = "/" + fields[2]
+ }
+ return ret
}
diff --git a/modules/httplib/url_test.go b/modules/httplib/url_test.go
index cb8fac0a21..d57653646b 100644
--- a/modules/httplib/url_test.go
+++ b/modules/httplib/url_test.go
@@ -122,3 +122,26 @@ func TestIsCurrentGiteaSiteURL(t *testing.T) {
assert.True(t, IsCurrentGiteaSiteURL(ctx, "https://user-host"))
assert.False(t, IsCurrentGiteaSiteURL(ctx, "https://forwarded-host"))
}
+
+func TestParseGiteaSiteURL(t *testing.T) {
+ defer test.MockVariableValue(&setting.AppURL, "http://localhost:3000/sub/")()
+ defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
+ ctx := t.Context()
+ tests := []struct {
+ url string
+ exp *GiteaSiteURL
+ }{
+ {"http://localhost:3000/sub?k=v", &GiteaSiteURL{RoutePath: ""}},
+ {"http://localhost:3000/sub/", &GiteaSiteURL{RoutePath: ""}},
+ {"http://localhost:3000/sub/foo", &GiteaSiteURL{RoutePath: "/foo"}},
+ {"http://localhost:3000/sub/foo/bar", &GiteaSiteURL{RoutePath: "/foo/bar", OwnerName: "foo", RepoName: "bar"}},
+ {"http://localhost:3000/sub/foo/bar/", &GiteaSiteURL{RoutePath: "/foo/bar", OwnerName: "foo", RepoName: "bar"}},
+ {"http://localhost:3000/sub/attachments/bar", &GiteaSiteURL{RoutePath: "/attachments/bar"}},
+ {"http://localhost:3000/other", nil},
+ {"http://other/", nil},
+ }
+ for _, test := range tests {
+ su := ParseGiteaSiteURL(ctx, test.url)
+ assert.Equal(t, test.exp, su, "URL = %s", test.url)
+ }
+}