=== added file 'django/contrib/auth/newforms.py'
--- django/contrib/auth/newforms.py	1970-01-01 00:00:00 +0000
+++ django/contrib/auth/newforms.py	2008-02-14 11:57:49 +0000
@@ -0,0 +1,191 @@
+import base64, md5
+import cPickle as pickle
+
+from django.conf import settings
+from django.contrib.auth import authenticate
+from django.contrib.auth.models import User
+from django.contrib.sites.models import Site
+from django import newforms as forms
+from django.template import Context, loader
+from django.utils.translation import ugettext as _
+
+class UserCreationForm(forms.ModelForm):
+    "A form that creates a user, with no privileges, from the given username and password."
+    # TODO: Model level validation should simplify this form.
+    username = forms.RegexField(label=_('Username'), max_length=30, regex=r'^\w+$',
+        error_message=_("This value must contain only letters, numbers and underscores."))
+    password = forms.CharField(label=_('Password'), max_length=60, widget=forms.PasswordInput)
+    password2 = forms.CharField(label=_('Password confirmation'), max_length=60, widget=forms.PasswordInput)
+
+    class Meta:
+        model = User
+        fields = 'username', 'password', 'password2',
+
+    def clean_username(self):
+        username = self.cleaned_data.get('username')
+        if username:
+            if User.objects.filter(username=username):
+                raise forms.ValidationError(_("A user with that username already exists."))
+        return username
+
+    def clean_password2(self):
+        password = self.cleaned_data.get('password')
+        password2 = self.cleaned_data.get('password2')
+        if password and password2:
+            if password != password2:
+                raise forms.ValidationError(_("The two password fields didn't match."))
+        return password2
+
+    def save(self, commit=True):
+        user = super(UserCreationForm, self).save(commit=False)
+        user.set_password(self.cleaned_data['password'])
+        if commit:
+            user.save()
+        return user
+
+class AuthenticationForm(forms.Form):
+    """
+    Base class for authenticating users.
+    """
+    username = forms.CharField(max_length=30)
+    password = forms.CharField(widget=forms.PasswordInput, max_length=30)
+
+    def __init__(self, request=None, *args, **kwargs):
+        self.request = request
+        self.user_cache = None
+        if self.request:
+            self.request.session.set_test_cookie()
+        super(AuthenticationForm, self).__init__(*args, **kwargs)
+
+    def clean(self):
+        username = self.cleaned_data.get('username')
+        password = self.cleaned_data.get('password')
+        if username and password:
+            self.user_cache = authenticate(username=username, password=password)
+            if self.user_cache is None:
+                raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
+            if not self.user_cache.is_active:
+                raise forms.ValidationError(_("This account is inactive."))
+        if self.request:
+            if not self.request.session.test_cookie_worked():
+                raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
+            self.request.session.delete_test_cookie()
+        return self.cleaned_data
+
+    def get_user_id(self):
+        if self.user_cache:
+            return self.user_cache.id
+        else:
+            return None
+
+    def get_user(self):
+        return self.user_cache
+
+class RedirectionAuthenticationForm(AuthenticationForm):
+    """
+    Authentication form with field for redirection url.
+    """
+    redirect_to = forms.CharField(required=False, widget=forms.HiddenInput)
+
+    def initial_redirect_to(request, redirect_field_name):
+        return request.REQUEST.get(redirect_field_name)
+    initial_redirect_to = staticmethod(initial_redirect_to)
+
+    def clean_redirect_to(self):
+        redirect_to = self.cleaned_data.get('redirect_to')
+        # Light security check -- make sure redirect_to isn't garbage.
+        if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
+            return settings.LOGIN_REDIRECT_URL
+        else:
+            return redirect_to
+
+class PostDataAuthenticationForm(AuthenticationForm):
+    """
+    Authentication form with field for post data.
+    """
+    post_data = forms.CharField(required=False, widget=forms.HiddenInput)
+    LOGIN_FORM_KEY = forms.CharField(required=False, widget=forms.HiddenInput)
+
+    def initial_post_data(request):
+        pickled = pickle.dumps(request.POST)
+        pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
+        return base64.encodestring(pickled + pickled_md5)
+    initial_post_data = staticmethod(initial_post_data)
+
+    def clean_post_data(self):
+        post_data = self.cleaned_data.get('post_data')
+        if post_data:
+            encoded_data = base64.decodestring(post_data)
+            pickled, pickled_md5 = encoded_data[:-32], encoded_data[-32:]
+            if md5.new(pickled + settings.SECRET_KEY).hexdigest() != pickled_md5:
+                # User may have tampered with session cookie.
+                return None
+            return pickle.loads(pickled)
+        else:
+            return None
+
+class PasswordChangeForm(forms.Form):
+    "A form that lets a user change his password."
+    old_password = forms.CharField(widget=forms.PasswordInput, max_length=30)
+    new_password = forms.CharField(widget=forms.PasswordInput, max_length=30)
+    new_password2 = forms.CharField(widget=forms.PasswordInput, max_length=30)
+
+    def __init__(self, user, *args, **kwargs):
+        self.user = user
+        super(PasswordChangeForm, self).__init__(*args, **kwargs)
+
+    def clean_old_password(self):
+        old_password = self.cleaned_data.get('old_password')
+        if old_password:
+            if not self.user.check_password(old_password):
+                raise forms.ValidationError(_("Your old password was entered incorrectly. Please enter it again."))
+        return old_password
+
+    def clean_password2(self):
+        new_password = self.cleaned_data.get('new_password')
+        new_password2 = self.cleaned_data.get('new_password2')
+        if new_password and new_password2:
+            if new_password != new_password2:
+                raise forms.ValidationError(_("The two 'new password' fields didn't match."))
+        return new_password2
+
+    def save(self, commit=True):
+        self.user.set_password(self.cleaned_data['new_password'])
+        if commit:
+            return self.user.save()
+        return self.user
+
+class PasswordResetForm(forms.Form):
+    "A form that lets a user request a password reset"
+    email = forms.EmailField()
+
+    def clean_email(self):
+        "Validates that a user exists with the given e-mail address"
+        email = self.cleaned_data.get('email')
+        if email:
+            self.users_cache = User.objects.filter(email__iexact=email)
+            if len(self.users_cache) == 0:
+                raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
+
+    def save(self, email_template_name='registration/password_reset_email.html', domain_override=None):
+        "Calculates a new password randomly and sends it to the user"
+        from django.core.mail import send_mail
+        for user in self.users_cache:
+            new_pass = User.objects.make_random_password()
+            user.set_password(new_pass)
+            user.save()
+            if not domain_override:
+                current_site = Site.objects.get_current()
+                site_name = current_site.name
+                domain = current_site.domain
+            else:
+                site_name = domain = domain_override
+            t = loader.get_template(email_template_name)
+            c = {
+                'new_password': new_pass,
+                'email': user.email,
+                'domain': domain,
+                'site_name': site_name,
+                'user': user,
+            }
+            send_mail(_('Password reset on %s') % site_name, t.render(Context(c)), None, [user.email])

=== added file 'django/contrib/auth/newviews.py'
--- django/contrib/auth/newviews.py	1970-01-01 00:00:00 +0000
+++ django/contrib/auth/newviews.py	2008-02-14 12:08:05 +0000
@@ -0,0 +1,96 @@
+from django.contrib.auth import REDIRECT_FIELD_NAME
+from django.contrib.auth.newforms import RedirectionAuthenticationForm
+from django.contrib.auth.newforms import PostDataAuthenticationForm
+from django.contrib.auth.newforms import PasswordChangeForm
+from django.contrib.auth.newforms import PasswordResetForm
+from django.http import HttpResponseRedirect
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+
+def _get_context(request, extra_context=None, **kwargs):
+    context = RequestContext(request)
+    context.update(kwargs)
+    if extra_context:
+        context.update(extra_context)
+    return context
+
+def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME, extra_context=None):
+    "Displays the login form and handles the login action."
+    if request.method == 'POST':
+        form = RedirectionAuthenticationForm(request, request.POST)
+        if form.is_valid():
+            from django.contrib.auth import login
+            login(request, form.get_user())
+            return HttpResponseRedirect(form.cleaned_data['redirect_to'])
+    else:
+        initial = {'redirect_to': RedirectionAuthenticationForm.initial_redirect_to(request, redirect_field_name)}
+        form = RedirectionAuthenticationForm(request, initial=initial)
+    return render_to_response(template_name, context_instance=_get_context(request, extra_context, form=form))
+
+def login_with_post_data(request, view_func, view_func_args, view_func_kwargs, template_name='registration/login.html', extra_context=None):
+    if request.method == 'POST':
+        if 'LOGIN_FORM_KEY' in request.POST:
+            form = PostDataAuthenticationForm(request, request.POST)
+            if form.is_valid():
+                from django.contrib.auth import login
+                login(request, form.get_user())
+                request.POST = form.cleaned_data['post_data']
+                return view_func(request, *view_func_args, **view_func_kwargs)
+        else:
+            initial = {'post_data': PostDataAuthenticationForm.initial_post_data(request)}
+            form = PostDataAuthenticationForm(request, initial=initial)
+    else:
+        form = PostDataAuthenticationForm(request)
+    return render_to_response(template_name, context_instance=_get_context(request, extra_context, form=form))
+
+def logout(request, template_name='registration/logged_out.html', next_page=None, extra_context=None):
+    "Logs out the user and displays 'You are logged out' message."
+    from django.contrib.auth import logout
+    logout(request)
+    if next_page is None:
+        return render_to_response(template_name, context_instance=_get_context(request, extra_context))
+    else:
+        # Redirect to this page until the session has been cleared.
+        return HttpResponseRedirect(next_page or request.path)
+
+def logout_then_login(request, login_url=None):
+    "Logs out the user if he is logged in. Then redirects to the log-in page."
+    if not login_url:
+        from django.conf import settings
+        login_url = settings.LOGIN_URL
+    return logout(request, next_page=login_url)
+
+def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
+    "Redirects the user to the login page, passing the given 'next' page"
+    if not login_url:
+        from django.conf import settings
+        login_url = settings.LOGIN_URL
+    return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, next))
+
+def password_change(request, template_name='registration/password_change_form.html', next_page=None, extra_context=None):
+    if request.method == 'POST':
+        form = PasswordChangeForm(request.user, request.POST)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(next_page or '%sdone/' % request.path)
+    else:
+        form = PasswordChangeForm(request.user)
+    context = RequestContext(request)
+    return render_to_response(template_name, context_instance=_get_context(request, extra_context, form=form))
+
+def password_change_done(request, template_name='registration/password_change_done.html', extra_context=None):
+    return render_to_response(template_name, context_instance=_get_context(request, extra_context))
+
+def password_reset(request, template_name='registration/password_reset_form.html', next_page=None, extra_context=None,
+        email_template_name='registration/password_reset_email.html', domain_override=None):
+    if request.method == 'POST':
+        form = PasswordResetForm(request.POST)
+        if form.is_valid():
+            form.save(email_template_name=email_template_name, domain_override=domain_override)
+            return HttpResponseRedirect(next_page or '%sdone/' % request.path)
+    else:
+        form = PasswordResetForm()
+    return render_to_response(template_name, context_instance=_get_context(request, extra_context, form=form))
+
+def password_reset_done(request, template_name='registration/password_reset_done.html', extra_context=None):
+    return render_to_response(template_name, context_instance=_get_context(request, extra_context))

=== modified file 'django/contrib/auth/decorators.py'
--- django/contrib/auth/decorators.py	2008-01-28 22:21:24 +0000
+++ django/contrib/auth/decorators.py	2008-02-14 11:49:48 +0000
@@ -2,35 +2,53 @@
 from django.http import HttpResponseRedirect
 from django.utils.http import urlquote
 
-def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
+def user_passes_test(test_func, login_url=None, redirect_field_name=None,
+        post_data=False, login_func=None, **login_func_kwargs):
     """
     Decorator for views that checks that the user passes the given test,
     redirecting to the log-in page if necessary. The test should be a callable
     that takes the user object and returns True if the user passes.
+    If post data is True, there is no redirection but login funcion is used.
     """
     def decorate(view_func):
-        return _CheckLogin(view_func, test_func, login_url, redirect_field_name)
+        return _CheckLogin(view_func, test_func, login_url, redirect_field_name,
+            post_data, login_func, **login_func_kwargs)
     return decorate
 
-def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
+def login_required(view_func=None, login_url=None, redirect_field_name=None,
+        post_data=False, login_func=None, **login_func_kwargs):
     """
     Decorator for views that checks that the user is logged in, redirecting
     to the log-in page if necessary.
     """
-    actual_decorator = user_passes_test(
-        lambda u: u.is_authenticated(),
-        redirect_field_name=redirect_field_name
-    )
-    if function:
-        return actual_decorator(function)
-    return actual_decorator
-
-def permission_required(perm, login_url=None):
+    actual_decorator = user_passes_test(lambda u: u.is_authenticated(), login_url,
+        redirect_field_name, post_data, login_func, **login_func_kwargs)
+    if view_func:
+        return actual_decorator(view_func)
+    else:
+        return actual_decorator
+
+def staff_required(view_func=None, login_url=None, redirect_field_name=None,
+        post_data=False, login_func=None, **login_func_kwargs):
+    """
+    Decorator for views that checks that the user is staff, redirecting
+    to the log-in page if necessary.
+    """
+    actual_decorator = user_passes_test(lambda u: u.is_staff, login_url,
+        redirect_field_name, post_data, login_func, **login_func_kwargs)
+    if view_func:
+        return actual_decorator(view_func)
+    else:
+        return actual_decorator
+
+def permission_required(perm, login_url=None, redirect_field_name=None,
+        post_data=False, login_func=None, **login_func_kwargs):
     """
     Decorator for views that checks whether a user has a particular permission
     enabled, redirecting to the log-in page if necessary.
     """
-    return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
+    return user_passes_test(lambda u: u.has_perm(perm), login_url,
+        redirect_field_name, post_data, login_func, **login_func_kwargs)
 
 class _CheckLogin(object):
     """
@@ -43,23 +61,37 @@
     _CheckLogin object is used as a method decorator, the view function
     is properly bound to its instance.
     """
-    def __init__(self, view_func, test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
+    def __init__(self, view_func, test_func, login_url=None, redirect_field_name=None,
+            post_data=False, login_func=None, **login_func_kwargs):
         if not login_url:
             from django.conf import settings
             login_url = settings.LOGIN_URL
+        if not redirect_field_name:
+            redirect_field_name = REDIRECT_FIELD_NAME
+        if not login_func:
+            from django.contrib.auth.newviews import login_with_post_data
+            login_func = login_with_post_data
         self.view_func = view_func
         self.test_func = test_func
         self.login_url = login_url
         self.redirect_field_name = redirect_field_name
+        self.post_data = post_data
+        self.login_func = login_func
+        self.login_func_kwargs = login_func_kwargs
         self.__name__ = view_func.__name__
-        
+
     def __get__(self, obj, cls=None):
         view_func = self.view_func.__get__(obj, cls)
-        return _CheckLogin(view_func, self.test_func, self.login_url, self.redirect_field_name)
-    
+        return _CheckLogin(view_func, self.test_func, self.login_url, self.redirect_field_name,
+            self.post_data, self.login_func, self.login_func_kwargs)
+
     def __call__(self, request, *args, **kwargs):
         if self.test_func(request.user):
             return self.view_func(request, *args, **kwargs)
-        path = urlquote(request.get_full_path())
-        tup = self.login_url, self.redirect_field_name, path
-        return HttpResponseRedirect('%s?%s=%s' % tup)
+        else:
+            if self.post_data:
+                return self.login_func(request, self.view_func, args, kwargs, **self.login_func_kwargs)
+            else:
+                path = urlquote(request.get_full_path())
+                tup = self.login_url, self.redirect_field_name, path
+                return HttpResponseRedirect('%s?%s=%s' % tup)

