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