1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 Benoît PIN <benoit.pin@ensmp.fr> #
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. #
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. #
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
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 zope
.i18n
import translate
as i18ntranslate
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
48 security
= ModuleSecurityInfo( 'Products.Plinn.utils' )
50 security
.declarePublic('thisObjectComeFromPortalSkin')
51 def thisObjectComeFromPortalSkin(ob
, portal
=None):
52 """ check if ob comes from portal_skins """
54 portal
= getToolByName(ob
, 'portal_url')
55 portal
= portal
.getPortalObject()
57 if ob
.aq_self
== portal
.aq_self
:
64 sob
= getattr(portal
, obId
, None)
68 elif not(sob
.aq_inner
.aq_self
is ob
.aq_inner
.aq_self
) :
77 security
.declarePublic('listActionProviders_')
78 def listActionProviders_(context
) :
79 atool
= getToolByName(context
, 'portal_actions')
80 return atool
.listActionProviders()
82 def capitalizeCompoundGivenName(givenName
) :
83 givenName
= givenName
.strip()
84 givenNames
= ' '.join(givenName
.split('-')).split()
85 givenNameCapitalized
= '-'.join(map(string
.capitalize
, givenNames
))
86 return givenNameCapitalized
89 def formatFullName(memberName
, memberGivenName
, memberId
, nameBefore
=1) :
90 memberName
= memberName
.decode('utf-8')
91 memberGivenName
= memberGivenName
.decode('utf-8')
93 if memberName
and memberGivenName
:
95 memberFullName
= memberName
.upper() + ' ' + capitalizeCompoundGivenName(memberGivenName
)
97 memberFullName
= capitalizeCompoundGivenName(memberGivenName
) + ' ' + memberName
.upper()
99 elif memberName
and not memberGivenName
:
100 memberFullName
= memberName
.upper()
102 elif not memberName
and memberGivenName
:
103 memberFullName
= capitalizeCompoundGivenName(memberGivenName
)
106 memberFullName
= memberId
108 return memberFullName
.encode('utf-8')
110 # from OFS.ObjectManager #63
111 bad_url_chars
= re
.compile(r
'[^a-zA-Z0-9-_~,.$\(\)@]')
113 security
.declarePublic('makeValidId')
114 def makeValidId(self
, id, allow_dup
=0):
115 id = Utf8Utils
.desacc(id)
116 id = bad_url_chars
.sub('-', id)
117 # If allow_dup is false, an error will be raised if an object
118 # with the given id already exists. If allow_dup is true,
119 # only check that the id string contains no illegal chars;
120 # check_valid_id() will be called again later with allow_dup
121 # set to false before the object is added.
124 if id in ('.', '..'):
126 if id.startswith('_'):
128 if id.startswith('aq_'):
131 while id.endswith('__') :
134 obj
= getattr(self
, id, None)
136 # An object by the given id exists either in this
137 # ObjectManager or in the acquisition path.
138 flags
= getattr(obj
, '__replaceable__', NOT_REPLACEABLE
)
139 if hasattr(aq_base(self
), id):
140 # The object is located in this ObjectManager.
141 if not flags
& REPLACEABLE
:
143 # else the object is replaceable even if the UNIQUE
150 if makeRandomId
is True :
151 id = str(randrange(2,10000)) + id
156 def _checkMemberPermission(userid
, permission
, obj
, StringType
= type('')):
157 user
= obj
.aq_inner
.acl_users
.getUser(userid
)
158 roles
= rolesForPermissionOn(permission
, obj
)
159 if type(roles
) is StringType
:
161 if user
.allowed( obj
, roles
):
165 def getCPInfo(self
) :
166 try: cp
= _cb_decode(self
.REQUEST
['__cp'])
171 def popCP(self
, indexes
=None) :
172 try: cp
= _cb_decode(self
.REQUEST
['__cp'])
176 if indexes
is not None :
177 indexes
= list(indexes
)
180 for index
in indexes
:
186 self
.REQUEST
.RESPONSE
.expireCookie('__cp', path
=self
.REQUEST
['BASEPATH1'] or "/")
189 cp
= _cb_encode( (cp
[0], paths
) )
190 resp
= self
.REQUEST
['RESPONSE']
191 resp
.setCookie('__cp', cp
, path
='%s' % cookie_path(self
.REQUEST
))
193 security
.declarePublic('Message')
194 Message
= MessageFactory('plinn')
196 security
.declarePublic('translate')
197 def translate(message
, context
):
198 """ Translate i18n message.
200 if isinstance(message
, Exception):
203 except (TypeError, IndexError):
205 return i18ntranslate(message
, domain
='plinn', context
=context
.REQUEST
)
207 security
.declarePublic('desacc')
208 desacc
= Utf8Utils
.desacc
210 security
.declarePublic('getPreferredLanguages')
211 def getPreferredLanguages(context
):
212 """ returns browser prefered languages"""
213 request
= getattr(context
, 'REQUEST', None)
214 if request
is not None :
215 adapter
= IUserPreferredLanguages(request
, None)
216 if adapter
is not None :
217 return adapter
.getPreferredLanguages()
220 security
.declarePublic('getBestTranslationLanguage')
221 def getBestTranslationLanguage(langs
, context
):
222 """ returns best translation language according
223 availables languages (param langs)
224 and user preferences (retrieves by context)
226 request
= getattr(context
, 'REQUEST', None)
228 negociator
= getUtilityByInterfaceName('zope.i18n.interfaces.INegotiator')
229 return negociator
.getLanguage(langs
, request
) or langs
[0]
233 security
.declarePublic('getAdapterByInterface')
234 def getAdapterByInterface(ob
, dotted_name
, default
=_marker
) :
235 """ Get the adapter which provides the interface on the given object.
238 iface
= resolve_dotted_name(dotted_name
)
240 if default
is _marker
:
241 raise ComponentLookupError
, dotted_name
244 adapter
= queryAdapter(ob
, iface
, default
=default
)
245 if adapter
is _marker
:
246 raise ComponentLookupError
, "no adapter providing %r found on %r" % (dotted_name
, ob
)
248 # the adapter must be wrapped to allow security mahinery to work.
249 if adapter
!= default
:
250 return adapter
.__of
__(ob
)
254 def _sudo(func
, userid
=None) :
256 execute func or any callable object
257 without restriction. Used to switch off
258 security assertions (eg. checkPermission) encountered
259 during the execution.
262 sm
= getSecurityManager()
263 restrictedUser
= sm
.getUser()
266 userid
= restrictedUser
.getId()
268 sm
._context
.user
= UnrestrictedUser(userid
, '', (), ())
273 except Exception, e
:
276 sm
._context
.user
= restrictedUser
278 if deferedEx
is not None :