I have a couple of small patches here that allow you to override the manage options (i.e. manage_tabs, manage_page_header, manage_page_footer) in the ZODB. This simple patch seems a nice way to provide this option without breaking compatibility with the current system. It patches the App/Management.py and OFS/Application.py file. This also causes risk of locking yourself out of management, there are 2 ways around this problem; First is to ftp/webDAV in and delete the offending file. I've also added a SUPPRESS_CUST_MANAGE option, (for example abc/SUPPRESS_CUST_MANAGE/manage_main) when this is in the path it will stop use the core zope management interface instead of the custom ones. The problem with this is that i get a "<Override instance at 8189638>" instead of the DTML code that should be in place of the object. As well this option IS NOT thread safe. I'm looking for a better solution but i can't think of one? What do people think of this patch? Is there a better way to do this? Is it possible to get a patch similar to this integrated into the Zope core because it's an extremely useful. Hope to hear from you soon Mithro ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## __doc__='''Application support $Id: Application.py,v 1.135.12.8 2001/04/07 16:33:51 jim Exp $''' __version__='$Revision: 1.135.12.8 $'[11:-2] import Globals,Folder,os,sys,App.Product, App.ProductRegistry, misc_ import time, traceback, os, string, Products from string import strip, lower, find, rfind, join from DateTime import DateTime from AccessControl.User import UserFolder from App.ApplicationManager import ApplicationManager from webdav.NullResource import NullResource from FindSupport import FindSupport from urllib import quote from cStringIO import StringIO from AccessControl.PermissionRole import PermissionRole from App.ProductContext import ProductContext from App.Management import RealNavigation, RealTabs from misc_ import Misc_ import ZDOM from zLOG import LOG, ERROR, WARNING, INFO from HelpSys.HelpSys import HelpSys _standard_error_msg='''\ <dtml-var standard_html_header> <dtml-if error_message> <dtml-var error_message> <dtml-else> <H2>Site Error</H2> <P>An error was encountered while publishing this resource. </P> <P> <STRONG>Error Type: <dtml-var error_type html_quote></STRONG><BR> <STRONG>Error Value: <dtml-var error_value html_quote></STRONG><BR> </P> <HR NOSHADE> <P>Troubleshooting Suggestions</P> <UL> <dtml-if "error_type in ('KeyError','NameError')"> <LI>This resource may be trying to reference a nonexistent object or variable <STRONG><dtml-var error_value></STRONG>.</LI> </dtml-if> <LI>The URL may be incorrect.</LI> <LI>The parameters passed to this resource may be incorrect.</LI> <LI>A resource that this resource relies on may be encountering an error.</LI> </UL> <P>For more detailed information about the error, please refer to the HTML source for this page. </P> <P>If the error persists please contact the site maintainer. Thank you for your patience. </P> <dtml-comment> Here, events like logging and other actions may also be performed, such as sending mail automatically to the administrator. </dtml-comment> </dtml-if> <dtml-var standard_html_footer>''' class Application(Globals.ApplicationDefaultPermissions, ZDOM.Root, Folder.Folder, App.ProductRegistry.ProductRegistry, FindSupport, RealNavigation, RealTabs): """Top-level system object""" title ='Zope' #__roles__=['Manager', 'Anonymous'] __defined_roles__=('Manager','Anonymous','Owner') web__form__method='GET' isTopLevelPrincipiaApplicationObject=1 _isBeingUsedAsAMethod_=0 # Create the help system object HelpSys=HelpSys('HelpSys') p_=misc_.p_ misc_=misc_.misc_ _reserved_names=('standard_html_header', 'standard_html_footer', 'standard_error_message', 'Control_Panel') # This class-default __allow_groups__ ensures that the # emergency user can still access the system if the top-level # UserFolder is deleted. This is necessary to allow people # to replace the top-level UserFolder object. __allow_groups__=UserFolder() def title_and_id(self): return self.title def title_or_id(self): return self.title def __init__(self): # Initialize users uf=UserFolder() self.__allow_groups__=uf self._setObject('acl_users', uf) # Initialize control panel cpl=ApplicationManager() cpl._init() self._setObject('Control_Panel', cpl) # Note that this may happen before products are # installed, so we have to use addDocument as stand-alone. import Document Document.manage_addDocument( self, 'standard_html_header', 'Standard Html Header', '<HTML><HEAD><TITLE><dtml-var title_or_id>' \ '</TITLE></HEAD><BODY BGCOLOR="#FFFFFF">') Document.manage_addDocument( self, 'standard_html_footer', 'Standard Html Footer', '</BODY></HTML>') Document.manage_addDocument( self, 'standard_error_message', 'Standard Error Message', _standard_error_msg) def id(self): try: return self.REQUEST['SCRIPT_NAME'][1:] except: return self.title def __class_init__(self): Globals.default__class_init__(self) def PrincipiaRedirect(self,destination,URL1): """Utility function to allow user-controlled redirects""" if find(destination,'//') >= 0: raise 'Redirect', destination raise 'Redirect', ("%s/%s" % (URL1, destination)) Redirect=ZopeRedirect=PrincipiaRedirect def __bobo_traverse__(self, REQUEST, name=None): try: return getattr(self, name) except AttributeError: pass try: return self[name] except KeyError: pass method=REQUEST.get('REQUEST_METHOD', 'GET') if not method in ('GET', 'POST'): return NullResource(self, name, REQUEST).__of__(self) # Waaa. unrestrictedTraverse calls us with a fake REQUEST. # There is proabably a better fix for this. try: REQUEST.RESPONSE.notFoundError("%s\n%s" % (name, method)) except AttributeError: raise KeyError, name def PrincipiaTime(self, *args): """Utility function to return current date/time""" return apply(DateTime, args) ZopeTime=PrincipiaTime ZopeAttributionButton__roles__=None def ZopeAttributionButton(self): """Returns an HTML fragment that displays the 'powered by zope' button along with a link to the Zope site.""" return '<a href="http://www.zope.org/Credits" target="_top"><img ' \ 'src="%s/p_/ZopeButton" width="115" height="50" ' \ 'border="0" alt="Powered by Zope" /></a>' % self.REQUEST.BASE1 def DELETE(self, REQUEST, RESPONSE): """Delete a resource object.""" self.dav__init(REQUEST, RESPONSE) raise 'Forbidden', 'This resource cannot be deleted.' def MOVE(self, REQUEST, RESPONSE): """Move a resource to a new location.""" self.dav__init(REQUEST, RESPONSE) raise 'Forbidden', 'This resource cannot be moved.' test_url___allow_groups__=None test_url=ZopeAttributionButton def absolute_url(self, relative=0): """Return an absolute url to the object. Note that the url will reflect the acquisition path of the object if the object has been acquired.""" if relative: return '' return self.aq_acquire('REQUEST')['BASE1'] def getPhysicalPath(self): '''Returns a path that can be used to access this object again later, for example in a copy/paste operation. Designed to be used with getPhysicalRoot(). ''' # We're at the base of the path. return ('',) def getPhysicalRoot(self): return self fixupZClassDependencies__roles__=() def fixupZClassDependencies(self, rebuild=0): # Note that callers should not catch exceptions from this method # to ensure that the transaction gets aborted if the registry # cannot be rebuilt for some reason. Returns true if any ZClasses # were registered as a result of the call or the registry was # rebuilt. jar=self._p_jar result=0 if rebuild: import BTree jar.root()['ZGlobals']=BTree.BTree() result=1 zglobals =jar.root()['ZGlobals'] reg_has_key=zglobals.has_key products=self.Control_Panel.Products for product in products.objectValues(): items=list(product.objectItems()) finished=[] idx=0 while(idx < len(items)): name, ob = items[idx] base=getattr(ob, 'aq_base', ob) if base in finished: idx=idx+1 continue finished.append(base) try: # Try to re-register ZClasses if they need it. if hasattr(ob, '_register') and hasattr(ob, '_zclass_'): class_id=getattr(ob._zclass_, '__module__', None) if class_id and not reg_has_key(class_id): ob._register() result=1 if not rebuild: LOG('Zope', INFO, 'Registered ZClass: %s' % ob.id ) # Include subobjects. if hasattr(ob, 'objectItems'): m = list(ob.objectItems()) items.extend(m) # Try to find ZClasses-in-ZClasses. if hasattr(ob, 'propertysheets'): ps = ob.propertysheets if (hasattr(ps, 'methods') and hasattr(ps.methods, 'objectItems')): m = list(ps.methods.objectItems()) items.extend(m) except: LOG('Zope', WARNING, 'Broken objects exist in product %s.' % product.id) idx = idx + 1 return result checkGlobalRegistry__roles__=() def checkGlobalRegistry(self): """Check the global (zclass) registry for problems, which can be caused by things like disk-based products being deleted. Return true if a problem is found""" try: keys=list(self._p_jar.root()['ZGlobals'].keys()) except: return 1 return 0 class Expired(Globals.Persistent): icon='p_/broken' def __setstate__(self, s={}): dict=self.__dict__ if s.has_key('id'): dict['id']=s['id'] elif s.has_key('__name__'): dict['id']=s['__name__'] else: dict['id']='Unknown' dict['title']='** Expired **' def __save__(self): pass __inform_commit__=__save__ def initialize(app): # Initialize the application # Initialize the cache: app.Control_Panel.initialize_cache() # The following items marked b/c are backward compatibility hacks # which make sure that expected system objects are added to the # bobobase. This is required because the bobobase in use may pre- # date the introduction of certain system objects such as those # which provide Lever support. # b/c: Ensure that Control Panel exists. if not hasattr(app, 'Control_Panel'): cpl=ApplicationManager() cpl._init() app._setObject('Control_Panel', cpl) get_transaction().note('Added Control_Panel') get_transaction().commit() # b/c: Ensure that a ProductFolder exists. if not hasattr(app.Control_Panel.aq_base, 'Products'): app.Control_Panel.Products=App.Product.ProductFolder() get_transaction().note('Added Control_Panel.Products') get_transaction().commit() # b/c: Ensure that std err msg exists. if not hasattr(app, 'standard_error_message'): import Document Document.manage_addDocument( app, 'standard_error_message', 'Standard Error Message', _standard_error_msg) get_transaction().note('Added standard_error_message') get_transaction().commit() # b/c: Ensure that Owner role exists. if hasattr(app, '__ac_roles__') and not ('Owner' in app.__ac_roles__): app.__ac_roles__=app.__ac_roles__ + ('Owner',) get_transaction().note('Added Owner role') get_transaction().commit() # Make sure we have Globals root=app._p_jar.root() if not root.has_key('ZGlobals'): import BTree app._p_jar.root()['ZGlobals']=BTree.BTree() get_transaction().note('Added Globals') get_transaction().commit() # Install the initial user. if hasattr(app, 'acl_users'): users = app.acl_users if hasattr(users, '_createInitialUser'): app.acl_users._createInitialUser() get_transaction().note('Created initial user') get_transaction().commit() install_products(app) # Note that the code from here on only runs if we are not a ZEO # client, or if we are a ZEO client and we've specified by way # of env variable that we want to force products to load. if (os.environ.get('ZEO_CLIENT') and not os.environ.get('FORCE_PRODUCT_LOAD')): return # Check for dangling pointers (broken zclass dependencies) in the # global class registry. If found, rebuild the registry. Note that # if the check finds problems but fails to successfully rebuild the # registry we abort the transaction so that we don't leave it in an # indeterminate state. did_fixups=0 bad_things=0 try: if app.checkGlobalRegistry(): app.fixupZClassDependencies(rebuild=1) did_fixups=1 LOG('Zope', INFO, 'A broken ZClass dependency was found in the global ' \ 'class registry. This is probably due to a product ' \ 'being uninstalled. The registry has successfully ' \ 'been rebuilt.') get_transaction().note('Rebuilt global product registry') get_transaction().commit() except: bad_things=1 LOG('Zope', ERROR, 'A problem was found in the global product registry but ' 'the attempt to rebuild the registry failed.', error=sys.exc_info()) get_transaction().abort() # Now we need to see if any (disk-based) products were installed # during intialization. If so (and the registry has no errors), # there may still be zclasses dependent on a base class in the # newly installed product that were previously broken and need to # be fixed up. If any really Bad Things happened (dangling pointers # were found in the registry but it couldn't be rebuilt), we don't # try to do anything to avoid making the problem worse. if (not did_fixups) and (not bad_things): # App.Product.initializeProduct will set this if a disk-based # product was added or updated and we are not a ZEO client. if getattr(Globals, '__disk_product_installed__', 0): try: if app.fixupZClassDependencies(): get_transaction().commit() except: LOG('Zope', ERROR, 'Attempt to fixup ZClass dependencies after detecting ' \ 'an updated disk-based product failed.', error=sys.exc_info()) get_transaction().abort() def import_products(_st=type('')): # Try to import each product, checking for and catching errors. path_join=os.path.join isdir=os.path.isdir exists=os.path.exists DictType=type({}) global_dict=globals() silly=('__doc__',) modules=sys.modules have_module=modules.has_key done={} for product_dir in Products.__path__: product_names=os.listdir(product_dir) product_names.sort() for product_name in product_names: if done.has_key(product_name): continue done[product_name]=1 package_dir=path_join(product_dir, product_name) if not isdir(package_dir): continue if not exists(path_join(package_dir, '__init__.py')): if not exists(path_join(package_dir, '__init__.pyc')): continue pname="Products.%s" % product_name try: product=__import__(pname, global_dict, global_dict, silly) if hasattr(product, '__module_aliases__'): for k, v in product.__module_aliases__: if not have_module(k): if type(v) is _st and have_module(v): v=modules[v] modules[k]=v except: LOG('Zope',ERROR,'Couldn\'t import %s' % pname, error=sys.exc_info()) f=StringIO() traceback.print_exc(100,f) f=f.getvalue() try: modules[pname].__import_error__=f except: pass def install_products(app): # Install a list of products into the basic folder class, so # that all folders know about top-level objects, aka products path_join=os.path.join isdir=os.path.isdir exists=os.path.exists DictType=type({}) from Folder import Folder folder_permissions={} for p in Folder.__ac_permissions__: permission, names = p[:2] folder_permissions[permission]=names meta_types=[] global_dict=globals() silly=('__doc__',) done={} get_transaction().note('Prior to product installs') get_transaction().commit() for product_dir in Products.__path__: product_names=os.listdir(product_dir) product_names.sort() for product_name in product_names: # For each product, we will import it and try to call the # intialize() method in the product __init__ module. If # the method doesnt exist, we put the old-style information # together and do a default initialization. if done.has_key(product_name): continue done[product_name]=1 package_dir=path_join(product_dir, product_name) __traceback_info__=product_name if not isdir(package_dir): continue if not exists(path_join(package_dir, '__init__.py')): if not exists(path_join(package_dir, '__init__.pyc')): continue try: product=__import__("Products.%s" % product_name, global_dict, global_dict, silly) # Install items into the misc_ namespace, used by products # and the framework itself to store common static resources # like icon images. misc_=pgetattr(product, 'misc_', {}) if misc_: if type(misc_) is DictType: misc_=Misc_(product_name, misc_) Application.misc_.__dict__[product_name]=misc_ # Here we create a ProductContext object which contains # information about the product and provides an interface # for registering things like classes and help topics that # should be associated with that product. Products are # expected to implement a method named 'initialize' in # their __init__.py that takes the ProductContext as an # argument. productObject=App.Product.initializeProduct( product, product_name, package_dir, app) context=ProductContext(productObject, app, product) # Look for an 'initialize' method in the product. If it does # not exist, then this is an old product that has never been # updated. In that case, we will analyze the product and # build up enough information to do initialization manually. initmethod=pgetattr(product, 'initialize', None) if initmethod is not None: initmethod(context) # Support old-style product metadata. Older products may # define attributes to name their permissions, meta_types, # constructors, etc. permissions={} new_permissions={} for p in pgetattr(product, '__ac_permissions__', ()): permission, names, default = ( tuple(p)+('Manager',))[:3] if names: for name in names: permissions[name]=permission elif not folder_permissions.has_key(permission): new_permissions[permission]=() for meta_type in pgetattr(product, 'meta_types', ()): # Modern product initialization via a ProductContext # adds 'product' and 'permission' keys to the meta_type # mapping. We have to add these here for old products. pname=permissions.get(meta_type['action'], None) if pname is not None: meta_type['permission']=pname meta_type['product']=productObject.id meta_types.append(meta_type) for name,method in pgetattr( product, 'methods', {}).items(): if not hasattr(Folder, name): setattr(Folder, name, method) if name[-9:]!='__roles__': # not Just setting roles if (permissions.has_key(name) and not folder_permissions.has_key( permissions[name])): permission=permissions[name] if new_permissions.has_key(permission): new_permissions[permission].append(name) else: new_permissions[permission]=[name] if new_permissions: new_permissions=new_permissions.items() for permission, names in new_permissions: folder_permissions[permission]=names new_permissions.sort() Folder.__dict__['__ac_permissions__']=tuple( list(Folder.__ac_permissions__)+new_permissions) if (os.environ.get('ZEO_CLIENT') and not os.environ.get('FORCE_PRODUCT_LOAD')): # we don't want to install products from clients # (unless FORCE_PRODUCT_LOAD is defined). get_transaction().abort() else: get_transaction().note('Installed product '+product_name) get_transaction().commit() except: LOG('Zope',ERROR,'Couldn\'t install %s' % product_name, error=sys.exc_info()) get_transaction().abort() Products.meta_types=Products.meta_types+tuple(meta_types) Globals.default__class_init__(Folder) def pgetattr(product, name, default=install_products, __init__=0): if not __init__ and hasattr(product, name): return getattr(product, name) if hasattr(product, '__init__'): product=product.__init__ if hasattr(product, name): return getattr(product, name) if default is not install_products: return default raise AttributeError, name ############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## """Standard management interface support $Id: Management.py,v 1.46.2.1 2001/01/16 22:56:53 evan Exp $""" __version__='$Revision: 1.46.2.1 $'[11:-2] import sys, Globals, ExtensionClass, urllib from Dialogs import MessageDialog from Globals import DTMLFile, HTMLFile from string import split, join, find from AccessControl import getSecurityManager import Acquisition class Tabs(ExtensionClass.Base): """Mix-in provides management folder tab support.""" manage_options =() filtered_manage_options__roles__=None def filtered_manage_options(self, REQUEST=None): validate=getSecurityManager().validate result=[] try: options=tuple(self.manage_options) except: options=tuple(self.manage_options()) for d in options: filter=d.get('filter', None) if filter is not None and not filter(self): continue path=d.get('path', None) if path is None: path=d['action'] o=self.unrestrictedTraverse(path, None) if o is None: continue try: if validate(container=self, value=o): result.append(d) except: if not hasattr(o, '__roles__'): result.append(d) return result manage_workspace__roles__=('Anonymous',) def manage_workspace(self, REQUEST): """Dispatch to first interface in manage_options """ options=self.filtered_manage_options(REQUEST) try: m=options[0]['action'] if m=='manage_workspace': raise TypeError except: raise 'Unauthorized', ( 'You are not authorized to view this object.<p>') if find(m,'/'): raise 'Redirect', ( "%s/%s" % (REQUEST['URL1'], m)) return getattr(self, m)(self, REQUEST) def tabs_path_default(self, REQUEST, # Static var unquote=urllib.unquote, ): steps = REQUEST._steps[:-1] script = REQUEST['BASEPATH1'] linkpat = '<a href="%s/manage_workspace">%s</a>' out = [] url = linkpat % (script, ' /') if not steps: return url last = steps.pop() for step in steps: script = '%s/%s' % (script, step) out.append(linkpat % (script, unquote(step))) out.append(unquote(last)) return '%s%s' % (url, join(out,'/')) def tabs_path_info(self, script, path, # Static vars quote=urllib.quote, ): out=[] while path[:1]=='/': path=path[1:] while path[-1:]=='/': path=path[:-1] while script[:1]=='/': script=script[1:] while script[-1:]=='/': script=script[:-1] path=split(path,'/')[:-1] if script: path=[script]+path if not path: return '' script='' last=path[-1] del path[-1] for p in path: script="%s/%s" % (script, quote(p)) out.append('<a href="%s/manage_workspace">%s</a>' % (script, p)) out.append(last) return join(out, '/') class RealTabs(ExtensionClass.Base): manage_tabs__roles__=('Anonymous',) manage_tabs=DTMLFile('dtml/manage_tabs', globals()) class Navigation(ExtensionClass.Base): pass class RealNavigation(ExtensionClass.Base): """Basic navigation UI support""" __ac_permissions__=( ('View management screens', ('manage', 'manage_menu', 'manage_top_frame', 'manage_page_header', 'manage_page_footer', )), ) manage =DTMLFile('dtml/manage', globals()) manage_menu =DTMLFile('dtml/menu', globals()) manage_top_frame =DTMLFile('dtml/manage_top_frame', globals()) manage_page_header=DTMLFile('dtml/manage_page_header', globals()) manage_page_footer=DTMLFile('dtml/manage_page_footer', globals()) manage_form_title =DTMLFile('dtml/manage_form_title', globals(), form_title='Add Form', help_product=None, help_topic=None) manage_form_title._setFuncSignature( varnames=('form_title', 'help_product', 'help_topic') ) manage_form_title__roles__ = None zope_quick_start=DTMLFile('dtml/zope_quick_start', globals()) zope_quick_start__roles__=None manage_copyright=DTMLFile('dtml/copyright', globals()) manage_copyright__roles__ = None manage_zmi_logout__roles__ = None def manage_zmi_logout(self, REQUEST, RESPONSE): """Logout current user""" p = getattr(REQUEST, '_logout_path', None) if p is not None: return apply(self.restrictedTraverse(p)) realm=RESPONSE.realm RESPONSE.setStatus(401) RESPONSE.setHeader('WWW-Authenticate', 'basic realm="%s"' % realm, 1) RESPONSE.setBody("""<html> <head><title>Logout</title></head> <body> <p> You have been logged out. </p> </body> </html>""") return manage_zmi_prefs=DTMLFile('dtml/manage_zmi_prefs', globals()) manage_zmi_prefs__roles__ = None file = DTMLFile('dtml/manage_page_style.css', globals()) setattr(RealNavigation, 'manage_page_style.css', file) setattr(RealNavigation, 'manage_page_style.css__roles__', None) class Override(Acquisition.Implicit, RealNavigation, RealTabs): def __bobo_traverse__(self, request, key): self._v_bit = getattr(self, key, None) return self._v_bit setattr(Tabs, 'SUPPRESS_CUST_MANAGE', Override()) setattr(Navigation, 'SUPPRESS_CUST_MANAGE', Override()) Globals.default__class_init__(Tabs) Globals.default__class_init__(Navigation)