1. import re
    
  2. 
    
  3. from django.forms import CharField, Form, Media
    
  4. from django.http import HttpRequest, HttpResponse
    
  5. from django.middleware.csrf import (
    
  6.     CSRF_TOKEN_LENGTH,
    
  7.     CsrfViewMiddleware,
    
  8.     _unmask_cipher_token,
    
  9.     get_token,
    
  10. )
    
  11. from django.template import TemplateDoesNotExist, TemplateSyntaxError
    
  12. from django.template.backends.dummy import TemplateStrings
    
  13. from django.test import SimpleTestCase
    
  14. 
    
  15. 
    
  16. class TemplateStringsTests(SimpleTestCase):
    
  17.     engine_class = TemplateStrings
    
  18.     backend_name = "dummy"
    
  19.     options = {}
    
  20. 
    
  21.     @classmethod
    
  22.     def setUpClass(cls):
    
  23.         super().setUpClass()
    
  24.         params = {
    
  25.             "DIRS": [],
    
  26.             "APP_DIRS": True,
    
  27.             "NAME": cls.backend_name,
    
  28.             "OPTIONS": cls.options,
    
  29.         }
    
  30.         cls.engine = cls.engine_class(params)
    
  31. 
    
  32.     def test_from_string(self):
    
  33.         template = self.engine.from_string("Hello!\n")
    
  34.         content = template.render()
    
  35.         self.assertEqual(content, "Hello!\n")
    
  36. 
    
  37.     def test_get_template(self):
    
  38.         template = self.engine.get_template("template_backends/hello.html")
    
  39.         content = template.render({"name": "world"})
    
  40.         self.assertEqual(content, "Hello world!\n")
    
  41. 
    
  42.     def test_get_template_nonexistent(self):
    
  43.         with self.assertRaises(TemplateDoesNotExist) as e:
    
  44.             self.engine.get_template("template_backends/nonexistent.html")
    
  45.         self.assertEqual(e.exception.backend, self.engine)
    
  46. 
    
  47.     def test_get_template_syntax_error(self):
    
  48.         # There's no way to trigger a syntax error with the dummy backend.
    
  49.         # The test still lives here to factor it between other backends.
    
  50.         if self.backend_name == "dummy":
    
  51.             self.skipTest("test doesn't apply to dummy backend")
    
  52.         with self.assertRaises(TemplateSyntaxError):
    
  53.             self.engine.get_template("template_backends/syntax_error.html")
    
  54. 
    
  55.     def test_html_escaping(self):
    
  56.         template = self.engine.get_template("template_backends/hello.html")
    
  57.         context = {"name": '<script>alert("XSS!");</script>'}
    
  58.         content = template.render(context)
    
  59. 
    
  60.         self.assertIn("&lt;script&gt;", content)
    
  61.         self.assertNotIn("<script>", content)
    
  62. 
    
  63.     def test_django_html_escaping(self):
    
  64.         if self.backend_name == "dummy":
    
  65.             self.skipTest("test doesn't apply to dummy backend")
    
  66. 
    
  67.         class TestForm(Form):
    
  68.             test_field = CharField()
    
  69. 
    
  70.         media = Media(js=["my-script.js"])
    
  71.         form = TestForm()
    
  72.         template = self.engine.get_template("template_backends/django_escaping.html")
    
  73.         content = template.render({"media": media, "test_form": form})
    
  74. 
    
  75.         expected = "{}\n\n{}\n\n{}".format(media, form, form["test_field"])
    
  76. 
    
  77.         self.assertHTMLEqual(content, expected)
    
  78. 
    
  79.     def check_tokens_equivalent(self, token1, token2):
    
  80.         self.assertEqual(len(token1), CSRF_TOKEN_LENGTH)
    
  81.         self.assertEqual(len(token2), CSRF_TOKEN_LENGTH)
    
  82.         token1, token2 = map(_unmask_cipher_token, (token1, token2))
    
  83.         self.assertEqual(token1, token2)
    
  84. 
    
  85.     def test_csrf_token(self):
    
  86.         request = HttpRequest()
    
  87.         CsrfViewMiddleware(lambda req: HttpResponse()).process_view(
    
  88.             request, lambda r: None, (), {}
    
  89.         )
    
  90. 
    
  91.         template = self.engine.get_template("template_backends/csrf.html")
    
  92.         content = template.render(request=request)
    
  93. 
    
  94.         expected = '<input type="hidden" name="csrfmiddlewaretoken" value="([^"]+)">'
    
  95.         match = re.match(expected, content) or re.match(
    
  96.             expected.replace('"', "'"), content
    
  97.         )
    
  98.         self.assertTrue(match, "hidden csrftoken field not found in output")
    
  99.         self.check_tokens_equivalent(match[1], get_token(request))
    
  100. 
    
  101.     def test_no_directory_traversal(self):
    
  102.         with self.assertRaises(TemplateDoesNotExist):
    
  103.             self.engine.get_template("../forbidden/template_backends/hello.html")
    
  104. 
    
  105.     def test_non_ascii_characters(self):
    
  106.         template = self.engine.get_template("template_backends/hello.html")
    
  107.         content = template.render({"name": "Jérôme"})
    
  108.         self.assertEqual(content, "Hello Jérôme!\n")