mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-02 19:25:05 +03:00
fix(link): decode share link remarks once (#6977)
url.Parse already unescapes the fragment, and decodeHash unescaped it again, so a + in a vless, trojan, hysteria2 or wireguard remark became a space and an escaped % was decoded twice. These parsers now pass the escaped fragment, decoding it once like the shadowsocks parser and the frontend.
This commit is contained in:
@@ -387,7 +387,7 @@ func parseVless(link string) (*ParseResult, error) {
|
||||
|
||||
ob := Outbound{
|
||||
"protocol": "vless",
|
||||
"tag": decodeHash(u.Fragment),
|
||||
"tag": decodeHash(u.EscapedFragment()),
|
||||
"settings": map[string]any{
|
||||
"address": host,
|
||||
"port": port,
|
||||
@@ -429,7 +429,7 @@ func parseTrojan(link string) (*ParseResult, error) {
|
||||
|
||||
ob := Outbound{
|
||||
"protocol": "trojan",
|
||||
"tag": decodeHash(u.Fragment),
|
||||
"tag": decodeHash(u.EscapedFragment()),
|
||||
"settings": map[string]any{
|
||||
"servers": []any{
|
||||
map[string]any{"address": host, "port": port, "password": pw},
|
||||
@@ -634,7 +634,7 @@ func parseHysteria2(link string) (*ParseResult, error) {
|
||||
|
||||
ob := Outbound{
|
||||
"protocol": "hysteria",
|
||||
"tag": decodeHash(u.Fragment),
|
||||
"tag": decodeHash(u.EscapedFragment()),
|
||||
"settings": map[string]any{"address": host, "port": port, "version": 2},
|
||||
"streamSettings": stream,
|
||||
}
|
||||
@@ -712,7 +712,7 @@ func parseWireguard(link string) (*ParseResult, error) {
|
||||
|
||||
ob := Outbound{
|
||||
"protocol": "wireguard",
|
||||
"tag": decodeHash(u.Fragment),
|
||||
"tag": decodeHash(u.EscapedFragment()),
|
||||
"settings": settings,
|
||||
}
|
||||
return &ParseResult{Outbound: ob, Identity: identity}, nil
|
||||
|
||||
@@ -430,3 +430,34 @@ func TestParse_VmessFinalMask(t *testing.T) {
|
||||
t.Fatalf("finalmask.udp = %#v, want %#v", udp, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_RemarkDecodedOnce(t *testing.T) {
|
||||
// Remarks as the subscription server writes them (encodeURIComponent).
|
||||
cases := []struct {
|
||||
fragment string
|
||||
want string
|
||||
}{
|
||||
{"VIP%2B", "VIP+"},
|
||||
{"US%2BEU%201", "US+EU 1"},
|
||||
{"a%2520b", "a%20b"},
|
||||
{"%D0%A2%D0%B5%D1%81%D1%82", "Тест"},
|
||||
}
|
||||
prefixes := []string{
|
||||
"vless://uuid@1.2.3.4:443?type=tcp#",
|
||||
"trojan://pw@1.2.3.4:443#",
|
||||
"hysteria2://auth@1.2.3.4:443#",
|
||||
"wireguard://key@1.2.3.4:51820?publickey=pub#",
|
||||
"ss://YWVzLTI1Ni1nY206cHc@1.2.3.4:8388#",
|
||||
}
|
||||
for _, p := range prefixes {
|
||||
for _, c := range cases {
|
||||
res, err := ParseLink(p + c.fragment)
|
||||
if err != nil {
|
||||
t.Fatalf("parse %s%s: %v", p, c.fragment, err)
|
||||
}
|
||||
if res.Outbound["tag"] != c.want {
|
||||
t.Errorf("%s%s: tag = %q, want %q", p, c.fragment, res.Outbound["tag"], c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user