diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f30c88..e58c5080 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### Core v16.8.0 > ? +- Fix output address validation for tee outputs - Fix updating process config - Add experimental SRT connection stats and logs - Hide /config/reload endpoint in reade-only mode diff --git a/restream/restream.go b/restream/restream.go index 4c749ea3..c58b235e 100644 --- a/restream/restream.go +++ b/restream/restream.go @@ -725,24 +725,30 @@ func (r *restream) validateInputAddress(address, basedir string) (string, error) } func (r *restream) validateOutputAddress(address, basedir string) (string, bool, error) { - if strings.HasPrefix(address, "tee:") { - address = strings.TrimPrefix(address, "tee:") + if strings.Contains(address, "|") { addresses := strings.Split(address, "|") isFile := false - for _, a := range addresses { - _, file, err := r.validateOutputAddress(a, basedir) + teeOptions := regexp.MustCompile(`^\[[^\]]*\]`) + + for i, a := range addresses { + options := teeOptions.FindString(a) + a = teeOptions.ReplaceAllString(a, "") + + va, file, err := r.validateOutputAddress(a, basedir) if err != nil { - return "tee:" + address, false, err + return address, false, err } if file { isFile = true } + + addresses[i] = options + va } - return "tee:" + address, isFile, nil + return strings.Join(addresses, "|"), isFile, nil } address = strings.TrimPrefix(address, "file:") diff --git a/restream/restream_test.go b/restream/restream_test.go index ab0b7358..51026384 100644 --- a/restream/restream_test.go +++ b/restream/restream_test.go @@ -458,17 +458,19 @@ func TestOutputAddressValidation(t *testing.T) { } paths := map[string]res{ - "/dev/null": {"file:/dev/null", false}, - "/dev/../etc/passwd": {"/etc/passwd", true}, - "/dev/fb0": {"file:/dev/fb0", false}, - "/etc/passwd": {"/etc/passwd", true}, - "/core/data/../../etc/passwd": {"/etc/passwd", true}, - "/core/data/./etc/passwd": {"file:/core/data/etc/passwd", false}, - "file:/core/data/foobar": {"file:/core/data/foobar", false}, - "http://example.com": {"http://example.com", false}, - "-": {"pipe:", false}, - "tee:/core/data/foobar|http://example.com": {"tee:/core/data/foobar|http://example.com", false}, - "tee:/core/data/foobar|/etc/passwd": {"tee:/core/data/foobar|/etc/passwd", true}, + "/dev/null": {"file:/dev/null", false}, + "/dev/../etc/passwd": {"/etc/passwd", true}, + "/dev/fb0": {"file:/dev/fb0", false}, + "/etc/passwd": {"/etc/passwd", true}, + "/core/data/../../etc/passwd": {"/etc/passwd", true}, + "/core/data/./etc/passwd": {"file:/core/data/etc/passwd", false}, + "file:/core/data/foobar": {"file:/core/data/foobar", false}, + "http://example.com": {"http://example.com", false}, + "-": {"pipe:", false}, + "/core/data/foobar|http://example.com": {"file:/core/data/foobar|http://example.com", false}, + "/core/data/foobar|/etc/passwd": {"/core/data/foobar|/etc/passwd", true}, + "[f=null]-|[f=null]-": {"[f=null]pipe:|[f=null]pipe:", false}, + "[onfail=ignore]/core/data/archive-20121107.mkv|[f=mpegts]udp://10.0.1.255:1234/": {"[onfail=ignore]file:/core/data/archive-20121107.mkv|[f=mpegts]udp://10.0.1.255:1234/", false}, } for path, r := range paths {