Fixed #7919 -- md5 and sha modules are deprecated since Python 2.5, use hashlib module when available. Patch from Karen Tracey.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8193 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
8a58f2216c
commit
c85c8f8891
|
@ -1,3 +1,8 @@
|
||||||
|
import base64
|
||||||
|
import cPickle as pickle
|
||||||
|
import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
from django import http, template
|
from django import http, template
|
||||||
from django.contrib.admin import ModelAdmin
|
from django.contrib.admin import ModelAdmin
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
|
@ -9,11 +14,7 @@ from django.utils.text import capfirst
|
||||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||||
from django.views.decorators.cache import never_cache
|
from django.views.decorators.cache import never_cache
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import base64
|
from django.utils.hashcompat import md5_constructor
|
||||||
import cPickle as pickle
|
|
||||||
import datetime
|
|
||||||
import md5
|
|
||||||
import re
|
|
||||||
|
|
||||||
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
||||||
|
@ -29,14 +30,14 @@ class NotRegistered(Exception):
|
||||||
def _encode_post_data(post_data):
|
def _encode_post_data(post_data):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
pickled = pickle.dumps(post_data)
|
pickled = pickle.dumps(post_data)
|
||||||
pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
|
pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
|
||||||
return base64.encodestring(pickled + pickled_md5)
|
return base64.encodestring(pickled + pickled_md5)
|
||||||
|
|
||||||
def _decode_post_data(encoded_data):
|
def _decode_post_data(encoded_data):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
encoded_data = base64.decodestring(encoded_data)
|
encoded_data = base64.decodestring(encoded_data)
|
||||||
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
||||||
if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
raise SuspiciousOperation, "User may have tampered with session cookie."
|
raise SuspiciousOperation, "User may have tampered with session cookie."
|
||||||
return pickle.loads(pickled)
|
return pickle.loads(pickled)
|
||||||
|
@ -48,10 +49,10 @@ class AdminSite(object):
|
||||||
register() method, and the root() method can then be used as a Django view function
|
register() method, and the root() method can then be used as a Django view function
|
||||||
that presents a full admin interface for the collection of registered models.
|
that presents a full admin interface for the collection of registered models.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
index_template = None
|
index_template = None
|
||||||
login_template = None
|
login_template = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._registry = {} # model_class class -> admin_class instance
|
self._registry = {} # model_class class -> admin_class instance
|
||||||
|
|
||||||
|
@ -117,23 +118,23 @@ class AdminSite(object):
|
||||||
return request.user.is_authenticated() and request.user.is_staff
|
return request.user.is_authenticated() and request.user.is_staff
|
||||||
|
|
||||||
def root(self, request, url):
|
def root(self, request, url):
|
||||||
"""
|
"""
|
||||||
Handles main URL routing for the admin app.
|
Handles main URL routing for the admin app.
|
||||||
|
|
||||||
`url` is the remainder of the URL -- e.g. 'comments/comment/'.
|
`url` is the remainder of the URL -- e.g. 'comments/comment/'.
|
||||||
"""
|
"""
|
||||||
if request.method == 'GET' and not request.path.endswith('/'):
|
if request.method == 'GET' and not request.path.endswith('/'):
|
||||||
return http.HttpResponseRedirect(request.path + '/')
|
return http.HttpResponseRedirect(request.path + '/')
|
||||||
|
|
||||||
# Figure out the admin base URL path and stash it for later use
|
# Figure out the admin base URL path and stash it for later use
|
||||||
self.root_path = re.sub(re.escape(url) + '$', '', request.path)
|
self.root_path = re.sub(re.escape(url) + '$', '', request.path)
|
||||||
|
|
||||||
url = url.rstrip('/') # Trim trailing slash, if it exists.
|
url = url.rstrip('/') # Trim trailing slash, if it exists.
|
||||||
|
|
||||||
# The 'logout' view doesn't require that the person is logged in.
|
# The 'logout' view doesn't require that the person is logged in.
|
||||||
if url == 'logout':
|
if url == 'logout':
|
||||||
return self.logout(request)
|
return self.logout(request)
|
||||||
|
|
||||||
# Check permission to continue or display login form.
|
# Check permission to continue or display login form.
|
||||||
if not self.has_permission(request):
|
if not self.has_permission(request):
|
||||||
return self.login(request)
|
return self.login(request)
|
||||||
|
@ -154,7 +155,7 @@ class AdminSite(object):
|
||||||
match = USER_CHANGE_PASSWORD_URL_RE.match(url)
|
match = USER_CHANGE_PASSWORD_URL_RE.match(url)
|
||||||
if match:
|
if match:
|
||||||
return self.user_change_password(request, match.group(1))
|
return self.user_change_password(request, match.group(1))
|
||||||
|
|
||||||
if '/' in url:
|
if '/' in url:
|
||||||
return self.model_page(request, *url.split('/', 2))
|
return self.model_page(request, *url.split('/', 2))
|
||||||
|
|
||||||
|
@ -320,14 +321,14 @@ class AdminSite(object):
|
||||||
# Sort the models alphabetically within each app.
|
# Sort the models alphabetically within each app.
|
||||||
for app in app_list:
|
for app in app_list:
|
||||||
app['models'].sort(lambda x, y: cmp(x['name'], y['name']))
|
app['models'].sort(lambda x, y: cmp(x['name'], y['name']))
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'title': _('Site administration'),
|
'title': _('Site administration'),
|
||||||
'app_list': app_list,
|
'app_list': app_list,
|
||||||
'root_path': self.root_path,
|
'root_path': self.root_path,
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(self.index_template or 'admin/index.html', context,
|
return render_to_response(self.index_template or 'admin/index.html', context,
|
||||||
context_instance=template.RequestContext(request)
|
context_instance=template.RequestContext(request)
|
||||||
)
|
)
|
||||||
index = never_cache(index)
|
index = never_cache(index)
|
||||||
|
@ -342,7 +343,7 @@ class AdminSite(object):
|
||||||
post_data = _encode_post_data(request.POST)
|
post_data = _encode_post_data(request.POST)
|
||||||
else:
|
else:
|
||||||
post_data = _encode_post_data({})
|
post_data = _encode_post_data({})
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'title': _('Log in'),
|
'title': _('Log in'),
|
||||||
'app_path': request.path,
|
'app_path': request.path,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import base64
|
import base64
|
||||||
import md5
|
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
try:
|
try:
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
@ -12,6 +11,7 @@ from django.contrib.auth.models import User
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
||||||
|
@ -35,13 +35,13 @@ def _display_login_form(request, error_message=''):
|
||||||
|
|
||||||
def _encode_post_data(post_data):
|
def _encode_post_data(post_data):
|
||||||
pickled = pickle.dumps(post_data)
|
pickled = pickle.dumps(post_data)
|
||||||
pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
|
pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
|
||||||
return base64.encodestring(pickled + pickled_md5)
|
return base64.encodestring(pickled + pickled_md5)
|
||||||
|
|
||||||
def _decode_post_data(encoded_data):
|
def _decode_post_data(encoded_data):
|
||||||
encoded_data = base64.decodestring(encoded_data)
|
encoded_data = base64.decodestring(encoded_data)
|
||||||
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
||||||
if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
raise SuspiciousOperation, "User may have tampered with session cookie."
|
raise SuspiciousOperation, "User may have tampered with session cookie."
|
||||||
return pickle.loads(pickled)
|
return pickle.loads(pickled)
|
||||||
|
@ -87,7 +87,7 @@ def staff_member_required(view_func):
|
||||||
if len(users) == 1:
|
if len(users) == 1:
|
||||||
message = _("Your e-mail address is not your username. Try '%s' instead.") % users[0].username
|
message = _("Your e-mail address is not your username. Try '%s' instead.") % users[0].username
|
||||||
else:
|
else:
|
||||||
# Either we cannot find the user, or if more than 1
|
# Either we cannot find the user, or if more than 1
|
||||||
# we cannot guess which user is the correct one.
|
# we cannot guess which user is the correct one.
|
||||||
message = _("Usernames cannot contain the '@' character.")
|
message = _("Usernames cannot contain the '@' character.")
|
||||||
return _display_login_form(request, message)
|
return _display_login_form(request, message)
|
||||||
|
|
|
@ -50,17 +50,17 @@ class PasswordResetTokenGenerator(object):
|
||||||
# last_login will also change), we produce a hash that will be
|
# last_login will also change), we produce a hash that will be
|
||||||
# invalid as soon as it is used.
|
# invalid as soon as it is used.
|
||||||
# We limit the hash to 20 chars to keep URL short
|
# We limit the hash to 20 chars to keep URL short
|
||||||
import sha
|
from django.utils.hashcompat import sha_constructor
|
||||||
hash = sha.new(settings.SECRET_KEY + unicode(user.id) +
|
hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) +
|
||||||
user.password + unicode(user.last_login) +
|
user.password + unicode(user.last_login) +
|
||||||
unicode(timestamp)).hexdigest()[::2]
|
unicode(timestamp)).hexdigest()[::2]
|
||||||
return "%s-%s" % (ts_b36, hash)
|
return "%s-%s" % (ts_b36, hash)
|
||||||
|
|
||||||
def _num_days(self, dt):
|
def _num_days(self, dt):
|
||||||
return (dt - date(2001,1,1)).days
|
return (dt - date(2001,1,1)).days
|
||||||
|
|
||||||
def _today(self):
|
def _today(self):
|
||||||
# Used for mocking in tests
|
# Used for mocking in tests
|
||||||
return date.today()
|
return date.today()
|
||||||
|
|
||||||
default_token_generator = PasswordResetTokenGenerator()
|
default_token_generator = PasswordResetTokenGenerator()
|
||||||
|
|
|
@ -29,8 +29,8 @@ class CommentManager(models.Manager):
|
||||||
'pa,ra') and target (something like 'lcom.eventtimes:5157'). Used to
|
'pa,ra') and target (something like 'lcom.eventtimes:5157'). Used to
|
||||||
validate that submitted form options have not been tampered-with.
|
validate that submitted form options have not been tampered-with.
|
||||||
"""
|
"""
|
||||||
import md5
|
from django.utils.hashcompat import md5_constructor
|
||||||
return md5.new(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest()
|
return md5_constructor(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest()
|
||||||
|
|
||||||
def get_rating_options(self, rating_string):
|
def get_rating_options(self, rating_string):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -2,44 +2,45 @@
|
||||||
Cross Site Request Forgery Middleware.
|
Cross Site Request Forgery Middleware.
|
||||||
|
|
||||||
This module provides a middleware that implements protection
|
This module provides a middleware that implements protection
|
||||||
against request forgeries from other sites.
|
against request forgeries from other sites.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.conf import settings
|
|
||||||
from django.http import HttpResponseForbidden
|
|
||||||
from django.utils.safestring import mark_safe
|
|
||||||
import md5
|
|
||||||
import re
|
import re
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.http import HttpResponseForbidden
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
_ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>')
|
_ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>')
|
||||||
|
|
||||||
_POST_FORM_RE = \
|
_POST_FORM_RE = \
|
||||||
re.compile(r'(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE)
|
re.compile(r'(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE)
|
||||||
|
|
||||||
_HTML_TYPES = ('text/html', 'application/xhtml+xml')
|
_HTML_TYPES = ('text/html', 'application/xhtml+xml')
|
||||||
|
|
||||||
def _make_token(session_id):
|
def _make_token(session_id):
|
||||||
return md5.new(settings.SECRET_KEY + session_id).hexdigest()
|
return md5_constructor(settings.SECRET_KEY + session_id).hexdigest()
|
||||||
|
|
||||||
class CsrfMiddleware(object):
|
class CsrfMiddleware(object):
|
||||||
"""Django middleware that adds protection against Cross Site
|
"""Django middleware that adds protection against Cross Site
|
||||||
Request Forgeries by adding hidden form fields to POST forms and
|
Request Forgeries by adding hidden form fields to POST forms and
|
||||||
checking requests for the correct value.
|
checking requests for the correct value.
|
||||||
|
|
||||||
In the list of middlewares, SessionMiddleware is required, and must come
|
In the list of middlewares, SessionMiddleware is required, and must come
|
||||||
after this middleware. CsrfMiddleWare must come after compression
|
after this middleware. CsrfMiddleWare must come after compression
|
||||||
middleware.
|
middleware.
|
||||||
|
|
||||||
If a session ID cookie is present, it is hashed with the SECRET_KEY
|
If a session ID cookie is present, it is hashed with the SECRET_KEY
|
||||||
setting to create an authentication token. This token is added to all
|
setting to create an authentication token. This token is added to all
|
||||||
outgoing POST forms and is expected on all incoming POST requests that
|
outgoing POST forms and is expected on all incoming POST requests that
|
||||||
have a session ID cookie.
|
have a session ID cookie.
|
||||||
|
|
||||||
If you are setting cookies directly, instead of using Django's session
|
If you are setting cookies directly, instead of using Django's session
|
||||||
framework, this middleware will not work.
|
framework, this middleware will not work.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
|
@ -54,10 +55,10 @@ class CsrfMiddleware(object):
|
||||||
request_csrf_token = request.POST['csrfmiddlewaretoken']
|
request_csrf_token = request.POST['csrfmiddlewaretoken']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return HttpResponseForbidden(_ERROR_MSG)
|
return HttpResponseForbidden(_ERROR_MSG)
|
||||||
|
|
||||||
if request_csrf_token != csrf_token:
|
if request_csrf_token != csrf_token:
|
||||||
return HttpResponseForbidden(_ERROR_MSG)
|
return HttpResponseForbidden(_ERROR_MSG)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
|
@ -66,7 +67,7 @@ class CsrfMiddleware(object):
|
||||||
cookie = response.cookies[settings.SESSION_COOKIE_NAME]
|
cookie = response.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
csrf_token = _make_token(cookie.value)
|
csrf_token = _make_token(cookie.value)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# No outgoing cookie to set session, but
|
# No outgoing cookie to set session, but
|
||||||
# a session might already exist.
|
# a session might already exist.
|
||||||
try:
|
try:
|
||||||
session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
|
session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
|
||||||
|
@ -74,12 +75,12 @@ class CsrfMiddleware(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# no incoming or outgoing cookie
|
# no incoming or outgoing cookie
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if csrf_token is not None and \
|
if csrf_token is not None and \
|
||||||
response['Content-Type'].split(';')[0] in _HTML_TYPES:
|
response['Content-Type'].split(';')[0] in _HTML_TYPES:
|
||||||
|
|
||||||
# ensure we don't add the 'id' attribute twice (HTML validity)
|
# ensure we don't add the 'id' attribute twice (HTML validity)
|
||||||
idattributes = itertools.chain(("id='csrfmiddlewaretoken'",),
|
idattributes = itertools.chain(("id='csrfmiddlewaretoken'",),
|
||||||
itertools.repeat(''))
|
itertools.repeat(''))
|
||||||
def add_csrf_field(match):
|
def add_csrf_field(match):
|
||||||
"""Returns the matched <form> tag plus the added <input> element"""
|
"""Returns the matched <form> tag plus the added <input> element"""
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
Formtools Preview application.
|
Formtools Preview application.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import cPickle as pickle
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.template.context import RequestContext
|
from django.template.context import RequestContext
|
||||||
import cPickle as pickle
|
from django.utils.hashcompat import md5_constructor
|
||||||
import md5
|
|
||||||
|
|
||||||
AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.
|
AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ class FormPreview(object):
|
||||||
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
|
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
|
||||||
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
|
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
|
||||||
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
|
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
|
||||||
return md5.new(pickled).hexdigest()
|
return md5_constructor(pickled).hexdigest()
|
||||||
|
|
||||||
def failed_hash(self, request):
|
def failed_hash(self, request):
|
||||||
"Returns an HttpResponse in the case of an invalid security hash."
|
"Returns an HttpResponse in the case of an invalid security hash."
|
||||||
|
|
|
@ -4,13 +4,14 @@ step and storing the form's state as HTML hidden fields so that no state is
|
||||||
stored on the server side.
|
stored on the server side.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import cPickle as pickle
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.template.context import RequestContext
|
from django.template.context import RequestContext
|
||||||
import cPickle as pickle
|
from django.utils.hashcompat import md5_constructor
|
||||||
import md5
|
|
||||||
|
|
||||||
class FormWizard(object):
|
class FormWizard(object):
|
||||||
# Dictionary of extra template context variables.
|
# Dictionary of extra template context variables.
|
||||||
|
@ -150,7 +151,7 @@ class FormWizard(object):
|
||||||
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
|
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
|
||||||
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
|
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
|
||||||
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
|
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
|
||||||
return md5.new(pickled).hexdigest()
|
return md5_constructor(pickled).hexdigest()
|
||||||
|
|
||||||
def determine_step(self, request, *args, **kwargs):
|
def determine_step(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import base64
|
import base64
|
||||||
import md5
|
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
@ -12,6 +11,7 @@ except ImportError:
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
|
|
||||||
class SessionBase(object):
|
class SessionBase(object):
|
||||||
|
@ -73,13 +73,13 @@ class SessionBase(object):
|
||||||
def encode(self, session_dict):
|
def encode(self, session_dict):
|
||||||
"Returns the given session dictionary pickled and encoded as a string."
|
"Returns the given session dictionary pickled and encoded as a string."
|
||||||
pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
|
pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
|
||||||
pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
|
pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
|
||||||
return base64.encodestring(pickled + pickled_md5)
|
return base64.encodestring(pickled + pickled_md5)
|
||||||
|
|
||||||
def decode(self, session_data):
|
def decode(self, session_data):
|
||||||
encoded_data = base64.decodestring(session_data)
|
encoded_data = base64.decodestring(session_data)
|
||||||
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
||||||
if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
||||||
raise SuspiciousOperation("User tampered with session cookie.")
|
raise SuspiciousOperation("User tampered with session cookie.")
|
||||||
try:
|
try:
|
||||||
return pickle.loads(pickled)
|
return pickle.loads(pickled)
|
||||||
|
@ -117,8 +117,8 @@ class SessionBase(object):
|
||||||
# No getpid() in Jython, for example
|
# No getpid() in Jython, for example
|
||||||
pid = 1
|
pid = 1
|
||||||
while 1:
|
while 1:
|
||||||
session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
|
session_key = md5_constructor("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
|
||||||
pid, time.time(), settings.SECRET_KEY)).hexdigest()
|
pid, time.time(), settings.SECRET_KEY)).hexdigest()
|
||||||
if not self.exists(session_key):
|
if not self.exists(session_key):
|
||||||
break
|
break
|
||||||
return session_key
|
return session_key
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import base64
|
import base64
|
||||||
import md5
|
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
|
|
||||||
class SessionManager(models.Manager):
|
class SessionManager(models.Manager):
|
||||||
|
@ -13,7 +13,7 @@ class SessionManager(models.Manager):
|
||||||
Returns the given session dictionary pickled and encoded as a string.
|
Returns the given session dictionary pickled and encoded as a string.
|
||||||
"""
|
"""
|
||||||
pickled = pickle.dumps(session_dict)
|
pickled = pickle.dumps(session_dict)
|
||||||
pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
|
pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
|
||||||
return base64.encodestring(pickled + pickled_md5)
|
return base64.encodestring(pickled + pickled_md5)
|
||||||
|
|
||||||
def save(self, session_key, session_dict, expire_date):
|
def save(self, session_key, session_dict, expire_date):
|
||||||
|
@ -56,7 +56,7 @@ class Session(models.Model):
|
||||||
def get_decoded(self):
|
def get_decoded(self):
|
||||||
encoded_data = base64.decodestring(self.session_data)
|
encoded_data = base64.decodestring(self.session_data)
|
||||||
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
||||||
if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
raise SuspiciousOperation, "User tampered with session cookie."
|
raise SuspiciousOperation, "User tampered with session cookie."
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,29 +1,31 @@
|
||||||
"File-based cache backend"
|
"File-based cache backend"
|
||||||
|
|
||||||
import md5
|
import os
|
||||||
import os, time
|
import time
|
||||||
try:
|
try:
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
from django.core.cache.backends.base import BaseCache
|
from django.core.cache.backends.base import BaseCache
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
class CacheClass(BaseCache):
|
class CacheClass(BaseCache):
|
||||||
def __init__(self, dir, params):
|
def __init__(self, dir, params):
|
||||||
BaseCache.__init__(self, params)
|
BaseCache.__init__(self, params)
|
||||||
|
|
||||||
max_entries = params.get('max_entries', 300)
|
max_entries = params.get('max_entries', 300)
|
||||||
try:
|
try:
|
||||||
self._max_entries = int(max_entries)
|
self._max_entries = int(max_entries)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
self._max_entries = 300
|
self._max_entries = 300
|
||||||
|
|
||||||
cull_frequency = params.get('cull_frequency', 3)
|
cull_frequency = params.get('cull_frequency', 3)
|
||||||
try:
|
try:
|
||||||
self._cull_frequency = int(cull_frequency)
|
self._cull_frequency = int(cull_frequency)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
self._cull_frequency = 3
|
self._cull_frequency = 3
|
||||||
|
|
||||||
self._dir = dir
|
self._dir = dir
|
||||||
if not os.path.exists(self._dir):
|
if not os.path.exists(self._dir):
|
||||||
self._createdir()
|
self._createdir()
|
||||||
|
@ -31,7 +33,7 @@ class CacheClass(BaseCache):
|
||||||
def add(self, key, value, timeout=None):
|
def add(self, key, value, timeout=None):
|
||||||
if self.has_key(key):
|
if self.has_key(key):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self.set(key, value, timeout)
|
self.set(key, value, timeout)
|
||||||
|
|
||||||
def get(self, key, default=None):
|
def get(self, key, default=None):
|
||||||
|
@ -52,12 +54,12 @@ class CacheClass(BaseCache):
|
||||||
def set(self, key, value, timeout=None):
|
def set(self, key, value, timeout=None):
|
||||||
fname = self._key_to_file(key)
|
fname = self._key_to_file(key)
|
||||||
dirname = os.path.dirname(fname)
|
dirname = os.path.dirname(fname)
|
||||||
|
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self.default_timeout
|
timeout = self.default_timeout
|
||||||
|
|
||||||
self._cull()
|
self._cull()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not os.path.exists(dirname):
|
if not os.path.exists(dirname):
|
||||||
os.makedirs(dirname)
|
os.makedirs(dirname)
|
||||||
|
@ -103,12 +105,12 @@ class CacheClass(BaseCache):
|
||||||
def _cull(self):
|
def _cull(self):
|
||||||
if int(self._num_entries) < self._max_entries:
|
if int(self._num_entries) < self._max_entries:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
filelist = os.listdir(self._dir)
|
filelist = os.listdir(self._dir)
|
||||||
except (IOError, OSError):
|
except (IOError, OSError):
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._cull_frequency == 0:
|
if self._cull_frequency == 0:
|
||||||
doomed = filelist
|
doomed = filelist
|
||||||
else:
|
else:
|
||||||
|
@ -133,11 +135,11 @@ class CacheClass(BaseCache):
|
||||||
Convert the filename into an md5 string. We'll turn the first couple
|
Convert the filename into an md5 string. We'll turn the first couple
|
||||||
bits of the path into directory prefixes to be nice to filesystems
|
bits of the path into directory prefixes to be nice to filesystems
|
||||||
that have problems with large numbers of files in a directory.
|
that have problems with large numbers of files in a directory.
|
||||||
|
|
||||||
Thus, a cache key of "foo" gets turnned into a file named
|
Thus, a cache key of "foo" gets turnned into a file named
|
||||||
``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``.
|
``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``.
|
||||||
"""
|
"""
|
||||||
path = md5.new(key.encode('utf-8')).hexdigest()
|
path = md5_constructor(key.encode('utf-8')).hexdigest()
|
||||||
path = os.path.join(path[:2], path[2:4], path[4:])
|
path = os.path.join(path[:2], path[2:4], path[4:])
|
||||||
return os.path.join(self._dir, path)
|
return os.path.join(self._dir, path)
|
||||||
|
|
||||||
|
@ -147,4 +149,3 @@ class CacheClass(BaseCache):
|
||||||
count += len(files)
|
count += len(files)
|
||||||
return count
|
return count
|
||||||
_num_entries = property(_get_num_entries)
|
_num_entries = property(_get_num_entries)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import datetime
|
import datetime
|
||||||
import md5
|
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import decimal
|
import decimal
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -114,7 +115,7 @@ def truncate_name(name, length=None):
|
||||||
if length is None or len(name) <= length:
|
if length is None or len(name) <= length:
|
||||||
return name
|
return name
|
||||||
|
|
||||||
hash = md5.md5(name).hexdigest()[:4]
|
hash = md5_constructor(name).hexdigest()[:4]
|
||||||
|
|
||||||
return '%s%s' % (name[:length-4], hash)
|
return '%s%s' % (name[:length-4], hash)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import md5
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -6,6 +5,7 @@ from django import http
|
||||||
from django.core.mail import mail_managers
|
from django.core.mail import mail_managers
|
||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
from django.core import urlresolvers
|
from django.core import urlresolvers
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
class CommonMiddleware(object):
|
class CommonMiddleware(object):
|
||||||
"""
|
"""
|
||||||
|
@ -21,7 +21,7 @@ class CommonMiddleware(object):
|
||||||
slash, and it is not found in urlpatterns, a new URL is formed by
|
slash, and it is not found in urlpatterns, a new URL is formed by
|
||||||
appending a slash at the end. If this new URL is found in
|
appending a slash at the end. If this new URL is found in
|
||||||
urlpatterns, then an HTTP-redirect is returned to this new URL;
|
urlpatterns, then an HTTP-redirect is returned to this new URL;
|
||||||
otherwise the initial URL is processed as usual.
|
otherwise the initial URL is processed as usual.
|
||||||
|
|
||||||
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
||||||
the entire page content and Not Modified responses will be returned
|
the entire page content and Not Modified responses will be returned
|
||||||
|
@ -108,7 +108,7 @@ class CommonMiddleware(object):
|
||||||
if response.has_header('ETag'):
|
if response.has_header('ETag'):
|
||||||
etag = response['ETag']
|
etag = response['ETag']
|
||||||
else:
|
else:
|
||||||
etag = '"%s"' % md5.new(response.content).hexdigest()
|
etag = '"%s"' % md5_constructor(response.content).hexdigest()
|
||||||
if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
|
if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
|
||||||
cookies = response.cookies
|
cookies = response.cookies
|
||||||
response = http.HttpResponseNotModified()
|
response = http.HttpResponseNotModified()
|
||||||
|
|
|
@ -17,7 +17,6 @@ An example: i18n middleware would need to distinguish caches by the
|
||||||
"Accept-language" header.
|
"Accept-language" header.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import md5
|
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
try:
|
try:
|
||||||
|
@ -29,6 +28,7 @@ from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils.encoding import smart_str, iri_to_uri
|
from django.utils.encoding import smart_str, iri_to_uri
|
||||||
from django.utils.http import http_date
|
from django.utils.http import http_date
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
cc_delim_re = re.compile(r'\s*,\s*')
|
cc_delim_re = re.compile(r'\s*,\s*')
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ def patch_response_headers(response, cache_timeout=None):
|
||||||
if cache_timeout < 0:
|
if cache_timeout < 0:
|
||||||
cache_timeout = 0 # Can't have max-age negative
|
cache_timeout = 0 # Can't have max-age negative
|
||||||
if not response.has_header('ETag'):
|
if not response.has_header('ETag'):
|
||||||
response['ETag'] = '"%s"' % md5.new(response.content).hexdigest()
|
response['ETag'] = '"%s"' % md5_constructor(response.content).hexdigest()
|
||||||
if not response.has_header('Last-Modified'):
|
if not response.has_header('Last-Modified'):
|
||||||
response['Last-Modified'] = http_date()
|
response['Last-Modified'] = http_date()
|
||||||
if not response.has_header('Expires'):
|
if not response.has_header('Expires'):
|
||||||
|
@ -138,7 +138,7 @@ def patch_vary_headers(response, newheaders):
|
||||||
|
|
||||||
def _generate_cache_key(request, headerlist, key_prefix):
|
def _generate_cache_key(request, headerlist, key_prefix):
|
||||||
"""Returns a cache key from the headers given in the header list."""
|
"""Returns a cache key from the headers given in the header list."""
|
||||||
ctx = md5.new()
|
ctx = md5_constructor()
|
||||||
for header in headerlist:
|
for header in headerlist:
|
||||||
value = request.META.get(header, None)
|
value = request.META.get(header, None)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
The md5 and sha modules are deprecated since Python 2.5, replaced by the
|
||||||
|
hashlib module containing both hash algorithms. Here, we provide a common
|
||||||
|
interface to the md5 and sha constructors, preferring the hashlib module when
|
||||||
|
available.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import hashlib
|
||||||
|
md5_constructor = hashlib.md5
|
||||||
|
sha_constructor = hashlib.sha1
|
||||||
|
except ImportError:
|
||||||
|
import md5
|
||||||
|
md5_constructor = md5.new
|
||||||
|
import sha
|
||||||
|
sha_constructor = sha.new
|
|
@ -3,11 +3,17 @@
|
||||||
# Unit tests for cache framework
|
# Unit tests for cache framework
|
||||||
# Uses whatever cache backend is set in the test settings file.
|
# Uses whatever cache backend is set in the test settings file.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils.cache import patch_vary_headers
|
from django.core.cache.backends.filebased import CacheClass as FileCache
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.utils.cache import patch_vary_headers
|
||||||
|
from django.utils.hashcompat import md5_constructor
|
||||||
|
|
||||||
# functions/classes for complex data type tests
|
# functions/classes for complex data type tests
|
||||||
def f():
|
def f():
|
||||||
|
@ -27,7 +33,7 @@ class Cache(unittest.TestCase):
|
||||||
cache.add("addkey1", "value")
|
cache.add("addkey1", "value")
|
||||||
cache.add("addkey1", "newvalue")
|
cache.add("addkey1", "newvalue")
|
||||||
self.assertEqual(cache.get("addkey1"), "value")
|
self.assertEqual(cache.get("addkey1"), "value")
|
||||||
|
|
||||||
def test_non_existent(self):
|
def test_non_existent(self):
|
||||||
# get with non-existent keys
|
# get with non-existent keys
|
||||||
self.assertEqual(cache.get("does_not_exist"), None)
|
self.assertEqual(cache.get("does_not_exist"), None)
|
||||||
|
@ -80,9 +86,9 @@ class Cache(unittest.TestCase):
|
||||||
cache.set('expire2', 'very quickly', 1)
|
cache.set('expire2', 'very quickly', 1)
|
||||||
cache.set('expire3', 'very quickly', 1)
|
cache.set('expire3', 'very quickly', 1)
|
||||||
|
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
self.assertEqual(cache.get("expire1"), None)
|
self.assertEqual(cache.get("expire1"), None)
|
||||||
|
|
||||||
cache.add("expire2", "newvalue")
|
cache.add("expire2", "newvalue")
|
||||||
self.assertEqual(cache.get("expire2"), "newvalue")
|
self.assertEqual(cache.get("expire2"), "newvalue")
|
||||||
self.assertEqual(cache.has_key("expire3"), False)
|
self.assertEqual(cache.has_key("expire3"), False)
|
||||||
|
@ -98,11 +104,6 @@ class Cache(unittest.TestCase):
|
||||||
cache.set(key, value)
|
cache.set(key, value)
|
||||||
self.assertEqual(cache.get(key), value)
|
self.assertEqual(cache.get(key), value)
|
||||||
|
|
||||||
import os
|
|
||||||
import md5
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
from django.core.cache.backends.filebased import CacheClass as FileCache
|
|
||||||
|
|
||||||
class FileBasedCacheTests(unittest.TestCase):
|
class FileBasedCacheTests(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
|
@ -112,23 +113,23 @@ class FileBasedCacheTests(unittest.TestCase):
|
||||||
self.dirname = tempfile.mktemp()
|
self.dirname = tempfile.mktemp()
|
||||||
os.mkdir(self.dirname)
|
os.mkdir(self.dirname)
|
||||||
self.cache = FileCache(self.dirname, {})
|
self.cache = FileCache(self.dirname, {})
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.dirname)
|
shutil.rmtree(self.dirname)
|
||||||
|
|
||||||
def test_hashing(self):
|
def test_hashing(self):
|
||||||
"""Test that keys are hashed into subdirectories correctly"""
|
"""Test that keys are hashed into subdirectories correctly"""
|
||||||
self.cache.set("foo", "bar")
|
self.cache.set("foo", "bar")
|
||||||
keyhash = md5.new("foo").hexdigest()
|
keyhash = md5_constructor("foo").hexdigest()
|
||||||
keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
|
keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
|
||||||
self.assert_(os.path.exists(keypath))
|
self.assert_(os.path.exists(keypath))
|
||||||
|
|
||||||
def test_subdirectory_removal(self):
|
def test_subdirectory_removal(self):
|
||||||
"""
|
"""
|
||||||
Make sure that the created subdirectories are correctly removed when empty.
|
Make sure that the created subdirectories are correctly removed when empty.
|
||||||
"""
|
"""
|
||||||
self.cache.set("foo", "bar")
|
self.cache.set("foo", "bar")
|
||||||
keyhash = md5.new("foo").hexdigest()
|
keyhash = md5_constructor("foo").hexdigest()
|
||||||
keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
|
keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
|
||||||
self.assert_(os.path.exists(keypath))
|
self.assert_(os.path.exists(keypath))
|
||||||
|
|
||||||
|
@ -139,9 +140,9 @@ class FileBasedCacheTests(unittest.TestCase):
|
||||||
|
|
||||||
class CacheUtils(unittest.TestCase):
|
class CacheUtils(unittest.TestCase):
|
||||||
"""TestCase for django.utils.cache functions."""
|
"""TestCase for django.utils.cache functions."""
|
||||||
|
|
||||||
def test_patch_vary_headers(self):
|
def test_patch_vary_headers(self):
|
||||||
headers = (
|
headers = (
|
||||||
# Initial vary, new headers, resulting vary.
|
# Initial vary, new headers, resulting vary.
|
||||||
(None, ('Accept-Encoding',), 'Accept-Encoding'),
|
(None, ('Accept-Encoding',), 'Accept-Encoding'),
|
||||||
('Accept-Encoding', ('accept-encoding',), 'Accept-Encoding'),
|
('Accept-Encoding', ('accept-encoding',), 'Accept-Encoding'),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import os
|
import os
|
||||||
import errno
|
import errno
|
||||||
import sha
|
|
||||||
import shutil
|
import shutil
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@ -8,6 +7,7 @@ from django.core.files import temp as tempfile
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.test import TestCase, client
|
from django.test import TestCase, client
|
||||||
from django.utils import simplejson
|
from django.utils import simplejson
|
||||||
|
from django.utils.hashcompat import sha_constructor
|
||||||
|
|
||||||
from models import FileModel, UPLOAD_ROOT, UPLOAD_TO
|
from models import FileModel, UPLOAD_ROOT, UPLOAD_TO
|
||||||
|
|
||||||
|
@ -45,10 +45,10 @@ class FileUploadTests(TestCase):
|
||||||
|
|
||||||
for key in post_data.keys():
|
for key in post_data.keys():
|
||||||
try:
|
try:
|
||||||
post_data[key + '_hash'] = sha.new(post_data[key].read()).hexdigest()
|
post_data[key + '_hash'] = sha_constructor(post_data[key].read()).hexdigest()
|
||||||
post_data[key].seek(0)
|
post_data[key].seek(0)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
post_data[key + '_hash'] = sha.new(post_data[key]).hexdigest()
|
post_data[key + '_hash'] = sha_constructor(post_data[key]).hexdigest()
|
||||||
|
|
||||||
response = self.client.post('/file_uploads/verify/', post_data)
|
response = self.client.post('/file_uploads/verify/', post_data)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
"""
|
"""
|
||||||
Regression tests for the Test Client, especially the customized assertions.
|
Regression tests for the Test Client, especially the customized assertions.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
import os
|
|
||||||
import sha
|
|
||||||
|
|
||||||
class AssertContainsTests(TestCase):
|
class AssertContainsTests(TestCase):
|
||||||
def test_contains(self):
|
def test_contains(self):
|
||||||
|
@ -24,7 +22,7 @@ class AssertContainsTests(TestCase):
|
||||||
self.assertNotContains(response, 'once')
|
self.assertNotContains(response, 'once')
|
||||||
except AssertionError, e:
|
except AssertionError, e:
|
||||||
self.assertEquals(str(e), "Response should not contain 'once'")
|
self.assertEquals(str(e), "Response should not contain 'once'")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.assertContains(response, 'never', 1)
|
self.assertContains(response, 'never', 1)
|
||||||
except AssertionError, e:
|
except AssertionError, e:
|
||||||
|
@ -287,7 +285,7 @@ class URLEscapingTests(TestCase):
|
||||||
|
|
||||||
class ExceptionTests(TestCase):
|
class ExceptionTests(TestCase):
|
||||||
fixtures = ['testdata.json']
|
fixtures = ['testdata.json']
|
||||||
|
|
||||||
def test_exception_cleared(self):
|
def test_exception_cleared(self):
|
||||||
"#5836 - A stale user exception isn't re-raised by the test client."
|
"#5836 - A stale user exception isn't re-raised by the test client."
|
||||||
|
|
||||||
|
@ -300,7 +298,7 @@ class ExceptionTests(TestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# At this point, an exception has been raised, and should be cleared.
|
# At this point, an exception has been raised, and should be cleared.
|
||||||
|
|
||||||
# This next operation should be successful; if it isn't we have a problem.
|
# This next operation should be successful; if it isn't we have a problem.
|
||||||
login = self.client.login(username='staff', password='password')
|
login = self.client.login(username='staff', password='password')
|
||||||
self.failUnless(login, 'Could not log in')
|
self.failUnless(login, 'Could not log in')
|
||||||
|
|
Loading…
Reference in New Issue