Sfoglia il codice sorgente

@uppy/companion: fix 500 when file name contains non-ASCII chars (#4493)

* @uppy/companion: fix 500 when file name contains non-ASCII chars

* Update packages/@uppy/companion/src/server/controllers/s3.js

* fixup! @uppy/companion: fix 500 when file name contains non-ASCII chars

* we need a lint rule for this
Antoine du Hamel 1 anno fa
parent
commit
f07697e7f4

+ 5 - 0
e2e/cypress/fixtures/images/١٠ كم мест для Нью-Йорке.pdf

@@ -0,0 +1,5 @@
+%PDF-1.
+1 0 obj<</Pages 2 0 R>>endobj
+2 0 obj<</Kids[3 0 R]/Count 1>>endobj
+3 0 obj<</Parent 2 0 R>>endobj
+trailer <</Root 1 0 R>>

+ 9 - 0
e2e/cypress/integration/dashboard-aws-multipart.spec.ts

@@ -14,6 +14,15 @@ describe('Dashboard with @uppy/aws-s3-multipart', () => {
     cy.wait(['@post', '@get', '@put'])
     cy.get('.uppy-StatusBar-statusPrimary').should('contain', 'Complete')
   })
+  it('should upload Russian poem image successfully', () => {
+    const fileName = '١٠ كم мест для Нью-Йорке.pdf'
+    cy.get('@file-input').selectFile(`cypress/fixtures/images/${fileName}`, { force:true })
+
+    cy.get('.uppy-StatusBar-actionBtn--upload').click()
+    cy.wait(['@post', '@get', '@put'])
+    cy.get('.uppy-Dashboard-Item-name').should('contain', fileName)
+    cy.get('.uppy-StatusBar-statusPrimary').should('contain', 'Complete')
+  })
 
   it('should handle retry request gracefully',  () => {
     cy.get('@file-input').selectFile('cypress/fixtures/images/cat.jpg', { force:true })

+ 9 - 1
packages/@uppy/companion/src/server/controllers/s3.js

@@ -1,5 +1,13 @@
 const express = require('express')
 
+function rfc2047Encode (data) {
+  // eslint-disable-next-line no-param-reassign
+  data = `${data}`
+  // eslint-disable-next-line no-control-regex
+  if (/^[\x00-\x7F]*$/.test(data)) return data // we return ASCII as is
+  return `=?UTF-8?B?${Buffer.from(data).toString('base64')}?=` // We encode non-ASCII strings
+}
+
 module.exports = function s3 (config) {
   if (typeof config.acl !== 'string' && config.acl != null) {
     throw new TypeError('s3: The `acl` option must be a string or null')
@@ -102,7 +110,7 @@ module.exports = function s3 (config) {
       Bucket: config.bucket,
       Key: key,
       ContentType: type,
-      Metadata: metadata,
+      Metadata: Object.fromEntries(Object.entries(metadata).map(entry => entry.map(rfc2047Encode))),
     }
 
     if (config.acl != null) params.ACL = config.acl