Skip to content

Commit 5ffefa4

Browse files
committed
Merge pull request #19 from knowsis/nonrel-1.6.11
Nonrel 1.6.11
2 parents 0859303 + 4dd85c9 commit 5ffefa4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1103
-332
lines changed

django/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = (1, 6, 8, 'final', 0)
1+
VERSION = (1, 6, 11, 'final', 0)
22

33
def get_version(*args, **kwargs):
44
# Don't litter django/__init__.py with all the get_version stuff.

django/contrib/admin/options.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,9 @@ def to_field_allowed(self, request, to_field):
339339
except FieldDoesNotExist:
340340
return False
341341

342-
# Check whether this model is the origin of a M2M relationship
343-
# in which case to_field has to be the pk on this model.
344-
if opts.many_to_many and field.primary_key:
342+
# Always allow referencing the primary key since it's already possible
343+
# to get this information from the change view URL.
344+
if field.primary_key:
345345
return True
346346

347347
# Make sure at least one of the models registered for this site
@@ -352,8 +352,7 @@ def to_field_allowed(self, request, to_field):
352352
for inline in admin.inlines:
353353
registered_models.add(inline.model)
354354

355-
for related_object in (opts.get_all_related_objects(include_hidden=True) +
356-
opts.get_all_related_many_to_many_objects()):
355+
for related_object in opts.get_all_related_objects(include_hidden=True):
357356
related_model = related_object.model
358357
if (any(issubclass(model, related_model) for model in registered_models) and
359358
related_object.field.rel.get_related_field() == field):

django/core/servers/basehttp.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ def log_message(self, format, *args):
157157

158158
sys.stderr.write(msg)
159159

160+
def get_environ(self):
161+
# Strip all headers with underscores in the name before constructing
162+
# the WSGI environ. This prevents header-spoofing based on ambiguity
163+
# between underscores and dashes both normalized to underscores in WSGI
164+
# env vars. Nginx and Apache 2.4+ both do this as well.
165+
for k, v in self.headers.items():
166+
if '_' in k:
167+
del self.headers[k]
168+
169+
return super(WSGIRequestHandler, self).get_environ()
170+
160171

161172
def run(addr, port, wsgi_handler, ipv6=False, threading=False):
162173
server_address = (addr, port)

django/forms/models.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,8 +1174,7 @@ def __init__(self, queryset, cache_choices=False, required=True,
11741174
def to_python(self, value):
11751175
if not value:
11761176
return []
1177-
to_py = super(ModelMultipleChoiceField, self).to_python
1178-
return [to_py(val) for val in value]
1177+
return list(self._check_values(value))
11791178

11801179
def clean(self, value):
11811180
if self.required and not value:
@@ -1184,7 +1183,29 @@ def clean(self, value):
11841183
return self.queryset.none()
11851184
if not isinstance(value, (list, tuple)):
11861185
raise ValidationError(self.error_messages['list'], code='list')
1186+
qs = self._check_values(value)
1187+
# Since this overrides the inherited ModelChoiceField.clean
1188+
# we run custom validators here
1189+
self.run_validators(value)
1190+
return qs
1191+
1192+
def _check_values(self, value):
1193+
"""
1194+
Given a list of possible PK values, returns a QuerySet of the
1195+
corresponding objects. Raises a ValidationError if a given value is
1196+
invalid (not a valid PK, not in the queryset, etc.)
1197+
"""
11871198
key = self.to_field_name or 'pk'
1199+
# deduplicate given values to avoid creating many querysets or
1200+
# requiring the database backend deduplicate efficiently.
1201+
try:
1202+
value = frozenset(value)
1203+
except TypeError:
1204+
# list of lists isn't hashable, for example
1205+
raise ValidationError(
1206+
self.error_messages['list'],
1207+
code='list',
1208+
)
11881209
for pk in value:
11891210
try:
11901211
self.queryset.filter(**{key: pk})
@@ -1203,9 +1224,6 @@ def clean(self, value):
12031224
code='invalid_choice',
12041225
params={'value': val},
12051226
)
1206-
# Since this overrides the inherited ModelChoiceField.clean
1207-
# we run custom validators here
1208-
self.run_validators(value)
12091227
return qs
12101228

12111229
def prepare_value(self, value):

django/utils/html.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ def strip_tags(value):
156156
if not ('<' in value or '>' in value):
157157
return value
158158
new_value = _strip_once(value)
159-
if new_value == value:
160-
# _strip_once was not able to detect more tags
159+
if len(new_value) >= len(value):
160+
# _strip_once was not able to detect more tags or length increased
161+
# due to http://bugs.python.org/issue20288
162+
# (affects Python 2 < 2.7.7 and Python 3 < 3.3.5)
161163
return value
162164
else:
163165
value = new_value

django/utils/http.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import datetime
66
import re
77
import sys
8-
8+
import unicodedata
99
from binascii import Error as BinasciiError
1010
from email.utils import formatdate
1111

@@ -254,6 +254,8 @@ def is_safe_url(url, host=None):
254254
255255
Always returns ``False`` on an empty url.
256256
"""
257+
if url is not None:
258+
url = url.strip()
257259
if not url:
258260
return False
259261
# Chrome treats \ completely as /
@@ -269,5 +271,10 @@ def is_safe_url(url, host=None):
269271
# allow this syntax.
270272
if not url_info.netloc and url_info.scheme:
271273
return False
272-
return (not url_info.netloc or url_info.netloc == host) and \
273-
(not url_info.scheme or url_info.scheme in ['http', 'https'])
274+
# Forbid URLs that start with control characters. Some browsers (like
275+
# Chrome) ignore quite a few control characters at the start of a
276+
# URL and might consider the URL as scheme relative.
277+
if unicodedata.category(url[0])[0] == 'C':
278+
return False
279+
return ((not url_info.netloc or url_info.netloc == host) and
280+
(not url_info.scheme or url_info.scheme in ['http', 'https']))

0 commit comments

Comments
 (0)