summaryrefslogtreecommitdiff
path: root/django/utils
diff options
context:
space:
mode:
authorAndre Cruz <andre.cruz@co.sapo.pt>2015-01-07 18:41:29 +0000
committerTim Graham <timograham@gmail.com>2016-05-12 10:17:52 -0400
commit929684d6ee0efb5afad51dc584489d0437d2451b (patch)
tree44714f4502df964790f9db9a4751c843fa49a997 /django/utils
parent4065f429f559533f11abbab40624a61027a52b61 (diff)
Fixed #21231 -- Enforced a max size for GET/POST values read into memory.
Thanks Tom Christie for review.
Diffstat (limited to 'django/utils')
-rw-r--r--django/utils/http.py60
1 files changed, 60 insertions, 0 deletions
diff --git a/django/utils/http.py b/django/utils/http.py
index 31de726184..151e85de92 100644
--- a/django/utils/http.py
+++ b/django/utils/http.py
@@ -9,6 +9,7 @@ import unicodedata
from binascii import Error as BinasciiError
from email.utils import formatdate
+from django.core.exceptions import TooManyFieldsSent
from django.utils import six
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_bytes, force_str, force_text
@@ -34,6 +35,8 @@ ASCTIME_DATE = re.compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y))
RFC3986_GENDELIMS = str(":/?#[]@")
RFC3986_SUBDELIMS = str("!$&'()*+,;=")
+FIELDS_MATCH = re.compile('[&;]')
+
@keep_lazy_text
def urlquote(url, safe='/'):
@@ -314,3 +317,60 @@ def _is_safe_url(url, host):
return False
return ((not url_info.netloc or url_info.netloc == host) and
(not url_info.scheme or url_info.scheme in ['http', 'https']))
+
+
+def limited_parse_qsl(qs, keep_blank_values=False, encoding='utf-8',
+ errors='replace', fields_limit=None):
+ """
+ Return a list of key/value tuples parsed from query string.
+
+ Copied from urlparse with an additional "fields_limit" argument.
+ Copyright (C) 2013 Python Software Foundation (see LICENSE.python).
+
+ Arguments:
+
+ qs: percent-encoded query string to be parsed
+
+ keep_blank_values: flag indicating whether blank values in
+ percent-encoded queries should be treated as blank strings. A
+ true value indicates that blanks should be retained as blank
+ strings. The default false value indicates that blank values
+ are to be ignored and treated as if they were not included.
+
+ encoding and errors: specify how to decode percent-encoded sequences
+ into Unicode characters, as accepted by the bytes.decode() method.
+
+ fields_limit: maximum number of fields parsed or an exception
+ is raised. None means no limit and is the default.
+ """
+ if fields_limit:
+ pairs = FIELDS_MATCH.split(qs, fields_limit)
+ if len(pairs) > fields_limit:
+ raise TooManyFieldsSent(
+ 'The number of GET/POST parameters exceeded '
+ 'settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.'
+ )
+ else:
+ pairs = FIELDS_MATCH.split(qs)
+ r = []
+ for name_value in pairs:
+ if not name_value:
+ continue
+ nv = name_value.split(str('='), 1)
+ if len(nv) != 2:
+ # Handle case of a control-name with no equal sign
+ if keep_blank_values:
+ nv.append('')
+ else:
+ continue
+ if len(nv[1]) or keep_blank_values:
+ if six.PY3:
+ name = nv[0].replace('+', ' ')
+ name = unquote(name, encoding=encoding, errors=errors)
+ value = nv[1].replace('+', ' ')
+ value = unquote(value, encoding=encoding, errors=errors)
+ else:
+ name = unquote(nv[0].replace(b'+', b' '))
+ value = unquote(nv[1].replace(b'+', b' '))
+ r.append((name, value))
+ return r