def __init__(self, id, title, file, permissions=None, categories=None): self.id = id self.title = title file, ext = os.path.splitext(file) prefix, file = os.path.split(file) self.index_html = DTMLFile(file, prefix) if permissions is not None: self.permissions = permissions if categories is not None: self.categories = categories
class DTMLTopic(HelpTopic): """ A basic Help Topic. Holds a HTMLFile object. """ def __init__(self, id, title, file, permissions=None, categories=None): self.id = id self.title = title file, ext = os.path.splitext(file) prefix, file = os.path.split(file) self.index_html = DTMLFile(file, prefix) if permissions is not None: self.permissions = permissions if categories is not None: self.categories = categories def SearchableText(self): "The full text of the Help Topic, for indexing purposes" return "%s %s" % (self.title, self.index_html.read())
class PloneControlPanel(PloneBaseTool, UniqueObject, Folder, ActionProviderBase, PropertyManager): """Weave together the various sources of "actions" which are apropos to the current user and context. """ security = ClassSecurityInfo() id = 'portal_controlpanel' title = 'Control Panel' toolicon = 'skins/plone_images/site_icon.png' meta_type = 'Plone Control Panel Tool' _actions_form = DTMLFile('www/editPloneConfiglets', globals()) manage_options = (ActionProviderBase.manage_options + PropertyManager.manage_options) group = dict(member=[ ('Member', _(u'My Preferences')), ], site=[ ('plone-general', _(u'General')), ('plone-content', _(u'Content')), ('plone-users', _(u'Users')), ('plone-security', _(u'Security')), ('plone-advanced', _(u'Advanced')), ('Plone', _(u'Plone Configuration')), ('Products', _(u'Add-on Configuration')), ]) def __init__(self, **kw): if kw: self.__dict__.update(**kw) security.declareProtected(ManagePortal, 'registerConfiglets') def registerConfiglets(self, configlets): for conf in configlets: self.registerConfiglet(**conf) security.declareProtected(ManagePortal, 'getGroupIds') def getGroupIds(self, category='site'): groups = self.group.get(category, []) return [g[0] for g in groups if g] security.declareProtected(View, 'getGroups') def getGroups(self, category='site'): groups = self.group.get(category, []) return [{'id': g[0], 'title': g[1]} for g in groups if g] security.declarePrivate('listActions') def listActions(self, info=None, object=None): # This exists here to shut up a deprecation warning about old-style # actions in CMFCore's ActionProviderBase. It was decided not to # move configlets to be based on action tool categories for Plone 4 # (see PLIP #8804), but that (or an alternative) will have to happen # before CMF 2.4 when support for old-style actions is removed. return self._actions or () security.declarePublic('maySeeSomeConfiglets') def maySeeSomeConfiglets(self): groups = self.getGroups('site') all = [] for group in groups: all.extend(self.enumConfiglets(group=group['id'])) all = [item for item in all if item['visible']] return len(all) != 0 security.declarePublic('enumConfiglets') def enumConfiglets(self, group=None): portal = getToolByName(self, 'portal_url').getPortalObject() context = createExprContext(self, portal, self) res = [] for a in self.listActions(): verified = 0 for permission in a.permissions: if _checkPermission(permission, portal): verified = 1 if verified and a.category == group and a.testCondition(context) \ and a.visible: res.append(a.getAction(context)) # Translate the title for sorting if getattr(self, 'REQUEST', None) is not None: for a in res: title = a['title'] if not isinstance(title, Message): title = Message(title, domain='plone') a['title'] = translate(title, context=self.REQUEST) def _title(v): return v['title'] res.sort(key=_title) return res security.declareProtected(ManagePortal, 'unregisterConfiglet') def unregisterConfiglet(self, id): actids = [o.id for o in self.listActions()] selection = [actids.index(a) for a in actids if a == id] if not selection: return self.deleteActions(selection) security.declareProtected(ManagePortal, 'unregisterApplication') def unregisterApplication(self, appId): acts = list(self.listActions()) selection = [acts.index(a) for a in acts if a.appId == appId] if not selection: return self.deleteActions(selection) def _extractAction(self, properties, index): # Extract an ActionInformation from the funky form properties. id = str(properties.get('id_%d' % index, '')) name = str(properties.get('name_%d' % index, '')) action = str(properties.get('action_%d' % index, '')) condition = str(properties.get('condition_%d' % index, '')) category = str(properties.get('category_%d' % index, '')) visible = properties.get('visible_%d' % index, 0) permissions = properties.get('permission_%d' % index, ()) appId = properties.get('appId_%d' % index, '') description = properties.get('description_%d' % index, '') icon_expr = properties.get('icon_expr_%d' % index, '') if not name: raise ValueError('A name is required.') if action != '': action = Expression(text=action) if condition != '': condition = Expression(text=condition) if category == '': category = 'object' if not isinstance(visible, int): try: visible = int(visible) except ValueError: visible = 0 if isinstance(permissions, six.string_types): permissions = (permissions, ) return PloneConfiglet( id=id, title=name, action=action, condition=condition, permissions=permissions, category=category, visible=visible, appId=appId, description=description, icon_expr=icon_expr, ) security.declareProtected(ManagePortal, 'addAction') def addAction( self, id, name, action, condition='', permission='', category='Plone', visible=1, appId=None, icon_expr='', description='', REQUEST=None, ): # Add an action to our list. if not name: raise ValueError('A name is required.') a_expr = action and Expression(text=str(action)) or '' c_expr = condition and Expression(text=str(condition)) or '' if not isinstance(permission, tuple): permission = permission and (str(permission), ) or () new_actions = self._cloneActions() new_action = PloneConfiglet( id=str(id), title=name, action=a_expr, condition=c_expr, permissions=permission, category=str(category), visible=int(visible), appId=appId, description=description, icon_expr=icon_expr, ) new_actions.append(new_action) self._actions = tuple(new_actions) if REQUEST is not None: return self.manage_editActionsForm(REQUEST, manage_tabs_message='Added.') security.declareProtected(ManagePortal, 'registerConfiglet') registerConfiglet = addAction security.declareProtected(ManagePortal, 'manage_editActionsForm') def manage_editActionsForm(self, REQUEST, manage_tabs_message=None): """ Show the 'Actions' management tab. """ actions = [] for a in self.listActions(): a1 = {} a1['id'] = a.getId() a1['name'] = a.Title() p = a.getPermissions() if p: a1['permission'] = p[0] else: a1['permission'] = '' a1['category'] = a.getCategory() or 'object' a1['visible'] = a.getVisibility() a1['action'] = a.getActionExpression() a1['condition'] = a.getCondition() a1['appId'] = a.getAppId() a1['description'] = a.getDescription() a1['icon_expr'] = a.getIconExpression() actions.append(a1) # possible_permissions is in OFS.role.RoleManager. pp = self.possible_permissions() return self._actions_form( self, REQUEST, actions=actions, possible_permissions=pp, management_view='Actions', manage_tabs_message=manage_tabs_message, ) @property def site_url(self): """Return the absolute URL to the current site, which is likely not necessarily the portal root. Used by ``portlet_prefs`` to construct the URL to ``@@overview-controlpanel``. """ return getSite().absolute_url()
from OFS.FindSupport import FindSupport from OFS.interfaces import IFolder from OFS.Lockable import LockableItem from OFS.ObjectManager import ObjectManager from OFS.PropertyManager import PropertyManager from OFS.role import RoleManager from OFS.SimpleItem import Item from OFS.SimpleItem import PathReprProvider from zope.interface import implementer if bbb.HAS_ZSERVER: from webdav.Collection import Collection else: Collection = bbb.Collection manage_addFolderForm = DTMLFile('dtml/folderAdd', globals()) def manage_addFolder(self, id, title='', createPublic=0, createUserF=0, REQUEST=None): """Add a new Folder object with id *id*. """ ob = Folder(id) ob.title = title self._setObject(id, ob) ob = self._getOb(id) if REQUEST is not None:
from App.special_dtml import DTMLFile from OFS.Image import File from Products.ERP5Type import _dtmldir # Patch for displaying textearea in full window instead of # remembering a quantity of lines to display in a cookie manage_editForm = DTMLFile("fileEdit", _dtmldir) manage_editForm._setName('manage_editForm') File.manage_editForm = manage_editForm File.manage = manage_editForm File.manage_main = manage_editForm File.manage_editDocument = manage_editForm File.manage_editForm = manage_editForm
IISet([])), (self.id, )) else: return (difference(resultset, index), (self.id, )) return (IISet(), (self.id, )) def indexSize(self): """Return distinct values, as an optimization we always claim 2.""" return 2 def items(self): items = [] for v, k in self._unindex.items(): if isinstance(v, int): v = IISet((v, )) items.append((k, v)) return items manage_addBooleanIndexForm = DTMLFile('dtml/addBooleanIndex', globals()) def manage_addBooleanIndex(self, id, extra=None, REQUEST=None, RESPONSE=None, URL3=None): """Add a boolean index""" return self.manage_addIndex(id, 'BooleanIndex', extra=extra, \ REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3)
class FSDTMLMethod(RestrictedDTML, RoleManager, FSObject, HTML): """FSDTMLMethods act like DTML methods but are not directly modifiable from the management interface. """ meta_type = 'Filesystem DTML Method' _owner = None _proxy_roles = () _cache_namespace_keys = () _reading = 0 manage_options = ( {'label': 'Customize', 'action': 'manage_main'}, {'label': 'View', 'action': ''}, {'label': 'Proxy', 'action': 'manage_proxyForm'}) security = ClassSecurityInfo() security.declareObjectProtected(View) security.declareProtected(ViewManagementScreens, 'manage_main') manage_main = DTMLFile('custdtml', _dtmldir) def __init__(self, id, filepath, fullname=None, properties=None): FSObject.__init__(self, id, filepath, fullname, properties) # Normally called via HTML.__init__ but we don't need the rest that # happens there. self.initvars(None, {}) def _createZODBClone(self): """Create a ZODB (editable) equivalent of this object.""" return DTMLMethod(self.read(), __name__=self.getId()) def _readFile(self, reparse): """Read the data from the filesystem. """ file = open(self._filepath, 'r') # not 'rb', as this is a text file! try: data = file.read() finally: file.close() self.raw = data if reparse: self._reading = 1 # Avoid infinite recursion try: self.cook() finally: self._reading = 0 # Hook up chances to reload in debug mode @security.private def read_raw(self): if not self._reading: self._updateFromFS() return HTML.read_raw(self) #### The following is mainly taken from OFS/DTMLMethod.py ### index_html = None # Prevent accidental acquisition # Documents masquerade as functions: __code__ = DTMLMethod.__code__ default_content_type = 'text/html' def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw): """Render the document given a client object, REQUEST mapping, Response, and key word arguments.""" self._updateFromFS() kw['document_id'] = self.getId() kw['document_title'] = self.title if client is not None: if _checkConditionalGET(self, kw): return '' if not self._cache_namespace_keys: data = self.ZCacheable_get(default=_marker) if data is not _marker: # Return cached results. return data __traceback_info__ = self._filepath security = getSecurityManager() security.addContext(self) try: r = HTML.__call__(self, client, REQUEST, **kw) if client is None: # Called as subtemplate, so don't need error propagation! if RESPONSE is None: result = r else: result = decapitate(r, RESPONSE) if not self._cache_namespace_keys: self.ZCacheable_set(result) return result if not isinstance(r, six.string_types) or RESPONSE is None: if not self._cache_namespace_keys: self.ZCacheable_set(r) return r finally: security.removeContext(self) headers = RESPONSE.headers if not ('content-type' in headers or 'Content-Type' in headers): if 'content_type' in self.__dict__: c = self.content_type else: if six.PY2: c, _e = guess_content_type(self.getId(), r) else: c, _e = guess_content_type(self.getId(), r.encode()) RESPONSE.setHeader('Content-Type', c) if RESPONSE is not None: # caching policy manager hook _setCacheHeaders(self, {}) result = decapitate(r, RESPONSE) if not self._cache_namespace_keys: self.ZCacheable_set(result) return result def getCacheNamespaceKeys(self): ''' Returns the cacheNamespaceKeys. ''' return self._cache_namespace_keys def setCacheNamespaceKeys(self, keys, REQUEST=None): ''' Sets the list of names that should be looked up in the namespace to provide a cache key. ''' ks = [] for key in keys: key = str(key).strip() if key: ks.append(key) self._cache_namespace_keys = tuple(ks) if REQUEST is not None: return self.ZCacheable_manage(self, REQUEST) # Zope 2.3.x way: def validate(self, inst, parent, name, value, md=None): return getSecurityManager().validate(inst, parent, name, value) if bbb.HAS_ZSERVER: security.declareProtected(FTPAccess, 'manage_FTPget') manage_FTPget = get_unbound_function(DTMLMethod.manage_FTPget) security.declareProtected(ViewManagementScreens, 'PrincipiaSearchSource') PrincipiaSearchSource = get_unbound_function(DTMLMethod.PrincipiaSearchSource) security.declareProtected(ViewManagementScreens, 'document_src') document_src = get_unbound_function(DTMLMethod.document_src) security.declareProtected(ViewManagementScreens, 'manage_haveProxy') manage_haveProxy = get_unbound_function(DTMLMethod.manage_haveProxy)
class ActionProviderBase: """ Provide ActionTabs and management methods for ActionProviders """ implements(IActionProvider) security = ClassSecurityInfo() _actions = () _actions_form = DTMLFile('editToolsActions', _dtmldir) manage_options = ({ 'label': 'Actions', 'action': 'manage_editActionsForm', 'help': ('CMFCore', 'Actions.stx') }, ) # # ActionProvider interface # security.declarePrivate('listActions') def listActions(self, info=None, object=None): """ List all the actions defined by a provider. """ oldstyle_actions = self._actions or () if oldstyle_actions: warn( 'Old-style actions are deprecated and will be removed in CMF ' '2.4. Use Action and Action Category objects instead.', DeprecationWarning, stacklevel=2) return oldstyle_actions security.declarePrivate('getActionObject') def getActionObject(self, action): """Return the actions object or None if action doesn't exist. """ # separate cataegory and id from action sep = action.rfind('/') if sep == -1: raise ValueError('Actions must have the format <category>/<id>.') category, id = action[:sep], action[sep + 1:] # search for action and return first one found for ai in self.listActions(): try: if id == ai.getId() and category == ai.getCategory(): return ai except AttributeError: continue # no action found return None security.declarePublic('listActionInfos') def listActionInfos(self, action_chain=None, object=None, check_visibility=1, check_permissions=1, check_condition=1, max=-1): # List ActionInfo objects. # (method is without docstring to disable publishing) # ec = self._getExprContext(object) actions = self.listActions(object=object) actions = [ActionInfo(action, ec) for action in actions] if action_chain: filtered_actions = [] if isinstance(action_chain, basestring): action_chain = (action_chain, ) for action_ident in action_chain: sep = action_ident.rfind('/') category, id = action_ident[:sep], action_ident[sep + 1:] for ai in actions: if id == ai['id'] and category == ai['category']: filtered_actions.append(ai) actions = filtered_actions action_infos = [] for ai in actions: if check_visibility and not ai['visible']: continue if check_permissions and not ai['allowed']: continue if check_condition and not ai['available']: continue action_infos.append(ai) if max + 1 and len(action_infos) >= max: break return action_infos security.declarePublic('getActionInfo') def getActionInfo(self, action_chain, object=None, check_visibility=0, check_condition=0): """ Get an ActionInfo object specified by a chain of actions. """ action_infos = self.listActionInfos(action_chain, object, check_visibility=check_visibility, check_permissions=False, check_condition=check_condition) if not action_infos: if object is None: provider = self else: provider = object msg = 'Action "%s" not available for %s' % (action_chain, '/'.join( provider.getPhysicalPath())) raise ValueError(msg) for ai in action_infos: if ai['allowed']: return ai raise AccessControl_Unauthorized('You are not allowed to access any ' 'of the specified Actions.') # # ZMI methods # security.declareProtected(ManagePortal, 'manage_editActionsForm') def manage_editActionsForm(self, REQUEST, manage_tabs_message=None): """ Show the 'Actions' management tab. """ actions = [] for action in self.listActions(): # The Actions tab currently only shows old-style actions, # so we need to weed out everything else. if getattr(action, 'getMapping', None) is not None: actions.append(action.getMapping()) # possible_permissions is in AccessControl.Role.RoleManager. pp = self.possible_permissions() return self._actions_form(self, REQUEST, actions=actions, possible_permissions=pp, management_view='Actions', manage_tabs_message=manage_tabs_message) security.declareProtected(ManagePortal, 'addAction') def addAction(self, id, name, action, condition, permission, category, visible=1, icon_expr='', link_target='', REQUEST=None): """ Add an action to our list. """ if not name: raise ValueError('A name is required.') action = action and str(action) or '' condition = condition and str(condition) or '' if not isinstance(permission, tuple): permission = (str(permission), ) new_actions = self._cloneActions() new_action = ActionInformation(id=str(id), title=str(name), category=str(category), condition=condition, permissions=permission, visible=bool(visible), action=action, icon_expr=icon_expr, link_target=link_target) new_actions.append(new_action) self._actions = tuple(new_actions) if REQUEST is not None: return self.manage_editActionsForm(REQUEST, manage_tabs_message='Added.') security.declareProtected(ManagePortal, 'changeActions') def changeActions(self, properties=None, REQUEST=None): """ Update our list of actions. """ if properties is None: properties = REQUEST actions = [] for index in range(len(self._actions)): actions.append(self._extractAction(properties, index)) self._actions = tuple(actions) if REQUEST is not None: return self.manage_editActionsForm( REQUEST, manage_tabs_message='Actions changed.') security.declareProtected(ManagePortal, 'deleteActions') def deleteActions(self, selections=(), REQUEST=None): """ Delete actions indicated by indexes in 'selections'. """ sels = list(map(int, selections)) # Convert to a list of integers. old_actions = self._cloneActions() new_actions = [] for index in range(len(old_actions)): if index not in sels: new_actions.append(old_actions[index]) self._actions = tuple(new_actions) if REQUEST is not None: return self.manage_editActionsForm( REQUEST, manage_tabs_message=('Deleted %d action(s).' % len(sels))) security.declareProtected(ManagePortal, 'moveUpActions') def moveUpActions(self, selections=(), REQUEST=None): """ Move the specified actions up one slot in our list. """ sels = list(map(int, selections)) # Convert to a list of integers. sels.sort() new_actions = self._cloneActions() for idx in sels: idx2 = idx - 1 if idx2 < 0: # Wrap to the bottom. idx2 = len(new_actions) - 1 # Swap. a = new_actions[idx2] new_actions[idx2] = new_actions[idx] new_actions[idx] = a self._actions = tuple(new_actions) if REQUEST is not None: return self.manage_editActionsForm( REQUEST, manage_tabs_message=('Moved up %d action(s).' % len(sels))) security.declareProtected(ManagePortal, 'moveDownActions') def moveDownActions(self, selections=(), REQUEST=None): """ Move the specified actions down one slot in our list. """ sels = list(map(int, selections)) # Convert to a list of integers. sels.sort() sels.reverse() new_actions = self._cloneActions() for idx in sels: idx2 = idx + 1 if idx2 >= len(new_actions): # Wrap to the top. idx2 = 0 # Swap. a = new_actions[idx2] new_actions[idx2] = new_actions[idx] new_actions[idx] = a self._actions = tuple(new_actions) if REQUEST is not None: return self.manage_editActionsForm( REQUEST, manage_tabs_message=('Moved down %d action(s).' % len(sels))) # # Helper methods # security.declarePrivate('_cloneActions') def _cloneActions(self): """ Return a list of actions, cloned from our current list. """ return map(lambda x: x.clone(), list(self._actions)) security.declarePrivate('_extractAction') def _extractAction(self, properties, index): """ Extract an ActionInformation from the funky form properties. """ id = str(properties.get('id_%d' % index, '')) title = str(properties.get('name_%d' % index, '')) action = str(properties.get('action_%d' % index, '')) icon_expr = str(properties.get('icon_expr_%d' % index, '')) condition = str(properties.get('condition_%d' % index, '')) category = str(properties.get('category_%d' % index, '')) visible = bool(properties.get('visible_%d' % index, False)) permissions = properties.get('permission_%d' % index, ()) link_target = str(properties.get('link_target_%d' % index, '')) if not title: raise ValueError('A title is required.') if category == '': category = 'object' if isinstance(permissions, basestring): permissions = (permissions, ) return ActionInformation(id=id, title=title, action=action, condition=condition, permissions=permissions, category=category, visible=visible, icon_expr=icon_expr, link_target=link_target) def _getOAI(self, object): return getOAI(self, object) def _getExprContext(self, object): return getExprContext(self, object)
class DTMLMethod(PathReprProvider, RestrictedDTML, HTML, Implicit, RoleManager, Item_w__name__, Historical, Cacheable): """ DocumentTemplate.HTML objects that act as methods of their containers. """ meta_type = 'DTML Method' zmi_icon = 'far fa-file-alt' _proxy_roles = () index_html = None # Prevent accidental acquisition _cache_namespace_keys = () _locked_error_text = 'This DTML Method is locked.' security = ClassSecurityInfo() security.declareObjectProtected(View) __code__ = Code() __code__.co_varnames = 'self', 'REQUEST', 'RESPONSE' __code__.co_argcount = 3 __defaults__ = None manage_options = (( { 'label': 'Edit', 'action': 'manage_main', }, { 'label': 'View', 'action': '', }, { 'label': 'Proxy', 'action': 'manage_proxyForm', }, ) + Historical.manage_options + RoleManager.manage_options + Item_w__name__.manage_options + Cacheable.manage_options) # Careful in permission changes--used by DTMLDocument! security.declareProtected( change_dtml_methods, # NOQA: D001 'manage_historyCopy') security.declareProtected( change_dtml_methods, # NOQA: D001 'manage_beforeHistoryCopy') security.declareProtected( change_dtml_methods, # NOQA: D001 'manage_afterHistoryCopy') # More reasonable default for content-type for http HEAD requests. default_content_type = 'text/html' def errQuote(self, s): # Quoting is done when rendering the error in the template. return s @security.protected(View) def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw): """Render using the given client object o If client is not passed, we are being called as a sub-template: don't do any error propagation. o If supplied, use the REQUEST mapping, Response, and key word arguments. """ if not self._cache_namespace_keys: data = self.ZCacheable_get(default=_marker) if data is not _marker: if IStreamIterator.isImplementedBy(data) and \ RESPONSE is not None: # This is a stream iterator and we need to set some # headers now before giving it to medusa headers_get = RESPONSE.headers.get if headers_get('content-length', None) is None: RESPONSE.setHeader('content-length', len(data)) if headers_get('content-type', None) is None and \ headers_get('Content-type', None) is None: ct = (self.__dict__.get('content_type') or self.default_content_type) RESPONSE.setHeader('content-type', ct) # Return cached results. return data __traceback_supplement__ = (PathTracebackSupplement, self) kw['document_id'] = self.getId() kw['document_title'] = self.title security = getSecurityManager() security.addContext(self) if 'validate' in self.__dict__: first_time_through = 0 else: self.__dict__['validate'] = security.DTMLValidate first_time_through = 1 try: if client is None: # Called as subtemplate, so don't need error propagation! r = HTML.__call__(self, client, REQUEST, **kw) if RESPONSE is None: result = r else: result = decapitate(r, RESPONSE) if not self._cache_namespace_keys: self.ZCacheable_set(result) return result r = HTML.__call__(self, client, REQUEST, **kw) if RESPONSE is None or not isinstance(r, str): if not self._cache_namespace_keys: self.ZCacheable_set(r) return r finally: security.removeContext(self) if first_time_through: del self.__dict__['validate'] have_key = RESPONSE.headers.__contains__ if not (have_key('content-type') or have_key('Content-Type')): if 'content_type' in self.__dict__: c = self.content_type else: encoding = getattr(self, 'encoding', default_encoding) c, e = guess_content_type(self.getId(), r.encode(encoding)) RESPONSE.setHeader('Content-Type', c) result = decapitate(r, RESPONSE) if not self._cache_namespace_keys: self.ZCacheable_set(result) return result def validate(self, inst, parent, name, value, md=None): return getSecurityManager().validate(inst, parent, name, value) def ZDocumentTemplate_beforeRender(self, md, default): # Tries to get a cached value. if self._cache_namespace_keys: # Use the specified keys from the namespace to identify a # cache entry. kw = {} for key in self._cache_namespace_keys: try: val = md[key] except Exception: val = None kw[key] = val return self.ZCacheable_get(keywords=kw, default=default) return default def ZDocumentTemplate_afterRender(self, md, result): # Tries to set a cache value. if self._cache_namespace_keys: kw = {} for key in self._cache_namespace_keys: try: val = md[key] except Exception: val = None kw[key] = val self.ZCacheable_set(result, keywords=kw) security.declareProtected(change_dtml_methods, 'ZCacheable_configHTML') # NOQA: D001,E501 ZCacheable_configHTML = DTMLFile('dtml/cacheNamespaceKeys', globals()) @security.protected(change_dtml_methods) def getCacheNamespaceKeys(self): # Return the cacheNamespaceKeys. return self._cache_namespace_keys @security.protected(change_dtml_methods) def setCacheNamespaceKeys(self, keys, REQUEST=None): # Set the list of names looked up to provide a cache key. ks = [] for key in keys: key = str(key).strip() if key: ks.append(key) self._cache_namespace_keys = tuple(ks) if REQUEST is not None: return self.ZCacheable_manage(self, REQUEST) @security.protected(View) def get_size(self): return len(self.raw) # deprecated; use get_size! getSize = get_size security.declareProtected(change_dtml_methods, 'manage') # NOQA: D001 security.declareProtected(change_dtml_methods, 'manage_editForm') # NOQA: D001,E501 manage_editForm = DTMLFile('dtml/documentEdit', globals()) manage_editForm._setName('manage_editForm') # deprecated! manage_uploadForm = manage_editForm security.declareProtected(change_dtml_methods, 'manage_main') # NOQA: D001 manage = manage_main = manage_editDocument = manage_editForm security.declareProtected(change_proxy_roles, 'manage_proxyForm') # NOQA: D001,E501 manage_proxyForm = DTMLFile('dtml/documentProxy', globals()) @security.protected(change_dtml_methods) def manage_edit(self, data, title, SUBMIT='Change', REQUEST=None): """ Replace contents with 'data', title with 'title'. """ self._validateProxy(REQUEST) if self.wl_isLocked(): raise ResourceLockedError(self._locked_error_text) self.title = str(title) if isinstance(data, TaintedString): data = data.quoted() if hasattr(data, 'read'): data = data.read() try: self.munge(data) except ParseError as e: if REQUEST: return self.manage_main(self, REQUEST, manage_tabs_message=e, manage_tabs_type='warning') else: raise self.ZCacheable_invalidate() if REQUEST: message = "Saved changes." return self.manage_main(self, REQUEST, manage_tabs_message=message) @security.protected(change_dtml_methods) def manage_upload(self, file='', REQUEST=None): """ Replace the contents of the document with the text in 'file'. Store `file` as a native `str`. """ self._validateProxy(REQUEST) if self.wl_isLocked(): if REQUEST is not None: return self.manage_main( self, REQUEST, manage_tabs_message=self._locked_error_text, manage_tabs_type='warning') raise ResourceLockedError(self._locked_error_text) if REQUEST is not None and not file: return self.manage_main(self, REQUEST, manage_tabs_message='No file specified', manage_tabs_type='warning') self.munge(safe_file_data(file)) self.ZCacheable_invalidate() if REQUEST is not None: message = "Content uploaded." return self.manage_main(self, REQUEST, manage_tabs_message=message) def manage_haveProxy(self, r): return r in self._proxy_roles def _validateProxy(self, request, roles=None): if roles is None: roles = self._proxy_roles if not roles: return user = u = getSecurityManager().getUser() user = user.allowed for r in roles: if r and not user(self, (r, )): user = None break if user is not None: return raise Forbidden( 'You are not authorized to change <em>%s</em> because you ' 'do not have proxy roles.\n<!--%s, %s-->' % (self.__name__, u, roles)) @security.protected(change_proxy_roles) @requestmethod('POST') def manage_proxy(self, roles=(), REQUEST=None): "Change Proxy Roles" self._validateProxy(REQUEST, roles) self._validateProxy(REQUEST) self._proxy_roles = tuple(roles) if REQUEST: message = "Saved changes." return self.manage_proxyForm(self, REQUEST, manage_tabs_message=message) @security.protected(view_management_screens) def PrincipiaSearchSource(self): # Support for searching - the document's contents are searched. return self.read() @security.protected(view_management_screens) def document_src(self, REQUEST=None, RESPONSE=None): # Return unprocessed document source. if RESPONSE is not None: RESPONSE.setHeader('Content-Type', 'text/plain') return self.read() def manage_historyCompare(self, rev1, rev2, REQUEST, historyComparisonResults=''): return DTMLMethod.inheritedAttribute('manage_historyCompare')( self, rev1, rev2, REQUEST, historyComparisonResults=html_diff(rev1.read(), rev2.read()))
InitializeClass(ZCTextIndex) def manage_addZCTextIndex(self, id, extra=None, REQUEST=None, RESPONSE=None): """Add a text index""" if REQUEST is None: URL3 = None else: URL3 = REQUEST.URL3 return self.manage_addIndex(id, 'ZCTextIndex', extra, REQUEST, RESPONSE, URL3) manage_addZCTextIndexForm = DTMLFile('dtml/addZCTextIndex', globals()) manage_addLexiconForm = DTMLFile('dtml/addLexicon', globals()) def manage_addLexicon(self, id, title='', elements=[], REQUEST=None): """Add ZCTextIndex Lexicon""" pipeline = [] for el_record in elements: if not hasattr(el_record, 'name'): continue # Skip over records that only specify element group element = element_factory.instantiate(el_record.group, el_record.name) if element is not None: if el_record.group == 'Word Splitter': # I don't like hardcoding this, but its a simple solution
class BrowserIdManager(Item, Persistent, Implicit, RoleManager, Owned, Tabs): """ browser id management class """ implements(IBrowserIdManager) meta_type = 'Browser Id Manager' security = ClassSecurityInfo() security.declareObjectPublic() ok = {'meta_type': 1, 'id': 1, 'title': 1, 'icon': 1, 'title_or_id': 1} security.setDefaultAccess(ok) security.setPermissionDefault(MGMT_SCREEN_PERM, ['Manager']) security.setPermissionDefault(ACCESS_CONTENTS_PERM, ['Manager', 'Anonymous']) security.setPermissionDefault(CHANGE_IDMGR_PERM, ['Manager']) # BBB auto_url_encoding = 0 cookie_http_only = 0 def __init__(self, id, title='', idname='_ZopeId', location=('cookies', 'form'), cookiepath=('/'), cookiedomain='', cookielifedays=0, cookiesecure=0, cookiehttponly=0, auto_url_encoding=0): self.id = str(id) self.title = str(title) self.setBrowserIdName(idname) self.setBrowserIdNamespaces(location) self.setCookiePath(cookiepath) self.setCookieDomain(cookiedomain) self.setCookieLifeDays(cookielifedays) self.setCookieSecure(cookiesecure) self.setCookieHTTPOnly(cookiehttponly) self.setAutoUrlEncoding(auto_url_encoding) # IBrowserIdManager security.declareProtected(ACCESS_CONTENTS_PERM, 'hasBrowserId') def hasBrowserId(self): """ See IBrowserIdManager. """ try: return self.getBrowserId(create=0) is not None except BrowserIdManagerErr: return False security.declareProtected(ACCESS_CONTENTS_PERM, 'getBrowserId') def getBrowserId(self, create=1): """ See IBrowserIdManager. """ REQUEST = self.REQUEST # let's see if bid has already been attached to request bid = getattr(REQUEST, 'browser_id_', None) if bid is not None: # it's already set in this request so we can just return it # if it's well-formed if not isAWellFormedBrowserId(bid): # somebody screwed with the REQUEST instance during # this request. raise BrowserIdManagerErr('Ill-formed browserid in ' 'REQUEST.browser_id_: %s' % escape(bid)) return bid # fall through & ck form/cookie namespaces if bid is not in request. tk = self.browserid_name ns = self.browserid_namespaces for name in ns: if name == 'url': continue # browser ids in url are checked by Traverser class current_ns = getattr(REQUEST, name, None) if current_ns is None: continue bid = current_ns.get(tk, None) if bid is not None: # hey, we got a browser id! if isAWellFormedBrowserId(bid): # bid is not "plain old broken" REQUEST.browser_id_ = bid REQUEST.browser_id_ns_ = name return bid # fall through if bid is invalid or not in namespaces if create: # create a brand new bid bid = getNewBrowserId() if 'cookies' in ns: self._setCookie(bid, REQUEST) REQUEST.browser_id_ = bid REQUEST.browser_id_ns_ = None return bid # implies a return of None if: # (not create=1) and (invalid or ((not in req) and (not in ns))) security.declareProtected(ACCESS_CONTENTS_PERM, 'getBrowserIdName') def getBrowserIdName(self): """ See IBrowserIdManager. """ return self.browserid_name security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdNew') def isBrowserIdNew(self): """ See IBrowserIdManager. """ if not self.getBrowserId(create=False): raise BrowserIdManagerErr('There is no current browser id.') # ns will be None if new return getattr(self.REQUEST, 'browser_id_ns_', None) is None security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdFromCookie') def isBrowserIdFromCookie(self): """ See IBrowserIdManager. """ if not self.getBrowserId(create=False): raise BrowserIdManagerErr('There is no current browser id.') if getattr(self.REQUEST, 'browser_id_ns_') == 'cookies': return 1 security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdFromForm') def isBrowserIdFromForm(self): """ See IBrowserIdManager. """ if not self.getBrowserId(create=False): raise BrowserIdManagerErr('There is no current browser id.') if getattr(self.REQUEST, 'browser_id_ns_') == 'form': return 1 security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdFromUrl') def isBrowserIdFromUrl(self): """ See IBrowserIdManager. """ if not self.getBrowserId(create=False): raise BrowserIdManagerErr('There is no current browser id.') if getattr(self.REQUEST, 'browser_id_ns_') == 'url': return 1 security.declareProtected(ACCESS_CONTENTS_PERM, 'flushBrowserIdCookie') def flushBrowserIdCookie(self): """ See IBrowserIdManager. """ if 'cookies' not in self.browserid_namespaces: raise BrowserIdManagerErr('Cookies are not now being used as a ' 'browser id namespace, thus the ' 'browserid cookie cannot be flushed.') self._setCookie('deleted', self.REQUEST, remove=1) security.declareProtected(ACCESS_CONTENTS_PERM, 'setBrowserIdCookieByForce') def setBrowserIdCookieByForce(self, bid): """ See IBrowserIdManager. """ if 'cookies' not in self.browserid_namespaces: raise BrowserIdManagerErr('Cookies are not now being used as a ' 'browser id namespace, thus the ' 'browserid cookie cannot be forced.') self._setCookie(bid, self.REQUEST) security.declareProtected(ACCESS_CONTENTS_PERM, 'getHiddenFormField') def getHiddenFormField(self): """ See IBrowserIdManager. """ s = '<input type="hidden" name="%s" value="%s" />' return s % (self.getBrowserIdName(), self.getBrowserId()) security.declareProtected(ACCESS_CONTENTS_PERM, 'encodeUrl') def encodeUrl(self, url, style='querystring', create=1): # See IBrowserIdManager bid = self.getBrowserId(create) if bid is None: raise BrowserIdManagerErr('There is no current browser id.') name = self.getBrowserIdName() if style == 'querystring': # encode bid in querystring if '?' in url: return '%s&%s=%s' % (url, name, bid) else: return '%s?%s=%s' % (url, name, bid) else: # encode bid as first two URL path segments proto, host, path, params, query, frag = urlparse(url) path = '/%s/%s%s' % (name, bid, path) return urlunparse((proto, host, path, params, query, frag)) # Non-IBrowserIdManager accessors / mutators. security.declareProtected(CHANGE_IDMGR_PERM, 'setBrowserIdName') def setBrowserIdName(self, k): """ Set browser id name string o Enforce "valid" values. """ if not (type(k) is type('') and k and not badidnamecharsin(k)): raise BrowserIdManagerErr('Bad id name string %s' % escape(repr(k))) self.browserid_name = k security.declareProtected(CHANGE_IDMGR_PERM, 'setBrowserIdNamespaces') def setBrowserIdNamespaces(self, ns): """ accepts list of allowable browser id namespaces """ for name in ns: if name not in ALLOWED_BID_NAMESPACES: raise BrowserIdManagerErr('Bad browser id namespace %s' % repr(name)) self.browserid_namespaces = tuple(ns) security.declareProtected(ACCESS_CONTENTS_PERM, 'getBrowserIdNamespaces') def getBrowserIdNamespaces(self): """ """ return self.browserid_namespaces security.declareProtected(CHANGE_IDMGR_PERM, 'setCookiePath') def setCookiePath(self, path=''): """ sets cookie 'path' element for id cookie """ if not (type(path) is type('') and not badcookiecharsin(path)): raise BrowserIdManagerErr('Bad cookie path %s' % escape(repr(path))) self.cookie_path = path security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookiePath') def getCookiePath(self): """ """ return self.cookie_path security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieLifeDays') def setCookieLifeDays(self, days): """ offset for id cookie 'expires' element """ if type(days) not in (type(1), type(1.0)): raise BrowserIdManagerErr('Bad cookie lifetime in days %s ' '(requires integer value)' % escape(repr(days))) self.cookie_life_days = int(days) security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookieLifeDays') def getCookieLifeDays(self): """ """ return self.cookie_life_days security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieDomain') def setCookieDomain(self, domain): """ sets cookie 'domain' element for id cookie """ if type(domain) is not type(''): raise BrowserIdManagerErr('Cookie domain must be string: %s' % escape(repr(domain))) if not domain: self.cookie_domain = '' return if not twodotsin(domain): raise BrowserIdManagerErr( 'Cookie domain must contain at least two dots ' '(e.g. ".zope.org" or "www.zope.org") or it must ' 'be left blank. : ' '%s' % escape( ` domain `)) if badcookiecharsin(domain): raise BrowserIdManagerErr('Bad characters in cookie domain %s' % escape( ` domain `)) self.cookie_domain = domain security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookieDomain') def getCookieDomain(self): """ """ return self.cookie_domain security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieHTTPOnly') def setCookieHTTPOnly(self, http_only): """ sets cookie 'HTTPOnly' on or off """ self.cookie_http_only = bool(http_only) security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookieHTTPOnly') def getCookieHTTPOnly(self): """ retrieve the 'HTTPOnly' flag """ return self.cookie_http_only security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieSecure') def setCookieSecure(self, secure): """ sets cookie 'secure' element for id cookie """ self.cookie_secure = not not secure security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookieSecure') def getCookieSecure(self): """ """ return self.cookie_secure security.declareProtected(CHANGE_IDMGR_PERM, 'setAutoUrlEncoding') def setAutoUrlEncoding(self, auto_url_encoding): """ sets 'auto url encoding' on or off """ self.auto_url_encoding = not not auto_url_encoding security.declareProtected(ACCESS_CONTENTS_PERM, 'getAutoUrlEncoding') def getAutoUrlEncoding(self): """ """ return self.auto_url_encoding security.declareProtected(ACCESS_CONTENTS_PERM, 'isUrlInBidNamespaces') def isUrlInBidNamespaces(self): """ Returns true if 'url' is in the browser id namespaces for this browser id """ return 'url' in self.browserid_namespaces def _setCookie(self, bid, REQUEST, remove=0, now=time.time, strftime=time.strftime, gmtime=time.gmtime): """ """ expires = None if remove: expires = "Sun, 10-May-1971 11:59:00 GMT" elif self.cookie_life_days: expires = now() + self.cookie_life_days * 86400 # Wdy, DD-Mon-YYYY HH:MM:SS GMT expires = strftime('%a %d-%b-%Y %H:%M:%S GMT', gmtime(expires)) # cookie attributes managed by BrowserIdManager d = { 'domain': self.cookie_domain, 'path': self.cookie_path, 'secure': self.cookie_secure, 'http_only': self.cookie_http_only, 'expires': expires } if self.cookie_secure: URL1 = REQUEST.get('URL1', None) if URL1 is None: return # should we raise an exception? if string.split(URL1, ':')[0] != 'https': return # should we raise an exception? cookies = REQUEST.RESPONSE.cookies cookie = cookies[self.browserid_name] = {} for k, v in d.items(): if v: cookie[k] = v #only stuff things with true values cookie['value'] = bid def _setId(self, id): if id != self.id: raise ValueError('Cannot rename a browser id manager') # Jukes for handling URI-munged browser IDS def hasTraversalHook(self, parent): name = TRAVERSAL_APPHANDLE return not not queryBeforeTraverse(parent, name) def updateTraversalData(self): if 'url' in self.browserid_namespaces: self.registerTraversalHook() else: self.unregisterTraversalHook() def unregisterTraversalHook(self): parent = aq_parent(aq_inner(self)) name = TRAVERSAL_APPHANDLE if self.hasTraversalHook(parent): unregisterBeforeTraverse(parent, name) def registerTraversalHook(self): parent = aq_parent(aq_inner(self)) if not self.hasTraversalHook(parent): hook = BrowserIdManagerTraverser() name = TRAVERSAL_APPHANDLE priority = 40 # "higher" priority than session data traverser registerBeforeTraverse(parent, hook, name, priority) # ZMI manage_options = ( { 'label': 'Settings', 'action': 'manage_browseridmgr' }, { 'label': 'Security', 'action': 'manage_access' }, { 'label': 'Ownership', 'action': 'manage_owner' }, ) def manage_afterAdd(self, item, container): """ Maybe add our traversal hook """ self.updateTraversalData() def manage_beforeDelete(self, item, container): """ Remove our traversal hook if it exists """ self.unregisterTraversalHook() security.declareProtected(MGMT_SCREEN_PERM, 'manage_browseridmgr') manage_browseridmgr = DTMLFile('dtml/manageIdManager', globals()) security.declareProtected(CHANGE_IDMGR_PERM, 'manage_changeBrowserIdManager') def manage_changeBrowserIdManager(self, title='', idname='_ZopeId', location=('cookies', 'form'), cookiepath='/', cookiedomain='', cookielifedays=0, cookiesecure=0, cookiehttponly=0, auto_url_encoding=0, REQUEST=None): """ """ self.title = str(title) self.setBrowserIdName(idname) self.setCookiePath(cookiepath) self.setCookieDomain(cookiedomain) self.setCookieLifeDays(cookielifedays) self.setCookieSecure(cookiesecure) self.setCookieHTTPOnly(cookiehttponly) self.setBrowserIdNamespaces(location) self.setAutoUrlEncoding(auto_url_encoding) self.updateTraversalData() if REQUEST is not None: msg = '/manage_browseridmgr?manage_tabs_message=Changes saved' REQUEST.RESPONSE.redirect(self.absolute_url() + msg)
class VirtualHostMonster(Persistent, Item, Implicit): """Provide a simple drop-in solution for virtual hosting. """ meta_type = 'Virtual Host Monster' priority = 25 id = 'VHM' title = '' lines = () have_map = 0 security = ClassSecurityInfo() manage_options = ({ 'label': 'About', 'action': 'manage_main' }, { 'label': 'Mappings', 'action': 'manage_edit' }) security.declareProtected(View, 'manage_main') manage_main = DTMLFile('www/VirtualHostMonster', globals(), __name__='manage_main') security.declareProtected('Add Site Roots', 'manage_edit') manage_edit = DTMLFile('www/manage_edit', globals()) security.declareProtected('Add Site Roots', 'set_map') def set_map(self, map_text, RESPONSE=None): "Set domain to path mappings." lines = map_text.split('\n') self.fixed_map = fixed_map = {} self.sub_map = sub_map = {} new_lines = [] for line in lines: line = line.split('#!')[0].strip() if not line: continue try: # Drop the protocol, if any line = line.split('://')[-1] try: host, path = [x.strip() for x in line.split('/', 1)] except: raise ValueError( 'Line needs a slash between host and path: %s' % line) pp = filter(None, path.split('/')) if pp: obpath = pp[:] if obpath[0] == 'VirtualHostBase': obpath = obpath[3:] if 'VirtualHostRoot' in obpath: i1 = obpath.index('VirtualHostRoot') i2 = i1 + 1 while i2 < len(obpath) and obpath[i2][:4] == '_vh_': i2 = i2 + 1 del obpath[i1:i2] if obpath: try: ob = self.unrestrictedTraverse(obpath) except: raise ValueError, ('Path not found: %s' % obpath) if not getattr(ob.aq_base, 'isAnObjectManager', 0): raise ValueError, ( 'Path must lead to an Object Manager: %s' % obpath) if 'VirtualHostRoot' not in pp: pp.append('/') pp.reverse() try: int(host.replace('.', '')) raise ValueError, ('IP addresses are not mappable: %s' % host) except ValueError: pass if host[:2] == '*.': host_map = sub_map host = host[2:] else: host_map = fixed_map hostname, port = (host.split(':', 1) + [None])[:2] if hostname not in host_map: host_map[hostname] = {} host_map[hostname][port] = pp except 'LineError', msg: line = '%s #! %s' % (line, msg) new_lines.append(line) self.lines = tuple(new_lines) self.have_map = not not (fixed_map or sub_map) # booleanize if RESPONSE is not None: RESPONSE.redirect( 'manage_edit?manage_tabs_message=Changes%20Saved.')
class MembershipTool(BaseTool): """ Implement 'portal_membership' interface using "stock" policies. """ implements(IMembershipTool) meta_type = 'Default Membership Tool' membersfolder_id = 'Members' security = ClassSecurityInfo() # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainMembershipTool', _dtmldir) security.declareProtected(ManagePortal, 'manage_mapRoles') manage_mapRoles = DTMLFile('membershipRolemapping', _dtmldir) security.declareProtected(ManagePortal, 'manage_setMembersFolderById') def manage_setMembersFolderById(self, id='', REQUEST=None): """ ZMI method to set the members folder object by its id. """ self.setMembersFolderById(id) if REQUEST is not None: REQUEST['RESPONSE'].redirect( self.absolute_url() + '/manage_mapRoles' + '?manage_tabs_message=Members+folder+changed.') # # 'portal_membership' interface methods # security.declareProtected(ListPortalMembers, 'getRoster') def getRoster(self): """ Return a list of mappings for 'listed' members. If Manager, return a list of all usernames. The mapping contains the id and listed variables. """ isUserManager = _checkPermission(ManageUsers, self) roster = [] for member in self.listMembers(): listed = member.getProperty('listed') if isUserManager or listed: roster.append({'id': member.getId(), 'listed': listed}) return roster security.declareProtected(ManagePortal, 'setMembersFolderById') def setMembersFolderById(self, id=''): """ Set the members folder object by its id. """ self.membersfolder_id = id.strip() security.declarePublic('getMembersFolder') def getMembersFolder(self): """ Get the members folder object. """ parent = aq_parent(aq_inner(self)) try: members_folder = parent.restrictedTraverse(self.membersfolder_id) except (AttributeError, KeyError): return None request_container = RequestContainer(REQUEST=getRequest()) return members_folder.__of__(request_container) security.declarePublic('createMemberArea') def createMemberArea(self, member_id=''): """ Create a member area for 'member_id' or authenticated user. """ if not self.getMemberareaCreationFlag(): return None members = self.getMembersFolder() if members is None: return None if self.isAnonymousUser(): return None if member_id: if not self.isMemberAccessAllowed(member_id): return None member = self.getMemberById(member_id) if member is None: return None else: member = self.getAuthenticatedMember() member_id = member.getId() if hasattr(aq_base(members), member_id): return None # Note: We can't use invokeFactory() to add folder and content because # the user might not have the necessary permissions. # Create Member's home folder. members.manage_addPortalFolder(id=member_id, title="%s's Home" % member_id) f = members._getOb(member_id) # Grant Ownership and Owner role to Member f.changeOwnership(member) f.__ac_local_roles__ = None f.manage_setLocalRoles(member_id, ['Owner']) # Create Member's initial content. if hasattr(self, 'createMemberContent'): self.createMemberContent(member=member, member_id=member_id, member_folder=f) else: addDocument(f, 'index_html', member_id + "'s Home", member_id + "'s front page", "structured-text", (DEFAULT_MEMBER_CONTENT % member_id)) # Grant Ownership and Owner role to Member f.index_html.changeOwnership(member) f.index_html.__ac_local_roles__ = None f.index_html.manage_setLocalRoles(member_id, ['Owner']) f.index_html._setPortalTypeName('Document') f.index_html.reindexObject() f.index_html.notifyWorkflowCreated() return f security.declarePublic('createMemberarea') createMemberarea = createMemberArea def getHomeFolder(self, id=None, verifyPermission=0): """ Return a member's home folder object, or None. """ if id is None: member = self.getAuthenticatedMember() if not hasattr(member, 'getMemberId'): return None id = member.getMemberId() members = self.getMembersFolder() if members: try: folder = members._getOb(id) if verifyPermission and not _checkPermission(View, folder): # Don't return the folder if the user can't get to it. return None return folder except (AttributeError, TypeError, KeyError): pass return None def getHomeUrl(self, id=None, verifyPermission=0): """ Return the URL to a member's home folder, or None. """ home = self.getHomeFolder(id, verifyPermission) if home is not None: return home.absolute_url() else: return None
class DTMLMethod( RestrictedDTML, HTML, Implicit, RoleManager, ElementWithTitle, Item_w__name__, Historical, Cacheable, ): """ DocumentTemplate.HTML objects that act as methods of their containers. """ meta_type = 'DTML Method' _proxy_roles = () index_html = None # Prevent accidental acquisition _cache_namespace_keys = () security = ClassSecurityInfo() security.declareObjectProtected(View) # Documents masquerade as functions: class func_code: pass func_code = func_code() func_code.co_varnames = 'self', 'REQUEST', 'RESPONSE' func_code.co_argcount = 3 manage_options = (( { 'label': 'Edit', 'action': 'manage_main' }, { 'label': 'View', 'action': '' }, { 'label': 'Proxy', 'action': 'manage_proxyForm' }, ) + Historical.manage_options + RoleManager.manage_options + Item_w__name__.manage_options + Cacheable.manage_options) # Careful in permission changes--used by DTMLDocument! security.declareProtected(change_dtml_methods, 'manage_historyCopy') security.declareProtected(change_dtml_methods, 'manage_beforeHistoryCopy') security.declareProtected(change_dtml_methods, 'manage_afterHistoryCopy') # More reasonable default for content-type for http HEAD requests. default_content_type = 'text/html' security.declareProtected(View, '__call__') def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw): """Render using the given client object o If client is not passed, we are being called as a sub-template: don't do any error propagation. o If supplied, use the REQUEST mapping, Response, and key word arguments. """ if not self._cache_namespace_keys: data = self.ZCacheable_get(default=_marker) if data is not _marker: if (IStreamIterator.isImplementedBy(data) and RESPONSE is not None): # This is a stream iterator and we need to set some # headers now before giving it to medusa if RESPONSE.headers.get('content-length', None) is None: RESPONSE.setHeader('content-length', len(data)) if (RESPONSE.headers.get('content-type', None) is None and RESPONSE.headers.get('Content-type', None) is None): ct = (self.__dict__.get('content_type') or self.default_content_type) RESPONSE.setHeader('content-type', ct) # Return cached results. return data __traceback_supplement__ = (PathTracebackSupplement, self) kw['document_id'] = self.getId() kw['document_title'] = self.title security = getSecurityManager() security.addContext(self) if self.__dict__.has_key('validate'): first_time_through = 0 else: self.__dict__['validate'] = security.DTMLValidate first_time_through = 1 try: if client is None: # Called as subtemplate, so don't need error propagation! r = apply(HTML.__call__, (self, client, REQUEST), kw) if RESPONSE is None: result = r else: result = decapitate(r, RESPONSE) if not self._cache_namespace_keys: self.ZCacheable_set(result) return result r = apply(HTML.__call__, (self, client, REQUEST), kw) if type(r) is not str or RESPONSE is None: if not self._cache_namespace_keys: self.ZCacheable_set(r) return r finally: security.removeContext(self) if first_time_through: del self.__dict__['validate'] have_key = RESPONSE.headers.has_key if not (have_key('content-type') or have_key('Content-Type')): if self.__dict__.has_key('content_type'): c = self.content_type else: c, e = guess_content_type(self.getId(), r) RESPONSE.setHeader('Content-Type', c) result = decapitate(r, RESPONSE) if not self._cache_namespace_keys: self.ZCacheable_set(result) return result def validate(self, inst, parent, name, value, md=None): return getSecurityManager().validate(inst, parent, name, value) def ZDocumentTemplate_beforeRender(self, md, default): # Tries to get a cached value. if self._cache_namespace_keys: # Use the specified keys from the namespace to identify a # cache entry. kw = {} for key in self._cache_namespace_keys: try: val = md[key] except: val = None kw[key] = val return self.ZCacheable_get(keywords=kw, default=default) return default def ZDocumentTemplate_afterRender(self, md, result): # Tries to set a cache value. if self._cache_namespace_keys: kw = {} for key in self._cache_namespace_keys: try: val = md[key] except: val = None kw[key] = val self.ZCacheable_set(result, keywords=kw) security.declareProtected(change_dtml_methods, 'ZCacheable_configHTML') ZCacheable_configHTML = DTMLFile('dtml/cacheNamespaceKeys', globals()) security.declareProtected(change_dtml_methods, 'getCacheNamespaceKeys') def getCacheNamespaceKeys(self): # Return the cacheNamespaceKeys. return self._cache_namespace_keys security.declareProtected(change_dtml_methods, 'setCacheNamespaceKeys') def setCacheNamespaceKeys(self, keys, REQUEST=None): # Set the list of names looked up to provide a cache key. ks = [] for key in keys: key = str(key).strip() if key: ks.append(key) self._cache_namespace_keys = tuple(ks) if REQUEST is not None: return self.ZCacheable_manage(self, REQUEST) security.declareProtected(View, 'get_size') def get_size(self): return len(self.raw) # deprecated; use get_size! getSize = get_size security.declareProtected(change_dtml_methods, 'manage') security.declareProtected(change_dtml_methods, 'manage_editForm') manage_editForm = DTMLFile('dtml/documentEdit', globals()) manage_editForm._setName('manage_editForm') # deprecated! manage_uploadForm = manage_editForm security.declareProtected(change_dtml_methods, 'manage_main') manage = manage_main = manage_editDocument = manage_editForm security.declareProtected(change_proxy_roles, 'manage_proxyForm') manage_proxyForm = DTMLFile('dtml/documentProxy', globals()) _size_changes = { 'Bigger': (5, 5), 'Smaller': (-5, -5), 'Narrower': (0, -5), 'Wider': (0, 5), 'Taller': (5, 0), 'Shorter': (-5, 0), } def _er(self, data, title, SUBMIT, dtpref_cols, dtpref_rows, REQUEST): dr, dc = self._size_changes[SUBMIT] rows = str(max(1, int(dtpref_rows) + dr)) cols = str(dtpref_cols) if cols.endswith('%'): cols = str(min(100, max(25, int(cols[:-1]) + dc))) + '%' else: cols = str(max(35, int(cols) + dc)) e = (DateTime("GMT") + 365).rfc822() setCookie = REQUEST["RESPONSE"].setCookie setCookie("dtpref_rows", rows, path='/', expires=e) setCookie("dtpref_cols", cols, path='/', expires=e) REQUEST.other.update({"dtpref_cols": cols, "dtpref_rows": rows}) return self.manage_main(self, REQUEST, title=title, __str__=self.quotedHTML(data)) security.declareProtected(change_dtml_methods, 'manage_edit') def manage_edit(self, data, title, SUBMIT='Change', dtpref_cols='100%', dtpref_rows='20', REQUEST=None): """ Replace contents with 'data', title with 'title'. The SUBMIT parameter is also used to change the size of the editing area on the default Document edit screen. If the value is "Smaller", the rows and columns decrease by 5. If the value is "Bigger", the rows and columns increase by 5. If any other or no value is supplied, the data gets checked for DTML errors and is saved. """ self._validateProxy(REQUEST) if self._size_changes.has_key(SUBMIT): return self._er(data, title, SUBMIT, dtpref_cols, dtpref_rows, REQUEST) if self.wl_isLocked(): raise ResourceLockedError('This item is locked via WebDAV') self.title = str(title) if isinstance(data, TaintedString): data = data.quoted() if not isinstance(data, basestring): data = data.read() self.munge(data) self.ZCacheable_invalidate() if REQUEST: message = "Saved changes." return self.manage_main(self, REQUEST, manage_tabs_message=message) security.declareProtected(change_dtml_methods, 'manage_upload') def manage_upload(self, file='', REQUEST=None): """ Replace the contents of the document with the text in 'file'. """ self._validateProxy(REQUEST) if self.wl_isLocked(): raise ResourceLockedError('This DTML Method is locked via WebDAV') if type(file) is not str: if REQUEST and not file: raise ValueError('No file specified') file = file.read() self.munge(file) self.ZCacheable_invalidate() if REQUEST: message = "Saved changes." return self.manage_main(self, REQUEST, manage_tabs_message=message) def manage_haveProxy(self, r): return r in self._proxy_roles def _validateProxy(self, request, roles=None): if roles is None: roles = self._proxy_roles if not roles: return user = u = getSecurityManager().getUser() user = user.allowed for r in roles: if r and not user(self, (r, )): user = None break if user is not None: return raise Forbidden( 'You are not authorized to change <em>%s</em> because you ' 'do not have proxy roles.\n<!--%s, %s-->' % (self.__name__, u, roles)) security.declareProtected(change_proxy_roles, 'manage_proxy') @requestmethod('POST') def manage_proxy(self, roles=(), REQUEST=None): "Change Proxy Roles" self._validateProxy(REQUEST, roles) self._validateProxy(REQUEST) self._proxy_roles = tuple(roles) self.ZCacheable_invalidate() if REQUEST: message = "Saved changes." return self.manage_proxyForm(self, REQUEST, manage_tabs_message=message) security.declareProtected(view_management_screens, 'PrincipiaSearchSource') def PrincipiaSearchSource(self): # Support for searching - the document's contents are searched. return self.read() security.declareProtected(view_management_screens, 'document_src') def document_src(self, REQUEST=None, RESPONSE=None): # Return unprocessed document source. if RESPONSE is not None: RESPONSE.setHeader('Content-Type', 'text/plain') return self.read() ## Protocol handlers security.declareProtected(change_dtml_methods, 'PUT') def PUT(self, REQUEST, RESPONSE): """ Handle FTP / HTTP PUT requests. """ self.dav__init(REQUEST, RESPONSE) self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1) body = REQUEST.get('BODY', '') self._validateProxy(REQUEST) self.munge(body) self.ZCacheable_invalidate() RESPONSE.setStatus(204) return RESPONSE security.declareProtected(ftp_access, 'manage_FTPstat') security.declareProtected(ftp_access, 'manage_FTPlist') security.declareProtected(ftp_access, 'manage_FTPget') def manage_FTPget(self): """ Get source for FTP download. """ return self.read() def manage_historyCompare(self, rev1, rev2, REQUEST, historyComparisonResults=''): return DTMLMethod.inheritedAttribute('manage_historyCompare')( self, rev1, rev2, REQUEST, historyComparisonResults=html_diff(rev1.read(), rev2.read()))
class DiscussionTool(UniqueObject, SimpleItem): """ Links content to discussions. """ implements(IDiscussionTool) id = 'portal_discussion' meta_type = 'Default Discussion Tool' security = ClassSecurityInfo() manage_options = (({ 'label': 'Overview', 'action': 'manage_overview' }, ) + SimpleItem.manage_options) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainDiscussionTool', _dtmldir) # # 'portal_discussion' interface methods # security.declarePublic('overrideDiscussionFor') def overrideDiscussionFor(self, content, allowDiscussion): """ Override discussability for the given object or clear the setting. """ if not _checkPermission(ModifyPortalContent, content): raise AccessControl_Unauthorized if allowDiscussion is None or allowDiscussion == 'None': disc_flag = getattr(aq_base(content), 'allow_discussion', _marker) if disc_flag is not _marker: try: del content.allow_discussion except AttributeError: # https://bugs.launchpad.net/zope-cmf/+bug/162532 pass else: content.allow_discussion = bool(allowDiscussion) security.declarePublic('getDiscussionFor') def getDiscussionFor(self, content): """ Get DiscussionItemContainer for content, create it if necessary. """ if not self.isDiscussionAllowedFor(content): raise DiscussionNotAllowed if not IDiscussionResponse.providedBy(content) and \ getattr( aq_base(content), 'talkback', None ) is None: # Discussion Items use the DiscussionItemContainer object of the # related content item, so only create one for other content items self._createDiscussionFor(content) return content.talkback # Return wrapped talkback security.declarePublic('isDiscussionAllowedFor') def isDiscussionAllowedFor(self, content): """ Get boolean indicating whether discussion is allowed for content. """ if hasattr(aq_base(content), 'allow_discussion'): return bool(content.allow_discussion) if IDynamicType.providedBy(content): # Grabbing type information objects only works for dynamic types typeInfo = content.getTypeInfo() if typeInfo: return bool(typeInfo.allowDiscussion()) return False # # Utility methods # security.declarePrivate('_createDiscussionFor') def _createDiscussionFor(self, content): """ Create DiscussionItemContainer for content, if allowed. """ if not self.isDiscussionAllowedFor(content): raise DiscussionNotAllowed content.talkback = DiscussionItemContainer() return content.talkback
class UndoTool(UniqueObject, SimpleItem): """ This tool is used to undo changes. """ implements(IUndoTool) id = 'portal_undo' meta_type = 'CMF Undo Tool' security = ClassSecurityInfo() manage_options = (SimpleItem.manage_options + ({ 'label': 'Overview', 'action': 'manage_overview' }, )) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainUndoTool', _dtmldir) # # 'IUndoTool' interface methods # security.declareProtected(ListUndoableChanges, 'listUndoableTransactionsFor') def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): """ List all transaction IDs the user is allowed to undo on 'object'. """ transactions = object.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) for t in transactions: # Ensure transaction ids don't have embedded LF. t['id'] = t['id'].replace('\n', '') if not _checkPermission(ManagePortal, object): # Filter out transactions done by other members of the portal. user_id = _getAuthenticatedUser(self).getId() transactions = filter(lambda record, user_id=user_id: record[ 'user_name'].split()[-1] == user_id, transactions) return transactions security.declarePublic('undo') def undo(self, object, transaction_info): """ Undo the list of transactions passed in 'transaction_info', first verifying that the current user is allowed to undo them. """ # Belt and suspenders: make sure that the user is actually # allowed to undo the transation(s) in transaction_info. xids = {} # set of allowed transaction IDs allowed = self.listUndoableTransactionsFor(object) for xid in map(lambda x: x['id'], allowed): xids[xid] = 1 if type(transaction_info) == type(''): transaction_info = [transaction_info] for tinfo in transaction_info: if not xids.get(tinfo, None): raise AccessControl_Unauthorized object.manage_undo_transactions(transaction_info)
class ZCTextIndex(Persistent, Implicit, SimpleItem): """Persistent text index. """ implements(IZCTextIndex, IPluggableIndex) ## Magic class attributes ## meta_type = 'ZCTextIndex' query_options = ('query', ) manage_options = ({'label': 'Overview', 'action': 'manage_main'}, ) security = ClassSecurityInfo() security.declareObjectProtected(manage_zcatalog_indexes) ## Constructor ## def __init__(self, id, extra=None, caller=None, index_factory=None, field_name=None, lexicon_id=None): self.id = id # Arguments can be passed directly to the constructor or # via the silly "extra" record. self._fieldname = field_name or getattr(extra, 'doc_attr', '') or id self._indexed_attrs = self._fieldname.split(',') self._indexed_attrs = [ attr.strip() for attr in self._indexed_attrs if attr ] lexicon_id = lexicon_id or getattr(extra, 'lexicon_id', '') lexicon = getattr(caller, lexicon_id, None) if lexicon is None: raise LookupError, 'Lexicon "%s" not found' % escape(lexicon_id) if not ILexicon.providedBy(lexicon): raise ValueError('Object "%s" does not implement ' 'ZCTextIndex Lexicon interface' % lexicon.getId()) self.lexicon_id = lexicon.getId() self._v_lexicon = lexicon if index_factory is None: if extra.index_type not in index_types.keys(): raise ValueError, 'Invalid index type "%s"' % escape( extra.index_type) self._index_factory = index_types[extra.index_type] self._index_type = extra.index_type else: self._index_factory = index_factory self.index = self._index_factory(aq_base(self.getLexicon())) ## Private Methods ## security.declarePrivate('getLexicon') def getLexicon(self): """Get the lexicon for this index """ if hasattr(aq_base(self), 'lexicon'): # Fix up old ZCTextIndexes by removing direct lexicon ref # and changing it to an ID lexicon = getattr(aq_parent(aq_inner(self)), self.lexicon.getId()) self.lexicon_id = lexicon.getId() del self.lexicon if getattr(aq_base(self), 'lexicon_path', None): # Fix up slightly less old ZCTextIndexes by removing # the physical path and changing it to an ID. # There's no need to use a physical path, which otherwise # makes it difficult to move or rename ZCatalogs. self.lexicon_id = self.lexicon_path[-1] del self.lexicon_path try: return self._v_lexicon except AttributeError: lexicon = getattr(aq_parent(aq_inner(self)), self.lexicon_id) if not ILexicon.providedBy(lexicon): raise TypeError('Object "%s" is not a ZCTextIndex Lexicon' % repr(lexicon)) self._v_lexicon = lexicon return lexicon ## External methods not in the Pluggable Index API ## security.declareProtected(search_zcatalog, 'query') def query(self, query, nbest=10): """Return pair (mapping from docids to scores, num results). The num results is the total number of results before trimming to the nbest results. """ tree = QueryParser(self.getLexicon()).parseQuery(query) results = tree.executeQuery(self.index) if results is None: return [], 0 chooser = NBest(nbest) chooser.addmany(results.items()) return chooser.getbest(), len(results) ## Pluggable Index APIs ## def index_object(self, documentId, obj, threshold=None): """Wrapper for index_doc() handling indexing of multiple attributes. Enter the document with the specified documentId in the index under the terms extracted from the indexed text attributes, each of which should yield either a string or a list of strings (Unicode or otherwise) to be passed to index_doc(). """ # XXX We currently ignore subtransaction threshold # needed for backward compatibility try: fields = self._indexed_attrs except: fields = [self._fieldname] res = 0 all_texts = [] for attr in fields: text = getattr(obj, attr, None) if text is None: continue if safe_callable(text): text = text() if text is None: continue if text: if isinstance(text, ( list, tuple, )): all_texts.extend(text) else: all_texts.append(text) # Check that we're sending only strings all_texts = filter(lambda text: isinstance(text, basestring), \ all_texts) if all_texts: return self.index.index_doc(documentId, all_texts) return res def unindex_object(self, docid): if self.index.has_doc(docid): self.index.unindex_doc(docid) def _apply_index(self, request): """Apply query specified by request, a mapping containing the query. Returns two object on success, the resultSet containing the matching record numbers and a tuple containing the names of the fields used Returns None if request is not valid for this index. """ record = parseIndexRequest(request, self.id, self.query_options) if record.keys is None: return None query_str = ' '.join(record.keys) if not query_str: return None tree = QueryParser(self.getLexicon()).parseQuery(query_str) results = tree.executeQuery(self.index) return results, (self.id, ) def getEntryForObject(self, documentId, default=None): """Return the list of words indexed for documentId""" try: word_ids = self.index.get_words(documentId) except KeyError: return default get_word = self.getLexicon().get_word return [get_word(wid) for wid in word_ids] def uniqueValues(self, name=None, withLengths=0): raise NotImplementedError ## The ZCatalog Index management screen uses these methods ## def numObjects(self): """Return number of unique words in the index""" return self.index.length() def indexSize(self): """Return the number of indexes objects """ return self.index.document_count() def clear(self): """reinitialize the index (but not the lexicon)""" try: # Remove the cached reference to the lexicon # So that it is refreshed del self._v_lexicon except (AttributeError, KeyError): pass self.index = self._index_factory(aq_base(self.getLexicon())) ## User Interface Methods ## manage_main = DTMLFile('dtml/manageZCTextIndex', globals()) def getIndexSourceNames(self): """Return sequence of names of indexed attributes""" try: return self._indexed_attrs except: return [self._fieldname] def getIndexType(self): """Return index type string""" return getattr(self, '_index_type', self._index_factory.__name__) def getLexiconURL(self): """Return the url of the lexicon used by the index""" try: lex = self.getLexicon() except (KeyError, AttributeError): return None else: return lex.absolute_url()
class PLexicon(Lexicon, Implicit, SimpleItem): """Lexicon for ZCTextIndex. """ implements(IZCLexicon) meta_type = 'ZCTextIndex Lexicon' manage_options = ( { 'label': 'Overview', 'action': 'manage_main' }, { 'label': 'Query', 'action': 'queryLexicon' }, ) + SimpleItem.manage_options security = ClassSecurityInfo() security.declareObjectProtected(LexiconQueryPerm) def __init__(self, id, title='', *pipeline): self.id = str(id) self.title = str(title) PLexicon.inheritedAttribute('__init__')(self, *pipeline) ## User Interface Methods ## def getPipelineNames(self): """Return list of names of pipeline element classes""" return [element.__class__.__name__ for element in self._pipeline] _queryLexicon = DTMLFile('dtml/queryLexicon', globals()) security.declareProtected(LexiconQueryPerm, 'queryLexicon') def queryLexicon(self, REQUEST, words=None, page=0, rows=20, cols=4): """Lexicon browser/query user interface """ if words: wids = [] for word in self.parseTerms(words): wids.extend(self.globToWordIds(word)) words = [self.get_word(wid) for wid in wids] else: words = self.words() word_count = len(words) rows = max(min(rows, 500), 1) cols = max(min(cols, 12), 1) page_count = word_count / (rows * cols) + \ (word_count % (rows * cols) > 0) page = max(min(page, page_count - 1), 0) start = rows * cols * page end = min(rows * cols * (page + 1), word_count) if word_count: words = list(words[start:end]) else: words = [] columns = [] i = 0 while i < len(words): columns.append(words[i:i + rows]) i += rows info = dict(page=page, rows=rows, cols=cols, start_word=start + 1, end_word=end, word_count=word_count, page_count=page_count, page_range=xrange(page_count), page_columns=columns) if REQUEST is not None: return self._queryLexicon(self, REQUEST, **info) return info security.declareProtected(LexiconMgmtPerm, 'manage_main') manage_main = DTMLFile('dtml/manageLexicon', globals())
from Products.Sessions.interfaces import IBrowserIdManager from Products.Sessions.interfaces import BrowserIdManagerErr from Products.Sessions.SessionPermissions import ACCESS_CONTENTS_PERM from Products.Sessions.SessionPermissions import CHANGE_IDMGR_PERM from Products.Sessions.SessionPermissions import MGMT_SCREEN_PERM b64_trans = string.maketrans('+/', '-.') b64_untrans = string.maketrans('-.', '+/') badidnamecharsin = re.compile('[\?&;,<> ]').search badcookiecharsin = re.compile('[;,<>& ]').search twodotsin = re.compile('(\w*\.){2,}').search _marker = [] constructBrowserIdManagerForm = DTMLFile('dtml/addIdManager', globals()) BROWSERID_MANAGER_NAME = 'browser_id_manager' # imported by SessionDataManager ALLOWED_BID_NAMESPACES = ('form', 'cookies', 'url') ADD_BROWSER_ID_MANAGER_PERM = "Add Browser Id Manager" TRAVERSAL_APPHANDLE = 'BrowserIdManager' LOG = logging.getLogger('Zope.BrowserIdManager') # Use the system PRNG if possible import random try: random = random.SystemRandom() using_sysrandom = True except NotImplementedError: using_sysrandom = False
self.unindex_objectKeywords(documentId, keywords) try: del self._unindex[documentId] except KeyError: LOG.debug('%s: Attempt to unindex nonexistent ' 'document with id %s' % (self.__class__.__name__, documentId), exc_info=True) manage = manage_main = DTMLFile('dtml/manageKeywordIndex', globals()) manage_main._setName('manage_main') manage_browse = DTMLFile('../dtml/browseIndex', globals()) manage_addKeywordIndexForm = DTMLFile('dtml/addKeywordIndex', globals()) def manage_addKeywordIndex(self, id, extra=None, REQUEST=None, RESPONSE=None, URL3=None): """Add a keyword index""" return self.manage_addIndex(id, 'KeywordIndex', extra=extra, REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3)
class DavLockManager(Item, Implicit): id = 'DavLockManager' name = title = 'WebDAV Lock Manager' meta_type = 'WebDAV Lock Manager' zmi_icon = 'fa fa-lock' security = ClassSecurityInfo() security.declareProtected( webdav_manage_locks, # NOQA: D001 'manage_davlocks') manage_davlocks = manage_main = manage = manage_workspace = DTMLFile( 'dtml/davLockManager', globals()) manage_davlocks._setName('manage_davlocks') manage_options = ( { 'label': 'Control Panel', 'action': '../manage_main' }, { 'label': 'Databases', 'action': '../Database/manage_main' }, { 'label': 'Configuration', 'action': '../Configuration/manage_main' }, { 'label': 'DAV Locks', 'action': 'manage_main' }, { 'label': 'Debug Information', 'action': '../DebugInfo/manage_main' }, ) @security.protected(webdav_manage_locks) def findLockedObjects(self, frompath=''): app = self.getPhysicalRoot() if frompath: if frompath[0] == '/': frompath = frompath[1:] # since the above will turn '/' into an empty string, check # for truth before chopping a final slash if frompath and frompath[-1] == '/': frompath = frompath[:-1] # Now we traverse to the node specified in the 'frompath' if # the user chose to filter the search, and run a ZopeFind with # the expression 'wl_isLocked()' to find locked objects. obj = app.unrestrictedTraverse(frompath) lockedobjs = self._findapply(obj, path=frompath) return lockedobjs @security.private def unlockObjects(self, paths=[]): app = self.getPhysicalRoot() for path in paths: ob = app.unrestrictedTraverse(path) ob.wl_clearLocks() @security.protected(webdav_manage_locks) def manage_unlockObjects(self, paths=[], REQUEST=None): " Management screen action to unlock objects. " if paths: self.unlockObjects(paths) if REQUEST is not None: m = '%s objects unlocked.' % len(paths) return self.manage_davlocks(self, REQUEST, manage_tabs_message=m) def _findapply(self, obj, result=None, path=''): # recursive function to actually dig through and find the locked # objects. if result is None: result = [] base = aq_base(obj) if not hasattr(base, 'objectItems'): return result try: items = obj.objectItems() except Exception: return result addresult = result.append for id, ob in items: if path: p = f'{path}/{id}' else: p = id dflag = hasattr(ob, '_p_changed') and (ob._p_changed is None) bs = aq_base(ob) if wl_isLocked(ob): li = [] addlockinfo = li.append for token, lock in ob.wl_lockItems(): addlockinfo({ 'owner': lock.getCreatorPath(), 'token': token }) addresult((p, li)) dflag = 0 if hasattr(bs, 'objectItems'): self._findapply(ob, result, p) if dflag: ob._p_deactivate() return result
class KeywordIndex(UnIndex): """Like an UnIndex only it indexes sequences of items. Searches match any keyword. This should have an _apply_index that returns a relevance score """ meta_type = "KeywordIndex" query_options = ('query', 'range', 'not', 'operator') manage_options = ( { 'label': 'Settings', 'action': 'manage_main' }, { 'label': 'Browse', 'action': 'manage_browse' }, ) def _index_object(self, documentId, obj, threshold=None, attr=''): """ index an object 'obj' with integer id 'i' Ideally, we've been passed a sequence of some sort that we can iterate over. If however, we haven't, we should do something useful with the results. In the case of a string, this means indexing the entire string as a keyword.""" # First we need to see if there's anything interesting to look at # self.id is the name of the index, which is also the name of the # attribute we're interested in. If the attribute is callable, # we'll do so. newKeywords = self._get_object_keywords(obj, attr) oldKeywords = self._unindex.get(documentId, None) if oldKeywords is None: # we've got a new document, let's not futz around. try: for kw in newKeywords: self.insertForwardIndexEntry(kw, documentId) if newKeywords: self._unindex[documentId] = list(newKeywords) except TypeError: return 0 else: # we have an existing entry for this document, and we need # to figure out if any of the keywords have actually changed if type(oldKeywords) is not OOSet: oldKeywords = OOSet(oldKeywords) newKeywords = OOSet(newKeywords) fdiff = difference(oldKeywords, newKeywords) rdiff = difference(newKeywords, oldKeywords) if fdiff or rdiff: # if we've got forward or reverse changes if newKeywords: self._unindex[documentId] = list(newKeywords) else: del self._unindex[documentId] if fdiff: self.unindex_objectKeywords(documentId, fdiff) if rdiff: for kw in rdiff: self.insertForwardIndexEntry(kw, documentId) return 1 def _get_object_keywords(self, obj, attr): newKeywords = getattr(obj, attr, ()) if safe_callable(newKeywords): try: newKeywords = newKeywords() except (AttributeError, TypeError): return () if not newKeywords: return () elif isinstance(newKeywords, basestring): return (newKeywords, ) else: try: # unique newKeywords = set(newKeywords) except TypeError: # Not a sequence return (newKeywords, ) else: return tuple(newKeywords) def unindex_objectKeywords(self, documentId, keywords): """ carefully unindex the object with integer id 'documentId'""" if keywords is not None: for kw in keywords: self.removeForwardIndexEntry(kw, documentId) def unindex_object(self, documentId): """ carefully unindex the object with integer id 'documentId'""" keywords = self._unindex.get(documentId, None) # Couldn't we return 'None' immediately # if keywords is 'None' (or _marker)??? if keywords is not None: self._increment_counter() self.unindex_objectKeywords(documentId, keywords) try: del self._unindex[documentId] except KeyError: LOG.debug('%s: Attempt to unindex nonexistent ' 'document with id %s' % (self.__class__.__name__, documentId), exc_info=True) manage = manage_main = DTMLFile('dtml/manageKeywordIndex', globals()) manage_main._setName('manage_main') manage_browse = DTMLFile('../dtml/browseIndex', globals())
<!DOCTYPE html> <html> <head> <title><dtml-var title_or_id></title> <meta charset="utf-8" /> </head> <body> <h2><dtml-var title_or_id> <dtml-var document_title></h2> <p> This is the <dtml-var document_id> Document in the <dtml-var title_and_id> Folder. </p> </body> </html>""" addForm = DTMLFile('dtml/methodAdd', globals()) def addDTMLMethod(self, id, title='', file='', REQUEST=None, submit=None): """Add a DTML Method object with the contents of file. If 'file' is empty, default document text is used. """ data = safe_file_data(file) if not data: data = default_dm_html id = str(id) title = str(title) ob = DTMLMethod(data, __name__=id) ob.title = title id = self._setObject(id, ob) if REQUEST is not None:
from App.special_dtml import DTMLFile from Persistence import Persistent, PersistentMapping from Acquisition import aq_base from BTrees.OOBTree import OOBTree from BTrees.Length import Length from ZODB.POSException import ConflictError from OFS.ObjectManager import BadRequestException, BeforeDeleteException from OFS.Folder import Folder from AccessControl import getSecurityManager, ClassSecurityInfo from AccessControl.Permissions import access_contents_information, \ view_management_screens from zLOG import LOG, ERROR from AccessControl.SimpleObjectPolicies import ContainerAssertions manage_addHBTreeFolder2Form = DTMLFile('folderAdd', globals()) def manage_addHBTreeFolder2(dispatcher, id, title='', REQUEST=None): """Adds a new HBTreeFolder object with id *id*. """ id = str(id) ob = HBTreeFolder2(id) ob.title = str(title) dispatcher._setObject(id, ob) ob = dispatcher._getOb(id) if REQUEST is not None: return dispatcher.manage_main(dispatcher, REQUEST, update_menu=1) listtext0 = '''<select name="ids:list" multiple="multiple" size="%s"> '''
'title': self.meta_type }, ) if self.haveProxyRole(): icons = ({ 'path': 'p_/PythonScript_ProxyRole_icon', 'alt': 'Proxy Roled Python Script', 'title': 'This script has proxy role.' }, ) return icons pyscript_proxyrole = ImageFile('pyscript_proxyrole.gif', globals()) # # Add proxy role icon in ZMI # PythonScript.haveProxyRole = haveProxyRole PythonScript.om_icons = om_icons p_.PythonScript_ProxyRole_icon = pyscript_proxyrole # Patch for displaying textearea in full window instead of # remembering a quantity of lines to display in a cookie manage_editForm = DTMLFile("pyScriptEdit", _dtmldir) manage_editForm._setName('manage_editForm') PythonScript.ZPythonScriptHTML_editForm = manage_editForm PythonScript.manage_editForm = manage_editForm PythonScript.manage = manage_editForm PythonScript.manage_main = manage_editForm PythonScript.manage_editDocument = manage_editForm PythonScript.manage_editForm = manage_editForm
class HBTreeFolder2Base (Persistent): """Base for BTree-based folders. BUG: Due to wrong design, we can't store 2 objects <A> and <A>-<B> where <A> does not contain '-'. We detect conflicts at the root level using 'type(ob) is OOBTree' """ security = ClassSecurityInfo() manage_options=( ({'label':'Contents', 'action':'manage_main',}, ) + Folder.manage_options[1:] ) security.declareProtected(view_management_screens, 'manage_main') manage_main = DTMLFile('contents', globals()) _htree = None # OOBTree: { id -> object } _count = None # A BTrees.Length _v_nextid = 0 # The integer component of the next generated ID title = '' def __init__(self, id=None): if id is not None: self.id = id self._initBTrees() def _initBTrees(self): self._htree = OOBTree() self._count = Length() def _populateFromFolder(self, source): """Fill this folder with the contents of another folder. """ for name, value in source.objectItems(): self._setOb(name, aq_base(value)) security.declareProtected(view_management_screens, 'manage_fixCount') def manage_fixCount(self, dry_run=0): """Calls self._fixCount() and reports the result as text. """ old, new = self._fixCount(dry_run) path = '/'.join(self.getPhysicalPath()) if old == new: return "No count mismatch detected in HBTreeFolder2 at %s." % path else: return ("Fixed count mismatch in HBTreeFolder2 at %s. " "Count was %d; corrected to %d" % (path, old, new)) def _fixCount(self, dry_run=0): """Checks if the value of self._count disagrees with the content of the htree. If so, corrects self._count. Returns the old and new count values. If old==new, no correction was performed. """ old = self._count() new = sum(1 for x in self._htree_iteritems()) if old != new and not dry_run: self._count.set(new) return old, new def hashId(self, id): return id.split(H_SEPARATOR) def _htree_get(self, id): id_list = self.hashId(id) if len(id_list) == 1: ob = self._htree[id] if type(ob) is OOBTree: raise KeyError else: ob = self._htree[id_list.pop(0)] if type(ob) is not OOBTree: raise KeyError id_list[-1] = id for sub_id in id_list: ob = ob[sub_id] return ob def _getOb(self, id, default=_marker): """Return the named object from the folder """ try: return self._htree_get(id).__of__(self) except KeyError: if default is _marker: raise KeyError(id) return default def __getitem__(self, id): try: return self._htree_get(id).__of__(self) except KeyError: raise KeyError(id) def _setOb(self, id, object): """Store the named object in the folder. """ if type(object) is OOBTree: raise ValueError('HBTreeFolder2 can not store OOBTree objects') htree = self._htree for sub_id in self.hashId(id)[:-1]: try: htree = htree[sub_id] except KeyError: htree[sub_id] = htree = OOBTree() continue if type(htree) is not OOBTree: assert self._htree[sub_id] is htree, (htree, id) raise KeyError('There is already an item whose id is %r' % sub_id) if htree.has_key(id): raise KeyError('There is already an item named %r.' % id) htree[id] = object self._count.change(1) def _delOb(self, id): """Remove the named object from the folder. """ htree = self._htree h = [] for sub_id in self.hashId(id)[:-1]: h.append((htree, sub_id)) htree = htree.get(sub_id) if type(htree) is not OOBTree: raise KeyError(id) if type(htree[id]) is OOBTree: raise KeyError(id) del htree[id] self._count.change(-1) while h and not htree: htree, sub_id = h.pop() del htree[sub_id] security.declareProtected(view_management_screens, 'getBatchObjectListing') def getBatchObjectListing(self, REQUEST=None): """Return a structure for a page template to show the list of objects. """ if REQUEST is None: REQUEST = {} pref_rows = int(REQUEST.get('dtpref_rows', 20)) b_start = int(REQUEST.get('b_start', 1)) b_count = int(REQUEST.get('b_count', 1000)) b_end = b_start + b_count - 1 url = self.absolute_url() + '/manage_main' count = self.objectCount() if b_end < count: next_url = url + '?b_start=%d' % (b_start + b_count) else: b_end = count next_url = '' if b_start > 1: prev_url = url + '?b_start=%d' % max(b_start - b_count, 1) else: prev_url = '' formatted = [listtext0 % pref_rows] for optID in islice(self.objectIds(), b_start - 1, b_end): optID = escape(optID) formatted.append(listtext1 % (escape(optID, quote=1), optID)) formatted.append(listtext2) return {'b_start': b_start, 'b_end': b_end, 'prev_batch_url': prev_url, 'next_batch_url': next_url, 'formatted_list': ''.join(formatted)} security.declareProtected(view_management_screens, 'manage_object_workspace') def manage_object_workspace(self, ids=(), REQUEST=None): '''Redirects to the workspace of the first object in the list.''' if ids and REQUEST is not None: REQUEST.RESPONSE.redirect( '%s/%s/manage_workspace' % ( self.absolute_url(), quote(ids[0]))) else: return self.manage_main(self, REQUEST) security.declareProtected(access_contents_information, 'tpValues') def tpValues(self): """Ensures the items don't show up in the left pane. """ return () security.declareProtected(access_contents_information, 'objectCount') def objectCount(self): """Returns the number of items in the folder.""" return self._count() security.declareProtected(access_contents_information, 'has_key') def has_key(self, id): """Indicates whether the folder has an item by ID. """ try: self._htree_get(id) except KeyError: return 0 return 1 # Work around for the performance regression introduced in Zope 2.12.23. # Otherwise, we use superclass' __contains__ implementation, which uses # objectIds, which is inefficient in HBTreeFolder2 to lookup a single key. __contains__ = has_key def _htree_iteritems(self, min=None): # BUG: Due to bad design of HBTreeFolder2, buckets other than the root # one must not contain both buckets & leafs. Otherwise, this method # fails. h = self._htree recurse_stack = [] try: for sub_id in self.hashId(min) if min else ('',): if recurse_stack: i.next() if type(h) is not OOBTree: break id += H_SEPARATOR + sub_id if type(h.itervalues().next()) is not OOBTree: sub_id = id else: id = sub_id i = h.iteritems(sub_id) recurse_stack.append(i) h = h[sub_id] except (KeyError, StopIteration): pass while recurse_stack: i = recurse_stack.pop() try: while 1: id, h = i.next() if type(h) is OOBTree: recurse_stack.append(i) i = h.iteritems() else: yield id, h except StopIteration: pass security.declareProtected(access_contents_information, 'getTreeIdList') def getTreeIdList(self, htree=None): """ Return list of all tree ids """ r = [] s = [(None, self._htree.iteritems())] while s: base_id, items = s.pop() if base_id: for k, v in items: if type(v) is not OOBTree: r.append(base_id) # As an optimization, and because _htree_iteritems does not # support mixed buckets except at the root, we consider that # this one only contains leafs. break s.append((base_id + H_SEPARATOR + k, v.iteritems())) else: for k, v in items: if type(v) is not OOBTree: r.append(base_id) for k, v in items: if type(v) is OOBTree: s.append((k, v.iteritems())) break s.append((k, v.iteritems())) r.sort() return r security.declareProtected(access_contents_information, 'objectValues') def objectValues(self, base_id=_marker): return HBTreeObjectValues(self, base_id) security.declareProtected(access_contents_information, 'objectIds') def objectIds(self, base_id=_marker): return HBTreeObjectIds(self, base_id) security.declareProtected(access_contents_information, 'objectItems') def objectItems(self, base_id=_marker): # Returns a list of (id, subobject) tuples of the current object. return HBTreeObjectItems(self, base_id) # superValues() looks for the _objects attribute, but the implementation # would be inefficient, so superValues() support is disabled. _objects = () security.declareProtected(access_contents_information, 'objectIds_d') def objectIds_d(self, t=None): return dict.fromkeys(self.objectIds(t), 1) def _checkId(self, id, allow_dup=0): if not allow_dup and self.has_key(id): raise BadRequestException, ('The id "%s" is invalid--' 'it is already in use.' % id) def _setObject(self, id, object, roles=None, user=None, set_owner=1): v=self._checkId(id) if v is not None: id=v # If an object by the given id already exists, remove it. if self.has_key(id): self._delObject(id) self._setOb(id, object) object = self._getOb(id) if set_owner: object.manage_fixupOwnershipAfterAdd() # Try to give user the local role "Owner", but only if # no local roles have been set on the object yet. if hasattr(object, '__ac_local_roles__'): if object.__ac_local_roles__ is None: user=getSecurityManager().getUser() if user is not None: userid=user.getId() if userid is not None: object.manage_setLocalRoles(userid, ['Owner']) object.manage_afterAdd(object, self) return id def _delObject(self, id, dp=1): object = self._getOb(id) try: object.manage_beforeDelete(object, self) except BeforeDeleteException, ob: raise except ConflictError: raise
class BooleanIndex(UnIndex): """Index for booleans self._index = set([documentId1, documentId2]) self._unindex = {documentId:[True/False]} False doesn't have actual entries in _index. """ meta_type = "BooleanIndex" manage_options = ( { 'label': 'Settings', 'action': 'manage_main' }, { 'label': 'Browse', 'action': 'manage_browse' }, ) query_options = ["query"] manage = manage_main = DTMLFile('dtml/manageBooleanIndex', globals()) manage_main._setName('manage_main') manage_browse = DTMLFile('../dtml/browseIndex', globals()) def clear(self): self._length = BTrees.Length.Length() self._index = IITreeSet() self._unindex = IIBTree() def insertForwardIndexEntry(self, entry, documentId): """If True, insert directly into treeset """ if entry: self._index.insert(documentId) self._length.change(1) def removeForwardIndexEntry(self, entry, documentId): """Take the entry provided and remove any reference to documentId in its entry in the index. """ try: if entry: self._index.remove(documentId) self._length.change(-1) except ConflictError: raise except Exception: LOG.exception( '%s: unindex_object could not remove ' 'documentId %s from index %s. This ' 'should not happen.' % (self.__class__.__name__, str(documentId), str(self.id))) def _index_object(self, documentId, obj, threshold=None, attr=''): """ index and object 'obj' with integer id 'documentId'""" returnStatus = 0 # First we need to see if there's anything interesting to look at datum = self._get_object_datum(obj, attr) # Make it boolean, int as an optimization datum = int(bool(datum)) # We don't want to do anything that we don't have to here, so we'll # check to see if the new and existing information is the same. oldDatum = self._unindex.get(documentId, _marker) if datum != oldDatum: if oldDatum is not _marker: self.removeForwardIndexEntry(oldDatum, documentId) if datum is _marker: try: del self._unindex[documentId] except ConflictError: raise except Exception: LOG.error('Should not happen: oldDatum was there, now ' 'its not, for document with id %s' % documentId) if datum is not _marker: if datum: self.insertForwardIndexEntry(datum, documentId) self._unindex[documentId] = datum returnStatus = 1 return returnStatus def _apply_index(self, request, resultset=None): record = parseIndexRequest(request, self.id, self.query_options) if record.keys is None: return None index = self._index for key in record.keys: if key: # If True, check index return (intersection(index, resultset), (self.id, )) else: # Otherwise, remove from resultset or _unindex if resultset is None: return (union(difference(self._unindex, index), IISet([])), (self.id, )) else: return (difference(resultset, index), (self.id, )) return (IISet(), (self.id, )) def indexSize(self): """Return distinct values, as an optimization we always claim 2.""" return 2 def items(self): items = [] for v, k in self._unindex.items(): if isinstance(v, int): v = IISet((v, )) items.append((k, v)) return items
class RegistrationTool(UniqueObject, SimpleItem): """ Create and modify users by making calls to portal_membership. """ id = 'portal_registration' meta_type = 'CMF Registration Tool' member_id_pattern = '' default_member_id_pattern = "^[A-Za-z][A-Za-z0-9_]*$" _ALLOWED_MEMBER_ID_PATTERN = re.compile(default_member_id_pattern) security = ClassSecurityInfo() manage_options = (({ 'label': 'Overview', 'action': 'manage_overview' }, { 'label': 'Configure', 'action': 'manage_configuration' }) + SimpleItem.manage_options) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainRegistrationTool', _dtmldir) security.declareProtected(ManagePortal, 'manage_configuration') manage_configuration = DTMLFile('configureRegistrationTool', _dtmldir) @security.protected(ManagePortal) def manage_editIDPattern(self, pattern, REQUEST=None): """Edit the allowable member ID pattern TTW""" pattern.strip() if len(pattern) > 0: self.member_id_pattern = pattern self._ALLOWED_MEMBER_ID_PATTERN = re.compile(pattern) else: self.member_id_pattern = '' self._ALLOWED_MEMBER_ID_PATTERN = re.compile( self.default_member_id_pattern) if REQUEST is not None: msg = 'Member ID Pattern changed' return self.manage_configuration(manage_tabs_message=msg) @security.protected(ManagePortal) def getIDPattern(self): """ Return the currently-used member ID pattern """ return self.member_id_pattern @security.protected(ManagePortal) def getDefaultIDPattern(self): """ Return the currently-used member ID pattern """ return self.default_member_id_pattern # # 'portal_registration' interface methods # @security.public def isRegistrationAllowed(self, REQUEST): '''Returns a boolean value indicating whether the user is allowed to add a member to the portal. ''' return _checkPermission(AddPortalMember, self.aq_inner.aq_parent) @security.public def testPasswordValidity(self, password, confirm=None): '''If the password is valid, returns None. If not, returns a string explaining why. ''' return None @security.public def testPropertiesValidity(self, new_properties, member=None): '''If the properties are valid, returns None. If not, returns a string explaining why. ''' return None @security.public def generatePassword(self): """ Generate a valid password. """ # we don't use these to avoid typos: OQ0Il1 chars = 'ABCDEFGHJKLMNPRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789' return ''.join([choice(chars) for i in range(6)]) @security.protected(AddPortalMember) def addMember(self, id, password, roles=('Member', ), domains='', properties=None, REQUEST=None): # XXX Do not make this a normal method comment. Doing so makes # this method publishable # Creates a PortalMember and returns it. The properties argument # can be a mapping with additional member properties. Raises an # exception if the given id already exists, the password does not # comply with the policy in effect, or the authenticated user is not # allowed to grant one of the roles listed (where Member is a special # role that can always be granted); these conditions should be # detected before the fact so that a cleaner message can be printed. if not self.isMemberIdAllowed(id): raise ValueError( _(u'The login name you selected is already in ' u'use or is not valid. Please choose another.')) failMessage = self.testPasswordValidity(password) if failMessage is not None: raise ValueError(failMessage) if properties is not None: failMessage = self.testPropertiesValidity(properties) if failMessage is not None: raise ValueError(failMessage) # Limit the granted roles. # Anyone is always allowed to grant the 'Member' role. _limitGrantedRoles(roles, self, ('Member', )) mtool = getUtility(IMembershipTool) mtool.addMember(id, password, roles, domains, properties) member = mtool.getMemberById(id) self.afterAdd(member, id, password, properties) return member @security.protected(AddPortalMember) def isMemberIdAllowed(self, id): '''Returns 1 if the ID is not in use and is not reserved. ''' if len(id) < 1 or id == 'Anonymous User': return 0 if not self._ALLOWED_MEMBER_ID_PATTERN.match(id): return 0 mtool = getUtility(IMembershipTool) if mtool.getMemberById(id) is not None: return 0 return 1 @security.public def afterAdd(self, member, id, password, properties): '''Called by portal_registration.addMember() after a member has been added successfully.''' pass @security.protected(MailForgottenPassword) def mailPassword(self, forgotten_userid, REQUEST): '''Email a forgotten password to a member. Raises an exception if user ID is not found. ''' raise NotImplementedError
class DirectoryViewSurrogate(Folder): """ Folderish DirectoryView. """ meta_type = 'Filesystem Directory View' zmi_icon = 'far fa-folder-open' all_meta_types = () security = ClassSecurityInfo() def __init__(self, real, data, objects): d = self.__dict__ d.update(data) d.update(real.__dict__) d['_real'] = real d['_objects'] = objects def __setattr__(self, name, value): d = self.__dict__ d[name] = value setattr(d['_real'], name, value) def __delattr__(self, name): d = self.__dict__ del d[name] delattr(d['_real'], name) security.declareProtected(ManagePortal, 'manage_propertiesForm') manage_propertiesForm = DTMLFile('dirview_properties', _dtmldir) @security.protected(ManagePortal) def manage_properties(self, reg_key, REQUEST=None): """ Update the directory path of the DirectoryView. """ self.__dict__['_real']._dirpath = reg_key if REQUEST is not None: REQUEST['RESPONSE'].redirect('%s/manage_propertiesForm' % self.absolute_url()) @security.protected(ACI) def getCustomizableObject(self): ob = aq_parent(aq_inner(self)) while ob: if IDirectoryView.providedBy(ob): ob = aq_parent(ob) else: break return ob @security.protected(ACI) def listCustFolderPaths(self, adding_meta_type=None): """ List possible customization folders as key, value pairs. """ rval = [] ob = self.getCustomizableObject() listFolderHierarchy(ob, '', rval, adding_meta_type) rval.sort() return rval @security.protected(ACI) def getDirPath(self): return self.__dict__['_real']._dirpath @security.public def getId(self): return self.id
class SkinsTool(UniqueObject, SkinsContainer, Folder, ActionProviderBase): """ This tool is used to supply skins to a portal. """ id = 'portal_skins' meta_type = 'CMF Skins Tool' allow_any = 0 cookie_persistence = 0 default_skin = '' request_varname = 'portal_skin' selections = None security = ClassSecurityInfo() manage_options = (modifiedOptions() + ({ 'label': 'Overview', 'action': 'manage_overview' }, ) + ActionProviderBase.manage_options) def __init__(self): self.selections = PersistentMapping() def _getSelections(self): sels = self.selections if sels is None: # Backward compatibility. self.selections = sels = PersistentMapping() return sels # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainSkinsTool', _dtmldir) security.declareProtected(ManagePortal, 'manage_propertiesForm') manage_propertiesForm = DTMLFile('dtml/skinProps', globals()) # the following two methods override those in FindSupport, to # support marking of objects used in specific skins security.declareProtected(ManagePortal, 'manage_findResult') manage_findResult = DTMLFile('findResult', _dtmldir, management_view='Find') security.declareProtected(ManagePortal, 'manage_findForm') manage_findForm = DTMLFile('findForm', _dtmldir, management_view='Find') security.declareProtected(ManagePortal, 'manage_compareResults') manage_compareResults = DTMLFile('compareResults', _dtmldir, management_view='Compare') @security.protected(ManagePortal) def manage_skinLayers(self, chosen=(), add_skin=0, del_skin=0, skinname='', skinpath='', REQUEST=None): """ Change the skinLayers. """ sels = self._getSelections() if del_skin: for name in chosen: del sels[name] if REQUEST is not None: for key in sels.keys(): fname = 'skinpath_%s' % key val = REQUEST[fname] # if val is a list from the new lines field # then munge it back into a comma delimited list # for hysterical reasons if isinstance(val, list): val = ','.join([layer.strip() for layer in val]) if sels[key] != val: self.testSkinPath(val) sels[key] = val if add_skin: skinpath = ','.join([layer.strip() for layer in skinpath]) self.testSkinPath(skinpath) sels[str(skinname)] = skinpath if REQUEST is not None: return self.manage_propertiesForm( self, REQUEST, management_view='Properties', manage_tabs_message='Skins changed.') @security.protected(ManagePortal) def isFirstInSkin(self, template_path, skin=None): """ Is the specified template the one that would get returned from the current skin? """ if skin is None or skin == 'None': skin = self.getDefaultSkin() template = self.restrictedTraverse(template_path) name = template.getId() skin_path = self.getSkinPath(skin) if not skin_path: return 0 parts = list(skin_path.split(",")) found = "" for part in parts: part = part.strip() if part[0] == "_": continue partob = getattr(self, part, None) if partob: skin_template = getattr(partob.aq_base, name, None) if skin_template: found = skin_template break if found == template: return 1 else: return 0 @security.protected(ManagePortal) def manage_properties(self, default_skin='', request_varname='', allow_any=0, chosen=(), add_skin=0, del_skin=0, skinname='', skinpath='', cookie_persistence=0, REQUEST=None): """ Changes portal_skin properties. """ self.default_skin = str(default_skin) self.request_varname = str(request_varname) self.allow_any = allow_any and 1 or 0 self.cookie_persistence = cookie_persistence and 1 or 0 if REQUEST is not None: return self.manage_propertiesForm( self, REQUEST, management_view='Properties', manage_tabs_message='Properties changed.') @security.private def PUT_factory(self, name, typ, body): """ Dispatcher for PUT requests to non-existent IDs. Returns an object of the appropriate type (or None, if we don't know what to do). """ major, minor = typ.split('/', 1) if major == 'image': return Image(id=name, title='', file='', content_type=typ) if major == 'text': if minor == 'x-python': return PythonScript(id=name) if minor in ('html', 'xml'): return ZopePageTemplate(name) return DTMLMethod(__name__=name) return None # Make the PUT_factory replaceable PUT_factory__replaceable__ = REPLACEABLE @security.private def testSkinPath(self, p): """ Calls SkinsContainer.getSkinByPath(). """ self.getSkinByPath(p, raise_exc=1) # # 'SkinsContainer' interface methods # @security.protected(AccessContentsInformation) def getSkinPath(self, name): """ Convert a skin name to a skin path. """ sels = self._getSelections() p = sels.get(name, None) if p is None: if self.allow_any: return name return p # Can be None @security.protected(AccessContentsInformation) def getDefaultSkin(self): """ Get the default skin name. """ return self.default_skin @security.protected(AccessContentsInformation) def getRequestVarname(self): """ Get the variable name to look for in the REQUEST. """ return self.request_varname # # UI methods # @security.protected(AccessContentsInformation) def getAllowAny(self): ''' Used by the management UI. Returns a flag indicating whether users are allowed to use arbitrary skin paths. ''' return self.allow_any @security.protected(AccessContentsInformation) def getCookiePersistence(self): ''' Used by the management UI. Returns a flag indicating whether the skins cookie is persistent or not. ''' return self.cookie_persistence @security.protected(AccessContentsInformation) def getSkinPaths(self): ''' Used by the management UI. Returns the list of skin name to skin path mappings as a sorted list of tuples. ''' sels = self._getSelections() rval = [] for key, value in sels.items(): rval.append((key, value)) rval.sort() return rval # # 'portal_skins' interface methods # @security.public def getSkinSelections(self): """ Get the sorted list of available skin names. """ sels = self._getSelections() rval = list(sels.keys()) rval.sort() return rval @security.protected(View) def updateSkinCookie(self): """ If needed, updates the skin cookie based on the member preference. """ mtool = getUtility(IMembershipTool) member = mtool.getAuthenticatedMember() if hasattr(aq_base(member), 'getProperty'): mskin = member.getProperty('portal_skin') if mskin: req = getRequest() cookie = req.cookies.get(self.request_varname, None) if cookie != mskin: resp = req.RESPONSE utool = getUtility(IURLTool) portal_path = req['BASEPATH1'] + '/' + utool(1) if not self.cookie_persistence: # *Don't* make the cookie persistent! resp.setCookie(self.request_varname, mskin, path=portal_path) else: expires = (DateTime('GMT') + 365).rfc822() resp.setCookie(self.request_varname, mskin, path=portal_path, expires=expires) # Ensure updateSkinCookie() doesn't try again # within this request. req.cookies[self.request_varname] = mskin req[self.request_varname] = mskin return 1 return 0 @security.protected(View) def clearSkinCookie(self): """ Expire the skin cookie. """ req = getRequest() resp = req.RESPONSE utool = getUtility(IURLTool) portal_path = req['BASEPATH1'] + '/' + utool(1) resp.expireCookie(self.request_varname, path=portal_path) @security.protected(ManagePortal) def addSkinSelection(self, skinname, skinpath, test=0, make_default=0): ''' Adds a skin selection. ''' sels = self._getSelections() skinpath = str(skinpath) # Basic precaution to make sure the stuff we want to ignore in # DirectoryViews gets prevented from ending up in a skin path path_elems = [x.strip() for x in skinpath.split(',')] ignored = base_ignore + ignore for elem in path_elems[:]: if elem in ignored or ignore_re.match(elem): path_elems.remove(elem) skinpath = ','.join(path_elems) if test: self.testSkinPath(skinpath) sels[str(skinname)] = skinpath if make_default: self.default_skin = skinname @security.protected(AccessContentsInformation) def getDiff(self, item_one_path, item_two_path, reverse=0): """ Return a diff between one and two. """ if not reverse: item_one = self.unrestrictedTraverse(item_one_path) item_two = self.unrestrictedTraverse(item_two_path) else: item_one = self.unrestrictedTraverse(item_two_path) item_two = self.unrestrictedTraverse(item_one_path) res = unified_diff(item_one.read().splitlines(), item_two.read().splitlines(), item_one_path, item_two_path, '', '', lineterm="") return res
def __init__(self, name, _prefix=None, **kw): DTMLFile.__init__(self, name, _prefix, **kw) DomainAware.__init__(self, _prefix)
ids = folder.objectIds() for idx, id in enumerate(ids): rid = rids.get(id) if rid: pos[rid] = idx return pos else: # otherwise the entire map needs to be constructed... for rid, container, id in items: if getattr(aq_base(container), 'getObjectPosition', None): pos[rid] = container.getObjectPosition(id) else: # fallback for unordered folders pos[rid] = 0 return pos manage_addGopipForm = DTMLFile('dtml/addGopipIndex', globals()) def manage_addGopipIndex(self, identifier, REQUEST=None, RESPONSE=None, URL3=None): """ add a fake gopip index """ return self.manage_addIndex( identifier, 'GopipIndex', REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3 )
def _exec(self, bound_data, args, kw): request = getRequest() if request is not None: request.response.setHeader('X-Theme-Disabled', '1') return DTMLFile._exec(self, bound_data, args, kw)
class MethodDoc(Persistent): """ Describes a method of an API. required - a sequence of required arguments optional - a sequence of tuples (name, default value) varargs - the name of the variable argument or None kwargs - the name of the kw argument or None """ security = ClassSecurityInfo() security.setDefaultAccess({ 'doc': True, 'kwargs': True, 'name': True, 'optional': True, 'required': True, 'varargs': True }) varargs = None kwargs = None def __init__(self, func, isInterface=0): if isInterface: self._createFromInterfaceMethod(func) else: self._createFromFunc(func) def _createFromInterfaceMethod(self, func): self.name = func.__name__ self.doc = trim_doc_string(func.__doc__) self.required = func.required opt = [] for p in func.positional[len(func.required):]: opt.append((p, func.optional[p])) self.optional = tuple(opt) if func.varargs: self.varargs = func.varargs if func.kwargs: self.kwargs = func.kwargs def _createFromFunc(self, func): if hasattr(func, 'im_func'): func = func.im_func self.name = func.__name__ self.doc = trim_doc_string(func.__doc__) # figure out the method arguments # mostly stolen from pythondoc CO_VARARGS = 4 CO_VARKEYWORDS = 8 names = func.func_code.co_varnames nrargs = func.func_code.co_argcount if func.func_defaults: nrdefaults = len(func.func_defaults) else: nrdefaults = 0 self.required = names[:nrargs - nrdefaults] if func.func_defaults: self.optional = tuple( map(None, names[nrargs - nrdefaults:nrargs], func.func_defaults)) else: self.optional = () varargs = [] ix = nrargs if func.func_code.co_flags & CO_VARARGS: self.varargs = names[ix] ix = ix + 1 if func.func_code.co_flags & CO_VARKEYWORDS: self.kwargs = names[ix] view = DTMLFile('dtml/methodView', globals())
class APIDoc(Persistent): """ Describes an API. """ security = ClassSecurityInfo() security.setDefaultAccess({ 'attributes': True, 'constructor': True, 'doc': True, 'extends': True, 'name': True, 'methods': True }) extends = () def __init__(self, klass, isInterface=0): if isInterface: self._createFromInterface(klass) else: self._createFromClass(klass) def _createFromInterface(self, klass): # Creates an APIDoc instance given an interface object. self.name = klass.__name__ self.doc = trim_doc_string(klass.__doc__) # inheritence information self.extends = [] # Get info on methods and attributes, ignore special items self.attributes = [] self.methods = [] for k, v in klass.namesAndDescriptions(): if hasattr(v, 'getSignatureInfo'): self.methods.append(MethodDoc(v, 1)) else: self.attributes.append(AttributeDoc(k, v.__doc__)) def _createFromClass(self, klass): # Creates an APIDoc instance given a python class. # the class describes the API; it contains # methods, arguments and doc strings. # # The name of the API is deduced from the name # of the class. self.name = klass.__name__ self.doc = trim_doc_string(klass.__doc__) # Get info on methods and attributes, ignore special items self.attributes = [] self.methods = [] for k, v in klass.__dict__.items(): if k not in ('__extends__', '__doc__', '__constructor__'): if type(v) == types.FunctionType: self.methods.append(MethodDoc(v, 0)) else: self.attributes.append(AttributeDoc(k, v)) def SearchableText(self): """ The full text of the API, for indexing purposes. """ text = "%s %s" % (self.name, self.doc) for attribute in self.attributes: text = "%s %s" % (text, attribute.name) for method in self.methods: text = "%s %s %s" % (text, method.name, method.doc) return text view = DTMLFile('dtml/APIView', globals())
def _exec(self, bound_data, args, kw): getRequest().response.setHeader('X-Theme-Disabled', '1') return DTMLFile._exec(self, bound_data, args, kw)