fix: filename case (#351)

This commit is contained in:
Julien Neuhart
2021-09-15 17:41:03 +02:00
committed by GitHub
parent 13e6c2dbeb
commit 6e47f16fe1
9 changed files with 118 additions and 13 deletions

View File

@@ -125,10 +125,9 @@ func newContext(echoCtx echo.Context, logger *zap.Logger, timeout time.Duration)
copyToDisk := func(fh *multipart.FileHeader) error {
// Avoid directory traversal and normalize filename.
// See https://github.com/gotenberg/gotenberg/issues/104.
// See https://github.com/gotenberg/gotenberg/issues/228.
t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
filename, _, err := transform.String(t, strings.ToLower(filepath.Base(fh.Filename)))
filename, _, err := transform.String(t, filepath.Base(fh.Filename))
if err != nil {
return fmt.Errorf("transform filename: %w", err)
}

View File

@@ -396,7 +396,9 @@ func (form *FormData) mustAssign(key, value string, target interface{}) *FormDat
// path binds the absolute path of a form data file to a string variable.
func (form *FormData) path(filename string, target *string) *FormData {
for name, path := range form.files {
if name == filename {
// See https://github.com/gotenberg/gotenberg/issues/228.
nameLowerExt := strings.TrimSuffix(name, filepath.Ext(name)) + strings.ToLower(filepath.Ext(name))
if name == filename || nameLowerExt == filename {
*target = path
return form
}

View File

@@ -850,6 +850,7 @@ func TestFormData_MandatoryPath(t *testing.T) {
func TestFormData_Content(t *testing.T) {
for i, tc := range []struct {
form *FormData
filename string
defaultValue string
expect string
expectErr bool
@@ -863,6 +864,7 @@ func TestFormData_Content(t *testing.T) {
"bar": "/bar",
},
},
filename: "foo",
},
{
form: &FormData{
@@ -870,6 +872,7 @@ func TestFormData_Content(t *testing.T) {
"bar": "/bar",
},
},
filename: "foo",
defaultValue: "foo",
expect: "foo",
},
@@ -879,6 +882,7 @@ func TestFormData_Content(t *testing.T) {
"foo": "/foo",
},
},
filename: "foo",
expectErr: true,
},
{
@@ -887,12 +891,31 @@ func TestFormData_Content(t *testing.T) {
"foo": "/tests/test/testdata/api/sample1.txt",
},
},
expect: "foo",
filename: "foo",
expect: "foo",
},
{
form: &FormData{
files: map[string]string{
"foo.TXT": "/tests/test/testdata/api/sample1.txt",
},
},
filename: "foo.txt",
expect: "foo",
},
{
form: &FormData{
files: map[string]string{
"foo.txt": "/tests/test/testdata/api/sample1.txt",
},
},
filename: "foo.txt",
expect: "foo",
},
} {
var actual string
tc.form.Content("foo", &actual, tc.defaultValue)
tc.form.Content(tc.filename, &actual, tc.defaultValue)
if actual != tc.expect {
t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual)
@@ -911,11 +934,13 @@ func TestFormData_Content(t *testing.T) {
func TestFormData_MandatoryContent(t *testing.T) {
for i, tc := range []struct {
form *FormData
filename string
expect string
expectErr bool
}{
{
form: &FormData{},
filename: "foo",
expectErr: true,
},
{
@@ -924,6 +949,7 @@ func TestFormData_MandatoryContent(t *testing.T) {
"bar": "/bar",
},
},
filename: "foo",
expectErr: true,
},
{
@@ -932,6 +958,7 @@ func TestFormData_MandatoryContent(t *testing.T) {
"foo": "/foo",
},
},
filename: "foo",
expectErr: true,
},
{
@@ -940,12 +967,31 @@ func TestFormData_MandatoryContent(t *testing.T) {
"foo": "/tests/test/testdata/api/sample1.txt",
},
},
expect: "foo",
filename: "foo",
expect: "foo",
},
{
form: &FormData{
files: map[string]string{
"foo.TXT": "/tests/test/testdata/api/sample1.txt",
},
},
filename: "foo.txt",
expect: "foo",
},
{
form: &FormData{
files: map[string]string{
"foo.txt": "/tests/test/testdata/api/sample1.txt",
},
},
filename: "foo.txt",
expect: "foo",
},
} {
var actual string
tc.form.MandatoryContent("foo", &actual)
tc.form.MandatoryContent(tc.filename, &actual)
if actual != tc.expect {
t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expect, actual)
@@ -995,6 +1041,21 @@ func TestFormData_Paths(t *testing.T) {
},
expectCount: 2,
},
{
form: &FormData{
files: map[string]string{
"foo.zip": "/foo.zip",
"b.PDF": "/b.PDF",
"a.pdf": "/a.pdf",
},
},
extensions: []string{".pdf"},
expect: []string{
"/a.pdf",
"/b.PDF",
},
expectCount: 2,
},
} {
var actual []string
@@ -1051,6 +1112,21 @@ func TestFormData_MandatoryPaths(t *testing.T) {
},
expectCount: 2,
},
{
form: &FormData{
files: map[string]string{
"foo.zip": "/foo.zip",
"b.PDF": "/b.PDF",
"a.pdf": "/a.pdf",
},
},
extensions: []string{".pdf"},
expect: []string{
"/a.pdf",
"/b.PDF",
},
expectCount: 2,
},
} {
var actual []string

View File

@@ -111,7 +111,7 @@ func TestHttpErrorHandler(t *testing.T) {
func() {
rand.Seed(time.Now().UnixNano())
webhookPort := rand.Intn(65535 - 1025 + 1) + 1025
webhookPort := rand.Intn(65535-1025+1) + 1025
tc.webhookClient.errorURL = fmt.Sprintf(tc.webhookClient.errorURL, webhookPort)
@@ -825,7 +825,7 @@ func TestContextMiddlewareWithWebhook(t *testing.T) {
webhook.HidePort = true
rand.Seed(time.Now().UnixNano())
webhookPort := rand.Intn(65535 - 1025 + 1) + 1025
webhookPort := rand.Intn(65535-1025+1) + 1025
if tc.autoWebhookURLs {
c.Request().Header.Set("Gotenberg-Webhook-Url", fmt.Sprintf("http://localhost:%d/", webhookPort))