=== added file 'django/template/loaders/util.py'
      
        
          
        
        
          
            |  |  |  | 
        
        
          
            |  | 1 | """ | 
          
            |  | 2 | Utility functions for template loaders. | 
          
            |  | 3 | """ | 
          
            |  | 4 |  | 
          
            |  | 5 | from os.path import abspath, join | 
          
            |  | 6 |  | 
          
            |  | 7 | def get_template_sources(template_name, template_dirs=None): | 
          
            |  | 8 | """ | 
          
            |  | 9 | Return a generater that will return the full paths of possible template | 
          
            |  | 10 | locations given the template_name and a list of template_dirs. | 
          
            |  | 11 | """ | 
          
            |  | 12 | if not template_dirs: | 
          
            |  | 13 | raise StopIteration | 
          
            |  | 14 | for template_dir in template_dirs: | 
          
            |  | 15 | full_template_dir = abspath(join(template_dir, template_name)) | 
          
            |  | 16 | # Security check to ensure that we are still in the template directory | 
          
            |  | 17 | # after the os.path.join (see ticket #4952). | 
          
            |  | 18 | if full_template_dir.startswith(template_dir): | 
          
            |  | 19 | yield full_template_dir | 
        
      
    
    
      
      
=== added directory 'tests/regressiontests/template_loaders'
=== added file 'tests/regressiontests/template_loaders/__init__.py'
=== added file 'tests/regressiontests/template_loaders/models.py'
=== added file 'tests/regressiontests/template_loaders/tests.py'
      
        
          
        
        
          
            |  |  |  | 
        
        
          
            |  | 1 | """ | 
          
            |  | 2 | >>> template_dirs = ['/dir1', '/dir2'] | 
          
            |  | 3 |  | 
          
            |  | 4 | >>> list(get_template_sources('index.html', template_dirs)) | 
          
            |  | 5 | ['/dir1/index.html', '/dir2/index.html'] | 
          
            |  | 6 |  | 
          
            |  | 7 | >>> list(get_template_sources('/etc/passwd', template_dirs)) | 
          
            |  | 8 | [] | 
          
            |  | 9 |  | 
          
            |  | 10 | >>> list(get_template_sources('etc/passwd', template_dirs)) | 
          
            |  | 11 | ['/dir1/etc/passwd', '/dir2/etc/passwd'] | 
          
            |  | 12 |  | 
          
            |  | 13 | >>> list(get_template_sources('../etc/passwd', template_dirs)) | 
          
            |  | 14 | [] | 
          
            |  | 15 |  | 
          
            |  | 16 | >>> list(get_template_sources('../../../etc/passwd', template_dirs)) | 
          
            |  | 17 | [] | 
          
            |  | 18 | """ | 
          
            |  | 19 |  | 
          
            |  | 20 | from django.template.loaders.util import get_template_sources | 
          
            |  | 21 |  | 
          
            |  | 22 | if __name__ == "__main__": | 
          
            |  | 23 | import doctest | 
          
            |  | 24 | doctest.testmod() | 
        
      
    
    
      
      
=== modified file 'django/template/loaders/app_directories.py'
      
        
          
        
        
          
            |  |  |  | 
        
        
          
            | 1 |  | # Wrapper for loading templates from "template" directories in installed app packages. | 
          
            |  | 1 | """ | 
          
            |  | 2 | Wrapper for loading templates from "template" directories in INSTALLED_APPS | 
          
            |  | 3 | packages. | 
          
            |  | 4 | """ | 
          
            |  | 5 |  | 
          
            |  | 6 | import os | 
        
        
          
            | 2 | 7 |  | 
          
            | 3 | 8 | from django.conf import settings | 
          
            | 4 | 9 | from django.core.exceptions import ImproperlyConfigured | 
          
            | 5 | 10 | from django.template import TemplateDoesNotExist | 
        
        
          
            | 6 |  | import os | 
          
            |  | 11 | from django.template.loaders.util import get_template_sources | 
        
        
          
            | 7 | 12 |  | 
          
            | 8 | 13 | # At compile time, cache the directories to search. | 
          
            | 9 | 14 | app_template_dirs = [] | 
        
        
          
            | … | … |  | 
        
        
          
            | 27 | 32 | # It won't change, so convert it to a tuple to save memory. | 
          
            | 28 | 33 | app_template_dirs = tuple(app_template_dirs) | 
          
            | 29 | 34 |  | 
        
        
          
            | 30 |  | def get_template_sources(template_name, template_dirs=None): | 
          
            | 31 |  |     for template_dir in app_template_dirs: | 
          
            | 32 |  |         yield os.path.join(template_dir, template_name) | 
          
            | 33 |  |  | 
        
        
          
            | 34 | 35 | def load_template_source(template_name, template_dirs=None): | 
        
        
          
            |  | 36 | if not template_dirs: | 
          
            |  | 37 | template_dirs = app_template_dirs | 
        
        
          
            | 35 | 38 | for filepath in get_template_sources(template_name, template_dirs): | 
          
            | 36 | 39 | try: | 
          
            | 37 | 40 | return (open(filepath).read().decode(settings.FILE_CHARSET), filepath) | 
        
      
    
    
      
      
=== modified file 'django/template/loaders/filesystem.py'
      
        
          
        
        
          
            |  |  |  | 
        
        
          
            | 1 |  | # Wrapper for loading templates from the filesystem. | 
          
            |  | 1 | """ | 
          
            |  | 2 | Wrapper for loading templates from the filesystem. | 
          
            |  | 3 | """ | 
        
        
          
            | 2 | 4 |  | 
          
            | 3 | 5 | from django.conf import settings | 
          
            | 4 | 6 | from django.template import TemplateDoesNotExist | 
        
        
          
            | 5 |  | import os | 
          
            |  | 7 | from django.template.loaders.util import get_template_sources | 
        
        
          
            | 6 | 8 |  | 
        
        
          
            | 7 |  | def get_template_sources(template_name, template_dirs=None): | 
          
            |  | 9 | def load_template_source(template_name, template_dirs=None): | 
        
        
          
            | 8 | 10 | if not template_dirs: | 
          
            | 9 | 11 | template_dirs = settings.TEMPLATE_DIRS | 
        
        
          
            | 10 |  |     for template_dir in template_dirs: | 
          
            | 11 |  |         yield os.path.join(template_dir, template_name) | 
          
            | 12 |  |  | 
          
            | 13 |  | def load_template_source(template_name, template_dirs=None): | 
        
        
          
            | 14 | 12 | tried = [] | 
          
            | 15 | 13 | for filepath in get_template_sources(template_name, template_dirs): | 
          
            | 16 | 14 | try: |