726c4e8b57da42182ad71a7884e9de4ed7250626
[Plinn.git] / utils.py
1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 BenoƮt PIN <benoit.pin@ensmp.fr> #
5 # #
6 # This program is free software; you can redistribute it and/or #
7 # modify it under the terms of the GNU General Public License #
8 # as published by the Free Software Foundation; either version 2 #
9 # of the License, or (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program; if not, write to the Free Software #
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #
19 #######################################################################################
20 """ Plinn public utilities
21 $Id: utils.py 1534 2009-09-07 11:05:57Z pin $
22 $URL: http://svn.cri.ensmp.fr/svn/Plinn/branches/CMF-2.1/utils.py $
23 """
24
25 import string
26 import re
27 from types import StringType
28 from random import randrange
29 from Acquisition import aq_base
30 from AccessControl.PermissionRole import rolesForPermissionOn
31 from AccessControl import ModuleSecurityInfo
32 from AccessControl import getSecurityManager
33 from AccessControl.User import UnrestrictedUser
34 from OFS.CopySupport import _cb_decode, _cb_encode, cookie_path
35 from Products.CMFCore.utils import getToolByName, getUtilityByInterfaceName
36 from Products.CMFCore.exceptions import BadRequest
37 from Products.Utf8Splitter.Utf8Splitter import Utf8Utils
38 from Globals import REPLACEABLE, NOT_REPLACEABLE, UNIQUE
39 #from Products.PageTemplates.GlobalTranslationService import getGlobalTranslationService
40 from zope.i18n.interfaces import IUserPreferredLanguages
41 from zope.i18nmessageid import MessageFactory
42 from zope.component.interfaces import ComponentLookupError
43 from zope.dottedname.resolve import resolve as resolve_dotted_name
44 from zope.component import queryAdapter
45
46 _marker = []
47
48 security = ModuleSecurityInfo( 'Products.Plinn.utils' )
49
50 security.declarePublic('thisObjectComeFromPortalSkin')
51 def thisObjectComeFromPortalSkin(ob, portal=None):
52 """ check if ob comes from portal_skins """
53 if not portal :
54 portal = getToolByName(ob, 'portal_url')
55 portal = portal.getPortalObject()
56
57 if ob.aq_self == portal.aq_self :
58 return False
59
60 obId = ob.id
61 if callable(obId) :
62 obId = obId()
63
64 sob = getattr(portal, obId, None)
65
66 if sob is None :
67 return False
68 elif not(sob.aq_inner.aq_self is ob.aq_inner.aq_self) :
69 return False
70 else :
71 try :
72 portal._checkId(obId)
73 return True
74 except BadRequest :
75 return False
76
77 security.declarePublic('listActionProviders_')
78 def listActionProviders_(context) :
79 atool = getToolByName(context, 'portal_actions')
80 return atool.listActionProviders()
81
82 def capitalizeCompoundGivenName(givenName) :
83 givenName = givenName.strip()
84 givenNames = ' '.join(givenName.split('-')).split()
85 givenNameCapitalized = '-'.join(map(string.capitalize, givenNames))
86 return givenNameCapitalized
87
88
89 def formatFullName(memberName, memberGivenName, memberId, nameBefore=1) :
90 memberFullName = ''
91 if memberName and memberGivenName :
92 if nameBefore :
93 memberFullName = memberName.capitalize() + ' ' + capitalizeCompoundGivenName(memberGivenName)
94 else :
95 memberFullName = capitalizeCompoundGivenName(memberGivenName) + ' ' + memberName.capitalize()
96
97 elif memberName and not memberGivenName :
98 memberFullName = memberName.capitalize()
99
100 elif not memberName and memberGivenName :
101 memberFullName = capitalizeCompoundGivenName(memberGivenName)
102
103 else :
104 memberFullName = memberId
105
106 return memberFullName
107
108 # from OFS.ObjectManager #63
109 bad_url_chars = re.compile(r'[^a-zA-Z0-9-_~,.$\(\)@]')
110
111 security.declarePublic('makeValidId')
112 def makeValidId(self, id, allow_dup=0):
113 id = Utf8Utils.desacc(id)
114 id = bad_url_chars.sub('-', id)
115 # If allow_dup is false, an error will be raised if an object
116 # with the given id already exists. If allow_dup is true,
117 # only check that the id string contains no illegal chars;
118 # check_valid_id() will be called again later with allow_dup
119 # set to false before the object is added.
120
121 makeRandomId = False
122 if id in ('.', '..'):
123 makeRandomId = True
124 if id.startswith('_'):
125 id = id.lstrip('_')
126 if id.startswith('aq_'):
127 id = id[3:]
128
129 while id.endswith('__') :
130 id = id[:-1]
131 if not allow_dup:
132 obj = getattr(self, id, None)
133 if obj is not None:
134 # An object by the given id exists either in this
135 # ObjectManager or in the acquisition path.
136 flags = getattr(obj, '__replaceable__', NOT_REPLACEABLE)
137 if hasattr(aq_base(self), id):
138 # The object is located in this ObjectManager.
139 if not flags & REPLACEABLE:
140 makeRandomId = True
141 # else the object is replaceable even if the UNIQUE
142 # flag is set.
143 elif flags & UNIQUE:
144 makeRandomId = True
145 if id == 'REQUEST':
146 makeRandomId = True
147
148 if makeRandomId is True :
149 id = str(randrange(2,10000)) + id
150 return id
151
152
153
154 def _checkMemberPermission(userid, permission, obj, StringType = type('')):
155 user = obj.aq_inner.acl_users.getUser(userid)
156 roles = rolesForPermissionOn(permission, obj)
157 if type(roles) is StringType:
158 roles=[roles]
159 if user.allowed( obj, roles ):
160 return 1
161 return 0
162
163 def getCPInfo(self) :
164 try: cp = _cb_decode(self.REQUEST['__cp'])
165 except: return None
166 return cp
167
168
169 def popCP(self, indexes=None) :
170 try: cp = _cb_decode(self.REQUEST['__cp'])
171 except: return
172
173 paths = list(cp[1])
174 if indexes is not None :
175 indexes = list(indexes)
176 indexes.sort()
177 indexes.reverse()
178 for index in indexes :
179 paths.pop(index)
180 else :
181 paths.pop()
182
183 if not paths :
184 self.REQUEST.RESPONSE.expireCookie('__cp', path=self.REQUEST['BASEPATH1'] or "/")
185 else :
186 paths = tuple(paths)
187 cp = _cb_encode( (cp[0], paths) )
188 resp = self.REQUEST['RESPONSE']
189 resp.setCookie('__cp', cp, path='%s' % cookie_path(self.REQUEST))
190
191 security.declarePublic('Message')
192 Message = MessageFactory('plinn')
193
194 security.declarePublic('translate')
195 def translate(message, context):
196 """ Translate i18n message.
197 """
198 # TODO : localisation.
199 #GTS = getGlobalTranslationService()
200 if isinstance(message, Exception):
201 try:
202 message = message[0]
203 except (TypeError, IndexError):
204 pass
205 return message
206 return GTS.translate('plinn', message, context=context)
207
208 security.declarePublic('desacc')
209 desacc = Utf8Utils.desacc
210
211 security.declarePublic('getPreferredLanguages')
212 def getPreferredLanguages(context):
213 """ returns browser prefered languages"""
214 request = getattr(context, 'REQUEST', None)
215 if request is not None :
216 adapter = IUserPreferredLanguages(request, None)
217 if adapter is not None :
218 return adapter.getPreferredLanguages()
219 return []
220
221 security.declarePublic('getBestTranslationLanguage')
222 def getBestTranslationLanguage(langs, context):
223 """ returns best translation language according
224 availables languages (param langs)
225 and user preferences (retrieves by context)
226 """
227 request = getattr(context, 'REQUEST', None)
228 if request :
229 negociator = getUtilityByInterfaceName('zope.i18n.interfaces.INegotiator')
230 return negociator.getLanguage(langs, request) or langs[0]
231 else :
232 return langs[0]
233
234 security.declarePublic('getAdapterByInterface')
235 def getAdapterByInterface(ob, dotted_name, default=_marker) :
236 """ Get the adapter which provides the interface on the given object.
237 """
238 try:
239 iface = resolve_dotted_name(dotted_name)
240 except ImportError:
241 if default is _marker:
242 raise ComponentLookupError, dotted_name
243 return default
244
245 adapter = queryAdapter(ob, iface, default=default)
246 if adapter is _marker :
247 raise ComponentLookupError, "no adapter providing %r found on %r" % (dotted_name, ob)
248
249 # the adapter must be wrapped to allow security mahinery to work.
250 if adapter != default :
251 return adapter.__of__(ob)
252 else :
253 return default
254
255 def _sudo(func, userid=None) :
256 """
257 execute func or any callable object
258 without restriction. Used to switch off
259 security assertions (eg. checkPermission) encountered
260 during the execution.
261 """
262
263 sm = getSecurityManager()
264 restrictedUser = sm.getUser()
265
266 if not userid :
267 userid = restrictedUser.getId()
268
269 sm._context.user = UnrestrictedUser(userid, '', (), ())
270
271 deferedEx = None
272 try :
273 ret = func()
274 except Exception, e :
275 deferedEx = e
276
277 sm._context.user = restrictedUser
278
279 if deferedEx is not None :
280 raise e
281
282 return ret
283