Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Upgrade Django 1.4.5
Browse files Browse the repository at this point in the history
  • Loading branch information
Cameron Dawson committed Mar 22, 2013
1 parent 9f29294 commit 3c69523
Show file tree
Hide file tree
Showing 33 changed files with 386 additions and 118 deletions.
2 changes: 1 addition & 1 deletion lib/python/django/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION = (1, 4, 2, 'final', 0)
VERSION = (1, 4, 5, 'final', 0)

def get_version(version=None):
"""Derives a PEP386-compliant version number from VERSION."""
Expand Down
4 changes: 4 additions & 0 deletions lib/python/django/conf/global_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
# * Receive x-headers
INTERNAL_IPS = ()

# Hosts/domain names that are valid for this site.
# "*" matches anything, ".example.com" matches example.com and all subdomains
ALLOWED_HOSTS = ['*']

# Local time zone for this installation. All choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name (although not all
# systems may support all possibilities). When USE_TZ is True, this is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
}
}

# Hosts/domain names that are valid for this site; required if DEBUG is False
# See https://docs.djangoproject.com/en/1.4/ref/settings/#allowed-hosts
ALLOWED_HOSTS = []

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
Expand Down
4 changes: 2 additions & 2 deletions lib/python/django/contrib/admin/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from django.db import models
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_unicode, force_unicode
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.contrib.admin.util import (get_model_from_relation,
Expand Down Expand Up @@ -102,7 +102,7 @@ def choices(self, cl):
}
for lookup, title in self.lookup_choices:
yield {
'selected': self.value() == lookup,
'selected': self.value() == force_unicode(lookup),
'query_string': cl.get_query_string({
self.parameter_name: lookup,
}, []),
Expand Down
10 changes: 8 additions & 2 deletions lib/python/django/contrib/admin/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -1317,15 +1317,21 @@ def delete_view(self, request, object_id, extra_context=None):
def history_view(self, request, object_id, extra_context=None):
"The 'history' admin view for this model."
from django.contrib.admin.models import LogEntry
# First check if the user can see this history.
model = self.model
obj = get_object_or_404(model, pk=unquote(object_id))

if not self.has_change_permission(request, obj):
raise PermissionDenied

# Then get the history for this object.
opts = model._meta
app_label = opts.app_label
action_list = LogEntry.objects.filter(
object_id = object_id,
content_type__id__exact = ContentType.objects.get_for_model(model).id
).select_related().order_by('action_time')
# If no history was found, see whether this object even exists.
obj = get_object_or_404(model, pk=unquote(object_id))

context = {
'title': _('Change history: %s') % force_unicode(obj),
'action_list': action_list,
Expand Down
5 changes: 4 additions & 1 deletion lib/python/django/contrib/auth/hashers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def check_password(password, encoded, setter=None, preferred='default'):
password = smart_str(password)
encoded = smart_str(encoded)

if len(encoded) == 32 and '$' not in encoded:
if ((len(encoded) == 32 and '$' not in encoded) or
(len(encoded) == 37 and encoded.startswith('md5$$'))):
hasher = get_hasher('unsalted_md5')
else:
algorithm = encoded.split('$', 1)[0]
Expand Down Expand Up @@ -347,6 +348,8 @@ def encode(self, password, salt):
return hashlib.md5(password).hexdigest()

def verify(self, password, encoded):
if len(encoded) == 37 and encoded.startswith('md5$$'):
encoded = encoded[5:]
encoded_2 = self.encode(password, '')
return constant_time_compare(encoded, encoded_2)

Expand Down
5 changes: 5 additions & 0 deletions lib/python/django/contrib/auth/tests/hashers.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def test_unsalted_md5(self):
self.assertTrue(is_password_usable(encoded))
self.assertTrue(check_password(u'letmein', encoded))
self.assertFalse(check_password('letmeinz', encoded))
# Alternate unsalted syntax
alt_encoded = "md5$$%s" % encoded
self.assertTrue(is_password_usable(alt_encoded))
self.assertTrue(check_password(u'letmein', alt_encoded))
self.assertFalse(check_password('letmeinz', alt_encoded))

@skipUnless(crypt, "no crypt module to generate password.")
def test_crypt(self):
Expand Down
5 changes: 5 additions & 0 deletions lib/python/django/contrib/auth/tests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def test_email_found_custom_from(self):
self.assertEqual(len(mail.outbox), 1)
self.assertEqual("staffmember@example.com", mail.outbox[0].from_email)

@override_settings(ALLOWED_HOSTS=['adminsite.com'])
def test_admin_reset(self):
"If the reset view is marked as being for admin, the HTTP_HOST header is used for a domain override."
response = self.client.post('/admin_password_reset/',
Expand All @@ -118,6 +119,8 @@ def test_admin_reset(self):
self.assertTrue("http://adminsite.com" in mail.outbox[0].body)
self.assertEqual(settings.DEFAULT_FROM_EMAIL, mail.outbox[0].from_email)

# Skip any 500 handler action (like sending more mail...)
@override_settings(DEBUG_PROPAGATE_EXCEPTIONS=True)
def test_poisoned_http_host(self):
"Poisoned HTTP_HOST headers can't be used for reset emails"
# This attack is based on the way browsers handle URLs. The colon
Expand All @@ -134,6 +137,8 @@ def test_poisoned_http_host(self):
)
self.assertEqual(len(mail.outbox), 0)

# Skip any 500 handler action (like sending more mail...)
@override_settings(DEBUG_PROPAGATE_EXCEPTIONS=True)
def test_poisoned_http_host_admin_site(self):
"Poisoned HTTP_HOST headers can't be used for reset emails on admin views"
with self.assertRaises(SuspiciousOperation):
Expand Down
51 changes: 22 additions & 29 deletions lib/python/django/contrib/auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, QueryDict
from django.template.response import TemplateResponse
from django.utils.http import base36_to_int
from django.utils.http import base36_to_int, is_safe_url
from django.utils.translation import ugettext as _
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.cache import never_cache
Expand Down Expand Up @@ -34,18 +34,11 @@ def login(request, template_name='registration/login.html',
if request.method == "POST":
form = authentication_form(data=request.POST)
if form.is_valid():
netloc = urlparse.urlparse(redirect_to)[1]

# Use default setting if redirect_to is empty
if not redirect_to:
redirect_to = settings.LOGIN_REDIRECT_URL

# Heavier security check -- don't allow redirection to a different
# host.
elif netloc and netloc != request.get_host():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = settings.LOGIN_REDIRECT_URL

# Okay, security checks complete. Log the user in.
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())

if request.session.test_cookie_worked():
Expand Down Expand Up @@ -78,27 +71,27 @@ def logout(request, next_page=None,
Logs out the user and displays 'You are logged out' message.
"""
auth_logout(request)
redirect_to = request.REQUEST.get(redirect_field_name, '')
if redirect_to:
netloc = urlparse.urlparse(redirect_to)[1]

if redirect_field_name in request.REQUEST:
next_page = request.REQUEST[redirect_field_name]
# Security check -- don't allow redirection to a different host.
if not (netloc and netloc != request.get_host()):
return HttpResponseRedirect(redirect_to)
if not is_safe_url(url=next_page, host=request.get_host()):
next_page = request.path

if next_page is None:
current_site = get_current_site(request)
context = {
'site': current_site,
'site_name': current_site.name,
'title': _('Logged out')
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
else:
if next_page:
# Redirect to this page until the session has been cleared.
return HttpResponseRedirect(next_page or request.path)
return HttpResponseRedirect(next_page)

current_site = get_current_site(request)
context = {
'site': current_site,
'site_name': current_site.name,
'title': _('Logged out')
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)

def logout_then_login(request, login_url=None, current_app=None, extra_context=None):
"""
Expand Down
11 changes: 4 additions & 7 deletions lib/python/django/contrib/comments/views/comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ def post_comment(request, next=None, using=None):
if not data.get('email', ''):
data["email"] = request.user.email

# Check to see if the POST data overrides the view's next argument.
next = data.get("next", next)

# Look up the object we're trying to comment about
ctype = data.get("content_type")
object_pk = data.get("object_pk")
Expand Down Expand Up @@ -98,9 +95,9 @@ def post_comment(request, next=None, using=None):
]
return render_to_response(
template_list, {
"comment" : form.data.get("comment", ""),
"form" : form,
"next": next,
"comment": form.data.get("comment", ""),
"form": form,
"next": data.get("next", next),
},
RequestContext(request, {})
)
Expand Down Expand Up @@ -131,7 +128,7 @@ def post_comment(request, next=None, using=None):
request = request
)

return next_redirect(data, next, comment_done, c=comment._get_pk_val())
return next_redirect(request, next, comment_done, c=comment._get_pk_val())

comment_done = confirmation_view(
template = "comments/posted.html",
Expand Down
7 changes: 3 additions & 4 deletions lib/python/django/contrib/comments/views/moderation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from django.views.decorators.csrf import csrf_protect



@csrf_protect
@login_required
def flag(request, comment_id, next=None):
Expand All @@ -27,7 +26,7 @@ def flag(request, comment_id, next=None):
# Flag on POST
if request.method == 'POST':
perform_flag(request, comment)
return next_redirect(request.POST.copy(), next, flag_done, c=comment.pk)
return next_redirect(request, next, flag_done, c=comment.pk)

# Render a form on GET
else:
Expand All @@ -54,7 +53,7 @@ def delete(request, comment_id, next=None):
if request.method == 'POST':
# Flag the comment as deleted instead of actually deleting it.
perform_delete(request, comment)
return next_redirect(request.POST.copy(), next, delete_done, c=comment.pk)
return next_redirect(request, next, delete_done, c=comment.pk)

# Render a form on GET
else:
Expand All @@ -81,7 +80,7 @@ def approve(request, comment_id, next=None):
if request.method == 'POST':
# Flag the comment as approved.
perform_approve(request, comment)
return next_redirect(request.POST.copy(), next, approve_done, c=comment.pk)
return next_redirect(request, next, approve_done, c=comment.pk)

# Render a form on GET
else:
Expand Down
10 changes: 6 additions & 4 deletions lib/python/django/contrib/comments/views/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

import urllib
import textwrap
from django.http import HttpResponseRedirect
from django.core import urlresolvers
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core.exceptions import ObjectDoesNotExist
from django.contrib import comments
from django.utils.http import is_safe_url

def next_redirect(data, default, default_view, **get_kwargs):
def next_redirect(request, default, default_view, **get_kwargs):
"""
Handle the "where should I go next?" part of comment views.
Expand All @@ -21,9 +22,10 @@ def next_redirect(data, default, default_view, **get_kwargs):
Returns an ``HttpResponseRedirect``.
"""
next = data.get("next", default)
if next is None:
next = request.POST.get('next', default)
if not is_safe_url(url=next, host=request.get_host()):
next = urlresolvers.reverse(default_view)

if get_kwargs:
if '#' in next:
tmp = next.rsplit('#', 1)
Expand Down
2 changes: 2 additions & 0 deletions lib/python/django/contrib/contenttypes/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.http import HttpRequest, Http404
from django.test import TestCase
from django.utils.encoding import smart_str
from django.test.utils import override_settings


class FooWithoutUrl(models.Model):
Expand Down Expand Up @@ -114,6 +115,7 @@ def test_get_for_models_full_cache(self):
FooWithUrl: ContentType.objects.get_for_model(FooWithUrl),
})

@override_settings(ALLOWED_HOSTS=['example.com'])
def test_shortcut_view(self):
"""
Check that the shortcut view (used for the admin "view on site"
Expand Down
24 changes: 1 addition & 23 deletions lib/python/django/contrib/gis/db/backends/oracle/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,7 @@ class GeoSQLCompiler(BaseGeoSQLCompiler, SQLCompiler):
pass

class SQLInsertCompiler(compiler.SQLInsertCompiler, GeoSQLCompiler):
def placeholder(self, field, val):
if field is None:
# A field value of None means the value is raw.
return val
elif hasattr(field, 'get_placeholder'):
# Some fields (e.g. geo fields) need special munging before
# they can be inserted.
ph = field.get_placeholder(val, self.connection)
if ph == 'NULL':
# If the placeholder returned is 'NULL', then we need to
# to remove None from the Query parameters. Specifically,
# cx_Oracle will assume a CHAR type when a placeholder ('%s')
# is used for columns of MDSYS.SDO_GEOMETRY. Thus, we use
# 'NULL' for the value, and remove None from the query params.
# See also #10888.
param_idx = self.query.columns.index(field.column)
params = list(self.query.params)
params.pop(param_idx)
self.query.params = tuple(params)
return ph
else:
# Return the common case for the placeholder
return '%s'
pass

class SQLDeleteCompiler(compiler.SQLDeleteCompiler, GeoSQLCompiler):
pass
Expand Down
10 changes: 10 additions & 0 deletions lib/python/django/contrib/gis/db/backends/oracle/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""
import re
from decimal import Decimal
from itertools import izip

from django.db.backends.oracle.base import DatabaseOperations
from django.contrib.gis.db.backends.base import BaseSpatialOperations
Expand Down Expand Up @@ -287,3 +288,12 @@ def geometry_columns(self):
def spatial_ref_sys(self):
from django.contrib.gis.db.backends.oracle.models import SpatialRefSys
return SpatialRefSys

def modify_insert_params(self, placeholders, params):
"""Drop out insert parameters for NULL placeholder. Needed for Oracle Spatial
backend due to #10888
"""
# This code doesn't work for bulk insert cases.
assert len(placeholders) == 1
return [[param for pholder,param
in izip(placeholders[0], params[0]) if pholder != 'NULL'], ]
Loading

0 comments on commit 3c69523

Please sign in to comment.