mirror of
https://github.com/filebrowser/filebrowser.git
synced 2026-07-17 16:36:49 +00:00
fix: preserve SRT subtitle line breaks (#6002)
This commit is contained in:
parent
6209f8fddd
commit
d9cf2f0100
2 changed files with 75 additions and 1 deletions
|
|
@ -2,7 +2,9 @@ package fbhttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/asticode/go-astisub"
|
"github.com/asticode/go-astisub"
|
||||||
|
|
@ -10,6 +12,8 @@ import (
|
||||||
"github.com/filebrowser/filebrowser/v2/files"
|
"github.com/filebrowser/filebrowser/v2/files"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var srtLineBreakTag = regexp.MustCompile(`(?i)<br(?:\s+[^>]*)?\s*/?>`)
|
||||||
|
|
||||||
var subtitleHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var subtitleHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
if !d.user.Perm.Download {
|
if !d.user.Perm.Download {
|
||||||
return http.StatusAccepted, nil
|
return http.StatusAccepted, nil
|
||||||
|
|
@ -49,7 +53,11 @@ func subtitleFileHandler(w http.ResponseWriter, r *http.Request, file *files.Fil
|
||||||
// load subtitle for conversion to vtt
|
// load subtitle for conversion to vtt
|
||||||
var sub *astisub.Subtitles
|
var sub *astisub.Subtitles
|
||||||
if strings.HasSuffix(file.Name, ".srt") {
|
if strings.HasSuffix(file.Name, ".srt") {
|
||||||
sub, err = astisub.ReadFromSRT(fd)
|
content, readErr := io.ReadAll(fd)
|
||||||
|
if readErr != nil {
|
||||||
|
return http.StatusInternalServerError, readErr
|
||||||
|
}
|
||||||
|
sub, err = astisub.ReadFromSRT(bytes.NewReader(normalizeSRTLineBreaks(content)))
|
||||||
} else if strings.HasSuffix(file.Name, ".ass") || strings.HasSuffix(file.Name, ".ssa") {
|
} else if strings.HasSuffix(file.Name, ".ass") || strings.HasSuffix(file.Name, ".ssa") {
|
||||||
sub, err = astisub.ReadFromSSA(fd)
|
sub, err = astisub.ReadFromSSA(fd)
|
||||||
}
|
}
|
||||||
|
|
@ -78,3 +86,7 @@ func subtitleFileHandler(w http.ResponseWriter, r *http.Request, file *files.Fil
|
||||||
http.ServeContent(w, r, file.Name, file.ModTime, bytes.NewReader(buf.Bytes()))
|
http.ServeContent(w, r, file.Name, file.ModTime, bytes.NewReader(buf.Bytes()))
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizeSRTLineBreaks(content []byte) []byte {
|
||||||
|
return srtLineBreakTag.ReplaceAll(content, []byte("\n"))
|
||||||
|
}
|
||||||
|
|
|
||||||
62
http/subtitle_test.go
Normal file
62
http/subtitle_test.go
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
package fbhttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/files"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNormalizeSRTLineBreaks(t *testing.T) {
|
||||||
|
input := []byte("first<br>second<BR/>third<br />fourth<br class=\"x\">fifth")
|
||||||
|
got := string(normalizeSRTLineBreaks(input))
|
||||||
|
want := "first\nsecond\nthird\nfourth\nfifth"
|
||||||
|
if got != want {
|
||||||
|
t.Fatalf("normalizeSRTLineBreaks() = %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSubtitleFileHandlerConvertsSRTBreakTags(t *testing.T) {
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
const path = "/sample.srt"
|
||||||
|
const content = "1\n" +
|
||||||
|
"00:00:01,000 --> 00:00:02,000\n" +
|
||||||
|
"First<br>Second<BR/>Third<br />Fourth\n\n"
|
||||||
|
|
||||||
|
if err := afero.WriteFile(fs, path, []byte(content), 0o644); err != nil {
|
||||||
|
t.Fatalf("failed to write subtitle: %v", err)
|
||||||
|
}
|
||||||
|
info, err := fs.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to stat subtitle: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
file := &files.FileInfo{
|
||||||
|
Fs: fs,
|
||||||
|
Path: path,
|
||||||
|
Name: "sample.srt",
|
||||||
|
ModTime: info.ModTime(),
|
||||||
|
}
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/api/subtitle/sample.srt?inline=true", http.NoBody)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
status, err := subtitleFileHandler(rec, req, file)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("subtitleFileHandler returned error: %v", err)
|
||||||
|
}
|
||||||
|
if status != 0 {
|
||||||
|
t.Fatalf("subtitleFileHandler status = %d, want 0", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
body := rec.Body.String()
|
||||||
|
if strings.Contains(body, "FirstSecond") {
|
||||||
|
t.Fatalf("WebVTT output collapsed SRT <br> tags: %q", body)
|
||||||
|
}
|
||||||
|
if !strings.Contains(body, "First\nSecond\nThird\nFourth") {
|
||||||
|
t.Fatalf("WebVTT output = %q, want converted SRT <br> tags as line breaks", body)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue