[Zope3-checkins] CVS: Zope3/lib/python/Zope/Server/FTP - FTPServerChannel.py:1.5 FTPStatusMessages.py:1.3 IFTPCommandHandler.py:1.3 OSEmulators.py:1.3
Stephan Richter
srichter@cbu.edu
Fri, 20 Dec 2002 04:26:16 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/Server/FTP
In directory cvs.zope.org:/tmp/cvs-serv31450/Zope/Server/FTP
Modified Files:
FTPServerChannel.py FTPStatusMessages.py IFTPCommandHandler.py
OSEmulators.py
Log Message:
Refactoring and fixing VFS and FTP
I am glad to make this commit that fixes up a lot of the FTP
implementation. I fixed the behavior of many of the FTP commands,
including LIST, SIZE, and CWD.
I moved the original VFSFile/DirectoryView into abstract classes and wrote
a special implementation for each content type, which makes the code much
more flexible.
Also I finally implemented a smart way of adding files via VFS through
file extension introspection, based on Jim's ExtensionViewName proposal.
I am adding documentation in the DevelCookbook right now and will later
add a README file.
TODOs:
- make VFS View names flexible, so that file extensions specify views.
- Simplify ZCML directives, so that one can add new extensions for Add views
quicker. A solution might look like that:
<vfs:view
name=".dtml"
for="Zope.App.OFS.Container.IAdding."
factory=".DTMLPageAdd."
permission="Zope.ManageContent">
<vfs:extension name=".html" />
<vfs:extension name=".xul" />
<vfs:extension name=".xml" />
...
</vfs:view>
This method would also be good for defining a default fiel extension.
- Show an object with its default file extension.
=== Zope3/lib/python/Zope/Server/FTP/FTPServerChannel.py 1.4 => 1.5 ===
--- Zope3/lib/python/Zope/Server/FTP/FTPServerChannel.py:1.4 Mon Nov 11 09:55:37 2002
+++ Zope3/lib/python/Zope/Server/FTP/FTPServerChannel.py Fri Dec 20 04:25:44 2002
@@ -124,8 +124,9 @@
def cmd_cwd(self, args):
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
+ fs = self._getFilesystem()
path = self._generatePath(args)
- if self._getFilesystem().exists(path):
+ if fs.exists(path) and fs.isdir(path):
self.cwd = path
self.reply('SUCCESS_250', 'CWD')
else:
@@ -156,9 +157,14 @@
def cmd_list(self, args, long=1):
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
+ fs = self._getFilesystem()
+ path = self._generatePath(args)
+ if not fs.exists(path):
+ self.reply('ERR_NO_DIR_FILE', path)
+ return
args = args.split()
try:
- s = self.getDirectoryList(args, long)
+ s = self.getList(args, long)
except OSError, err:
self.reply('ERR_NO_LIST', str(err))
return
@@ -174,12 +180,13 @@
def cmd_mdtm(self, args):
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
+ fs = self._getFilesystem()
# We simply do not understand this non-standard extension to MDTM
if len(args.split()) > 1:
self.reply('ERR_ARGS')
return
path = self._generatePath(args)
- if not self._getFilesystem().isfile(path):
+ if not fs.exists(path) or not fs.isfile(path):
self.reply('ERR_IS_NOT_FILE', path)
else:
mtime = time.gmtime(
@@ -249,7 +256,6 @@
def cmd_port(self, args):
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
-
info = args.split(',')
ip = '.'.join(info[:4])
port = int(info[4])*256 + int(info[5])
@@ -274,11 +280,12 @@
def cmd_retr(self, args):
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
+ fs = self._getFilesystem()
if not args:
self.reply('CMD_UNKNOWN', 'RETR')
path = self._generatePath(args)
- if not self._getFilesystem().isfile(path):
+ if not fs.exists(path) or not fs.isfile(path):
self.reply('ERR_IS_NOT_FILE', path)
return
@@ -295,8 +302,7 @@
outstream = ApplicationXmitStream(cdc)
try:
- self._getFilesystem().readfile(
- path, mode, outstream, start)
+ fs.readfile(path, mode, outstream, start)
cdc.close_when_done()
except OSError, err:
cdc.close('ERR_OPEN_READ', str(err))
@@ -357,7 +363,7 @@
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
path = self._generatePath(args)
fs = self._getFilesystem()
- if not fs.isfile(path):
+ if not fs.exists(path) or not fs.isfile(path):
self.reply('ERR_NO_FILE', path)
else:
self.reply('FILE_SIZE', fs.stat(path)[stat.ST_SIZE])
@@ -471,17 +477,9 @@
return self.passive_acceptor
- def listdir(self, path, long=0):
- """returns a string"""
- path = self._generatePath(path)
- file_list = self._getFilesystem().listdir(path, long)
- if long:
- file_list = map(ls_longify, file_list)
- return ''.join(map(lambda line: line + '\r\n', file_list))
-
-
- def getDirectoryList(self, args, long=0):
+ def getList(self, args, long=0):
# we need to scan the command line for arguments to '/bin/ls'...
+ fs = self._getFilesystem()
path_args = []
for arg in args:
if arg[0] != '-':
@@ -490,12 +488,20 @@
# ignore arguments
pass
if len(path_args) < 1:
- dir = '.'
+ path = '.'
+ else:
+ path = path_args[0]
+
+ path = self._generatePath(path)
+ if fs.isdir(path):
+ file_list = fs.listdir(path, long)
else:
- dir = path_args[0]
+ file_list = [ (posixpath.split(path)[1], fs.stat(path)) ]
+ # Make a pretty unix-like FTP output
+ if long:
+ file_list = map(ls_longify, file_list)
+ return ''.join(map(lambda line: line + '\r\n', file_list))
- dir = self._generatePath(dir)
- return self.listdir(dir, long)
def connectDataChannel(self, cdc):
=== Zope3/lib/python/Zope/Server/FTP/FTPStatusMessages.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Server/FTP/FTPStatusMessages.py:1.2 Mon Jun 10 19:29:35 2002
+++ Zope3/lib/python/Zope/Server/FTP/FTPStatusMessages.py Fri Dec 20 04:25:44 2002
@@ -54,9 +54,10 @@
"'%s' command",
'LOGIN_REQUIRED' : '530 Please log in with USER and PASS',
'LOGIN_MISMATCH' : '530 The username and password do not match.',
- 'ERR_NO_LIST' : '550 Could not list directory: %s',
+ 'ERR_NO_LIST' : '550 Could not list directory or file: %s',
'ERR_NO_DIR' : '550 "%s": No such directory.',
'ERR_NO_FILE' : '550 "%s": No such file.',
+ 'ERR_NO_DIR_FILE' : '550 "%s": No such file or directory.',
'ERR_IS_NOT_FILE' : '550 "%s": Is not a file',
'ERR_CREATE_FILE' : '550 Error creating file.',
'ERR_CREATE_DIR' : '550 Error creating directory: %s',
=== Zope3/lib/python/Zope/Server/FTP/IFTPCommandHandler.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Server/FTP/IFTPCommandHandler.py:1.2 Mon Jun 10 19:29:35 2002
+++ Zope3/lib/python/Zope/Server/FTP/IFTPCommandHandler.py Fri Dec 20 04:25:44 2002
@@ -35,7 +35,7 @@
"""
def cmd_list(args):
- """Give list files in a directory.
+ """Give list files in a directory or displays the info of one file.
"""
def cmd_mdtm(args):
=== Zope3/lib/python/Zope/Server/FTP/OSEmulators.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Server/FTP/OSEmulators.py:1.2 Mon Jun 10 19:29:35 2002
+++ Zope3/lib/python/Zope/Server/FTP/OSEmulators.py Fri Dec 20 04:25:44 2002
@@ -11,16 +11,16 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""
+"""OS-Emulator Package
+
+Simulates OS-level directory listing output for *nix and MS-DOS (including
+Windows NT).
$Id$
"""
import stat
-import time
-
-months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
- 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+import datetime
mode_table = {
'0':'---',
@@ -49,7 +49,7 @@
dirchar = 'd'
else:
dirchar = '-'
- date = ls_date (long(time.time()), stat_info[stat.ST_MTIME])
+ date = ls_date(datetime.datetime.now(), stat_info[stat.ST_MTIME])
return '%s%s %3d %-8s %-8s %8d %s %s' % (
dirchar,
mode,
@@ -62,7 +62,7 @@
)
-def ls_date (now, t):
+def ls_date(now, t):
"""Emulate the 'ls' command's date field. It has two formats.
If the date is more than 180 days in the past or future, then
it's like this:
@@ -70,25 +70,10 @@
otherwise, it looks like this:
Oct 19 17:33
"""
- try:
- info = time.localtime(t)
- except:
- info = time.localtime(0)
-
- # 15,600,000 == 86,400 * 180
- if abs((now - t) > 15600000):
- return '%s %2d %5d' % (
- months[info[1]-1],
- info[2],
- info[0]
- )
+ if abs((now - t).days) > 180:
+ return t.strftime('%b %d, %Y')
else:
- return '%s %2d %02d:%02d' % (
- months[info[1]-1],
- info[2],
- info[3],
- info[4]
- )
+ return t.strftime('%b %d %H:%M')
def msdos_longify((file, stat_info)):
@@ -104,17 +89,7 @@
def msdos_date(t):
- try:
- info = time.gmtime(t)
- except:
- info = time.gmtime(0)
-
- # year, month, day, hour, minute, second, ...
- if info[3] > 11:
- merid = 'PM'
- info[3] = info[3] - 12
- else:
- merid = 'AM'
-
- return '%02d-%02d-%02d %02d:%02d%s' % (
- info[1], info[2], info[0]%100, info[3], info[4], merid )
+ """Emulate MS-DOS 'dir' command. Example:
+ 09-19-95 05:33PM
+ """
+ return t.strftime('%m-%d-%y %H:%M%p')