[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/VFS - PublisherFileSystem.py:1.1.2.1 PublisherVFSTask.py:1.1.2.1 ZODBFileSystem.py:NONE

Stephan Richter srichter@cbu.edu
Thu, 4 Apr 2002 06:44:54 -0500


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

Added Files:
      Tag: Zope3-Server-Branch
	PublisherFileSystem.py PublisherVFSTask.py 
Removed Files:
      Tag: Zope3-Server-Branch
	ZODBFileSystem.py 
Log Message:
Worked some more on FTP, especially in regards with the Publisher.

- Finally we can get rid of the medusa base. I think I have extracted all
  of the interesting code.

- Started on a PublisherFileSystem. A few methods might work, but most of 
  the FS methods are not hooked up yet.

- Started writing VFS Publisher hooks.

- Added the FTPServer to the startup registry. It comes up, but do not 
  expect it to work, since no views have been written for VFS yet.


=== Added File Zope3/lib/python/Zope/Server/VFS/PublisherFileSystem.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: PublisherFileSystem.py,v 1.1.2.1 2002/04/04 11:44:53 srichter Exp $
"""
        
import os, re
import stat
import time
        
from IReadFileSystem import IReadFileSystem
from IWriteFileSystem import IWriteFileSystem

from Zope.Publisher.Publish import publish
from ListProducer import ListProducer


class PublisherFileSystem:
    """Generic Publisher FileSystem implementation. 
    """

    __implements__ = IReadFileSystem, IWriteFileSystem

    request_factory = None


    def __init__ (self, root):
        self.root = root


    def _execute(self, path, command, env=None):

        if env is None:
            env = {}
        
        env['command'] = command
        env['path'] = path

        request = self.request_factory(StringIO(''), StringIO(''), env)
        publish(request)
        return request.getResponse().getResult()


    ############################################################
    # Implementation methods for interface
    # Zope.Server.VFS.IReadFileSystem.IReadFileSystem

    def exists(self, path):
        'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
        path = self.translate(path)
        return self._execute(path, 'exists')
        

    def isdir(self, path):
        'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
        path = self.translate(path)
        return self._execute(path, 'isdir')


    def isfile(self, path):
        'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
        path = self.translate(path)
        return self._execute(path, 'isfile')


    def listdir(self, path, long=0):
        'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
        path = self.translate(path)
        # Returns a list of Wrapper objects representing the objects
        # Also, the Wrapper object should contain *all* stat information
        ld = self._execute(path, 'listdir')
        ld.sort()
        if not long:
            return ListProducer(ld, 0, None)
        else:
            return ListProducer(result, 1, self.longify)


    def longify(self, (path, stat_info)):
        'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
        return unix_longify (path, stat_info)


    def open(self, path, mode):
        'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
        path = self.translate(path)
        return self._execute(path, 'open', {'mode': mode})


    def stat(self, path):
        'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
        path = self.translate(path)
        return self._execute(path, 'stat')

    #
    ############################################################

    ############################################################
    # Implementation methods for interface
    # Zope.Server.VFS.IWriteFileSystem.

    def chmod(self, path, mode):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        p = self.translate (path)
        return os.chmod(p, mode)


    def chown(self, path, uid, gid):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        p = self.translate (path)
        raise NotImplementedError('This function is not implemented.')


    def link(self, src, dst):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        src = self.translate(src)
        dst = self.translate(dst)
        raise NotImplementedError('This function is not implemented.')


    def mkdir(self, path, mode=6*2**6):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        p = self.translate(path)


    def mkfifo(self, path, mode=6*2**6):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        raise NotImplementedError('This function is not implemented.')

    def remove(self, path):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        p = self.translate (path)


    def rmdir(self, path):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        p = self.translate (path)


    def rename(self, old, new):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        old = self.translate(old)
        new = self.translate(new)


    def symlink(self, src, dst):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        src = self.translate(src)
        dst = self.translate(dst)
        raise NotImplementedError('This function is not implemented.')


    def unlink(self, path):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        pass
    

    def write(self, fd, data):
        'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
        pass
    
    #
    ############################################################


    # utility methods

    def normalize (self, path):
        # watch for the ever-sneaky '/+' path element
        path = re.sub('/+', '/', path)
        # Someone is trying to get lower than the permitted root.
        # We just ignore it. 
        path = os.path.normpath(path)
        if path.startswith('..'):
            path = '/'
        return path

        
    def translate (self, path):
        """We need to join together three separate path components,
           and do it safely.  <real_root>/<path>
           use the operating system's path separator.

           We need to be extremly careful to include the cases where a hacker
           could attempt to a directory below root!
        """
        # Normalize the directory
        path = os.sep.join(path.split('/'))
        path = self.normalize(self.path_module.join(path))        
        # Prepare for joining with root
        if path[0] == '/':
            path = path[1:]
        # Join path with root
        path = self.path_module.join(self.root, path)
        return path

        
    def __repr__ (self):
        return '<Publisher-FileSystem Root:%s>' % self.root
        


    
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

    import pwd, grp

    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 safe_stat (path):
    try:
        return os.stat(path)
    except:
        return None


=== Added File Zope3/lib/python/Zope/Server/VFS/PublisherVFSTask.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: PublisherVFSTask.py,v 1.1.2.1 2002/04/04 11:44:53 srichter Exp $
"""

import socket
from Zope.Server.ITask import ITask


class FTPTask:
    """
    """

    __implements__ = ITask


    def __init__(self, channel, command, m_name):
        self.channel = channel
        self.m_name = m_name
        self.args = command.args


    ############################################################
    # Implementation methods for interface
    # Zope.Server.ITask

    def service(self):
        """Called to execute the task.
        """
        try:
            try:
                self.start()
                getattr(self, self.m_name)(self.args)
                self.finish()
            except socket.error:
                self.close_on_finish = 1
                if self.channel.adj.log_socket_errors:
                    raise
        finally:
            self.channel.end_task(self.close_on_finish)


    def cancel(self):
        'See Zope.Server.ITask.ITask'
        self.channel.close_when_done()


    def defer(self):
        'See Zope.Server.ITask.ITask'
        pass

    #
    ############################################################

    def start(self):
        now = time.time()
        self.start_time = now


    def finish(self):
        hit_log = self.channel.server.hit_log
        if hit_log is not None:
            hit_log.log(self)

=== Removed File Zope3/lib/python/Zope/Server/VFS/ZODBFileSystem.py ===