Blob Blame History Raw
--- jinja2/bccache.py.orig	2011-07-12 14:02:32.000000000 +0200
+++ jinja2/bccache.py	2014-05-30 13:15:12.850410773 +0200
@@ -20,6 +20,9 @@
 import tempfile
 import cPickle as pickle
 import fnmatch
+import os
+import errno
+import stat
 try:
     from hashlib import sha1
 except ImportError:
@@ -194,7 +197,9 @@
     two arguments: The directory where the cache items are stored and a
     pattern string that is used to build the filename.
 
-    If no directory is specified the system temporary items folder is used.
+    If no directory is specified a default cache directory is selected.  On
+    Windows the user's temp directory is used, on UNIX systems a directory
+    is created for the user in the system temp directory.
 
     The pattern can be used to have multiple separate caches operate on the
     same directory.  The default pattern is ``'__jinja2_%s.cache'``.  ``%s``
@@ -207,10 +212,39 @@
 
     def __init__(self, directory=None, pattern='__jinja2_%s.cache'):
         if directory is None:
-            directory = tempfile.gettempdir()
+            directory = self._get_default_cache_dir()
         self.directory = directory
         self.pattern = pattern
 
+    def _get_default_cache_dir(self):
+        tmpdir = tempfile.gettempdir()
+
+        # On windows the temporary directory is used specific unless
+        # explicitly forced otherwise.  We can just use that.
+        if os.name == 'nt':
+            return tmpdir
+        if not hasattr(os, 'getuid'):
+            raise RuntimeError('Cannot determine safe temp directory.  You '
+                               'need to explicitly provide one.')
+
+        dirname = '_jinja2-cache-%d' % os.getuid()
+        actual_dir = os.path.join(tmpdir, dirname)
+        try:
+            os.mkdir(actual_dir, stat.S_IRWXU) # 0o700
+        except OSError as e:
+            if e.errno != errno.EEXIST:
+                raise
+
+        actual_dir_stat = os.lstat(actual_dir)
+        if actual_dir_stat.st_uid != os.getuid() \
+                or not stat.S_ISDIR(actual_dir_stat.st_mode) \
+                or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU:
+            raise RuntimeError('Temporary directory \'%s\' has an incorrect '
+                              'owner, permissions, or type.' % actual_dir)
+
+
+        return actual_dir
+
     def _get_cache_filename(self, bucket):
         return path.join(self.directory, self.pattern % bucket.key)