/usr/share/pyshared/zope/browsermenu/menu.py is in python-zope.browsermenu 3.9.1-0ubuntu4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | ##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Menu implementation code
$Id: menu.py 103270 2009-08-27 13:56:02Z nadako $
"""
__docformat__ = "reStructuredText"
import sys
from zope.component import getAdapters, getUtility
from zope.interface import Interface, implements, providedBy
from zope.interface.interfaces import IInterface
from zope.pagetemplate.engine import Engine
from zope.publisher.browser import BrowserView
from zope.security import canAccess, checkPermission
from zope.security.interfaces import Forbidden, Unauthorized
from zope.security.proxy import removeSecurityProxy
from zope.traversing.publicationtraverse import PublicationTraverser
from zope.browsermenu.interfaces import IBrowserMenu, IMenuItemType
from zope.browsermenu.interfaces import IBrowserMenuItem, IBrowserSubMenuItem
from zope.browsermenu.interfaces import IMenuAccessView
class BrowserMenu(object):
"""Browser Menu"""
implements(IBrowserMenu)
def __init__(self, id, title=u'', description=u''):
self.id = id
self.title = title
self.description = description
def getMenuItemType(self):
return getUtility(IMenuItemType, self.id)
def getMenuItems(self, object, request):
"""Return menu item entries in a TAL-friendly form."""
result = []
for name, item in getAdapters((object, request),
self.getMenuItemType()):
if item.available():
result.append(item)
# Now order the result. This is not as easy as it seems.
#
# (1) Look at the interfaces and put the more specific menu entries
# to the front.
# (2) Sort unambigious entries by order and then by title.
ifaces = list(providedBy(removeSecurityProxy(object)).__iro__)
max_key = len(ifaces)
def iface_index(item):
iface = item._for
if not iface:
iface = Interface
if IInterface.providedBy(iface):
return ifaces.index(iface)
if isinstance(removeSecurityProxy(object), item._for):
# directly specified for class, this goes first.
return -1
# no idea. This goes last.
return max_key
result = [(iface_index(item), item.order, item.title, item)
for item in result]
result.sort()
result = [
{'title': title,
'description': item.description,
'action': item.action,
'selected': (item.selected() and u'selected') or u'',
'icon': item.icon,
'extra': item.extra,
'submenu': (IBrowserSubMenuItem.providedBy(item) and
getMenu(item.submenuId, object, request)) or None}
for index, order, title, item in result]
return result
class BrowserMenuItem(BrowserView):
"""Browser Menu Item Class"""
implements(IBrowserMenuItem)
title = u''
description = u''
action = u''
extra = None
order = 0
permission = None
filter = None
icon = None
_for = Interface
def available(self):
# Make sure we have the permission needed to access the menu's action
if self.permission is not None:
# If we have an explicit permission, check that we
# can access it.
if not checkPermission(self.permission, self.context):
return False
elif self.action != u'':
# Otherwise, test access by attempting access
path = self.action
l = self.action.find('?')
if l >= 0:
path = self.action[:l]
traverser = PublicationTraverser()
try:
view = traverser.traverseRelativeURL(
self.request, self.context, path)
except (Unauthorized, Forbidden, LookupError):
return False
else:
# we're assuming that view pages are callable
# this is a pretty sound assumption
if not canAccess(view, '__call__'):
return False
# Make sure that we really want to see this menu item
if self.filter is not None:
try:
include = self.filter(Engine.getContext(
context = self.context,
nothing = None,
request = self.request,
modules = sys.modules,
))
except Unauthorized:
return False
else:
if not include:
return False
return True
def selected(self):
request_url = self.request.getURL()
normalized_action = self.action
if self.action.startswith('@@'):
normalized_action = self.action[2:]
if request_url.endswith('/'+normalized_action):
return True
if request_url.endswith('/++view++'+normalized_action):
return True
if request_url.endswith('/@@'+normalized_action):
return True
return False
class BrowserSubMenuItem(BrowserMenuItem):
"""Browser Menu Item Base Class"""
implements(IBrowserSubMenuItem)
submenuId = None
def selected(self):
if self.action is u'':
return False
return super(BrowserSubMenuItem, self).selected()
def getMenu(id, object, request):
"""Return menu item entries in a TAL-friendly form."""
menu = getUtility(IBrowserMenu, id)
return menu.getMenuItems(object, request)
def getFirstMenuItem(id, object, request):
"""Get the first item of a menu."""
items = getMenu(id, object, request)
if items:
return items[0]
return None
class MenuAccessView(BrowserView):
"""A view allowing easy access to menus."""
implements(IMenuAccessView)
def __getitem__(self, menuId):
return getMenu(menuId, self.context, self.request)
|