18 | | class CommentForm(forms.Form): |
19 | | name = forms.CharField(label=_("Name"), max_length=50) |
20 | | email = forms.EmailField(label=_("Email address")) |
21 | | url = forms.URLField(label=_("URL"), required=False) |
22 | | comment = forms.CharField(label=_('Comment'), widget=forms.Textarea, |
23 | | max_length=COMMENT_MAX_LENGTH) |
24 | | honeypot = forms.CharField(required=False, |
25 | | label=_('If you enter anything in this field '\ |
26 | | 'your comment will be treated as spam')) |
| 18 | class BaseCommentForm(forms.Form): |
37 | | super(CommentForm, self).__init__(data=data, initial=initial) |
| 29 | super(BaseCommentForm, self).__init__(data=data, initial=initial) |
| 30 | |
| 31 | def generate_security_data(self): |
| 32 | """Generate a dict of security data for "initial" data.""" |
| 33 | timestamp = int(time.time()) |
| 34 | security_dict = { |
| 35 | 'content_type' : str(self.target_object._meta), |
| 36 | 'object_pk' : str(self.target_object._get_pk_val()), |
| 37 | 'timestamp' : str(timestamp), |
| 38 | 'security_hash' : self.initial_security_hash(timestamp), |
| 39 | } |
| 40 | return security_dict |
| 41 | |
| 42 | def initial_security_hash(self, timestamp): |
| 43 | """ |
| 44 | Generate the initial security hash from self.content_object |
| 45 | and a (unix) timestamp. |
| 46 | """ |
| 47 | |
| 48 | initial_security_dict = { |
| 49 | 'content_type' : str(self.target_object._meta), |
| 50 | 'object_pk' : str(self.target_object._get_pk_val()), |
| 51 | 'timestamp' : str(timestamp), |
| 52 | } |
| 53 | return self.generate_security_hash(**initial_security_dict) |
| 54 | |
| 55 | def generate_security_hash(self, content_type, object_pk, timestamp): |
| 56 | """Generate a (SHA1) security hash from the provided info.""" |
| 57 | info = (content_type, object_pk, timestamp, settings.SECRET_KEY) |
| 58 | return sha_constructor("".join(info)).hexdigest() |
| 59 | |
| 60 | def security_errors(self): |
| 61 | """Return just those errors associated with security""" |
| 62 | errors = ErrorDict() |
| 63 | for f in ["timestamp", "security_hash"]: |
| 64 | if f in self.errors: |
| 65 | errors[f] = self.errors[f] |
| 66 | return errors |
| 67 | |
| 68 | def clean_security_hash(self): |
| 69 | """Check the security hash.""" |
| 70 | security_hash_dict = { |
| 71 | 'content_type' : self.data.get("content_type", ""), |
| 72 | 'object_pk' : self.data.get("object_pk", ""), |
| 73 | 'timestamp' : self.data.get("timestamp", ""), |
| 74 | } |
| 75 | expected_hash = self.generate_security_hash(**security_hash_dict) |
| 76 | actual_hash = self.cleaned_data["security_hash"] |
| 77 | if expected_hash != actual_hash: |
| 78 | raise forms.ValidationError("Security hash check failed.") |
| 79 | return actual_hash |
| 80 | |
| 81 | def clean_timestamp(self): |
| 82 | """Make sure the timestamp isn't too far (> 2 hours) in the past.""" |
| 83 | ts = self.cleaned_data["timestamp"] |
| 84 | if time.time() - ts > (2 * 60 * 60): |
| 85 | raise forms.ValidationError("Timestamp check failed") |
| 86 | return ts |
| 87 | |
| 88 | class MetaCommentForm(BaseCommentForm): |
| 89 | name = forms.CharField(label=_("Name"), max_length=50) |
| 90 | email = forms.EmailField(label=_("Email address")) |
| 91 | url = forms.URLField(label=_("URL"), required=False) |
| 92 | comment = forms.CharField(label=_('Comment'), widget=forms.Textarea, |
| 93 | max_length=COMMENT_MAX_LENGTH) |
79 | | def security_errors(self): |
80 | | """Return just those errors associated with security""" |
81 | | errors = ErrorDict() |
82 | | for f in ["honeypot", "timestamp", "security_hash"]: |
83 | | if f in self.errors: |
84 | | errors[f] = self.errors[f] |
85 | | return errors |
86 | | |
87 | | def clean_honeypot(self): |
88 | | """Check that nothing's been entered into the honeypot.""" |
89 | | value = self.cleaned_data["honeypot"] |
90 | | if value: |
91 | | raise forms.ValidationError(self.fields["honeypot"].label) |
92 | | return value |
93 | | |
94 | | def clean_security_hash(self): |
95 | | """Check the security hash.""" |
96 | | security_hash_dict = { |
97 | | 'content_type' : self.data.get("content_type", ""), |
98 | | 'object_pk' : self.data.get("object_pk", ""), |
99 | | 'timestamp' : self.data.get("timestamp", ""), |
100 | | } |
101 | | expected_hash = self.generate_security_hash(**security_hash_dict) |
102 | | actual_hash = self.cleaned_data["security_hash"] |
103 | | if expected_hash != actual_hash: |
104 | | raise forms.ValidationError("Security hash check failed.") |
105 | | return actual_hash |
106 | | |
107 | | def clean_timestamp(self): |
108 | | """Make sure the timestamp isn't too far (> 2 hours) in the past.""" |
109 | | ts = self.cleaned_data["timestamp"] |
110 | | if time.time() - ts > (2 * 60 * 60): |
111 | | raise forms.ValidationError("Timestamp check failed") |
112 | | return ts |
113 | | |
147 | | initial_security_dict = { |
148 | | 'content_type' : str(self.target_object._meta), |
149 | | 'object_pk' : str(self.target_object._get_pk_val()), |
150 | | 'timestamp' : str(timestamp), |
151 | | } |
152 | | return self.generate_security_hash(**initial_security_dict) |
| 157 | def security_errors(self): |
| 158 | errors = super(CommentForm, self).security_errors() |
| 159 | if 'honeypot' in self.errors: |
| 160 | errors['honeypot'] = self.errors['honeypot'] |
| 161 | return errors |
| 162 | |
| 163 | def clean_honeypot(self): |
| 164 | """Check that nothing's been entered into the honeypot.""" |
| 165 | value = self.cleaned_data["honeypot"] |
| 166 | if value: |
| 167 | raise forms.ValidationError(self.fields["honeypot"].label) |
| 168 | return value |