vendor/CMF/1.6.3/CMFCore

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