Patch #711838: Allow non-anonymous ftp urls in urllib2.
Backported to 2.3.
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index 0980ce2..9f6dc63 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -115,7 +115,7 @@
 # not sure how many of these need to be gotten rid of
 from urllib import unwrap, unquote, splittype, splithost, \
      addinfourl, splitport, splitgophertype, splitquery, \
-     splitattr, ftpwrapper, noheaders
+     splitattr, ftpwrapper, noheaders, splituser, splitpasswd
 
 # support for FileHandler, proxies via environment variables
 from urllib import localhost, url2pathname, getproxies
@@ -1090,21 +1090,30 @@
         host = req.get_host()
         if not host:
             raise IOError, ('ftp error', 'no host given')
-        # XXX handle custom username & password
+        host, port = splitport(host)
+        if port is None:
+            port = ftplib.FTP_PORT
+
+        # username/password handling
+        user, host = splituser(host)
+        if user:
+            user, passwd = splitpasswd(user)
+        else:
+            passwd = None
+        host = unquote(host)
+        user = unquote(user or '')
+        passwd = unquote(passwd or '')
+
         try:
             host = socket.gethostbyname(host)
         except socket.error, msg:
             raise URLError(msg)
-        host, port = splitport(host)
-        if port is None:
-            port = ftplib.FTP_PORT
         path, attrs = splitattr(req.get_selector())
         dirs = path.split('/')
         dirs = map(unquote, dirs)
         dirs, file = dirs[:-1], dirs[-1]
         if dirs and not dirs[0]:
             dirs = dirs[1:]
-        user = passwd = '' # XXX
         try:
             fw = self.connect_ftp(user, passwd, host, port, dirs)
             type = file and 'I' or 'D'
diff --git a/Misc/NEWS b/Misc/NEWS
index 4f16e2e..3fdef4b 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -237,6 +237,8 @@
 Library
 -------
 
+- Support non-anonymous ftp URLs in urllib2.
+
 - The encodings package will now applies codec name aliases
   first before starting to try the import of the codec module.
   This simplifies overriding built-in codecs with external