58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
|
|
package core
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
|
||
|
|
"github.com/metacubex/mihomo/config"
|
||
|
|
"go.yaml.in/yaml/v3"
|
||
|
|
)
|
||
|
|
|
||
|
|
// mihomo decodes an unquoted REALITY short-id as a YAML number (0123 is 83, 00
|
||
|
|
// is 0); the scalar keeps its literal text, so retagging it restores the id.
|
||
|
|
func unmarshalRawConfig(buf []byte) (*config.RawConfig, error) {
|
||
|
|
if !bytes.Contains(buf, []byte("short-id")) {
|
||
|
|
return config.UnmarshalRawConfig(buf)
|
||
|
|
}
|
||
|
|
var document yaml.Node
|
||
|
|
if yaml.Unmarshal(buf, &document) != nil || !retagShortIDs(&document) {
|
||
|
|
return config.UnmarshalRawConfig(buf)
|
||
|
|
}
|
||
|
|
rawConfig := config.DefaultRawConfig()
|
||
|
|
if err := document.Decode(rawConfig); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return rawConfig, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func retagShortIDs(node *yaml.Node) bool {
|
||
|
|
retagged := false
|
||
|
|
if node.Kind == yaml.MappingNode {
|
||
|
|
for i := 0; i+1 < len(node.Content); i += 2 {
|
||
|
|
if node.Content[i].Value == "short-id" {
|
||
|
|
retagged = retagNumber(node.Content[i+1]) || retagged
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for _, child := range node.Content {
|
||
|
|
retagged = retagShortIDs(child) || retagged
|
||
|
|
}
|
||
|
|
return retagged
|
||
|
|
}
|
||
|
|
|
||
|
|
func retagNumber(node *yaml.Node) bool {
|
||
|
|
switch node.Kind {
|
||
|
|
case yaml.ScalarNode:
|
||
|
|
if node.Style == 0 && (node.Tag == "!!int" || node.Tag == "!!float") {
|
||
|
|
node.Tag = "!!str"
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
case yaml.SequenceNode:
|
||
|
|
retagged := false
|
||
|
|
for _, item := range node.Content {
|
||
|
|
retagged = retagNumber(item) || retagged
|
||
|
|
}
|
||
|
|
return retagged
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|