Solve two annoying problems with ftp URLs for Jack: when repeated
retrieving files from the same host and directory, you had to close
the previous instance before opening a new one; and retrieving a
non-existent file would return an empty file.  (The latter fix relies
on maybe an undocumented property of NLST -- NLST of a file returns
just that file, while NLST of a non-existent file returns nothing.  A
side effect, unfortunately, seems to be that now ftp-retrieving an
*empty* directory may fail.  Ah well.)
diff --git a/Lib/urllib.py b/Lib/urllib.py
index a16529a..b9a82d1 100644
--- a/Lib/urllib.py
+++ b/Lib/urllib.py
@@ -497,6 +497,7 @@
 		self.init()
 	def init(self):
 		import ftplib
+		self.busy = 0
 		self.ftp = ftplib.FTP()
 		self.ftp.connect(self.host, self.port)
 		self.ftp.login(self.user, self.passwd)
@@ -504,6 +505,7 @@
 			self.ftp.cwd(dir)
 	def retrfile(self, file, type):
 		import ftplib
+		self.endtransfer()
 		if type in ('d', 'D'): cmd = 'TYPE A'; isdir = 1
 		else: cmd = 'TYPE ' + type; isdir = 0
 		try:
@@ -513,6 +515,13 @@
 			self.ftp.voidcmd(cmd)
 		conn = None
 		if file and not isdir:
+			# Use nlst to see if the file exists at all
+			try:
+				self.ftp.nlst(file)
+			except ftplib.error_perm, reason:
+				raise IOError, ('ftp error', reason), \
+				      sys.exc_info()[2]
+			# Try to retrieve as a file
 			try:
 				cmd = 'RETR ' + file
 				conn = self.ftp.transfercmd(cmd)
@@ -525,13 +534,18 @@
 			if file: cmd = 'LIST ' + file
 			else: cmd = 'LIST'
 			conn = self.ftp.transfercmd(cmd)
+		self.busy = 1
 		return addclosehook(conn.makefile('rb'), self.endtransfer)
 	def endtransfer(self):
+		if not self.busy:
+			return
+		self.busy = 0
 		try:
 			self.ftp.voidresp()
 		except ftperrors():
 			pass
 	def close(self):
+		self.endtransfer()
 		try:
 			self.ftp.close()
 		except ftperrors():