Commit b0c70de0 authored by Hanno Schlichting's avatar Hanno Schlichting

Move in the Zope2.buildout stuff into the trunk

parent ff02876c

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

# Run tests of all packages that would have their tests run in a Zope-trunk
# SVN checkout.
[buildout]
extends = buildout.cfg
parts += alltests
[alltests]
recipe = zc.recipe.testrunner<1.1dev
# The commented packages are present on SVN trunk but not used (downloaded)
# by Zope2.buildout. If you manage to reduce the dependencies further, feel
# free to comment out more eggs.
eggs =
${buildout:eggs}
Acquisition
DateTime
ExtensionClass
Persistence
RestrictedPython
tempstorage
zLOG
zodbcode
zope.annotation
zope.broken
zope.browser
zope.cachedescriptors
zope.component
zope.configuration
zope.container
zope.contentprovider
zope.contenttype
zope.copypastemove
zope.datetime
zope.deferredimport
zope.deprecation
# zope.documenttemplate
zope.dottedname
zope.dublincore
zope.error
zope.event
zope.exceptions
zope.formlib
zope.hookable
zope.i18n
zope.i18nmessageid
zope.index
zope.interface
zope.lifecycleevent
zope.location
zope.minmax
zope.modulealias
zope.pagetemplate
zope.proxy
zope.publisher
# zope.rdb
zope.schema
zope.security
zope.securitypolicy
zope.sendmail
zope.sequencesort
# zope.server
zope.session
zope.site
zope.size
zope.structuredtext
zope.tal
zope.tales
zope.testbrowser
zope.thread
zope.traversing
zope.viewlet
# zope.wfmc
# Fetch undeclared ftests dependencies
zope.app.principalannotation
zope.app.schema
zope.app.securitypolicy
zope.app.zcmlfiles
zope.app.zptpage
defaults = ['--module', '!^(zope[.]app)[.]']
environment = test-environment
import os
import shutil
def create_lib_python(options, buildout):
if os.path.exists(options['dst-dir']):
shutil.rmtree(options['dst-dir'])
shutil.copytree(options['src-dir'], options['dst-dir'])
for pathname in options['skip-names'].split():
path = os.path.join(options['dst-dir'], pathname)
if os.path.exists(path):
if os.path.isdir(path):
shutil.rmtree(path)
else:
os.remove(path)
[buildout]
develop =
.
parts =
test
zopepy
eggs-directory = ${buildout:directory}/eggs
extends = versions-zope2.cfg
versions = versions
unzip = true
eggs =
Zope2
[test]
recipe = zc.recipe.testrunner<1.1dev
eggs = ${buildout:eggs}
environment = test-environment
[test-environment]
SOFTWARE_HOME = ${buildout:directory}/src
ZOPE_HOME = ${buildout:directory}
INSTANCE_HOME = ${buildout:directory}
[omelette]
recipe = collective.recipe.omelette >= 0.7
eggs = ${buildout:eggs}
[lib_python]
recipe = z3c.recipe.runscript
install-script = bin/create_lib_python.py:create_lib_python
update-script = bin/create_lib_python.py:create_lib_python
src-dir = ${omelette:location}
dst-dir = ${buildout:directory}/lib/python
skip-names =
easy_install.py
pkg_resources.py
setuptools
site.py
[zopepy]
recipe = zc.recipe.egg
eggs = ${buildout:eggs}
interpreter = zopepy
scripts = zopepy
......@@ -7,22 +7,19 @@
# BEGIN EDITABLE PARAMETERS #
#####################################################################
# Place the Zope major version number below.
ZOPE_VERS=2.12
# Place the optimal target version number for Zope (as returned by sys.version)
# below
TARGET="2.4.5"
TARGET="2.5.4"
# Order a list of "acceptable" python version numbers (as returned by
# sys.version) below in "best" to "worst" order, not including the
# target version. Up to six acceptable python versions are allowed.
# Do not include the target version number in this list!
ACCEPTABLE="2.4.4"
ACCEPTABLE="2.6.1"
# provide the executable names for all the acceptable versions
# (and the target version) below
EXENAMES="python python2 python2.4"
EXENAMES="python python2 python2.5 python2.6"
#####################################################################
# END EDITABLE PARAMETERS #
......@@ -56,7 +53,8 @@ usage()
echo " --no-compile Dont compile Python bytecode"
echo
echo " Given no options, configure will search your PATH for a suitable"
echo " Python interpreter and will use '/opt/Zope-$ZOPE_VERS' as a prefix."
echo " Python interpreter and will use '/opt/Zope-<ZOPE_MAJOR_VERSION>'"
echo " as a prefix."
echo
}
......
Security Architecture
---------------------
Users
-----
Objects representing users may be created in Principia
User Folder objects. User objects maintain the information
used to authenticate users, and allow roles to be associated
with a user.
Permissions
-----------
A "permission" is the smallest unit of access to an object,
roughly equivalent to the atomic permissions seen in NT:
R (Read), W(Write), X(Execute), etc. In Principia, a permission
usually describes a fine-grained logical operation on an object,
such as "View Management Screens", "Add Properties", etc.
Different types of objects will define different permissions
as appropriate for the object.
Types of access
---------------
A "type of access" is a named grouping of 0 or more of the
permissions defined by an object. All objects have one predefined
type of access called Full Access (all permissions defined by that
object). A user who has the special role "Manager" always has Full
Access to all objects at or below the level in the object hierarchy
at which the user is defined.
New types of access may be defined as combinations of the
various permissions defined by a given object. These new
types of access may be defined by the programmer, or by
users at runtime.
Roles
-----
A role is a name that ties users (authentication of identity)
to permissions (authorization for that identity) in the system.
Roles may be defined in any Folder (or Folderish) object in the
system. Sub folders can make use of roles defined higher in the
hierarchy. These roles can be assigned to users. All users,
including non-authenticated users have the built-in role of
"Anonymous".
Principia objects allow the association of defined roles
with a single "type of access" each, in the context of that
object. A single role is associated with one and only one
type of access in the context of a given object.
Examples
--------
User Object1
o has the role "RoleA" o has given "RoleA" Full Access
Result: the user has Full Access to Object1.
User Object2
o has the role "RoleA" o has given "RoleB" Full Access
o has given the role "RoleA" View Access,
a custom type of access that allows only
viewing of the object.
Result: the user has only View Access.
Notes
-----
All objects define a permission called "Default permission". If this
permission is given to a role, users with that role will be able to
access subobjects which do not explicitly restrict access.
Technical
---------
Objects define their permissions as logical operations.
Programmers have to determine the appropriate operations
for their object type, and provide a mapping of permission
name to attribute names. It is important to note that permissions
cannot overlap - none of the attributes named in a permission
can occur in any of the other permissions. The following are
proposed permissions for some current principia objects:
Folder
o View management screens
o Change permissions
o Undo changes
o Add objects
o Delete objects
o Add properties
o Change properties
o Delete properties
o Default permission
Confera Topic
o View management screens
o Change permissions
o Undo changes
o Add objects
o Delete objects
o Add properties
o Change properties
o Delete properties
o Default permission
o Change Configuration
o Add Messages
o Change Messages
o Delete Messages
Tabula Collection
o View management screens
o Change permissions
o Undo changes
o Add objects
o Delete objects
o Add properties
o Change properties
o Delete properties
o Default permission
o Change schema
o Upload data
o Add computed fields
o Change computed fields
o Delete computed fields
Document/Image/File
o View management screens
o Change permissions
o Change/upload data
o View
Session
o View management screens
o Change permissions
o Change session config
o Join/leave session
o Save/discard session
Mail Host
o View management screens
o Change permissions
o Change configuration
To support the architecture, developers must derive an
object from the AccessControl.RoleManager mixin class,
and define in their class an __ac_permissions__ attribute.
This should be a tuple of tuples, where each tuple represents
a permission and contains a string permission name as its first
element and a list of attribute names as its second element.
Example:
__ac_permissions__=(
('View management screens',
['manage','manage_menu','manage_main','manage_copyright',
'manage_tabs','manage_propertiesForm','manage_UndoForm']),
('Undo changes', ['manage_undo_transactions']),
('Change permissions', ['manage_access']),
('Add objects', ['manage_addObject']),
('Delete objects', ['manage_delObjects']),
('Add properties', ['manage_addProperty']),
('Change properties', ['manage_editProperties']),
('Delete properties', ['manage_delProperties']),
('Default permission', ['']),
)
The developer may also predefine useful types of access, by
specifying an __ac_types__ attribute. This should be a tuple of
tuples, where each tuple represents a type of access and contains
a string name as its first element and a list of permission names
as its second element.
By default, only "Full Access" is defined (by the RoleManager mixin).
If you wish to override __ac_types__ to provide convenient types of
access, you must always be sure to define "Full Access" as containing
the names of all possible permissions for your object.
Example:
__ac_types__=(
('Full Access', map(lambda x: x[0], __ac_permissions__)),
('Change', ['Add Objects', 'Add Properties', 'Change Properties']),
)
Developers may also provide pre-defined role names that are
not deletable via the interface by specifying an __ac_roles__
attribute. This is probably not something we'll ever use under
the new architecture, but it's there if you need it.
Example:
__ac_roles__=('Manager', 'Anonymous')
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
__version__='$Revision: 1.9 $'[11:-2]
try:
from hashlib import sha1 as sha
except:
from sha import new as sha
import binascii
from binascii import b2a_base64, a2b_base64
from random import choice, randrange
class PasswordEncryptionScheme: # An Interface
def encrypt(pw):
"""
Encrypt the provided plain text password.
"""
def validate(reference, attempt):
"""
Validate the provided password string. Reference is the
correct password, which may be encrypted; attempt is clear text
password attempt.
"""
_schemes = []
def registerScheme(id, s):
'''
Registers an LDAP password encoding scheme.
'''
_schemes.append((id, '{%s}' % id, s))
def listSchemes():
r = []
for id, prefix, scheme in _schemes:
r.append(id)
return r
class SSHADigestScheme:
'''
SSHA is a modification of the SHA digest scheme with a salt
starting at byte 20 of the base64-encoded string.
'''
# Source: http://developer.netscape.com/docs/technote/ldap/pass_sha.html
def generate_salt(self):
# Salt can be any length, but not more than about 37 characters
# because of limitations of the binascii module.
# 7 is what Netscape's example used and should be enough.
# All 256 characters are available.
salt = ''
for n in range(7):
salt += chr(randrange(256))
return salt
def encrypt(self, pw):
pw = str(pw)
salt = self.generate_salt()
return b2a_base64(sha(pw + salt).digest() + salt)[:-1]
def validate(self, reference, attempt):
try:
ref = a2b_base64(reference)
except binascii.Error:
# Not valid base64.
return 0
salt = ref[20:]
compare = b2a_base64(sha(attempt + salt).digest() + salt)[:-1]
return (compare == reference)
registerScheme('SSHA', SSHADigestScheme())
class SHADigestScheme:
def encrypt(self, pw):
return b2a_base64(sha(pw).digest())[:-1]
def validate(self, reference, attempt):
compare = b2a_base64(sha(attempt).digest())[:-1]
return (compare == reference)
registerScheme('SHA', SHADigestScheme())
# Bogosity on various platforms due to ITAR restrictions
try:
from crypt import crypt
except ImportError:
crypt = None
if crypt is not None:
class CryptDigestScheme:
def generate_salt(self):
choices = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789./")
return choice(choices) + choice(choices)
def encrypt(self, pw):
return crypt(pw, self.generate_salt())
def validate(self, reference, attempt):
a = crypt(attempt, reference[:2])
return (a == reference)
registerScheme('CRYPT', CryptDigestScheme())
class MySQLDigestScheme:
def encrypt(self, pw):
nr = 1345345333L
add = 7
nr2 = 0x12345671L
for i in pw:
if i == ' ' or i == '\t':
continue
nr ^= (((nr & 63) + add) * ord(i)) + (nr << 8)
nr2 += (nr2 << 8) ^ nr
add += ord(i)
r0 = nr & ((1L << 31) - 1L)
r1 = nr2 & ((1L << 31) - 1L)
return "%08lx%08lx" % (r0, r1)
def validate(self, reference, attempt):
a = self.encrypt(attempt)
return (a == reference)
registerScheme('MYSQL', MySQLDigestScheme())
def pw_validate(reference, attempt):
"""Validate the provided password string, which uses LDAP-style encoding
notation. Reference is the correct password, attempt is clear text
password attempt."""
for id, prefix, scheme in _schemes:
lp = len(prefix)
if reference[:lp] == prefix:
return scheme.validate(reference[lp:], attempt)
# Assume cleartext.
return (reference == attempt)
def is_encrypted(pw):
for id, prefix, scheme in _schemes:
lp = len(prefix)
if pw[:lp] == prefix:
return 1
return 0
def pw_encrypt(pw, encoding='SSHA'):
"""Encrypt the provided plain text password using the encoding if provided
and return it in an LDAP-style representation."""
for id, prefix, scheme in _schemes:
if encoding == id:
return prefix + scheme.encrypt(pw)
raise ValueError, 'Not supported: %s' % encoding
pw_encode = pw_encrypt # backward compatibility
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
"""Add security system support to Document Templates
$Id$
"""
from DocumentTemplate import DT_Util
import SecurityManagement, string, math, random, sets
import DocumentTemplate.sequence
from ZopeGuards import safe_builtins
# RestrictedDTML is inserted by AccessControl.Implementation.
# Allow access to unprotected attributes
DT_Util.TemplateDict.__allow_access_to_unprotected_subobjects__=1
string.__allow_access_to_unprotected_subobjects__=1
math.__allow_access_to_unprotected_subobjects__=1
random.__allow_access_to_unprotected_subobjects__=1
sets.__allow_access_to_unprotected_subobjects__=1
DocumentTemplate.sequence.__allow_access_to_unprotected_subobjects__=1
# Add security testing capabilities
class DTMLSecurityAPI:
"""API for performing security checks in DTML using '_' methods.
"""
def SecurityValidate(md, inst, parent, name, value):
"""Validate access.
Arguments:
accessed -- the object that was being accessed
container -- the object the value was found in
name -- The name used to access the value
value -- The value retrieved though the access.
The arguments may be provided as keyword arguments. Some of these
arguments may be ommitted, however, the policy may reject access
in some cases when arguments are ommitted. It is best to provide
all the values possible.
"""
return (SecurityManagement
.getSecurityManager()
.validate(inst, parent, name, value)
)
def SecurityCheckPermission(md, permission, object):
"""Check whether the security context allows the given permission on
the given object.
Arguments:
permission -- A permission name
object -- The object being accessed according to the permission
"""
return (SecurityManagement
.getSecurityManager()
.checkPermission(permission, object)
)
def SecurityGetUser(md):
"""Gen the current authenticated user"""
return (SecurityManagement
.getSecurityManager()
.getUser()
)
def SecurityCalledByExecutable(md):
"""Return a boolean value indicating if this context was called
by an executable"""
r = (SecurityManagement
.getSecurityManager()
.calledByExecutable()
)
if r > 0: return r-1
return r
for name, v in DTMLSecurityAPI.__dict__.items():
if name[0] != '_':
setattr(DT_Util.TemplateDict, name, v)
from types import FunctionType
for name, v in safe_builtins.items():
if type(v) is FunctionType:
v = DT_Util.NotBindable(v)
if name.startswith('__'):
continue
setattr(DT_Util.TemplateDict, name, v)
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""C implementation of the access control machinery."""
try:
from AccessControl.cAccessControl import rolesForPermissionOn
from AccessControl.cAccessControl import PermissionRole
from AccessControl.cAccessControl import imPermissionRole
from AccessControl.cAccessControl import _what_not_even_god_should_do
from AccessControl.cAccessControl import RestrictedDTMLMixin
from AccessControl.cAccessControl import aq_validate
from AccessControl.cAccessControl import guarded_getattr
from AccessControl.cAccessControl import setDefaultBehaviors
from AccessControl.cAccessControl import ZopeSecurityPolicy \
as cZopeSecurityPolicy
from AccessControl.cAccessControl import SecurityManager \
as cSecurityManager
except ImportError:
import sys
# make sure a partial import doesn't pollute sys.modules
del sys.modules[__name__]
raise
from AccessControl.ImplPython import RestrictedDTML
from AccessControl.ImplPython import SecurityManager
from AccessControl.ImplPython import ZopeSecurityPolicy
class RestrictedDTML(RestrictedDTMLMixin, RestrictedDTML):
"""A mix-in for derivatives of DT_String.String that adds Zope security."""
class ZopeSecurityPolicy(cZopeSecurityPolicy, ZopeSecurityPolicy):
"""A security manager provides methods for checking access and managing
executable context and policies
"""
class SecurityManager(cSecurityManager, SecurityManager):
"""A security manager provides methods for checking access and managing
executable context and policies
"""
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""Controller that can switch between security machinery implementations.
This module allows configuration of the security implementation after
the initial import of the modules. It is intended to allow runtime
selection of the machinery based on Zope's configuration file.
The helper function defined here switches between the 'C' and 'PYTHON'
security implementations by loading the appropriate implementation
module and wiring the implementation into the other modules of the
AccessControl package that defined the various components before this
module was introduced.
"""
def getImplementationName():
"""Return the name of the implementation currently being used."""
return _implementation_name
def setImplementation(name):
"""Select the policy implementation to use. The 'name' must be either
'PYTHON' or 'C'. NOTE: this function is intended to be called
exactly once, so that the Zope config file can dictate the policy
implementation to be used. Subsequent calls to this function will
have no effect!!
"""
import sys
global _implementation_name
global _implementation_set
if _implementation_set:
return
name = name.upper()
if name == _implementation_name:
return
if name == "C":
from AccessControl import ImplC as impl
elif name == "PYTHON":
from AccessControl import ImplPython as impl
else:
raise ValueError("unknown policy implementation: %r" % name)
_implementation_name = name
for modname, names in _policy_names.items():
__import__(modname)
mod = sys.modules[modname]
for n in names:
setattr(mod, n, getattr(impl, n))
if hasattr(mod, "initialize"):
mod.initialize(impl)
from AccessControl.SecurityManager import setSecurityPolicy
policy = impl.ZopeSecurityPolicy(True, True)
setSecurityPolicy(policy)
_implementation_set = 1
_implementation_name = None
_implementation_set = 0
_policy_names = {
"AccessControl": ("setDefaultBehaviors",
),
"AccessControl.DTML": ("RestrictedDTML",
),
"AccessControl.PermissionRole": ("_what_not_even_god_should_do",
"rolesForPermissionOn",
"PermissionRole",
"imPermissionRole",
),
"AccessControl.SecurityManagement": ("SecurityManager",
),
"AccessControl.SecurityManager": ("SecurityManager",
),
"AccessControl.ZopeGuards": ("aq_validate",
"guarded_getattr",
),
"AccessControl.ZopeSecurityPolicy": ("ZopeSecurityPolicy",
),
}
# start with the default, mostly because we need something for the tests
setImplementation("C")
# allow the implementation to change from the default
_implementation_set = 0
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""Permissions
$Id$
"""
import string
from Acquisition import aq_base
name_trans=filter(lambda c, an=string.letters+string.digits+'_': c not in an,
map(chr,range(256)))
name_trans=string.maketrans(''.join(name_trans), '_'*len(name_trans))
def pname(name, translate=string.translate, name_trans=name_trans):
return '_'+translate(name,name_trans)+"_Permission"
_marker=[]
class Permission:
# A Permission maps a named logical permission to a set
# of attribute names. Attribute names which appear in a
# permission may not appear in any other permission defined
# by the object.
def __init__(self,name,data,obj,default=None):
self.name=name
self._p='_'+string.translate(name,name_trans)+"_Permission"
self.data=data
self.obj=aq_base(obj)
self.default=default
def getRoles(self, default=_marker):
# Return the list of role names which have been given
# this permission for the object in question. To do
# this, we try to get __roles__ from all of the object
# attributes that this permission represents.
obj=self.obj
name=self._p
if hasattr(obj, name): return getattr(obj, name)
roles=default
for name in self.data:
if name:
if hasattr(obj, name):
attr=getattr(obj, name)
if hasattr(attr,'im_self'):
attr=attr.im_self
if hasattr(attr, '__dict__'):
attr=attr.__dict__
name=name+'__roles__'
if attr.has_key(name):
roles=attr[name]
break
elif hasattr(obj, '__dict__'):
attr=obj.__dict__
if attr.has_key('__roles__'):
roles=attr['__roles__']
break
if roles:
try:
if 'Shared' not in roles: return tuple(roles)
roles=list(roles)
roles.remove('Shared')
return roles
except: return []
if roles is None: return ['Manager','Anonymous']
if roles is _marker: return ['Manager']
return roles
def setRoles(self, roles):
obj=self.obj
if isinstance(roles, list) and not roles:
if hasattr(obj, self._p): delattr(obj, self._p)
else:
setattr(obj, self._p, roles)
for name in self.data:
if name=='': attr=obj
else: attr=getattr(obj, name)
try: del attr.__roles__
except: pass
try: delattr(obj,name+'__roles__')
except: pass
def setRole(self, role, present):
roles=self.getRoles()
if role in roles:
if present: return
if isinstance(roles, list): roles.remove(role)
else:
roles=list(roles)
roles.remove(role)
roles=tuple(roles)
elif not present: return
else:
if isinstance(roles, list): roles.append(role)
else: roles=roles+(role,)
self.setRoles(roles)
def __len__(self): return 1
def __str__(self): return self.name
_registeredPermissions={}
_registerdPermission=_registeredPermissions.has_key
def registerPermissions(permissions, defaultDefault=('Manager',)):
"""Register an __ac_permissions__ sequence.
"""
import Products
for setting in permissions:
if _registerdPermission(setting[0]): continue
if len(setting)==2:
perm, methods = setting
default = defaultDefault
else:
perm, methods, default = setting
_registeredPermissions[perm]=1
Products_permissions = getattr(Products, '__ac_permissions__', ())
Products.__ac_permissions__=(
Products_permissions + ((perm, (), default),))
mangled=pname(perm) # get mangled permission name
if not hasattr(ApplicationDefaultPermissions, mangled):
setattr(ApplicationDefaultPermissions,
mangled, default)
class ApplicationDefaultPermissions:
_View_Permission = ('Manager', 'Anonymous')
_Access_contents_information_Permission = ('Manager', 'Anonymous')
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
"""Permission Mapping
Sometimes, we need an object's permissions to be remapped to other permissions
when the object is used in specual ways. This is rather hard, since we
need the object's ordinary permissions intact so we can manage it.
$Id$
"""
from cgi import escape
from Acquisition import ImplicitAcquisitionWrapper
from App.class_init import InitializeClass
from ExtensionClass import Base
from zope.interface import implements
from AccessControl.interfaces import IPermissionMappingSupport
from AccessControl.Owned import UnownableOwner
from AccessControl.Permission import pname
from AccessControl.requestmethod import requestmethod
class RoleManager:
implements(IPermissionMappingSupport)
# XXX: No security declarations?
def manage_getPermissionMapping(self):
"""Return the permission mapping for the object
This is a list of dictionaries with:
permission_name -- The name of the native object permission
class_permission -- The class permission the permission is
mapped to.
"""
wrapper=getattr(self, '_permissionMapper', None)
if wrapper is None: wrapper=PM()
perms={}
for p in self.possible_permissions():
perms[pname(p)]=p
r=[]
a=r.append
for ac_perms in self.ac_inherited_permissions(1):
p=perms.get(getPermissionMapping(ac_perms[0], wrapper), '')
a({'permission_name': ac_perms[0], 'class_permission': p})
return r
@requestmethod('POST')
def manage_setPermissionMapping(self,
permission_names=[],
class_permissions=[], REQUEST=None):
"""Change the permission mapping
"""
wrapper=getattr(self, '_permissionMapper', None)
if wrapper is None: wrapper=PM()
perms=self.possible_permissions()
for i in range(len(permission_names)):
name=permission_names[i]
p=class_permissions[i]
if p and (p not in perms):
__traceback_info__=perms, p, i
raise ValueError, (
"""Attempted to map a permission to a permission, %s,
that is not valid. This should never happen. (Waaa).
""" % escape(p))
setPermissionMapping(name, wrapper, p)
self._permissionMapper=wrapper
if REQUEST is not None:
return self.manage_access(
REQUEST,
manage_tabs_message='The permission mapping has been updated')
def _isBeingUsedAsAMethod(self, REQUEST =None, wannaBe=0):
try:
if hasattr(self, 'aq_self'):
r=self.aq_acquire('_isBeingUsedAsAMethod_')
else:
r=self._isBeingUsedAsAMethod_
except: r=0
if REQUEST is not None:
if not r != (not wannaBe): REQUEST.response.notFoundError()
return r
InitializeClass(RoleManager)
def getPermissionMapping(name, obj, st=type('')):
obj=getattr(obj, 'aq_base', obj)
name=pname(name)
r=getattr(obj, name, '')
if type(r) is not st: r=''
return r
def setPermissionMapping(name, obj, v):
name=pname(name)
if v: setattr(obj, name, pname(v))
elif obj.__dict__.has_key(name): delattr(obj, name)
class PM(Base):
_owner=UnownableOwner
_View_Permission='_View_Permission'
_is_wrapperish = 1
def __getattr__(self, name):
# We want to make sure that any non-explicitly set methods are
# private!
if name.startswith('_') and name.endswith("_Permission"): return ''
raise AttributeError, escape(name)
PermissionMapper=PM
def aqwrap(object, wrapper, parent):
r=Rewrapper()
r._ugh=wrapper, object, parent
return r
class Rewrapper(Base):
def __of__(self, parent):
w, m, p = self._ugh
return m.__of__(
ImplicitAcquisitionWrapper(
w, parent))
def __getattr__(self, name):
w, m, parent = self._ugh
self=m.__of__(
ImplicitAcquisitionWrapper(
w, parent))
return getattr(self, name)
def __call__(self, *args, **kw):
w, m, parent = self._ugh
self=m.__of__(
ImplicitAcquisitionWrapper(
w, parent))
return apply(self, args, kw)
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
'''Objects that implement Permission-based roles.
$Id$'''
# The following names are inserted by AccessControl.Implementation:
#
# rolesForPermissionOn, PermissionRole, imPermissionRole,
# _what_not_even_god_should_do
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
"""Constant definitions for built-in Zope permissions
$Id$"""
access_contents_information='Access contents information'
add_database_methods='Add Database Methods'
add_documents_images_and_files='Add Documents, Images, and Files'
add_external_methods='Add External Methods'
add_folders='Add Folders'
add_mailhost_objects='Add MailHost objects'
add_page_templates='Add Page Templates'
add_python_scripts='Add Python Scripts'
add_user_folders='Add User Folders'
add_vocabularies='Add Vocabularies'
add_z_gadfly_database_connections='Add Z Gadfly Database Connections'
add_zcatalogs='Add ZCatalogs'
add_zope_tutorials='Add Zope Tutorials'
change_dtml_documents='Change DTML Documents'
change_dtml_methods='Change DTML Methods'
change_database_connections='Change Database Connections'
change_database_methods='Change Database Methods'
change_external_methods='Change External Methods'
change_images_and_files='Change Images and Files'
change_python_scripts='Change Python Scripts'
change_configuration='Change configuration'
change_page_templates='Change Page Templates'
change_permissions='Change permissions'
change_proxy_roles='Change proxy roles'
create_class_instances='Create class instances'
define_permissions='Define permissions'
delete_objects='Delete objects'
edit_factories='Edit Factories'
ftp_access='FTP access'
import_export_objects='Import/Export objects'
manage_vocabulary='Manage Vocabulary'
manage_zcatalog_entries='Manage ZCatalog Entries'
manage_zcatalog_indexes='Manage ZCatalogIndex Entries'
manage_properties='Manage properties'
manage_users='Manage users'
open_close_database_connection='Open/Close Database Connection'
open_close_database_connections='Open/Close Database Connections'
query_vocabulary='Query Vocabulary'
search_zcatalog='Search ZCatalog'
take_ownership='Take ownership'
test_database_connections='Test Database Connections'
undo_changes='Undo changes'
use_database_methods='Use Database Methods'
use_factories='Use Factories'
use_mailhost_services='Use mailhost services'
view='View'
view_history='View History'
view_management_screens='View management screens'
copy_or_move='Copy or Move'
webdav_access='WebDAV access'
webdav_lock_items='WebDAV Lock items'
webdav_unlock_items='WebDAV Unlock items'
This diff is collapsed.
<extension cAccessControl>
source cAccessControl.c
</extension>
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
"""Security management
$Id$
"""
def getSecurityManager():
"""Get a security manager, for the current thread.
"""
thread_id=get_ident()
manager=_managers.get(thread_id, None)
if manager is None:
nobody = getattr(SpecialUsers, 'nobody', None)
if nobody is None:
# Initialize SpecialUsers by importing User.py.
import User
nobody = SpecialUsers.nobody
manager = SecurityManager(thread_id, SecurityContext(nobody))
_managers[thread_id]=manager
return manager
def setSecurityManager(manager):
"""install *manager* as current security manager for this thread."""
thread_id=get_ident()
_managers[thread_id]=manager
import SpecialUsers
# AccessControl.Implementation inserts SecurityManager.
try:
from thread import get_ident
except ImportError:
def get_ident():
return 0
_managers={}
def newSecurityManager(request, user):
"""Set up a new security context for a request for a user
"""
thread_id=get_ident()
_managers[thread_id]=SecurityManager(
thread_id,
SecurityContext(user),
)
def noSecurityManager():
try: del _managers[get_ident()]
except: pass
def setSecurityPolicy(aSecurityPolicy):
"""Set the system default security policy.
This method should only be caused by system startup code. It should
never, for example, be called during a web request.
"""
SecurityManager.setSecurityPolicy(aSecurityPolicy)
class SecurityContext:
"""The security context is an object used internally to the security
machinery. It captures data about the current security context.
"""
def __init__(self, user):
self.stack=[]
self.user=user
self.objectCache = {}
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
'''API module to set the security policy
$Id$'''
from AccessControl import ImplPython as _ImplPython
from AccessControl.SimpleObjectPolicies import _noroles
def setSecurityPolicy(aSecurityPolicy):
"""Set the system default security policy.
This method should only be caused by system startup code. It should
never, for example, be called during a web request.
"""
last = _ImplPython._defaultPolicy
_ImplPython._defaultPolicy = aSecurityPolicy
return last
# AccessControl.Implementation inserts SecurityManager.
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
'''Collect rules for access to objects that don\'t have roles.
The rules are expressed as a mapping from type -> assertion
An assertion can be:
- A dict
- A callable
- Something with a truth value
If the assertion is a callable, then it will be called with
a name being accessed and the name used. Its return value is ignored,
but in may veto an access by raising an exception.
If the assertion is a dictionary, then the keys are attribute names.
The values may be callables or objects with boolean values. If a value
is callable, it will be called with the object we are accessing an
attribute of and the attribute name. It should return an attribute
value. Callables are often used to returned guarded versions of
methods. Otherwise, accesses are allowed if values in this dictionary
are true and disallowed if the values are false or if an item for an
attribute name is not present.
If the assertion is not a dict and is not callable, then access to
unprotected attributes is allowed if the assertion is true, and
disallowed otherwise.
XXX This descrition doesn't actually match what's done in ZopeGuards
or in ZopeSecurityPolicy. :(
$Id$'''
_noroles = [] # this is imported in various places
import Record
# Allow access to unprotected attributes
Record.Record.__allow_access_to_unprotected_subobjects__=1
# ContainerAssertions are used by cAccessControl to check access to
# attributes of container types, like dict, list, or string.
# ContainerAssertions maps types to a either a dict, a function, or a
# simple boolean value. When guarded_getattr checks the type of its
# first argument against ContainerAssertions, and invokes checking
# logic depending on what value it finds.
# If the value for a type is:
# - a boolean value:
# - the value determines whether access is allowed
# - a function (or callable):
# - The function is called with the name of the attribute and
# the actual attribute value, then the value is returned.
# The function can raise an exception.
# - a dict:
# - The dict maps attribute names to boolean values or functions.
# The boolean values behave as above, but the functions do not.
# The value returned for attribute access is the result of
# calling the function with the object and the attribute name.
ContainerAssertions={
type(()): 1,
type(''): 1,
type(u''): 1,
}
class _dummy_class: pass
from DocumentTemplate.DT_Util import TemplateDict
# Temporarily create a DictInstance so that we can mark its type as
# being a key in the ContainerAssertions.
templateDict = TemplateDict()
try:
dictInstance = templateDict(dummy=1)[0]
if type(dictInstance) is not type(_dummy_class()):
ContainerAssertions[type(dictInstance)]=1
except:
# Hmm, this may cause _() and _.namespace() to fail.
# What to do?
pass
Containers = ContainerAssertions.get
def allow_type(Type, allowed=1):
"""Allow a type and all of its methods and attributes to be used from
restricted code. The argument Type must be a type."""
if type(Type) is not type:
raise ValueError, "%s is not a type" % `Type`
if hasattr(Type, '__roles__'):
raise ValueError, "%s handles its own security" % `Type`
if not (isinstance(allowed, int) or isinstance(allowed, dict)):
raise ValueError, "The 'allowed' argument must be an int or dict."
ContainerAssertions[Type] = allowed
#
# WAAAA!
#
from BTrees.OOBTree import OOBTree, OOBucket, OOSet
from BTrees.OIBTree import OIBTree, OIBucket, OISet
from BTrees.IOBTree import IOBTree, IOBucket, IOSet
from BTrees.IIBTree import IIBTree, IIBucket, IISet
for tree_type, has_values in [(OOBTree, 1),
(OOBucket, 1),
(OOSet, 0),
(OIBTree, 1),
(OIBucket, 1),
(OISet, 0),
(IOBTree, 1),
(IOBucket, 1),
(IOSet, 0),
(IIBTree, 1),
(IIBucket, 1),
(IISet, 0),
]:
tree = tree_type()
key_type = type(tree.keys())
if key_type is not list: # lists have their own declarations
allow_type(key_type)
if has_values:
assert key_type is type(tree.values())
assert key_type is type(tree.items())
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""Place to find special users
This is needed to avoid a circular import problem. The 'real' values
are stored here by the AccessControl.User module as part of it's
initialization.
$Id$
"""
nobody = None
system = None
emergency_user = None
# Note: use of the 'super' name is deprecated.
super = None
This diff is collapsed.
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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
#
##############################################################################
"""Define Zope's default security policy
$Id$"""
from types import MethodType
# AccessControl.Implementation inserts:
# ZopeSecurityPolicy, getRoles, rolesForPermissionOn
from AccessControl.SimpleObjectPolicies import _noroles
rolesForPermissionOn = None # XXX: avoid import loop
tuple_or_list = tuple, list
def getRoles(container, name, value, default):
global rolesForPermissionOn # XXX: avoid import loop
if rolesForPermissionOn is None:
from PermissionRole import rolesForPermissionOn
roles = getattr(value, '__roles__', _noroles)
if roles is _noroles:
if not name or not isinstance(name, basestring):
return default
if type(value) is MethodType:
container = value.im_self
cls = getattr(container, '__class__', None)
if cls is None:
return default
roles = getattr(cls, name+'__roles__', _noroles)
if roles is _noroles:
return default
value = container
if roles is None or isinstance(roles, tuple_or_list):
return roles
rolesForPermissionOn = getattr(roles, 'rolesForPermissionOn', None)
if rolesForPermissionOn is not None:
roles = rolesForPermissionOn(value)
return roles
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# A wrapper to replace the usage of the zLOG module in cAccessControl without
# having the need to change the C code significantly.
from logging import getLogger
LOG = getLogger('AccessControl')
warn = LOG.warn
This diff is collapsed.
This diff is collapsed.
Architecture of the Zope SecuritySuite
The base class of the suite is "SecurityBase" and contains
the basic function of perform tests for permissions, roles
and perform ZPublisher request:
- _checkPermission()
- _checkRoles()
- _request()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment