|
41 | 41 | # loaders are out of the picture, because there is no way to ask them to |
42 | 42 | # return all templates. |
43 | 43 | # |
44 | | -# - If you put the {% csrf_token %} tag on the same line as the <form> tag it |
45 | | -# will be detected, otherwise it will be assumed that the form does not have |
46 | | -# the token. |
47 | | -# |
48 | 44 | # - It's impossible to programmatically determine which forms should and should |
49 | 45 | # not have the token added. The developer must decide when to do this, |
50 | 46 | # ensuring that the token is only added to internally targetted forms. |
|
138 | 134 |
|
139 | 135 | _POST_FORM_RE = \ |
140 | 136 | re.compile(r'(<form\W[^>]*\bmethod\s*=\s*(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE) |
| 137 | +_FORM_CLOSE_RE = re.compile(r'</form\s*>') |
141 | 138 | _TOKEN_RE = re.compile('\{% csrf_token') |
142 | 139 |
|
143 | 140 | def get_template_dirs(): |
@@ -190,12 +187,22 @@ def post_form_info(self): |
190 | 187 | Get information about any POST forms in the template. |
191 | 188 | Returns [(linenumber, csrf_token added)] |
192 | 189 | """ |
193 | | - matches = [] |
| 190 | + forms = {} |
| 191 | + form_line = 0 |
194 | 192 | for ln, line in enumerate(self.content.split("\n")): |
195 | | - m = _POST_FORM_RE.search(line) |
196 | | - if m is not None: |
197 | | - matches.append((ln + 1, _TOKEN_RE.search(line) is not None)) |
198 | | - return matches |
| 193 | + if not form_line and _POST_FORM_RE.search(line): |
| 194 | + # record the form with no CSRF token yet |
| 195 | + form_line = ln + 1 |
| 196 | + forms[form_line] = False |
| 197 | + if form_line and _TOKEN_RE.search(line): |
| 198 | + # found the CSRF token |
| 199 | + forms[form_line] = True |
| 200 | + form_line = 0 |
| 201 | + if form_line and _FORM_CLOSE_RE.search(line): |
| 202 | + # no token found by form closing tag |
| 203 | + form_line = 0 |
| 204 | + |
| 205 | + return forms.items() |
199 | 206 |
|
200 | 207 | def includes_template(self, t): |
201 | 208 | """ |
|
0 commit comments