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:
Gary Wilson Jr 2008-08-02 05:56:57 +00:00
parent 8a58f2216c
commit c85c8f8891
17 changed files with 138 additions and 117 deletions

View File

@ -1,3 +1,8 @@
import base64
import cPickle as pickle
import datetime
import re
from django import http, template
from django.contrib.admin import ModelAdmin
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.views.decorators.cache import never_cache
from django.conf import settings
import base64
import cPickle as pickle
import datetime
import md5
import re
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.")
LOGIN_FORM_KEY = 'this_is_the_login_form'
@ -29,14 +30,14 @@ class NotRegistered(Exception):
def _encode_post_data(post_data):
from django.conf import settings
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)
def _decode_post_data(encoded_data):
from django.conf import settings
encoded_data = base64.decodestring(encoded_data)
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
raise SuspiciousOperation, "User may have tampered with session cookie."
return pickle.loads(pickled)

View File

@ -1,5 +1,4 @@
import base64
import md5
import cPickle as pickle
try:
from functools import wraps
@ -12,6 +11,7 @@ from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from django.shortcuts import render_to_response
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.")
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):
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)
def _decode_post_data(encoded_data):
encoded_data = base64.decodestring(encoded_data)
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
raise SuspiciousOperation, "User may have tampered with session cookie."
return pickle.loads(pickled)

View File

@ -50,10 +50,10 @@ class PasswordResetTokenGenerator(object):
# last_login will also change), we produce a hash that will be
# invalid as soon as it is used.
# We limit the hash to 20 chars to keep URL short
import sha
hash = sha.new(settings.SECRET_KEY + unicode(user.id) +
user.password + unicode(user.last_login) +
unicode(timestamp)).hexdigest()[::2]
from django.utils.hashcompat import sha_constructor
hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) +
user.password + unicode(user.last_login) +
unicode(timestamp)).hexdigest()[::2]
return "%s-%s" % (ts_b36, hash)
def _num_days(self, dt):

View File

@ -29,8 +29,8 @@ class CommentManager(models.Manager):
'pa,ra') and target (something like 'lcom.eventtimes:5157'). Used to
validate that submitted form options have not been tampered-with.
"""
import md5
return md5.new(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest()
from django.utils.hashcompat import md5_constructor
return md5_constructor(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest()
def get_rating_options(self, rating_string):
"""

View File

@ -3,15 +3,16 @@ Cross Site Request Forgery Middleware.
This module provides a middleware that implements protection
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 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>')
_POST_FORM_RE = \
@ -20,7 +21,7 @@ _POST_FORM_RE = \
_HTML_TYPES = ('text/html', 'application/xhtml+xml')
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):
"""Django middleware that adds protection against Cross Site

View File

@ -2,12 +2,13 @@
Formtools Preview application.
"""
import cPickle as pickle
from django.conf import settings
from django.http import Http404
from django.shortcuts import render_to_response
from django.template.context import RequestContext
import cPickle as pickle
import md5
from django.utils.hashcompat import md5_constructor
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
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
return md5.new(pickled).hexdigest()
return md5_constructor(pickled).hexdigest()
def failed_hash(self, request):
"Returns an HttpResponse in the case of an invalid security hash."

View File

@ -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.
"""
import cPickle as pickle
from django import forms
from django.conf import settings
from django.http import Http404
from django.shortcuts import render_to_response
from django.template.context import RequestContext
import cPickle as pickle
import md5
from django.utils.hashcompat import md5_constructor
class FormWizard(object):
# Dictionary of extra template context variables.
@ -150,7 +151,7 @@ class FormWizard(object):
# Use HIGHEST_PROTOCOL because it's the most efficient. It requires
# Python 2.3, but Django requires 2.3 anyway, so that's OK.
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
return md5.new(pickled).hexdigest()
return md5_constructor(pickled).hexdigest()
def determine_step(self, request, *args, **kwargs):
"""

View File

@ -1,5 +1,4 @@
import base64
import md5
import os
import random
import sys
@ -12,6 +11,7 @@ except ImportError:
from django.conf import settings
from django.core.exceptions import SuspiciousOperation
from django.utils.hashcompat import md5_constructor
class SessionBase(object):
@ -73,13 +73,13 @@ class SessionBase(object):
def encode(self, session_dict):
"Returns the given session dictionary pickled and encoded as a string."
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)
def decode(self, session_data):
encoded_data = base64.decodestring(session_data)
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.")
try:
return pickle.loads(pickled)
@ -117,8 +117,8 @@ class SessionBase(object):
# No getpid() in Jython, for example
pid = 1
while 1:
session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
pid, time.time(), settings.SECRET_KEY)).hexdigest()
session_key = md5_constructor("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
pid, time.time(), settings.SECRET_KEY)).hexdigest()
if not self.exists(session_key):
break
return session_key

View File

@ -1,10 +1,10 @@
import base64
import md5
import cPickle as pickle
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.utils.hashcompat import md5_constructor
class SessionManager(models.Manager):
@ -13,7 +13,7 @@ class SessionManager(models.Manager):
Returns the given session dictionary pickled and encoded as a string.
"""
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)
def save(self, session_key, session_dict, expire_date):
@ -56,7 +56,7 @@ class Session(models.Model):
def get_decoded(self):
encoded_data = base64.decodestring(self.session_data)
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
raise SuspiciousOperation, "User tampered with session cookie."
try:

View File

@ -1,12 +1,14 @@
"File-based cache backend"
import md5
import os, time
import os
import time
try:
import cPickle as pickle
except ImportError:
import pickle
from django.core.cache.backends.base import BaseCache
from django.utils.hashcompat import md5_constructor
class CacheClass(BaseCache):
def __init__(self, dir, params):
@ -137,7 +139,7 @@ class CacheClass(BaseCache):
Thus, a cache key of "foo" gets turnned into a file named
``{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:])
return os.path.join(self._dir, path)
@ -147,4 +149,3 @@ class CacheClass(BaseCache):
count += len(files)
return count
_num_entries = property(_get_num_entries)

View File

@ -1,7 +1,8 @@
import datetime
import md5
from time import time
from django.utils.hashcompat import md5_constructor
try:
import decimal
except ImportError:
@ -114,7 +115,7 @@ def truncate_name(name, length=None):
if length is None or len(name) <= length:
return name
hash = md5.md5(name).hexdigest()[:4]
hash = md5_constructor(name).hexdigest()[:4]
return '%s%s' % (name[:length-4], hash)

View File

@ -1,4 +1,3 @@
import md5
import re
from django.conf import settings
@ -6,6 +5,7 @@ from django import http
from django.core.mail import mail_managers
from django.utils.http import urlquote
from django.core import urlresolvers
from django.utils.hashcompat import md5_constructor
class CommonMiddleware(object):
"""
@ -108,7 +108,7 @@ class CommonMiddleware(object):
if response.has_header('ETag'):
etag = response['ETag']
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:
cookies = response.cookies
response = http.HttpResponseNotModified()

View File

@ -17,7 +17,6 @@ An example: i18n middleware would need to distinguish caches by the
"Accept-language" header.
"""
import md5
import re
import time
try:
@ -29,6 +28,7 @@ from django.conf import settings
from django.core.cache import cache
from django.utils.encoding import smart_str, iri_to_uri
from django.utils.http import http_date
from django.utils.hashcompat import md5_constructor
cc_delim_re = re.compile(r'\s*,\s*')
@ -104,7 +104,7 @@ def patch_response_headers(response, cache_timeout=None):
if cache_timeout < 0:
cache_timeout = 0 # Can't have max-age negative
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'):
response['Last-Modified'] = http_date()
if not response.has_header('Expires'):
@ -138,7 +138,7 @@ def patch_vary_headers(response, newheaders):
def _generate_cache_key(request, headerlist, key_prefix):
"""Returns a cache key from the headers given in the header list."""
ctx = md5.new()
ctx = md5_constructor()
for header in headerlist:
value = request.META.get(header, None)
if value is not None:

View File

@ -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

View File

@ -3,11 +3,17 @@
# Unit tests for cache framework
# Uses whatever cache backend is set in the test settings file.
import os
import shutil
import tempfile
import time
import unittest
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.utils.cache import patch_vary_headers
from django.utils.hashcompat import md5_constructor
# functions/classes for complex data type tests
def f():
@ -98,11 +104,6 @@ class Cache(unittest.TestCase):
cache.set(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):
"""
@ -119,7 +120,7 @@ class FileBasedCacheTests(unittest.TestCase):
def test_hashing(self):
"""Test that keys are hashed into subdirectories correctly"""
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:])
self.assert_(os.path.exists(keypath))
@ -128,7 +129,7 @@ class FileBasedCacheTests(unittest.TestCase):
Make sure that the created subdirectories are correctly removed when empty.
"""
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:])
self.assert_(os.path.exists(keypath))

View File

@ -1,6 +1,5 @@
import os
import errno
import sha
import shutil
import unittest
@ -8,6 +7,7 @@ from django.core.files import temp as tempfile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, client
from django.utils import simplejson
from django.utils.hashcompat import sha_constructor
from models import FileModel, UPLOAD_ROOT, UPLOAD_TO
@ -45,10 +45,10 @@ class FileUploadTests(TestCase):
for key in post_data.keys():
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)
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)

View File

@ -1,12 +1,10 @@
"""
Regression tests for the Test Client, especially the customized assertions.
"""
from django.test import Client, TestCase
from django.core.urlresolvers import reverse
from django.core.exceptions import SuspiciousOperation
import os
import sha
class AssertContainsTests(TestCase):
def test_contains(self):