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.

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from django.core.exceptions import (
  2. ImproperlyConfigured, SuspiciousFileOperation,
  3. )
  4. from django.template.utils import get_app_template_dirs
  5. from django.utils._os import safe_join
  6. from django.utils.functional import cached_property
  7. class BaseEngine:
  8. # Core methods: engines have to provide their own implementation
  9. # (except for from_string which is optional).
  10. def __init__(self, params):
  11. """
  12. Initialize the template engine.
  13. `params` is a dict of configuration settings.
  14. """
  15. params = params.copy()
  16. self.name = params.pop('NAME')
  17. self.dirs = list(params.pop('DIRS'))
  18. self.app_dirs = params.pop('APP_DIRS')
  19. if params:
  20. raise ImproperlyConfigured(
  21. "Unknown parameters: {}".format(", ".join(params)))
  22. @property
  23. def app_dirname(self):
  24. raise ImproperlyConfigured(
  25. "{} doesn't support loading templates from installed "
  26. "applications.".format(self.__class__.__name__))
  27. def from_string(self, template_code):
  28. """
  29. Create and return a template for the given source code.
  30. This method is optional.
  31. """
  32. raise NotImplementedError(
  33. "subclasses of BaseEngine should provide "
  34. "a from_string() method")
  35. def get_template(self, template_name):
  36. """
  37. Load and return a template for the given name.
  38. Raise TemplateDoesNotExist if no such template exists.
  39. """
  40. raise NotImplementedError(
  41. "subclasses of BaseEngine must provide "
  42. "a get_template() method")
  43. # Utility methods: they are provided to minimize code duplication and
  44. # security issues in third-party backends.
  45. @cached_property
  46. def template_dirs(self):
  47. """
  48. Return a list of directories to search for templates.
  49. """
  50. # Immutable return value because it's cached and shared by callers.
  51. template_dirs = tuple(self.dirs)
  52. if self.app_dirs:
  53. template_dirs += get_app_template_dirs(self.app_dirname)
  54. return template_dirs
  55. def iter_template_filenames(self, template_name):
  56. """
  57. Iterate over candidate files for template_name.
  58. Ignore files that don't lie inside configured template dirs to avoid
  59. directory traversal attacks.
  60. """
  61. for template_dir in self.template_dirs:
  62. try:
  63. yield safe_join(template_dir, template_name)
  64. except SuspiciousFileOperation:
  65. # The joined path was located outside of this template_dir
  66. # (it might be inside another one, so this isn't fatal).
  67. pass