mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-06 21:25:04 +03:00
Fix fragment exports for older Xray clients (#6702)
* Fix fragment exports for older Xray clients * fix(link): tolerate a finalmask without tcp in panel share links withLegacyFragmentRanges called finalmask.tcp.map unguarded, but stored rows reach the link generator unparsed and dropEmptyFinalMask deletes an empty tcp list on save. Any VMess/VLESS/Trojan/SS inbound with only UDP masks or quicParams threw a TypeError in the QR, info and export-links views. The Go counterpart already skipped a missing tcp. Also trims the Go helper's comment to the two-line cap and drops a []string branch no JSON-decoded finalmask can reach. --------- Co-authored-by: Artem K <a.kush@vkteam.ru> Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
+66
-1
@@ -2844,7 +2844,7 @@ func applyFinalMaskObj(finalmask map[string]any, obj map[string]any) {
|
||||
}
|
||||
|
||||
func marshalFinalMask(finalmask map[string]any) (string, bool) {
|
||||
normalized := normalizeFinalMask(finalmask)
|
||||
normalized := withLegacyFragmentRanges(normalizeFinalMask(finalmask))
|
||||
if !hasFinalMaskContent(normalized) {
|
||||
return "", false
|
||||
}
|
||||
@@ -2855,6 +2855,71 @@ func marshalFinalMask(finalmask map[string]any) (string, bool) {
|
||||
return string(b), true
|
||||
}
|
||||
|
||||
// withLegacyFragmentRanges copies the last lengths/delays entry into the singular fields older
|
||||
// cores require; newer xray-core prefers the arrays whenever they are non-empty.
|
||||
func withLegacyFragmentRanges(finalmask map[string]any) map[string]any {
|
||||
tcpMasks, ok := finalmask["tcp"].([]any)
|
||||
if !ok {
|
||||
return finalmask
|
||||
}
|
||||
|
||||
var result map[string]any
|
||||
var resultMasks []any
|
||||
for i, rawMask := range tcpMasks {
|
||||
mask, ok := rawMask.(map[string]any)
|
||||
if !ok || mask["type"] != "fragment" {
|
||||
continue
|
||||
}
|
||||
settings, ok := mask["settings"].(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
legacySettings := maps.Clone(settings)
|
||||
changed := false
|
||||
if _, exists := settings["length"]; !exists {
|
||||
if value, ok := lastFragmentRange(settings["lengths"]); ok {
|
||||
legacySettings["length"] = value
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if _, exists := settings["delay"]; !exists {
|
||||
if value, ok := lastFragmentRange(settings["delays"]); ok {
|
||||
legacySettings["delay"] = value
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
result = maps.Clone(finalmask)
|
||||
resultMasks = slices.Clone(tcpMasks)
|
||||
result["tcp"] = resultMasks
|
||||
}
|
||||
legacyMask := maps.Clone(mask)
|
||||
legacyMask["settings"] = legacySettings
|
||||
resultMasks[i] = legacyMask
|
||||
}
|
||||
if result == nil {
|
||||
return finalmask
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func lastFragmentRange(value any) (string, bool) {
|
||||
ranges, _ := value.([]any)
|
||||
if len(ranges) == 0 {
|
||||
return "", false
|
||||
}
|
||||
rangeValue, ok := ranges[len(ranges)-1].(string)
|
||||
if !ok || strings.TrimSpace(rangeValue) == "" {
|
||||
return "", false
|
||||
}
|
||||
return rangeValue, true
|
||||
}
|
||||
|
||||
func normalizeFinalMask(finalmask map[string]any) map[string]any {
|
||||
tcpMasks := normalizedFinalMaskTCPMasks(finalmask)
|
||||
udpMasks := normalizedFinalMaskUDPMasks(finalmask)
|
||||
|
||||
Reference in New Issue
Block a user