You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

83 lines
3.2 KiB

  1. # Copyright 2019 New Vector Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from unittest.mock import Mock
  15. from synapse.media._base import add_file_headers, get_filename_from_headers
  16. from tests import unittest
  17. class GetFileNameFromHeadersTests(unittest.TestCase):
  18. # input -> expected result
  19. TEST_CASES = {
  20. b"attachment; filename=abc.txt": "abc.txt",
  21. b'attachment; filename="azerty"': "azerty",
  22. b'attachment; filename="aze%20rty"': "aze%20rty",
  23. b'attachment; filename="aze"rty"': 'aze"rty',
  24. b'attachment; filename="azer;ty"': "azer;ty",
  25. b"attachment; filename*=utf-8''foo%C2%A3bar": "foo£bar",
  26. }
  27. def tests(self) -> None:
  28. for hdr, expected in self.TEST_CASES.items():
  29. res = get_filename_from_headers({b"Content-Disposition": [hdr]})
  30. self.assertEqual(
  31. res,
  32. expected,
  33. f"expected output for {hdr!r} to be {expected} but was {res}",
  34. )
  35. class AddFileHeadersTests(unittest.TestCase):
  36. TEST_CASES = {
  37. # Safe values use inline.
  38. "text/plain": b"inline; filename=file.name",
  39. "text/csv": b"inline; filename=file.name",
  40. "image/png": b"inline; filename=file.name",
  41. # Unlisted values are set to attachment.
  42. "text/html": b"attachment; filename=file.name",
  43. "any/thing": b"attachment; filename=file.name",
  44. # Parameters get ignored.
  45. "text/plain; charset=utf-8": b"inline; filename=file.name",
  46. "text/markdown; charset=utf-8; variant=CommonMark": b"attachment; filename=file.name",
  47. # Parsed as lowercase.
  48. "Text/Plain": b"inline; filename=file.name",
  49. # Bad values don't choke.
  50. "": b"attachment; filename=file.name",
  51. ";": b"attachment; filename=file.name",
  52. }
  53. def test_content_disposition(self) -> None:
  54. for media_type, expected in self.TEST_CASES.items():
  55. request = Mock()
  56. add_file_headers(request, media_type, 0, "file.name")
  57. # There should be a single call to set Content-Disposition.
  58. for call in request.setHeader.call_args_list:
  59. args, _ = call
  60. if args[0] == b"Content-Disposition":
  61. break
  62. else:
  63. self.fail(f"No Content-Disposition header found for {media_type}")
  64. self.assertEqual(args[1], expected, media_type)
  65. def test_no_filename(self) -> None:
  66. request = Mock()
  67. add_file_headers(request, "text/plain", 0, None)
  68. request.setHeader.assert_any_call(b"Content-Disposition", b"inline")
  69. request.reset_mock()
  70. add_file_headers(request, "text/html", 0, None)
  71. request.setHeader.assert_any_call(b"Content-Disposition", b"attachment")