From 96b5b6b34c293618824d12dfb29cdd5cec1c2e7e Mon Sep 17 00:00:00 2001
From: Jacob Kaplan-Moss <jacob@jacobian.org>
Date: Tue, 12 May 2009 22:02:38 +0000
Subject: [PATCH] Fixed #10643: fixed the formtools security hash to handle
 allowed empty forms or forms without changed data.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10753 bcc190cf-cafb-0310-a4f2-bffc1f526a37
---
 django/contrib/formtools/tests.py | 27 +++++++++++++++++++++------
 django/contrib/formtools/utils.py |  8 +++++++-
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/django/contrib/formtools/tests.py b/django/contrib/formtools/tests.py
index 8cfa08303b..86d40b963b 100644
--- a/django/contrib/formtools/tests.py
+++ b/django/contrib/formtools/tests.py
@@ -110,15 +110,30 @@ class SecurityHashTests(unittest.TestCase):
         leading/trailing whitespace so as to be friendly to broken browsers that
         submit it (usually in textareas).
         """
-        class TestForm(forms.Form):
-            name = forms.CharField()
-            bio = forms.CharField()
-        
-        f1 = TestForm({'name': 'joe', 'bio': 'Nothing notable.'})
-        f2 = TestForm({'name': '  joe', 'bio': 'Nothing notable.  '})
+        f1 = HashTestForm({'name': 'joe', 'bio': 'Nothing notable.'})
+        f2 = HashTestForm({'name': '  joe', 'bio': 'Nothing notable.  '})
         hash1 = utils.security_hash(None, f1)
         hash2 = utils.security_hash(None, f2)
         self.assertEqual(hash1, hash2)
+        
+    def test_empty_permitted(self):
+        """
+        Regression test for #10643: the security hash should allow forms with
+        empty_permitted = True, or forms where data has not changed.
+        """
+        f1 = HashTestBlankForm({})
+        f2 = HashTestForm({}, empty_permitted=True)
+        hash1 = utils.security_hash(None, f1)
+        hash2 = utils.security_hash(None, f2)
+        self.assertEqual(hash1, hash2)
+
+class HashTestForm(forms.Form):
+    name = forms.CharField()
+    bio = forms.CharField()
+
+class HashTestBlankForm(forms.Form):
+    name = forms.CharField(required=False)
+    bio = forms.CharField(required=False)
 
 #
 # FormWizard tests
diff --git a/django/contrib/formtools/utils.py b/django/contrib/formtools/utils.py
index 5be8b21928..44b8de1188 100644
--- a/django/contrib/formtools/utils.py
+++ b/django/contrib/formtools/utils.py
@@ -18,10 +18,16 @@ def security_hash(request, form, *args):
 
     data = []
     for bf in form:
-        value = bf.field.clean(bf.data) or ''
+        # Get the value from the form data. If the form allows empty or hasn't
+        # changed then don't call clean() to avoid trigger validation errors.
+        if form.empty_permitted and not form.has_changed():
+            value = bf.data or ''
+        else:
+            value = bf.field.clean(bf.data) or ''
         if isinstance(value, basestring):
             value = value.strip()
         data.append((bf.name, value))
+        
     data.extend(args)
     data.append(settings.SECRET_KEY)