Annotation of kupu/plone/plonelibrarytool.py, revision 1.1.1.1
1.1 dwinter 1: ##############################################################################
2: #
3: # Copyright (c) 2003-2005 Kupu Contributors. All rights reserved.
4: #
5: # This software is distributed under the terms of the Kupu
6: # License. See LICENSE.txt for license text. For a list of Kupu
7: # Contributors see CREDITS.txt.
8: #
9: ##############################################################################
10: """Plone Kupu library tool
11:
12: This module contains the Plone specific version of the Kupu library
13: tool.
14:
15: $Id: plonelibrarytool.py 15693 2005-08-05 14:14:33Z duncan $
16: """
17: import os
18: from ZODB.PersistentList import PersistentList
19: from ZODB.PersistentMapping import PersistentMapping
20: from AccessControl import ClassSecurityInfo
21: from OFS.SimpleItem import SimpleItem
22: import Globals
23: from Globals import InitializeClass
24:
25: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
26: from Products.CMFCore.utils import UniqueObject, getToolByName
27:
28: from Products.kupu.plone.librarytool import KupuLibraryTool
29: from Products.kupu.plone import permissions, scanner
30: from Products.kupu import kupu_globals
31: from Products.kupu.config import TOOLNAME, TOOLTITLE
32:
33: _default_libraries = (
34: dict(id="root",
35: title="string:Home",
36: uri="string:${portal_url}",
37: src="string:${portal_url}/kupucollection.xml",
38: icon="string:${portal_url}/misc_/CMFPlone/plone_icon"),
39: dict(id="current",
40: title="string:Current folder",
41: uri="string:${folder_url}",
42: src="string:${folder_url}/kupucollection.xml",
43: icon="string:${portal_url}/folder_icon.gif"),
44: dict(id="myitems",
45: title="string:My recent items",
46: uri="string:${portal_url}/kupumyitems.xml",
47: src="string:${portal_url}/kupumyitems.xml",
48: icon="string:${portal_url}/kupuimages/kupusearch_icon.gif"),
49: dict(id="recentitems",
50: title="string:Recent items",
51: uri="string:${portal_url}/kupurecentitems.xml",
52: src="string:${portal_url}/kupurecentitems.xml",
53: icon="string:${portal_url}/kupuimages/kupusearch_icon.gif")
54: )
55:
56: _default_resource_types = {
57: 'collection': ('Plone Site', 'Folder', 'Large Plone Folder'),
58: 'mediaobject': ('Image',),
59: 'linkable': ('Document', 'Image', 'File', 'News Item', 'Event')
60: }
61:
62: # Tidy up html by exlcluding lots of things.
63: _excluded_html = [
64: (('center', 'span', 'tt', 'big', 'small', 'u', 's', 'strike', 'basefont', 'font'), ()),
65: ((), ('dir','lang','valign','halign','border','frame','rules','cellspacing','cellpadding','bgcolor')),
66: (('table','th','td'),('width','height')),
67: ]
68:
69: # Default should list all styles used by Kupu
70: _style_whitelist = ['text-align', 'list-style-type', 'float']
71:
72: _default_paragraph_styles = (
73: "Heading|h2|Heading",
74: "Subheading|h3|Subheading",
75: "Formatted|pre",
76: )
77:
78: class PloneKupuLibraryTool(UniqueObject, SimpleItem, KupuLibraryTool):
79: """Plone specific version of the kupu library tool"""
80:
81: id = TOOLNAME
82: meta_type = "Kupu Library Tool"
83: title = TOOLTITLE
84: security = ClassSecurityInfo()
85:
86: # protect methods provided by super class KupuLibraryTool
87: security.declareProtected(permissions.QueryLibraries, "getLibraries",
88: "getPortalTypesForResourceType")
89: security.declareProtected(permissions.ManageLibraries, "addLibrary",
90: "deleteLibraries", "updateLibraries",
91: "moveUp", "moveDown")
92: security.declareProtected(permissions.ManageLibraries, "addResourceType",
93: "updateResourceTypes", "deleteResourceTypes")
94:
95: def __init__(self):
96: self._libraries = PersistentList()
97: self._res_types = PersistentMapping()
98: self.linkbyuid = True
99:
100: def manage_afterAdd(self, item, container):
101: # We load default values here, so __init__ can still be used
102: # in unit tests. Plus, it only makes sense to load these if
103: # we're being added to a Plone site anyway
104: for lib in _default_libraries:
105: self.addLibrary(**lib)
106: self._res_types.update(_default_resource_types)
107:
108: security.declareProtected('View', "getLinkbyuid")
109: def getLinkbyuid(self):
110: """Returns 'is linking by UID enabled'?"""
111: try:
112: return self.linkbyuid
113: except AttributeError:
114: return 1
115:
116: security.declareProtected('View', "getTableClassnames")
117: def getTableClassnames(self):
118: """Return a list of classnames supported in tables"""
119: try:
120: return self.table_classnames
121: except AttributeError:
122: return ('plain', 'listing', 'vertical listing', 'listing nosort')
123:
124: security.declareProtected('View', "getParagraphStyles")
125: def getParagraphStyles(self):
126: """Return a list of classnames supported in tables"""
127: try:
128: return self.paragraph_styles
129: except AttributeError:
130: return _default_paragraph_styles
131:
132: security.declareProtected('View', "getHtmlExclusions")
133: def getHtmlExclusions(self):
134: try:
135: return self.html_exclusions
136: except AttributeError:
137: self.html_exclusions = _excluded_html
138: return self.html_exclusions
139:
140: security.declareProtected('View', "getStyleWhitelist")
141: def getStyleWhitelist(self):
142: try:
143: return self.style_whitelist
144: except AttributeError:
145: self.style_whitelist = _style_whitelist
146: return self.style_whitelist
147:
148: security.declareProtected('View', "getClassBlacklist")
149: def getClassBlacklist(self):
150: return getattr(self, 'class_blacklist', [])
151:
152: security.declareProtected('View', "getClassBlacklist")
153: def installBeforeUnload(self):
154: return getattr(self, 'install_beforeunload', True)
155:
156: security.declareProtected('View', 'isKupuEnabled')
157: def isKupuEnabled(self, useragent='', allowAnonymous=False, REQUEST=None):
158: def numerics(s):
159: '''Convert a string into a tuple of all digit sequences
160: '''
161: seq = ['']
162: for c in s:
163: if c.isdigit():
164: seq[-1] = seq[-1] + c
165: elif seq[-1]:
166: seq.append('')
167: return tuple([ int(val) for val in seq if val])
168:
169: # First check whether the user actually wants kupu
170: pm = getToolByName(self, 'portal_membership')
171: if pm.isAnonymousUser() and not allowAnonymous:
172: return False
173:
174: user = pm.getAuthenticatedMember()
175: if user.getProperty('wysiwyg_editor').lower() != 'kupu':
176: return False
177:
178: # Then check whether their browser supports it.
179: if not useragent:
180: useragent = REQUEST['HTTP_USER_AGENT']
181:
182: if 'Opera' in useragent or 'BEOS' in useragent:
183: return False
184:
185: if not useragent.startswith('Mozilla/'):
186: return False
187:
188: try:
189: mozillaver = numerics(useragent[len('Mozilla/'):].split(' ')[0])
190: if mozillaver > (5,0):
191: return True
192: elif mozillaver == (5,0):
193: rv = useragent.find(' rv:')
194: if rv >= 0:
195: verno = numerics(useragent[rv+4:].split(')')[0])
196: return verno >= (1,3,1)
197:
198: MSIE = useragent.find('MSIE')
199: if MSIE >= 0:
200: verno = numerics(useragent[MSIE+4:].split(';')[0])
201: return verno >= (5,5)
202:
203: except:
204: # In case some weird browser makes the test code blow up.
205: pass
206: return False
207:
208: # ZMI views
209: manage_options = (SimpleItem.manage_options[1:] + (
210: dict(label='Config', action='kupu_config'),
211: dict(label='Libraries', action='zmi_libraries'),
212: dict(label='Resource types', action='zmi_resource_types'),
213: dict(label='Documentation', action='zmi_docs'),
214: dict(label='Status', action='sanity_check'),
215: ))
216:
217:
218: security.declarePublic('scanIds')
219: def scanIds(self):
220: """Finds the relevant source files and the doller/Id/dollar strings they contain"""
221: return scanner.scanIds()
222:
223: security.declarePublic('scanKWS')
224: def scanKWS(self):
225: """Check that kupu_wysiwyg_support is up to date"""
226: return scanner.scanKWS()
227:
228: security.declarePublic('docs')
229: def docs(self):
230: """Returns Kupu docs formatted as HTML"""
231: docpath = os.path.join(Globals.package_home(kupu_globals), 'doc')
232: f = open(os.path.join(docpath, 'PLONE2.txt'), 'r')
233: _docs = f.read()
234: return _docs
235:
236: security.declareProtected(permissions.ManageLibraries, "zmi_docs")
237: zmi_docs = PageTemplateFile("zmi_docs.pt", globals())
238: zmi_docs.title = 'kupu configuration documentation'
239:
240: security.declareProtected(permissions.ManageLibraries, "sanity_check")
241: sanity_check = PageTemplateFile("sanity_check.pt", globals())
242: sanity_check.title = 'kupu status'
243:
244: security.declareProtected(permissions.ManageLibraries, "kupu_config")
245: kupu_config = PageTemplateFile("kupu_config.pt", globals())
246: kupu_config.title = 'kupu configuration'
247:
248: security.declareProtected(permissions.ManageLibraries, "zmi_libraries")
249: zmi_libraries = PageTemplateFile("libraries.pt", globals())
250: zmi_libraries.title = 'kupu configuration'
251:
252: security.declareProtected(permissions.ManageLibraries, "zmi_resource_types")
253: zmi_resource_types = PageTemplateFile("resource_types.pt", globals())
254: zmi_resource_types.title = 'kupu configuration'
255:
256: security.declareProtected(permissions.ManageLibraries,
257: "zmi_get_libraries")
258: def zmi_get_libraries(self):
259: """Return the libraries sequence for the ZMI view"""
260: #return ()
261: def text(value):
262: return getattr(value, 'text', value)
263: return [dict([(key, text(value)) for key, value in lib.items()])
264: for lib in self._libraries]
265:
266: security.declareProtected(permissions.ManageLibraries,
267: "zmi_add_library")
268: def zmi_add_library(self, id, title, uri, src, icon, REQUEST):
269: """Add a library through the ZMI"""
270: self.addLibrary(id, title, uri, src, icon)
271: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
272:
273: security.declareProtected(permissions.ManageLibraries,
274: "zmi_update_libraries")
275: def zmi_update_libraries(self, libraries, REQUEST):
276: """Update libraries through the ZMI"""
277: self.updateLibraries(libraries)
278: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
279:
280: security.declareProtected(permissions.ManageLibraries,
281: "zmi_delete_libraries")
282: def zmi_delete_libraries(self, indices, REQUEST):
283: """Delete libraries through the ZMI"""
284: self.deleteLibraries(indices)
285: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
286:
287: security.declareProtected(permissions.ManageLibraries,
288: "zmi_move_up")
289: def zmi_move_up(self, indices, REQUEST):
290: """Move libraries up through the ZMI"""
291: self.moveUp(indices)
292: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
293:
294: security.declareProtected(permissions.ManageLibraries,
295: "zmi_move_down")
296: def zmi_move_down(self, indices, REQUEST):
297: """Move libraries down through the ZMI"""
298: self.moveDown(indices)
299: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_libraries')
300:
301: security.declarePublic("zmi_get_default_library")
302: def zmi_get_default_library(self):
303: """Return the default selected library for the ZMI view"""
304: return getattr(self, '_default_library', '')
305:
306: security.declareProtected(permissions.ManageLibraries,
307: "zmi_set_default_library")
308: def zmi_set_default_library(self, defid=''):
309: """Return the libraries sequence for the ZMI view"""
310: self._default_library = defid
311:
312: security.declareProtected(permissions.ManageLibraries,
313: "zmi_get_type_mapping")
314: def zmi_get_type_mapping(self):
315: """Return the type mapping for the ZMI view"""
316: return [(res_type, tuple(portal_type)) for res_type, portal_type
317: in self._res_types.items()]
318:
319: security.declareProtected(permissions.ManageLibraries,
320: "zmi_add_resource_type")
321: def zmi_add_resource_type(self, resource_type, portal_types, REQUEST):
322: """Add resource type through the ZMI"""
323: self.addResourceType(resource_type, portal_types)
324: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_resource_types')
325:
326: security.declareProtected(permissions.ManageLibraries,
327: "zmi_update_resource_types")
328: def zmi_update_resource_types(self, type_info, REQUEST):
329: """Update resource types through the ZMI"""
330: self.updateResourceTypes(type_info)
331: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_resource_types')
332:
333: security.declareProtected(permissions.ManageLibraries,
334: "zmi_delete_resource_types")
335: def zmi_delete_resource_types(self, resource_types, REQUEST):
336: """Delete resource types through the ZMI"""
337: self.deleteResourceTypes(resource_types)
338: REQUEST.RESPONSE.redirect(self.absolute_url() + '/zmi_resource_types')
339:
340: security.declareProtected(permissions.ManageLibraries,
341: "configure_kupu")
342: def configure_kupu(self,
343: linkbyuid, table_classnames, html_exclusions, style_whitelist, class_blacklist,
344: installBeforeUnload=None, parastyles=None,
345: REQUEST=None):
346: """Delete resource types through the ZMI"""
347: self.linkbyuid = int(linkbyuid)
348: self.table_classnames = table_classnames
349: if installBeforeUnload is not None:
350: self.install_beforeunload = bool(installBeforeUnload)
351: if parastyles:
352: self.paragraph_styles = [ line.strip() for line in parastyles if line.strip() ]
353:
354: newex = html_exclusions[-1]
355:
356: html_exclusions = [ (tuple(h.get('tags', ())), tuple(h.get('attributes', ())))
357: for h in html_exclusions[:-1] if h.get('keep')]
358:
359: tags, attr = newex.get('tags', ()), newex.get('attributes', ())
360: if tags or attr:
361: tags = tuple(tags.replace(',',' ').split())
362: attr = tuple(attr.replace(',',' ').split())
363: html_exclusions.append((tags, attr))
364:
365: self.html_exclusions = html_exclusions
366:
367: self.style_whitelist = list(style_whitelist)
368: self.class_blacklist = list(class_blacklist)
369:
370: if REQUEST:
371: REQUEST.RESPONSE.redirect(self.absolute_url() + '/kupu_config')
372:
373: InitializeClass(PloneKupuLibraryTool)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>