[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/FTP - FTPServerChannel.py:1.1.2.13 FTPStatusMessages.py:1.1.2.6 RecvChannel.py:1.1.2.4 XmitChannel.py:1.1.2.3

Stephan Richter srichter@cbu.edu
Fri, 5 Apr 2002 10:18:48 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/Server/FTP
In directory cvs.zope.org:/tmp/cvs-serv20940/FTP

Modified Files:
      Tag: Zope3-Server-Branch
	FTPServerChannel.py FTPStatusMessages.py RecvChannel.py 
	XmitChannel.py 
Log Message:
Changed Status messages mechanism.


=== Zope3/lib/python/Zope/Server/FTP/FTPServerChannel.py 1.1.2.12 => 1.1.2.13 ===
                        'cmd_rnto', 'cmd_size', 'cmd_stor', 'cmd_stru')
 
-    # Define the reply code for non-authenticated responses
-    not_auth_reply = (530, 1)
-
-    # Define the reply code for an unrecognized command
-    unknown_reply = (500, 0)
-
     # Define the status messages
     status_messages = status_msgs
 
@@ -94,7 +88,7 @@
         self.username = ''
         self.password = ''
 
-        self.reply(220, 0, self.server.server_name)
+        self.reply('SERVER_READY', self.server.server_name)
 
 
     ############################################################
@@ -105,7 +99,7 @@
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if self.client_dc:
             self.client_dc.close()
-        self.reply(226, 0, 'ABOR')
+        self.reply('TRANS_SUCCESS', 'ABOR')
 
 
     def cmd_appe (self, args):
@@ -118,9 +112,9 @@
         path = self._generatePath('../')
         if self.server.filesystem.exists(path):
             self.cwd = path
-            self.reply(250, 0, 'CDUP')
+            self.reply('SUCCESS_250', 'CDUP')
         else:
-            self.reply(550, 2, path)
+            self.reply('ERR_NO_FILE', path)
 
 
     def cmd_cwd(self, args):
@@ -128,32 +122,32 @@
         path = self._generatePath(args)
         if self.server.filesystem.exists(path):
             self.cwd = path
-            self.reply(250, 0, 'CWD')
+            self.reply('SUCCESS_250', 'CWD')
         else:
-            self.reply(550, 1, path)
+            self.reply('ERR_NO_DIR', path)
 
 
     def cmd_dele(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if not args:
-            self.reply(500, 0, 'DELE')
+            self.reply('CMD_UNKNOWN', 'DELE')
         else:
             path = self._generatePath(args)
 
             try:
                 self.server.filesystem.unlink(path)
-                self.reply(250, 0, 'DELE')
+                self.reply('SUCCESS_250', 'DELE')
             except:
-                self.reply(550, 6)
+                self.reply('ERR_DELETE_FILE')
             else:
-                self.reply(550, 2, file)
+                self.reply('NO_FILE', file)
 
 
     def cmd_help(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
-        self.reply(214, flush=0)
+        self.reply('HELP_START')
         self.write('Help goes here somewhen.\r\n')
-        self.reply(214, 1)
+        self.reply('HELP_END')
 
 
     def cmd_list(self, args):
@@ -162,10 +156,10 @@
         try:
             producer = self.getDirectoryList(args, 1)
         except os.error, why:
-            self.reply(550, 0, repr(why))
+            self.reply('ERR_NO_LIST', repr(why))
             return
 
-        self.reply(150, 0, self.type_map[self.transfer_mode])
+        self.reply('OPEN_DATA_CONN', self.type_map[self.transfer_mode])
         self.createXmitChannel()
         self.client_dc.push_with_producer(producer)
         self.client_dc.close_when_done()
@@ -175,35 +169,35 @@
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         path = self._generatePath(args)
         if not self.server.filesystem.isfile(path):
-            self.reply(550, 3, path)
+            self.reply('ERR_IS_NOT_FILE', path)
         else:
             mtime = time.gmtime(
                 self.server.filesystem.stat(path)[stat.ST_MTIME]
                 )
-            self.reply(213, 0, (mtime[0], mtime[1], mtime[2],
-                                mtime[3], mtime[4], mtime[5]) )
+            self.reply('FILE_DATE', (mtime[0], mtime[1], mtime[2],
+                                     mtime[3], mtime[4], mtime[5]) )
 
 
     def cmd_mkd(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if not args:
-            self.reply(500, 0, 'MKD')
+            self.reply('CMD_UNKNOWN', 'MKD')
         else:
             path = self._generatePath(args)
 
             try:
                 self.server.filesystem.mkdir(path)
-                self.reply(257, 0, 'MKD')
+                self.reply('SUCCESS_257', 'MKD')
             except:
-                self.reply (550, 5)
+                self.reply('ERR_CREATE_DIR')
 
 
     def cmd_mode(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if len(args) == 1 and args in 'sS':
-            self.reply(200, 3)
+            self.reply('MODE_OK')
         else:
-            self.reply(502)
+            self.reply('MODE_UNKNOWN')
 
 
     def cmd_nlst(self, args):
@@ -216,18 +210,18 @@
         try:
             producer = self.getDirectoryList(args, 0)
         except os.error, why:
-            self.reply( 550, 0, (repr(why),) )
+            self.reply('ERR_NO_LIST', repr(why))
             return
 
         self.createXmitChannel()
         self.client_dc.push_with_producer(producer)
         self.client_dc.close_when_done()
-        self.reply(150, 0, (self.type_map[self.transfer_mode],))
+        self.reply('OPEN_DATA_CONN', (self.type_map[self.transfer_mode],))
 
 
     def cmd_noop(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
-        self.reply(200, 0, ('NOOP'))
+        self.reply('SUCCESS_200', 'NOOP')
 
 
     def cmd_pass(self, args):
@@ -237,9 +231,9 @@
         self.authenticated, message = auth.authenticate(self.username,
                                                         self.password)
         if self.authenticated:
-            self.reply(230)
+            self.reply('LOGIN_SUCCESS')
         else:
-            self.reply(530, 2)
+            self.reply('LOGIN_MISMATCH')
             self.close_when_done()
 
 
@@ -249,9 +243,9 @@
         self.client_dc = None
         port = pc.addr[1]
         ip_addr = pc.control_channel.getsockname()[0]
-        self.reply(227, args=( ','.join(ip_addr.split('.')),
-                               port/256,
-                               port%256 ) )
+        self.reply('PASV_MODE_MSG', (','.join(ip_addr.split('.')),
+                                     port/256,
+                                     port%256 ) )
 
 
     def cmd_port(self, args):
@@ -266,27 +260,26 @@
             # XXX: we should (optionally) verify that the
             # ip number belongs to the client.  [wu-ftpd does this?]
             self.client_addr = (ip, port)
-            self.reply(200, 0, 'PORT')
+            self.reply('SUCCESS_200', 'PORT')
         except:
-            return self.reply(550, 0, 'PORT')
-
+            return self.reply('CMD_UNKNOWN', 'PORT')
 
 
     def cmd_pwd(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
-        self.reply(257, 0, self.cwd)
+        self.reply('SUCCESS_257', self.cwd)
 
 
     def cmd_quit(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
-        self.reply(221)
+        self.reply('GOODBYE')
         self.close_when_done()
 
 
     def cmd_retr(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if not args:
-            self.reply(550, 0, 'RETR')
+            self.reply('CMD_UNKNOWN', 'RETR')
         else:
             path = self._generatePath(args)
 
@@ -299,9 +292,10 @@
                     mode = 'r'+self.type_mode_map[self.transfer_mode]
                     fd = self.server.filesystem.open(path, mode)
                 except IOError, why:
-                    self.reply(553, 0, repre(why))
+                    self.reply('ERR_OPEN_READ', repre(why))
                     return
-                self.reply(150, 1, (self.type_map[self.transfer_mode], path) )
+                self.reply('OPEN_CONN',
+                           (self.type_map[self.transfer_mode], path) )
                 self.createXmitChannel()
 
                 if self.restart_position:
@@ -325,22 +319,22 @@
         try:
             pos = int(args)
         except ValueError:
-            self.reply(500, 0, 'REST')
+            self.reply('CMD_UNKNWON', 'REST')
         self.restart_position = pos
-        self.reply(350, 0, pos)
+        self.reply('RESTART_TRANSFER', pos)
 
 
     def cmd_rmd(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if not args:
-            self.reply(500, 0, 'RMD')
+            self.reply('CMD_UNKNOWN', 'RMD')
         else:
             path = self._generatePath(args)
             try:
                 self.server.filesystem.rmdir(path)
-                self.reply(250, 0, 'RMD')
+                self.reply('SUCCESS_250', 'RMD')
             except:
-                self.reply(550, 7)
+                self.reply('ERR_DELETE_DIR')
 
 
     def cmd_rnfr(self, args):
@@ -348,21 +342,21 @@
         path = self._generatePath(args)
         if self.server.filesystem.exists(path):
             self._rnfr = path
-            self.reply(350, 1)
+            self.reply('READY_FOR_DEST')
         else:
-            self.reply(550, 2, path)
+            self.reply('ERR_NO_FILE', path)
 
 
     def cmd_rnto(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         path = self._generatePath(args)
         if self._rnfr is None:
-            self.reply(560, 1)
+            self.reply('ERR_RENAME')
         try:
             self.server.filesystem.rename(self._rnfr, path)
-            self.reply(250, 0, 'RNTO')
+            self.reply('SUCCESS_250', 'RNTO')
         except:
-            self.reply(560, 0, (self._rnfr, rnto))
+            self.reply('ERR_RENAME', (self._rnfr, rnto))
         self._rnfr = None
 
 
@@ -370,44 +364,44 @@
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         path = self._generatePath(args)
         if not self.server.filesystem.isfile(path):
-            self.reply(550, 2, path)
+            self.reply('ERR_NO_FILE', path)
         else:
-            self.reply(213, 1,
+            self.reply('FILE_SIZE',
                        self.server.filesystem.stat(path)[stat.ST_SIZE])
 
 
     def cmd_stor(self, args, mode='wb'):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if not args:
-            self.reply(550, 0, 'STOR')
+            self.reply('CMD_UNKNOWN', 'STOR')
         else:
             path = self._generatePath(args)
 
             if self.restart_position:
                 restart_position = 0
-                self.reply(553, 2)
+                self.reply('ERR_RESTART_STOR')
                 return
             # todo: handle that type flag
             try:
                 fd = self.server.filesystem.open(args, mode)
             except IOError, why:
-                self.reply(553, 1, repr(why))
+                self.reply('ERR_OPEN_WRITE', repr(why))
                 return
-            self.reply(150, 1, (self.type_map[self.transfer_mode], file) )
+            self.reply('OPEN_CONN', (self.type_map[self.transfer_mode], file) )
             self.createRecvChannel(fd)
 
 
     def cmd_stru(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if len(args) == 1 and args in 'fF':
-            self.reply(200, 2)
+            self.reply('STRU_OK')
         else:
-            self.reply(504, 1)
+            self.reply('STRU_UNKNOWN')
 
 
     def cmd_syst(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
-        self.reply(215, 0, self.system)
+        self.reply('SERVER_TYPE', self.system)
 
 
     def cmd_type(self, args):
@@ -418,24 +412,24 @@
         # no support for EBCDIC
         # if t not in ['a','e','i','l']:
         if t not in ['a','i','l']:
-            self.reply(500, 0, args=('TYPE',))
+            self.reply('CMD_UNKNOWN', 'TYPE')
 
         elif t == 'l' and (len(args) > 2 and args[2] != '8'):
-            self.reply(504, 0)
+            self.reply('WRONG_BYTE_SIZE')
 
         else:
             if t == 'a':
                 self.transfer_mode = t
-            self.reply(200, 1, self.type_map[t])
+            self.reply('TYPE_SET_OK', self.type_map[t])
 
 
     def cmd_user(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         if len(args) > 1:
             self.username = args
-            self.reply(331)  # Or whatever the code should be
+            self.reply('PASS_REQUIRED')
         else:
-            self.reply(500, 0, ('USER'))
+            self.reply('CMD_UNKNOWN', 'USER')
 
     #
     ############################################################


=== Zope3/lib/python/Zope/Server/FTP/FTPStatusMessages.py 1.1.2.5 => 1.1.2.6 ===
 
 status_msgs = {
-    150: ('Opening %s mode data connection for file list',
-          'Opening %s connection for %s',),
-    200: ('%s command successful.',
-          'Type set to %s.',
-          'STRU F Ok.',
-          'MODE S Ok.',),
-    213: ('%4d%02d%02d%02d%02d%02d', # A date
-          '%d Bytes'), # Size
-    214: ('-The following commands are recognized',
-          ''),
-    215: ('%s Type: %s',),  # Server Type
-    220: ('%s FTP server (Zope Async/Thread V0.1) ready.',),
-    221: ('Goodbye.',),
-    226: ('%s command successful.',
-          'Transfer successful.'),
-    227: ('Entering Passive Mode (%s,%d,%d)',),
-    230: ('Login Successful.',),
-    250: ('%s command successful.',),
-    257: ('%s command successful.',
-          "'%s' is the current directory.",),
-    331: ('Password required',),
-    350: ('Restarting at %d. Send STORE or RETRIEVE to initiate transfer.',
-          'File exists, ready for destination.',),
-    425: ("Can't build data connection",),
-    426: ('Connection closed; transfer aborted.',),
-    500: ("'%s': command not understood.",),
-    502: ("Unimplemented MODE type",),
-    504: ('Byte size must be 8',
-          'Unimplemented STRU type',),
-    530: ("You are not authorized to perform the '%s' command",
-          'Please log in with USER and PASS',
-          'The username and password do not match.',),
-    550: ('Could not list directory: %s',
-          '%s: No such directory.',
-          '%s: No such file.',
-          '%s: Is not a file',
-          'Error creating file.',
-          'Error creating directory.',
-          'Error deleting file.',
-          'Error removing directory.'),
-    553: ('Could not open file for reading: %s',
-          'Could not open file for writing: %s',
-          'Restart on STOR not yet supported',),
-
-    560: ('Could not rename %s to %s.',
-          'No source filename specify. Call RNFR first.',),
+    'OPEN_DATA_CONN'   : '150 Opening %s mode data connection for file list',
+    'OPEN_CONN'        : '150 Opening %s connection for %s',
+    'SUCCESS_200'      : '200 %s command successful.',
+    'TYPE_SET_OK'      : '200 Type set to %s.',
+    'STRU_OK'          : '200 STRU F Ok.',
+    'MODE_OK'          : '200 MODE S Ok.',
+    'FILE_DATE'        : '213 %4d%02d%02d%02d%02d%02d', 
+    'FILE_SIZE'        : '213 %d Bytes',
+    'HELP_START'       : '214-The following commands are recognized',
+    'HELP_END'         : '214 Help done.',
+    'SERVER_TYPE'      : '215 %s Type: %s',
+    'SERVER_READY'     : '220 %s FTP server (Zope Async/Thread V0.1) ready.',
+    'GOODBYE'          : '221 Goodbye.',
+    'SUCCESS_226'      : '226 %s command successful.',
+    'TRANS_SUCCESS'    : '226 Transfer successful.',
+    'PASV_MODE_MSG'    : '227 Entering Passive Mode (%s,%d,%d)',
+    'LOGIN_SUCCESS'    : '230 Login Successful.',
+    'SUCCESS_250'      : '250 %s command successful.',
+    'SUCCESS_257'      : '257 %s command successful.',
+    'ALREADY_CURRENT'  : "257 '%s' is the current directory.",
+    'PASS_REQUIRED'    : '331 Password required',
+    'RESTART_TRANSFER' : '350 Restarting at %d. Send STORE or '
+                         'RETRIEVE to initiate transfer.',
+    'READY_FOR_DEST'   : '350 File exists, ready for destination.',
+    'NO_DATA_CONN'     : "425 Can't build data connection",
+    'TRANSFER_ABORTED' : '426 Connection closed; transfer aborted.',
+    'CMD_UNKNOWN'      : "500 '%s': command not understood.",
+    'MODE_UNKOWN'      : '502 Unimplemented MODE type',
+    'WRONG_BYTE_SIZE'  : '504 Byte size must be 8',
+    'STRU_UNKNOWN'     : '504 Unimplemented STRU type',
+    'NOT_AUTH'         : "530 You are not authorized to perform the "
+                         "'%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_DIR'       : '550 %s: No such directory.',
+    'ERR_NO_FILE'      : '550 %s: No such file.',
+    'ERR_IS_NOT_FILE'  : '550 %s: Is not a file',
+    'ERR_CREATE_FILE'  : '550 Error creating file.',
+    'ERR_CREATE_DIR'   : '550 Error creating directory.',
+    'ERR_DELETE_FILE'  : '550 Error deleting file.',
+    'ERR_DELETE_DIR'   : '550 Error removing directory.',
+    'ERR_OPEN_READ'    : '553 Could not open file for reading: %s',
+    'ERR_OPEN_WRITE'   : '553 Could not open file for writing: %s',
+    'ERR_RESTART_STOR' : '553 Restart on STOR not yet supported',
+    'ERR_RENAME'       : '560 Could not rename %s to %s.',
+    'ERR_RNFR_SOURCE'  : '560 No source filename specify. Call RNFR first.',
     }
 


=== Zope3/lib/python/Zope/Server/FTP/RecvChannel.py 1.1.2.3 => 1.1.2.4 ===
         s.total_bytes_in.increment(self.bytes_in.as_long())
         self.fd.close()
-        self.channel.reply(226, 1)
+        self.channel.reply('TRANS_SUCCESS')
         self.close()


=== Zope3/lib/python/Zope/Server/FTP/XmitChannel.py 1.1.2.2 => 1.1.2.3 ===
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""
-
-$Id$
-"""
-
-import asynchat
-
-
-class XmitChannel(asynchat.async_chat, object):
-
-    # for an ethernet, you want this to be fairly large, in fact, it
-    # _must_ be large for performance comparable to an ftpd.  [64k] we
-    # ought to investigate automatically-sized buffers...
-    ac_out_buffer_size = 16384
-
-    bytes_out = 0
-
-    def __init__ (self, channel, client_addr=None):
-        self.channel = channel
-        self.client_addr = client_addr
-        super(XmitChannel, self).__init__()
-
-
-    def log (*args):
-        pass
-
-
-    def readable (self):
-        return not self.connected
-
-
-    def writable (self):
-        return 1
-
-
-    def send (self, data):
-        result = super(XmitChannel, self).send(data)
-        self.bytes_out = self.bytes_out + result
-        return result
-
-
-    def handle_error (self):
-        # usually this is to catch an unexpected disconnect.
-        # XXX: Helpfule for debugging
-        import traceback
-        traceback.print_exc()
-        self.log_info ('unexpected disconnect on data xmit channel', 'error')
-        try:
-            self.close()
-        except:
-            pass
-
-    # TODO: there's a better way to do this.  we need to be able to
-    # put 'events' in the producer fifo.  to do this cleanly we need
-    # to reposition the 'producer' fifo as an 'event' fifo.
-
-    # dummy function to suppress warnings caused by some FTP clients
-    def handle_connect(self):
-        pass
-
-
-    def close (self):
-        c = self.channel
-        s = c.server
-        c.client_dc = None
-        s.total_files_out.increment()
-        s.total_bytes_out.increment (self.bytes_out)
-        if not len(self.producer_fifo):
-            c.reply(226, 1)
-        elif not c.closed:
-            c.reply(426)
-        del c
-        del s
-        del self.channel
-        asynchat.async_chat.close(self)
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+
+import asynchat
+
+
+class XmitChannel(asynchat.async_chat, object):
+
+    # for an ethernet, you want this to be fairly large, in fact, it
+    # _must_ be large for performance comparable to an ftpd.  [64k] we
+    # ought to investigate automatically-sized buffers...
+    ac_out_buffer_size = 16384
+
+    bytes_out = 0
+
+    def __init__ (self, channel, client_addr=None):
+        self.channel = channel
+        self.client_addr = client_addr
+        super(XmitChannel, self).__init__()
+
+
+    def log (*args):
+        pass
+
+
+    def readable (self):
+        return not self.connected
+
+
+    def writable (self):
+        return 1
+
+
+    def send (self, data):
+        result = super(XmitChannel, self).send(data)
+        self.bytes_out = self.bytes_out + result
+        return result
+
+
+    def handle_error (self):
+        # usually this is to catch an unexpected disconnect.
+        # XXX: Helpfule for debugging
+        import traceback
+        traceback.print_exc()
+        self.log_info ('unexpected disconnect on data xmit channel', 'error')
+        try:
+            self.close()
+        except:
+            pass
+
+    # TODO: there's a better way to do this.  we need to be able to
+    # put 'events' in the producer fifo.  to do this cleanly we need
+    # to reposition the 'producer' fifo as an 'event' fifo.
+
+    # dummy function to suppress warnings caused by some FTP clients
+    def handle_connect(self):
+        pass
+
+
+    def close (self):
+        c = self.channel
+        s = c.server
+        c.client_dc = None
+        s.total_files_out.increment()
+        s.total_bytes_out.increment (self.bytes_out)
+        if not len(self.producer_fifo):
+            c.reply('TRANS_SUCCESS')
+        elif not c.closed:
+            c.reply('TRANSFER_ABORTED')
+        del c
+        del s
+        del self.channel
+        asynchat.async_chat.close(self)