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 quopri
import encodestring
31 from AccessControl
.PermissionRole
import rolesForPermissionOn
32 from AccessControl
import ModuleSecurityInfo
33 from AccessControl
import getSecurityManager
34 from AccessControl
.User
import UnrestrictedUser
35 from OFS
.CopySupport
import _cb_decode
, _cb_encode
, cookie_path
36 from Products
.CMFCore
.utils
import getToolByName
, getUtilityByInterfaceName
37 from Products
.CMFCore
.exceptions
import BadRequest
38 from Products
.Utf8Splitter
.Utf8Splitter
import Utf8Utils
39 from Globals
import REPLACEABLE
, NOT_REPLACEABLE
, UNIQUE
40 from zope
.i18n
import translate
as i18ntranslate
41 from zope
.i18n
.interfaces
import IUserPreferredLanguages
42 from zope
.i18nmessageid
import MessageFactory
43 from zope
.component
.interfaces
import ComponentLookupError
44 from zope
.dottedname
.resolve
import resolve
as resolve_dotted_name
45 from zope
.component
import queryAdapter
49 security
= ModuleSecurityInfo( 'Products.Plinn.utils' )
51 security
.declarePublic('thisObjectComeFromPortalSkin')
52 def thisObjectComeFromPortalSkin(ob
, portal
=None):
53 """ check if ob comes from portal_skins """
55 portal
= getToolByName(ob
, 'portal_url')
56 portal
= portal
.getPortalObject()
58 if ob
.aq_self
== portal
.aq_self
:
65 sob
= getattr(portal
, obId
, None)
69 elif not(sob
.aq_inner
.aq_self
is ob
.aq_inner
.aq_self
) :
78 security
.declarePublic('listActionProviders_')
79 def listActionProviders_(context
) :
80 atool
= getToolByName(context
, 'portal_actions')
81 return atool
.listActionProviders()
83 def capitalizeCompoundGivenName(givenName
) :
84 givenName
= givenName
.strip()
85 givenNames
= ' '.join(givenName
.split('-')).split()
86 givenNameCapitalized
= '-'.join(map(string
.capitalize
, givenNames
))
87 return givenNameCapitalized
90 def formatFullName(memberName
, memberGivenName
, memberId
, nameBefore
=1) :
91 memberName
= memberName
.decode('utf-8')
92 memberGivenName
= memberGivenName
.decode('utf-8')
94 if memberName
and memberGivenName
:
96 memberFullName
= memberName
.upper() + ' ' + capitalizeCompoundGivenName(memberGivenName
)
98 memberFullName
= capitalizeCompoundGivenName(memberGivenName
) + ' ' + memberName
.upper()
100 elif memberName
and not memberGivenName
:
101 memberFullName
= memberName
.upper()
103 elif not memberName
and memberGivenName
:
104 memberFullName
= capitalizeCompoundGivenName(memberGivenName
)
107 memberFullName
= memberId
109 return memberFullName
.encode('utf-8')
111 # from OFS.ObjectManager #63
112 bad_url_chars
= re
.compile(r
'[^a-zA-Z0-9-_~,.$\(\)@]')
114 security
.declarePublic('makeValidId')
115 def makeValidId(self
, id, allow_dup
=0):
116 id = Utf8Utils
.desacc(id)
117 id = bad_url_chars
.sub('-', id)
118 # If allow_dup is false, an error will be raised if an object
119 # with the given id already exists. If allow_dup is true,
120 # only check that the id string contains no illegal chars;
121 # check_valid_id() will be called again later with allow_dup
122 # set to false before the object is added.
125 if id in ('.', '..'):
127 if id.startswith('_'):
129 if id.startswith('aq_'):
132 while id.endswith('__') :
135 obj
= getattr(self
, id, None)
137 # An object by the given id exists either in this
138 # ObjectManager or in the acquisition path.
139 flags
= getattr(obj
, '__replaceable__', NOT_REPLACEABLE
)
140 if hasattr(aq_base(self
), id):
141 # The object is located in this ObjectManager.
142 if not flags
& REPLACEABLE
:
144 # else the object is replaceable even if the UNIQUE
151 if makeRandomId
is True :
152 id = str(randrange(2,10000)) + id
157 def _checkMemberPermission(userid
, permission
, obj
, StringType
= type('')):
158 user
= obj
.aq_inner
.acl_users
.getUser(userid
)
159 roles
= rolesForPermissionOn(permission
, obj
)
160 if type(roles
) is StringType
:
162 if user
.allowed( obj
, roles
):
166 def getCPInfo(self
) :
167 try: cp
= _cb_decode(self
.REQUEST
['__cp'])
172 def popCP(self
, indexes
=None) :
173 try: cp
= _cb_decode(self
.REQUEST
['__cp'])
177 if indexes
is not None :
178 indexes
= list(indexes
)
181 for index
in indexes
:
187 self
.REQUEST
.RESPONSE
.expireCookie('__cp', path
=self
.REQUEST
['BASEPATH1'] or "/")
190 cp
= _cb_encode( (cp
[0], paths
) )
191 resp
= self
.REQUEST
['RESPONSE']
192 resp
.setCookie('__cp', cp
, path
='%s' % cookie_path(self
.REQUEST
))
194 security
.declarePublic('Message')
195 Message
= MessageFactory('plinn')
197 security
.declarePublic('translate')
198 def translate(message
, context
):
199 """ Translate i18n message.
201 if isinstance(message
, Exception):
204 except (TypeError, IndexError):
206 return i18ntranslate(message
, domain
='plinn', context
=context
.REQUEST
)
208 security
.declarePublic('desacc')
209 desacc
= Utf8Utils
.desacc
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()
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)
227 request
= getattr(context
, 'REQUEST', None)
229 negociator
= getUtilityByInterfaceName('zope.i18n.interfaces.INegotiator')
230 return negociator
.getLanguage(langs
, request
) or langs
[0]
234 security
.declarePublic('getAdapterByInterface')
235 def getAdapterByInterface(ob
, dotted_name
, default
=_marker
) :
236 """ Get the adapter which provides the interface on the given object.
239 iface
= resolve_dotted_name(dotted_name
)
241 if default
is _marker
:
242 raise ComponentLookupError
, dotted_name
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
)
249 # the adapter must be wrapped to allow security mahinery to work.
250 if adapter
!= default
:
251 return adapter
.__of
__(ob
)
255 def encodeQuopriEmail(name
, email
) :
256 qpName
= encodestring(name
).replace('=\n', '')
257 return '''"=?utf-8?q?%s?=" <%s>''' % (qpName
, email
)
260 def _sudo(func
, userid
=None) :
262 execute func or any callable object
263 without restriction. Used to switch off
264 security assertions (eg. checkPermission) encountered
265 during the execution.
268 sm
= getSecurityManager()
269 restrictedUser
= sm
.getUser()
272 userid
= restrictedUser
.getId()
274 sm
._context
.user
= UnrestrictedUser(userid
, '', (), ())
279 except Exception, e
:
282 sm
._context
.user
= restrictedUser
284 if deferedEx
is not None :