[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/VFS - IFilesystemAccess.py:1.1.4.1 IPosixFileSystem.py:1.1.4.1 IReadFileSystem.py:1.1.4.1 IUsernamePassword.py:1.1.4.1 IWriteFileSystem.py:1.1.4.1 OSFileSystem.py:1.1.4.1 PublisherFileSystem.py:1.1.4.1 TestFilesystemAccess.py:1.1.4.1 UsernamePassword.py:1.1.4.1 __init__.py:1.1.4.1
Shane Hathaway
shane@cvs.zope.org
Fri, 12 Apr 2002 17:31:00 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Server/VFS
In directory cvs.zope.org:/tmp/cvs-serv20835/lib/python/Zope/Server/VFS
Added Files:
Tag: Zope-3x-branch
IFilesystemAccess.py IPosixFileSystem.py IReadFileSystem.py
IUsernamePassword.py IWriteFileSystem.py OSFileSystem.py
PublisherFileSystem.py TestFilesystemAccess.py
UsernamePassword.py __init__.py
Log Message:
Merged Zope3-Server-Branch.
=== Added File Zope3/lib/python/Zope/Server/VFS/IFilesystemAccess.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: IFilesystemAccess.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
from Interface import Interface
# XXX This interface should be in a more central location.
class IFilesystemAccess(Interface):
"""Provides authenticated access to a filesystem.
"""
def authenticate(credentials):
"""Verifies filesystem access based on the presented credentials.
Should raise Unauthorized if the user can not be authenticated.
This method only checks general access and is not used for each
call to open(). Rather, open() should do its own verification.
"""
def open(credentials):
"""Returns an IReadFilesystem or IWriteFilesystem.
Should raise Unauthorized if the user can not be authenticated.
"""
=== Added File Zope3/lib/python/Zope/Server/VFS/IPosixFileSystem.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: IPosixFileSystem.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
from IWriteFileSystem import IWriteFileSystem
from IReadFileSystem import IReadFileSystem
class IPosixFileSystem(IWriteFileSystem, IReadFileSystem):
"""
"""
def chmod(path, mode):
"""Change the access permissions of a file.
"""
def chown(path, uid, gid):
"""Change the owner and group id of path to numeric uid and gid.
"""
def link(src, dst):
"""Create a heard link to a file.
"""
def mkfifo(path, mode=777):
"""Create a FIFO (a POSIX named pipe).
"""
def symlink(src, dst):
"""Create a symbolic link at dst pointing to src.
"""
=== Added File Zope3/lib/python/Zope/Server/VFS/IReadFileSystem.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: IReadFileSystem.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
from Interface import Interface
class IReadFileSystem(Interface):
"""We want to provide a complete wrapper around any and all read
filesystem operations.
Opening files for reading, and listing directories, should
return a producer.
All paths are POSIX paths, even when run on Windows,
which mainly means that FS implementations always expect forward
slashes, and filenames are case-sensitive.
Note: A file system should *not* store any state!
"""
def exists(path):
"""Test whether a path exists.
"""
def isdir(path):
"""Test whether a path is a directory.
"""
def isfile(path):
"""Test whether a path is a file.
"""
def listdir(path, with_stats=0, pattern='*'):
"""Return a listing of the directory at 'path' The empty
string indicates the current directory. If 'with_stats' is set,
instead return a list of (name, stat_info) tuples. All file
names are filtered by the globbing pattern. (See the 'glob'
module in the Python standard library.)
"""
return list(tuple(str, str))
def readfile(path, mode, outstream, start=0, end=-1):
"""Outputs the file at path to a stream.
"""
def stat(path):
"""Return the equivalent of os.stat() on the given path:
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)
"""
=== Added File Zope3/lib/python/Zope/Server/VFS/IUsernamePassword.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: IUsernamePassword.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
from Interface import Interface
# XXX These interfaces should be located in a more central location.
# (so I don't mind putting them together in one module for now ;-) )
class ICredentials(Interface):
"""Base interface for presentation of authentication credentials.
Different kinds of credentials include username/password, client
certificate, IP address and port, etc., including combinations.
"""
class IUsernamePassword(ICredentials):
"""A type of authentication credentials consisting of user name and
password. The most recognized form of credentials.
"""
def getUserName():
"""Returns the user name presented for authentication.
"""
def getPassword():
"""Returns the password presented for authentication.
"""
=== Added File Zope3/lib/python/Zope/Server/VFS/IWriteFileSystem.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: IWriteFileSystem.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
from Interface import Interface
class IWriteFileSystem(Interface):
"""We want to provide a complete wrapper around any and all write
filesystem operations.
Notes:
- A file system should *not* store any state!
- Most of the commands copy the functionality given in os.
"""
def mkdir(path, mode=777):
"""Create a directory.
"""
def remove(path):
"""Remove a file. Same as unlink.
"""
def rmdir(path):
"""Remove a directory.
"""
def rename(old, new):
"""Rename a file or directory.
"""
def writefile(path, mode, instream, start=0):
"""Write data to a file.
"""
def check_writable(path):
"""Ensures a path is writable. Throws an IOError if not."""
=== Added File Zope3/lib/python/Zope/Server/VFS/OSFileSystem.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: OSFileSystem.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
import os
import re
import stat
import time
import fnmatch
from IPosixFileSystem import IPosixFileSystem
class OSFileSystem(object):
"""Generic OS FileSystem implementation.
The root of this file system is a string describing the path
to the directory used as root.
"""
__implements__ = IPosixFileSystem
copy_bytes = 65536
def __init__ (self, root):
self.root = root
############################################################
# Implementation methods for interface
# Zope.Server.VFS.IPosixFileSystem.IPosixFileSystem
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)
return os.chown(p, uid, gid)
def link(self, src, dst):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
src = self.translate(src)
dst = self.translate(dst)
return os.link(src, dst)
def mkfifo(self, path, mode=6*2**6):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
return os.mkfifo(path, mode)
def symlink(self, src, dst):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
src = self.translate(src)
dst = self.translate(dst)
return os.symlink(src, dst)
######################################
# from: Zope.Server.VFS.IReadFileSystem.IReadFileSystem
def exists(self, path):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
p = self.translate(path)
return os.path.exists(p)
def isdir(self, path):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
p = self.translate(path)
return os.path.isdir(p)
def isfile(self, path):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
p = self.translate(path)
return os.path.isfile(p)
def listdir(self, path, with_stats=0, pattern='*'):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
p = self.translate(path)
# list the directory's files
ld = os.listdir(p)
# filter them using the pattern
ld = filter(lambda f, p=pattern, fnm=fnmatch.fnmatch: fnm(f, p), ld)
# sort them alphabetically
ld.sort()
if not with_stats:
result = ld
else:
result = []
for file in ld:
path = os.path.join(p, file)
stat = safe_stat(path)
if stat is not None:
result.append((file, stat))
return result
def readfile(self, path, mode, outstream, start=0, end=-1):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
p = self.translate(path)
instream = open(p, mode)
if start:
instream.seek(start)
pos = start
while end < 0 or pos < end:
toread = self.copy_bytes
if end >= 0:
toread = min(toread, end - pos)
data = instream.read(toread)
if not data:
break
pos += len(data)
outstream.write(data)
def stat(self, path):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
p = self.translate(path)
return os.stat(p)
######################################
# from: Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem
def mkdir(self, path, mode=6*2**6):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
p = self.translate(path)
return os.mkdir(p, mode)
def remove(self, path):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
p = self.translate (path)
return os.remove(p)
def rmdir(self, path):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
p = self.translate (path)
return os.rmdir(p)
def rename(self, old, new):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
old = self.translate(old)
new = self.translate(new)
return os.rename(old, new)
def writefile(self, path, mode, instream, start=0):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
p = self.translate(path)
outstream = open(p, mode)
if start:
outstream.seek(start)
while 1:
data = instream.read(self.copy_bytes)
if not data:
break
outstream.write(data)
def check_writable(self, path):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
p = self.translate(path)
if os.path.exists(p):
remove = 0
else:
remove = 1
f = open(p, 'a') # append mode
f.close()
if remove:
os.remove(p)
#
############################################################
# utility methods
def normalize (self, path):
# watch for the ever-sneaky '/+' path element
# XXX It is unclear why "/+" is dangerous. It is definitely
# unexpected.
path = re.sub('/+', '/', path)
path = os.path.normpath(path)
if path.startswith('..'):
# Someone is trying to get lower than the permitted root.
# We just ignore it.
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 = self.normalize(path)
# Prepare for joining with root
while path.startswith('/'):
path = path[1:]
# Join path with root
return os.path.join(self.root, path)
def __repr__ (self):
return '<OSFileSystem, root=%s>' % self.root
def safe_stat (path):
try:
return os.stat(path)
except:
return None
=== 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.4.1 2002/04/12 21:30:58 shane Exp $
"""
import os, re
import stat
import time
from cStringIO import StringIO
from IReadFileSystem import IReadFileSystem
from IWriteFileSystem import IWriteFileSystem
from Zope.Publisher.Publish import publish
class NoOutput:
"""An output stream lookalike that warns you if you try to
dump anything into it."""
def write(self, data):
raise RuntimeError, "Not a writable stream"
def flush(self):
pass
close = flush
class PublisherFileSystem:
"""Generic Publisher FileSystem implementation.
"""
__implements__ = IReadFileSystem, IWriteFileSystem
def __init__ (self, credentials, request_factory):
self.credentials = credentials
self.request_factory = request_factory
def _execute(self, path, command, env=None):
if env is None:
env = {}
env['command'] = command
env['path'] = path
env['credentials'] = self.credentials
# NoOutput avoids creating a black hole.
request = self.request_factory(StringIO(''), NoOutput(), env)
# Note that publish() calls close() on request, which deletes the
# response from the request, so that we need to keep track of it.
response = request.getResponse()
publish(request)
return response.getResult()
############################################################
# Implementation methods for interface
# Zope.Server.VFS.IReadFileSystem.
def exists(self, path):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
path = self.translate(path)
if path == '/':
return 1
path, file = os.path.split(path)
env = {'name': file}
return self._execute(path, 'exists', env)
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, with_stats=0, pattern='*'):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
path = self.translate(path)
env = {'with_stats' : with_stats,
'pattern' : pattern}
return self._execute(path, 'listdir', env)
def readfile(self, path, mode, outstream, start=0, end=-1):
'See Zope.Server.VFS.IReadFileSystem.IReadFileSystem'
path = self.translate(path)
env = {'mode' : mode,
'outstream' : outstream,
'start' : start,
'end' : end}
return self._execute(path, 'read', env)
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 mkdir(self, path, mode=777):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
path = self.translate(path)
path, dir = os.path.split(path)
env = {'name': dir}
return self._execute(path, 'mkdir', env)
def remove(self, path):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
path = self.translate(path)
path, name = os.path.split(path)
env = {'name': name}
return self._execute(path, 'remove', env)
def rmdir(self, path):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
path = self.translate(path)
path, dir = os.path.split(path)
env = {'name': dir}
return self._execute(path, 'rmdir', env)
def rename(self, old, new):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
old = self.translate(old)
new = self.translate(new)
path0, old = os.path.split(old)
path1, new = os.path.split(new)
assert path0 == path1
env = {'old' : old,
'new' : new}
return self._execute(path0, 'rename', env)
def writefile(self, path, mode, instream, start=0):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
path = self.translate(path)
path, name = os.path.split(path)
env = {'name' : name,
'mode' : mode,
'instream' : instream,
'start' : start}
return self._execute(path, 'writefile', env)
def check_writable(self, path):
'See Zope.Server.VFS.IWriteFileSystem.IWriteFileSystem'
path = self.translate(path)
path, name = os.path.split(path)
env = {'name' : name}
return self._execute(path, 'check_writable', env)
#
############################################################
# utility methods
def translate (self, path):
# Normalize
path = os.path.normpath(path)
if path.startswith('..'):
# Someone is trying to get lower than the permitted root.
# We just ignore it.
path = '/'
return path
=== Added File Zope3/lib/python/Zope/Server/VFS/TestFilesystemAccess.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.
#
##############################################################################
"""Implementation of IFilesystemAccess intended only for testing.
$Id: TestFilesystemAccess.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
from Zope.Server.VFS.IFilesystemAccess import IFilesystemAccess
from Zope.Server.VFS.IUsernamePassword import IUsernamePassword
from Zope.Exceptions import Unauthorized
class TestFilesystemAccess:
__implements__ = IFilesystemAccess
passwords = {'foo': 'bar'}
def __init__(self, fs):
self.fs = fs
def authenticate(self, credentials):
if not IUsernamePassword.isImplementedBy(credentials):
raise Unauthorized
name = credentials.getUserName()
if not self.passwords.has_key(name):
raise Unauthorized
if credentials.getPassword() != self.passwords[name]:
raise Unauthorized
def open(self, credentials):
self.authenticate(credentials)
return self.fs
=== Added File Zope3/lib/python/Zope/Server/VFS/UsernamePassword.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: UsernamePassword.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""
from Zope.Server.VFS.IUsernamePassword import IUsernamePassword
class UsernamePassword:
__implements__ = IUsernamePassword
def __init__(self, username, password):
self.username = username
self.password = password
def getUserName(self):
return self.username
def getPassword(self):
return self.password
=== Added File Zope3/lib/python/Zope/Server/VFS/__init__.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: __init__.py,v 1.1.4.1 2002/04/12 21:30:58 shane Exp $
"""