diff -rw /tmp/Django-1.4/django/conf/global_settings.py /tmp/Django-1.4.5/django/conf/global_settings.py
31a32,35
> # Hosts/domain names that are valid for this site.
> # "*" matches anything, ".example.com" matches example.com and all subdomains
> ALLOWED_HOSTS = ['*']
> 
diff -rw /tmp/Django-1.4/django/conf/project_template/project_name/settings.py /tmp/Django-1.4.5/django/conf/project_template/project_name/settings.py
22a23,26
> # Hosts/domain names that are valid for this site; required if DEBUG is False
> # See https://docs.djangoproject.com/en/1.4/ref/settings/#allowed-hosts
> ALLOWED_HOSTS = []
> 
26,29c30
< # On Unix systems, a value of None will cause Django to use the same
< # timezone as the operating system.
< # If running in a Windows environment this must be set to the same as your
< # system time zone.
---
> # In a Windows environment this must be set to your system time zone.
diff -rw /tmp/Django-1.4/django/contrib/admin/filters.py /tmp/Django-1.4.5/django/contrib/admin/filters.py
11,12c11,12
< from django.core.exceptions import ImproperlyConfigured
< from django.utils.encoding import smart_unicode
---
> from django.core.exceptions import ImproperlyConfigured, ValidationError
> from django.utils.encoding import smart_unicode, force_unicode
15d14
< 
17a17
> from django.contrib.admin.options import IncorrectLookupParameters
105c105
<                 'selected': self.value() == lookup,
---
>                 'selected': self.value() == force_unicode(lookup),
131a132
>         try:
132a134,135
>         except ValidationError, e:
>             raise IncorrectLookupParameters(e)
157a161,163
>         if hasattr(field, 'rel'):
>             rel_name = field.rel.get_related_field().name
>         else:
diff -rw /tmp/Django-1.4/django/contrib/admin/options.py /tmp/Django-1.4.5/django/contrib/admin/options.py
248c248
<         pk_attr_name = None
---
>         rel_name = None
258c258
<                 pk_attr_name = model._meta.pk.name
---
>                 rel_name = field.rel.get_related_field().name
261c261
<                 pk_attr_name = model._meta.pk.name
---
>                 rel_name = model._meta.pk.name
263,264c263,264
<                 pk_attr_name = None
<         if pk_attr_name and len(parts) > 1 and parts[-1] == pk_attr_name:
---
>                 rel_name = None
>         if rel_name and len(parts) > 1 and parts[-1] == rel_name:
1319a1320
>         # First check if the user can see this history.
1320a1322,1327
>         obj = get_object_or_404(model, pk=unquote(object_id))
> 
>         if not self.has_change_permission(request, obj):
>             raise PermissionDenied
> 
>         # Then get the history for this object.
1327,1328c1334
<         # If no history was found, see whether this object even exists.
<         obj = get_object_or_404(model, pk=unquote(object_id))
---
> 
diff -rw /tmp/Django-1.4/django/contrib/admin/static/admin/css/widgets.css /tmp/Django-1.4.5/django/contrib/admin/static/admin/css/widgets.css
44c44,45
< .selector .selector-filter label {
---
> .selector .selector-filter label,
> .inline-group .aligned .selector .selector-filter label {
diff -rw /tmp/Django-1.4/django/contrib/admin/tests.py /tmp/Django-1.4.5/django/contrib/admin/tests.py
28d27
<         super(AdminSeleniumWebDriverTestCase, cls).tearDownClass()
30a30
>         super(AdminSeleniumWebDriverTestCase, cls).tearDownClass()
diff -rw /tmp/Django-1.4/django/contrib/admin/views/main.py /tmp/Django-1.4.5/django/contrib/admin/views/main.py
261c261
<             ordering.append('pk')
---
>             ordering.append('-pk')
diff -rw /tmp/Django-1.4/django/contrib/auth/context_processors.py /tmp/Django-1.4.5/django/contrib/auth/context_processors.py
13a14,18
>     def __iter__(self):
>         # To fix 'item in perms.someapp' and __getitem__ iteraction we need to
>         # define __iter__. See #18979 for details.
>         raise TypeError("PermLookupDict is not iterable.")
> 
diff -rw /tmp/Django-1.4/django/contrib/auth/hashers.py /tmp/Django-1.4.5/django/contrib/auth/hashers.py
38c38,39
<     if len(encoded) == 32 and '$' not in encoded:
---
>     if ((len(encoded) == 32 and '$' not in encoded) or
>             (len(encoded) == 37 and encoded.startswith('md5$$'))):
349a351,352
>         if len(encoded) == 37 and encoded.startswith('md5$$'):
>             encoded = encoded[5:]
diff -rw /tmp/Django-1.4/django/contrib/auth/tests/context_processors.py /tmp/Django-1.4.5/django/contrib/auth/tests/context_processors.py
4a5
> from django.contrib.auth.context_processors import PermWrapper, PermLookupDict
8a10,54
> 
> 
> class MockUser(object):
>     def has_module_perm(self, perm):
>         if perm == 'mockapp.someapp':
>             return True
>         return False
> 
>     def has_perm(self, perm):
>         if perm == 'someperm':
>             return True
>         return False
> 
> 
> class PermWrapperTests(TestCase):
>     """
>     Test some details of the PermWrapper implementation.
>     """
>     class EQLimiterObject(object):
>         """
>         This object makes sure __eq__ will not be called endlessly.
>         """
>         def __init__(self):
>             self.eq_calls = 0
> 
>         def __eq__(self, other):
>             if self.eq_calls > 0:
>                 return True
>             self.eq_calls += 1
>             return False
> 
>     def test_permwrapper_in(self):
>         """
>         Test that 'something' in PermWrapper doesn't end up in endless loop.
>         """
>         perms = PermWrapper(MockUser())
>         def raises():
>             self.EQLimiterObject() in perms
>         self.assertRaises(raises, TypeError)
> 
>     def test_permlookupdict_in(self):
>         pldict = PermLookupDict(MockUser(), 'mockapp')
>         def raises():
>             self.EQLimiterObject() in pldict
>         self.assertRaises(raises, TypeError)
diff -rw /tmp/Django-1.4/django/contrib/auth/tests/forms.py /tmp/Django-1.4.5/django/contrib/auth/tests/forms.py
11a12
> from django.utils.translation import ugettext as _
336c337
<                          [u"The user account associated with this e-mail address cannot reset the password."])
---
>                          [_(u"The user account associated with this e-mail address cannot reset the password.")])
diff -rw /tmp/Django-1.4/django/contrib/auth/tests/hashers.py /tmp/Django-1.4.5/django/contrib/auth/tests/hashers.py
61a62,66
>         # Alternate unsalted syntax
>         alt_encoded = "md5$$%s" % encoded
>         self.assertTrue(is_password_usable(alt_encoded))
>         self.assertTrue(check_password(u'letmein', alt_encoded))
>         self.assertFalse(check_password('letmeinz', alt_encoded))
diff -rw /tmp/Django-1.4/django/contrib/auth/tests/urls.py /tmp/Django-1.4.5/django/contrib/auth/tests/urls.py
53a54
>     (r'^admin_password_reset/$', 'django.contrib.auth.views.password_reset', dict(is_admin_site=True)),
diff -rw /tmp/Django-1.4/django/contrib/auth/tests/views.py /tmp/Django-1.4.5/django/contrib/auth/tests/views.py
9a10
> from django.core.exceptions import SuspiciousOperation
107a109,149
> 
>     @override_settings(ALLOWED_HOSTS=['adminsite.com'])
>     def test_admin_reset(self):
>         "If the reset view is marked as being for admin, the HTTP_HOST header is used for a domain override."
>         response = self.client.post('/admin_password_reset/',
>             {'email': 'staffmember@example.com'},
>             HTTP_HOST='adminsite.com'
>         )
>         self.assertEqual(response.status_code, 302)
>         self.assertEqual(len(mail.outbox), 1)
>         self.assertTrue("http://adminsite.com" in mail.outbox[0].body)
>         self.assertEqual(settings.DEFAULT_FROM_EMAIL, mail.outbox[0].from_email)
> 
>     # Skip any 500 handler action (like sending more mail...)
>     @override_settings(DEBUG_PROPAGATE_EXCEPTIONS=True)
>     def test_poisoned_http_host(self):
>         "Poisoned HTTP_HOST headers can't be used for reset emails"
>         # This attack is based on the way browsers handle URLs. The colon
>         # should be used to separate the port, but if the URL contains an @,
>         # the colon is interpreted as part of a username for login purposes,
>         # making 'evil.com' the request domain. Since HTTP_HOST is used to
>         # produce a meaningful reset URL, we need to be certain that the
>         # HTTP_HOST header isn't poisoned. This is done as a check when get_host()
>         # is invoked, but we check here as a practical consequence.
>         with self.assertRaises(SuspiciousOperation):
>             self.client.post('/password_reset/',
>                 {'email': 'staffmember@example.com'},
>                 HTTP_HOST='www.example:dr.frankenstein@evil.tld'
>             )
>         self.assertEqual(len(mail.outbox), 0)
> 
>     # Skip any 500 handler action (like sending more mail...)
>     @override_settings(DEBUG_PROPAGATE_EXCEPTIONS=True)
>     def test_poisoned_http_host_admin_site(self):
>         "Poisoned HTTP_HOST headers can't be used for reset emails on admin views"
>         with self.assertRaises(SuspiciousOperation):
>             self.client.post('/admin_password_reset/',
>                 {'email': 'staffmember@example.com'},
>                 HTTP_HOST='www.example:dr.frankenstein@evil.tld'
>             )
>         self.assertEqual(len(mail.outbox), 0)
diff -rw /tmp/Django-1.4/django/contrib/auth/views.py /tmp/Django-1.4.5/django/contrib/auth/views.py
7c7
< from django.utils.http import base36_to_int
---
> from django.utils.http import base36_to_int, is_safe_url
37,45c37,38
<             netloc = urlparse.urlparse(redirect_to)[1]
< 
<             # Use default setting if redirect_to is empty
<             if not redirect_to:
<                 redirect_to = settings.LOGIN_REDIRECT_URL
< 
<             # Heavier security check -- don't allow redirection to a different
<             # host.
<             elif netloc and netloc != request.get_host():
---
>             # Ensure the user-originating redirection url is safe.
>             if not is_safe_url(url=redirect_to, host=request.get_host()):
48c41
<             # Okay, security checks complete. Log the user in.
---
>             # Okay, security check complete. Log the user in.
81,83c74,76
<     redirect_to = request.REQUEST.get(redirect_field_name, '')
<     if redirect_to:
<         netloc = urlparse.urlparse(redirect_to)[1]
---
> 
>     if redirect_field_name in request.REQUEST:
>         next_page = request.REQUEST[redirect_field_name]
85,86c78,83
<         if not (netloc and netloc != request.get_host()):
<             return HttpResponseRedirect(redirect_to)
---
>         if not is_safe_url(url=next_page, host=request.get_host()):
>             next_page = request.path
> 
>     if next_page:
>         # Redirect to this page until the session has been cleared.
>         return HttpResponseRedirect(next_page)
88d84
<     if next_page is None:
99,101d94
<     else:
<         # Redirect to this page until the session has been cleared.
<         return HttpResponseRedirect(next_page or request.path)
159c152
<                 opts = dict(opts, domain_override=request.META['HTTP_HOST'])
---
>                 opts = dict(opts, domain_override=request.get_host())
diff -rw /tmp/Django-1.4/django/contrib/comments/views/comments.py /tmp/Django-1.4.5/django/contrib/comments/views/comments.py
47,49d46
<     # Check to see if the POST data overrides the view's next argument.
<     next = data.get("next", next)
< 
103c100
<                 "next": next,
---
>                 "next": data.get("next", next),
134c131
<     return next_redirect(data, next, comment_done, c=comment._get_pk_val())
---
>     return next_redirect(request, next, comment_done, c=comment._get_pk_val())
diff -rw /tmp/Django-1.4/django/contrib/comments/views/moderation.py /tmp/Django-1.4.5/django/contrib/comments/views/moderation.py
13d12
< 
30c29
<         return next_redirect(request.POST.copy(), next, flag_done, c=comment.pk)
---
>         return next_redirect(request, next, flag_done, c=comment.pk)
57c56
<         return next_redirect(request.POST.copy(), next, delete_done, c=comment.pk)
---
>         return next_redirect(request, next, delete_done, c=comment.pk)
84c83
<         return next_redirect(request.POST.copy(), next, approve_done, c=comment.pk)
---
>         return next_redirect(request, next, approve_done, c=comment.pk)
diff -rw /tmp/Django-1.4/django/contrib/comments/views/utils.py /tmp/Django-1.4.5/django/contrib/comments/views/utils.py
7d6
< from django.http import HttpResponseRedirect
8a8
> from django.http import HttpResponseRedirect
12a13
> from django.utils.http import is_safe_url
14c15
< def next_redirect(data, default, default_view, **get_kwargs):
---
> def next_redirect(request, default, default_view, **get_kwargs):
24,25c25,26
<     next = data.get("next", default)
<     if next is None:
---
>     next = request.POST.get('next', default)
>     if not is_safe_url(url=next, host=request.get_host()):
26a28
> 
diff -rw /tmp/Django-1.4/django/contrib/contenttypes/tests.py /tmp/Django-1.4.5/django/contrib/contenttypes/tests.py
11a12
> from django.test.utils import override_settings
116a118
>     @override_settings(ALLOWED_HOSTS=['example.com'])
diff -rw /tmp/Django-1.4/django/contrib/gis/db/backends/oracle/compiler.py /tmp/Django-1.4.5/django/contrib/gis/db/backends/oracle/compiler.py
10,32c10
<     def placeholder(self, field, val):
<         if field is None:
<             # A field value of None means the value is raw.
<             return val
<         elif hasattr(field, 'get_placeholder'):
<             # Some fields (e.g. geo fields) need special munging before
<             # they can be inserted.
<             ph = field.get_placeholder(val, self.connection)
<             if ph == 'NULL':
<                 # If the placeholder returned is 'NULL', then we need to
<                 # to remove None from the Query parameters. Specifically,
<                 # cx_Oracle will assume a CHAR type when a placeholder ('%s')
<                 # is used for columns of MDSYS.SDO_GEOMETRY.  Thus, we use
<                 # 'NULL' for the value, and remove None from the query params.
<                 # See also #10888.
<                 param_idx = self.query.columns.index(field.column)
<                 params = list(self.query.params)
<                 params.pop(param_idx)
<                 self.query.params = tuple(params)
<             return ph
<         else:
<             # Return the common case for the placeholder
<             return '%s'
---
>     pass
diff -rw /tmp/Django-1.4/django/contrib/gis/db/backends/oracle/operations.py /tmp/Django-1.4.5/django/contrib/gis/db/backends/oracle/operations.py
11a12
> from itertools import izip
289a291,299
>     
>     def modify_insert_params(self, placeholders, params):
>         """Drop out insert parameters for NULL placeholder. Needed for Oracle Spatial
>         backend due to #10888
>         """
>         # This code doesn't work for bulk insert cases.
>         assert len(placeholders) == 1
>         return [[param for pholder,param
>                  in izip(placeholders[0], params[0]) if pholder != 'NULL'], ]
diff -rw /tmp/Django-1.4/django/contrib/gis/tests/inspectapp/tests.py /tmp/Django-1.4.5/django/contrib/gis/tests/inspectapp/tests.py
71,85c71,90
<         expected = [
<             '# This is an auto-generated Django model module created by ogrinspect.',
<             'from django.contrib.gis.db import models',
<             '',
<             'class Measurement(models.Model):',
<             '    f_decimal = models.DecimalField(max_digits=0, decimal_places=0)',
<             '    f_int = models.IntegerField()',
<             '    f_datetime = models.DateTimeField()',
<             '    f_time = models.TimeField()',
<             '    f_float = models.FloatField()',
<             '    f_char = models.CharField(max_length=10)',
<             '    f_date = models.DateField()',
<             '    geom = models.PolygonField()',
<             '    objects = models.GeoManager()',
<         ]
---
>         self.assertTrue(model_def.startswith(
>             '# This is an auto-generated Django model module created by ogrinspect.\n'
>             'from django.contrib.gis.db import models\n'
>             '\n'
>             'class Measurement(models.Model):\n'
>         ))
> 
>         # The ordering of model fields might vary depending on several factors (version of GDAL, etc.)
>         self.assertIn('    f_decimal = models.DecimalField(max_digits=0, decimal_places=0)', model_def)
>         self.assertIn('    f_int = models.IntegerField()', model_def)
>         self.assertIn('    f_datetime = models.DateTimeField()', model_def)
>         self.assertIn('    f_time = models.TimeField()', model_def)
>         self.assertIn('    f_float = models.FloatField()', model_def)
>         self.assertIn('    f_char = models.CharField(max_length=10)', model_def)
>         self.assertIn('    f_date = models.DateField()', model_def)
> 
>         self.assertTrue(model_def.endswith(
>             '    geom = models.PolygonField()\n'
>             '    objects = models.GeoManager()'
>         ))
87d91
<         self.assertEqual(model_def, '\n'.join(expected))
diff -rw /tmp/Django-1.4/django/contrib/markup/templatetags/markup.py /tmp/Django-1.4.5/django/contrib/markup/templatetags/markup.py
68,69c68,69
<             python_markdown_deprecation = "The use of Python-Markdown "
<             "< 2.1 in Django is deprecated; please update to the current version"
---
>             python_markdown_deprecation = ("The use of Python-Markdown "
>             "< 2.1 in Django is deprecated; please update to the current version")
diff -rw /tmp/Django-1.4/django/contrib/sites/tests.py /tmp/Django-1.4.5/django/contrib/sites/tests.py
5a6
> from django.test.utils import override_settings
41a43
>     @override_settings(ALLOWED_HOSTS=['example.com'])
diff -rw /tmp/Django-1.4/django/contrib/staticfiles/storage.py /tmp/Django-1.4.5/django/contrib/staticfiles/storage.py
193,194c193,194
<         # delete cache of all handled paths
<         self.cache.delete_many([self.cache_key(path) for path in paths])
---
>         # where to store the new paths
>         hashed_paths = {}
243c243
<                 self.cache.set(self.cache_key(name), hashed_name)
---
>                 hashed_paths[self.cache_key(name)] = hashed_name
244a245,247
> 
>         # Finally set the cache
>         self.cache.set_many(hashed_paths)
diff -rw /tmp/Django-1.4/django/core/files/images.py /tmp/Django-1.4.5/django/core/files/images.py
49a50,53
>         # Most of the time PIL only needs a small chunk to parse the image and
>         # get the dimensions, but with some TIFF files PIL needs to parse the
>         # whole file.
>         chunk_size = 1024
51c55
<             data = file.read(1024)
---
>             data = file.read(chunk_size)
56a61
>             chunk_size = chunk_size*2
diff -rw /tmp/Django-1.4/django/core/management/commands/testserver.py /tmp/Django-1.4.5/django/core/management/commands/testserver.py
38c38,45
<         call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False, use_ipv6=options['use_ipv6'])
---
>         use_threading = connection.features.test_db_allows_multiple_connections
>         call_command('runserver',
>             addrport=addrport,
>             shutdown_message=shutdown_message,
>             use_reloader=False,
>             use_ipv6=options['use_ipv6'],
>             use_threading=use_threading
>         )
diff -rw /tmp/Django-1.4/django/core/serializers/xml_serializer.py /tmp/Django-1.4.5/django/core/serializers/xml_serializer.py
10a11,12
> from xml.sax import handler
> from xml.sax.expatreader import ExpatParser as _ExpatParser
152c154
<         self.event_stream = pulldom.parse(self.stream)
---
>         self.event_stream = pulldom.parse(self.stream, self._make_parser())
154a157,160
>     def _make_parser(self):
>         """Create a hardened XML parser (no custom/external entities)."""
>         return DefusedExpatParser()
> 
292a299,385
> 
> 
> # Below code based on Christian Heimes' defusedxml
> 
> 
> class DefusedExpatParser(_ExpatParser):
>     """
>     An expat parser hardened against XML bomb attacks.
> 
>     Forbids DTDs, external entity references
> 
>     """
>     def __init__(self, *args, **kwargs):
>         _ExpatParser.__init__(self, *args, **kwargs)
>         self.setFeature(handler.feature_external_ges, False)
>         self.setFeature(handler.feature_external_pes, False)
> 
>     def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
>         raise DTDForbidden(name, sysid, pubid)
> 
>     def entity_decl(self, name, is_parameter_entity, value, base,
>                     sysid, pubid, notation_name):
>         raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)
> 
>     def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):
>         # expat 1.2
>         raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)
> 
>     def external_entity_ref_handler(self, context, base, sysid, pubid):
>         raise ExternalReferenceForbidden(context, base, sysid, pubid)
> 
>     def reset(self):
>         _ExpatParser.reset(self)
>         parser = self._parser
>         parser.StartDoctypeDeclHandler = self.start_doctype_decl
>         parser.EntityDeclHandler = self.entity_decl
>         parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl
>         parser.ExternalEntityRefHandler = self.external_entity_ref_handler
> 
> 
> class DefusedXmlException(ValueError):
>     """Base exception."""
>     def __repr__(self):
>         return str(self)
> 
> 
> class DTDForbidden(DefusedXmlException):
>     """Document type definition is forbidden."""
>     def __init__(self, name, sysid, pubid):
>         super(DTDForbidden, self).__init__()
>         self.name = name
>         self.sysid = sysid
>         self.pubid = pubid
> 
>     def __str__(self):
>         tpl = "DTDForbidden(name='{}', system_id={!r}, public_id={!r})"
>         return tpl.format(self.name, self.sysid, self.pubid)
> 
> 
> class EntitiesForbidden(DefusedXmlException):
>     """Entity definition is forbidden."""
>     def __init__(self, name, value, base, sysid, pubid, notation_name):
>         super(EntitiesForbidden, self).__init__()
>         self.name = name
>         self.value = value
>         self.base = base
>         self.sysid = sysid
>         self.pubid = pubid
>         self.notation_name = notation_name
> 
>     def __str__(self):
>         tpl = "EntitiesForbidden(name='{}', system_id={!r}, public_id={!r})"
>         return tpl.format(self.name, self.sysid, self.pubid)
> 
> 
> class ExternalReferenceForbidden(DefusedXmlException):
>     """Resolving an external reference is forbidden."""
>     def __init__(self, context, base, sysid, pubid):
>         super(ExternalReferenceForbidden, self).__init__()
>         self.context = context
>         self.base = base
>         self.sysid = sysid
>         self.pubid = pubid
> 
>     def __str__(self):
>         tpl = "ExternalReferenceForbidden(system_id='{}', public_id={})"
>         return tpl.format(self.sysid, self.pubid)
diff -rw /tmp/Django-1.4/django/db/backends/__init__.py /tmp/Django-1.4.5/django/db/backends/__init__.py
85a86,96
>     def abort(self):
>         """
>         Roll back any ongoing transaction and clean the transaction state
>         stack.
>         """
>         if self._dirty:
>             self._rollback()
>             self._dirty = False
>         while self.transaction_state:
>             self.leave_transaction_management()
> 
472a484,491
>     def bulk_batch_size(self, fields, objs):
>         """
>         Returns the maximum allowed batch size for the backend. The fields
>         are the fields going to be inserted in the batch, the objs contains
>         all the objects to be inserted.
>         """
>         return len(objs)
> 
509a529,539
>     def distinct_sql(self, fields):
>         """
>         Returns an SQL DISTINCT clause which removes duplicate rows from the
>         result set. If any fields are given, only the given fields are being
>         checked for duplicates.
>         """
>         if fields:
>             raise NotImplementedError('DISTINCT ON fields is not supported by this database backend')
>         else:
>             return 'DISTINCT'
> 
565,575d594
<     def distinct_sql(self, fields):
<         """
<         Returns an SQL DISTINCT clause which removes duplicate rows from the
<         result set. If any fields are given, only the given fields are being
<         checked for duplicates.
<         """
<         if fields:
<             raise NotImplementedError('DISTINCT ON fields is not supported by this database backend')
<         else:
<             return 'DISTINCT'
< 
867a887,892
> 
>     def modify_insert_params(self, placeholders, params):
>         """Allow modification of insert parameters. Needed for Oracle Spatial
>         backend due to #10888.
>         """
>         return params
diff -rw /tmp/Django-1.4/django/db/backends/mysql/base.py /tmp/Django-1.4.5/django/db/backends/mysql/base.py
180c180
<             cursor.execute("SHOW TABLE STATUS WHERE Name='INTROSPECT_TEST'")
---
>             cursor.execute("SHOW TABLE STATUS LIKE 'INTROSPECT_TEST'")
409a410
>             new_connection = False
411,412c412,421
<                 self.cursor()
<             m = server_version_re.match(self.connection.get_server_info())
---
>                 # Ensure we have a connection with the DB by using a temporary
>                 # cursor
>                 new_connection = True
>                 self.cursor().close()
>             server_info = self.connection.get_server_info()
>             if new_connection:
>                 # Make sure we close the connection
>                 self.connection.close()
>                 self.connection = None
>             m = server_version_re.match(server_info)
414c423
<                 raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
---
>                 raise Exception('Unable to determine MySQL version from version string %r' % server_info)
diff -rw /tmp/Django-1.4/django/db/backends/sqlite3/base.py /tmp/Django-1.4.5/django/db/backends/sqlite3/base.py
86c86
<     can_combine_inserts_with_and_without_auto_increment_pk = True
---
>     can_combine_inserts_with_and_without_auto_increment_pk = False
106a107,113
>     def bulk_batch_size(self, fields, objs):
>         """
>         SQLite has a compile-time default (SQLITE_LIMIT_VARIABLE_NUMBER) of
>         999 variables per query.
>         """
>         return (999 // len(fields)) if len(fields) > 0 else len(objs)
> 
211c218
<         res.extend(["UNION SELECT %s" % ", ".join(["%s"] * len(fields))] * (num_values - 1))
---
>         res.extend(["UNION ALL SELECT %s" % ", ".join(["%s"] * len(fields))] * (num_values - 1))
diff -rw /tmp/Django-1.4/django/db/__init__.py /tmp/Django-1.4.5/django/db/__init__.py
45,46c45,52
<     for conn in connections.all():
<         conn.close()
---
>     # Avoid circular imports
>     from django.db import transaction
>     for conn in connections:
>         # If an error happens here the connection will be left in broken
>         # state. Once a good db connection is again available, the
>         # connection state will be cleaned up.
>         transaction.abort(conn)
>         connections[conn].close()
diff -rw /tmp/Django-1.4/django/db/models/fields/__init__.py /tmp/Django-1.4.5/django/db/models/fields/__init__.py
1026c1026,1027
<     def __init__(self, protocol='both', unpack_ipv4=False, *args, **kwargs):
---
>     def __init__(self, verbose_name=None, name=None, protocol='both',
>                  unpack_ipv4=False, *args, **kwargs):
1032c1033
<         Field.__init__(self, *args, **kwargs)
---
>         Field.__init__(self, verbose_name, name, *args, **kwargs)
diff -rw /tmp/Django-1.4/django/db/models/fields/related.py /tmp/Django-1.4.5/django/db/models/fields/related.py
242c242
<         return (self.get_query_set(instance=instances[0]),
---
>         return (self.get_query_set(instance=instances[0]).filter(**params),
534,536c534,560
<             self._pk_val = self.instance.pk
<             if self._pk_val is None:
<                 raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)
---
>             self._fk_val = self._get_fk_val(instance, source_field_name)
>             if self._fk_val is None:
>                 raise ValueError('"%r" needs to have a value for field "%s" before '
>                                  'this many-to-many relationship can be used.' %
>                                  (instance, source_field_name))
>             # Even if this relation is not to pk, we require still pk value.
>             # The wish is that the instance has been already saved to DB,
>             # although having a pk value isn't a guarantee of that.
>             if instance.pk is None:
>                 raise ValueError("%r instance needs to have a primary key value before "
>                                  "a many-to-many relationship can be used." %
>                                  instance.__class__.__name__)
> 
>         def _get_fk_val(self, obj, field_name):
>             """
>             Returns the correct value for this relationship's foreign key. This
>             might be something else than pk value when to_field is used.
>             """
>             if not self.through:
>                 # Make custom m2m fields with no through model defined usable.
>                 return obj.pk
>             fk = self.through._meta.get_field(field_name)
>             if fk.rel.field_name and fk.rel.field_name != fk.rel.to._meta.pk.attname:
>                 attname = fk.rel.get_related_field().get_attname()
>                 return fk.get_prep_lookup('exact', getattr(obj, attname))
>             else:
>                 return obj.pk
638c662,666
<                         new_ids.add(obj.pk)
---
>                         fk_val = self._get_fk_val(obj, target_field_name)
>                         if fk_val is None:
>                             raise ValueError('Cannot add "%r": the value for field "%s" is None' %
>                                              (obj, target_field_name))
>                         new_ids.add(self._get_fk_val(obj, target_field_name))
646c674
<                     source_field_name: self._pk_val,
---
>                     source_field_name: self._fk_val,
660c688
<                         '%s_id' % source_field_name: self._pk_val,
---
>                         '%s_id' % source_field_name: self._fk_val,
664a693
> 
683c712
<                         old_ids.add(obj.pk)
---
>                         old_ids.add(self._get_fk_val(obj, target_field_name))
697c726
<                     source_field_name: self._pk_val,
---
>                     source_field_name: self._fk_val,
717c746
<                 source_field_name: self._pk_val
---
>                 source_field_name: self._fk_val
diff -rw /tmp/Django-1.4/django/db/models/query.py /tmp/Django-1.4.5/django/db/models/query.py
380c380
<     def bulk_create(self, objs):
---
>     def bulk_create(self, objs, batch_size=None):
393,394c393,396
<         # insert into the childmost table. We're punting on these for now
<         # because they are relatively rare cases.
---
>         # insert into the childmost table. Some databases might allow doing
>         # this by using RETURNING clause for the insert query. We're punting
>         # on these for now because they are relatively rare cases.
>         assert batch_size is None or batch_size > 0
410c412
<                 self.model._base_manager._insert(objs, fields=fields, using=self.db)
---
>                 self._batched_insert(objs, fields, batch_size)
414c416
<                     self.model._base_manager._insert(objs_with_pk, fields=fields, using=self.db)
---
>                     self._batched_insert(objs_with_pk, fields, batch_size)
416c418,419
<                     self.model._base_manager._insert(objs_without_pk, fields=[f for f in fields if not isinstance(f, AutoField)], using=self.db)
---
>                     fields= [f for f in fields if not isinstance(f, AutoField)]
>                     self._batched_insert(objs_without_pk, fields, batch_size)
851a855,868
>     def _batched_insert(self, objs, fields, batch_size):
>         """
>         A little helper method for bulk_insert to insert the bulk one batch
>         at a time. Inserts recursively a batch from the front of the bulk and
>         then _batched_insert() the remaining objects again.
>         """
>         if not objs:
>             return
>         ops = connections[self.db].ops
>         batch_size = (batch_size or max(ops.bulk_batch_size(fields, objs), 1))
>         for batch in [objs[i:i+batch_size]
>                       for i in range(0, len(objs), batch_size)]:
>             self.model._base_manager._insert(batch, fields=fields,
>                                              using=self.db)
diff -rw /tmp/Django-1.4/django/db/models/sql/compiler.py /tmp/Django-1.4.5/django/db/models/sql/compiler.py
887a888,889
>             # Oracle Spatial needs to remove some values due to #10888
>             params = self.connection.ops.modify_insert_params(placeholders, params)
diff -rw /tmp/Django-1.4/django/db/transaction.py /tmp/Django-1.4.5/django/db/transaction.py
27a28,42
> def abort(using=None):
>     """
>     Roll back any ongoing transactions and clean the transaction management
>     state of the connection.
> 
>     This method is to be used only in cases where using balanced
>     leave_transaction_management() calls isn't possible. For example after a
>     request has finished, the transaction state isn't known, yet the connection
>     must be cleaned up for the next request.
>     """
>     if using is None:
>         using = DEFAULT_DB_ALIAS
>     connection = connections[using]
>     connection.abort()
> 
diff -rw /tmp/Django-1.4/django/forms/fields.py /tmp/Django-1.4.5/django/forms/fields.py
573,586c573,576
<             # load() is the only method that can spot a truncated JPEG,
<             #  but it cannot be called sanely after verify()
<             trial_image = Image.open(file)
<             trial_image.load()
< 
<             # Since we're about to use the file again we have to reset the
<             # file object if possible.
<             if hasattr(file, 'reset'):
<                 file.reset()
< 
<             # verify() is the only method that can spot a corrupt PNG,
<             #  but it must be called immediately after the constructor
<             trial_image = Image.open(file)
<             trial_image.verify()
---
>             # load() could spot a truncated JPEG, but it loads the entire
>             # image in memory, which is a DoS vector. See #3848 and #18520.
>             # verify() must be called immediately after the constructor.
>             Image.open(file).verify()
diff -rw /tmp/Django-1.4/django/forms/formsets.py /tmp/Django-1.4.5/django/forms/formsets.py
21a22,24
> # default maximum number of forms in a formset, to prevent memory exhaustion
> DEFAULT_MAX_NUM = 1000
> 
114c117
<         for i in xrange(self.total_form_count()):
---
>         for i in xrange(min(self.total_form_count(), self.absolute_max)):
362a366,370
>     if max_num is None:
>         max_num = DEFAULT_MAX_NUM
>     # hard limit on forms instantiated, to prevent memory-exhaustion attacks
>     # limit defaults to DEFAULT_MAX_NUM, but developer can increase it via max_num
>     absolute_max = max(DEFAULT_MAX_NUM, max_num)
365c373
<              'max_num': max_num}
---
>              'max_num': max_num, 'absolute_max': absolute_max}
diff -rw /tmp/Django-1.4/django/forms/widgets.py /tmp/Django-1.4.5/django/forms/widgets.py
489a490,495
> 
> # Defined at module level so that CheckboxInput is picklable (#17976)
> def boolean_check(v):
>     return not (v is False or v is None or v == '')
> 
> 
495,498c501
<         if check_test is None:
<             self.check_test = lambda v: not (v is False or v is None or v == '')
<         else:
<             self.check_test = check_test
---
>         self.check_test = boolean_check if check_test is None else check_test
diff -rw /tmp/Django-1.4/django/http/__init__.py /tmp/Django-1.4.5/django/http/__init__.py
12c12
< from urlparse import urljoin
---
> from urlparse import urljoin, urlparse
117c117
< from django.core.exceptions import ImproperlyConfigured
---
> from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
128a129,130
> host_validation_re = re.compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9:]+\])(:\d+)?$")
> 
214a217,219
> 
>         allowed_hosts = ['*'] if settings.DEBUG else settings.ALLOWED_HOSTS
>         if validate_host(host, allowed_hosts):
215a221,223
>         else:
>             raise SuspiciousOperation(
>                 "Invalid HTTP_HOST header (you may need to set ALLOWED_HOSTS): %s" % host)
734,735c742,743
< class HttpResponseRedirect(HttpResponse):
<     status_code = 302
---
> class HttpResponseRedirectBase(HttpResponse):
>     allowed_schemes = ['http', 'https', 'ftp']
738c746,749
<         super(HttpResponseRedirect, self).__init__()
---
>         super(HttpResponseRedirectBase, self).__init__()
>         parsed = urlparse(redirect_to)
>         if parsed.scheme and parsed.scheme not in self.allowed_schemes:
>             raise SuspiciousOperation("Unsafe redirect to URL with scheme '%s'" % parsed.scheme)
741,742c752,753
< class HttpResponsePermanentRedirect(HttpResponse):
<     status_code = 301
---
> class HttpResponseRedirect(HttpResponseRedirectBase):
>     status_code = 302
744,746c755,756
<     def __init__(self, redirect_to):
<         super(HttpResponsePermanentRedirect, self).__init__()
<         self['Location'] = iri_to_uri(redirect_to)
---
> class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
>     status_code = 301
792a803,842
> def validate_host(host, allowed_hosts):
>     """
>     Validate the given host header value for this site.
> 
>     Check that the host looks valid and matches a host or host pattern in the
>     given list of ``allowed_hosts``. Any pattern beginning with a period
>     matches a domain and all its subdomains (e.g. ``.example.com`` matches
>     ``example.com`` and any subdomain), ``*`` matches anything, and anything
>     else must match exactly.
> 
>     Return ``True`` for a valid host, ``False`` otherwise.
> 
>     """
>     # All validation is case-insensitive
>     host = host.lower()
> 
>     # Basic sanity check
>     if not host_validation_re.match(host):
>         return False
> 
>     # Validate only the domain part.
>     if host[-1] == ']':
>         # It's an IPv6 address without a port.
>         domain = host
>     else:
>         domain = host.rsplit(':', 1)[0]
> 
>     for pattern in allowed_hosts:
>         pattern = pattern.lower()
>         match = (
>             pattern == '*' or
>             pattern.startswith('.') and (
>                 domain.endswith(pattern) or domain == pattern[1:]
>                 ) or
>             pattern == domain
>             )
>         if match:
>             return True
> 
>     return False
diff -rw /tmp/Django-1.4/django/__init__.py /tmp/Django-1.4.5/django/__init__.py
1c1
< VERSION = (1, 4, 0, 'final', 0)
---
> VERSION = (1, 4, 5, 'final', 0)
diff -rw /tmp/Django-1.4/django/middleware/transaction.py /tmp/Django-1.4.5/django/middleware/transaction.py
17a18,21
>             # This rollback might fail because of network failure for example.
>             # If rollback isn't possible it is impossible to clean the
>             # connection's state. So leave the connection in dirty state and
>             # let request_finished signal deal with cleaning the connection.
24a29,34
>                 # Note: it is possible that the commit fails. If the reason is
>                 # closed connection or some similar reason, then there is
>                 # little hope to proceed nicely. However, in some cases (
>                 # deferred foreign key checks for exampl) it is still possible
>                 # to rollback().
>                 try:
25a36,44
>                 except Exception:
>                     # If the rollback fails, the transaction state will be
>                     # messed up. It doesn't matter, the connection will be set
>                     # to clean state after the request finishes. And, we can't
>                     # clean the state here properly even if we wanted to, the
>                     # connection is in transaction but we can't rollback...
>                     transaction.rollback()
>                     transaction.leave_transaction_management()
>                     raise
diff -rw /tmp/Django-1.4/django/test/testcases.py /tmp/Django-1.4.5/django/test/testcases.py
65a66
> real_abort = transaction.abort
75a77
>     transaction.abort = nop
82a85
>     transaction.abort = real_abort
1145a1149,1155
> 
>         # Restore sqlite connections' non-sharability
>         for conn in connections.all():
>             if (conn.settings_dict['ENGINE'] == 'django.db.backends.sqlite3'
>                 and conn.settings_dict['NAME'] == ':memory:'):
>                 conn.allow_thread_sharing = False
> 
diff -rw /tmp/Django-1.4/django/test/utils.py /tmp/Django-1.4.5/django/test/utils.py
77a78,80
>     settings._original_allowed_hosts = settings.ALLOWED_HOSTS
>     settings.ALLOWED_HOSTS = ['*']
> 
94a98,100
> 
>     settings.ALLOWED_HOSTS = settings._original_allowed_hosts
>     del settings._original_allowed_hosts
diff -rw /tmp/Django-1.4/django/utils/encoding.py /tmp/Django-1.4.5/django/utils/encoding.py
185a186,197
> 
> # Forwards compatibility with Django 1.5
> 
> def python_2_unicode_compatible(klass):
>     # Always use the Python 2 branch of the decorator here in Django 1.4
>     klass.__unicode__ = klass.__str__
>     klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
>     return klass
> 
> smart_text = smart_unicode
> force_text = force_unicode
> smart_bytes = smart_str
diff -rw /tmp/Django-1.4/django/utils/html_parser.py /tmp/Django-1.4.5/django/utils/html_parser.py
2a3
> import sys
3a5
> current_version = sys.version_info
4a7,14
> use_workaround = (
>     (current_version < (2, 7, 3)) or
>     (current_version >= (3, 0) and current_version < (3, 2, 3))
> )
> 
> if not use_workaround:
>     HTMLParser = _HTMLParser.HTMLParser
> else:
diff -rw /tmp/Django-1.4/django/utils/http.py /tmp/Django-1.4.5/django/utils/http.py
226a227,238
> 
> def is_safe_url(url, host=None):
>     """
>     Return ``True`` if the url is a safe redirection (i.e. it doesn't point to
>     a different host).
> 
>     Always returns ``False`` on an empty url.
>     """
>     if not url:
>         return False
>     netloc = urlparse.urlparse(url)[1]
>     return not netloc or netloc == host
diff -rw /tmp/Django-1.4/django/utils/safestring.py /tmp/Django-1.4.5/django/utils/safestring.py
119a120,125
> # Forwards compatibility with Django 1.5
> 
> EscapeBytes = EscapeString
> EscapeText = EscapeUnicode
> SafeBytes = SafeString
> SafeText = SafeUnicode
Only in /tmp/Django-1.4.5/django/utils: six.py
diff -rw /tmp/Django-1.4/django/utils/translation/trans_real.py /tmp/Django-1.4.5/django/utils/translation/trans_real.py
441,442c441,442
< inline_re = re.compile(r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))(\s+.*context\s+(?:"[^"]*?")|(?:'[^']*?'))?\s*""")
< block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+(?:"[^"]*?")|(?:'[^']*?'))?(?:\s+|$)""")
---
> inline_re = re.compile(r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?\s*""")
> block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""")
diff -rw /tmp/Django-1.4/django/views/debug.py /tmp/Django-1.4.5/django/views/debug.py
158,160c158,171
<         func_name = tb_frame.f_code.co_name
<         func = tb_frame.f_globals.get(func_name)
<         sensitive_variables = getattr(func, 'sensitive_variables', [])
---
>         # Loop through the frame's callers to see if the sensitive_variables
>         # decorator was used.
>         current_frame = tb_frame.f_back
>         sensitive_variables = None
>         while current_frame is not None:
>             if (current_frame.f_code.co_name == 'sensitive_variables_wrapper'
>                 and 'sensitive_variables_wrapper' in current_frame.f_locals):
>                 # The sensitive_variables decorator was used, so we take note
>                 # of the sensitive variables' names.
>                 wrapper = current_frame.f_locals['sensitive_variables_wrapper']
>                 sensitive_variables = getattr(wrapper, 'sensitive_variables', None)
>                 break
>             current_frame = current_frame.f_back
> 
diff -rw /tmp/Django-1.4/django/views/decorators/debug.py /tmp/Django-1.4.5/django/views/decorators/debug.py
29c29
<         def wrapper(*args, **kwargs):
---
>         def sensitive_variables_wrapper(*args, **kwargs):
31c31
<                 wrapper.sensitive_variables = variables
---
>                 sensitive_variables_wrapper.sensitive_variables = variables
33c33
<                 wrapper.sensitive_variables = '__ALL__'
---
>                 sensitive_variables_wrapper.sensitive_variables = '__ALL__'
35c35
<         return wrapper
---
>         return sensitive_variables_wrapper
64c64
<         def wrapper(request, *args, **kwargs):
---
>         def sensitive_post_parameters_wrapper(request, *args, **kwargs):
70c70
<         return wrapper
---
>         return sensitive_post_parameters_wrapper
diff -rw /tmp/Django-1.4/django/views/i18n.py /tmp/Django-1.4.5/django/views/i18n.py
10a11,12
> from django.utils.http import is_safe_url
> 
23,26c25,28
<     next = request.REQUEST.get('next', None)
<     if not next:
<         next = request.META.get('HTTP_REFERER', None)
<     if not next:
---
>     next = request.REQUEST.get('next')
>     if not is_safe_url(url=next, host=request.get_host()):
>         next = request.META.get('HTTP_REFERER')
>         if not is_safe_url(url=next, host=request.get_host()):

Leave a Reply

You must be logged in to post a comment.