3x-ui/subproject/Xray-core-main/infra/conf/serial/loader.go
test999 367152556a **Fixes & Changes:**
1. **Fixed XPadding Placement Dropdown**:
   - Added the missing `cookie` and `query` options to `xPaddingPlacement` (`stream_xhttp.html`).
   - *Why:* Previously, users wanting `cookie` obfuscation were forced to use the `header` placement string. This caused Xray-core to blindly intercept the entire monolithic HTTP Cookie header, failing internal padding-length validations and causing the inbound to silently drop the connection.
2. **Fixed Uplink Data Placement Validation**:
   - Replaced the unsupported `query` option with `cookie` in `uplinkDataPlacement`.
   - *Why:* Xray-core's `transport_internet.go` explicitly forbids `query` as an uplink placement option. Selecting it from the UI previously sent a payload that would cause Xray-core to instantly throw an `unsupported uplink data placement: query` panic. Adding `cookie` perfectly aligns the UI with Xray-core restrictions.
### Related Issues
- Resolves #3992
2026-04-06 15:00:43 +03:00

149 lines
3.5 KiB
Go

package serial
import (
"bytes"
"encoding/json"
"io"
"github.com/ghodss/yaml"
"github.com/pelletier/go-toml"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf"
json_reader "github.com/xtls/xray-core/infra/conf/json"
)
type offset struct {
line int
char int
}
func findOffset(b []byte, o int) *offset {
if o >= len(b) || o < 0 {
return nil
}
line := 1
char := 0
for i, x := range b {
if i == o {
break
}
if x == '\n' {
line++
char = 0
} else {
char++
}
}
return &offset{line: line, char: char}
}
// DecodeJSONConfig reads from reader and decode the config into *conf.Config
// syntax error could be detected.
func DecodeJSONConfig(reader io.Reader) (*conf.Config, error) {
jsonConfig := &conf.Config{}
jsonContent := bytes.NewBuffer(make([]byte, 0, 10240))
jsonReader := io.TeeReader(&json_reader.Reader{
Reader: reader,
}, jsonContent)
decoder := json.NewDecoder(jsonReader)
if err := decoder.Decode(jsonConfig); err != nil {
var pos *offset
cause := errors.Cause(err)
switch tErr := cause.(type) {
case *json.SyntaxError:
pos = findOffset(jsonContent.Bytes(), int(tErr.Offset))
case *json.UnmarshalTypeError:
pos = findOffset(jsonContent.Bytes(), int(tErr.Offset))
}
if pos != nil {
return nil, errors.New("failed to read config file at line ", pos.line, " char ", pos.char).Base(err)
}
return nil, errors.New("failed to read config file").Base(err)
}
return jsonConfig, nil
}
func LoadJSONConfig(reader io.Reader) (*core.Config, error) {
jsonConfig, err := DecodeJSONConfig(reader)
if err != nil {
return nil, err
}
pbConfig, err := jsonConfig.Build()
if err != nil {
return nil, errors.New("failed to parse json config").Base(err)
}
return pbConfig, nil
}
// DecodeTOMLConfig reads from reader and decode the config into *conf.Config
// using github.com/pelletier/go-toml and map to convert toml to json.
func DecodeTOMLConfig(reader io.Reader) (*conf.Config, error) {
tomlFile, err := io.ReadAll(reader)
if err != nil {
return nil, errors.New("failed to read config file").Base(err)
}
configMap := make(map[string]interface{})
if err := toml.Unmarshal(tomlFile, &configMap); err != nil {
return nil, errors.New("failed to convert toml to map").Base(err)
}
jsonFile, err := json.Marshal(&configMap)
if err != nil {
return nil, errors.New("failed to convert map to json").Base(err)
}
return DecodeJSONConfig(bytes.NewReader(jsonFile))
}
func LoadTOMLConfig(reader io.Reader) (*core.Config, error) {
tomlConfig, err := DecodeTOMLConfig(reader)
if err != nil {
return nil, err
}
pbConfig, err := tomlConfig.Build()
if err != nil {
return nil, errors.New("failed to parse toml config").Base(err)
}
return pbConfig, nil
}
// DecodeYAMLConfig reads from reader and decode the config into *conf.Config
// using github.com/ghodss/yaml to convert yaml to json.
func DecodeYAMLConfig(reader io.Reader) (*conf.Config, error) {
yamlFile, err := io.ReadAll(reader)
if err != nil {
return nil, errors.New("failed to read config file").Base(err)
}
jsonFile, err := yaml.YAMLToJSON(yamlFile)
if err != nil {
return nil, errors.New("failed to convert yaml to json").Base(err)
}
return DecodeJSONConfig(bytes.NewReader(jsonFile))
}
func LoadYAMLConfig(reader io.Reader) (*core.Config, error) {
yamlConfig, err := DecodeYAMLConfig(reader)
if err != nil {
return nil, err
}
pbConfig, err := yamlConfig.Build()
if err != nil {
return nil, errors.New("failed to parse yaml config").Base(err)
}
return pbConfig, nil
}