diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index 835b1a9..91bc169 100644
--- a/django/template/defaulttags.py
+++ b/django/template/defaulttags.py
@@ -2,6 +2,7 @@
 
 import sys
 import re
+import os
 from itertools import cycle as itertools_cycle
 try:
     reversed
@@ -287,20 +288,25 @@ class SsiNode(Node):
         self.filepath, self.parsed = filepath, parsed
 
     def render(self, context):
-        if not include_is_allowed(self.filepath):
+        filepath = self.filepath
+        try:
+            filepath = filepath.resolve(context)
+        except (AttributeError, VariableDoesNotExist):
+            pass
+        if not include_is_allowed(filepath):
             if settings.DEBUG:
                 return "[Didn't have permission to include file]"
             else:
                 return '' # Fail silently for invalid includes.
         try:
-            fp = open(self.filepath, 'r')
+            fp = open(filepath, 'r')
             output = fp.read()
             fp.close()
         except IOError:
             output = ''
         if self.parsed:
             try:
-                t = Template(output, name=self.filepath)
+                t = Template(output, name=filepath)
                 return t.render(context)
             except TemplateSyntaxError, e:
                 if settings.DEBUG:
@@ -377,7 +383,7 @@ class URLNode(Node):
                 except NoReverseMatch:
                     if self.asvar is None:
                         # Re-raise the original exception, not the one with
-                        # the path relative to the project. This makes a 
+                        # the path relative to the project. This makes a
                         # better error message.
                         raise e
             else:
@@ -897,7 +903,12 @@ def ssi(parser, token):
         else:
             raise TemplateSyntaxError("Second (optional) argument to %s tag"
                                       " must be 'parsed'" % bits[0])
-    return SsiNode(bits[1], parsed)
+    var = bits[1]
+    #For backwards compatibility, let things that look like a path be quoted.
+    if os.path.sep in var and var[0] != "'" and var[0] != '"':
+        var = '"' + var + '"'
+    var = parser.compile_filter(var)
+    return SsiNode(var, parsed)
 ssi = register.tag(ssi)
 
 #@register.tag
diff --git a/tests/regressiontests/templates/ssi_include.html b/tests/regressiontests/templates/ssi_include.html
new file mode 100755
index 0000000..58d5926
--- /dev/null
+++ b/tests/regressiontests/templates/ssi_include.html
@@ -0,0 +1 @@
+This is for testing an ssi include. {{ test }}
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 953e8fa..6767778 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -69,7 +69,7 @@ class SomeException(Exception):
 
 class SomeOtherException(Exception):
     pass
-    
+
 class ContextStackException(Exception):
     pass
 
@@ -211,6 +211,9 @@ class Templates(unittest.TestCase):
         old_invalid = settings.TEMPLATE_STRING_IF_INVALID
         expected_invalid_str = 'INVALID'
 
+        #Set ALLOWED_INCLUDE_ROOTS so that ssi works.
+        old_allowed, settings.ALLOWED_INCLUDE_ROOTS = settings.ALLOWED_INCLUDE_ROOTS, os.path.dirname(os.path.abspath(__file__))
+
         for name, vals in tests:
             if isinstance(vals[2], tuple):
                 normal_string_result = vals[2][0]
@@ -257,6 +260,7 @@ class Templates(unittest.TestCase):
         deactivate()
         settings.TEMPLATE_DEBUG = old_td
         settings.TEMPLATE_STRING_IF_INVALID = old_invalid
+        settings.ALLOWED_INCLUDE_ROOTS = old_allowed
 
         self.assertEqual(failures, [], "Tests failed:\n%s\n%s" %
             ('-'*70, ("\n%s\n" % ('-'*70)).join(failures)))
@@ -915,6 +919,20 @@ class Templates(unittest.TestCase):
                           '{% endfor %}',
                           {}, ''),
 
+            ### SSI TAG ########################################################
+            #Test normal behavior
+            'ssi01': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),
+            'ssi02': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),
+            #Test passing as a variable
+            'ssi03': ('{% ssi ssi_file %}', {'ssi_file': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ssi_include.html')}, 'This is for testing an ssi include. {{ test }}\n'),
+            'ssi04': ('{% ssi ssi_file %}', {'ssi_file': 'no_file'}, ''),
+            #Test parsed output
+            'ssi05': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),
+            'ssi06': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''),
+            #Test quoting
+            'ssi07': ('{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),
+            'ssi08': ('{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),
+
             ### TEMPLATETAG TAG #######################################################
             'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
             'templatetag02': ('{% templatetag closeblock %}', {}, '%}'),
