diff --git a/main/commands/all/base64/base64.go b/main/commands/all/base64/base64.go index 84438fa5d..2bf2fcfa5 100644 --- a/main/commands/all/base64/base64.go +++ b/main/commands/all/base64/base64.go @@ -1,11 +1,6 @@ package base64 -import ( - "io" - "os" - - "github.com/xtls/xray-core/main/commands/base" -) +import "github.com/xtls/xray-core/main/commands/base" // CmdBase64 holds all Base64 subcommands. var CmdBase64 = &base.Command{ @@ -17,10 +12,3 @@ var CmdBase64 = &base.Command{ cmdDecode, }, } - -func readInput(args []string) ([]byte, error) { - if len(args) == 0 || args[0] == "-" || args[0] == "stdin:" { - return io.ReadAll(os.Stdin) - } - return os.ReadFile(args[0]) -} diff --git a/main/commands/all/base64/decode.go b/main/commands/all/base64/decode.go index 1b7b74927..1d8b4eb69 100644 --- a/main/commands/all/base64/decode.go +++ b/main/commands/all/base64/decode.go @@ -2,6 +2,7 @@ package base64 import ( "fmt" + "io" "os" "strings" @@ -10,17 +11,17 @@ import ( ) var cmdDecode = &base.Command{ - UsageLine: "{{.Exec}} base64 decode [-gzip] [file | - | stdin:]", + UsageLine: "{{.Exec}} base64 decode [-gzip] [value | - | stdin:] [output-file]", Short: "Decode Base64", Long: fmt.Sprintf(` -Decode Base64 from a file; omit file or pass "-" or "stdin:" to read stdin. -Accepts %s, %s, or no prefix. -Use -gzip to decompress gzip; %s is decompressed automatically. +Decode a Base64 value; omit value or pass "-" or "stdin:" to read stdin. +Write to output-file, or stdout if omitted. +Accepts %s, %s, or no prefix; gzip is enabled by %s or -gzip. Examples: - {{.Exec}} base64 decode encoded.txt - {{.Exec}} base64 decode -gzip - + {{.Exec}} base64 decode eA== out.bin + {{.Exec}} base64 decode -gzip H4sIAAAAAAAC/6sAAIMW3IwBAAAA out.bin `, xbase64.Prefix, xbase64.GzipPrefix, xbase64.GzipPrefix), } @@ -31,22 +32,37 @@ func init() { } func executeDecode(cmd *base.Command, args []string) { - if len(args) > 1 { + if len(args) > 2 { cmd.Usage() } - input, err := readInput(args) - if err != nil { - base.Fatalf("failed to read input: %s", err) + + var value string + if len(args) == 0 || args[0] == "-" || args[0] == "stdin:" { + input, err := io.ReadAll(os.Stdin) + if err != nil { + base.Fatalf("failed to read input: %s", err) + } + value = string(input) + } else { + value = args[0] } - value := strings.TrimSpace(string(input)) + + value = strings.TrimSpace(value) if *decodeGzipEnabled && !strings.HasPrefix(value, xbase64.GzipPrefix) { value = xbase64.GzipPrefix + strings.TrimPrefix(value, xbase64.Prefix) } + data, err := xbase64.Decode(value) if err != nil { base.Fatalf("failed to decode input: %s", err) } - if _, err := os.Stdout.Write(data); err != nil { + + if len(args) == 2 && args[1] != "-" { + err = os.WriteFile(args[1], data, 0o666) + } else { + _, err = os.Stdout.Write(data) + } + if err != nil { base.Fatalf("failed to write decoded output: %s", err) } } diff --git a/main/commands/all/base64/encode.go b/main/commands/all/base64/encode.go index 1378bc06f..0340c6c43 100644 --- a/main/commands/all/base64/encode.go +++ b/main/commands/all/base64/encode.go @@ -2,6 +2,7 @@ package base64 import ( "fmt" + "io" "os" xbase64 "github.com/xtls/xray-core/common/base64" @@ -9,17 +10,17 @@ import ( ) var cmdEncode = &base.Command{ - UsageLine: "{{.Exec}} base64 encode [-gzip] [file | - | stdin:]", + UsageLine: "{{.Exec}} base64 encode [-gzip] [input-file | - | stdin:]", Short: "Encode as Base64", Long: fmt.Sprintf(` -Encode a file as Base64 with the %s prefix. -Omit file or pass "-" or "stdin:" to read stdin. Use -gzip to compress and output %s. +Encode input-file as Base64 with the %s prefix. +Omit input-file or pass "-" or "stdin:" to read stdin. +Use -gzip to compress and output %s. Examples: - {{.Exec}} base64 encode data.bin - {{.Exec}} base64 encode -gzip data.bin - {{.Exec}} base64 encode + {{.Exec}} base64 encode input.bin + {{.Exec}} base64 encode -gzip input.bin `, xbase64.Prefix, xbase64.GzipPrefix), } @@ -33,14 +34,23 @@ func executeEncode(cmd *base.Command, args []string) { if len(args) > 1 { cmd.Usage() } - data, err := readInput(args) + + var data []byte + var err error + if len(args) == 0 || args[0] == "-" || args[0] == "stdin:" { + data, err = io.ReadAll(os.Stdin) + } else { + data, err = os.ReadFile(args[0]) + } if err != nil { base.Fatalf("failed to read input: %s", err) } + value, err := xbase64.Encode(data, *gzipEnabled) if err != nil { base.Fatalf("failed to encode input: %s", err) } + if _, err := fmt.Fprintln(os.Stdout, value); err != nil { base.Fatalf("failed to write encoded output: %s", err) }