diff -Nru python-django-1.6.1/AUTHORS python-django-1.6.11/AUTHORS
--- python-django-1.6.1/AUTHORS 2013-12-12 19:37:58.000000000 +0000
+++ python-django-1.6.11/AUTHORS 2015-03-18 23:50:42.000000000 +0000
@@ -60,6 +60,7 @@
Mathieu Agopian
Roberto Aguilar
ajs
+ Akis Kesoglou
alang@bright-green.com
A S Alam
Andi Albrecht
@@ -396,6 +397,7 @@
Javier Mansilla
masonsimon+django@gmail.com
Manuzhai
+ Moayad Mardini
Petr Marhoun
Petar Marić
Nuno Mariz
@@ -599,6 +601,7 @@
David Tulig
Justine Tunney
Amit Upadhyay
+ valtron
Adam Vandenberg
Geert Vanderkelen
Vasil Vangelovski
@@ -657,7 +660,7 @@
Ian Bicking for convincing Adrian to ditch code generation.
- Mark Pilgrim for "Dive Into Python" (http://diveintopython.net,
+ Mark Pilgrim for "Dive Into Python" (http://www.diveintopython.net,
http://www.diveintopython3.net).
Guido van Rossum for creating Python.
diff -Nru python-django-1.6.1/debian/changelog python-django-1.6.11/debian/changelog
--- python-django-1.6.1/debian/changelog 2016-03-07 13:50:01.000000000 +0000
+++ python-django-1.6.11/debian/changelog 2019-01-08 19:00:38.000000000 +0000
@@ -1,3 +1,83 @@
+python-django (1.6.11-0ubuntu1.3) trusty-security; urgency=medium
+
+ * SECURITY UPDATE: content spoofing in the default 404 page
+ - debian/patches/CVE-2019-3498.patch: properly quote string in
+ django/views/defaults.py.
+ - CVE-2019-3498
+
+ -- Marc Deslauriers Tue, 08 Jan 2019 14:00:29 -0500
+
+python-django (1.6.11-0ubuntu1.2) trusty-security; urgency=medium
+
+ * SECURITY UPDATE: DoS in urlize and urlizetrunc template filters
+ - debian/patches/CVE-2018-7536.patch: fix backtracking in
+ django/utils/html.py, add test to tests/utils_tests/test_html.py.
+ - CVE-2018-7536
+ * SECURITY UPDATE: DoS in truncatechars_html and truncatewords_html
+ template filters
+ - debian/patches/CVE-2018-7537.patch: fix backtracking in
+ django/utils/text.py, add test to tests/utils_tests/test_text.py.
+ - CVE-2018-7537
+
+ -- Marc Deslauriers Mon, 05 Mar 2018 15:52:37 +0100
+
+python-django (1.6.11-0ubuntu1.1) trusty-security; urgency=medium
+
+ * SECURITY UPDATE: Open redirect and possible XSS attack via
+ user-supplied numeric redirect URLs
+ - debian/patches/CVE-2017-7233.patch: fix is_safe_url() with numeric
+ URLs in django/utils/http.py, added tests to
+ tests/utils_tests/test_http.py.
+ - CVE-2017-7233
+ * SECURITY UPDATE: Open redirect vulnerability in
+ django.views.static.serve()
+ - debian/patches/CVE-2017-7234.patch: remove redirect from
+ django/views/static.py.
+ - CVE-2017-7234
+
+ -- Marc Deslauriers Wed, 29 Mar 2017 07:38:12 -0400
+
+python-django (1.6.11-0ubuntu1) trusty; urgency=medium
+
+ * Update to final upstream 1.6 microrelease (LP: #1644346)
+ * Drop patches included upstream:
+ - debian/patches/07_translation_encoding_fix.diff, ticket21869.diff,
+ CVE-2014-0472.patch, CVE-2014-0473.patch, CVE-2014-0474.patch,
+ CVE-2014-0472-regression.patch, drop_fix_ie_for_vary_1_6.diff,
+ is_safe_url_1_6.diff, CVE-2014-0480.patch, CVE-2014-0481.patch,
+ CVE-2014-0482.patch, CVE-2014-0483.patch, CVE-2014-0483-bug23329.patch,
+ CVE-2014-0483-bug23431.patch, CVE-2015-0219.patch, CVE-2015-0220.patch,
+ CVE-2015-0221.patch, CVE-2015-0222.patch, CVE-2015-2316.patch, and
+ CVE-2015-2317.patch
+
+ -- Scott Kitterman Wed, 23 Nov 2016 14:41:31 -0500
+
+python-django (1.6.1-2ubuntu0.16) trusty-security; urgency=medium
+
+ * SECURITY UPDATE: user with hardcoded password created when running
+ tests on Oracle
+ - debian/patches/CVE-2016-9013.patch: remove hardcoded password in
+ django/db/backends/oracle/creation.py, added note to
+ docs/ref/settings.txt.
+ - CVE-2016-9013
+ * SECURITY UPDATE: DNS rebinding vulnerability when DEBUG=True
+ - debian/patches/CVE-2016-9014.patch: properly check ALLOWED_HOSTS in
+ django/http/request.py, updated docs/ref/settings.txt, added test to
+ tests/requests/tests.py.
+ - CVE-2016-9014
+
+ -- Marc Deslauriers Mon, 31 Oct 2016 10:14:20 -0400
+
+python-django (1.6.1-2ubuntu0.15) trusty-security; urgency=medium
+
+ * SECURITY UPDATE: CSRF protection bypass on a site with Google Analytics
+ - debian/patches/CVE-2016-7401.patch: simplify cookie parsing in
+ django/http/cookie.py, add tests to tests/httpwrappers/tests.py,
+ tests/requests/tests.py.
+ - CVE-2016-7401
+
+ -- Marc Deslauriers Mon, 26 Sep 2016 07:36:53 -0400
+
python-django (1.6.1-2ubuntu0.14) trusty-security; urgency=medium
* SECURITY REGRESSION: is_safe_url() with non-unicode url (LP: #1553251)
diff -Nru python-django-1.6.1/debian/patches/02_disable-sources-in-sphinxdoc.diff python-django-1.6.11/debian/patches/02_disable-sources-in-sphinxdoc.diff
--- python-django-1.6.1/debian/patches/02_disable-sources-in-sphinxdoc.diff 2012-03-31 11:14:53.000000000 +0000
+++ python-django-1.6.11/debian/patches/02_disable-sources-in-sphinxdoc.diff 2016-11-09 17:07:14.000000000 +0000
@@ -7,9 +7,11 @@
Author: Raphaël Hertzog
Origin: vendor
---- a/docs/conf.py
-+++ b/docs/conf.py
-@@ -168,7 +168,10 @@ html_additional_pages = {}
+Index: python-django-1.6.11/docs/conf.py
+===================================================================
+--- python-django-1.6.11.orig/docs/conf.py 2016-11-09 12:06:52.320439986 -0500
++++ python-django-1.6.11/docs/conf.py 2016-11-09 12:06:52.316439985 -0500
+@@ -190,7 +190,10 @@
#html_split_index = False
# If true, links to the reST sources are added to the pages.
diff -Nru python-django-1.6.1/debian/patches/07_translation_encoding_fix.diff python-django-1.6.11/debian/patches/07_translation_encoding_fix.diff
--- python-django-1.6.1/debian/patches/07_translation_encoding_fix.diff 2014-01-29 14:58:20.000000000 +0000
+++ python-django-1.6.11/debian/patches/07_translation_encoding_fix.diff 1970-01-01 00:00:00.000000000 +0000
@@ -1,34 +0,0 @@
-Description: Remove doubly-UTF-8-encoded comment from German translations.
-
-We instead replace the offending line with the attribution information
-currently available in master.
-
-Author: Luke Faraone
-Origin: vendor
-Bug: https://code.djangoproject.com/ticket/21601
-Bug-Debian: http://bugs.debian.org/729194
-Forwarded: https://code.djangoproject.com/attachment/ticket/21601/21601.diff
-Last-Update: 2013-12-12
-
---- python-django-1.6.1.orig/django/contrib/admindocs/locale/de/LC_MESSAGES/django.po
-+++ python-django-1.6.1/django/contrib/admindocs/locale/de/LC_MESSAGES/django.po
-@@ -1,7 +1,7 @@
- # This file is distributed under the same license as the Django package.
- #
- # Translators:
--# Jannis , 2013
-+# Jannis Leidel , 2013
- msgid ""
- msgstr ""
- "Project-Id-Version: django-core\n"
---- python-django-1.6.1.orig/django/contrib/auth/locale/de/LC_MESSAGES/django.po
-+++ python-django-1.6.1/django/contrib/auth/locale/de/LC_MESSAGES/django.po
-@@ -3,7 +3,7 @@
- # Translators:
- # André Hagenbruch , 2011
- # apollo13 , 2012
--# Jannis , 2013
-+# Jannis Leidel , 2013
- # Markus Holtermann , 2013
- msgid ""
- msgstr ""
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0472.patch python-django-1.6.11/debian/patches/CVE-2014-0472.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0472.patch 2014-04-19 13:02:01.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0472.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,147 +0,0 @@
-Description: fix unexpected code execution using reverse()
-Origin: provided by upstream
-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-django/+bug/1309779
-
-Index: python-django-1.6.1/django/core/urlresolvers.py
-===================================================================
---- python-django-1.6.1.orig/django/core/urlresolvers.py 2014-04-19 08:48:23.470155540 -0400
-+++ python-django-1.6.1/django/core/urlresolvers.py 2014-04-19 08:48:23.462155540 -0400
-@@ -243,6 +243,10 @@
- self._reverse_dict = {}
- self._namespace_dict = {}
- self._app_dict = {}
-+ # set of dotted paths to all functions and classes that are used in
-+ # urlpatterns
-+ self._callback_strs = set()
-+ self._populated = False
-
- def __repr__(self):
- if isinstance(self.urlconf_name, list) and len(self.urlconf_name):
-@@ -260,6 +264,15 @@
- apps = {}
- language_code = get_language()
- for pattern in reversed(self.url_patterns):
-+ if hasattr(pattern, '_callback_str'):
-+ self._callback_strs.add(pattern._callback_str)
-+ elif hasattr(pattern, '_callback'):
-+ callback = pattern._callback
-+ if not hasattr(callback, '__name__'):
-+ lookup_str = callback.__module__ + "." + callback.__class__.__name__
-+ else:
-+ lookup_str = callback.__module__ + "." + callback.__name__
-+ self._callback_strs.add(lookup_str)
- p_pattern = pattern.regex.pattern
- if p_pattern.startswith('^'):
- p_pattern = p_pattern[1:]
-@@ -280,6 +293,7 @@
- namespaces[namespace] = (p_pattern + prefix, sub_pattern)
- for app_name, namespace_list in pattern.app_dict.items():
- apps.setdefault(app_name, []).extend(namespace_list)
-+ self._callback_strs.update(pattern._callback_strs)
- else:
- bits = normalize(p_pattern)
- lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args))
-@@ -288,6 +302,7 @@
- self._reverse_dict[language_code] = lookups
- self._namespace_dict[language_code] = namespaces
- self._app_dict[language_code] = apps
-+ self._populated = True
-
- @property
- def reverse_dict(self):
-@@ -380,8 +395,12 @@
- text_args = [force_text(v) for v in args]
- text_kwargs = dict((k, force_text(v)) for (k, v) in kwargs.items())
-
-+ if not self._populated:
-+ self._populate()
-+
- try:
-- lookup_view = get_callable(lookup_view, True)
-+ if lookup_view in self._callback_strs:
-+ lookup_view = get_callable(lookup_view, True)
- except (ImportError, AttributeError) as e:
- raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e))
- possibilities = self.reverse_dict.getlist(lookup_view)
-Index: python-django-1.6.1/tests/urlpatterns_reverse/nonimported_module.py
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ python-django-1.6.1/tests/urlpatterns_reverse/nonimported_module.py 2014-04-19 08:48:23.462155540 -0400
-@@ -0,0 +1,3 @@
-+def view(request):
-+ """Stub view"""
-+ pass
-Index: python-django-1.6.1/tests/urlpatterns_reverse/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/urlpatterns_reverse/tests.py 2014-04-19 08:48:23.470155540 -0400
-+++ python-django-1.6.1/tests/urlpatterns_reverse/tests.py 2014-04-19 08:48:23.466155540 -0400
-@@ -1,8 +1,11 @@
-+# -*- coding: utf-8 -*-
- """
- Unit tests for reverse URL lookups.
- """
- from __future__ import absolute_import, unicode_literals
-
-+import sys
-+
- from django.conf import settings
- from django.contrib.auth.models import User
- from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
-@@ -313,6 +316,25 @@
- self.assertEqual(res.url, '/foo/')
- res = redirect('http://example.com/')
- self.assertEqual(res.url, 'http://example.com/')
-+ # Assert that we can redirect using UTF-8 strings
-+ res = redirect('/æøå/abc/')
-+ self.assertEqual(res.url, '/%C3%A6%C3%B8%C3%A5/abc/')
-+ # Assert that no imports are attempted when dealing with a relative path
-+ # (previously, the below would resolve in a UnicodeEncodeError from __import__ )
-+ res = redirect('/æøå.abc/')
-+ self.assertEqual(res.url, '/%C3%A6%C3%B8%C3%A5.abc/')
-+ res = redirect('os.path')
-+ self.assertEqual(res.url, 'os.path')
-+
-+ def test_no_illegal_imports(self):
-+ # modules that are not listed in urlpatterns should not be importable
-+ redirect("urlpatterns_reverse.nonimported_module.view")
-+ self.assertNotIn("urlpatterns_reverse.nonimported_module", sys.modules)
-+
-+ def test_reverse_by_path_nested(self):
-+ # Views that are added to urlpatterns using include() should be
-+ # reversable by doted path.
-+ self.assertEqual(reverse('urlpatterns_reverse.views.nested_view'), '/includes/nested_path/')
-
- def test_redirect_view_object(self):
- from .views import absolute_kwargs_view
-@@ -641,4 +663,3 @@
- # swallow it.
- self.assertRaises(AttributeError, get_callable,
- 'urlpatterns_reverse.views_broken.i_am_broken')
--
-Index: python-django-1.6.1/tests/urlpatterns_reverse/urls.py
-===================================================================
---- python-django-1.6.1.orig/tests/urlpatterns_reverse/urls.py 2014-04-19 08:48:23.470155540 -0400
-+++ python-django-1.6.1/tests/urlpatterns_reverse/urls.py 2014-04-19 08:48:23.466155540 -0400
-@@ -7,6 +7,7 @@
-
- other_patterns = patterns('',
- url(r'non_path_include/$', empty_view, name='non_path_include'),
-+ url(r'nested_path/$', 'urlpatterns_reverse.views.nested_view'),
- )
-
- urlpatterns = patterns('',
-Index: python-django-1.6.1/tests/urlpatterns_reverse/views.py
-===================================================================
---- python-django-1.6.1.orig/tests/urlpatterns_reverse/views.py 2014-04-19 08:48:23.470155540 -0400
-+++ python-django-1.6.1/tests/urlpatterns_reverse/views.py 2014-04-19 08:48:23.466155540 -0400
-@@ -16,6 +16,10 @@
- def defaults_view(request, arg1, arg2):
- pass
-
-+def nested_view(request):
-+ pass
-+
-+
- def erroneous_view(request):
- import non_existent
-
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0472-regression.patch python-django-1.6.11/debian/patches/CVE-2014-0472-regression.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0472-regression.patch 2014-04-23 03:04:57.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0472-regression.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,82 +0,0 @@
-From b63ae5c60619a257ad57cf6043e71f681283e47b Mon Sep 17 00:00:00 2001
-From: Preston Timmons
-Date: Tue, 22 Apr 2014 20:19:46 +0000
-Subject: [PATCH] Fixed #22486 -- Reverse raises AttributeError on partial
- functions.
-
-Create the lookup_str from the original function whenever a partial
-is provided as an argument to a url pattern.
----
- django/core/urlresolvers.py | 4 ++++
- tests/urlpatterns_reverse/urls.py | 6 +++++-
- tests/urlpatterns_reverse/views.py | 10 ++++++++++
- 3 files changed, 19 insertions(+), 1 deletion(-)
-
-Index: python-django-1.6.1/django/core/urlresolvers.py
-===================================================================
---- python-django-1.6.1.orig/django/core/urlresolvers.py 2014-04-22 23:03:19.520345704 -0400
-+++ python-django-1.6.1/django/core/urlresolvers.py 2014-04-22 23:03:52.492346238 -0400
-@@ -8,6 +8,7 @@
- """
- from __future__ import unicode_literals
-
-+import functools
- import re
- from threading import local
-
-@@ -268,6 +269,9 @@
- self._callback_strs.add(pattern._callback_str)
- elif hasattr(pattern, '_callback'):
- callback = pattern._callback
-+ if isinstance(callback, functools.partial):
-+ callback = callback.func
-+
- if not hasattr(callback, '__name__'):
- lookup_str = callback.__module__ + "." + callback.__class__.__name__
- else:
-Index: python-django-1.6.1/tests/urlpatterns_reverse/urls.py
-===================================================================
---- python-django-1.6.1.orig/tests/urlpatterns_reverse/urls.py 2014-04-22 23:03:19.520345704 -0400
-+++ python-django-1.6.1/tests/urlpatterns_reverse/urls.py 2014-04-22 23:04:27.060346799 -0400
-@@ -2,7 +2,7 @@
-
- from django.conf.urls import patterns, url, include
-
--from .views import empty_view, absolute_kwargs_view
-+from .views import empty_view, empty_view_partial, empty_view_wrapped, absolute_kwargs_view
-
-
- other_patterns = patterns('',
-@@ -53,6 +53,10 @@
- include('urlpatterns_reverse.included_urls')),
- url('', include('urlpatterns_reverse.extra_urls')),
-
-+ # Partials should be fine.
-+ url(r'^partial/', empty_view_partial, name="partial"),
-+ url(r'^partial_wrapped/', empty_view_wrapped, name="partial_wrapped"),
-+
- # This is non-reversible, but we shouldn't blow up when parsing it.
- url(r'^(?:foo|bar)(\w+)/$', empty_view, name="disjunction"),
-
-Index: python-django-1.6.1/tests/urlpatterns_reverse/views.py
-===================================================================
---- python-django-1.6.1.orig/tests/urlpatterns_reverse/views.py 2014-04-22 23:03:19.520345704 -0400
-+++ python-django-1.6.1/tests/urlpatterns_reverse/views.py 2014-04-22 23:03:19.512345704 -0400
-@@ -1,3 +1,5 @@
-+from functools import partial, update_wrapper
-+
- from django.http import HttpResponse
- from django.views.generic import RedirectView
- from django.core.urlresolvers import reverse_lazy
-@@ -45,3 +47,11 @@
-
- def bad_view(request, *args, **kwargs):
- raise ValueError("I don't think I'm getting good value for this view")
-+
-+
-+empty_view_partial = partial(empty_view, template_name="template.html")
-+
-+
-+empty_view_wrapped = update_wrapper(
-+ partial(empty_view, template_name="template.html"), empty_view,
-+)
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0473.patch python-django-1.6.11/debian/patches/CVE-2014-0473.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0473.patch 2014-04-19 13:02:54.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0473.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,94 +0,0 @@
-Description: fix caching of anonymous pages could reveal CSRF token
-Origin: commit 95893e4b4225a7ec8cd4a13fbcc0b329a9517c0d
-Author: Aymeric Augustin
-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-django/+bug/1309782
-
-diff --git a/django/middleware/cache.py b/django/middleware/cache.py
-index e13a8c3..7bbc167 100644
---- a/django/middleware/cache.py
-+++ b/django/middleware/cache.py
-@@ -47,7 +47,8 @@ import warnings
-
- from django.conf import settings
- from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS
--from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age
-+from django.utils.cache import (get_cache_key, get_max_age, has_vary_header,
-+ learn_cache_key, patch_response_headers)
-
-
- class UpdateCacheMiddleware(object):
-@@ -90,8 +91,15 @@ class UpdateCacheMiddleware(object):
- if not self._should_update_cache(request, response):
- # We don't need to update the cache, just return.
- return response
-+
- if response.streaming or response.status_code != 200:
- return response
-+
-+ # Don't cache responses that set a user-specific (and maybe security
-+ # sensitive) cookie in response to a cookie-less request.
-+ if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
-+ return response
-+
- # Try to get the timeout from the "max-age" section of the "Cache-
- # Control" header before reverting to using the default cache_timeout
- # length.
-diff --git a/tests/cache/tests.py b/tests/cache/tests.py
-index 7413a4a..04ef21b 100644
---- a/tests/cache/tests.py
-+++ b/tests/cache/tests.py
-@@ -19,12 +19,14 @@ from django.core import management
- from django.core.cache import get_cache
- from django.core.cache.backends.base import (CacheKeyWarning,
- InvalidCacheBackendError)
-+from django.core.context_processors import csrf
- from django.db import router, transaction
- from django.core.cache.utils import make_template_fragment_key
- from django.http import (HttpResponse, HttpRequest, StreamingHttpResponse,
- QueryDict)
- from django.middleware.cache import (FetchFromCacheMiddleware,
- UpdateCacheMiddleware, CacheMiddleware)
-+from django.middleware.csrf import CsrfViewMiddleware
- from django.template import Template
- from django.template.response import TemplateResponse
- from django.test import TestCase, TransactionTestCase, RequestFactory
-@@ -1578,6 +1580,10 @@ def hello_world_view(request, value):
- return HttpResponse('Hello World %s' % value)
-
-
-+def csrf_view(request):
-+ return HttpResponse(csrf(request)['csrf_token'])
-+
-+
- @override_settings(
- CACHE_MIDDLEWARE_ALIAS='other',
- CACHE_MIDDLEWARE_KEY_PREFIX='middlewareprefix',
-@@ -1797,6 +1803,28 @@ class CacheMiddlewareTest(IgnorePendingDeprecationWarningsMixin, TestCase):
- response = other_with_prefix_view(request, '16')
- self.assertEqual(response.content, b'Hello World 16')
-
-+ def test_sensitive_cookie_not_cached(self):
-+ """
-+ Django must prevent caching of responses that set a user-specific (and
-+ maybe security sensitive) cookie in response to a cookie-less request.
-+ """
-+ csrf_middleware = CsrfViewMiddleware()
-+ cache_middleware = CacheMiddleware()
-+
-+ request = self.factory.get('/view/')
-+ self.assertIsNone(cache_middleware.process_request(request))
-+
-+ csrf_middleware.process_view(request, csrf_view, (), {})
-+
-+ response = csrf_view(request)
-+
-+ response = csrf_middleware.process_response(request, response)
-+ response = cache_middleware.process_response(request, response)
-+
-+ # Inserting a CSRF cookie in a cookie-less request prevented caching.
-+ self.assertIsNone(cache_middleware.process_request(request))
-+
-+
- @override_settings(
- CACHE_MIDDLEWARE_KEY_PREFIX='settingsprefix',
- CACHE_MIDDLEWARE_SECONDS=1,
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0474.patch python-django-1.6.11/debian/patches/CVE-2014-0474.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0474.patch 2014-04-19 13:03:20.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0474.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,255 +0,0 @@
-Description: fix MySQL typecasting issue
-Origin: provided by upstream
-Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-django/+bug/1309784
-
-Index: python-django-1.6.1/django/db/models/fields/__init__.py
-===================================================================
---- python-django-1.6.1.orig/django/db/models/fields/__init__.py 2014-04-19 08:48:00.998155176 -0400
-+++ python-django-1.6.1/django/db/models/fields/__init__.py 2014-04-19 08:48:00.990155175 -0400
-@@ -1013,6 +1013,12 @@
- kwargs['max_length'] = kwargs.get('max_length', 100)
- Field.__init__(self, verbose_name, name, **kwargs)
-
-+ def get_prep_value(self, value):
-+ value = super(FilePathField, self).get_prep_value(value)
-+ if value is None:
-+ return None
-+ return six.text_type(value)
-+
- def formfield(self, **kwargs):
- defaults = {
- 'path': self.path,
-@@ -1120,6 +1126,12 @@
- kwargs['max_length'] = 15
- Field.__init__(self, *args, **kwargs)
-
-+ def get_prep_value(self, value):
-+ value = super(IPAddressField, self).get_prep_value(value)
-+ if value is None:
-+ return None
-+ return six.text_type(value)
-+
- def get_internal_type(self):
- return "IPAddressField"
-
-@@ -1158,12 +1170,14 @@
- return value or None
-
- def get_prep_value(self, value):
-+ if value is None:
-+ return value
- if value and ':' in value:
- try:
- return clean_ipv6_address(value, self.unpack_ipv4)
- except exceptions.ValidationError:
- pass
-- return value
-+ return six.text_type(value)
-
- def formfield(self, **kwargs):
- defaults = {
-Index: python-django-1.6.1/docs/howto/custom-model-fields.txt
-===================================================================
---- python-django-1.6.1.orig/docs/howto/custom-model-fields.txt 2014-04-19 08:48:00.998155176 -0400
-+++ python-django-1.6.1/docs/howto/custom-model-fields.txt 2014-04-19 08:48:00.990155175 -0400
-@@ -501,6 +501,16 @@
- return ''.join([''.join(l) for l in (value.north,
- value.east, value.south, value.west)])
-
-+.. warning::
-+
-+ If your custom field uses the ``CHAR``, ``VARCHAR`` or ``TEXT``
-+ types for MySQL, you must make sure that :meth:`.get_prep_value`
-+ always returns a string type. MySQL performs flexible and unexpected
-+ matching when a query is performed on these types and the provided
-+ value is an integer, which can cause queries to include unexpected
-+ objects in their results. This problem cannot occur if you always
-+ return a string type from :meth:`.get_prep_value`.
-+
- Converting query values to database values
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Index: python-django-1.6.1/docs/ref/databases.txt
-===================================================================
---- python-django-1.6.1.orig/docs/ref/databases.txt 2014-04-19 08:48:00.998155176 -0400
-+++ python-django-1.6.1/docs/ref/databases.txt 2014-04-19 08:48:00.990155175 -0400
-@@ -484,6 +484,22 @@
- statement. If ``select_for_update()`` is used with ``nowait=True`` then a
- ``DatabaseError`` will be raised.
-
-+Automatic typecasting can cause unexpected results
-+--------------------------------------------------
-+
-+When performing a query on a string type, but with an integer value, MySQL will
-+coerce the types of all values in the table to an integer before performing the
-+comparison. If your table contains the values ``'abc'``, ``'def'`` and you
-+query for ``WHERE mycolumn=0``, both rows will match. Similarly, ``WHERE mycolumn=1``
-+will match the value ``'abc1'``. Therefore, string type fields included in Django
-+will always cast the value to a string before using it in a query.
-+
-+If you implement custom model fields that inherit from :class:`~django.db.models.Field`
-+directly, are overriding :meth:`~django.db.models.Field.get_prep_value`, or use
-+:meth:`extra() ` or
-+:meth:`raw() `, you should ensure that you
-+perform the appropriate typecasting.
-+
- .. _sqlite-notes:
-
- SQLite notes
-Index: python-django-1.6.1/docs/ref/models/querysets.txt
-===================================================================
---- python-django-1.6.1.orig/docs/ref/models/querysets.txt 2014-04-19 08:48:00.998155176 -0400
-+++ python-django-1.6.1/docs/ref/models/querysets.txt 2014-04-19 08:48:00.990155175 -0400
-@@ -1132,6 +1132,16 @@
-
- Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
-
-+.. warning::
-+
-+ If you are performing queries on MySQL, note that MySQL's silent type coercion
-+ may cause unexpected results when mixing types. If you query on a string
-+ type column, but with an integer value, MySQL will coerce the types of all values
-+ in the table to an integer before performing the comparison. For example, if your
-+ table contains the values ``'abc'``, ``'def'`` and you query for ``WHERE mycolumn=0``,
-+ both rows will match. To prevent this, perform the correct typecasting
-+ before using the value in a query.
-+
- defer
- ~~~~~
-
-Index: python-django-1.6.1/docs/topics/db/sql.txt
-===================================================================
---- python-django-1.6.1.orig/docs/topics/db/sql.txt 2014-04-19 08:48:00.998155176 -0400
-+++ python-django-1.6.1/docs/topics/db/sql.txt 2014-04-19 08:48:00.990155175 -0400
-@@ -66,6 +66,16 @@
- database, but does nothing to enforce that. If the query does not
- return rows, a (possibly cryptic) error will result.
-
-+.. warning::
-+
-+ If you are performing queries on MySQL, note that MySQL's silent type coercion
-+ may cause unexpected results when mixing types. If you query on a string
-+ type column, but with an integer value, MySQL will coerce the types of all values
-+ in the table to an integer before performing the comparison. For example, if your
-+ table contains the values ``'abc'``, ``'def'`` and you query for ``WHERE mycolumn=0``,
-+ both rows will match. To prevent this, perform the correct typecasting
-+ before using the value in a query.
-+
- Mapping query fields to model fields
- ------------------------------------
-
-Index: python-django-1.6.1/tests/model_fields/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/model_fields/tests.py 2014-04-19 08:48:00.998155176 -0400
-+++ python-django-1.6.1/tests/model_fields/tests.py 2014-04-19 08:48:00.994155175 -0400
-@@ -7,7 +7,14 @@
- from django import forms
- from django.core.exceptions import ValidationError
- from django.db import connection, models, IntegrityError
--from django.db.models.fields.files import FieldFile
-+from django.db.models.fields import (
-+ AutoField, BigIntegerField, BinaryField, BooleanField, CharField,
-+ CommaSeparatedIntegerField, DateField, DateTimeField, DecimalField,
-+ EmailField, FilePathField, FloatField, IntegerField, IPAddressField,
-+ GenericIPAddressField, NullBooleanField, PositiveIntegerField,
-+ PositiveSmallIntegerField, SlugField, SmallIntegerField, TextField,
-+ TimeField, URLField)
-+from django.db.models.fields.files import FileField, ImageField
- from django.utils import six
- from django.utils import unittest
-
-@@ -494,6 +501,94 @@
- self.assertRaises(ValidationError, form_field.clean, '127.0.0.1')
-
-
-+class PrepValueTest(test.TestCase):
-+ def test_AutoField(self):
-+ self.assertIsInstance(AutoField(primary_key=True).get_prep_value(1), int)
-+
-+ @unittest.skipIf(six.PY3, "Python 3 has no `long` type.")
-+ def test_BigIntegerField(self):
-+ self.assertIsInstance(BigIntegerField().get_prep_value(long(9999999999999999999)), long)
-+
-+ def test_BinaryField(self):
-+ self.assertIsInstance(BinaryField().get_prep_value(b''), bytes)
-+
-+ def test_BooleanField(self):
-+ self.assertIsInstance(BooleanField().get_prep_value(True), bool)
-+
-+ def test_CharField(self):
-+ self.assertIsInstance(CharField().get_prep_value(''), six.text_type)
-+ self.assertIsInstance(CharField().get_prep_value(0), six.text_type)
-+
-+ def test_CommaSeparatedIntegerField(self):
-+ self.assertIsInstance(CommaSeparatedIntegerField().get_prep_value('1,2'), six.text_type)
-+ self.assertIsInstance(CommaSeparatedIntegerField().get_prep_value(0), six.text_type)
-+
-+ def test_DateField(self):
-+ self.assertIsInstance(DateField().get_prep_value(datetime.date.today()), datetime.date)
-+
-+ def test_DateTimeField(self):
-+ self.assertIsInstance(DateTimeField().get_prep_value(datetime.datetime.now()), datetime.datetime)
-+
-+ def test_DecimalField(self):
-+ self.assertIsInstance(DecimalField().get_prep_value(Decimal('1.2')), Decimal)
-+
-+ def test_EmailField(self):
-+ self.assertIsInstance(EmailField().get_prep_value('mailbox@domain.com'), six.text_type)
-+
-+ def test_FileField(self):
-+ self.assertIsInstance(FileField().get_prep_value('filename.ext'), six.text_type)
-+ self.assertIsInstance(FileField().get_prep_value(0), six.text_type)
-+
-+ def test_FilePathField(self):
-+ self.assertIsInstance(FilePathField().get_prep_value('tests.py'), six.text_type)
-+ self.assertIsInstance(FilePathField().get_prep_value(0), six.text_type)
-+
-+ def test_FloatField(self):
-+ self.assertIsInstance(FloatField().get_prep_value(1.2), float)
-+
-+ def test_ImageField(self):
-+ self.assertIsInstance(ImageField().get_prep_value('filename.ext'), six.text_type)
-+
-+ def test_IntegerField(self):
-+ self.assertIsInstance(IntegerField().get_prep_value(1), int)
-+
-+ def test_IPAddressField(self):
-+ self.assertIsInstance(IPAddressField().get_prep_value('127.0.0.1'), six.text_type)
-+ self.assertIsInstance(IPAddressField().get_prep_value(0), six.text_type)
-+
-+ def test_GenericIPAddressField(self):
-+ self.assertIsInstance(GenericIPAddressField().get_prep_value('127.0.0.1'), six.text_type)
-+ self.assertIsInstance(GenericIPAddressField().get_prep_value(0), six.text_type)
-+
-+ def test_NullBooleanField(self):
-+ self.assertIsInstance(NullBooleanField().get_prep_value(True), bool)
-+
-+ def test_PositiveIntegerField(self):
-+ self.assertIsInstance(PositiveIntegerField().get_prep_value(1), int)
-+
-+ def test_PositiveSmallIntegerField(self):
-+ self.assertIsInstance(PositiveSmallIntegerField().get_prep_value(1), int)
-+
-+ def test_SlugField(self):
-+ self.assertIsInstance(SlugField().get_prep_value('slug'), six.text_type)
-+ self.assertIsInstance(SlugField().get_prep_value(0), six.text_type)
-+
-+ def test_SmallIntegerField(self):
-+ self.assertIsInstance(SmallIntegerField().get_prep_value(1), int)
-+
-+ def test_TextField(self):
-+ self.assertIsInstance(TextField().get_prep_value('Abc'), six.text_type)
-+ self.assertIsInstance(TextField().get_prep_value(0), six.text_type)
-+
-+ def test_TimeField(self):
-+ self.assertIsInstance(
-+ TimeField().get_prep_value(datetime.datetime.now().time()),
-+ datetime.time)
-+
-+ def test_URLField(self):
-+ self.assertIsInstance(URLField().get_prep_value('http://domain.com'), six.text_type)
-+
-+
- class CustomFieldTests(unittest.TestCase):
-
- def test_14786(self):
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0480.patch python-django-1.6.11/debian/patches/CVE-2014-0480.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0480.patch 2014-09-09 17:35:34.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0480.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,59 +0,0 @@
-From da051da8df5e69944745072611351d4cfc6435d5 Mon Sep 17 00:00:00 2001
-From: Florian Apolloner
-Date: Thu, 17 Jul 2014 21:59:28 +0200
-Subject: [PATCH] [1.6.x] Prevented reverse() from generating URLs pointing to
- other hosts.
-
-This is a security fix. Disclosure following shortly.
----
- django/core/urlresolvers.py | 6 +++++-
- docs/releases/1.4.14.txt | 13 +++++++++++++
- docs/releases/1.5.9.txt | 13 +++++++++++++
- docs/releases/1.6.6.txt | 13 +++++++++++++
- tests/urlpatterns_reverse/tests.py | 3 +++
- tests/urlpatterns_reverse/urls.py | 3 +++
- 6 files changed, 50 insertions(+), 1 deletion(-)
-
-diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
-index b3008e8..4f251ab 100644
---- a/django/core/urlresolvers.py
-+++ b/django/core/urlresolvers.py
-@@ -435,7 +435,11 @@ def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
- candidate_pat = prefix_norm.replace('%', '%%') + result
- if re.search('^%s%s' % (prefix_norm, pattern), candidate_pat % candidate_subs, re.UNICODE):
- candidate_subs = dict((k, urlquote(v)) for (k, v) in candidate_subs.items())
-- return candidate_pat % candidate_subs
-+ url = candidate_pat % candidate_subs
-+ # Don't allow construction of scheme relative urls.
-+ if url.startswith('//'):
-+ url = '/%%2F%s' % url[2:]
-+ return url
- # lookup_view can be URL label, or dotted path, or callable, Any of
- # these can be passed in at the top, but callables are not friendly in
- # error messages.
-diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py
-index 249acc1..7df4acf 100644
---- a/tests/urlpatterns_reverse/tests.py
-+++ b/tests/urlpatterns_reverse/tests.py
-@@ -147,6 +147,9 @@
- ('defaults', '/defaults_view2/3/', [], {'arg1': 3, 'arg2': 2}),
- ('defaults', NoReverseMatch, [], {'arg1': 3, 'arg2': 3}),
- ('defaults', NoReverseMatch, [], {'arg2': 1}),
-+
-+ # Security tests
-+ ('security', '/%2Fexample.com/security/', ['/example.com'], {}),
- )
-
- class NoURLPatternsTests(TestCase):
-diff --git a/tests/urlpatterns_reverse/urls.py b/tests/urlpatterns_reverse/urls.py
-index ac112c6..74c881e 100644
---- a/tests/urlpatterns_reverse/urls.py
-+++ b/tests/urlpatterns_reverse/urls.py
-@@ -71,4 +71,7 @@
- (r'defaults_view2/(?P\d+)/', 'defaults_view', {'arg2': 2}, 'defaults'),
-
- url('^includes/', include(other_patterns)),
-+
-+ # Security tests
-+ url('(.+)/security/$', empty_view, name='security'),
- )
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0481.patch python-django-1.6.11/debian/patches/CVE-2014-0481.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0481.patch 2014-09-09 17:35:42.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0481.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,209 +0,0 @@
-From dd0c3f4ee1a30c1a1e6055061c6ba6e58c6b54d1 Mon Sep 17 00:00:00 2001
-From: Tim Graham
-Date: Fri, 8 Aug 2014 10:20:08 -0400
-Subject: [PATCH] [1.6.x] Fixed #23157 -- Removed O(n) algorithm when uploading
- duplicate file names.
-
-This is a security fix. Disclosure following shortly.
----
- django/core/files/storage.py | 11 +++++------
- docs/howto/custom-file-storage.txt | 13 +++++++++++--
- docs/ref/files/storage.txt | 11 +++++++++++
- docs/releases/1.4.14.txt | 20 ++++++++++++++++++++
- docs/releases/1.5.9.txt | 20 ++++++++++++++++++++
- docs/releases/1.6.6.txt | 20 ++++++++++++++++++++
- tests/file_storage/tests.py | 21 +++++++++++++--------
- tests/files/tests.py | 22 +++++++++++++---------
- 8 files changed, 113 insertions(+), 25 deletions(-)
-
-Index: python-django-1.6.1/django/core/files/storage.py
-===================================================================
---- python-django-1.6.1.orig/django/core/files/storage.py 2014-09-09 13:35:39.572751632 -0400
-+++ python-django-1.6.1/django/core/files/storage.py 2014-09-09 13:35:39.568751632 -0400
-@@ -1,12 +1,12 @@
- import os
- import errno
--import itertools
- from datetime import datetime
-
- from django.conf import settings
- from django.core.exceptions import SuspiciousFileOperation
- from django.core.files import locks, File
- from django.core.files.move import file_move_safe
-+from django.utils.crypto import get_random_string
- from django.utils.encoding import force_text, filepath_to_uri
- from django.utils.functional import LazyObject
- from django.utils.module_loading import import_by_path
-@@ -67,13 +67,12 @@
- """
- dir_name, file_name = os.path.split(name)
- file_root, file_ext = os.path.splitext(file_name)
-- # If the filename already exists, add an underscore and a number (before
-- # the file extension, if one exists) to the filename until the generated
-- # filename doesn't exist.
-- count = itertools.count(1)
-+ # If the filename already exists, add an underscore and a random 7
-+ # character alphanumeric string (before the file extension, if one
-+ # exists) to the filename until the generated filename doesn't exist.
- while self.exists(name):
- # file_ext includes the dot.
-- name = os.path.join(dir_name, "%s_%s%s" % (file_root, next(count), file_ext))
-+ name = os.path.join(dir_name, "%s_%s%s" % (file_root, get_random_string(7), file_ext))
-
- return name
-
-Index: python-django-1.6.1/docs/howto/custom-file-storage.txt
-===================================================================
---- python-django-1.6.1.orig/docs/howto/custom-file-storage.txt 2014-09-09 13:35:39.572751632 -0400
-+++ python-django-1.6.1/docs/howto/custom-file-storage.txt 2014-09-09 13:35:39.568751632 -0400
-@@ -83,5 +83,14 @@
- will have already cleaned to a filename valid for the storage system, according
- to the ``get_valid_name()`` method described above.
-
--The code provided on ``Storage`` simply appends ``"_1"``, ``"_2"``, etc. to the
--filename until it finds one that's available in the destination directory.
-+.. versionchanged:: 1.6.6
-+
-+ If a file with ``name`` already exists, an underscore plus a random 7
-+ character alphanumeric string is appended to the filename before the
-+ extension.
-+
-+ Previously, an underscore followed by a number (e.g. ``"_1"``, ``"_2"``,
-+ etc.) was appended to the filename until an avaible name in the destination
-+ directory was found. A malicious user could exploit this deterministic
-+ algorithm to create a denial-of-service attack. This change was also made
-+ in Django 1.5.9 and 1.4.14.
-Index: python-django-1.6.1/docs/ref/files/storage.txt
-===================================================================
---- python-django-1.6.1.orig/docs/ref/files/storage.txt 2014-09-09 13:35:39.572751632 -0400
-+++ python-django-1.6.1/docs/ref/files/storage.txt 2014-09-09 13:35:39.568751632 -0400
-@@ -81,6 +81,17 @@
- available for new content to be written to on the target storage
- system.
-
-+ .. versionchanged:: 1.6.6
-+
-+ If a file with ``name`` already exists, an underscore plus a random 7
-+ character alphanumeric string is appended to the filename before the
-+ extension.
-+
-+ Previously, an underscore followed by a number (e.g. ``"_1"``, ``"_2"``,
-+ etc.) was appended to the filename until an avaible name in the
-+ destination directory was found. A malicious user could exploit this
-+ deterministic algorithm to create a denial-of-service attack. This
-+ change was also made in Django 1.5.9 and 1.4.14.
-
- .. method:: get_valid_name(name)
-
-Index: python-django-1.6.1/tests/file_storage/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/file_storage/tests.py 2014-09-09 13:35:39.572751632 -0400
-+++ python-django-1.6.1/tests/file_storage/tests.py 2014-09-09 13:35:39.568751632 -0400
-@@ -35,6 +35,9 @@
- Image = None
-
-
-+FILE_SUFFIX_REGEX = '[A-Za-z0-9]{7}'
-+
-+
- class GetStorageClassTests(SimpleTestCase):
-
- def test_get_filesystem_storage(self):
-@@ -430,10 +433,9 @@
- self.thread.start()
- name = self.save_file('conflict')
- self.thread.join()
-- self.assertTrue(self.storage.exists('conflict'))
-- self.assertTrue(self.storage.exists('conflict_1'))
-- self.storage.delete('conflict')
-- self.storage.delete('conflict_1')
-+ files = sorted(os.listdir(self.storage_dir))
-+ self.assertEqual(files[0], 'conflict')
-+ six.assertRegex(self, files[1], 'conflict_%s' % FILE_SUFFIX_REGEX)
-
- @unittest.skipIf(sys.platform.startswith('win'), "Windows only partially supports umasks and chmod.")
- class FileStoragePermissions(unittest.TestCase):
-@@ -477,9 +479,10 @@
- self.storage.save('dotted.path/test', ContentFile("1"))
- self.storage.save('dotted.path/test', ContentFile("2"))
-
-+ files = sorted(os.listdir(os.path.join(self.storage_dir, 'dotted.path')))
- self.assertFalse(os.path.exists(os.path.join(self.storage_dir, 'dotted_.path')))
-- self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/test')))
-- self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/test_1')))
-+ self.assertEqual(files[0], 'test')
-+ six.assertRegex(self, files[1], 'test_%s' % FILE_SUFFIX_REGEX)
-
- def test_first_character_dot(self):
- """
-@@ -489,8 +492,10 @@
- self.storage.save('dotted.path/.test', ContentFile("1"))
- self.storage.save('dotted.path/.test', ContentFile("2"))
-
-- self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/.test')))
-- self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/.test_1')))
-+ files = sorted(os.listdir(os.path.join(self.storage_dir, 'dotted.path')))
-+ self.assertFalse(os.path.exists(os.path.join(self.storage_dir, 'dotted_.path')))
-+ self.assertEqual(files[0], '.test')
-+ six.assertRegex(self, files[1], '.test_%s' % FILE_SUFFIX_REGEX)
-
- class DimensionClosingBug(unittest.TestCase):
- """
-Index: python-django-1.6.1/tests/files/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/files/tests.py 2014-09-09 13:35:39.572751632 -0400
-+++ python-django-1.6.1/tests/files/tests.py 2014-09-09 13:35:39.568751632 -0400
-@@ -12,12 +12,15 @@
- from django.core.files.uploadedfile import SimpleUploadedFile
- from django.core.files.temp import NamedTemporaryFile
- from django.test import TestCase
--from django.utils import unittest
-+from django.utils import six, unittest
- from django.utils.six import StringIO
-
- from .models import Storage, temp_storage, temp_storage_location
-
-
-+FILE_SUFFIX_REGEX = '[A-Za-z0-9]{7}'
-+
-+
- class FileStorageTests(TestCase):
- def tearDown(self):
- shutil.rmtree(temp_storage_location)
-@@ -63,27 +66,28 @@
- # Save another file with the same name.
- obj2 = Storage()
- obj2.normal.save("django_test.txt", ContentFile("more content"))
-- self.assertEqual(obj2.normal.name, "tests/django_test_1.txt")
-+ obj2_name = obj2.normal.name
-+ six.assertRegex(self, obj2_name, "tests/django_test_%s.txt" % FILE_SUFFIX_REGEX)
- self.assertEqual(obj2.normal.size, 12)
-
- # Push the objects into the cache to make sure they pickle properly
- cache.set("obj1", obj1)
- cache.set("obj2", obj2)
-- self.assertEqual(cache.get("obj2").normal.name, "tests/django_test_1.txt")
-+ six.assertRegex(self, cache.get("obj2").normal.name, "tests/django_test_%s.txt" % FILE_SUFFIX_REGEX)
-
- # Deleting an object does not delete the file it uses.
- obj2.delete()
- obj2.normal.save("django_test.txt", ContentFile("more content"))
-- self.assertEqual(obj2.normal.name, "tests/django_test_2.txt")
-+ self.assertNotEqual(obj2_name, obj2.normal.name)
-+ six.assertRegex(self, obj2.normal.name, "tests/django_test_%s.txt" % FILE_SUFFIX_REGEX)
-
- # Multiple files with the same name get _N appended to them.
-- objs = [Storage() for i in range(3)]
-+ objs = [Storage() for i in range(2)]
- for o in objs:
- o.normal.save("multiple_files.txt", ContentFile("Same Content"))
-- self.assertEqual(
-- [o.normal.name for o in objs],
-- ["tests/multiple_files.txt", "tests/multiple_files_1.txt", "tests/multiple_files_2.txt"]
-- )
-+ names = [o.normal.name for o in objs]
-+ self.assertEqual(names[0], "tests/multiple_files.txt")
-+ six.assertRegex(self, names[1], "tests/multiple_files_%s.txt" % FILE_SUFFIX_REGEX)
- for o in objs:
- o.delete()
-
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0482.patch python-django-1.6.11/debian/patches/CVE-2014-0482.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0482.patch 2014-09-09 17:35:48.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0482.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,94 +0,0 @@
-From 0268b855f9eab3377f2821164ef3e66037789e09 Mon Sep 17 00:00:00 2001
-From: Preston Holmes
-Date: Mon, 11 Aug 2014 12:04:53 -0400
-Subject: [PATCH] [1.6.x] Fixed #23066 -- Modified RemoteUserMiddleware to
- logout on REMOTE_USE change.
-
-This is a security fix. Disclosure following shortly.
----
- django/contrib/auth/middleware.py | 28 +++++++++++++++++++--------
- django/contrib/auth/tests/test_remote_user.py | 18 +++++++++++++++++
- docs/releases/1.4.14.txt | 9 +++++++++
- docs/releases/1.5.9.txt | 9 +++++++++
- docs/releases/1.6.6.txt | 9 +++++++++
- 5 files changed, 65 insertions(+), 8 deletions(-)
-
-diff --git a/django/contrib/auth/middleware.py b/django/contrib/auth/middleware.py
-index f38efdd..023e082 100644
---- a/django/contrib/auth/middleware.py
-+++ b/django/contrib/auth/middleware.py
-@@ -53,14 +53,7 @@ def process_request(self, request):
- # authenticated remote-user, or return (leaving request.user set to
- # AnonymousUser by the AuthenticationMiddleware).
- if request.user.is_authenticated():
-- try:
-- stored_backend = load_backend(request.session.get(
-- auth.BACKEND_SESSION_KEY, ''))
-- if isinstance(stored_backend, RemoteUserBackend):
-- auth.logout(request)
-- except ImproperlyConfigured as e:
-- # backend failed to load
-- auth.logout(request)
-+ self._remove_invalid_user(request)
- return
- # If the user is already authenticated and that user is the user we are
- # getting passed in the headers, then the correct user is already
-@@ -68,6 +61,11 @@ def process_request(self, request):
- if request.user.is_authenticated():
- if request.user.get_username() == self.clean_username(username, request):
- return
-+ else:
-+ # An authenticated user is associated with the request, but
-+ # it does not match the authorized user in the header.
-+ self._remove_invalid_user(request)
-+
- # We are seeing this user for the first time in this session, attempt
- # to authenticate the user.
- user = auth.authenticate(remote_user=username)
-@@ -89,3 +87,17 @@ def clean_username(self, username, request):
- except AttributeError: # Backend has no clean_username method.
- pass
- return username
-+
-+ def _remove_invalid_user(self, request):
-+ """
-+ Removes the current authenticated user in the request which is invalid
-+ but only if the user is authenticated via the RemoteUserBackend.
-+ """
-+ try:
-+ stored_backend = load_backend(request.session.get(auth.BACKEND_SESSION_KEY, ''))
-+ except ImproperlyConfigured:
-+ # backend failed to load
-+ auth.logout(request)
-+ else:
-+ if isinstance(stored_backend, RemoteUserBackend):
-+ auth.logout(request)
-diff --git a/django/contrib/auth/tests/test_remote_user.py b/django/contrib/auth/tests/test_remote_user.py
-index 5c5024e..642a6e9 100644
---- a/django/contrib/auth/tests/test_remote_user.py
-+++ b/django/contrib/auth/tests/test_remote_user.py
-@@ -118,6 +118,24 @@ def test_header_disappears(self):
- response = self.client.get('/remote_user/')
- self.assertEqual(response.context['user'].username, 'modeluser')
-
-+ def test_user_switch_forces_new_login(self):
-+ """
-+ Tests that if the username in the header changes between requests
-+ that the original user is logged out
-+ """
-+ User.objects.create(username='knownuser')
-+ # Known user authenticates
-+ response = self.client.get('/remote_user/',
-+ **{'REMOTE_USER': self.known_user})
-+ self.assertEqual(response.context['user'].username, 'knownuser')
-+ # During the session, the REMOTE_USER changes to a different user.
-+ response = self.client.get('/remote_user/',
-+ **{'REMOTE_USER': "newnewuser"})
-+ # Ensure that the current user is not the prior remote_user
-+ # In backends that create a new user, username is "newnewuser"
-+ # In backends that do not create new users, it is '' (anonymous user)
-+ self.assertNotEqual(response.context['user'].username, 'knownuser')
-+
- def tearDown(self):
- """Restores settings to avoid breaking other tests."""
- settings.MIDDLEWARE_CLASSES = self.curr_middleware
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0483-bug23329.patch python-django-1.6.11/debian/patches/CVE-2014-0483-bug23329.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0483-bug23329.patch 2014-09-09 17:37:03.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0483-bug23329.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,113 +0,0 @@
-From e3453b61c6269d7868ceb404abaea5ad2569778f Mon Sep 17 00:00:00 2001
-From: Simon Charette
-Date: Thu, 21 Aug 2014 11:55:23 -0400
-Subject: [PATCH] [1.6.x] Fixed #23329 -- Allowed inherited and m2m fields to
- be referenced in the admin.
-
-Thanks to Trac alias Markush2010 and ross for the detailed reports.
-
-Backport of 3cbb759 from master
----
- django/contrib/admin/options.py | 10 ++++++----
- docs/releases/1.4.15.txt | 13 +++++++++++++
- docs/releases/1.5.10.txt | 13 +++++++++++++
- docs/releases/1.6.7.txt | 13 +++++++++++++
- docs/releases/index.txt | 3 +++
- tests/admin_views/admin.py | 5 ++++-
- tests/admin_views/models.py | 17 +++++++++++++++++
- tests/admin_views/tests.py | 9 +++++++++
- 8 files changed, 78 insertions(+), 5 deletions(-)
- create mode 100644 docs/releases/1.4.15.txt
- create mode 100644 docs/releases/1.5.10.txt
- create mode 100644 docs/releases/1.6.7.txt
-
-Index: python-django-1.6.1/django/contrib/admin/options.py
-===================================================================
---- python-django-1.6.1.orig/django/contrib/admin/options.py 2014-09-09 13:37:00.428753797 -0400
-+++ python-django-1.6.1/django/contrib/admin/options.py 2014-09-09 13:37:00.420753797 -0400
-@@ -336,11 +336,13 @@
- return False
-
- # Make sure at least one of the models registered for this site
-- # references this field.
-+ # references this field through a FK or a M2M relationship.
- registered_models = self.admin_site._registry
-- for related_object in opts.get_all_related_objects():
-- if (related_object.model in registered_models and
-- field in related_object.field.foreign_related_fields):
-+ for related_object in (opts.get_all_related_objects() +
-+ opts.get_all_related_many_to_many_objects()):
-+ related_model = related_object.model
-+ if (any(issubclass(model, related_model) for model in registered_models) and
-+ related_object.field.rel.get_related_field() == field):
- return True
-
- return False
-Index: python-django-1.6.1/tests/admin_views/admin.py
-===================================================================
---- python-django-1.6.1.orig/tests/admin_views/admin.py 2014-09-09 13:37:00.428753797 -0400
-+++ python-django-1.6.1/tests/admin_views/admin.py 2014-09-09 13:37:00.420753797 -0400
-@@ -30,7 +30,7 @@
- AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
- AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated,
- RelatedPrepopulated, UndeletableObject, UserMessenger, Simple, Choice,
-- ShortMessage, Telegram)
-+ ShortMessage, Telegram, ReferencedByParent, ChildOfReferer, M2MReference)
-
-
- def callable_year(dt_value):
-@@ -745,6 +745,9 @@
- site.register(MainPrepopulated, MainPrepopulatedAdmin)
- site.register(UnorderedObject, UnorderedObjectAdmin)
- site.register(UndeletableObject, UndeletableObjectAdmin)
-+site.register(ReferencedByParent)
-+site.register(ChildOfReferer)
-+site.register(M2MReference)
-
- # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
- # That way we cover all four cases:
-Index: python-django-1.6.1/tests/admin_views/models.py
-===================================================================
---- python-django-1.6.1.orig/tests/admin_views/models.py 2014-09-09 13:37:00.428753797 -0400
-+++ python-django-1.6.1/tests/admin_views/models.py 2014-09-09 13:37:00.420753797 -0400
-@@ -687,3 +687,20 @@
- class Choice(models.Model):
- choice = models.IntegerField(blank=True, null=True,
- choices=((1, 'Yes'), (0, 'No'), (None, 'No opinion')))
-+
-+# Models for #23329
-+class ReferencedByParent(models.Model):
-+ pass
-+
-+
-+class ParentWithFK(models.Model):
-+ fk = models.ForeignKey(ReferencedByParent)
-+
-+
-+class ChildOfReferer(ParentWithFK):
-+ pass
-+
-+
-+class M2MReference(models.Model):
-+ ref = models.ManyToManyField('self')
-+
-Index: python-django-1.6.1/tests/admin_views/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/admin_views/tests.py 2014-09-09 13:37:00.428753797 -0400
-+++ python-django-1.6.1/tests/admin_views/tests.py 2014-09-09 13:37:00.424753797 -0400
-@@ -594,6 +594,15 @@
- response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'id'})
- self.assertEqual(response.status_code, 200)
-
-+ # Specifying a field referenced by another model though a m2m should be allowed.
-+ response = self.client.get("/test_admin/admin/admin_views/m2mreference/", {TO_FIELD_VAR: 'id'})
-+ self.assertEqual(response.status_code, 200)
-+
-+ # Specifying a field that is not refered by any other model directly registered
-+ # to this admin site but registered through inheritance should be allowed.
-+ response = self.client.get("/test_admin/admin/admin_views/referencedbyparent/", {TO_FIELD_VAR: 'id'})
-+ self.assertEqual(response.status_code, 200)
-+
- def test_allowed_filtering_15103(self):
- """
- Regressions test for ticket 15103 - filtering on fields defined in a
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0483-bug23431.patch python-django-1.6.11/debian/patches/CVE-2014-0483-bug23431.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0483-bug23431.patch 2014-09-09 17:37:16.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0483-bug23431.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,138 +0,0 @@
-From a7af6ad96a35634383c2d73fa049127e85a886a6 Mon Sep 17 00:00:00 2001
-From: Simon Charette
-Date: Thu, 4 Sep 2014 17:04:53 -0400
-Subject: [PATCH] [1.6.x] Fixed #23431 -- Allowed inline and hidden references
- to admin fields.
-
-This fixes a regression introduced by the 53ff096982 security fix.
-
-Thanks to @a1tus for the report and Tim for the review.
-
-refs #23329.
-
-Backport of 342ccbd from master
----
- django/contrib/admin/options.py | 13 +++++++++++--
- docs/releases/1.4.16.txt | 13 +++++++++++++
- docs/releases/1.5.11.txt | 13 +++++++++++++
- docs/releases/1.6.8.txt | 12 ++++++++++++
- docs/releases/index.txt | 3 +++
- tests/admin_views/admin.py | 13 ++++++++++++-
- tests/admin_views/models.py | 12 ++++++++++++
- tests/admin_views/tests.py | 7 ++++++-
- 8 files changed, 82 insertions(+), 4 deletions(-)
- create mode 100644 docs/releases/1.4.16.txt
- create mode 100644 docs/releases/1.5.11.txt
- create mode 100644 docs/releases/1.6.8.txt
-
-Index: python-django-1.6.1/django/contrib/admin/options.py
-===================================================================
---- python-django-1.6.1.orig/django/contrib/admin/options.py 2014-09-09 13:37:13.704754153 -0400
-+++ python-django-1.6.1/django/contrib/admin/options.py 2014-09-09 13:37:13.696754152 -0400
-@@ -328,6 +328,10 @@
- return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy
-
- def to_field_allowed(self, request, to_field):
-+ """
-+ Returns True if the model associated with this admin should be
-+ allowed to be referenced by the specified field.
-+ """
- opts = self.model._meta
-
- try:
-@@ -337,8 +341,13 @@
-
- # Make sure at least one of the models registered for this site
- # references this field through a FK or a M2M relationship.
-- registered_models = self.admin_site._registry
-- for related_object in (opts.get_all_related_objects() +
-+ registered_models = set()
-+ for model, admin in self.admin_site._registry.items():
-+ registered_models.add(model)
-+ for inline in admin.inlines:
-+ registered_models.add(inline.model)
-+
-+ for related_object in (opts.get_all_related_objects(include_hidden=True) +
- opts.get_all_related_many_to_many_objects()):
- related_model = related_object.model
- if (any(issubclass(model, related_model) for model in registered_models) and
-Index: python-django-1.6.1/tests/admin_views/admin.py
-===================================================================
---- python-django-1.6.1.orig/tests/admin_views/admin.py 2014-09-09 13:37:13.704754153 -0400
-+++ python-django-1.6.1/tests/admin_views/admin.py 2014-09-09 13:37:13.696754152 -0400
-@@ -30,7 +30,8 @@
- AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
- AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated,
- RelatedPrepopulated, UndeletableObject, UserMessenger, Simple, Choice,
-- ShortMessage, Telegram, ReferencedByParent, ChildOfReferer, M2MReference)
-+ ShortMessage, Telegram, ReferencedByParent, ChildOfReferer, M2MReference,
-+ ReferencedByInline, InlineReference, InlineReferer)
-
-
- def callable_year(dt_value):
-@@ -696,6 +697,14 @@
- fields = ['choice']
-
-
-+class InlineReferenceInline(admin.TabularInline):
-+ model = InlineReference
-+
-+
-+class InlineRefererAdmin(admin.ModelAdmin):
-+ inlines = [InlineReferenceInline]
-+
-+
- site = admin.AdminSite(name="admin")
- site.register(Article, ArticleAdmin)
- site.register(CustomArticle, CustomArticleAdmin)
-@@ -748,6 +757,8 @@
- site.register(ReferencedByParent)
- site.register(ChildOfReferer)
- site.register(M2MReference)
-+site.register(ReferencedByInline)
-+site.register(InlineReferer, InlineRefererAdmin)
-
- # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
- # That way we cover all four cases:
-Index: python-django-1.6.1/tests/admin_views/models.py
-===================================================================
---- python-django-1.6.1.orig/tests/admin_views/models.py 2014-09-09 13:37:13.704754153 -0400
-+++ python-django-1.6.1/tests/admin_views/models.py 2014-09-09 13:37:13.696754152 -0400
-@@ -704,3 +704,15 @@
- class M2MReference(models.Model):
- ref = models.ManyToManyField('self')
-
-+# Models for #23431
-+class ReferencedByInline(models.Model):
-+ pass
-+
-+
-+class InlineReference(models.Model):
-+ fk = models.ForeignKey(ReferencedByInline, related_name='hidden+')
-+
-+
-+class InlineReferer(models.Model):
-+ refs = models.ManyToManyField(InlineReference)
-+
-Index: python-django-1.6.1/tests/admin_views/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/admin_views/tests.py 2014-09-09 13:37:13.704754153 -0400
-+++ python-django-1.6.1/tests/admin_views/tests.py 2014-09-09 13:37:13.696754152 -0400
-@@ -598,11 +598,16 @@
- response = self.client.get("/test_admin/admin/admin_views/m2mreference/", {TO_FIELD_VAR: 'id'})
- self.assertEqual(response.status_code, 200)
-
-- # Specifying a field that is not refered by any other model directly registered
-+ # #23329 - Specifying a field that is not refered by any other model directly registered
- # to this admin site but registered through inheritance should be allowed.
- response = self.client.get("/test_admin/admin/admin_views/referencedbyparent/", {TO_FIELD_VAR: 'id'})
- self.assertEqual(response.status_code, 200)
-
-+ # #23431 - Specifying a field that is only refered to by a inline of a registered
-+ # model should be allowed.
-+ response = self.client.get("/test_admin/admin/admin_views/referencedbyinline/", {TO_FIELD_VAR: 'id'})
-+ self.assertEqual(response.status_code, 200)
-+
- def test_allowed_filtering_15103(self):
- """
- Regressions test for ticket 15103 - filtering on fields defined in a
diff -Nru python-django-1.6.1/debian/patches/CVE-2014-0483.patch python-django-1.6.11/debian/patches/CVE-2014-0483.patch
--- python-django-1.6.1/debian/patches/CVE-2014-0483.patch 2014-09-09 17:35:59.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2014-0483.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,146 +0,0 @@
-From f7c494f2506250b8cb5923714360a3642ed63e0f Mon Sep 17 00:00:00 2001
-From: Simon Charette
-Date: Thu, 7 Aug 2014 00:18:10 -0400
-Subject: [PATCH] [1.6.x] Prevented data leakage in contrib.admin via query
- string manipulation.
-
-This is a security fix. Disclosure following shortly.
----
- django/contrib/admin/exceptions.py | 5 +++++
- django/contrib/admin/options.py | 18 ++++++++++++++++++
- django/contrib/admin/views/main.py | 7 +++++--
- docs/ref/exceptions.txt | 1 +
- docs/releases/1.4.14.txt | 15 +++++++++++++++
- docs/releases/1.5.9.txt | 15 +++++++++++++++
- docs/releases/1.6.6.txt | 15 +++++++++++++++
- tests/admin_views/tests.py | 23 ++++++++++++++++++++---
- 8 files changed, 94 insertions(+), 5 deletions(-)
-
-Index: python-django-1.6.1/django/contrib/admin/exceptions.py
-===================================================================
---- python-django-1.6.1.orig/django/contrib/admin/exceptions.py 2014-09-09 13:35:56.416752083 -0400
-+++ python-django-1.6.1/django/contrib/admin/exceptions.py 2014-09-09 13:35:56.408752083 -0400
-@@ -4,3 +4,8 @@
- class DisallowedModelAdminLookup(SuspiciousOperation):
- """Invalid filter was passed to admin view via URL querystring"""
- pass
-+
-+
-+class DisallowedModelAdminToField(SuspiciousOperation):
-+ """Invalid to_field was passed to admin view via URL query string"""
-+ pass
-Index: python-django-1.6.1/django/contrib/admin/options.py
-===================================================================
---- python-django-1.6.1.orig/django/contrib/admin/options.py 2014-09-09 13:35:56.416752083 -0400
-+++ python-django-1.6.1/django/contrib/admin/options.py 2014-09-09 13:35:56.408752083 -0400
-@@ -327,6 +327,24 @@
- clean_lookup = LOOKUP_SEP.join(parts)
- return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy
-
-+ def to_field_allowed(self, request, to_field):
-+ opts = self.model._meta
-+
-+ try:
-+ field = opts.get_field(to_field)
-+ except FieldDoesNotExist:
-+ return False
-+
-+ # Make sure at least one of the models registered for this site
-+ # references this field.
-+ registered_models = self.admin_site._registry
-+ for related_object in opts.get_all_related_objects():
-+ if (related_object.model in registered_models and
-+ field in related_object.field.foreign_related_fields):
-+ return True
-+
-+ return False
-+
- def has_add_permission(self, request):
- """
- Returns True if the given request has permission to add an object.
-Index: python-django-1.6.1/django/contrib/admin/views/main.py
-===================================================================
---- python-django-1.6.1.orig/django/contrib/admin/views/main.py 2014-09-09 13:35:56.416752083 -0400
-+++ python-django-1.6.1/django/contrib/admin/views/main.py 2014-09-09 13:35:56.408752083 -0400
-@@ -14,7 +14,7 @@
- from django.utils.http import urlencode
-
- from django.contrib.admin import FieldListFilter
--from django.contrib.admin.exceptions import DisallowedModelAdminLookup
-+from django.contrib.admin.exceptions import DisallowedModelAdminLookup, DisallowedModelAdminToField
- from django.contrib.admin.options import IncorrectLookupParameters, IS_POPUP_VAR
- from django.contrib.admin.util import (quote, get_fields_from_path,
- lookup_needs_distinct, prepare_lookup_value)
-@@ -90,7 +90,10 @@
- self.page_num = 0
- self.show_all = ALL_VAR in request.GET
- self.is_popup = _is_changelist_popup(request)
-- self.to_field = request.GET.get(TO_FIELD_VAR)
-+ to_field = request.GET.get(TO_FIELD_VAR)
-+ if to_field and not model_admin.to_field_allowed(request, to_field):
-+ raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)
-+ self.to_field = to_field
- self.params = dict(request.GET.items())
- if PAGE_VAR in self.params:
- del self.params[PAGE_VAR]
-Index: python-django-1.6.1/docs/ref/exceptions.txt
-===================================================================
---- python-django-1.6.1.orig/docs/ref/exceptions.txt 2014-09-09 13:35:56.416752083 -0400
-+++ python-django-1.6.1/docs/ref/exceptions.txt 2014-09-09 13:35:56.412752083 -0400
-@@ -56,6 +56,7 @@
-
- * DisallowedHost
- * DisallowedModelAdminLookup
-+ * DisallowedModelAdminToField
- * DisallowedRedirect
- * InvalidSessionKey
- * SuspiciousFileOperation
-Index: python-django-1.6.1/tests/admin_views/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/admin_views/tests.py 2014-09-09 13:35:56.416752083 -0400
-+++ python-django-1.6.1/tests/admin_views/tests.py 2014-09-09 13:35:56.412752083 -0400
-@@ -14,6 +14,7 @@
- from django.contrib import admin
- from django.contrib.auth import get_permission_codename
- from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
-+from django.contrib.admin.views.main import TO_FIELD_VAR
- from django.contrib.admin.models import LogEntry, DELETION
- from django.contrib.admin.sites import LOGIN_FORM_KEY
- from django.contrib.admin.util import quote
-@@ -576,6 +577,23 @@
- response = self.client.get("/test_admin/admin/admin_views/workhour/?employee__person_ptr__exact=%d" % e1.pk)
- self.assertEqual(response.status_code, 200)
-
-+ def test_disallowed_to_field(self):
-+ with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls:
-+ response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'missing_field'})
-+ self.assertEqual(response.status_code, 400)
-+ self.assertEqual(len(calls), 1)
-+
-+ # Specifying a field that is not refered by any other model registered
-+ # to this admin site should raise an exception.
-+ with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls:
-+ response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'name'})
-+ self.assertEqual(response.status_code, 400)
-+ self.assertEqual(len(calls), 1)
-+
-+ # Specifying a field referenced by another model should be allowed.
-+ response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'id'})
-+ self.assertEqual(response.status_code, 200)
-+
- def test_allowed_filtering_15103(self):
- """
- Regressions test for ticket 15103 - filtering on fields defined in a
-@@ -2203,10 +2221,9 @@
- """Ensure that the to_field GET parameter is preserved when a search
- is performed. Refs #10918.
- """
-- from django.contrib.admin.views.main import TO_FIELD_VAR
-- response = self.client.get('/test_admin/admin/auth/user/?q=joe&%s=username' % TO_FIELD_VAR)
-+ response = self.client.get('/test_admin/admin/auth/user/?q=joe&%s=id' % TO_FIELD_VAR)
- self.assertContains(response, "\n1 user\n")
-- self.assertContains(response, '', html=True)
-+ self.assertContains(response, '' % TO_FIELD_VAR, html=True)
-
- def test_exact_matches(self):
- response = self.client.get('/test_admin/admin/admin_views/recommendation/?q=bar')
diff -Nru python-django-1.6.1/debian/patches/CVE-2015-0219.patch python-django-1.6.11/debian/patches/CVE-2015-0219.patch
--- python-django-1.6.1/debian/patches/CVE-2015-0219.patch 2015-01-13 12:47:23.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2015-0219.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,124 +0,0 @@
-Description: fix WSGI header spoofing via underscore/dash conflation
-Author: Carl Meyer
-
-Index: python-django-1.6.1/django/core/servers/basehttp.py
-===================================================================
---- python-django-1.6.1.orig/django/core/servers/basehttp.py 2015-01-13 07:47:20.530014471 -0500
-+++ python-django-1.6.1/django/core/servers/basehttp.py 2015-01-13 07:47:20.526014442 -0500
-@@ -157,6 +157,17 @@
-
- sys.stderr.write(msg)
-
-+ def get_environ(self):
-+ # Strip all headers with underscores in the name before constructing
-+ # the WSGI environ. This prevents header-spoofing based on ambiguity
-+ # between underscores and dashes both normalized to underscores in WSGI
-+ # env vars. Nginx and Apache 2.4+ both do this as well.
-+ for k, v in self.headers.items():
-+ if '_' in k:
-+ del self.headers[k]
-+
-+ return super(WSGIRequestHandler, self).get_environ()
-+
-
- def run(addr, port, wsgi_handler, ipv6=False, threading=False):
- server_address = (addr, port)
-Index: python-django-1.6.1/docs/howto/auth-remote-user.txt
-===================================================================
---- python-django-1.6.1.orig/docs/howto/auth-remote-user.txt 2015-01-13 07:47:20.530014471 -0500
-+++ python-django-1.6.1/docs/howto/auth-remote-user.txt 2015-01-13 07:47:20.530014471 -0500
-@@ -72,6 +72,22 @@
-
- .. class:: django.contrib.auth.backends.RemoteUserBackend
-
-+.. warning::
-+
-+ Be very careful if using a ``RemoteUserMiddleware`` subclass with a custom
-+ HTTP header. You must be sure that your front-end web server always sets or
-+ strips that header based on the appropriate authentication checks, never
-+ permitting an end-user to submit a fake (or "spoofed") header value. Since
-+ the HTTP headers ``X-Auth-User`` and ``X-Auth_User`` (for example) both
-+ normalize to the ``HTTP_X_AUTH_USER`` key in ``request.META``, you must
-+ also check that your web server doesn't allow a spoofed header using
-+ underscores in place of dashes.
-+
-+ This warning doesn't apply to ``RemoteUserMiddleware`` in its default
-+ configuration with ``header = 'REMOTE_USER'``, since a key that doesn't
-+ start with ``HTTP_`` in ``request.META`` can only be set by your WSGI
-+ server, not directly from an HTTP request header.
-+
- If you need more control, you can create your own authentication backend
- that inherits from ``RemoteUserBackend`` and overrides certain parts:
-
-Index: python-django-1.6.1/tests/servers/test_basehttp.py
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ python-django-1.6.1/tests/servers/test_basehttp.py 2015-01-13 07:47:20.530014471 -0500
-@@ -0,0 +1,67 @@
-+import sys
-+
-+from django.core.servers.basehttp import WSGIRequestHandler
-+from django.test import TestCase
-+from django.utils.six import BytesIO, StringIO
-+
-+
-+class Stub(object):
-+ def __init__(self, **kwargs):
-+ self.__dict__.update(kwargs)
-+
-+
-+class WSGIRequestHandlerTestCase(TestCase):
-+
-+ def test_strips_underscore_headers(self):
-+ """WSGIRequestHandler ignores headers containing underscores.
-+
-+ This follows the lead of nginx and Apache 2.4, and is to avoid
-+ ambiguity between dashes and underscores in mapping to WSGI environ,
-+ which can have security implications.
-+ """
-+ def test_app(environ, start_response):
-+ """A WSGI app that just reflects its HTTP environ."""
-+ start_response('200 OK', [])
-+ http_environ_items = sorted(
-+ '%s:%s' % (k, v) for k, v in environ.items()
-+ if k.startswith('HTTP_')
-+ )
-+ yield (','.join(http_environ_items)).encode('utf-8')
-+
-+ rfile = BytesIO()
-+ rfile.write(b"GET / HTTP/1.0\r\n")
-+ rfile.write(b"Some-Header: good\r\n")
-+ rfile.write(b"Some_Header: bad\r\n")
-+ rfile.write(b"Other_Header: bad\r\n")
-+ rfile.seek(0)
-+
-+ # WSGIRequestHandler closes the output file; we need to make this a
-+ # no-op so we can still read its contents.
-+ class UnclosableBytesIO(BytesIO):
-+ def close(self):
-+ pass
-+
-+ wfile = UnclosableBytesIO()
-+
-+ def makefile(mode, *a, **kw):
-+ if mode == 'rb':
-+ return rfile
-+ elif mode == 'wb':
-+ return wfile
-+
-+ request = Stub(makefile=makefile)
-+ server = Stub(base_environ={}, get_app=lambda: test_app)
-+
-+ # We don't need to check stderr, but we don't want it in test output
-+ old_stderr = sys.stderr
-+ sys.stderr = StringIO()
-+ try:
-+ # instantiating a handler runs the request as side effect
-+ WSGIRequestHandler(request, '192.168.0.2', server)
-+ finally:
-+ sys.stderr = old_stderr
-+
-+ wfile.seek(0)
-+ body = list(wfile.readlines())[-1]
-+
-+ self.assertEqual(body, b'HTTP_SOME_HEADER:good')
diff -Nru python-django-1.6.1/debian/patches/CVE-2015-0220.patch python-django-1.6.11/debian/patches/CVE-2015-0220.patch
--- python-django-1.6.1/debian/patches/CVE-2015-0220.patch 2015-01-13 12:47:29.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2015-0220.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,29 +0,0 @@
-Description: fix mitigated possible XSS attack via user-supplied redirect URLs
-Author: Tim Graham
-
-Index: python-django-1.6.6/django/utils/http.py
-===================================================================
---- python-django-1.6.6.orig/django/utils/http.py 2014-08-20 16:13:48.000000000 -0400
-+++ python-django-1.6.6/django/utils/http.py 2015-01-13 07:30:50.854918976 -0500
-@@ -256,6 +256,7 @@
- """
- if not url:
- return False
-+ url = url.strip()
- # Chrome treats \ completely as /
- url = url.replace('\\', '/')
- # Chrome considers any URL with more than two slashes to be absolute, but
-Index: python-django-1.6.6/tests/utils_tests/test_http.py
-===================================================================
---- python-django-1.6.6.orig/tests/utils_tests/test_http.py 2014-08-20 16:13:48.000000000 -0400
-+++ python-django-1.6.6/tests/utils_tests/test_http.py 2015-01-13 07:30:50.854918976 -0500
-@@ -109,7 +109,8 @@
- 'http:/\//example.com',
- 'http:\/example.com',
- 'http:/\example.com',
-- 'javascript:alert("XSS")'):
-+ 'javascript:alert("XSS")',
-+ '\njavascript:alert(x)'):
- self.assertFalse(http.is_safe_url(bad_url, host='testserver'), "%s should be blocked" % bad_url)
- for good_url in ('/view/?param=http://example.com',
- '/view/?param=https://example.com',
diff -Nru python-django-1.6.1/debian/patches/CVE-2015-0221.patch python-django-1.6.11/debian/patches/CVE-2015-0221.patch
--- python-django-1.6.1/debian/patches/CVE-2015-0221.patch 2015-01-13 12:47:34.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2015-0221.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,61 +0,0 @@
-Description: fix denial-of-service attack against django.views.static.serve
-Author: Tim Graham
-
-Index: python-django-1.6.6/django/views/static.py
-===================================================================
---- python-django-1.6.6.orig/django/views/static.py 2014-08-20 16:13:48.000000000 -0400
-+++ python-django-1.6.6/django/views/static.py 2015-01-13 07:31:42.007288607 -0500
-@@ -17,6 +17,9 @@
- from django.utils.six.moves.urllib.parse import unquote
- from django.utils.translation import ugettext as _, ugettext_noop
-
-+STREAM_CHUNK_SIZE = 4096
-+
-+
- def serve(request, path, document_root=None, show_indexes=False):
- """
- Serve static files below a given point in the directory structure.
-@@ -60,7 +63,8 @@
- return HttpResponseNotModified()
- content_type, encoding = mimetypes.guess_type(fullpath)
- content_type = content_type or 'application/octet-stream'
-- response = CompatibleStreamingHttpResponse(open(fullpath, 'rb'),
-+ f = open(fullpath, 'rb')
-+ response = CompatibleStreamingHttpResponse(iter(lambda: f.read(STREAM_CHUNK_SIZE), b''),
- content_type=content_type)
- response["Last-Modified"] = http_date(statobj.st_mtime)
- if stat.S_ISREG(statobj.st_mode):
-Index: python-django-1.6.6/tests/view_tests/media/long-line.txt
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ python-django-1.6.6/tests/view_tests/media/long-line.txt 2015-01-13 07:31:42.007288607 -0500
-@@ -0,0 +1 @@
-+lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua hic tempora est veritatis culpa fugiat doloribus fugit in sed harum veniam porro eveniet maxime labore assumenda non illum possimus aut vero laudantium cum magni numquam dolorem explicabo quidem quasi nesciunt ipsum deleniti facilis neque similique nisi ad magnam accusamus quae provident dolor ab atque modi laboriosam fuga suscipit ea beatae ipsam consequatur saepe dolore nulla error quo iusto expedita nemo commodi aspernatur aliquam enim reiciendis rerum necessitatibus recusandae sint amet placeat temporibus autem iste deserunt esse dolores reprehenderit doloremque pariatur velit maiores repellat dignissimos asperiores aperiam alias a corporis id praesentium voluptatibus soluta voluptatem sit molestiae quas odio facere nostrum laborum incidunt eaque nihil ullam rem mollitia at cumque iure tenetur tempore totam repudiandae quisquam quod architecto officia vitae consectetur cupiditate molestias delectus voluptates earum et impedit quibusdam odit sequi perferendis eius perspiciatis eos quam quaerat officiis sunt ratione consequuntur quia quis obcaecati repellendus exercitationem vel minima libero blanditiis eligendi minus dicta voluptas excepturi nam eum inventore voluptatum ducimus sapiente dolorum itaque ipsa qui omnis debitis voluptate quos aliquid accusantium ex illo corrupti ut adipisci natus animi distinctio optio nobis unde similique excepturi vero culpa molestias fugit dolorum non amet iure inventore nihil suscipit explicabo veritatis officiis distinctio nesciunt saepe incidunt reprehenderit porro vitae cumque alias ut deleniti expedita ratione odio magnam eligendi a nostrum laborum minus esse sit libero quaerat qui id illo voluptates soluta neque odit dolore consectetur ducimus nulla est nisi impedit quia sapiente ullam temporibus ipsam repudiandae delectus fugiat blanditiis maxime voluptatibus aspernatur ea ipsum quisquam sunt eius ipsa accusantium enim corporis earum sed sequi dicta accusamus dignissimos illum pariatur quos aut reiciendis obcaecati perspiciatis consequuntur nam modi praesentium cum repellat possimus iste atque quidem architecto recusandae harum eaque sint quae optio voluptate quod quasi beatae magni necessitatibus facilis aperiam repellendus nemo aliquam et quibusdam debitis itaque cupiditate laboriosam unde tempora commodi laudantium in placeat ad vel maiores aliquid hic tempore provident quas officia adipisci rem corrupti iusto natus eum rerum at ex quam eveniet totam dolor assumenda error eos doloribus labore fuga facere deserunt ab dolores consequatur veniam animi exercitationem asperiores mollitia minima numquam voluptatem voluptatum nobis molestiae voluptas omnis velit quis quo tenetur perferendis autem dolorem doloremque sequi vitae laudantium magnam quae adipisci expedita doloribus minus perferendis vero animi at quos iure facere nihil veritatis consectetur similique porro tenetur nobis fugiat quo ducimus qui soluta maxime placeat error sunt ullam quaerat provident eos minima ab harum ratione inventore unde sint dolorum deserunt veniam laborum quasi suscipit facilis eveniet voluptatibus est ipsum sapiente omnis vel repellat perspiciatis illo voluptate aliquid magni alias modi odit ea a voluptatem reiciendis recusandae mollitia eius distinctio amet atque voluptates obcaecati deleniti eligendi commodi debitis dolore laboriosam nam illum pariatur earum exercitationem velit in quas explicabo fugit asperiores itaque quam sit dolorem beatae quod cumque necessitatibus tempora dolores hic aperiam ex tempore ut neque maiores ad dicta voluptatum eum officia assumenda reprehenderit nisi cum molestiae et iusto quidem consequuntur repellendus saepe corrupti numquam culpa rerum incidunt dolor impedit iste sed non praesentium ipsam consequatur eaque possimus quia quibusdam excepturi aspernatur voluptas quisquam autem molestias aliquam corporis delectus nostrum labore nesciunt blanditiis quis enim accusamus nulla architecto fuga natus ipsa repudiandae cupiditate temporibus aut libero optio id officiis esse dignissimos odio totam doloremque accusantium nemo rem repudiandae aliquam accusamus autem minima reiciendis debitis quis ut ducimus quas dolore ratione neque velit repellat natus est error ea nam consequuntur rerum excepturi aspernatur quaerat cumque voluptatibus rem quasi eos unde architecto animi sunt veritatis delectus nulla at iusto repellendus dolorum obcaecati commodi earum assumenda quisquam cum officiis modi ab tempora harum vitae voluptatem explicabo alias maxime nostrum iure consectetur incidunt laudantium distinctio deleniti iste facere fugit libero illo nobis expedita perferendis labore similique beatae sint dicta dignissimos sapiente dolor soluta perspiciatis aut ad illum facilis totam necessitatibus eveniet temporibus reprehenderit quidem fugiat magni dolorem doloribus quibusdam eligendi fuga quae recusandae eum amet dolores asperiores voluptas inventore officia sit vel id vero nihil optio nisi magnam deserunt odit corrupti adipisci aliquid odio enim pariatur cupiditate suscipit voluptatum corporis porro mollitia eaque quia non quod consequatur ipsa nesciunt itaque exercitationem molestias molestiae atque in numquam quo ipsam nemo ex tempore ipsum saepe esse sed veniam a voluptates placeat accusantium quos laboriosam voluptate provident hic sequi quam doloremque eius impedit omnis possimus laborum tenetur praesentium et minus ullam blanditiis culpa qui aperiam maiores quidem numquam nulla
-Index: python-django-1.6.6/tests/view_tests/tests/test_static.py
-===================================================================
---- python-django-1.6.6.orig/tests/view_tests/tests/test_static.py 2014-08-20 16:13:48.000000000 -0400
-+++ python-django-1.6.6/tests/view_tests/tests/test_static.py 2015-01-13 07:31:42.007288607 -0500
-@@ -9,7 +9,7 @@
- from django.test import TestCase
- from django.test.utils import override_settings
- from django.utils.http import http_date
--from django.views.static import was_modified_since
-+from django.views.static import was_modified_since, STREAM_CHUNK_SIZE
-
- from .. import urls
- from ..urls import media_dir
-@@ -33,6 +33,14 @@
- self.assertEqual(len(response_content), int(response['Content-Length']))
- self.assertEqual(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None))
-
-+ def test_chunked(self):
-+ "The static view should stream files in chunks to avoid large memory usage"
-+ response = self.client.get('/views/%s/%s' % (self.prefix, 'long-line.txt'))
-+ first_chunk = next(response.streaming_content)
-+ self.assertEqual(len(first_chunk), STREAM_CHUNK_SIZE)
-+ second_chunk = next(response.streaming_content)
-+ self.assertEqual(len(second_chunk), 1451)
-+
- def test_unknown_mime_type(self):
- response = self.client.get('/views/%s/file.unknown' % self.prefix)
- self.assertEqual('application/octet-stream', response['Content-Type'])
diff -Nru python-django-1.6.1/debian/patches/CVE-2015-0222.patch python-django-1.6.11/debian/patches/CVE-2015-0222.patch
--- python-django-1.6.1/debian/patches/CVE-2015-0222.patch 2015-01-13 12:47:43.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2015-0222.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,89 +0,0 @@
-Description: fix database denial-of-service with ModelMultipleChoiceField
-Author: Tim Graham
-
-Index: python-django-1.6.1/django/forms/models.py
-===================================================================
---- python-django-1.6.1.orig/django/forms/models.py 2015-01-13 07:47:40.154160157 -0500
-+++ python-django-1.6.1/django/forms/models.py 2015-01-13 07:47:40.150160126 -0500
-@@ -1170,8 +1170,7 @@
- def to_python(self, value):
- if not value:
- return []
-- to_py = super(ModelMultipleChoiceField, self).to_python
-- return [to_py(val) for val in value]
-+ return list(self._check_values(value))
-
- def clean(self, value):
- if self.required and not value:
-@@ -1180,7 +1179,29 @@
- return self.queryset.none()
- if not isinstance(value, (list, tuple)):
- raise ValidationError(self.error_messages['list'], code='list')
-+ qs = self._check_values(value)
-+ # Since this overrides the inherited ModelChoiceField.clean
-+ # we run custom validators here
-+ self.run_validators(value)
-+ return qs
-+
-+ def _check_values(self, value):
-+ """
-+ Given a list of possible PK values, returns a QuerySet of the
-+ corresponding objects. Raises a ValidationError if a given value is
-+ invalid (not a valid PK, not in the queryset, etc.)
-+ """
- key = self.to_field_name or 'pk'
-+ # deduplicate given values to avoid creating many querysets or
-+ # requiring the database backend deduplicate efficiently.
-+ try:
-+ value = frozenset(value)
-+ except TypeError:
-+ # list of lists isn't hashable, for example
-+ raise ValidationError(
-+ self.error_messages['list'],
-+ code='list',
-+ )
- for pk in value:
- try:
- self.queryset.filter(**{key: pk})
-@@ -1199,9 +1220,6 @@
- code='invalid_choice',
- params={'value': val},
- )
-- # Since this overrides the inherited ModelChoiceField.clean
-- # we run custom validators here
-- self.run_validators(value)
- return qs
-
- def prepare_value(self, value):
-Index: python-django-1.6.1/tests/model_forms/tests.py
-===================================================================
---- python-django-1.6.1.orig/tests/model_forms/tests.py 2015-01-13 07:47:40.154160157 -0500
-+++ python-django-1.6.1/tests/model_forms/tests.py 2015-01-13 07:47:40.150160126 -0500
-@@ -1381,6 +1381,27 @@
-
-
''' % (w_woodward.pk, w_bernstein.pk, bw.pk, w_royko.pk))
-
-+ def test_show_hidden_initial_changed_queries_efficiently(self):
-+ class WriterForm(forms.Form):
-+ persons = forms.ModelMultipleChoiceField(
-+ show_hidden_initial=True, queryset=Writer.objects.all())
-+
-+ writers = (Writer.objects.create(name=str(x)) for x in range(0, 50))
-+ writer_pks = tuple(x.pk for x in writers)
-+ form = WriterForm(data={'initial-persons': writer_pks})
-+ with self.assertNumQueries(1):
-+ self.assertTrue(form.has_changed())
-+
-+ def test_clean_does_deduplicate_values(self):
-+ class WriterForm(forms.Form):
-+ persons = forms.ModelMultipleChoiceField(queryset=Writer.objects.all())
-+
-+ person1 = Writer.objects.create(name="Person 1")
-+ form = WriterForm(data={})
-+ queryset = form.fields['persons'].clean([str(person1.pk)] * 50)
-+ sql, params = queryset.query.sql_with_params()
-+ self.assertEqual(len(params), 1)
-+
- def test_file_field(self):
- # Test conditions when files is either not given or empty.
-
diff -Nru python-django-1.6.1/debian/patches/CVE-2015-2316.patch python-django-1.6.11/debian/patches/CVE-2015-2316.patch
--- python-django-1.6.1/debian/patches/CVE-2015-2316.patch 2015-03-20 14:36:18.000000000 +0000
+++ python-django-1.6.11/debian/patches/CVE-2015-2316.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,155 +0,0 @@
-Description: fix denial-of-service possibility with strip_tags
-Origin: backport, https://github.com/django/django/commit/d1503afd66ca8f2f8d3819ba8a60727e0ee66cec
-Origin: backport, https://github.com/django/django/commit/f05f5c231a916082b5fa2e0980fbf7abeb390032
-Origin: backport, https://github.com/django/django/commit/c9b2feffeed46765ed6c4b74066059e2a6541735
-Origin: backport, https://github.com/django/django/commit/b6b3cb9899214a23ebb0f4ebf0e0b300b0ee524f
-
-Index: python-django-1.6.1/django/utils/html.py
-===================================================================
---- python-django-1.6.1.orig/django/utils/html.py 2013-12-12 14:37:59.000000000 -0500
-+++ python-django-1.6.1/django/utils/html.py 2015-03-20 10:34:26.957545358 -0400
-@@ -115,7 +115,10 @@
-
- class MLStripper(HTMLParser):
- def __init__(self):
-- HTMLParser.__init__(self)
-+ if six.PY2:
-+ HTMLParser.__init__(self)
-+ else:
-+ HTMLParser.__init__(self, strict=False)
- self.reset()
- self.fed = []
- def handle_data(self, d):
-@@ -127,16 +130,39 @@
- def get_data(self):
- return ''.join(self.fed)
-
--def strip_tags(value):
-- """Returns the given HTML with all tags stripped."""
-+
-+def _strip_once(value):
-+ """
-+ Internal tag stripping utility used by strip_tags.
-+ """
- s = MLStripper()
- try:
- s.feed(value)
-- s.close()
- except HTMLParseError:
- return value
-+ try:
-+ s.close()
-+ except (HTMLParseError, UnboundLocalError) as err:
-+ # UnboundLocalError because of http://bugs.python.org/issue17802
-+ # on Python 3.2, triggered by strict=False mode of HTMLParser
-+ return s.get_data() + s.rawdata
- else:
- return s.get_data()
-+
-+
-+def strip_tags(value):
-+ """Returns the given HTML with all tags stripped."""
-+ while True:
-+ if not ('<' in value or '>' in value):
-+ return value
-+ new_value = _strip_once(value)
-+ if len(new_value) >= len(value):
-+ # _strip_once was not able to detect more tags or length increased
-+ # due to http://bugs.python.org/issue20288
-+ # (affects Python 2 < 2.7.7 and Python 3 < 3.3.5)
-+ return value
-+ else:
-+ value = new_value
- strip_tags = allow_lazy(strip_tags)
-
- def remove_tags(html, tags):
-Index: python-django-1.6.1/docs/ref/templates/builtins.txt
-===================================================================
---- python-django-1.6.1.orig/docs/ref/templates/builtins.txt 2013-12-12 14:37:59.000000000 -0500
-+++ python-django-1.6.1/docs/ref/templates/builtins.txt 2015-03-20 10:34:16.045456760 -0400
-@@ -1997,7 +1997,7 @@
- striptags
- ^^^^^^^^^
-
--Strips all [X]HTML tags.
-+Makes all possible efforts to strip all [X]HTML tags.
-
- For example::
-
-@@ -2006,6 +2006,16 @@
- If ``value`` is ``"Joel a slug"``, the
- output will be ``"Joel is a slug"``.
-
-+.. admonition:: No safety guarantee
-+
-+ Note that ``striptags`` doesn't give any guarantee about its output being
-+ entirely HTML safe, particularly with non valid HTML input. So **NEVER**
-+ apply the ``safe`` filter to a ``striptags`` output.
-+ If you are looking for something more robust, you can use the ``bleach``
-+ Python library, notably its `clean`_ method.
-+
-+.. _clean: http://bleach.readthedocs.org/en/latest/clean.html
-+
- .. templatefilter:: time
-
- time
-Index: python-django-1.6.1/docs/ref/utils.txt
-===================================================================
---- python-django-1.6.1.orig/docs/ref/utils.txt 2013-12-12 14:37:59.000000000 -0500
-+++ python-django-1.6.1/docs/ref/utils.txt 2015-03-20 10:34:16.045456760 -0400
-@@ -616,17 +616,23 @@
-
- .. function:: strip_tags(value)
-
-- Removes anything that looks like an html tag from the string, that is
-- anything contained within ``<>``.
-+ Tries to remove anything that looks like an HTML tag from the string, that
-+ is anything contained within ``<>``.
-+ Absolutely NO guaranty is provided about the resulting string being entirely
-+ HTML safe. So NEVER mark safe the result of a ``strip_tag`` call without
-+ escaping it first, for example with :func:`~django.utils.html.escape`.
-
- For example::
-
- strip_tags(value)
-
-- If ``value`` is ``"Joel a slug"`` the
-- return value will be ``"Joel is a slug"``. Note that ``strip_tags`` result
-- may still contain unsafe HTML content, so you might use
-- :func:`~django.utils.html.escape` to make it a safe string.
-+ If ``value`` is ``"Joel a slug"``
-+ the return value will be ``"Joel is a slug"``.
-+
-+ If you are looking for a more robust solution, take a look at the `bleach`_
-+ Python library.
-+
-+ .. _bleach: https://pypi.python.org/pypi/bleach
-
- .. versionchanged:: 1.6
-
-Index: python-django-1.6.1/tests/utils_tests/test_html.py
-===================================================================
---- python-django-1.6.1.orig/tests/utils_tests/test_html.py 2013-08-13 13:17:36.000000000 -0400
-+++ python-django-1.6.1/tests/utils_tests/test_html.py 2015-03-20 10:34:26.957545358 -0400
-@@ -80,10 +80,21 @@
- ('a
b
c', 'abc'),
- ('def', 'def'),
- ('foobar', 'foobar'),
-+ # caused infinite loop on Pythons not patched with
-+ # http://bugs.python.org/issue20288
-+ ('&gotcha<>', '&gotcha<>'),
- )
- for value, output in items:
- self.check_output(f, value, output)
-
-+ # Some convoluted syntax for which parsing may differ between python versions
-+ output = html.strip_tags('ript>test</script>')
-+ self.assertNotIn('&h')
-+ self.assertNotIn('ript>"`` won't be safe even if
+ you apply ``|removetags:"script"``. So if the input is user provided,
+ **NEVER** apply the ``safe`` filter to a ``removetags`` output. If you are
+ looking for something more robust, you can use the ``bleach`` Python
+ library, notably its `clean`_ method.
+
+.. _clean: http://bleach.readthedocs.org/en/latest/clean.html
.. templatefilter:: rjust
@@ -1997,7 +2040,7 @@
striptags
^^^^^^^^^
-Strips all [X]HTML tags.
+Makes all possible efforts to strip all [X]HTML tags.
For example::
@@ -2006,6 +2049,16 @@
If ``value`` is ``"Joel a slug"``, the
output will be ``"Joel is a slug"``.
+.. admonition:: No safety guarantee
+
+ Note that ``striptags`` doesn't give any guarantee about its output being
+ HTML safe, particularly with non valid HTML input. So **NEVER** apply the
+ ``safe`` filter to a ``striptags`` output. If you are looking for something
+ more robust, you can use the ``bleach`` Python library, notably its
+ `clean`_ method.
+
+.. _clean: http://bleach.readthedocs.org/en/latest/clean.html
+
.. templatefilter:: time
time
@@ -2454,10 +2507,9 @@
.. highlight:: html+django
-If you're not using :class:`~django.template.RequestContext`, or if you need
-more control over exactly where and how :setting:`STATIC_URL` is injected
-into the template, you can use the :ttag:`get_static_prefix` template tag
-instead::
+You should prefer the :ttag:`static` template tag, but if you need more control
+over exactly where and how :setting:`STATIC_URL` is injected into the template,
+you can use the :ttag:`get_static_prefix` template tag::
{% load static %}
@@ -2481,6 +2533,8 @@
Similar to the :ttag:`get_static_prefix`, ``get_media_prefix`` populates a
template variable with the media prefix :setting:`MEDIA_URL`, e.g.::
-
+ {% load static %}
+
+
+By storing the value in a data attribute, we ensure it's escaped appropriately
+if we want to use it in a JavaScript context.
diff -Nru python-django-1.6.1/docs/ref/templates/index.txt python-django-1.6.11/docs/ref/templates/index.txt
--- python-django-1.6.1/docs/ref/templates/index.txt 2013-06-04 21:37:51.000000000 +0000
+++ python-django-1.6.11/docs/ref/templates/index.txt 2015-03-18 23:40:08.000000000 +0000
@@ -5,7 +5,8 @@
Django's template engine provides a powerful mini-language for defining the
user-facing layer of your application, encouraging a clean separation of
application and presentation logic. Templates can be maintained by anyone with
-an understanding of HTML; no knowledge of Python is required.
+an understanding of HTML; no knowledge of Python is required. For introductory
+material, see :doc:`/topics/templates` topic guide.
.. toctree::
:maxdepth: 2
diff -Nru python-django-1.6.1/docs/ref/unicode.txt python-django-1.6.11/docs/ref/unicode.txt
--- python-django-1.6.1/docs/ref/unicode.txt 2013-08-13 17:17:35.000000000 +0000
+++ python-django-1.6.11/docs/ref/unicode.txt 2015-03-18 23:50:43.000000000 +0000
@@ -17,8 +17,8 @@
a more restrictive encoding -- for example, latin1 (iso8859-1) -- you won't be
able to store certain characters in the database, and information will be lost.
-* MySQL users, refer to the `MySQL manual`_ (section 9.1.3.2 for MySQL 5.1)
- for details on how to set or alter the database character set encoding.
+* MySQL users, refer to the `MySQL manual`_ for details on how to set or alter
+ the database character set encoding.
* PostgreSQL users, refer to the `PostgreSQL manual`_ (section 22.3.2 in
PostgreSQL 9) for details on creating databases with the correct encoding.
@@ -26,7 +26,7 @@
* SQLite users, there is nothing you need to do. SQLite always uses UTF-8
for internal encoding.
-.. _MySQL manual: http://dev.mysql.com/doc/refman/5.1/en/charset-database.html
+.. _MySQL manual: http://dev.mysql.com/doc/refman/5.6/en/charset-database.html
.. _PostgreSQL manual: http://www.postgresql.org/docs/current/static/multibyte.html
All of Django's database backends automatically convert Unicode strings into
diff -Nru python-django-1.6.1/docs/ref/urlresolvers.txt python-django-1.6.11/docs/ref/urlresolvers.txt
--- python-django-1.6.1/docs/ref/urlresolvers.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/ref/urlresolvers.txt 2015-03-18 23:40:08.000000000 +0000
@@ -12,17 +12,41 @@
.. function:: reverse(viewname, [urlconf=None, args=None, kwargs=None, current_app=None])
-``viewname`` is either the function name (either a function reference, or the
-string version of the name, if you used that form in ``urlpatterns``) or the
-:ref:`URL pattern name `. Normally, you won't need to
-worry about the ``urlconf`` parameter and will only pass in the positional and
-keyword arguments to use in the URL matching. For example::
+``viewname`` can be a string containing the Python path to the view object, a
+:ref:`URL pattern name `, or the callable view object.
+For example, given the following ``url``::
+
+ url(r'^archive/$', 'news.views.archive', name='news_archive')
+
+you can use any of the following to reverse the URL::
+
+ # using the Python path
+ reverse('news.views.archive')
+
+ # using the named URL
+ reverse('news_archive')
+
+ # passing a callable object
+ from news import views
+ reverse(views.archive)
+
+If the URL accepts arguments, you may pass them in ``args``. For example::
from django.core.urlresolvers import reverse
def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
+You can also pass ``kwargs`` instead of ``args``. For example::
+
+ >>> reverse('admin:app_list', kwargs={'app_label': 'auth'})
+ '/admin/auth/'
+
+``args`` and ``kwargs`` cannot be passed to ``reverse()`` at the same time.
+
+If no match can be made, ``reverse()`` raises a
+:class:`~django.core.urlresolvers.NoReverseMatch` exception.
+
The ``reverse()`` function can reverse a large variety of regular expression
patterns for URLs, but not every possible one. The main restriction at the
moment is that the pattern cannot contain alternative choices using the
@@ -36,12 +60,9 @@
namespaces into URLs on specific application instances, according to the
:ref:`namespaced URL resolution strategy `.
-You can use ``kwargs`` instead of ``args``. For example::
+The ``urlconf`` argument is the URLconf module containing the url patterns to
+use for reversing. By default, the root URLconf for the current thread is used.
- >>> reverse('admin:app_list', kwargs={'app_label': 'auth'})
- '/admin/auth/'
-
-``args`` and ``kwargs`` cannot be passed to ``reverse()`` at the same time.
.. admonition:: Make sure your views are all correct.
@@ -143,6 +164,11 @@
i.e., if the namespace is ``foo:bar``, then namespaces will be
``['foo', 'bar']``.
+ .. attribute:: ResolverMatch.view_name
+
+ The name of the view that matches the URL, including the namespace if
+ there is one.
+
A :class:`ResolverMatch` object can then be interrogated to provide
information about the URL pattern that matches a URL::
@@ -158,9 +184,9 @@
One possible use of :func:`~django.core.urlresolvers.resolve` would be to test
whether a view would raise a ``Http404`` error before redirecting to it::
- from urlparse import urlparse
from django.core.urlresolvers import resolve
from django.http import HttpResponseRedirect, Http404
+ from django.utils.six.moves.urllib.parse import urlparse
def myview(request):
next = request.META.get('HTTP_REFERER', None) or '/'
diff -Nru python-django-1.6.1/docs/ref/urls.txt python-django-1.6.11/docs/ref/urls.txt
--- python-django-1.6.1/docs/ref/urls.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/ref/urls.txt 2015-03-18 23:40:08.000000000 +0000
@@ -76,6 +76,9 @@
url(regex, view, kwargs=None, name=None, prefix='')
+The ``kwargs`` parameter allows you to pass additional arguments to the view
+function or method. See :ref:`views-extra-options` for an example.
+
See :ref:`Naming URL patterns ` for why the ``name``
parameter is useful.
@@ -123,7 +126,7 @@
that should be called if the HTTP client has sent a request that caused an error
condition and a response with a status code of 400.
-By default, this is ``'django.views.defaults.permission_denied'``. That default
+By default, this is ``'django.views.defaults.bad_request'``. That default
value should suffice.
See the documentation about :ref:`the 400 (bad request) view
diff -Nru python-django-1.6.1/docs/ref/utils.txt python-django-1.6.11/docs/ref/utils.txt
--- python-django-1.6.1/docs/ref/utils.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/ref/utils.txt 2015-03-18 23:50:43.000000000 +0000
@@ -616,17 +616,24 @@
.. function:: strip_tags(value)
- Removes anything that looks like an html tag from the string, that is
- anything contained within ``<>``.
+ Tries to remove anything that looks like an HTML tag from the string, that
+ is anything contained within ``<>``.
+
+ Absolutely NO guarantee is provided about the resulting string being
+ HTML safe. So NEVER mark safe the result of a ``strip_tag`` call without
+ escaping it first, for example with :func:`~django.utils.html.escape`.
For example::
strip_tags(value)
- If ``value`` is ``"Joel a slug"`` the
- return value will be ``"Joel is a slug"``. Note that ``strip_tags`` result
- may still contain unsafe HTML content, so you might use
- :func:`~django.utils.html.escape` to make it a safe string.
+ If ``value`` is ``"Joel a slug"``
+ the return value will be ``"Joel is a slug"``.
+
+ If you are looking for a more robust solution, take a look at the `bleach`_
+ Python library.
+
+ .. _bleach: https://pypi.python.org/pypi/bleach
.. versionchanged:: 1.6
@@ -636,6 +643,13 @@
Removes a space-separated list of [X]HTML tag names from the output.
+ Absolutely NO guarantee is provided about the resulting string being HTML
+ safe. In particular, it doesn't work recursively, so the output of
+ ``remove_tags("ript>alert('XSS')ript>", "script")``
+ won't remove the "nested" script tags. So if the ``value`` is untrusted,
+ NEVER mark safe the result of a ``remove_tags()`` call without escaping it
+ first, for example with :func:`~django.utils.html.escape`.
+
For example::
remove_tags(value, "b span")
@@ -675,7 +689,7 @@
.. function:: urlencode(query, doseq=0)
A version of Python's urllib.urlencode() function that can operate on
- unicode strings. The parameters are first case to UTF-8 encoded strings
+ unicode strings. The parameters are first cast to UTF-8 encoded strings
and then encoded as per normal.
.. function:: cookie_date(epoch_seconds=None)
@@ -790,6 +804,9 @@
Can be called multiple times on a single string.
+ For building up fragments of HTML, you should normally be using
+ :func:`django.utils.html.format_html` instead.
+
String marked safe will become unsafe again if modified. For example::
>>> mystr = 'Hello World '
@@ -1020,7 +1037,7 @@
current point in time. Exactly what's returned depends on the value of
:setting:`USE_TZ`:
- * If :setting:`USE_TZ` is ``False``, this will be be a
+ * If :setting:`USE_TZ` is ``False``, this will be a
:ref:`naive ` datetime (i.e. a datetime
without an associated timezone) that represents the current time
in the system's local timezone.
diff -Nru python-django-1.6.1/docs/releases/1.0-alpha-1.txt python-django-1.6.11/docs/releases/1.0-alpha-1.txt
--- python-django-1.6.1/docs/releases/1.0-alpha-1.txt 2013-06-04 21:37:51.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.0-alpha-1.txt 2015-03-18 23:50:43.000000000 +0000
@@ -77,7 +77,7 @@
uploading process as well as streaming uploads of large files.
Along with these improvements and additions, we've made a number of
-of backwards-incompatible changes to the framework, as features have been
+backwards-incompatible changes to the framework, as features have been
fleshed out and APIs have been finalized for the 1.0 release. A
complete guide to these changes will be available as part of the final
Django 1.0 release, and a comprehensive list of backwards-incompatible
diff -Nru python-django-1.6.1/docs/releases/1.1.txt python-django-1.6.11/docs/releases/1.1.txt
--- python-django-1.6.1/docs/releases/1.1.txt 2013-08-13 17:17:09.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.1.txt 2015-03-18 23:50:43.000000000 +0000
@@ -50,7 +50,7 @@
As a result of this change, you will not be able to use the ``reset``
management command on any table made by a 64-bit machine. This is because the
-the new generated name will not match the historically generated name; as a
+new generated name will not match the historically generated name; as a
result, the SQL constructed by the reset command will be invalid.
If you need to reset an application that was created with 64-bit constraints,
diff -Nru python-django-1.6.1/docs/releases/1.2-alpha-1.txt python-django-1.6.11/docs/releases/1.2-alpha-1.txt
--- python-django-1.6.1/docs/releases/1.2-alpha-1.txt 2013-08-13 17:17:09.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.2-alpha-1.txt 2015-03-18 23:50:43.000000000 +0000
@@ -520,7 +520,7 @@
:attr:`django.contrib.admin.ModelAdmin.readonly_fields` has been added to
enable non-editable fields in add/change pages for models and inlines. Field
-and calculated values can be displayed along side editable fields.
+and calculated values can be displayed alongside editable fields.
Customizable syntax highlighting
--------------------------------
diff -Nru python-django-1.6.1/docs/releases/1.2.txt python-django-1.6.11/docs/releases/1.2.txt
--- python-django-1.6.1/docs/releases/1.2.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.2.txt 2015-03-18 23:50:43.000000000 +0000
@@ -721,8 +721,9 @@
:ref:`django.forms.formsets.formset_factory() ` and
:ref:`django.forms.models.modelformset_factory()
` functions has changed slightly. This
-change also affects the way the ``max_num`` argument is :ref:`used for
-inline admin objects `
+change also affects the way the
+:attr:`~django.contrib.admin.InlineModelAdmin.max_num` argument is used for
+inline admin objects.
Previously, the default value for ``max_num`` was ``0`` (zero).
FormSets then used the boolean value of ``max_num`` to determine if a
diff -Nru python-django-1.6.1/docs/releases/1.4.11.txt python-django-1.6.11/docs/releases/1.4.11.txt
--- python-django-1.6.1/docs/releases/1.4.11.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.11.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,110 @@
+===========================
+Django 1.4.11 release notes
+===========================
+
+*April 21, 2014*
+
+Django 1.4.11 fixes three security issues in 1.4.10. Additionally,
+Django's vendored version of six, :mod:`django.utils.six`, has been
+upgraded to the latest release (1.6.1).
+
+Unexpected code execution using ``reverse()``
+=============================================
+
+Django's URL handling is based on a mapping of regex patterns
+(representing the URLs) to callable views, and Django's own processing
+consists of matching a requested URL against those patterns to
+determine the appropriate view to invoke.
+
+Django also provides a convenience function --
+:func:`~django.core.urlresolvers.reverse` -- which performs this process
+in the opposite direction. The ``reverse()`` function takes
+information about a view and returns a URL which would invoke that
+view. Use of ``reverse()`` is encouraged for application developers,
+as the output of ``reverse()`` is always based on the current URL
+patterns, meaning developers do not need to change other code when
+making changes to URLs.
+
+One argument signature for ``reverse()`` is to pass a dotted Python
+path to the desired view. In this situation, Django will import the
+module indicated by that dotted path as part of generating the
+resulting URL. If such a module has import-time side effects, those
+side effects will occur.
+
+Thus it is possible for an attacker to cause unexpected code
+execution, given the following conditions:
+
+1. One or more views are present which construct a URL based on user
+ input (commonly, a "next" parameter in a querystring indicating
+ where to redirect upon successful completion of an action).
+
+2. One or more modules are known to an attacker to exist on the
+ server's Python import path, which perform code execution with side
+ effects on importing.
+
+To remedy this, ``reverse()`` will now only accept and import dotted
+paths based on the view-containing modules listed in the project's :doc:`URL
+pattern configuration `, so as to ensure that only modules
+the developer intended to be imported in this fashion can or will be imported.
+
+Caching of anonymous pages could reveal CSRF token
+==================================================
+
+Django includes both a :doc:`caching framework ` and a system
+for :doc:`preventing cross-site request forgery (CSRF) attacks
+`. The CSRF-protection system is based on a random nonce
+sent to the client in a cookie which must be sent by the client on future
+requests and, in forms, a hidden value which must be submitted back with the
+form.
+
+The caching framework includes an option to cache responses to
+anonymous (i.e., unauthenticated) clients.
+
+When the first anonymous request to a given page is by a client which
+did not have a CSRF cookie, the cache framework will also cache the
+CSRF cookie and serve the same nonce to other anonymous clients who
+do not have a CSRF cookie. This can allow an attacker to obtain a
+valid CSRF cookie value and perform attacks which bypass the check for
+the cookie.
+
+To remedy this, the caching framework will no longer cache such
+responses. The heuristic for this will be:
+
+1. If the incoming request did not submit any cookies, and
+
+2. If the response did send one or more cookies, and
+
+3. If the ``Vary: Cookie`` header is set on the response, then the
+ response will not be cached.
+
+MySQL typecasting
+=================
+
+The MySQL database is known to "typecast" on certain queries; for
+example, when querying a table which contains string values, but using
+a query which filters based on an integer value, MySQL will first
+silently coerce the strings to integers and return a result based on that.
+
+If a query is performed without first converting values to the
+appropriate type, this can produce unexpected results, similar to what
+would occur if the query itself had been manipulated.
+
+Django's model field classes are aware of their own types and most
+such classes perform explicit conversion of query arguments to the
+correct database-level type before querying. However, three model
+field classes did not correctly convert their arguments:
+
+* :class:`~django.db.models.FilePathField`
+* :class:`~django.db.models.GenericIPAddressField`
+* :class:`~django.db.models.IPAddressField`
+
+These three fields have been updated to convert their arguments to the
+correct types before querying.
+
+Additionally, developers of custom model fields are now warned via
+documentation to ensure their custom field classes will perform
+appropriate type conversions, and users of the :meth:`raw()
+` and :meth:`extra()
+` query methods -- which allow the
+developer to supply raw SQL or SQL fragments -- will be advised to ensure they
+perform appropriate manual type conversions prior to executing queries.
diff -Nru python-django-1.6.1/docs/releases/1.4.12.txt python-django-1.6.11/docs/releases/1.4.12.txt
--- python-django-1.6.1/docs/releases/1.4.12.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.12.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,14 @@
+===========================
+Django 1.4.12 release notes
+===========================
+
+*April 28, 2014*
+
+Django 1.4.12 fixes a regression in the 1.4.11 security release.
+
+Bugfixes
+========
+
+* Restored the ability to :meth:`~django.core.urlresolvers.reverse` views
+ created using :func:`functools.partial()`
+ (`#22486 `_)
diff -Nru python-django-1.6.1/docs/releases/1.4.13.txt python-django-1.6.11/docs/releases/1.4.13.txt
--- python-django-1.6.1/docs/releases/1.4.13.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.13.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,47 @@
+===========================
+Django 1.4.13 release notes
+===========================
+
+*May 14, 2014*
+
+Django 1.4.13 fixes two security issues in 1.4.12.
+
+Caches may incorrectly be allowed to store and serve private data
+=================================================================
+
+In certain situations, Django may allow caches to store private data
+related to a particular session and then serve that data to requests
+with a different session, or no session at all. This can lead to
+information disclosure and can be a vector for cache poisoning.
+
+When using Django sessions, Django will set a ``Vary: Cookie`` header to
+ensure caches do not serve cached data to requests from other sessions.
+However, older versions of Internet Explorer (most likely only Internet
+Explorer 6, and Internet Explorer 7 if run on Windows XP or Windows Server
+2003) are unable to handle the ``Vary`` header in combination with many content
+types. Therefore, Django would remove the header if the request was made by
+Internet Explorer.
+
+To remedy this, the special behavior for these older Internet Explorer versions
+has been removed, and the ``Vary`` header is no longer stripped from the response.
+In addition, modifications to the ``Cache-Control`` header for all Internet Explorer
+requests with a ``Content-Disposition`` header have also been removed as they
+were found to have similar issues.
+
+Malformed redirect URLs from user input not correctly validated
+===============================================================
+
+The validation for redirects did not correctly validate some malformed URLs,
+which are accepted by some browsers. This allows a user to be redirected to
+an unsafe URL unexpectedly.
+
+Django relies on user input in some cases (e.g.
+:func:`django.contrib.auth.views.login`, ``django.contrib.comments``, and
+:doc:`i18n `) to redirect the user to an "on success" URL.
+The security checks for these redirects (namely
+``django.util.http.is_safe_url()``) did not correctly validate some malformed
+URLs, such as `http:\\\\\\djangoproject.com`, which are accepted by some browsers
+with more liberal URL parsing.
+
+To remedy this, the validation in ``is_safe_url()`` has been tightened to be able
+to handle and correctly validate these malformed URLs.
diff -Nru python-django-1.6.1/docs/releases/1.4.14.txt python-django-1.6.11/docs/releases/1.4.14.txt
--- python-django-1.6.1/docs/releases/1.4.14.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.14.txt 2015-01-06 01:20:47.000000000 +0000
@@ -0,0 +1,64 @@
+===========================
+Django 1.4.14 release notes
+===========================
+
+*August 20, 2014*
+
+Django 1.4.14 fixes several security issues in 1.4.13.
+
+:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
+=======================================================================================
+
+In certain situations, URL reversing could generate scheme-relative URLs (URLs
+starting with two slashes), which could unexpectedly redirect a user to a
+different host. An attacker could exploit this, for example, by redirecting
+users to a phishing site designed to ask for user's passwords.
+
+To remedy this, URL reversing now ensures that no URL starts with two slashes
+(//), replacing the second slash with its URL encoded counterpart (%2F). This
+approach ensures that semantics stay the same, while making the URL relative to
+the domain and not to the scheme.
+
+File upload denial-of-service
+=============================
+
+Before this release, Django's file upload handing in its default configuration
+may degrade to producing a huge number of ``os.stat()`` system calls when a
+duplicate filename is uploaded. Since ``stat()`` may invoke IO, this may produce
+a huge data-dependent slowdown that slowly worsens over time. The net result is
+that given enough time, a user with the ability to upload files can cause poor
+performance in the upload handler, eventually causing it to become very slow
+simply by uploading 0-byte files. At this point, even a slow network connection
+and few HTTP requests would be all that is necessary to make a site unavailable.
+
+We've remedied the issue by changing the algorithm for generating file names
+if a file with the uploaded name already exists.
+:meth:`Storage.get_available_name()
+` now appends an
+underscore plus a random 7 character alphanumeric string (e.g. ``"_x3a1gho"``),
+rather than iterating through an underscore followed by a number (e.g. ``"_1"``,
+``"_2"``, etc.).
+
+``RemoteUserMiddleware`` session hijacking
+==========================================
+
+When using the :class:`~django.contrib.auth.middleware.RemoteUserMiddleware`
+and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
+requests without an intervening logout could result in the prior user's session
+being co-opted by the subsequent user. The middleware now logs the user out on
+a failed login attempt.
+
+Data leakage via query string manipulation in ``contrib.admin``
+===============================================================
+
+In older versions of Django it was possible to reveal any field's data by
+modifying the "popup" and "to_field" parameters of the query string on an admin
+change form page. For example, requesting a URL like
+``/admin/auth/user/?pop=1&t=password`` and viewing the page's HTML allowed
+viewing the password hash of each user. While the admin requires users to have
+permissions to view the change form pages in the first place, this could leak
+data if you rely on users having access to view only certain fields on a model.
+
+To address the issue, an exception will now be raised if a ``to_field`` value
+that isn't a related field to a model that has been registered with the admin
+is specified.
diff -Nru python-django-1.6.1/docs/releases/1.4.15.txt python-django-1.6.11/docs/releases/1.4.15.txt
--- python-django-1.6.1/docs/releases/1.4.15.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.15.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,13 @@
+===========================
+Django 1.4.15 release notes
+===========================
+
+*September 2, 2014*
+
+Django 1.4.15 fixes a regression in the 1.4.14 security release.
+
+Bugfixes
+========
+
+* Allowed inherited and m2m fields to be referenced in the admin
+ (`#22486 `_)
diff -Nru python-django-1.6.1/docs/releases/1.4.16.txt python-django-1.6.11/docs/releases/1.4.16.txt
--- python-django-1.6.1/docs/releases/1.4.16.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.16.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,20 @@
+===========================
+Django 1.4.16 release notes
+===========================
+
+*October 22, 2014*
+
+Django 1.4.16 fixes a couple regressions in the 1.4.14 security release and a
+bug preventing the use of some GEOS versions with GeoDjango.
+
+Bugfixes
+========
+
+* Allowed related many-to-many fields to be referenced in the admin
+ (`#23604 `_).
+
+* Allowed inline and hidden references to admin fields
+ (`#23431 `_).
+
+* Fixed parsing of the GEOS version string
+ (`#20036 `_).
diff -Nru python-django-1.6.1/docs/releases/1.4.17.txt python-django-1.6.11/docs/releases/1.4.17.txt
--- python-django-1.6.1/docs/releases/1.4.17.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.17.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,17 @@
+===========================
+Django 1.4.17 release notes
+===========================
+
+*January 2, 2015*
+
+Django 1.4.17 fixes a regression in the 1.4.14 security release.
+
+Additionally, Django's vendored version of six, :mod:`django.utils.six`, has
+been upgraded to the latest release (1.9.0).
+
+Bugfixes
+========
+
+* Fixed a regression with dynamically generated inlines and allowed field
+ references in the admin
+ (`#23754 `_).
diff -Nru python-django-1.6.1/docs/releases/1.4.18.txt python-django-1.6.11/docs/releases/1.4.18.txt
--- python-django-1.6.1/docs/releases/1.4.18.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.18.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,68 @@
+===========================
+Django 1.4.18 release notes
+===========================
+
+*January 13, 2015*
+
+Django 1.4.18 fixes several security issues in 1.4.17 as well as a regression
+on Python 2.5 in the 1.4.17 release.
+
+WSGI header spoofing via underscore/dash conflation
+===================================================
+
+When HTTP headers are placed into the WSGI environ, they are normalized by
+converting to uppercase, converting all dashes to underscores, and prepending
+`HTTP_`. For instance, a header ``X-Auth-User`` would become
+``HTTP_X_AUTH_USER`` in the WSGI environ (and thus also in Django's
+``request.META`` dictionary).
+
+Unfortunately, this means that the WSGI environ cannot distinguish between
+headers containing dashes and headers containing underscores: ``X-Auth-User``
+and ``X-Auth_User`` both become ``HTTP_X_AUTH_USER``. This means that if a
+header is used in a security-sensitive way (for instance, passing
+authentication information along from a front-end proxy), even if the proxy
+carefully strips any incoming value for ``X-Auth-User``, an attacker may be
+able to provide an ``X-Auth_User`` header (with underscore) and bypass this
+protection.
+
+In order to prevent such attacks, both Nginx and Apache 2.4+ strip all headers
+containing underscores from incoming requests by default. Django's built-in
+development server now does the same. Django's development server is not
+recommended for production use, but matching the behavior of common production
+servers reduces the surface area for behavior changes during deployment.
+
+Mitigated possible XSS attack via user-supplied redirect URLs
+=============================================================
+
+Django relies on user input in some cases (e.g.
+:func:`django.contrib.auth.views.login` and :doc:`i18n `)
+to redirect the user to an "on success" URL. The security checks for these
+redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
+whitespace on the tested URL and as such considered URLs like
+``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
+provide safe redirect targets and put such a URL into a link, they could suffer
+from a XSS attack. This bug doesn't affect Django currently, since we only put
+this URL into the ``Location`` response header and browsers seem to ignore
+JavaScript there.
+
+Denial-of-service attack against ``django.views.static.serve``
+==============================================================
+
+In older versions of Django, the :func:`django.views.static.serve` view read
+the files it served one line at a time. Therefore, a big file with no newlines
+would result in memory usage equal to the size of that file. An attacker could
+exploit this and launch a denial-of-service attack by simultaneously requesting
+many large files. This view now reads the file in chunks to prevent large
+memory usage.
+
+Note, however, that this view has always carried a warning that it is not
+hardened for production use and should be used only as a development aid. Now
+may be a good time to audit your project and serve your files in production
+using a real front-end web server if you are not doing so.
+
+Bugfixes
+========
+
+* To maintain compatibility with Python 2.5, Django's vendored version of six,
+ :mod:`django.utils.six`, has been downgraded to 1.8.0 which is the last
+ version to support Python 2.5.
diff -Nru python-django-1.6.1/docs/releases/1.4.19.txt python-django-1.6.11/docs/releases/1.4.19.txt
--- python-django-1.6.1/docs/releases/1.4.19.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.19.txt 2015-01-27 17:27:56.000000000 +0000
@@ -0,0 +1,16 @@
+===========================
+Django 1.4.19 release notes
+===========================
+
+*January 27, 2015*
+
+Django 1.4.19 fixes a regression in the 1.4.18 security release.
+
+Bugfixes
+========
+
+* ``GZipMiddleware`` now supports streaming responses. As part of the 1.4.18
+ security release, the ``django.views.static.serve()`` function was altered
+ to stream the files it serves. Unfortunately, the ``GZipMiddleware`` consumed
+ the stream prematurely and prevented files from being served properly
+ (`#24158 `_).
diff -Nru python-django-1.6.1/docs/releases/1.4.20.txt python-django-1.6.11/docs/releases/1.4.20.txt
--- python-django-1.6.1/docs/releases/1.4.20.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.4.20.txt 2015-03-18 23:50:46.000000000 +0000
@@ -0,0 +1,26 @@
+===========================
+Django 1.4.20 release notes
+===========================
+
+*March 18, 2015*
+
+Django 1.4.20 fixes one security issue in 1.4.19.
+
+Mitigated possible XSS attack via user-supplied redirect URLs
+=============================================================
+
+Django relies on user input in some cases (e.g.
+:func:`django.contrib.auth.views.login` and :doc:`i18n `)
+to redirect the user to an "on success" URL. The security checks for these
+redirects (namely ``django.utils.http.is_safe_url()``) accepted URLs with
+leading control characters and so considered URLs like ``\x08javascript:...``
+safe. This issue doesn't affect Django currently, since we only put this URL
+into the ``Location`` response header and browsers seem to ignore JavaScript
+there. Browsers we tested also treat URLs prefixed with control characters such
+as ``%08//example.com`` as relative paths so redirection to an unsafe target
+isn't a problem either.
+
+However, if a developer relies on ``is_safe_url()`` to
+provide safe redirect targets and puts such a URL into a link, they could
+suffer from an XSS attack as some browsers such as Google Chrome ignore control
+characters at the start of a URL in an anchor ``href``.
diff -Nru python-django-1.6.1/docs/releases/1.5.10.txt python-django-1.6.11/docs/releases/1.5.10.txt
--- python-django-1.6.1/docs/releases/1.5.10.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.10.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,13 @@
+===========================
+Django 1.5.10 release notes
+===========================
+
+*September 2, 2014*
+
+Django 1.5.10 fixes a regression in the 1.5.9 security release.
+
+Bugfixes
+========
+
+* Allowed inherited and m2m fields to be referenced in the admin
+ (`#22486 `_)
diff -Nru python-django-1.6.1/docs/releases/1.5.11.txt python-django-1.6.11/docs/releases/1.5.11.txt
--- python-django-1.6.1/docs/releases/1.5.11.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.11.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,16 @@
+===========================
+Django 1.5.11 release notes
+===========================
+
+*October 22, 2014*
+
+Django 1.5.11 fixes a couple regressions in the 1.5.9 security release.
+
+Bugfixes
+========
+
+* Allowed related many-to-many fields to be referenced in the admin
+ (`#23604 `_).
+
+* Allowed inline and hidden references to admin fields
+ (`#23431 `_).
diff -Nru python-django-1.6.1/docs/releases/1.5.12.txt python-django-1.6.11/docs/releases/1.5.12.txt
--- python-django-1.6.1/docs/releases/1.5.12.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.12.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,14 @@
+===========================
+Django 1.5.12 release notes
+===========================
+
+*January 2, 2015*
+
+Django 1.5.12 fixes a regression in the 1.5.9 security release.
+
+Bugfixes
+========
+
+* Fixed a regression with dynamically generated inlines and allowed field
+ references in the admin
+ (`#23754 `_).
diff -Nru python-django-1.6.1/docs/releases/1.5.6.txt python-django-1.6.11/docs/releases/1.5.6.txt
--- python-django-1.6.1/docs/releases/1.5.6.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.6.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,119 @@
+==========================
+Django 1.5.6 release notes
+==========================
+
+*April 21, 2014*
+
+Django 1.5.6 fixes several bugs in 1.5.5, including three security
+issues.
+
+Unexpected code execution using ``reverse()``
+=============================================
+
+Django's URL handling is based on a mapping of regex patterns
+(representing the URLs) to callable views, and Django's own processing
+consists of matching a requested URL against those patterns to
+determine the appropriate view to invoke.
+
+Django also provides a convenience function --
+:func:`~django.core.urlresolvers.reverse` -- which performs this process
+in the opposite direction. The ``reverse()`` function takes
+information about a view and returns a URL which would invoke that
+view. Use of ``reverse()`` is encouraged for application developers,
+as the output of ``reverse()`` is always based on the current URL
+patterns, meaning developers do not need to change other code when
+making changes to URLs.
+
+One argument signature for ``reverse()`` is to pass a dotted Python
+path to the desired view. In this situation, Django will import the
+module indicated by that dotted path as part of generating the
+resulting URL. If such a module has import-time side effects, those
+side effects will occur.
+
+Thus it is possible for an attacker to cause unexpected code
+execution, given the following conditions:
+
+1. One or more views are present which construct a URL based on user
+ input (commonly, a "next" parameter in a querystring indicating
+ where to redirect upon successful completion of an action).
+
+2. One or more modules are known to an attacker to exist on the
+ server's Python import path, which perform code execution with side
+ effects on importing.
+
+To remedy this, ``reverse()`` will now only accept and import dotted
+paths based on the view-containing modules listed in the project's :doc:`URL
+pattern configuration `, so as to ensure that only modules
+the developer intended to be imported in this fashion can or will be imported.
+
+Caching of anonymous pages could reveal CSRF token
+==================================================
+
+Django includes both a :doc:`caching framework ` and a system
+for :doc:`preventing cross-site request forgery (CSRF) attacks
+`. The CSRF-protection system is based on a random nonce
+sent to the client in a cookie which must be sent by the client on future
+requests and, in forms, a hidden value which must be submitted back with the
+form.
+
+The caching framework includes an option to cache responses to
+anonymous (i.e., unauthenticated) clients.
+
+When the first anonymous request to a given page is by a client which
+did not have a CSRF cookie, the cache framework will also cache the
+CSRF cookie and serve the same nonce to other anonymous clients who
+do not have a CSRF cookie. This can allow an attacker to obtain a
+valid CSRF cookie value and perform attacks which bypass the check for
+the cookie.
+
+To remedy this, the caching framework will no longer cache such
+responses. The heuristic for this will be:
+
+1. If the incoming request did not submit any cookies, and
+
+2. If the response did send one or more cookies, and
+
+3. If the ``Vary: Cookie`` header is set on the response, then the
+ response will not be cached.
+
+MySQL typecasting
+=================
+
+The MySQL database is known to "typecast" on certain queries; for
+example, when querying a table which contains string values, but using
+a query which filters based on an integer value, MySQL will first
+silently coerce the strings to integers and return a result based on that.
+
+If a query is performed without first converting values to the
+appropriate type, this can produce unexpected results, similar to what
+would occur if the query itself had been manipulated.
+
+Django's model field classes are aware of their own types and most
+such classes perform explicit conversion of query arguments to the
+correct database-level type before querying. However, three model
+field classes did not correctly convert their arguments:
+
+* :class:`~django.db.models.FilePathField`
+* :class:`~django.db.models.GenericIPAddressField`
+* :class:`~django.db.models.IPAddressField`
+
+These three fields have been updated to convert their arguments to the
+correct types before querying.
+
+Additionally, developers of custom model fields are now warned via
+documentation to ensure their custom field classes will perform
+appropriate type conversions, and users of the :meth:`raw()
+` and :meth:`extra()
+` query methods -- which allow the
+developer to supply raw SQL or SQL fragments -- will be advised to ensure they
+perform appropriate manual type conversions prior to executing queries.
+
+Bugfixes
+========
+
+* Fixed :class:`~django.contrib.auth.backends.ModelBackend` raising
+ ``UnboundLocalError`` if :func:`~django.contrib.auth.get_user_model`
+ raised an error (#21439).
+
+Additionally, Django's vendored version of six, :mod:`django.utils.six`,
+has been upgraded to the latest release (1.6.1).
diff -Nru python-django-1.6.1/docs/releases/1.5.7.txt python-django-1.6.11/docs/releases/1.5.7.txt
--- python-django-1.6.1/docs/releases/1.5.7.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.7.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,14 @@
+==========================
+Django 1.5.7 release notes
+==========================
+
+*April 28, 2014*
+
+Django 1.5.7 fixes a regression in the 1.5.6 security release.
+
+Bugfixes
+========
+
+* Restored the ability to :meth:`~django.core.urlresolvers.reverse` views
+ created using :func:`functools.partial()`
+ (`#22486 `_)
diff -Nru python-django-1.6.1/docs/releases/1.5.8.txt python-django-1.6.11/docs/releases/1.5.8.txt
--- python-django-1.6.1/docs/releases/1.5.8.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.8.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,47 @@
+==========================
+Django 1.5.8 release notes
+==========================
+
+*May 14, 2014*
+
+Django 1.5.8 fixes two security issues in 1.5.8.
+
+Caches may incorrectly be allowed to store and serve private data
+=================================================================
+
+In certain situations, Django may allow caches to store private data
+related to a particular session and then serve that data to requests
+with a different session, or no session at all. This can lead to
+information disclosure and can be a vector for cache poisoning.
+
+When using Django sessions, Django will set a ``Vary: Cookie`` header to
+ensure caches do not serve cached data to requests from other sessions.
+However, older versions of Internet Explorer (most likely only Internet
+Explorer 6, and Internet Explorer 7 if run on Windows XP or Windows Server
+2003) are unable to handle the ``Vary`` header in combination with many content
+types. Therefore, Django would remove the header if the request was made by
+Internet Explorer.
+
+To remedy this, the special behavior for these older Internet Explorer versions
+has been removed, and the ``Vary`` header is no longer stripped from the response.
+In addition, modifications to the ``Cache-Control`` header for all Internet Explorer
+requests with a ``Content-Disposition`` header have also been removed as they
+were found to have similar issues.
+
+Malformed redirect URLs from user input not correctly validated
+===============================================================
+
+The validation for redirects did not correctly validate some malformed URLs,
+which are accepted by some browsers. This allows a user to be redirected to
+an unsafe URL unexpectedly.
+
+Django relies on user input in some cases (e.g.
+:func:`django.contrib.auth.views.login`, ``django.contrib.comments``, and
+:doc:`i18n `) to redirect the user to an "on success" URL.
+The security checks for these redirects (namely
+``django.util.http.is_safe_url()``) did not correctly validate some malformed
+URLs, such as `http:\\\\\\djangoproject.com`, which are accepted by some browsers
+with more liberal URL parsing.
+
+To remedy this, the validation in ``is_safe_url()`` has been tightened to be able
+to handle and correctly validate these malformed URLs.
diff -Nru python-django-1.6.1/docs/releases/1.5.9.txt python-django-1.6.11/docs/releases/1.5.9.txt
--- python-django-1.6.1/docs/releases/1.5.9.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.9.txt 2015-03-09 15:58:12.000000000 +0000
@@ -0,0 +1,64 @@
+==========================
+Django 1.5.9 release notes
+==========================
+
+*August 20, 2014*
+
+Django 1.5.9 fixes several security issues in 1.5.8.
+
+:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
+=======================================================================================
+
+In certain situations, URL reversing could generate scheme-relative URLs (URLs
+starting with two slashes), which could unexpectedly redirect a user to a
+different host. An attacker could exploit this, for example, by redirecting
+users to a phishing site designed to ask for user's passwords.
+
+To remedy this, URL reversing now ensures that no URL starts with two slashes
+(//), replacing the second slash with its URL encoded counterpart (%2F). This
+approach ensures that semantics stay the same, while making the URL relative to
+the domain and not to the scheme.
+
+File upload denial-of-service
+=============================
+
+Before this release, Django's file upload handing in its default configuration
+may degrade to producing a huge number of ``os.stat()`` system calls when a
+duplicate filename is uploaded. Since ``stat()`` may invoke IO, this may produce
+a huge data-dependent slowdown that slowly worsens over time. The net result is
+that given enough time, a user with the ability to upload files can cause poor
+performance in the upload handler, eventually causing it to become very slow
+simply by uploading 0-byte files. At this point, even a slow network connection
+and few HTTP requests would be all that is necessary to make a site unavailable.
+
+We've remedied the issue by changing the algorithm for generating file names
+if a file with the uploaded name already exists.
+:meth:`Storage.get_available_name()
+` now appends an
+underscore plus a random 7 character alphanumeric string (e.g. ``"_x3a1gho"``),
+rather than iterating through an underscore followed by a number (e.g. ``"_1"``,
+``"_2"``, etc.).
+
+``RemoteUserMiddleware`` session hijacking
+==========================================
+
+When using the :class:`~django.contrib.auth.middleware.RemoteUserMiddleware`
+and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
+requests without an intervening logout could result in the prior user's session
+being co-opted by the subsequent user. The middleware now logs the user out on
+a failed login attempt.
+
+Data leakage via query string manipulation in ``contrib.admin``
+===============================================================
+
+In older versions of Django it was possible to reveal any field's data by
+modifying the "popup" and "to_field" parameters of the query string on an admin
+change form page. For example, requesting a URL like
+``/admin/auth/user/?pop=1&t=password`` and viewing the page's HTML allowed
+viewing the password hash of each user. While the admin requires users to have
+permissions to view the change form pages in the first place, this could leak
+data if you rely on users having access to view only certain fields on a model.
+
+To address the issue, an exception will now be raised if a ``to_field`` value
+that isn't a related field to a model that has been registered with the admin
+is specified.
diff -Nru python-django-1.6.1/docs/releases/1.5-alpha-1.txt python-django-1.6.11/docs/releases/1.5-alpha-1.txt
--- python-django-1.6.1/docs/releases/1.5-alpha-1.txt 2013-08-13 17:17:09.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5-alpha-1.txt 2015-03-18 23:50:43.000000000 +0000
@@ -559,7 +559,7 @@
* Uploaded files are no longer created as executable by default. If you need
them to be executable change :setting:`FILE_UPLOAD_PERMISSIONS` to your
- needs. The new default value is ``0666`` (octal) and the current umask value
+ needs. The new default value is ``0o666`` (octal) and the current umask value
is first masked out.
* The :ref:`F() expressions ` supported bitwise operators by
diff -Nru python-django-1.6.1/docs/releases/1.5-beta-1.txt python-django-1.6.11/docs/releases/1.5-beta-1.txt
--- python-django-1.6.1/docs/releases/1.5-beta-1.txt 2013-08-13 17:17:09.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5-beta-1.txt 2015-03-18 23:50:43.000000000 +0000
@@ -598,7 +598,7 @@
* Uploaded files are no longer created as executable by default. If you need
them to be executable change :setting:`FILE_UPLOAD_PERMISSIONS` to your
- needs. The new default value is ``0666`` (octal) and the current umask value
+ needs. The new default value is ``0o666`` (octal) and the current umask value
is first masked out.
* The :ref:`F() expressions ` supported bitwise operators by
diff -Nru python-django-1.6.1/docs/releases/1.5.txt python-django-1.6.11/docs/releases/1.5.txt
--- python-django-1.6.1/docs/releases/1.5.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.5.txt 2015-03-18 23:50:43.000000000 +0000
@@ -354,7 +354,7 @@
.. warning::
In addition to the changes outlined in this section, be sure to review the
- :doc:`deprecation plan ` for any features that
+ :ref:`deprecation plan ` for any features that
have been removed. If you haven't updated your code within the
deprecation timeline for a given feature, its removal may appear as a
backwards incompatible change.
@@ -676,7 +676,7 @@
* Uploaded files are no longer created as executable by default. If you need
them to be executable change :setting:`FILE_UPLOAD_PERMISSIONS` to your
- needs. The new default value is ``0666`` (octal) and the current umask value
+ needs. The new default value is ``0o666`` (octal) and the current umask value
is first masked out.
* The :ref:`F() expressions ` supported bitwise operators by
diff -Nru python-django-1.6.1/docs/releases/1.6.10.txt python-django-1.6.11/docs/releases/1.6.10.txt
--- python-django-1.6.1/docs/releases/1.6.10.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.10.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,69 @@
+===========================
+Django 1.6.10 release notes
+===========================
+
+*January 13, 2015*
+
+Django 1.6.10 fixes several security issues in 1.6.9.
+
+WSGI header spoofing via underscore/dash conflation
+===================================================
+
+When HTTP headers are placed into the WSGI environ, they are normalized by
+converting to uppercase, converting all dashes to underscores, and prepending
+`HTTP_`. For instance, a header ``X-Auth-User`` would become
+``HTTP_X_AUTH_USER`` in the WSGI environ (and thus also in Django's
+``request.META`` dictionary).
+
+Unfortunately, this means that the WSGI environ cannot distinguish between
+headers containing dashes and headers containing underscores: ``X-Auth-User``
+and ``X-Auth_User`` both become ``HTTP_X_AUTH_USER``. This means that if a
+header is used in a security-sensitive way (for instance, passing
+authentication information along from a front-end proxy), even if the proxy
+carefully strips any incoming value for ``X-Auth-User``, an attacker may be
+able to provide an ``X-Auth_User`` header (with underscore) and bypass this
+protection.
+
+In order to prevent such attacks, both Nginx and Apache 2.4+ strip all headers
+containing underscores from incoming requests by default. Django's built-in
+development server now does the same. Django's development server is not
+recommended for production use, but matching the behavior of common production
+servers reduces the surface area for behavior changes during deployment.
+
+Mitigated possible XSS attack via user-supplied redirect URLs
+=============================================================
+
+Django relies on user input in some cases (e.g.
+:func:`django.contrib.auth.views.login` and :doc:`i18n `)
+to redirect the user to an "on success" URL. The security checks for these
+redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
+whitespace on the tested URL and as such considered URLs like
+``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
+provide safe redirect targets and put such a URL into a link, they could suffer
+from a XSS attack. This bug doesn't affect Django currently, since we only put
+this URL into the ``Location`` response header and browsers seem to ignore
+JavaScript there.
+
+Denial-of-service attack against ``django.views.static.serve``
+==============================================================
+
+In older versions of Django, the :func:`django.views.static.serve` view read
+the files it served one line at a time. Therefore, a big file with no newlines
+would result in memory usage equal to the size of that file. An attacker could
+exploit this and launch a denial-of-service attack by simultaneously requesting
+many large files. This view now reads the file in chunks to prevent large
+memory usage.
+
+Note, however, that this view has always carried a warning that it is not
+hardened for production use and should be used only as a development aid. Now
+may be a good time to audit your project and serve your files in production
+using a real front-end web server if you are not doing so.
+
+Database denial-of-service with ``ModelMultipleChoiceField``
+============================================================
+
+Given a form that uses ``ModelMultipleChoiceField`` and
+``show_hidden_initial=True`` (not a documented API), it was possible for a user
+to cause an unreasonable number of SQL queries by submitting duplicate values
+for the field's data. The validation logic in ``ModelMultipleChoiceField`` now
+deduplicates submitted values to address this issue.
diff -Nru python-django-1.6.1/docs/releases/1.6.11.txt python-django-1.6.11/docs/releases/1.6.11.txt
--- python-django-1.6.1/docs/releases/1.6.11.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.11.txt 2015-03-18 23:50:46.000000000 +0000
@@ -0,0 +1,43 @@
+===========================
+Django 1.6.11 release notes
+===========================
+
+*March 18, 2015*
+
+Django 1.6.11 fixes two security issues in 1.6.10.
+
+Denial-of-service possibility with ``strip_tags()``
+===================================================
+
+Last year :func:`~django.utils.html.strip_tags` was changed to work
+iteratively. The problem is that the size of the input it's processing can
+increase on each iteration which results in an infinite loop in
+``strip_tags()``. This issue only affects versions of Python that haven't
+received `a bugfix in HTMLParser `_; namely
+Python < 2.7.7 and 3.3.5. Some operating system vendors have also backported
+the fix for the Python bug into their packages of earlier versions.
+
+To remedy this issue, ``strip_tags()`` will now return the original input if
+it detects the length of the string it's processing increases. Remember that
+absolutely NO guarantee is provided about the results of ``strip_tags()`` being
+HTML safe. So NEVER mark safe the result of a ``strip_tags()`` call without
+escaping it first, for example with :func:`~django.utils.html.escape`.
+
+Mitigated possible XSS attack via user-supplied redirect URLs
+=============================================================
+
+Django relies on user input in some cases (e.g.
+:func:`django.contrib.auth.views.login` and :doc:`i18n `)
+to redirect the user to an "on success" URL. The security checks for these
+redirects (namely ``django.utils.http.is_safe_url()``) accepted URLs with
+leading control characters and so considered URLs like ``\x08javascript:...``
+safe. This issue doesn't affect Django currently, since we only put this URL
+into the ``Location`` response header and browsers seem to ignore JavaScript
+there. Browsers we tested also treat URLs prefixed with control characters such
+as ``%08//example.com`` as relative paths so redirection to an unsafe target
+isn't a problem either.
+
+However, if a developer relies on ``is_safe_url()`` to
+provide safe redirect targets and puts such a URL into a link, they could
+suffer from an XSS attack as some browsers such as Google Chrome ignore control
+characters at the start of a URL in an anchor ``href``.
diff -Nru python-django-1.6.1/docs/releases/1.6.1.txt python-django-1.6.11/docs/releases/1.6.1.txt
--- python-django-1.6.1/docs/releases/1.6.1.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.1.txt 2015-03-09 15:58:12.000000000 +0000
@@ -2,7 +2,7 @@
Django 1.6.1 release notes
==========================
-*Under development*
+*December 12, 2013*
This is Django 1.6.1, a bugfix release for Django 1.6. In addition to the bug
fixes listed below, translations submitted since the 1.6 release are also
diff -Nru python-django-1.6.1/docs/releases/1.6.2.txt python-django-1.6.11/docs/releases/1.6.2.txt
--- python-django-1.6.1/docs/releases/1.6.2.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.2.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,52 @@
+==========================
+Django 1.6.2 release notes
+==========================
+
+*February 6, 2014*
+
+This is Django 1.6.2, a bugfix release for Django 1.6. Django 1.6.2 fixes
+several bugs in 1.6.1:
+
+* Prevented the base geometry object of a prepared geometry to be garbage
+ collected, which could lead to crash Django
+ (`#21662 `_).
+
+* Fixed a crash when executing the :djadmin:`changepassword` command when the
+ user object representation contained non-ASCII characters
+ (`#21627 `_).
+
+* The :djadmin:`collectstatic` command will raise an error rather than
+ default to using the current working directory if :setting:`STATIC_ROOT` is
+ not set. Combined with the ``--clear`` option, the previous behavior could
+ wipe anything below the current working directory
+ (`#21581 `_).
+
+* Fixed mail encoding on Python 3.3.3+
+ (`#21093 `_).
+
+* Fixed an issue where when
+ ``settings.DATABASES['default']['AUTOCOMMIT'] = False``, the connection
+ wasn't in autocommit mode but Django pretended it was.
+
+* Fixed a regression in multiple-table inheritance ``exclude()`` queries
+ (`#21787 `_).
+
+* Added missing items to ``django.utils.timezone.__all__``
+ (`#21880 `_).
+
+* Fixed a field misalignment issue with ``select_related()`` and model
+ inheritance
+ (`#21413 `_).
+
+* Fixed join promotion for negated ``AND`` conditions
+ (`#21748 `_).
+
+* Oracle database introspection now works with boolean and float fields
+ (`#19884 `_).
+
+* Fixed an issue where lazy objects weren't actually marked as safe when passed
+ through :func:`~django.utils.safestring.mark_safe` and could end up being
+ double-escaped (`#21882 `_).
+
+Additionally, Django's vendored version of six, :mod:`django.utils.six` has been
+upgraded to the latest release (1.5.2).
diff -Nru python-django-1.6.1/docs/releases/1.6.3.txt python-django-1.6.11/docs/releases/1.6.3.txt
--- python-django-1.6.1/docs/releases/1.6.3.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.3.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,186 @@
+==========================
+Django 1.6.3 release notes
+==========================
+
+*April 21, 2014*
+
+Django 1.6.3 fixes several bugs in 1.6.2, including three security issues,
+and makes one backwards-incompatible change:
+
+Unexpected code execution using ``reverse()``
+=============================================
+
+Django's URL handling is based on a mapping of regex patterns
+(representing the URLs) to callable views, and Django's own processing
+consists of matching a requested URL against those patterns to
+determine the appropriate view to invoke.
+
+Django also provides a convenience function --
+:func:`~django.core.urlresolvers.reverse` -- which performs this process
+in the opposite direction. The ``reverse()`` function takes
+information about a view and returns a URL which would invoke that
+view. Use of ``reverse()`` is encouraged for application developers,
+as the output of ``reverse()`` is always based on the current URL
+patterns, meaning developers do not need to change other code when
+making changes to URLs.
+
+One argument signature for ``reverse()`` is to pass a dotted Python
+path to the desired view. In this situation, Django will import the
+module indicated by that dotted path as part of generating the
+resulting URL. If such a module has import-time side effects, those
+side effects will occur.
+
+Thus it is possible for an attacker to cause unexpected code
+execution, given the following conditions:
+
+1. One or more views are present which construct a URL based on user
+ input (commonly, a "next" parameter in a querystring indicating
+ where to redirect upon successful completion of an action).
+
+2. One or more modules are known to an attacker to exist on the
+ server's Python import path, which perform code execution with side
+ effects on importing.
+
+To remedy this, ``reverse()`` will now only accept and import dotted
+paths based on the view-containing modules listed in the project's :doc:`URL
+pattern configuration `, so as to ensure that only modules
+the developer intended to be imported in this fashion can or will be imported.
+
+Caching of anonymous pages could reveal CSRF token
+==================================================
+
+Django includes both a :doc:`caching framework ` and a system
+for :doc:`preventing cross-site request forgery (CSRF) attacks
+`. The CSRF-protection system is based on a random nonce
+sent to the client in a cookie which must be sent by the client on future
+requests and, in forms, a hidden value which must be submitted back with the
+form.
+
+The caching framework includes an option to cache responses to
+anonymous (i.e., unauthenticated) clients.
+
+When the first anonymous request to a given page is by a client which
+did not have a CSRF cookie, the cache framework will also cache the
+CSRF cookie and serve the same nonce to other anonymous clients who
+do not have a CSRF cookie. This can allow an attacker to obtain a
+valid CSRF cookie value and perform attacks which bypass the check for
+the cookie.
+
+To remedy this, the caching framework will no longer cache such
+responses. The heuristic for this will be:
+
+1. If the incoming request did not submit any cookies, and
+
+2. If the response did send one or more cookies, and
+
+3. If the ``Vary: Cookie`` header is set on the response, then the
+ response will not be cached.
+
+MySQL typecasting
+=================
+
+The MySQL database is known to "typecast" on certain queries; for
+example, when querying a table which contains string values, but using
+a query which filters based on an integer value, MySQL will first
+silently coerce the strings to integers and return a result based on that.
+
+If a query is performed without first converting values to the
+appropriate type, this can produce unexpected results, similar to what
+would occur if the query itself had been manipulated.
+
+Django's model field classes are aware of their own types and most
+such classes perform explicit conversion of query arguments to the
+correct database-level type before querying. However, three model
+field classes did not correctly convert their arguments:
+
+* :class:`~django.db.models.FilePathField`
+* :class:`~django.db.models.GenericIPAddressField`
+* :class:`~django.db.models.IPAddressField`
+
+These three fields have been updated to convert their arguments to the
+correct types before querying.
+
+Additionally, developers of custom model fields are now warned via
+documentation to ensure their custom field classes will perform
+appropriate type conversions, and users of the :meth:`raw()
+` and :meth:`extra()
+` query methods -- which allow the
+developer to supply raw SQL or SQL fragments -- will be advised to ensure they
+perform appropriate manual type conversions prior to executing queries.
+
+``select_for_update()`` requires a transaction
+==============================================
+
+Historically, queries that use
+:meth:`~django.db.models.query.QuerySet.select_for_update()` could be
+executed in autocommit mode, outside of a transaction. Before Django
+1.6, Django's automatic transactions mode allowed this to be used to
+lock records until the next write operation. Django 1.6 introduced
+database-level autocommit; since then, execution in such a context
+voids the effect of ``select_for_update()``. It is, therefore, assumed
+now to be an error and raises an exception.
+
+This change was made because such errors can be caused by including an
+app which expects global transactions (e.g. :setting:`ATOMIC_REQUESTS
+` set to ``True``), or Django's old autocommit
+behavior, in a project which runs without them; and further, such
+errors may manifest as data-corruption bugs.
+
+This change may cause test failures if you use ``select_for_update()``
+in a test class which is a subclass of
+:class:`~django.test.TransactionTestCase` rather than
+:class:`~django.test.TestCase`.
+
+Other bugfixes and changes
+==========================
+
+* Content retrieved from the GeoIP library is now properly decoded from its
+ default ``iso-8859-1`` encoding
+ (`#21996 `_).
+
+* Fixed ``AttributeError`` when using
+ :meth:`~django.db.models.query.QuerySet.bulk_create` with ``ForeignObject``
+ (`#21566 `_).
+
+* Fixed crash of ``QuerySet``\s that use ``F() + timedelta()`` when their query
+ was compiled more once
+ (`#21643 `_).
+
+* Prevented custom ``widget`` class attribute of
+ :class:`~django.forms.IntegerField` subclasses from being overwritten by the
+ code in their ``__init__`` method
+ (`#22245 `_).
+
+* Improved :func:`~django.utils.html.strip_tags` accuracy (but it still cannot
+ guarantee an HTML-safe result, as stated in the documentation).
+
+* Fixed a regression in the :mod:`django.contrib.gis` SQL compiler for
+ non-concrete fields (`#22250 `_).
+
+* Fixed :attr:`ModelAdmin.preserve_filters
+ ` when running a site with
+ a URL prefix (`#21795 `_).
+
+* Fixed a crash in the ``find_command`` management utility when the ``PATH``
+ environment variable wasn't set
+ (`#22256 `_).
+
+* Fixed :djadmin:`changepassword` on Windows
+ (`#22364 `_).
+
+* Avoided shadowing deadlock exceptions on MySQL
+ (`#22291 `_).
+
+* Wrapped database exceptions in ``_set_autocommit``
+ (`#22321 `_).
+
+* Fixed atomicity when closing a database connection or when the database server
+ disconnects (`#21239 `_ and
+ `#21202 `_)
+
+* Fixed regression in ``prefetch_related`` that caused the related objects
+ query to include an unnecessary join
+ (`#21760 `_).
+
+Additionally, Django's vendored version of six, :mod:`django.utils.six` has been
+upgraded to the latest release (1.6.1).
diff -Nru python-django-1.6.1/docs/releases/1.6.4.txt python-django-1.6.11/docs/releases/1.6.4.txt
--- python-django-1.6.1/docs/releases/1.6.4.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.4.txt 2015-03-18 23:40:08.000000000 +0000
@@ -0,0 +1,22 @@
+==========================
+Django 1.6.4 release notes
+==========================
+
+*April 28, 2014*
+
+Django 1.6.4 fixes several bugs in 1.6.3.
+
+Bugfixes
+========
+
+* Added backwards compatibility support for the :mod:`django.contrib.messages`
+ cookie format of Django 1.4 and earlier to facilitate upgrading to 1.6 from
+ 1.4 (`#22426 `_).
+
+* Restored the ability to :meth:`~django.core.urlresolvers.reverse` views
+ created using :func:`functools.partial()`
+ (`#22486 `_).
+
+* Fixed the ``object_id`` of the ``LogEntry`` that's created after a user
+ password change in the admin
+ (`#22515 `_).
diff -Nru python-django-1.6.1/docs/releases/1.6.5.txt python-django-1.6.11/docs/releases/1.6.5.txt
--- python-django-1.6.1/docs/releases/1.6.5.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.5.txt 2015-03-18 23:50:43.000000000 +0000
@@ -0,0 +1,63 @@
+==========================
+Django 1.6.5 release notes
+==========================
+
+*May 14, 2014*
+
+Django 1.6.5 fixes two security issues and several bugs in 1.6.4.
+
+Issue: Caches may incorrectly be allowed to store and serve private data
+========================================================================
+
+In certain situations, Django may allow caches to store private data
+related to a particular session and then serve that data to requests
+with a different session, or no session at all. This can lead to
+information disclosure and can be a vector for cache poisoning.
+
+When using Django sessions, Django will set a ``Vary: Cookie`` header to
+ensure caches do not serve cached data to requests from other sessions.
+However, older versions of Internet Explorer (most likely only Internet
+Explorer 6, and Internet Explorer 7 if run on Windows XP or Windows Server
+2003) are unable to handle the ``Vary`` header in combination with many content
+types. Therefore, Django would remove the header if the request was made by
+Internet Explorer.
+
+To remedy this, the special behavior for these older Internet Explorer versions
+has been removed, and the ``Vary`` header is no longer stripped from the response.
+In addition, modifications to the ``Cache-Control`` header for all Internet Explorer
+requests with a ``Content-Disposition`` header have also been removed as they
+were found to have similar issues.
+
+Issue: Malformed redirect URLs from user input not correctly validated
+======================================================================
+
+The validation for redirects did not correctly validate some malformed URLs,
+which are accepted by some browsers. This allows a user to be redirected to
+an unsafe URL unexpectedly.
+
+Django relies on user input in some cases (e.g.
+:func:`django.contrib.auth.views.login`, ``django.contrib.comments``, and
+:doc:`i18n `) to redirect the user to an "on success" URL.
+The security checks for these redirects (namely
+``django.util.http.is_safe_url()``) did not correctly validate some malformed
+URLs, such as `http:\\\\\\djangoproject.com`, which are accepted by some browsers
+with more liberal URL parsing.
+
+To remedy this, the validation in ``is_safe_url()`` has been tightened to be able
+to handle and correctly validate these malformed URLs.
+
+Bugfixes
+========
+
+* Made the ``year_lookup_bounds_for_datetime_field`` Oracle backend method
+ Python 3 compatible (`#22551 `_).
+
+* Fixed ``pgettext_lazy`` crash when receiving bytestring content on Python 2
+ (`#22565 `_).
+
+* Fixed the SQL generated when filtering by a negated ``Q`` object that contains
+ a ``F`` object. (`#22429 `_).
+
+* Avoided overwriting data fetched by ``select_related()`` in certain cases
+ which could cause minor performance regressions
+ (`#22508 `_).
diff -Nru python-django-1.6.1/docs/releases/1.6.6.txt python-django-1.6.11/docs/releases/1.6.6.txt
--- python-django-1.6.1/docs/releases/1.6.6.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.6.txt 2015-03-09 15:58:12.000000000 +0000
@@ -0,0 +1,97 @@
+==========================
+Django 1.6.6 release notes
+==========================
+
+*August 20, 2014*
+
+Django 1.6.6 fixes several security issues and bugs in 1.6.5.
+
+:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
+=======================================================================================
+
+In certain situations, URL reversing could generate scheme-relative URLs (URLs
+starting with two slashes), which could unexpectedly redirect a user to a
+different host. An attacker could exploit this, for example, by redirecting
+users to a phishing site designed to ask for user's passwords.
+
+To remedy this, URL reversing now ensures that no URL starts with two slashes
+(//), replacing the second slash with its URL encoded counterpart (%2F). This
+approach ensures that semantics stay the same, while making the URL relative to
+the domain and not to the scheme.
+
+File upload denial-of-service
+=============================
+
+Before this release, Django's file upload handing in its default configuration
+may degrade to producing a huge number of ``os.stat()`` system calls when a
+duplicate filename is uploaded. Since ``stat()`` may invoke IO, this may produce
+a huge data-dependent slowdown that slowly worsens over time. The net result is
+that given enough time, a user with the ability to upload files can cause poor
+performance in the upload handler, eventually causing it to become very slow
+simply by uploading 0-byte files. At this point, even a slow network connection
+and few HTTP requests would be all that is necessary to make a site unavailable.
+
+We've remedied the issue by changing the algorithm for generating file names
+if a file with the uploaded name already exists.
+:meth:`Storage.get_available_name()
+` now appends an
+underscore plus a random 7 character alphanumeric string (e.g. ``"_x3a1gho"``),
+rather than iterating through an underscore followed by a number (e.g. ``"_1"``,
+``"_2"``, etc.).
+
+``RemoteUserMiddleware`` session hijacking
+==========================================
+
+When using the :class:`~django.contrib.auth.middleware.RemoteUserMiddleware`
+and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
+requests without an intervening logout could result in the prior user's session
+being co-opted by the subsequent user. The middleware now logs the user out on
+a failed login attempt.
+
+Data leakage via query string manipulation in ``contrib.admin``
+===============================================================
+
+In older versions of Django it was possible to reveal any field's data by
+modifying the "popup" and "to_field" parameters of the query string on an admin
+change form page. For example, requesting a URL like
+``/admin/auth/user/?_popup=1&t=password`` and viewing the page's HTML allowed
+viewing the password hash of each user. While the admin requires users to have
+permissions to view the change form pages in the first place, this could leak
+data if you rely on users having access to view only certain fields on a model.
+
+To address the issue, an exception will now be raised if a ``to_field`` value
+that isn't a related field to a model that has been registered with the admin
+is specified.
+
+Bugfixes
+========
+
+* Corrected email and URL validation to reject a trailing dash
+ (:ticket:`22579`).
+
+* Prevented indexes on PostgreSQL virtual fields (:ticket:`22514`).
+
+* Prevented edge case where values of FK fields could be initialized with a
+ wrong value when an inline model formset is created for a relationship
+ defined to point to a field other than the PK (:ticket:`13794`).
+
+* Restored ``pre_delete`` signals for ``GenericRelation`` cascade deletion
+ (:ticket:`22998`).
+
+* Fixed transaction handling when specifying non-default database in
+ ``createcachetable`` and ``flush`` (:ticket:`23089`).
+
+* Fixed the "ORA-01843: not a valid month" errors when using Unicode
+ with older versions of Oracle server (:ticket:`20292`).
+
+* Restored bug fix for sending unicode email with Python 2.6.5 and below
+ (:ticket:`19107`).
+
+* Prevented ``UnicodeDecodeError`` in ``runserver`` with non-UTF-8 and
+ non-English locale (:ticket:`23265`).
+
+* Fixed JavaScript errors while editing multi-geometry objects in the OpenLayers
+ widget (:ticket:`23137`, :ticket:`23293`).
+
+* Prevented a crash on Python 3 with query strings containing unencoded
+ non-ASCII characters (:ticket:`22996`).
diff -Nru python-django-1.6.1/docs/releases/1.6.7.txt python-django-1.6.11/docs/releases/1.6.7.txt
--- python-django-1.6.1/docs/releases/1.6.7.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.7.txt 2015-03-09 15:58:12.000000000 +0000
@@ -0,0 +1,16 @@
+==========================
+Django 1.6.7 release notes
+==========================
+
+*September 2, 2014*
+
+Django 1.6.7 fixes several bugs in 1.6.6, including a regression related to
+a security fix in that release.
+
+Bugfixes
+========
+
+* Allowed inherited and m2m fields to be referenced in the admin
+ (:ticket:`23329`).
+* Fixed a crash when using ``QuerySet.defer()`` with ``select_related()``
+ (:ticket:`23370`).
diff -Nru python-django-1.6.1/docs/releases/1.6.8.txt python-django-1.6.11/docs/releases/1.6.8.txt
--- python-django-1.6.1/docs/releases/1.6.8.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.8.txt 2015-03-09 15:58:12.000000000 +0000
@@ -0,0 +1,15 @@
+==========================
+Django 1.6.8 release notes
+==========================
+
+*October 22, 2014*
+
+Django 1.6.8 fixes a couple regressions in the 1.6.6 security release.
+
+Bugfixes
+========
+
+* Allowed related many-to-many fields to be referenced in the admin
+ (:ticket:`23604`).
+
+* Allowed inline and hidden references to admin fields (:ticket:`23431`).
diff -Nru python-django-1.6.1/docs/releases/1.6.9.txt python-django-1.6.11/docs/releases/1.6.9.txt
--- python-django-1.6.1/docs/releases/1.6.9.txt 1970-01-01 00:00:00.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.9.txt 2015-03-09 15:58:12.000000000 +0000
@@ -0,0 +1,16 @@
+==========================
+Django 1.6.9 release notes
+==========================
+
+*January 2, 2015*
+
+Django 1.6.9 fixes a regression in the 1.6.6 security release.
+
+Additionally, Django's vendored version of six, :mod:`django.utils.six`, has
+been upgraded to the latest release (1.9.0).
+
+Bugfixes
+========
+
+* Fixed a regression with dynamically generated inlines and allowed field
+ references in the admin (:ticket:`23754`).
diff -Nru python-django-1.6.1/docs/releases/1.6.txt python-django-1.6.11/docs/releases/1.6.txt
--- python-django-1.6.1/docs/releases/1.6.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/releases/1.6.txt 2015-03-18 23:50:43.000000000 +0000
@@ -44,6 +44,8 @@
Django 1.6 will be the final release series to support Python 2.6; beginning
with Django 1.7, the minimum supported Python version will be 2.7.
+Python 3.4 is not supported, but support will be added in Django 1.7.
+
What's new in Django 1.6
========================
@@ -380,7 +382,7 @@
.. warning::
In addition to the changes outlined in this section, be sure to review the
- :doc:`deprecation plan ` for any features that
+ :ref:`deprecation plan ` for any features that
have been removed. If you haven't updated your code within the
deprecation timeline for a given feature, its removal may appear as a
backwards incompatible change.
@@ -444,6 +446,17 @@
.. _recommendations in the Python documentation: http://docs.python.org/2/library/doctest.html#unittest-api
+Removal of ``django.contrib.gis.tests.GeoDjangoTestSuiteRunner`` GeoDjango custom test runner
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is for developers working on the GeoDjango application itself and related
+to the item above about changes in the test runners:
+
+The ``django.contrib.gis.tests.GeoDjangoTestSuiteRunner`` test runner has been
+removed and the standalone GeoDjango tests execution setup it implemented isn't
+supported anymore. To run the GeoDjango tests simply use the new
+``DiscoverRunner`` and specify the ``django.contrib.gis`` app.
+
Custom User models in tests
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -480,7 +493,7 @@
tables with `mysql_tzinfo_to_sql`_.
.. _pytz: http://pytz.sourceforge.net/
-.. _mysql_tzinfo_to_sql: http://dev.mysql.com/doc/refman/5.5/en/mysql-tzinfo-to-sql.html
+.. _mysql_tzinfo_to_sql: http://dev.mysql.com/doc/refman/5.6/en/mysql-tzinfo-to-sql.html
Addition of ``QuerySet.datetimes()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -586,7 +599,8 @@
Django 1.6. If you worked around this bug by applying URL quoting before
passing arguments to :func:`~django.core.urlresolvers.reverse`, this may
result in double-quoting. If this happens, simply remove the URL quoting from
-your code.
+your code. You will also have to replace special characters in URLs used in
+:func:`~django.test.SimpleTestCase.assertRedirects` with their encoded versions.
Storage of IP addresses in the comments app
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -639,21 +653,24 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HTML rendering of model form fields corresponding to
-:class:`~django.db.models.ManyToManyField` ORM model fields used to get the
-hard-coded sentence
+:class:`~django.db.models.ManyToManyField` model fields used to get the
+hard-coded sentence:
*Hold down "Control", or "Command" on a Mac, to select more than one.*
(or its translation to the active locale) imposed as the help legend shown along
them if neither :attr:`model ` nor :attr:`form
-` ``help_text`` attribute was specified by the
-user (or appended to, if ``help_text`` was provided.)
+` ``help_text`` attributes were specified by the
+user (or this string was appended to any ``help_text`` that was provided).
-This happened always, possibly even with form fields implementing user
-interactions that don't involve a keyboard and/or a mouse and was handled at the
-model field layer.
-
-Starting with Django 1.6 this doesn't happen anymore.
+Since this happened at the model layer, there was no way to prevent the text
+from appearing in cases where it wasn't applicable such as form fields that
+implement user interactions that don't involve a keyboard and/or a mouse.
+
+Starting with Django 1.6, as an ad-hoc temporary backward-compatibility
+provision, the logic to add the "Hold down..." sentence has been moved to the
+model form field layer and modified to add the text only when the associated
+widget is :class:`~django.forms.SelectMultiple` or selected subclasses.
The change can affect you in a backward incompatible way if you employ custom
model form fields and/or widgets for ``ManyToManyField`` model fields whose UIs
@@ -666,11 +683,6 @@
and :doc:`widgets ` aren't affected but need to be aware of
what's described in :ref:`m2m-help_text-deprecation` below.
-This is because, as an ad-hoc temporary backward-compatibility provision, the
-described non-standard behavior has been preserved but moved to the model form
-field layer and occurs only when the associated widget is
-:class:`~django.forms.SelectMultiple` or selected subclasses.
-
QuerySet iteration
~~~~~~~~~~~~~~~~~~
@@ -826,11 +838,11 @@
Django 1.6 contains many changes to the ORM. These changes fall mostly in
three categories:
- 1. Bug fixes (e.g. proper join clauses for generic relations, query
- combining, join promotion, and join trimming fixes)
- 2. Preparation for new features. For example the ORM is now internally ready
- for multicolumn foreign keys.
- 3. General cleanup.
+1. Bug fixes (e.g. proper join clauses for generic relations, query combining,
+ join promotion, and join trimming fixes)
+2. Preparation for new features. For example the ORM is now internally ready
+ for multicolumn foreign keys.
+3. General cleanup.
These changes can result in some compatibility problems. For example, some
queries will now generate different table aliases. This can affect
@@ -904,8 +916,8 @@
from a method when rendering a template, it is not silenced. For example,
``{{ obj.view_href }}`` will cause template rendering to fail if
``view_href()`` raises ``NoReverseMatch``. There is no change to the
- ``{% url %}`` tag, it causes template rendering to fail like always when
- ``NoReverseMatch`` is raised.
+ :ttag:`{% url %}` tag, it causes template rendering to fail like always
+ when ``NoReverseMatch`` is raised.
* :meth:`django.test.client.Client.logout` now calls
:meth:`django.contrib.auth.logout` which will send the
@@ -1009,7 +1021,7 @@
Django 1.6 starts a process to correct this inconsistency. The ``future``
template library provides alternate implementations of :ttag:`cycle` and
:ttag:`firstof` that autoescape their inputs. If you're using these tags,
-you're encourage to include the following line at the top of your templates to
+you're encouraged to include the following line at the top of your templates to
enable the new behavior::
{% load cycle from future %}
@@ -1030,10 +1042,11 @@
``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-``CacheMiddleware`` used to provide a way to cache requests only if they
-weren't made by a logged-in user. This mechanism was largely ineffective
-because the middleware correctly takes into account the ``Vary: Cookie`` HTTP
-header, and this header is being set on a variety of occasions, such as:
+``CacheMiddleware`` and ``UpdateCacheMiddleware`` used to provide a way to
+cache requests only if they weren't made by a logged-in user. This mechanism
+was largely ineffective because the middleware correctly takes into account the
+``Vary: Cookie`` HTTP header, and this header is being set on a variety of
+occasions, such as:
* accessing the session, or
* using CSRF protection, which is turned on by default, or
@@ -1079,7 +1092,9 @@
``Model._meta.get_(add|change|delete)_permission`` methods were deprecated.
Even if they were not part of the public API they'll also go through
-a regular deprecation path.
+a regular deprecation path. You can replace them with
+``django.contrib.auth.get_permission_codename('action', Model._meta)`` where
+``'action'`` is ``'add'``, ``'change'``, or ``'delete'``.
``get_query_set`` and similar methods renamed to ``get_queryset``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1087,6 +1102,53 @@
Methods that return a ``QuerySet`` such as ``Manager.get_query_set`` or
``ModelAdmin.queryset`` have been renamed to ``get_queryset``.
+If you are writing a library that implements, for example, a
+``Manager.get_query_set`` method, and you need to support old Django versions,
+you should rename the method and conditionally add an alias with the old name::
+
+ class CustomManager(models.Manager):
+ def get_queryset(self):
+ pass # ...
+
+ if django.VERSION < (1, 6):
+ get_query_set = get_queryset
+
+ # For Django >= 1.6, models.Manager provides a get_query_set fallback
+ # that emits a warning when used.
+
+If you are writing a library that needs to call the ``get_queryset`` method and
+must support old Django versions, you should write::
+
+ get_queryset = (some_manager.get_query_set
+ if hasattr(some_manager, 'get_query_set')
+ else some_manager.get_queryset)
+ return get_queryset() # etc
+
+In the general case of a custom manager that both implements its own
+``get_queryset`` method and calls that method, and needs to work with older Django
+versions, and libraries that have not been updated yet, it is useful to define
+a ``get_queryset_compat`` method as below and use it internally to your manager::
+
+ class YourCustomManager(models.Manager):
+ def get_queryset(self):
+ return YourCustomQuerySet() # for example
+
+ get_query_set = get_queryset
+
+ def active(self): # for example
+ return self.get_queryset_compat().filter(active=True)
+
+ def get_queryset_compat(self):
+ get_queryset = (self.get_query_set
+ if hasattr(self, 'get_query_set')
+ else self.get_queryset)
+ return get_queryset()
+
+This helps to minimize the changes that are needed, but also works correctly in
+the case of subclasses (such as ``RelatedManagers`` from Django 1.5) which might
+override either ``get_query_set`` or ``get_queryset``.
+
+
``shortcut`` view and URLconf
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1151,7 +1213,7 @@
For this reason, if you use these views for editing models, you must also supply
the ``fields`` attribute (new in Django 1.6), which is a list of model fields
and works in the same way as the :class:`~django.forms.ModelForm`
-``Meta.fields`` attribute. Alternatively, you can set set the ``form_class``
+``Meta.fields`` attribute. Alternatively, you can set the ``form_class``
attribute to a ``ModelForm`` that explicitly defines the fields to be used.
Defining an ``UpdateView`` or ``CreateView`` subclass to be used with a model
but without an explicit list of fields is deprecated.
diff -Nru python-django-1.6.1/docs/releases/index.txt python-django-1.6.11/docs/releases/index.txt
--- python-django-1.6.1/docs/releases/index.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/releases/index.txt 2015-03-18 23:50:46.000000000 +0000
@@ -15,6 +15,9 @@
Final releases
==============
+Below are release notes through Django |version| and its minor releases. Newer
+versions of the documentation contain the release notes for any later releases.
+
.. _development_release_notes:
1.6 release
@@ -22,6 +25,16 @@
.. toctree::
:maxdepth: 1
+ 1.6.11
+ 1.6.10
+ 1.6.9
+ 1.6.8
+ 1.6.7
+ 1.6.6
+ 1.6.5
+ 1.6.4
+ 1.6.3
+ 1.6.2
1.6.1
1.6
@@ -30,6 +43,13 @@
.. toctree::
:maxdepth: 1
+ 1.5.12
+ 1.5.11
+ 1.5.10
+ 1.5.9
+ 1.5.8
+ 1.5.7
+ 1.5.6
1.5.5
1.5.4
1.5.3
@@ -42,6 +62,16 @@
.. toctree::
:maxdepth: 1
+ 1.4.20
+ 1.4.19
+ 1.4.18
+ 1.4.17
+ 1.4.16
+ 1.4.15
+ 1.4.14
+ 1.4.13
+ 1.4.12
+ 1.4.11
1.4.10
1.4.9
1.4.8
diff -Nru python-django-1.6.1/docs/releases/security.txt python-django-1.6.11/docs/releases/security.txt
--- python-django-1.6.1/docs/releases/security.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/releases/security.txt 2015-03-18 23:40:08.000000000 +0000
@@ -349,9 +349,9 @@
Versions affected
-----------------
- * Django 1.3: `(patch) `__
+* Django 1.3: `(patch) `__
- * Django 1.4: `(patch) `__
+* Django 1.4: `(patch) `__
February 19, 2013 - No CVE
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -448,3 +448,156 @@
* Django 1.4 `(patch `__ and `Python compatibility fix) `__
* Django 1.5 `(patch) `__
+
+
+April 21, 2014 - CVE-2014-0472
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-0472 `_: Unexpected code execution using ``reverse()``. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+April 21, 2014 - CVE-2014-0473
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-0473 `_: Caching of anonymous pages could reveal CSRF token. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+April 21, 2014 - CVE-2014-0474
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-0474 `_: MySQL typecasting causes unexpected query results. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+May 18, 2014 - CVE-2014-1418
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-1418 `_: Caches may be allowed to store and serve private data. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+May 18, 2014 - CVE-2014-3730
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-3730 `_: Malformed URLs from user input incorrectly validated. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+August 20, 2014 - CVE-2014-0480
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-0480 `_: reverse() can generate URLs pointing to other hosts. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+August 20, 2014 - CVE-2014-0481
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-0481 `_: File upload denial of service. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+August 20, 2014 - CVE-2014-0482
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-0482 `_: RemoteUserMiddleware session hijacking. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
+
+
+August 20, 2014 - CVE-2014-0483
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`CVE-2014-0483 `_: Data leakage via querystring manipulation in admin. `Full description `__
+
+Versions affected
+-----------------
+
+* Django 1.4 `(patch) `__
+
+* Django 1.5 `(patch) `__
+
+* Django 1.6 `(patch) `__
+
+* Django 1.7 `(patch) `__
diff -Nru python-django-1.6.1/docs/_theme/djangodocs/static/djangodocs.css python-django-1.6.11/docs/_theme/djangodocs/static/djangodocs.css
--- python-django-1.6.1/docs/_theme/djangodocs/static/djangodocs.css 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/_theme/djangodocs/static/djangodocs.css 2015-03-18 23:50:43.000000000 +0000
@@ -117,7 +117,8 @@
/*** versoinadded/changes ***/
div.versionadded, div.versionchanged { }
-div.versionadded span.title, div.versionchanged span.title, div.deprecated span.title { font-weight: bold; }
+div.versionadded span.title, div.versionchanged span.title, span.versionmodified { font-weight: bold; }
+div.deprecated { color:#555; }
/*** p-links ***/
a.headerlink { color: #c60f0f; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; visibility: hidden; }
diff -Nru python-django-1.6.1/docs/topics/auth/customizing.txt python-django-1.6.11/docs/topics/auth/customizing.txt
--- python-django-1.6.1/docs/topics/auth/customizing.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/auth/customizing.txt 2015-03-18 23:50:43.000000000 +0000
@@ -5,7 +5,7 @@
The authentication that comes with Django is good enough for most common cases,
but you may have needs not met by the out-of-the-box defaults. To customize
authentication to your projects needs involves understanding what points of the
-provided system are extendible or replaceable. This document provides details
+provided system are extensible or replaceable. This document provides details
about how the auth system can be customized.
:ref:`Authentication backends ` provide an extensible
@@ -451,6 +451,8 @@
class Article(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
+.. _specifying-custom-user-model:
+
Specifying a custom User model
------------------------------
@@ -502,7 +504,7 @@
as the identifying field::
class MyUser(AbstractBaseUser):
- identifier = models.CharField(max_length=40, unique=True, db_index=True)
+ identifier = models.CharField(max_length=40, unique=True)
...
USERNAME_FIELD = 'identifier'
@@ -530,8 +532,9 @@
.. note::
- ``REQUIRED_FIELDS`` must contain all required fields on your User
- model, but should *not* contain the ``USERNAME_FIELD``.
+ ``REQUIRED_FIELDS`` must contain all required fields on your
+ ``User`` model, but should *not* contain the ``USERNAME_FIELD`` or
+ ``password`` as these fields will always be prompted for.
.. attribute:: is_active
@@ -593,7 +596,7 @@
.. versionchanged:: 1.6
In Django 1.4 and 1.5, a blank string was unintentionally stored
- as an unsable password as well.
+ as an unusable password as well.
.. method:: models.AbstractBaseUser.check_password(raw_password)
@@ -690,10 +693,12 @@
-------------------------------
If you're entirely happy with Django's :class:`~django.contrib.auth.models.User`
-model and you just want to add some additional profile information, you can
+model and you just want to add some additional profile information, you could
simply subclass ``django.contrib.auth.models.AbstractUser`` and add your
-custom profile fields. This class provides the full implementation of the
-default :class:`~django.contrib.auth.models.User` as an :ref:`abstract model
+custom profile fields, although we'd recommend a separate model as described in
+the "Model design considerations" note of :ref:`specifying-custom-user-model`.
+``AbstractUser`` provides the full implementation of the default
+:class:`~django.contrib.auth.models.User` as an :ref:`abstract model
`.
.. _custom-users-and-the-built-in-auth-forms:
@@ -726,9 +731,9 @@
* :class:`~django.contrib.auth.forms.PasswordResetForm`
- Assumes that the user model has an integer primary key, has a field named
- ``email`` that can be used to identify the user, and a boolean field
- named `is_active` to prevent password resets for inactive users.
+ Assumes that the user model has a field named ``email`` that can be used to
+ identify the user and a boolean field named ``is_active`` to prevent
+ password resets for inactive users.
* :class:`~django.contrib.auth.forms.SetPasswordForm`
@@ -803,7 +808,7 @@
.. method:: models.PermissionsMixin.get_group_permissions(obj=None)
- Returns a set of permission strings that the user has, through his/her
+ Returns a set of permission strings that the user has, through their
groups.
If ``obj`` is passed in, only returns the group permissions for
@@ -991,7 +996,6 @@
verbose_name='email address',
max_length=255,
unique=True,
- db_index=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
@@ -1078,7 +1082,7 @@
class Meta:
model = MyUser
- fields = ['email', 'password', 'date_of_birth', 'is_active', 'is_admin']
+ fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
diff -Nru python-django-1.6.1/docs/topics/auth/default.txt python-django-1.6.11/docs/topics/auth/default.txt
--- python-django-1.6.1/docs/topics/auth/default.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/auth/default.txt 2015-03-18 23:50:43.000000000 +0000
@@ -7,14 +7,13 @@
This document explains the usage of Django's authentication system in its
default configuration. This configuration has evolved to serve the most common
project needs, handling a reasonably wide range of tasks, and has a careful
-implementation of passwords and permissions, and can handle many projects as
-is. For projects where authentication needs differ from the default, Django
-supports extensive :doc:`extension and customization
-` of authentication.
+implementation of passwords and permissions. For projects where authentication
+needs differ from the default, Django supports extensive :doc:`extension and
+customization ` of authentication.
-Django authentication provides both authentication and authorization, together
+Django authentication provides both authentication and authorization together
and is generally referred to as the authentication system, as these features
-somewhat coupled.
+are somewhat coupled.
.. _user-objects:
@@ -25,17 +24,18 @@
authentication system. They typically represent the people interacting with
your site and are used to enable things like restricting access, registering
user profiles, associating content with creators etc. Only one class of user
-exists in Django's authentication framework, i.e., 'superusers' or admin
-'staff' users are just user objects with special attributes set, not different
-classes of user objects.
+exists in Django's authentication framework, i.e., :attr:`'superusers'
+` or admin :attr:`'staff'
+` users are just user objects with
+special attributes set, not different classes of user objects.
The primary attributes of the default user are:
-* username
-* password
-* email
-* first name
-* last name
+* :attr:`~django.contrib.auth.models.User.username`
+* :attr:`~django.contrib.auth.models.User.password`
+* :attr:`~django.contrib.auth.models.User.email`
+* :attr:`~django.contrib.auth.models.User.first_name`
+* :attr:`~django.contrib.auth.models.User.last_name`
See the :class:`full API documentation ` for
full reference, the documentation that follows is more task oriented.
@@ -136,6 +136,16 @@
# the authentication system was unable to verify the username and password
print("The username and password were incorrect.")
+ .. note::
+
+ This is a low level way to authenticate a set of credentials; for
+ example, it's used by the
+ :class:`~django.contrib.auth.middleware.RemoteUserMiddleware`. Unless
+ you are writing your own authentication system, you probably won't use
+ this. Rather if you are looking for a way to limit access to logged in
+ users, see the :func:`~django.contrib.auth.decorators.login_required`
+ decorator.
+
.. _topic-authorization:
Permissions and Authorization
@@ -248,6 +258,39 @@
attribute or to a :class:`~django.contrib.auth.models.Group` via its
``permissions`` attribute.
+Permission caching
+------------------
+
+The :class:`~django.contrib.auth.backends.ModelBackend` caches permissions on
+the ``User`` object after the first time they need to be fetched for a
+permissions check. This is typically fine for the request-response cycle since
+permissions are not typically checked immediately after they are added (in the
+admin, for example). If you are adding permissions and checking them immediately
+afterward, in a test or view for example, the easiest solution is to re-fetch
+the ``User`` from the database. For example::
+
+ from django.contrib.auth.models import Permission, User
+ from django.shortcuts import get_object_or_404
+
+ def user_gains_perms(request, user_id):
+ user = get_object_or_404(User, pk=user_id)
+ # any permission check will cache the current set of permissions
+ user.has_perm('myapp.change_bar')
+
+ permission = Permission.objects.get(codename='change_bar')
+ user.user_permissions.add(permission)
+
+ # Checking the cached permission set
+ user.has_perm('myapp.change_bar') # False
+
+ # Request new instance of User
+ user = get_object_or_404(User, pk=user_id)
+
+ # Permission cache is repopulated from the database
+ user.has_perm('myapp.change_bar') # True
+
+ ...
+
.. _auth-web-requests:
Authentication in Web requests
@@ -460,7 +503,7 @@
return HttpResponse("You can't vote in this poll.")
# ...
-.. function:: user_passes_test(func, [login_url=None])
+.. function:: user_passes_test(func, [login_url=None, redirect_field_name=REDIRECT_FIELD_NAME])
As a shortcut, you can use the convenient ``user_passes_test`` decorator::
@@ -481,9 +524,19 @@
automatically check that the :class:`~django.contrib.auth.models.User` is
not anonymous.
- :func:`~django.contrib.auth.decorators.user_passes_test()` takes an
- optional ``login_url`` argument, which lets you specify the URL for your
- login page (:setting:`settings.LOGIN_URL ` by default).
+ :func:`~django.contrib.auth.decorators.user_passes_test` takes two
+ optional arguments:
+
+ ``login_url``
+ Lets you specify the URL that users who don't pass the test will be
+ redirected to. It may be a login page and defaults to
+ :setting:`settings.LOGIN_URL ` if you don't specify one.
+
+ ``redirect_field_name``
+ Same as for :func:`~django.contrib.auth.decorators.login_required`.
+ Setting it to ``None`` removes it from the URL, which you may want to do
+ if you are redirecting users that don't pass the test to a non-login
+ page where there's no "next page".
For example::
@@ -907,6 +960,11 @@
**URL name:** ``password_reset_done``
+ .. note::
+
+ If the email address provided does not exist in the system, the user is inactive, or has an unusable password,
+ the user will still be redirected to this view but no email will be sent.
+
**Optional arguments:**
* ``template_name``: The full name of a template to use.
@@ -1052,7 +1110,7 @@
.. class:: SetPasswordForm
- A form that lets a user change his/her password without entering the old
+ A form that lets a user change their password without entering the old
password.
.. class:: UserChangeForm
@@ -1070,7 +1128,7 @@
Authentication data in templates
--------------------------------
-The currently logged-in user and his/her permissions are made available in the
+The currently logged-in user and their permissions are made available in the
:doc:`template context ` when you use
:class:`~django.template.RequestContext`.
diff -Nru python-django-1.6.1/docs/topics/auth/passwords.txt python-django-1.6.11/docs/topics/auth/passwords.txt
--- python-django-1.6.1/docs/topics/auth/passwords.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/auth/passwords.txt 2015-03-18 23:50:43.000000000 +0000
@@ -220,7 +220,7 @@
to be an unusable password, resulting in this method returning
``False`` for such a password.
-.. function:: make_password(password[, salt, hashers])
+.. function:: make_password(password, salt=None, hasher='default')
Creates a hashed password in the format used by this application. It takes
one mandatory argument: the password in plain-text. Optionally, you can
diff -Nru python-django-1.6.1/docs/topics/cache.txt python-django-1.6.11/docs/topics/cache.txt
--- python-django-1.6.1/docs/topics/cache.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/cache.txt 2015-03-18 23:50:43.000000000 +0000
@@ -34,7 +34,7 @@
specific views, you can cache only the pieces that are difficult to produce,
or you can cache your entire site.
-Django also works well with "upstream" caches, such as `Squid
+Django also works well with "downstream" caches, such as `Squid
`_ and browser-based caches. These are the types of
caches that you don't directly control but to which you can provide hints (via
HTTP headers) about which parts of your site should be cached, and how.
@@ -278,8 +278,9 @@
This is the default cache if another is not specified in your settings file. If
you want the speed advantages of in-memory caching but don't have the capability
of running Memcached, consider the local-memory cache backend. This cache is
-multi-process and thread-safe. To use it, set :setting:`BACKEND `
-to ``"django.core.cache.backends.locmem.LocMemCache"``. For example::
+per-process (see below) and thread-safe. To use it, set :setting:`BACKEND
+` to ``"django.core.cache.backends.locmem.LocMemCache"``. For
+example::
CACHES = {
'default': {
@@ -410,6 +411,8 @@
Invalid arguments are silently ignored, as are invalid values of known
arguments.
+.. _the-per-site-cache:
+
The per-site cache
==================
@@ -441,14 +444,14 @@
the site, or some other string that is unique to this Django instance, to
prevent key collisions. Use an empty string if you don't care.
-The cache middleware caches GET and HEAD responses with status 200, where the request
-and response headers allow. Responses to requests for the same URL with different
-query parameters are considered to be unique pages and are cached separately.
-The cache middleware expects that a HEAD request is answered with the same
-response headers as the corresponding GET request; in which case it can return
-a cached GET response for HEAD request.
+``FetchFromCacheMiddleware`` caches GET and HEAD responses with status 200,
+where the request and response headers allow. Responses to requests for the same
+URL with different query parameters are considered to be unique pages and are
+cached separately. This middleware expects that a HEAD request is answered with
+the same response headers as the corresponding GET request; in which case it can
+return a cached GET response for HEAD request.
-Additionally, the cache middleware automatically sets a few headers in each
+Additionally, ``UpdateCacheMiddleware`` automatically sets a few headers in each
:class:`~django.http.HttpResponse`:
* Sets the ``Last-Modified`` header to the current date/time when a fresh
@@ -536,9 +539,9 @@
def my_view(request):
...
-The two settings can also be combined. If you specify a ``cache`` *and*
-a ``key_prefix``, you will get all the settings of the requested cache
-alias, but with the key_prefix overridden.
+The ``key_prefix and ``cache`` arguments may be specified together. The
+``key_prefix`` argument and the :setting:`KEY_PREFIX `
+specified under :setting:`CACHES` will be concatenated.
Specifying per-view cache in the URLconf
----------------------------------------
@@ -938,15 +941,15 @@
...and use the dotted Python path to this class in the
:setting:`BACKEND ` portion of your :setting:`CACHES` setting.
-Upstream caches
-===============
+Downstream caches
+=================
So far, this document has focused on caching your *own* data. But another type
-of caching is relevant to Web development, too: caching performed by "upstream"
-caches. These are systems that cache pages for users even before the request
-reaches your Web site.
+of caching is relevant to Web development, too: caching performed by
+"downstream" caches. These are systems that cache pages for users even before
+the request reaches your Web site.
-Here are a few examples of upstream caches:
+Here are a few examples of downstream caches:
* Your ISP may cache certain pages, so if you requested a page from
http://example.com/, your ISP would send you the page without having to
@@ -964,7 +967,7 @@
subsequent requests to that page, without even contacting the Web page
again to see whether it has changed.
-Upstream caching is a nice efficiency boost, but there's a danger to it:
+Downstream caching is a nice efficiency boost, but there's a danger to it:
Many Web pages' contents differ based on authentication and a host of other
variables, and cache systems that blindly save pages based purely on URLs could
expose incorrect or sensitive data to subsequent visitors to those pages.
@@ -976,7 +979,7 @@
not cool.
Fortunately, HTTP provides a solution to this problem. A number of HTTP headers
-exist to instruct upstream caches to differ their cache contents depending on
+exist to instruct downstream caches to differ their cache contents depending on
designated variables, and to tell caching mechanisms not to cache particular
pages. We'll look at some of these headers in the sections that follow.
@@ -1022,7 +1025,7 @@
def my_view(request):
# ...
-This tells upstream caches to vary on *both*, which means each combination of
+This tells downstream caches to vary on *both*, which means each combination of
user-agent and cookie will get its own cache value. For example, a request with
the user-agent ``Mozilla`` and the cookie value ``foo=bar`` will be considered
different from a request with the user-agent ``Mozilla`` and the cookie value
diff -Nru python-django-1.6.1/docs/topics/class-based-views/generic-display.txt python-django-1.6.11/docs/topics/class-based-views/generic-display.txt
--- python-django-1.6.1/docs/topics/class-based-views/generic-display.txt 2013-08-13 17:17:35.000000000 +0000
+++ python-django-1.6.11/docs/topics/class-based-views/generic-display.txt 2015-03-18 23:50:43.000000000 +0000
@@ -1,8 +1,8 @@
.. _Generic views:
-=========================
-Class-based generic views
-=========================
+==================================
+Built-in Class-based generic views
+==================================
Writing Web applications can be monotonous, because we repeat certain patterns
again and again. Django tries to take away some of that monotony at the model
diff -Nru python-django-1.6.1/docs/topics/class-based-views/generic-editing.txt python-django-1.6.11/docs/topics/class-based-views/generic-editing.txt
--- python-django-1.6.1/docs/topics/class-based-views/generic-editing.txt 2013-08-13 17:17:35.000000000 +0000
+++ python-django-1.6.11/docs/topics/class-based-views/generic-editing.txt 2015-03-18 23:50:43.000000000 +0000
@@ -181,7 +181,7 @@
the foreign key relation to the model::
# models.py
- from django.contrib.auth import User
+ from django.contrib.auth.models import User
from django.db import models
class Author(models.Model):
diff -Nru python-django-1.6.1/docs/topics/class-based-views/intro.txt python-django-1.6.11/docs/topics/class-based-views/intro.txt
--- python-django-1.6.1/docs/topics/class-based-views/intro.txt 2013-08-13 17:17:09.000000000 +0000
+++ python-django-1.6.11/docs/topics/class-based-views/intro.txt 2015-03-18 23:50:43.000000000 +0000
@@ -71,7 +71,7 @@
In a class-based view, this would become::
from django.http import HttpResponse
- from django.views.generic.base import View
+ from django.views.generic import View
class MyView(View):
def get(self, request):
@@ -113,7 +113,7 @@
``greeting`` like this::
from django.http import HttpResponse
- from django.views.generic.base import View
+ from django.views.generic import View
class GreetingView(View):
greeting = "Good Day"
@@ -198,7 +198,7 @@
from django.http import HttpResponseRedirect
from django.shortcuts import render
- from django.views.generic.base import View
+ from django.views.generic import View
from .forms import MyForm
diff -Nru python-django-1.6.1/docs/topics/class-based-views/mixins.txt python-django-1.6.11/docs/topics/class-based-views/mixins.txt
--- python-django-1.6.1/docs/topics/class-based-views/mixins.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/class-based-views/mixins.txt 2015-03-18 23:50:43.000000000 +0000
@@ -119,7 +119,7 @@
:meth:`~django.views.generic.base.TemplateResponseMixin.get_template_names()`
as discussed above. It actually provides a fairly sophisticated set of options,
but the main one that most people are going to use is
-``/_detail.html``. The ``_detail`` part can be changed
+``/_detail.html``. The ``_detail`` part can be changed
by setting
:attr:`~django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix`
on a subclass to something else. (For instance, the :doc:`generic edit
@@ -165,7 +165,7 @@
above, this overrides ``get_template_names()`` to provide :meth:`a range of
options `,
with the most commonly-used being
-``/_list.html``, with the ``_list`` part again
+``/_list.html``, with the ``_list`` part again
being taken from the
:attr:`~django.views.generic.list.MultipleObjectTemplateResponseMixin.template_name_suffix`
attribute. (The date based generic views use suffixes such as ``_archive``,
diff -Nru python-django-1.6.1/docs/topics/db/aggregation.txt python-django-1.6.11/docs/topics/db/aggregation.txt
--- python-django-1.6.1/docs/topics/db/aggregation.txt 2013-08-13 17:17:35.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/aggregation.txt 2015-03-18 23:50:43.000000000 +0000
@@ -179,6 +179,17 @@
modified using any other ``QuerySet`` operation, including ``filter()``,
``order_by()``, or even additional calls to ``annotate()``.
+.. admonition:: If in doubt, inspect the SQL query!
+
+ In order to understand what happens in your query, consider inspecting the
+ ``query`` property of your ``QuerySet``.
+
+ For instance, combining multiple aggregations with ``annotate()`` will
+ yield the wrong results, as `multiple tables are cross joined`_,
+ resulting in duplicate row aggregations.
+
+.. _multiple tables are cross joined: https://code.djangoproject.com/ticket/10060
+
Joins and aggregates
====================
diff -Nru python-django-1.6.1/docs/topics/db/examples/one_to_one.txt python-django-1.6.11/docs/topics/db/examples/one_to_one.txt
--- python-django-1.6.1/docs/topics/db/examples/one_to_one.txt 2013-08-13 17:17:35.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/examples/one_to_one.txt 2015-03-18 23:50:43.000000000 +0000
@@ -64,10 +64,17 @@
p2 doesn't have an associated restaurant::
- >>> p2.restaurant
- Traceback (most recent call last):
- ...
- DoesNotExist: Restaurant matching query does not exist.
+ >>> from django.core.exceptions import ObjectDoesNotExist
+ >>> try:
+ >>> p2.restaurant
+ >>> except ObjectDoesNotExist:
+ >>> print("There is no restaurant here.")
+ There is no restaurant here.
+
+You can also use ``hasattr`` to avoid the need for exception catching::
+
+ >>> hasattr(p2, 'restaurant')
+ False
Set the place using assignment notation. Because place is the primary key on
Restaurant, the save will create a new restaurant::
diff -Nru python-django-1.6.1/docs/topics/db/managers.txt python-django-1.6.11/docs/topics/db/managers.txt
--- python-django-1.6.1/docs/topics/db/managers.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/managers.txt 2015-03-18 23:50:43.000000000 +0000
@@ -169,6 +169,11 @@
This example allows you to request ``Person.men.all()``, ``Person.women.all()``,
and ``Person.people.all()``, yielding predictable results.
+.. _default-managers:
+
+Default managers
+~~~~~~~~~~~~~~~~
+
If you use custom ``Manager`` objects, take note that the first ``Manager``
Django encounters (in the order in which they're defined in the model) has a
special status. Django interprets the first ``Manager`` defined in a class as
diff -Nru python-django-1.6.1/docs/topics/db/models.txt python-django-1.6.11/docs/topics/db/models.txt
--- python-django-1.6.1/docs/topics/db/models.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/models.txt 2015-03-18 23:50:43.000000000 +0000
@@ -212,6 +212,23 @@
unless you want to override the default primary-key behavior. For more,
see :ref:`automatic-primary-key-fields`.
+ The primary key field is read-only. If you change the value of the primary
+ key on an existing object and then save it, a new object will be created
+ alongside the old one. For example::
+
+ from django.db import models
+
+ class Fruit(models.Model):
+ name = models.CharField(max_length=100, primary_key=True)
+
+ .. code-block:: pycon
+
+ >>> fruit = Fruit.objects.create(name='Apple')
+ >>> fruit.name = 'Pear'
+ >>> fruit.save()
+ >>> Fruit.objects.values_list('name', flat=True)
+ ['Apple', 'Pear']
+
:attr:`~Field.unique`
If ``True``, this field must be unique throughout the table.
@@ -684,9 +701,6 @@
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
- address = models.CharField(max_length=100)
- city = models.CharField(max_length=50)
- state = models.CharField(max_length=2) # yes, this is America-centric
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
@@ -698,10 +712,6 @@
else:
return "Post-boomer"
- def is_midwestern(self):
- "Returns True if this person is from the Midwest."
- return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')
-
def _get_full_name(self):
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
@@ -818,11 +828,14 @@
=================
Model inheritance in Django works almost identically to the way normal
-class inheritance works in Python. The only decision you have to make
-is whether you want the parent models to be models in their own right
-(with their own database tables), or if the parents are just holders
-of common information that will only be visible through the child
-models.
+class inheritance works in Python, but the basics at the beginning of the page
+should still be followed. That means the base class should subclass
+:class:`django.db.models.Model`.
+
+The only decision you have to make is whether you want the parent models to be
+models in their own right (with their own database tables), or if the parents
+are just holders of common information that will only be visible through the
+child models.
There are three styles of inheritance that are possible in Django.
@@ -1048,19 +1061,27 @@
default :attr:`~django.db.models.ForeignKey.related_name` value for
:class:`~django.db.models.ForeignKey` and
:class:`~django.db.models.ManyToManyField` relations. If you
-are putting those types of relations on a subclass of another model,
-you **must** specify the
-:attr:`~django.db.models.ForeignKey.related_name` attribute on each
-such field. If you forget, Django will raise an error when you run
-:djadmin:`validate` or :djadmin:`syncdb`.
+are putting those types of relations on a subclass of the parent model, you
+**must** specify the :attr:`~django.db.models.ForeignKey.related_name`
+attribute on each such field. If you forget, Django will raise a validation
+error.
For example, using the above ``Place`` class again, let's create another
subclass with a :class:`~django.db.models.ManyToManyField`::
class Supplier(Place):
- # Must specify related_name on all relations.
- customers = models.ManyToManyField(Restaurant, related_name='provider')
+ customers = models.ManyToManyField(Place)
+
+This results in the error::
+
+ Reverse query name for 'Supplier.customers' clashes with reverse query
+ name for 'Supplier.place_ptr'.
+ HINT: Add or change a related_name argument to the definition for
+ 'Supplier.customers' or 'Supplier.place_ptr'.
+
+Adding ``related_name`` to the ``customers`` field as follows would resolve the
+error: ``models.ManyToManyField(Place, related_name='provider')``.
Specifying the parent link field
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1285,3 +1306,9 @@
Django will raise a :exc:`~django.core.exceptions.FieldError` if you override
any model field in any ancestor model.
+
+.. seealso::
+
+ :doc:`The Models Reference `
+ Covers all the model related APIs including model fields, related
+ objects, and ``QuerySet``.
diff -Nru python-django-1.6.1/docs/topics/db/multi-db.txt python-django-1.6.11/docs/topics/db/multi-db.txt
--- python-django-1.6.1/docs/topics/db/multi-db.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/multi-db.txt 2015-03-18 23:50:43.000000000 +0000
@@ -695,6 +695,6 @@
.. warning::
- If you're synchronizing content types to more that one database, be aware
+ If you're synchronizing content types to more than one database, be aware
that their primary keys may not match across databases. This may result in
data corruption or data loss.
diff -Nru python-django-1.6.1/docs/topics/db/optimization.txt python-django-1.6.11/docs/topics/db/optimization.txt
--- python-django-1.6.1/docs/topics/db/optimization.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/optimization.txt 2015-03-18 23:50:43.000000000 +0000
@@ -36,11 +36,19 @@
...including:
-* Indexes. This is a number one priority, *after* you have determined from
+* Indexes_. This is a number one priority, *after* you have determined from
profiling what indexes should be added. Use
- :attr:`django.db.models.Field.db_index` or
+ :attr:`Field.db_index ` or
:attr:`Meta.index_together ` to add
- these from Django.
+ these from Django. Consider adding indexes to fields that you frequently
+ query using :meth:`~django.db.models.query.QuerySet.filter()`,
+ :meth:`~django.db.models.query.QuerySet.exclude()`,
+ :meth:`~django.db.models.query.QuerySet.order_by()`, etc. as indexes may help
+ to speed up lookups. Note that determining the best indexes is a complex
+ database-dependent topic that will depend on your particular application.
+ The overhead of maintaining an index may outweigh any gains in query speed.
+
+.. _Indexes: http://en.wikipedia.org/wiki/Database_index
* Appropriate use of field types.
diff -Nru python-django-1.6.1/docs/topics/db/queries.txt python-django-1.6.11/docs/topics/db/queries.txt
--- python-django-1.6.1/docs/topics/db/queries.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/queries.txt 2015-03-18 23:50:43.000000000 +0000
@@ -93,8 +93,8 @@
Given a ``Blog`` instance ``b5`` that has already been saved to the database,
this example changes its name and updates its record in the database::
- >> b5.name = 'New name'
- >> b5.save()
+ >>> b5.name = 'New name'
+ >>> b5.save()
This performs an ``UPDATE`` SQL statement behind the scenes. Django doesn't hit
the database until you explicitly call :meth:`~django.db.models.Model.save`.
@@ -254,9 +254,9 @@
Example::
- >> q1 = Entry.objects.filter(headline__startswith="What")
- >> q2 = q1.exclude(pub_date__gte=datetime.date.today())
- >> q3 = q1.filter(pub_date__gte=datetime.date.today())
+ >>> q1 = Entry.objects.filter(headline__startswith="What")
+ >>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
+ >>> q3 = q1.filter(pub_date__gte=datetime.date.today())
These three ``QuerySets`` are separate. The first is a base
:class:`~django.db.models.query.QuerySet` containing all entries that contain a
@@ -397,7 +397,9 @@
>>> Entry.objects.filter(pub_date__lte='2006-01-01')
-translates (roughly) into the following SQL::
+translates (roughly) into the following SQL:
+
+.. code-block:: sql
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
diff -Nru python-django-1.6.1/docs/topics/db/sql.txt python-django-1.6.11/docs/topics/db/sql.txt
--- python-django-1.6.1/docs/topics/db/sql.txt 2013-08-13 17:17:35.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/sql.txt 2015-03-18 23:50:43.000000000 +0000
@@ -13,6 +13,14 @@
__ `performing raw queries`_
__ `executing custom SQL directly`_
+.. warning::
+
+ You should be very careful whenever you write raw SQL. Every time you use
+ it, you should properly escape any parameters that the user can control
+ by using ``params`` in order to protect against SQL injection attacks.
+ Please read more about :ref:`SQL injection protection
+ `.
+
.. _executing-raw-queries:
Performing raw queries
@@ -23,11 +31,12 @@
.. method:: Manager.raw(raw_query, params=None, translations=None)
-This method method takes a raw SQL query, executes it, and returns a
+This method takes a raw SQL query, executes it, and returns a
``django.db.models.query.RawQuerySet`` instance. This ``RawQuerySet`` instance
-can be iterated over just like an normal QuerySet to provide object instances.
+can be iterated over just like a normal
+:class:`~django.db.models.query.QuerySet` to provide object instances.
-This is best illustrated with an example. Suppose you've got the following model::
+This is best illustrated with an example. Suppose you have the following model::
class Person(models.Model):
first_name = models.CharField(...)
@@ -66,6 +75,27 @@
database, but does nothing to enforce that. If the query does not
return rows, a (possibly cryptic) error will result.
+.. warning::
+
+ If you are performing queries on MySQL, note that MySQL's silent type coercion
+ may cause unexpected results when mixing types. If you query on a string
+ type column, but with an integer value, MySQL will coerce the types of all values
+ in the table to an integer before performing the comparison. For example, if your
+ table contains the values ``'abc'``, ``'def'`` and you query for ``WHERE mycolumn=0``,
+ both rows will match. To prevent this, perform the correct typecasting
+ before using the value in a query.
+
+.. warning::
+
+ While a ``RawQuerySet`` instance can be iterated over like a normal
+ :class:`~django.db.models.query.QuerySet`, ``RawQuerySet`` doesn't
+ implement all methods you can use with ``QuerySet``. For example,
+ ``__bool__()`` and ``__len__()`` are not defined in ``RawQuerySet``, and
+ thus all ``RawQuerySet`` instances are considered ``True``. The reason
+ these methods are not implemented in ``RawQuerySet`` is that implementing
+ them without internal caching would be a performance drawback and adding
+ such caching would be backward incompatible.
+
Mapping query fields to model fields
------------------------------------
@@ -108,7 +138,7 @@
>>> first_person = Person.objects.raw('SELECT * from myapp_person')[0]
However, the indexing and slicing are not performed at the database level. If
-you have a big amount of ``Person`` objects in your database, it is more
+you have a large number of ``Person`` objects in your database, it is more
efficient to limit the query at the SQL level::
>>> first_person = Person.objects.raw('SELECT * from myapp_person LIMIT 1')[0]
@@ -173,7 +203,7 @@
placeholders will be replaced with parameters from the ``params``
argument.
-.. note:: Dictionary params not supported with SQLite
+.. note::
Dictionary params are not supported with the SQLite backend; with
this backend, you must pass parameters as a list.
diff -Nru python-django-1.6.1/docs/topics/db/transactions.txt python-django-1.6.11/docs/topics/db/transactions.txt
--- python-django-1.6.1/docs/topics/db/transactions.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/db/transactions.txt 2015-03-18 23:50:43.000000000 +0000
@@ -13,14 +13,17 @@
-------------------------------------
Django's default behavior is to run in autocommit mode. Each query is
-immediately committed to the database. :ref:`See below for details
-`.
+immediately committed to the database, unless a transaction is active.
+:ref:`See below for details `.
Django uses transactions or savepoints automatically to guarantee the
integrity of ORM operations that require multiple queries, especially
:ref:`delete() ` and :ref:`update()
` queries.
+Django's :class:`~django.test.TestCase` class also wraps each test in a
+transaction for performance reasons.
+
.. versionchanged:: 1.6
Previous version of Django featured :ref:`a more complicated default
@@ -219,7 +222,7 @@
Open transactions have a performance cost for your database server. To
minimize this overhead, keep your transactions as short as possible. This
- is especially important of you're using :func:`atomic` in long-running
+ is especially important if you're using :func:`atomic` in long-running
processes, outside of Django's request / response cycle.
Autocommit
@@ -231,13 +234,15 @@
--------------------------
In the SQL standards, each SQL query starts a transaction, unless one is
-already in progress. Such transactions must then be committed or rolled back.
+already active. Such transactions must then be explicitly committed or rolled
+back.
This isn't always convenient for application developers. To alleviate this
problem, most databases provide an autocommit mode. When autocommit is turned
-on, each SQL query is wrapped in its own transaction. In other words, the
-transaction is not only automatically started, but also automatically
-committed.
+on and no transaction is active, each SQL query gets wrapped in its own
+transaction. In other words, not only does each such query start a
+transaction, but the transaction also gets automatically committed or rolled
+back, depending on whether the query succeeded.
:pep:`249`, the Python Database API Specification v2.0, requires autocommit to
be initially turned off. Django overrides this default and turns autocommit
@@ -469,7 +474,7 @@
as they're called. If your MySQL setup *does* support transactions, Django
will handle transactions as explained in this document.
-.. _information on MySQL transactions: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html
+.. _information on MySQL transactions: http://dev.mysql.com/doc/refman/5.6/en/sql-syntax-transactions.html
Handling exceptions within PostgreSQL transactions
--------------------------------------------------
@@ -517,8 +522,8 @@
transaction. For example::
a.save() # Succeeds, and never undone by savepoint rollback
+ sid = transaction.savepoint()
try:
- sid = transaction.savepoint()
b.save() # Could throw exception
transaction.savepoint_commit(sid)
except IntegrityError:
@@ -597,7 +602,7 @@
rollbacks, and switches back to auto mode.
So :func:`commit_on_success` really has two effects: it changes the
-transaction state and it defines an transaction block. Nesting will give the
+transaction state and it defines a transaction block. Nesting will give the
expected results in terms of transaction state, but not in terms of
transaction semantics. Most often, the inner block will commit, breaking the
atomicity of the outer block.
@@ -717,7 +722,10 @@
If you were relying on "automatic transactions" to provide locking between
:meth:`~django.db.models.query.QuerySet.select_for_update` and a subsequent
write operation — an extremely fragile design, but nonetheless possible — you
-must wrap the relevant code in :func:`atomic`.
+must wrap the relevant code in :func:`atomic`. Since Django 1.6.3, executing
+a query with :meth:`~django.db.models.query.QuerySet.select_for_update` in
+autocommit mode will raise a
+:exc:`~django.db.transaction.TransactionManagementError`.
Using a high isolation level
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff -Nru python-django-1.6.1/docs/topics/email.txt python-django-1.6.11/docs/topics/email.txt
--- python-django-1.6.1/docs/topics/email.txt 2013-12-12 19:37:59.000000000 +0000
+++ python-django-1.6.11/docs/topics/email.txt 2015-03-18 23:50:43.000000000 +0000
@@ -174,6 +174,7 @@
"/contact/thanks/" when it's done::
from django.core.mail import send_mail, BadHeaderError
+ from django.http import HttpResponse, HttpResponseRedirect
def send_email(request):
subject = request.POST.get('subject', '')
@@ -275,7 +276,8 @@
specified when the email was constructed, that connection will be used.
Otherwise, an instance of the default backend will be instantiated and
used. If the keyword argument ``fail_silently`` is ``True``, exceptions
- raised while sending the message will be quashed.
+ raised while sending the message will be quashed. An empty list of
+ recipients will not raise an exception.
* ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a
subclass of Python's ``email.MIMEText.MIMEText`` class) or a
@@ -364,7 +366,7 @@
The email backend class has the following methods:
-* ``open()`` instantiates an long-lived email-sending connection.
+* ``open()`` instantiates a long-lived email-sending connection.
* ``close()`` closes the current email-sending connection.
@@ -559,8 +561,8 @@
connection.close()
-Testing email sending
-=====================
+Configuring email for development
+=================================
There are times when you do not want Django to send emails at
all. For example, while developing a Web site, you probably don't want
@@ -568,13 +570,13 @@
emails will be sent to the right people under the right conditions,
and that those emails will contain the correct content.
-The easiest way to test your project's use of email is to use the ``console``
-email backend. This backend redirects all email to stdout, allowing you to
-inspect the content of mail.
-
-The ``file`` email backend can also be useful during development -- this backend
-dumps the contents of every SMTP connection to a file that can be inspected
-at your leisure.
+The easiest way to configure email for local development is to use the
+:ref:`console ` email backend. This backend
+redirects all email to stdout, allowing you to inspect the content of mail.
+
+The :ref:`file ` email backend can also be useful
+during development -- this backend dumps the contents of every SMTP connection
+to a file that can be inspected at your leisure.
Another approach is to use a "dumb" SMTP server that receives the emails
locally and displays them to the terminal, but does not actually send
@@ -585,7 +587,8 @@
This command will start a simple SMTP server listening on port 1025 of
localhost. This server simply prints to standard output all email headers and
the email body. You then only need to set the :setting:`EMAIL_HOST` and
-:setting:`EMAIL_PORT` accordingly, and you are set.
+:setting:`EMAIL_PORT` accordingly. For a more detailed discussion of SMTP
+server options, see the Python documentation for the :mod:`smtpd` module.
-For a more detailed discussion of testing and processing of emails locally,
-see the Python documentation for the :mod:`smtpd` module.
+For information about unit-testing the sending of emails in your application,
+see the :ref:`topics-testing-email` section of the testing documentation.
diff -Nru python-django-1.6.1/docs/topics/forms/formsets.txt python-django-1.6.11/docs/topics/forms/formsets.txt
--- python-django-1.6.1/docs/topics/forms/formsets.txt 2013-08-13 17:17:35.000000000 +0000
+++ python-django-1.6.11/docs/topics/forms/formsets.txt 2015-03-18 23:50:43.000000000 +0000
@@ -88,8 +88,7 @@
------------------------------------
The ``max_num`` parameter to :func:`~django.forms.formsets.formset_factory`
-gives you the ability to limit the maximum number of empty forms the formset
-will display::
+gives you the ability to limit the number of forms the formset will display::
>>> from django.forms.formsets import formset_factory
>>> from myapp.forms import ArticleForm
@@ -100,16 +99,22 @@
-If the value of ``max_num`` is greater than the number of existing
-objects, up to ``extra`` additional blank forms will be added to the formset,
-so long as the total number of forms does not exceed ``max_num``.
+If the value of ``max_num`` is greater than the number of existing items in the
+initial data, up to ``extra`` additional blank forms will be added to the
+formset, so long as the total number of forms does not exceed ``max_num``. For
+example, if ``extra=2`` and ``max_num=2`` and the formset is initialized with
+one ``initial`` item, a form for the initial item and one blank form will be
+displayed.
+
+If the number of items in the initial data exceeds ``max_num``, all initial
+data forms will be displayed regardless of the value of ``max_num`` and no
+extra forms will be displayed. For example, if ``extra=3`` and ``max_num=1``
+and the formset is initialized with two initial items, two forms with the
+initial data will be displayed.
A ``max_num`` value of ``None`` (the default) puts a high limit on the number
of forms displayed (1000). In practice this is equivalent to no limit.
-If the number of forms in the initial data exceeds ``max_num``, all initial
-data forms will be displayed regardless. (No extra forms will be displayed.)
-
By default, ``max_num`` only affects how many forms are displayed and does not
affect validation. If ``validate_max=True`` is passed to the
:func:`~django.forms.formsets.formset_factory`, then ``max_num`` will affect
@@ -166,7 +171,7 @@
.. currentmodule:: django.forms.formsets.BaseFormSet
-.. method:: total_error_count(self)
+.. method:: total_error_count()
.. versionadded:: 1.6
@@ -555,9 +560,9 @@