mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-31 00:04:44 +00:00
perf(appstore): reduce resource requests during synchronization
This commit is contained in:
@@ -6,13 +6,42 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
)
|
||||
|
||||
const IconPrefix = "app_"
|
||||
|
||||
func IsRemoteURL(icon string) bool {
|
||||
for _, ch := range icon {
|
||||
if unicode.IsSpace(ch) || unicode.IsControl(ch) || ch == '\\' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
u, err := url.Parse(icon)
|
||||
if err != nil || (!strings.EqualFold(u.Scheme, "http") && !strings.EqualFold(u.Scheme, "https")) || u.Hostname() == "" || u.User != nil {
|
||||
return false
|
||||
}
|
||||
if u.Port() != "" {
|
||||
port, err := strconv.Atoi(u.Port())
|
||||
if err != nil || port > 65535 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
_, err = url.QueryUnescape(u.RawQuery)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func RemoteURL(icon string) string {
|
||||
if IsRemoteURL(icon) {
|
||||
return icon
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func IsIconFile(icon string) bool {
|
||||
return strings.HasPrefix(icon, IconPrefix)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package appicon
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRemoteURLPreservesValidSources(t *testing.T) {
|
||||
for _, value := range []string{
|
||||
"https://cdn.example/icon.png",
|
||||
"http://cdn.example:8080/icon.png",
|
||||
"HTTPS://cdn.example/icon.png?token=a%2Bb&v=42#image",
|
||||
"https://[::1]:8443/icon.png",
|
||||
} {
|
||||
t.Run(value, func(t *testing.T) {
|
||||
if !IsRemoteURL(value) || RemoteURL(value) != value {
|
||||
t.Fatalf("URL was rejected or rewritten: %q", value)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoteURLRejectsOtherIconFormatsAndAmbiguousURLs(t *testing.T) {
|
||||
for _, value := range []string{
|
||||
"", "app_php.png?etag=42", "iVBORw0KGgo=", "data:image/png;base64,iVBORw0KGgo=",
|
||||
"javascript:alert(1)", "file:///icon.png", "//cdn.example/icon.png", "https:///icon.png",
|
||||
"https://", "https://user:secret@cdn.example/icon.png", "https://@cdn.example/icon.png",
|
||||
" https://cdn.example/icon.png", "https://cdn.example/icon.png ", "https://cdn.example/icon image.png",
|
||||
"https://cdn.example/\nicon.png", "https://cdn.example/icon.png\r\nLocation: https://other.example",
|
||||
"https://cdn.example/\\other.png", "https://cdn.example:bad/icon.png", "https://cdn.example/%zz",
|
||||
"https://cdn.example/icon.png?token=%zz", "https://cdn.example/\u00a0icon.png", "https://cdn.example/\x7ficon.png",
|
||||
"https://cdn.example:65536/icon.png",
|
||||
} {
|
||||
t.Run(value, func(t *testing.T) {
|
||||
if IsRemoteURL(value) || RemoteURL(value) != "" {
|
||||
t.Fatalf("invalid or historical icon was classified as a remote URL: %q", value)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user