Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop attachment requirements for media download #646

Merged
merged 11 commits into from
Sep 29, 2023
3 changes: 3 additions & 0 deletions internal/data/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ var MatrixPng []byte

//go:embed large.png
var LargePng []byte

//go:embed matrix-logo.svg
var MatrixSvg []byte
18 changes: 18 additions & 0 deletions internal/data/matrix-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 58 additions & 18 deletions tests/media_filename_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/matrix-org/complement/internal/b"
"github.com/matrix-org/complement/internal/client"
"github.com/matrix-org/complement/internal/data"
"github.com/matrix-org/complement/runtime"
)

const asciiFileName = "ascii"
Expand Down Expand Up @@ -43,8 +44,9 @@ func TestMediaFilenames(t *testing.T) {

mxcUri := alice.UploadContent(t, data.MatrixPng, filename, "image/png")

name := downloadForFilename(t, alice, mxcUri, "")
name, _ := downloadForFilename(t, alice, mxcUri, "")

// filename is not required, but if it's an attachment then check it matches
if name != filename {
t.Fatalf("Incorrect filename '%s', expected '%s'", name, filename)
}
Expand All @@ -55,10 +57,11 @@ func TestMediaFilenames(t *testing.T) {
t.Run("Can download specifying a different ASCII file name", func(t *testing.T) {
t.Parallel()

mxcUri := alice.UploadContent(t, data.MatrixPng, "test.png", "image/png")
mxcUri := alice.UploadContent(t, data.MatrixPng, asciiFileName, "image/png")

const altName = "file.png"
filename := downloadForFilename(t, alice, mxcUri, altName)
filename, _ := downloadForFilename(t, alice, mxcUri, altName)

if filename != altName {
t.Fatalf("filename did not match, expected '%s', got '%s'", altName, filename)
}
Expand All @@ -83,7 +86,8 @@ func TestMediaFilenames(t *testing.T) {

const diffUnicodeFilename = "\u2615" // coffee emoji

filename := downloadForFilename(t, alice, mxcUri, diffUnicodeFilename)
filename, _ := downloadForFilename(t, alice, mxcUri, diffUnicodeFilename)

if filename != diffUnicodeFilename {
t.Fatalf("filename did not match, expected '%s', got '%s'", diffUnicodeFilename, filename)
}
Expand All @@ -95,7 +99,7 @@ func TestMediaFilenames(t *testing.T) {

mxcUri := alice.UploadContent(t, data.MatrixPng, unicodeFileName, "image/png")

filename := downloadForFilename(t, alice, mxcUri, "")
filename, _ := downloadForFilename(t, alice, mxcUri, "")

if filename != unicodeFileName {
t.Fatalf("filename did not match, expected '%s', got '%s'", unicodeFileName, filename)
Expand All @@ -108,18 +112,54 @@ func TestMediaFilenames(t *testing.T) {

mxcUri := alice.UploadContent(t, data.MatrixPng, unicodeFileName, "image/png")

filename := downloadForFilename(t, bob, mxcUri, "")
filename, _ := downloadForFilename(t, bob, mxcUri, "")

if filename != unicodeFileName {
t.Fatalf("filename did not match, expected '%s', got '%s'", unicodeFileName, filename)
}
})

t.Run("Will serve safe media types as inline", func(t *testing.T) {
if runtime.Homeserver != runtime.Synapse {
// We need to check that this security behaviour is being correctly run in
// Synapse, but since this is not part of the Matrix spec we do not assume
// other homeservers are doing so.
t.Skip("Skipping test of Content-Disposition header requirements on non-Synapse homeserver")
}
t.Parallel()

mxcUri := alice.UploadContent(t, data.MatrixPng, "", "image/png")

_, isAttachment := downloadForFilename(t, bob, mxcUri, "")

if isAttachment {
t.Fatal("Expected file to be served as inline")
}
})

t.Run("Will serve unsafe media types as attachments", func(t *testing.T) {
if runtime.Homeserver != runtime.Synapse {
// We need to check that this security behaviour is being correctly run in
// Synapse, but since this is not part of the Matrix spec we do not assume
// other homeservers are doing so.
t.Skip("Skipping test of Content-Disposition header requirements on non-Synapse homeserver")
}
t.Parallel()

mxcUri := alice.UploadContent(t, data.MatrixSvg, "", "image/svg")

_, isAttachment := downloadForFilename(t, bob, mxcUri, "")

if !isAttachment {
t.Fatal("Expected file to be served as an attachment")
}
})
})
})
}

// Returns content disposition information like (mediatype, filename)
func downloadForFilename(t *testing.T, c *client.CSAPI, mxcUri string, diffName string) string {
// Returns content disposition information like (filename, isAttachment)
func downloadForFilename(t *testing.T, c *client.CSAPI, mxcUri string, diffName string) (filename string, isAttachment bool) {
t.Helper()

origin, mediaId := client.SplitMxc(mxcUri)
Expand All @@ -138,16 +178,16 @@ func downloadForFilename(t *testing.T, c *client.CSAPI, mxcUri string, diffName
if err != nil {
t.Fatalf("Got err when parsing content disposition: %s", err)
}

if mediaType != "attachment" {
t.Fatalf("Found unexpected mediatype %s, expected attachment", mediaType)
filename, hasFilename := params["filename"]
if mediaType == "attachment" {
if hasFilename {
return filename, true
} else {
return "", true
clokep marked this conversation as resolved.
Show resolved Hide resolved
}
}

if filename, ok := params["filename"]; ok {
return filename
} else {
t.Fatalf("Content Disposition did not have filename")

return ""
if mediaType != "inline" {
t.Fatalf("Found unexpected mediatype %s, expected 'attachment' or 'inline'", mediaType)
}
return filename, false
}
Loading