vendor/CMF/1.6.3/CMFCore

annotate FSMetadata.py @ 2:4c712d7bd1d7

Added tag 1.6.3 for changeset 1babb9d61518
author Georges Racinet on purity.racinet.fr <georges@racinet.fr>
date Fri, 09 Sep 2011 12:44:00 +0200
parents
children
rev   line source
bdelbosc@0 1 ##############################################################################
bdelbosc@0 2 #
bdelbosc@0 3 # Copyright (c) 2003 Zope Corporation and Contributors. All Rights Reserved.
bdelbosc@0 4 #
bdelbosc@0 5 # This software is subject to the provisions of the Zope Public License,
bdelbosc@0 6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
bdelbosc@0 7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
bdelbosc@0 8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
bdelbosc@0 9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
bdelbosc@0 10 # FOR A PARTICULAR PURPOSE.
bdelbosc@0 11 #
bdelbosc@0 12 ##############################################################################
bdelbosc@0 13 """ Handles reading the properties for an object that comes from the filesystem.
bdelbosc@0 14
bdelbosc@0 15 $Id$
bdelbosc@0 16 """
bdelbosc@0 17
bdelbosc@0 18 import logging
bdelbosc@0 19 from os.path import exists
bdelbosc@0 20 from ConfigParser import ConfigParser
bdelbosc@0 21 from warnings import warn
bdelbosc@0 22
bdelbosc@0 23 import re
bdelbosc@0 24
bdelbosc@0 25
bdelbosc@0 26 logger = logging.getLogger('CMFCore.FSMetadata')
bdelbosc@0 27
bdelbosc@0 28
bdelbosc@0 29 class CMFConfigParser(ConfigParser):
bdelbosc@0 30 """ This our wrapper around ConfigParser to
bdelbosc@0 31 solve a few minor niggles with the code """
bdelbosc@0 32 # adding in a space so that names can contain spaces
bdelbosc@0 33 OPTCRE = re.compile(
bdelbosc@0 34 r'(?P<option>[]\-[ \w_.*,(){}]+)' # a lot of stuff found by IvL
bdelbosc@0 35 r'[ \t]*(?P<vi>[:=])[ \t]*' # any number of space/tab,
bdelbosc@0 36 # followed by separator
bdelbosc@0 37 # (either : or =), followed
bdelbosc@0 38 # by any # space/tab
bdelbosc@0 39 r'(?P<value>.*)$' # everything up to eol
bdelbosc@0 40 )
bdelbosc@0 41
bdelbosc@0 42 def optionxform(self, optionstr):
bdelbosc@0 43 """
bdelbosc@0 44 Stop converting the key to lower case, very annoying for security etc
bdelbosc@0 45 """
bdelbosc@0 46 return optionstr.strip()
bdelbosc@0 47
bdelbosc@0 48 class FSMetadata:
bdelbosc@0 49 # public API
bdelbosc@0 50 def __init__(self, filename):
bdelbosc@0 51 self._filename = filename
bdelbosc@0 52
bdelbosc@0 53 def read(self):
bdelbosc@0 54 """ Find the files to read, either the old security and
bdelbosc@0 55 properties type or the new metadata type """
bdelbosc@0 56 filename = self._filename + '.metadata'
bdelbosc@0 57 if exists(filename):
bdelbosc@0 58 # found the new type, lets use that
bdelbosc@0 59 self._readMetadata()
bdelbosc@0 60 else:
bdelbosc@0 61 # not found so try the old ones
bdelbosc@0 62 self._properties = self._old_readProperties()
bdelbosc@0 63 self._security = self._old_readSecurity()
bdelbosc@0 64
bdelbosc@0 65 def getProxyRoles(self):
bdelbosc@0 66 """ Returns the proxy roles """
bdelbosc@0 67 if self.getProperties():
bdelbosc@0 68 pxy = self.getProperties().get('proxy')
bdelbosc@0 69 if pxy:
bdelbosc@0 70 return [r.strip() for r in pxy.split(',') if r.strip()]
bdelbosc@0 71 return []
bdelbosc@0 72
bdelbosc@0 73 def getSecurity(self):
bdelbosc@0 74 """ Gets the security settings """
bdelbosc@0 75 return self._security
bdelbosc@0 76
bdelbosc@0 77 def getProperties(self):
bdelbosc@0 78 """ Gets the properties settings """
bdelbosc@0 79 return self._properties
bdelbosc@0 80
bdelbosc@0 81 # private API
bdelbosc@0 82 def _readMetadata(self):
bdelbosc@0 83 """ Read the new file format using ConfigParser """
bdelbosc@0 84 self._properties = {}
bdelbosc@0 85 self._security = {}
bdelbosc@0 86
bdelbosc@0 87 try:
bdelbosc@0 88 cfg = CMFConfigParser()
bdelbosc@0 89 cfg.read(self._filename + '.metadata')
bdelbosc@0 90
bdelbosc@0 91 # the two sections we care about
bdelbosc@0 92 self._properties = self._getSectionDict(cfg, 'default')
bdelbosc@0 93 self._security = self._getSectionDict(cfg, 'security',
bdelbosc@0 94 self._securityParser)
bdelbosc@0 95 except:
bdelbosc@0 96 logger.exception("Error parsing .metadata file")
bdelbosc@0 97
bdelbosc@0 98 # to add in a new value such as proxy roles,
bdelbosc@0 99 # just add in the section, call it using getSectionDict
bdelbosc@0 100 # if you need a special parser for some whacky
bdelbosc@0 101 # config, then just pass through a special parser
bdelbosc@0 102
bdelbosc@0 103 def _nullParser(self, data):
bdelbosc@0 104 """
bdelbosc@0 105 This is the standard rather boring null parser that does very little
bdelbosc@0 106 """
bdelbosc@0 107 return data
bdelbosc@0 108
bdelbosc@0 109 def _securityParser(self, data):
bdelbosc@0 110 """ A specific parser for security lines
bdelbosc@0 111
bdelbosc@0 112 Security lines must be of the format
bdelbosc@0 113
bdelbosc@0 114 Permission = (0|1):Role[,Role...]
bdelbosc@0 115
bdelbosc@0 116 Where 0|1 is the acquire permission setting
bdelbosc@0 117 and Role is the roles for this permission
bdelbosc@0 118 eg: 1:Manager or 0:Manager,Anonymous
bdelbosc@0 119 """
bdelbosc@0 120 if data.find(':') < 1:
bdelbosc@0 121 raise ValueError, "The security declaration of file " + \
bdelbosc@0 122 "%r is in the wrong format" % self._filename
bdelbosc@0 123
bdelbosc@0 124 acquire, roles = data.split(':')
bdelbosc@0 125 roles = [r.strip() for r in roles.split(',') if r.strip()]
bdelbosc@0 126 return (int(acquire), roles)
bdelbosc@0 127
bdelbosc@0 128 def _getSectionDict(self, cfg, section, parser=None):
bdelbosc@0 129 """
bdelbosc@0 130 Get a section and put it into a dict, mostly a convenience
bdelbosc@0 131 function around the ConfigParser
bdelbosc@0 132
bdelbosc@0 133 Note: the parser is a function to parse each value, so you can
bdelbosc@0 134 have custom values for the key value pairs
bdelbosc@0 135 """
bdelbosc@0 136 if parser is None:
bdelbosc@0 137 parser = self._nullParser
bdelbosc@0 138
bdelbosc@0 139 props = {}
bdelbosc@0 140 if cfg.has_section(section):
bdelbosc@0 141 for opt in cfg.options(section):
bdelbosc@0 142 props[opt] = parser(cfg.get(section, opt))
bdelbosc@0 143 return props
bdelbosc@0 144
bdelbosc@0 145 # we need to return None if we have none to be compatible
bdelbosc@0 146 # with existing API
bdelbosc@0 147 return None
bdelbosc@0 148
bdelbosc@0 149 def _old_readProperties(self):
bdelbosc@0 150 """
bdelbosc@0 151 Reads the properties file next to an object.
bdelbosc@0 152
bdelbosc@0 153 Moved from DirectoryView.py to here with only minor
bdelbosc@0 154 modifications. Old and deprecated in favour of .metadata now
bdelbosc@0 155 """
bdelbosc@0 156 fp = self._filename + '.properties'
bdelbosc@0 157 try:
bdelbosc@0 158 f = open(fp, 'rt')
bdelbosc@0 159 except IOError:
bdelbosc@0 160 return None
bdelbosc@0 161 else:
bdelbosc@0 162 warn('.properties objects will disappear in CMF 2.0 - Use '
bdelbosc@0 163 '.metadata objects instead.', DeprecationWarning)
bdelbosc@0 164 lines = f.readlines()
bdelbosc@0 165 f.close()
bdelbosc@0 166 props = {}
bdelbosc@0 167 for line in lines:
bdelbosc@0 168 kv = line.split('=', 1)
bdelbosc@0 169 if len(kv) == 2:
bdelbosc@0 170 props[kv[0].strip()] = kv[1].strip()
bdelbosc@0 171 else:
bdelbosc@0 172 logger.exception("Error parsing .properties file")
bdelbosc@0 173
bdelbosc@0 174 return props
bdelbosc@0 175
bdelbosc@0 176 def _old_readSecurity(self):
bdelbosc@0 177 """
bdelbosc@0 178 Reads the security file next to an object.
bdelbosc@0 179
bdelbosc@0 180 Moved from DirectoryView.py to here with only minor
bdelbosc@0 181 modifications. Old and deprecated in favour of .metadata now
bdelbosc@0 182 """
bdelbosc@0 183 fp = self._filename + '.security'
bdelbosc@0 184 try:
bdelbosc@0 185 f = open(fp, 'rt')
bdelbosc@0 186 except IOError:
bdelbosc@0 187 return None
bdelbosc@0 188 else:
bdelbosc@0 189 warn('.security objects will disappear in CMF 2.0 - Use '
bdelbosc@0 190 '.metadata objects instead.', DeprecationWarning)
bdelbosc@0 191 lines = f.readlines()
bdelbosc@0 192 f.close()
bdelbosc@0 193 prm = {}
bdelbosc@0 194 for line in lines:
bdelbosc@0 195 try:
bdelbosc@0 196 c1 = line.index(':')+1
bdelbosc@0 197 c2 = line.index(':',c1)
bdelbosc@0 198 permission = line[:c1-1]
bdelbosc@0 199 acquire = bool(line[c1:c2])
bdelbosc@0 200 proles = line[c2+1:].split(',')
bdelbosc@0 201 roles=[]
bdelbosc@0 202 for role in proles:
bdelbosc@0 203 role = role.strip()
bdelbosc@0 204 if role:
bdelbosc@0 205 roles.append(role)
bdelbosc@0 206 except:
bdelbosc@0 207 logger.exception("Error reading permission "
bdelbosc@0 208 "from .security file")
bdelbosc@0 209 prm[permission]=(acquire,roles)
bdelbosc@0 210 return prm