[Python-modules-commits] [python-django] 09/16: Import python-django_1.7.10.orig.tar.gz

Brian May bam at moszumanska.debian.org
Sun Oct 11 02:44:12 UTC 2015


This is an automated email from the git hooks/post-receive script.

bam pushed a commit to branch debian/sid
in repository python-django.

commit e2f348a8f03d3f935e0233d7a747be5fd99c796f
Author: Brian May <brian at microcomaustralia.com.au>
Date:   Sun Oct 11 13:09:53 2015 +1100

    Import python-django_1.7.10.orig.tar.gz
---
 Django.egg-info/PKG-INFO                      |  2 +-
 Django.egg-info/SOURCES.txt                   |  2 +
 PKG-INFO                                      |  2 +-
 django/__init__.py                            |  2 +-
 django/contrib/gis/geoip/tests.py             | 20 ++++----
 django/contrib/sessions/backends/base.py      |  9 +++-
 django/contrib/sessions/backends/cached_db.py |  2 +-
 django/contrib/sessions/middleware.py         | 50 +++++++++++--------
 django/contrib/sessions/tests.py              | 70 +++++++++++++++++++++++++++
 docs/howto/outputting-pdf.txt                 |  2 +-
 docs/ref/contrib/admin/index.txt              |  2 +-
 docs/ref/contrib/flatpages.txt                |  2 +-
 docs/ref/contrib/gis/geoquerysets.txt         |  5 +-
 docs/ref/middleware.txt                       |  2 +-
 docs/releases/1.4.22.txt                      | 29 +++++++++++
 docs/releases/1.7.10.txt                      | 25 ++++++++++
 docs/releases/index.txt                       |  2 +
 docs/topics/http/sessions.txt                 | 14 ++++--
 setup.cfg                                     |  2 +-
 19 files changed, 195 insertions(+), 49 deletions(-)

diff --git a/Django.egg-info/PKG-INFO b/Django.egg-info/PKG-INFO
index cbffe51..ee0cc12 100644
--- a/Django.egg-info/PKG-INFO
+++ b/Django.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Django
-Version: 1.7.9
+Version: 1.7.10
 Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
 Home-page: http://www.djangoproject.com/
 Author: Django Software Foundation
diff --git a/Django.egg-info/SOURCES.txt b/Django.egg-info/SOURCES.txt
index 34213ff..be01607 100644
--- a/Django.egg-info/SOURCES.txt
+++ b/Django.egg-info/SOURCES.txt
@@ -3988,6 +3988,7 @@ docs/releases/1.4.19.txt
 docs/releases/1.4.2.txt
 docs/releases/1.4.20.txt
 docs/releases/1.4.21.txt
+docs/releases/1.4.22.txt
 docs/releases/1.4.3.txt
 docs/releases/1.4.4.txt
 docs/releases/1.4.5.txt
@@ -4022,6 +4023,7 @@ docs/releases/1.6.8.txt
 docs/releases/1.6.9.txt
 docs/releases/1.6.txt
 docs/releases/1.7.1.txt
+docs/releases/1.7.10.txt
 docs/releases/1.7.2.txt
 docs/releases/1.7.3.txt
 docs/releases/1.7.4.txt
diff --git a/PKG-INFO b/PKG-INFO
index cbffe51..ee0cc12 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Django
-Version: 1.7.9
+Version: 1.7.10
 Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
 Home-page: http://www.djangoproject.com/
 Author: Django Software Foundation
diff --git a/django/__init__.py b/django/__init__.py
index 8733754..42dcf4a 100644
--- a/django/__init__.py
+++ b/django/__init__.py
@@ -1,4 +1,4 @@
-VERSION = (1, 7, 9, 'final', 0)
+VERSION = (1, 7, 10, 'final', 0)
 
 
 def get_version(*args, **kwargs):
diff --git a/django/contrib/gis/geoip/tests.py b/django/contrib/gis/geoip/tests.py
index 9631a19..7d64801 100644
--- a/django/contrib/gis/geoip/tests.py
+++ b/django/contrib/gis/geoip/tests.py
@@ -27,6 +27,8 @@ if HAS_GEOS:
 @skipUnless(HAS_GEOIP and getattr(settings, "GEOIP_PATH", None),
     "GeoIP is required along with the GEOIP_PATH setting.")
 class GeoIPTest(unittest.TestCase):
+    addr = '128.249.1.1'
+    fqdn = 'tmc.edu'
 
     def test01_init(self):
         "Testing GeoIP initialization."
@@ -72,10 +74,7 @@ class GeoIPTest(unittest.TestCase):
         "Testing GeoIP country querying methods."
         g = GeoIP(city='<foo>')
 
-        fqdn = 'www.google.com'
-        addr = '12.215.42.19'
-
-        for query in (fqdn, addr):
+        for query in (self.fqdn, self.addr):
             for func in (g.country_code, g.country_code_by_addr, g.country_code_by_name):
                 self.assertEqual('US', func(query))
             for func in (g.country_name, g.country_name_by_addr, g.country_name_by_name):
@@ -88,9 +87,7 @@ class GeoIPTest(unittest.TestCase):
         "Testing GeoIP city querying methods."
         g = GeoIP(country='<foo>')
 
-        addr = '128.249.1.1'
-        fqdn = 'tmc.edu'
-        for query in (fqdn, addr):
+        for query in (self.fqdn, self.addr):
             # Country queries should still work.
             for func in (g.country_code, g.country_code_by_addr, g.country_code_by_name):
                 self.assertEqual('US', func(query))
@@ -117,7 +114,8 @@ class GeoIPTest(unittest.TestCase):
     def test05_unicode_response(self):
         "Testing that GeoIP strings are properly encoded, see #16553."
         g = GeoIP()
-        d = g.city("www.osnabrueck.de")
-        self.assertEqual('Osnabrück', d['city'])
-        d = g.country('200.7.49.81')
-        self.assertEqual('Curaçao', d['country_name'])
+        d = g.city("duesseldorf.de")
+        self.assertEqual('Düsseldorf', d['city'])
+        d = g.country('200.26.205.1')
+        # Some databases have only unaccented countries
+        self.assertIn(d['country_name'], ('Curaçao', 'Curacao'))
diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
index a77a25b..c7819b2 100644
--- a/django/contrib/sessions/backends/base.py
+++ b/django/contrib/sessions/backends/base.py
@@ -142,6 +142,13 @@ class SessionBase(object):
         self.accessed = True
         self.modified = True
 
+    def is_empty(self):
+        "Returns True when there is no session_key and the session is empty"
+        try:
+            return not bool(self._session_key) and not self._session_cache
+        except AttributeError:
+            return True
+
     def _get_new_session_key(self):
         "Returns session key that isn't being used."
         while True:
@@ -268,7 +275,7 @@ class SessionBase(object):
         """
         self.clear()
         self.delete()
-        self.create()
+        self._session_key = None
 
     def cycle_key(self):
         """
diff --git a/django/contrib/sessions/backends/cached_db.py b/django/contrib/sessions/backends/cached_db.py
index 5cc6f79..5a7664b 100644
--- a/django/contrib/sessions/backends/cached_db.py
+++ b/django/contrib/sessions/backends/cached_db.py
@@ -79,7 +79,7 @@ class SessionStore(DBStore):
         """
         self.clear()
         self.delete(self.session_key)
-        self.create()
+        self._session_key = None
 
 
 # At bottom to avoid circular import
diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py
index 211ef57..54d80f7 100644
--- a/django/contrib/sessions/middleware.py
+++ b/django/contrib/sessions/middleware.py
@@ -18,32 +18,40 @@ class SessionMiddleware(object):
     def process_response(self, request, response):
         """
         If request.session was modified, or if the configuration is to save the
-        session every time, save the changes and set a session cookie.
+        session every time, save the changes and set a session cookie or delete
+        the session cookie if the session has been emptied.
         """
         try:
             accessed = request.session.accessed
             modified = request.session.modified
+            empty = request.session.is_empty()
         except AttributeError:
             pass
         else:
-            if accessed:
-                patch_vary_headers(response, ('Cookie',))
-            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
-                if request.session.get_expire_at_browser_close():
-                    max_age = None
-                    expires = None
-                else:
-                    max_age = request.session.get_expiry_age()
-                    expires_time = time.time() + max_age
-                    expires = cookie_date(expires_time)
-                # Save the session data and refresh the client cookie.
-                # Skip session save for 500 responses, refs #3881.
-                if response.status_code != 500:
-                    request.session.save()
-                    response.set_cookie(settings.SESSION_COOKIE_NAME,
-                            request.session.session_key, max_age=max_age,
-                            expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
-                            path=settings.SESSION_COOKIE_PATH,
-                            secure=settings.SESSION_COOKIE_SECURE or None,
-                            httponly=settings.SESSION_COOKIE_HTTPONLY or None)
+            # First check if we need to delete this cookie.
+            # The session should be deleted only if the session is entirely empty
+            if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
+                response.delete_cookie(settings.SESSION_COOKIE_NAME,
+                    domain=settings.SESSION_COOKIE_DOMAIN)
+            else:
+                if accessed:
+                    patch_vary_headers(response, ('Cookie',))
+                if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
+                    if request.session.get_expire_at_browser_close():
+                        max_age = None
+                        expires = None
+                    else:
+                        max_age = request.session.get_expiry_age()
+                        expires_time = time.time() + max_age
+                        expires = cookie_date(expires_time)
+                    # Save the session data and refresh the client cookie.
+                    # Skip session save for 500 responses, refs #3881.
+                    if response.status_code != 500:
+                        request.session.save()
+                        response.set_cookie(settings.SESSION_COOKIE_NAME,
+                                request.session.session_key, max_age=max_age,
+                                expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
+                                path=settings.SESSION_COOKIE_PATH,
+                                secure=settings.SESSION_COOKIE_SECURE or None,
+                                httponly=settings.SESSION_COOKIE_HTTPONLY or None)
         return response
diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py
index 6e042c7..578b6f4 100644
--- a/django/contrib/sessions/tests.py
+++ b/django/contrib/sessions/tests.py
@@ -159,6 +159,7 @@ class SessionTestsMixin(object):
         self.session.flush()
         self.assertFalse(self.session.exists(prev_key))
         self.assertNotEqual(self.session.session_key, prev_key)
+        self.assertIsNone(self.session.session_key)
         self.assertTrue(self.session.modified)
         self.assertTrue(self.session.accessed)
 
@@ -589,6 +590,75 @@ class SessionMiddlewareTests(unittest.TestCase):
         # Check that the value wasn't saved above.
         self.assertNotIn('hello', request.session.load())
 
+    def test_session_delete_on_end(self):
+        request = RequestFactory().get('/')
+        response = HttpResponse('Session test')
+        middleware = SessionMiddleware()
+
+        # Before deleting, there has to be an existing cookie
+        request.COOKIES[settings.SESSION_COOKIE_NAME] = 'abc'
+
+        # Simulate a request that ends the session
+        middleware.process_request(request)
+        request.session.flush()
+
+        # Handle the response through the middleware
+        response = middleware.process_response(request, response)
+
+        # Check that the cookie was deleted, not recreated.
+        # A deleted cookie header looks like:
+        #  Set-Cookie: sessionid=; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/
+        self.assertEqual(
+            'Set-Cookie: {0}=; expires=Thu, 01-Jan-1970 00:00:00 GMT; '
+            'Max-Age=0; Path=/'.format(settings.SESSION_COOKIE_NAME),
+            str(response.cookies[settings.SESSION_COOKIE_NAME])
+        )
+
+    @override_settings(SESSION_COOKIE_DOMAIN='.example.local')
+    def test_session_delete_on_end_with_custom_domain(self):
+        request = RequestFactory().get('/')
+        response = HttpResponse('Session test')
+        middleware = SessionMiddleware()
+
+        # Before deleting, there has to be an existing cookie
+        request.COOKIES[settings.SESSION_COOKIE_NAME] = 'abc'
+
+        # Simulate a request that ends the session
+        middleware.process_request(request)
+        request.session.flush()
+
+        # Handle the response through the middleware
+        response = middleware.process_response(request, response)
+
+        # Check that the cookie was deleted, not recreated.
+        # A deleted cookie header with a custom domain looks like:
+        #  Set-Cookie: sessionid=; Domain=.example.local;
+        #              expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/
+        self.assertEqual(
+            'Set-Cookie: {}=; Domain=.example.local; expires=Thu, '
+            '01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/'.format(
+                settings.SESSION_COOKIE_NAME,
+            ),
+            str(response.cookies[settings.SESSION_COOKIE_NAME])
+        )
+
+    def test_flush_empty_without_session_cookie_doesnt_set_cookie(self):
+        request = RequestFactory().get('/')
+        response = HttpResponse('Session test')
+        middleware = SessionMiddleware()
+
+        # Simulate a request that ends the session
+        middleware.process_request(request)
+        request.session.flush()
+
+        # Handle the response through the middleware
+        response = middleware.process_response(request, response)
+
+        # A cookie should not be set.
+        self.assertEqual(response.cookies, {})
+        # The session is accessed so "Vary: Cookie" should be set.
+        self.assertEqual(response['Vary'], 'Cookie')
+
 
 class CookieSessionTests(SessionTestsMixin, TestCase):
 
diff --git a/docs/howto/outputting-pdf.txt b/docs/howto/outputting-pdf.txt
index 6e83e79..774ffc2 100644
--- a/docs/howto/outputting-pdf.txt
+++ b/docs/howto/outputting-pdf.txt
@@ -155,7 +155,7 @@ Further resources
 
 .. _PDFlib: http://www.pdflib.org/
 .. _`Pisa XHTML2PDF`: http://www.xhtml2pdf.com/
-.. _HTMLdoc: http://www.htmldoc.org/
+.. _HTMLdoc: https://www.msweet.org/projects.php?Z1
 
 Other formats
 =============
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index 68efb0d..4e8b6d0 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -1694,7 +1694,7 @@ templates used by the :class:`ModelAdmin` views:
     documentation for more details. One difference is that the level may be
     passed as a string label in addition to integer/constant.
 
-.. method:: ModelAdmin.get_paginator(queryset, per_page, orphans=0, allow_empty_first_page=True)
+.. method:: ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)
 
     Returns an instance of the paginator to use for this view. By default,
     instantiates an instance of :attr:`paginator`.
diff --git a/docs/ref/contrib/flatpages.txt b/docs/ref/contrib/flatpages.txt
index be9fe0c..e3f645f 100644
--- a/docs/ref/contrib/flatpages.txt
+++ b/docs/ref/contrib/flatpages.txt
@@ -192,7 +192,7 @@ Via the Python API
     If you add or modify flatpages via your own code, you will likely want to
     check for duplicate flatpage URLs within the same site. The flatpage form
     used in the admin performs this validation check, and can be imported from
-    ``django.contrib.flatpages.forms.FlatPageForm`` and used in your own
+    ``django.contrib.flatpages.forms.FlatpageForm`` and used in your own
     views.
 
 Flatpage templates
diff --git a/docs/ref/contrib/gis/geoquerysets.txt b/docs/ref/contrib/gis/geoquerysets.txt
index 6d4b793..b992c41 100644
--- a/docs/ref/contrib/gis/geoquerysets.txt
+++ b/docs/ref/contrib/gis/geoquerysets.txt
@@ -220,6 +220,8 @@ MySQL       ``MBRDisjoint(poly, geom)``
 SpatiaLite  ``Disjoint(poly, geom)``
 ==========  =================================================
 
+.. fieldlookup:: equals
+
 equals
 ------
 
@@ -634,9 +636,6 @@ Oracle      ``SDO_WITHIN_DISTANCE(poly, geom, 5)``
 
     This lookup is not available on SpatiaLite.
 
-.. fieldlookup:: equals
-
-
 ``GeoQuerySet`` Methods
 =======================
 
diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt
index 7f82b98..776ed85 100644
--- a/docs/ref/middleware.txt
+++ b/docs/ref/middleware.txt
@@ -287,7 +287,7 @@ Here are some hints about the ordering of various Django middleware classes:
 #. :class:`~django.middleware.locale.LocaleMiddleware`
 
    One of the topmost, after ``SessionMiddleware`` (uses session data) and
-   ``CacheMiddleware`` (modifies ``Vary`` header).
+   ``UpdateCacheMiddleware`` (modifies ``Vary`` header).
 
 #. :class:`~django.middleware.common.CommonMiddleware`
 
diff --git a/docs/releases/1.4.22.txt b/docs/releases/1.4.22.txt
new file mode 100644
index 0000000..9f81774
--- /dev/null
+++ b/docs/releases/1.4.22.txt
@@ -0,0 +1,29 @@
+===========================
+Django 1.4.22 release notes
+===========================
+
+*August 18, 2015*
+
+Django 1.4.22 fixes a security issue in 1.4.21.
+
+It also fixes support with pip 7+ by disabling wheel support. Older versions
+of 1.4 would silently build a broken wheel when installed with those versions
+of pip.
+
+Denial-of-service possibility in ``logout()`` view by filling session store
+===========================================================================
+
+Previously, a session could be created when anonymously accessing the
+:func:`django.contrib.auth.views.logout` view (provided it wasn't decorated
+with :func:`~django.contrib.auth.decorators.login_required` as done in the
+admin). This could allow an attacker to easily create many new session records
+by sending repeated requests, potentially filling up the session store or
+causing other users' session records to be evicted.
+
+The :class:`~django.contrib.sessions.middleware.SessionMiddleware` has been
+modified to no longer create empty session records.
+
+Additionally, the ``contrib.sessions.backends.base.SessionBase.flush()`` and
+``cache_db.SessionStore.flush()`` methods have been modified to avoid creating
+a new empty session. Maintainers of third-party session backends should check
+if the same vulnerability is present in their backend and correct it if so.
diff --git a/docs/releases/1.7.10.txt b/docs/releases/1.7.10.txt
new file mode 100644
index 0000000..38af4a4
--- /dev/null
+++ b/docs/releases/1.7.10.txt
@@ -0,0 +1,25 @@
+===========================
+Django 1.7.10 release notes
+===========================
+
+*August 18, 2015*
+
+Django 1.7.10 fixes a security issue in 1.7.9.
+
+Denial-of-service possibility in ``logout()`` view by filling session store
+===========================================================================
+
+Previously, a session could be created when anonymously accessing the
+:func:`django.contrib.auth.views.logout` view (provided it wasn't decorated
+with :func:`~django.contrib.auth.decorators.login_required` as done in the
+admin). This could allow an attacker to easily create many new session records
+by sending repeated requests, potentially filling up the session store or
+causing other users' session records to be evicted.
+
+The :class:`~django.contrib.sessions.middleware.SessionMiddleware` has been
+modified to no longer create empty session records.
+
+Additionally, the ``contrib.sessions.backends.base.SessionBase.flush()`` and
+``cache_db.SessionStore.flush()`` methods have been modified to avoid creating
+a new empty session. Maintainers of third-party session backends should check
+if the same vulnerability is present in their backend and correct it if so.
diff --git a/docs/releases/index.txt b/docs/releases/index.txt
index c88f29f..a1447ea 100644
--- a/docs/releases/index.txt
+++ b/docs/releases/index.txt
@@ -25,6 +25,7 @@ versions of the documentation contain the release notes for any later releases.
 .. toctree::
    :maxdepth: 1
 
+   1.7.10
    1.7.9
    1.7.8
    1.7.7
@@ -78,6 +79,7 @@ versions of the documentation contain the release notes for any later releases.
 .. toctree::
    :maxdepth: 1
 
+   1.4.22
    1.4.21
    1.4.20
    1.4.19
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
index 85431b5..f261a27 100644
--- a/docs/topics/http/sessions.txt
+++ b/docs/topics/http/sessions.txt
@@ -226,12 +226,18 @@ You can edit it multiple times.
 
     .. method:: flush()
 
-      Delete the current session data from the session and regenerate the
-      session key value that is sent back to the user in the cookie. This is
-      used if you want to ensure that the previous session data can't be
-      accessed again from the user's browser (for example, the
+      Deletes the current session data from the session and deletes the session
+      cookie. This is used if you want to ensure that the previous session data
+      can't be accessed again from the user's browser (for example, the
       :func:`django.contrib.auth.logout()` function calls it).
 
+      .. versionchanged:: 1.7.10
+
+          Deletion of the session cookie was added. Previously, the behavior
+          was to regenerate the session key value that was sent back to the
+          user in the cookie, but this could be a denial-of-service
+          vulnerability.
+
     .. method:: set_test_cookie()
 
       Sets a test cookie to determine whether the user's browser supports
diff --git a/setup.cfg b/setup.cfg
index 36c9d82..0c94c1d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -14,7 +14,7 @@ license-file = LICENSE
 universal = 1
 
 [egg_info]
+tag_svn_revision = 0
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django.git



More information about the Python-modules-commits mailing list