Index: django/conf/global_settings.py
===================================================================
--- django/conf/global_settings.py	(revision 11477)
+++ django/conf/global_settings.py	(working copy)
@@ -398,3 +398,11 @@
 
 # The list of directories to search for fixtures
 FIXTURE_DIRS = ()
+
+###############
+# BREADCRUMBS #
+###############
+
+# Enable/Disable breadcrumbs, default: disabled
+BREADCRUMBS = False
+BREADCRUMBS_AUTO_HOME = False
Index: django/forms/fields.py
===================================================================
--- django/forms/fields.py	(revision 11477)
+++ django/forms/fields.py	(working copy)
@@ -436,9 +436,11 @@
 try:
     from django.conf import settings
     URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT
+    URL_VERIFY_EXIST_SOCKET_TIMEOUT = settings.URL_VERIFY_EXIST_SOCKET_TIMEOUT
 except ImportError:
     # It's OK if Django settings aren't configured.
     URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
+    URL_VERIFY_EXIST_SOCKET_TIMEOUT = 10
 
 
 class FileField(Field):
@@ -543,6 +545,7 @@
     default_error_messages = {
         'invalid': _(u'Enter a valid URL.'),
         'invalid_link': _(u'This URL appears to be a broken link.'),
+        'invalid_timeout': _(u'This URL took to long to respond, appears to be broken.'),
     }
 
     def __init__(self, max_length=None, min_length=None, verify_exists=False,
@@ -563,7 +566,9 @@
         if value == u'':
             return value
         if self.verify_exists:
+            import socket
             import urllib2
+            import sys
             headers = {
                 "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
                 "Accept-Language": "en-us,en;q=0.5",
@@ -571,12 +576,25 @@
                 "Connection": "close",
                 "User-Agent": self.user_agent,
             }
+            if sys.version_info[:2]<(2,6):
+                def urlopen(req, timeout=None):
+                    socket_default_timeout = socket.getdefaulttimeout()
+                    socket.setdefaulttimeout(timeout)
+                    try:
+                        return urllib2.urlopen(req)
+                    finally:
+                        socket.setdefaulttimeout(socket_default_timeout)
+            else:
+                urlopen = urllib2.urlopen
+
             try:
                 req = urllib2.Request(value, None, headers)
-                u = urllib2.urlopen(req)
+                u = urlopen(req, timeout=URL_VERIFY_EXIST_SOCKET_TIMEOUT)
             except ValueError:
                 raise ValidationError(self.error_messages['invalid'])
-            except: # urllib2.URLError, httplib.InvalidURL, etc.
+            except Exception, e: # urllib2.URLError, httplib.InvalidURL, etc.
+                if e.args and isinstance(e.args[0], socket.timeout):
+                    raise ValidationError(self.error_messages['invalid_timeout'])
                 raise ValidationError(self.error_messages['invalid_link'])
         return value
 
Index: django/contrib/breadcrumbs/breadcrumbs.py
===================================================================
--- django/contrib/breadcrumbs/breadcrumbs.py	(revision 0)
+++ django/contrib/breadcrumbs/breadcrumbs.py	(revision 0)
@@ -0,0 +1,167 @@
+"""
+Classes to add request.breadcrumbs as one class to have a list of breadcrumbs
+TODO: maybe is better to move to contrib/breadcrumbs
+"""
+
+from django.conf import settings
+from django.utils.translation import ugettext_lazy as _
+from django.utils.safestring import mark_safe
+from django.utils.text import force_unicode 
+import sys
+
+class Singleton(object):
+    """
+    We use a simple singleton pattern in Breadcrumbs.
+    Example from http://svn.ademar.org/code/trunk/junk-code/singleton_vs_borg.py
+    """
+    def __new__(cls, *args, **kwds):
+        it = cls.__dict__.get("__it__")
+        if it is not None:
+            return it
+        cls.__it__ = it = object.__new__(cls)
+        it._1st_init(*args, **kwds)
+        return it
+
+    def _1st_init(self, *args, **kwds):
+        pass
+
+class BreadcrumbsInvalidFormat(Exception):
+    """
+    Simple exception that can be extended
+    """
+    pass
+
+class BreadcrumbsNotSet(Exception):
+    """
+    Raised in utils.breadcrumbs_for_flatpages when we not have breadcrumbs in
+    request.
+    """
+    pass
+
+class Breadcrumb(object):
+    """
+    Breadcrumb can have methods to customize breadcrumb object, Breadcrumbs
+    class send to us name and url.
+    """
+    def __init__(self,name,url):
+        # HERE
+        #
+        # If I don't use force_unicode, always runs ok, but have problems on
+        # template with unicode text
+        self.name = name
+        self.url = url
+
+    def __str__(self):
+        return self.__unicode__()
+
+    def __unicode__(self):
+        return u"%s,%s" % (self.name,self.url)
+
+    def __repr__(self):
+        return u"Breadcrumb <%s,%s>" % (self.name,self.url)
+
+class Breadcrumbs(Singleton):
+    """
+    Breadcrumbs maintain a list of breadcrumbs that you can get interating with
+    class or with get_breadcrumbs().
+    """
+    def _1st_init(self,*args,**kwargs):
+        """
+        singleton function that start some variables
+        """
+        self._clean()
+        self.__init__(*args,**kwargs)
+
+    def __call__(self,*args,**kwargs):
+        if not len(args) and not len(kwargs):
+            return self
+        return self.__init__(*args,**kwargs)
+
+    def _clean(self):
+        self.__bds = []
+        self.__autohome=settings.BREADCRUMBS_AUTO_HOME
+        self.__urls =[]
+
+    def __init__(self,*args,**kwargs):
+        """
+        Call validate and if ok, call fill bd
+        """
+        if settings.BREADCRUMBS:
+
+            # fill home if settings.BREADCRUMBS_AUTO_HOME is True
+            if self.__autohome and len(self.__bds) == 0:
+                self.__fill_bds( ( _("Home"), u"/" ) )
+
+            # match Breadcrumbs( 'name', 'url' )
+            if len(args) == 2 and type(args[0]) not in (list,tuple):
+                if(self.__validate(args,0)):
+                    self.__fill_bds( args )
+            # match ( ( 'name', 'url'), ..) and samething with list
+            elif len(args) == 1 and type(args[0]) in (list,tuple) \
+                    and len(args[0]) > 0:
+                for i,arg in enumerate(args[0]):
+                    if self.__validate(arg,i):
+                        self.__fill_bds( arg )
+            # try to ( obj1, obj2, ... ) and samething with list
+            else:
+                for i,arg in enumerate(args):
+                    if(self.__validate(arg,i)):
+                        self.__fill_bds( arg )
+
+    def __validate(self,obj,index):
+        """
+        check for object type and return a string as name for each item of a
+        list or tuple with items, if error was found raise
+        BreadcrumbsInvalidFormat
+        """
+        # for list or tuple
+        if type(obj) in (list,tuple):
+            if len(obj) == 2:
+                if (not obj[0] and not obj[1]) or \
+                ( type(obj[0]) not in (str,unicode) and \
+                  type(obj[1]) not in (str,unicode)):
+                    raise BreadcrumbsInvalidFormat(u"Invalid format for \
+                        breadcrumb %s in %s" % (index,type(obj).__name__))
+            if len(obj) != 2:
+                raise BreadcrumbsInvalidFormat(
+                    u"Wrong itens number in breadcrumb %s in %s. \
+                    You need to send as example (name,url)" % \
+                    (index,type(obj).__name__)
+                )
+        # for objects
+        elif not hasattr(obj,'name') and not hasattr(obj,'url'):
+            raise BreadcrumbsInvalidFormat(u"You need to use a tuple like"+ \
+                " (name,url) or object with name and url attributes for" + \
+                "breadcrumb.")
+        return True
+
+    def __fill_bds(self,bd):
+        """
+        simple interface to add Breadcrumb to bds
+        """
+        if hasattr(bd,'name') and hasattr(bd,'url'):
+            bd = Breadcrumb(bd.name,bd.url)
+        else:
+            bd = Breadcrumb(*bd)
+        if bd.url not in self.__urls:
+            self.__bds.append(bd)
+            self.__urls.append(bd.url)
+
+    def __iter__(self):
+        return iter(self.__bds)
+
+    def __getitem__(self,key):
+        return self.__bds[key]
+
+    def __repr__(self):
+        return self.__unicode__()
+
+    def __str__(self):
+        return self.__unicode__()
+
+    def __unicode__(self):
+        return u"Breadcrumbs <%s>" % u", ".join([mark_safe(item.name) for item in \
+            self[:10]] + [u' ...'])
+
+    def all(self):
+        return self.__bds
Index: django/contrib/breadcrumbs/middleware.py
===================================================================
--- django/contrib/breadcrumbs/middleware.py	(revision 0)
+++ django/contrib/breadcrumbs/middleware.py	(revision 0)
@@ -0,0 +1,7 @@
+from breadcrumbs import Breadcrumbs
+
+class BreadcrumbsMiddleware(object):
+
+    def process_request(self,request):
+        request.breadcrumbs = Breadcrumbs()
+        request.breadcrumbs._clean()
Index: django/contrib/breadcrumbs/__init__.py
===================================================================
--- django/contrib/breadcrumbs/__init__.py	(revision 0)
+++ django/contrib/breadcrumbs/__init__.py	(revision 0)
@@ -0,0 +1 @@
+from breadcrumbs import Breadcrumb
Index: django/contrib/breadcrumbs/utils.py
===================================================================
--- django/contrib/breadcrumbs/utils.py	(revision 0)
+++ django/contrib/breadcrumbs/utils.py	(revision 0)
@@ -0,0 +1,49 @@
+from breadcrumbs import Breadcrumbs,BreadcrumbsNotSet
+from django.contrib.flatpages.models import FlatPage
+from django.http import Http404
+
+def breadcrumbs_for_flatpages(request,flatpage):
+
+    if not hasattr(request,'breadcrumbs') or \
+        not isinstance(request.breadcrumbs,Breadcrumbs):
+        raise BreadcrumbNotSet(u"You need to setup breadcrumbs to use this " + \
+                "function.")
+
+    if not isinstance(flatpage,FlatPage) or \
+        not hasattr(flatpage,'id'):
+        raise TypeError(u"flatpage argument isn't a FlatPage instance or " + \
+            "not have id.")
+
+    paths = []
+    for part in request.path_info.split(u"/"):
+        # When split we have u"" for slashes
+        if len(part) == 0:
+            continue
+        # Add slash again
+        if not part.startswith(u"/"):
+            part = u"/"+part
+        if not part.endswith(u"/"):
+            part = part+u"/"
+        # If we have something on paths, url for flatpage is composed of what we
+        # have in path + part. Note that strins in path not have last slash, but
+        # part have.
+        if len(paths) > 0:
+            url = u"".join(paths+[part])
+        else:
+            url = part
+        # if is same url we don't hit database again
+        # else, get page from FlatPage. If page doesn't exist, we allow raise
+        # 404 because it is a url design problem, not flatpages or breadcrumbs
+        # problem.
+        if url == flatpage.url:
+            request.breadcrumbs(flatpage.title,flatpage.url)
+        else:
+            try:
+                f = FlatPage.objects.get(url=url)
+            except FlatPage.DoesNotExist:
+                raise Http404
+            else:
+                request.breadcrumbs(f.title,f.url)
+        # add last part of path in paths with one slash
+        paths.append(u"/"+url[1:-1].rpartition(u"/")[-1])
+
Index: django/contrib/breadcrumbs/tests.py
===================================================================
--- django/contrib/breadcrumbs/tests.py	(revision 0)
+++ django/contrib/breadcrumbs/tests.py	(revision 0)
@@ -0,0 +1,21 @@
+# run this script on your shell
+from django.contrib.breadcrumbs import Breadcrumbs
+
+bds = Breadcrumbs()
+
+# fill one per time
+for i in range(5):
+    bds( 'name%s' % i,'url%s' % i  )
+
+# create a simple class to emulate one object with name and url
+class emulatedobj(object):
+    def __init__(self,*args):
+        self.name = args[0]
+        self.url = args[1]
+
+# add 10 objects
+bds( [ emulatedobj('name %s' % (i+10), 'url %s' % (i+10)) for i in range(10) ] )
+
+# print all
+for bd in bds:
+    print bd.name,bd.url
Index: django/contrib/auth/views.py
===================================================================
--- django/contrib/auth/views.py	(revision 11477)
+++ django/contrib/auth/views.py	(working copy)
@@ -14,11 +14,11 @@
 from django.contrib.auth.models import User
 from django.views.decorators.cache import never_cache
 
-def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
+def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME, form_object=AuthenticationForm):
     "Displays the login form and handles the login action."
     redirect_to = request.REQUEST.get(redirect_field_name, '')
     if request.method == "POST":
-        form = AuthenticationForm(data=request.POST)
+        form = form_object(data=request.POST)
         if form.is_valid():
             # Light security check -- make sure redirect_to isn't garbage.
             if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
@@ -29,7 +29,7 @@
                 request.session.delete_test_cookie()
             return HttpResponseRedirect(redirect_to)
     else:
-        form = AuthenticationForm(request)
+        form = form_object(request)
     request.session.set_test_cookie()
     if Site._meta.installed:
         current_site = Site.objects.get_current()
Index: django/contrib/flatpages/views.py
===================================================================
--- django/contrib/flatpages/views.py	(revision 11477)
+++ django/contrib/flatpages/views.py	(working copy)
@@ -5,6 +5,7 @@
 from django.conf import settings
 from django.core.xheaders import populate_xheaders
 from django.utils.safestring import mark_safe
+from django.contrib.breadcrumbs.utils import breadcrumbs_for_flatpages
 
 DEFAULT_TEMPLATE = 'flatpages/default.html'
 
@@ -29,6 +30,9 @@
     if f.registration_required and not request.user.is_authenticated():
         from django.contrib.auth.views import redirect_to_login
         return redirect_to_login(request.path)
+    # if user enabled contrib.breadcrumbs add page to breadcrumbs
+    if settings.BREADCRUMBS:
+        breadcrumbs_for_flatpages(request,f)
     if f.template_name:
         t = loader.select_template((f.template_name, DEFAULT_TEMPLATE))
     else:
