[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/FTP - OSEmulators.py:1.1.2.1 PublisherFTPServerChannel.py:1.1.2.1 FTPServerChannel.py:1.1.2.19 PublisherFTPServer.py:1.1.2.5

Stephan Richter srichter@cbu.edu
Tue, 9 Apr 2002 20:23:04 -0400


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

Modified Files:
      Tag: Zope3-Server-Branch
	FTPServerChannel.py PublisherFTPServer.py 
Added Files:
      Tag: Zope3-Server-Branch
	OSEmulators.py PublisherFTPServerChannel.py 
Log Message:
This check-in makes the Publisher FTP Server finally work. Yipee!
Everything worked out much better than I hope and my protyping turned out
to be an overkill. Now it is time to clean up some things and complete the
code. Things that need to be done:

1. Finish File view, so that read and write can be supported.
2. Implement security. Right now it allows any username/password pair.
3. Fix bugs and remove debugging statements.
4. Write tests.


=== Added File Zope3/lib/python/Zope/Server/FTP/OSEmulators.py ===
##############################################################################
#
# 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: OSEmulators.py,v 1.1.2.1 2002/04/10 00:23:02 srichter Exp $
"""

import stat
import time
import pwd, grp

months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
          'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

mode_table = {
        '0':'---',
        '1':'--x',
        '2':'-w-',
        '3':'-wx',
        '4':'r--',
        '5':'r-x',
        '6':'rw-',
        '7':'rwx'
        }


def unix_longify((file, stat_info)):
        # for now, only pay attention to the lower bits

    try: username = pwd.getpwuid(int(stat_info[stat.ST_UID]))[0]
    except: username = stat_info[stat.ST_UID]

    try: grpname = grp.getgrgid(int(stat_info[stat.ST_GID]))[0]
    except: grpname = stat_info[stat.ST_GID]


    mode = ('%o' % stat_info[stat.ST_MODE])[-3:]
    mode = ''.join(map (lambda x: mode_table[x], mode))
    if stat.S_ISDIR (stat_info[stat.ST_MODE]):
        dirchar = 'd'
    else:
        dirchar = '-'
    date = ls_date (long(time.time()), stat_info[stat.ST_MTIME])
    return '%s%s %3d %-8s %-8s %8d %s %s' % (
            dirchar,
            mode,
            stat_info[stat.ST_NLINK],
            username,
            grpname,
            stat_info[stat.ST_SIZE],
            date,
            file
            )


def ls_date (now, t):
    """Emulate the unix 'ls' command's date field.  it has two formats
       - if the date is more than 180 days in the past, then it's like
       this: Oct 19 1995 otherwise, it looks like this: Oct 19 17:33
    """
    try:
        info = time.gmtime(t)
    except:
        info = time.gmtime(0)

    # 15,600,000 == 86,400 * 180
    if (now - t) > 15600000:
        return '%s %2d  %d' % (
                months[info[1]-1],
                info[2],
                info[0]
                )
    else:
        return '%s %2d %02d:%02d' % (
                months[info[1]-1],
                info[2],
                info[3],
                info[4]
                )


def msdos_longify((file, stat_info)):
    """This matches the output of NT's ftp server (when in MSDOS mode)
       exactly.
    """
    if stat.S_ISDIR(stat_info[stat.ST_MODE]):
        dir = '<DIR>'
    else:
        dir = '     '
    date = msdos_date(stat_info[stat.ST_MTIME])
    return '%s       %s %8d %s' % (date, dir, stat_info[stat.ST_SIZE], file)


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 )


=== Added File Zope3/lib/python/Zope/Server/FTP/PublisherFTPServerChannel.py ===
##############################################################################
#
# 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: PublisherFTPServerChannel.py,v 1.1.2.1 2002/04/10 00:23:02 srichter Exp $
"""

from FTPServerChannel import FTPServerChannel

class PublisherFTPServerChannel(FTPServerChannel):
    """The FTP Server Channel represents a connection to a particular
       client. We can therefore store information here."""

    __implements__ = FTPServerChannel.__implements__


    def authenticate(self):
        # XXX We need to hook this up to the Zope security mechanism
        return 1, 'All cool'
        




    


=== Zope3/lib/python/Zope/Server/FTP/FTPServerChannel.py 1.1.2.18 => 1.1.2.19 ===
 
 
-    def _getFileSystem(self):
+    def _getFilesystem(self):
         """Open the filesystem using the username and password."""
-        return self.server.openFileSystem(self.username, self.password)
+        return self.server.openFilesystem(self.username, self.password)
         
 
     ############################################################
@@ -179,9 +179,7 @@
             self.reply('ERR_IS_NOT_FILE', path)
         else:
             mtime = time.gmtime(
-                self.server.openFilesystem(
-                self.username).stat(path)[stat.ST_MTIME]
-                )
+                self._getFilesystem().stat(path)[stat.ST_MTIME])
             self.reply('FILE_DATE', (mtime[0], mtime[1], mtime[2],
                                      mtime[3], mtime[4], mtime[5]) )
 
@@ -221,9 +219,7 @@
     def cmd_pass(self, args):
         'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
         self.password = args
-        auth = self.server.auth_source
-        self.authenticated, message = auth.authenticate(self.username,
-                                                        self.password)
+        self.authenticated, message = self.authenticate()
         if self.authenticated:
             self.reply('LOGIN_SUCCESS')
         else:
@@ -457,6 +453,11 @@
         path = os.path.normpath(path)
         return path
 
+
+    def authenticate(self):
+        auth = self.server.auth_source
+        return auth.authenticate(self.username, self.password)
+        
 
     def newPassiveAcceptor(self):
             # ensure that only one of these exists at a time.


=== Zope3/lib/python/Zope/Server/FTP/PublisherFTPServer.py 1.1.2.4 => 1.1.2.5 ===
 $Id$
 """
-from FTPServerChannel import FTPServerChannel
+from PublisherFTPServerChannel import PublisherFTPServerChannel
 from Zope.Server.ServerBase import ServerBase
 
 from Zope.Server.VFS.PublisherFileSystem import PublisherFileSystem
@@ -40,11 +40,11 @@
 class PublisherFTPServer(ServerBase):
     """Generic FTP Server"""
 
-    channel_class = FTPServerChannel
+    channel_class = PublisherFTPServerChannel
     SERVER_IDENT = 'Zope.Server.FTPServer'
 
 
-    def __init__(self, request_factory, name='FTP', ip, port,
+    def __init__(self, request_factory, name, ip, port,
                  task_dispatcher=None, adj=None, start=1, hit_log=None,
                  verbose=0, socket_map=None):