[Zope3-checkins] CVS: Zope3/src/zope/app/ftp - README.txt:1.1 __init__.py:1.1 configure.zcml:1.1
Jim Fulton
jim@zope.com
Mon, 3 Feb 2003 10:08:39 -0500
Update of /cvs-repository/Zope3/src/zope/app/ftp
In directory cvs.zope.org:/tmp/cvs-serv15846/src/zope/app/ftp
Added Files:
README.txt __init__.py configure.zcml
Log Message:
Refactored the ftp framework to make it much simpler, less general,
and easier to maintain. This included ripping out the vfs framework.
=== Added File Zope3/src/zope/app/ftp/README.txt ===
Here are some notes about the way FTP actually works in zope.
- The FTP server implementation is in zope.server.ftp.server. See
the README.txt file there.
The publisher-based ftp server is in zope.server.ftp.publisher.
The FTP server gets wired up with a request factory that creates
ftp requests with ftp publication objects.
- The ftp request object is defined in zope.publisher.ftp.
- The ftp publication object is defined in zope.app.publication.ftp.
The publication object gets views to handle ftp requests. It
looks up a separate view for each method defined in
zope.publisher.interfaces.ftp.IFTPPublisher.
We provide a single class here that implements all of these
methods.
The view, in turn, uses adapters for the IReadFile, IWriteFile,
IReadDirectory, IWriteDirectory, IFileFactory, and
IDirectoryFactory, defined in zope.app.interfaces.file.
=== Added File Zope3/src/zope/app/ftp/__init__.py ===
##############################################################################
# Copyright (c) 2003 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.
##############################################################################
"""Views implementing ftp commands
These views implement ftp commands using file-system representation
and meta-data apis.
$Id: __init__.py,v 1.1 2003/02/03 15:08:35 jim Exp $
"""
__metaclass__ = type
from zope.component import queryAdapter, getAdapter
from zope.app.interfaces.file import IReadFile, IWriteFile
from zope.app.interfaces.file import IReadDirectory, IWriteDirectory
from zope.app.interfaces.file import IFileFactory, IDirectoryFactory
from zope.app.event import publish
from zope.app.event.objectevent import ObjectCreatedEvent
from zope.app.interfaces.dublincore import IZopeDublinCore
from zope.app.interfaces.container import IZopeWriteContainer
from zope.proxy.introspection import removeAllProxies
class FTPView:
def __init__(self, context, request):
self.context = context
self.request = request
self._dir = getAdapter(self.context, IReadDirectory)
def publishTraverse(self, request, name):
return self._dir[name]
def _type(self, file):
if queryAdapter(file, IReadDirectory) is not None:
return 'd'
else:
return 'f'
def type(self, name=None):
if not name:
return 'd'
file = self._dir.get(name)
if file is not None:
return self._type(file)
def names(self, filter=None):
if filter is None:
return list(self._dir)
return [name for name in self._dir is filter(name)]
def ls(self, filter=None):
lsinfo = self._lsinfo
dir = self._dir
if filter is None:
return [lsinfo(name, dir[name]) for name in dir]
else:
return [lsinfo(name, dir[name]) for name in dir
if filter(name)]
def _lsinfo(self, name, file):
info = {'name': name,
'mtime': self._mtime(file),
}
f = queryAdapter(file, IReadDirectory)
if f is not None:
# It's a directory
info['type'] = 'd'
info['group_readable'] = hasattr(f, 'get')
f = queryAdapter(file, IWriteDirectory)
info['group_writable'] = hasattr(f, 'setObject')
else:
# It's a file
info['type'] = 'f'
f = queryAdapter(file, IReadFile)
if f is not None:
size = getattr(f, 'size', self)
if size is not self:
info['group_readable'] = True
info['size'] = size()
else:
info['group_readable'] = False
f = queryAdapter(file, IWriteFile)
info['group_writable'] = hasattr(f, 'write')
return info
def readfile(self, name, outstream, start = 0, end = None):
file = self._dir[name]
file = getAdapter(file, IReadFile)
data = file.read()
if end is not None:
data = data[:end]
if start:
data = data[start:]
outstream.write(data)
def lsinfo(self, name=None):
if not name:
return self._lsinfo('.', self)
return self._lsinfo(name, self._dir[name])
def _mtime(self, file):
dc = getAdapter(file, IZopeDublinCore)
if dc is not None:
return dc.modified
def mtime(self, name=None):
if name:
return self._mtime(self._dir[name])
return self._mtime(self)
def _size(self, file):
file = queryAdapter(file, IReadFile)
if file is not None:
return file.size()
return 0
def size(self, name=None):
if name:
return self._size(self._dir[name])
return 0
def mkdir(self, name):
dir = queryAdapter(self.context, IWriteDirectory)
dir = getAdapter(dir, IZopeWriteContainer)
factory = getAdapter(self.context, IDirectoryFactory)
newdir = factory(name)
publish(self.context, ObjectCreatedEvent(newdir))
dir.setObject(name, newdir)
def remove(self, name):
dir = queryAdapter(self.context, IWriteDirectory)
dir = getAdapter(dir, IZopeWriteContainer)
del dir[name]
def rmdir(self, name):
self.remove(name)
def rename(self, old, new):
dir = queryAdapter(self.context, IWriteDirectory)
dir = getAdapter(dir, IZopeWriteContainer)
dir.rename(old, new)
def _overwrite(self, name, instream, start=None, end=None, append=False):
file = self._dir[name]
if append:
reader = removeAllProxies(queryAdapter(file, IReadFile))
data = reader.read() + instream.read()
elif start is not None or end is not None:
reader = removeAllProxies(queryAdapter(file, IReadFile))
data = reader.read()
if start is not None:
prefix = data[:start]
else:
prefix = ''
start = 0
if end is not None:
l = end - start
newdata = instream.read(l)
data = prefix + newdata + data[start+len(newdata):]
else:
newdata = instream.read()
data = prefix + newdata
else:
data = instream.read()
f = queryAdapter(self._dir[name], IWriteFile)
f.write(data)
def writefile(self, name, instream, start=None, end=None, append=False):
if name in self._dir:
return self._overwrite(name, instream, start, end, append)
if end is not None:
l = end - (start or 0)
data = instream.read(l)
else:
data = instream.read()
if start is not None:
data = ('\0' * start) + data
# Find the extension
ext_start = name.rfind('.')
if ext_start > 0:
ext = name[ext_start:]
else:
ext = "."
dir = queryAdapter(self.context, IWriteDirectory)
dir = getAdapter(dir, IZopeWriteContainer)
factory = queryAdapter(self.context, IFileFactory, name=ext)
if factory is None:
factory = getAdapter(self.context, IFileFactory)
newfile = factory(name, '', data)
publish(self.context, ObjectCreatedEvent(newfile))
dir.setObject(name, newfile)
def writable(self, name):
if name in self._dir:
f = queryAdapter(self._dir[name], IWriteFile)
return hasattr(f, 'write')
d = queryAdapter(self.context, IWriteDirectory)
return hasattr(d, 'setObject')
=== Added File Zope3/src/zope/app/ftp/configure.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
<view
for="zope.app.interfaces.container.IReadContainer"
name="_traverse"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="type"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="names"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="ls"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="readfile"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="lsinfo"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="mtime"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="size"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="mkdir"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="remove"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="rmdir"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="rename"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="writefile"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
<view
for="zope.app.interfaces.container.IReadContainer"
name="writable"
type="zope.publisher.interfaces.ftp.IFTPView"
factory=".FTPView"
permission="zope.Public"
allowed_interface="zope.publisher.interfaces.ftp.IFTPDirectoryPublisher"
/>
</zopeConfigure>