Log message for revision 40698: This version is now fully functional and without dependencies from Products.PageTemplates
Changed: U Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py D Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py.scary -=- Modified: Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py =================================================================== --- Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py 2005-12-11 11:21:09 UTC (rev 40697) +++ Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py 2005-12-11 12:02:36 UTC (rev 40698) @@ -16,36 +16,41 @@ __version__='$Revision: 1.48 $'[11:-2] import re -from urllib import quote -import os, AccessControl, Acquisition +import os +import Acquisition from Globals import ImageFile, package_home, InitializeClass from OFS.SimpleItem import SimpleItem from OFS.content_types import guess_content_type from DateTime.DateTime import DateTime from Shared.DC.Scripts.Script import Script from Shared.DC.Scripts.Signature import FuncCode -from AccessControl import getSecurityManager from OFS.History import Historical, html_diff from OFS.Cache import Cacheable from OFS.Traversable import Traversable from OFS.PropertyManager import PropertyManager -from Products.PageTemplates.Expressions import SecureModuleImporter -from Products.PageTemplates.PageTemplateFile import PageTemplateFile - -from AccessControl import Unauthorized +from AccessControl import getSecurityManager, safe_builtins, ClassSecurityInfo from AccessControl.Permissions import view, ftp_access, change_page_templates, view_management_screens from webdav.Lockable import ResourceLockedError from webdav.WriteLockInterface import WriteLockInterface - from zope.pagetemplate.pagetemplate import PageTemplate -#from zope.pagetemplate.pagetemplatefile import PageTemplateFile # regular expression to extract the encoding from the XML preamble encoding_reg= re.compile('<\?xml.*?encoding="(.*?)".*?\?>', re.M) + +class SecureModuleImporter: + __allow_access_to_unprotected_subobjects__ = 1 + def __getitem__(self, module): + mod = safe_builtins['__import__'](module) + path = module.split('.') + for name in path[1:]: + mod = getattr(mod, name) + return mod + + class Src(Acquisition.Explicit): """ I am scary code """ @@ -64,6 +69,7 @@ def sniffEncoding(text, default_encoding='utf-8'): """ try to determine the encoding from html or xml """ + # XXX: look at pagetemplates.py (BOM!!!) if text.startswith('<?xml'): mo = encoding_reg.search(text) if mo: @@ -101,12 +107,13 @@ {'id':'expand', 'type':'boolean', 'mode': 'w'}, ) - security = AccessControl.ClassSecurityInfo() + security = ClassSecurityInfo() security.declareObjectProtected(view) security.declareProtected(view, '__call__') def __init__(self, id, text=None, content_type=None, encoding='utf-8'): self.id = id + self.expand = 0 self.ZBindings_edit(self._default_bindings) self.pt_edit(text, content_type, encoding) @@ -124,15 +131,8 @@ def pt_edit(self, text, content_type, encoding='utf-8'): text = text.strip() -# if content_type == 'text/html': -# if not text.startswith('<?xml'): -# # not XHTML -> convert it to unicode -# text = unicode(text, encoding) - if not isinstance(text, unicode): text = unicode(text, encoding) - - print content_type, type(text),repr(text) self.ZCacheable_invalidate() PageTemplate.pt_edit(self, text, content_type) @@ -238,7 +238,7 @@ 'options': {}, 'root': root, 'request': getattr(root, 'REQUEST', None), - 'modules': SecureModuleImporter, + 'modules': SecureModuleImporter(), } return c @@ -258,7 +258,7 @@ except AttributeError: pass - security=getSecurityManager() + security = AccessControl.getSecurityManager() bound_names['user'] = security.getUser() # Retrieve the value from the cache. @@ -332,6 +332,9 @@ def document_src(self, REQUEST=None, RESPONSE=None): """Return expanded document source.""" + print 'src', self.read() + + if RESPONSE is not None: RESPONSE.setHeader('Content-Type', 'text/plain') if REQUEST is not None and REQUEST.get('raw'): @@ -363,15 +366,10 @@ def wl_isLocked(self): return 0 - security.declareProtected(view_management_screens, 'source_dot_xml') + security.declareProtected(view_management_screens, 'getSource') + getSource = Src() source_dot_xml = Src() - security.declareProtected(view_management_screens, 'pt_editForm') - pt_editForm = PageTemplateFile('pt/ptEdit.pt', globals()) - pt_editForm.__name__ = 'pt_editForm' - manage = manage_main = pt_editForm - - InitializeClass(ZPT) @@ -379,22 +377,31 @@ setattr(ZPT, 'source.html', ZPT.source_dot_xml) +def _newZPT(id, filename): + """ factory to generate ZPT instances from the file-system + based templates (basically for internal purposes) + """ + zpt = ZPT(id, open(filename).read(), 'text/html') + zpt.__name__= id + return zpt class FSZPT(ZPT): + """ factory to generate ZPT instances from the file-system + based templates (basically for internal purposes) + """ - def __init__(self, filename, name): - self.__name__= name - PageTemplate.__init__(self, open(filename).read(), 'text/html') + def __init__(self, id, filename): + ZPT.__init__(self, id, open(filename).read(), 'text/html') + self.__name__= id InitializeClass(FSZPT) -# Product registration and Add support -manage_addZPTForm= PageTemplateFile('pt/ptAdd.pt', globals()) -manage_addZPTForm.__name__ = 'manage_addZPTForm' -#manage_addZPTForm= FSZPT(os.path.join(package_home(globals()), 'pt', 'ptAdd.pt'), 'manage_addZPTForm') -#manage_addZPTForm.__name__ = 'manage_addZPTForm' +ZPT.pt_editForm = FSZPT('pt_editForm', os.path.join(package_home(globals()),'pt', 'ptEdit.pt')) +# this is scary, do we need this? +ZPT.manage = ZPT.manage_main = ZPT.pt_editForm +manage_addZPTForm= FSZPT('manage_addZPTForm', os.path.join(package_home(globals()), 'pt', 'ptAdd.pt')) def manage_addZPT(self, id, title='', file=None, encoding='utf-8', submit=None, RESPONSE=None): "Add a Page Template with optional file content." @@ -422,7 +429,7 @@ else: return zpt -from Products.PageTemplates import misc_ +from Products.ZPT import misc_ misc_['exclamation.gif'] = ImageFile('pt/exclamation.gif', globals()) def initialize(context): Deleted: Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py.scary =================================================================== --- Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py.scary 2005-12-11 11:21:09 UTC (rev 40697) +++ Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py.scary 2005-12-11 12:02:36 UTC (rev 40698) @@ -1,446 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 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 -# -############################################################################## - -""" Zope Page Template module (wrapper for the Zope 3 ZPT implementation) """ - -__version__='$Revision: 1.48 $'[11:-2] - -import re -from urllib import quote -import os, AccessControl, Acquisition -from Globals import ImageFile, package_home, InitializeClass -from OFS.SimpleItem import SimpleItem -from OFS.content_types import guess_content_type -from DateTime.DateTime import DateTime -from Shared.DC.Scripts.Script import Script -from Shared.DC.Scripts.Signature import FuncCode -from AccessControl import getSecurityManager - -from OFS.History import Historical, html_diff -from OFS.Cache import Cacheable -from OFS.Traversable import Traversable -from OFS.PropertyManager import PropertyManager - -from Products.PageTemplates.Expressions import SecureModuleImporter - -from AccessControl import Unauthorized -from AccessControl.Permissions import view, ftp_access, change_page_templates, view_management_screens - -from webdav.Lockable import ResourceLockedError -from webdav.WriteLockInterface import WriteLockInterface -from zope.pagetemplate.pagetemplate import PageTemplate - -# regular expression to extract the encoding from the XML preamble -encoding_reg= re.compile('<\?xml.*?encoding="(.*?)".*?\?>', re.M) - -class Src(Acquisition.Explicit): - """ I am scary code """ - - index_html = None - PUT = document_src = Acquisition.Acquired - - def __before_publishing_traverse__(self, ob, request): - if getattr(request, '_hacked_path', 0): - request._hacked_path = 0 - - def __call__(self, REQUEST, RESPONSE): - " " - return self.document_src(REQUEST) - - -def sniffEncoding(text, default_encoding='utf-8'): - """ try to determine the encoding from html or xml """ - - # XXX: look at pagetemplates.py (BOM!!!) - if text.startswith('<?xml'): - mo = encoding_reg.search(text) - if mo: - return mo.group(1) - return default_encoding - -_default_content_fn = os.path.join(package_home(globals()), 'pt', 'default.html') - - -class ZPT(Script, PageTemplate, Historical, Cacheable, - Traversable, PropertyManager): - """ Z2 wrapper class for Zope 3 page templates """ - - __implements__ = (WriteLockInterface,) - - meta_type = 'ZPT' - - func_defaults = None - func_code = FuncCode((), 0) - - _default_bindings = {'name_subpath': 'traverse_subpath'} - - manage_options = ( - {'label':'Edit', 'action':'pt_editForm', - 'help': ('PageTemplates', 'PageTemplate_Edit.stx')}, - {'label':'Test', 'action':'ZScriptHTML_tryForm'}, - ) + PropertyManager.manage_options \ - + Historical.manage_options \ - + SimpleItem.manage_options \ - + Cacheable.manage_options - - - _properties=({'id':'title', 'type': 'ustring', 'mode': 'w'}, - {'id':'content_type', 'type':'string', 'mode': 'w'}, - {'id':'expand', 'type':'boolean', 'mode': 'w'}, - ) - - security = AccessControl.ClassSecurityInfo() - security.declareObjectProtected(view) - security.declareProtected(view, '__call__') - - def __init__(self, id, text=None, content_type=None, encoding='utf-8'): - self.id = id - self.ZBindings_edit(self._default_bindings) - self.pt_edit(text, content_type, encoding) - - security.declareProtected(change_page_templates, 'pt_encoding') - def pt_encoding(self): - encoding = sniffEncoding(self.read()) - return encoding - - # Use the encoding of the document as encoding for the ZMI to - # avoid any kind of encoding troubles - from ComputedAttribute import ComputedAttribute - management_page_charset = ComputedAttribute(pt_encoding, 1) - - security.declareProtected(change_page_templates, 'pt_edit') - def pt_edit(self, text, content_type, encoding='utf-8'): - - text = text.strip() -# if content_type == 'text/html': -# if not text.startswith('<?xml'): -# # not XHTML -> convert it to unicode -# text = unicode(text, encoding) - - if not isinstance(text, unicode): - text = unicode(text, encoding) - - self.ZCacheable_invalidate() - import pdb - pdb.set_trace() - PageTemplate.pt_edit(self, text, content_type) - - security.declareProtected(change_page_templates, 'pt_editAction') - def pt_editAction(self, REQUEST, title, text, content_type, encoding, expand): - """Change the title and document.""" - - if self.wl_isLocked(): - raise ResourceLockedError("File is locked via WebDAV") - - self.expand = expand - self.pt_setTitle(title, encoding) - - self.pt_edit(text, content_type, encoding) - REQUEST.set('text', self.read()) # May not equal 'text'! - REQUEST.set('title', self.title) - message = "Saved changes." - if getattr(self, '_v_warnings', None): - message = ("<strong>Warning:</strong> <i>%s</i>" - % '<br>'.join(self._v_warnings)) - return self.pt_editForm(manage_tabs_message=message) - - - security.declareProtected(change_page_templates, 'pt_setTitle') - def pt_setTitle(self, title, encoding='utf-8'): - if not isinstance(title, unicode): - title = unicode(title, encoding) - self._setPropValue('title', title) - - - def _setPropValue(self, id, value): - """ set a property and invalidate the cache """ - PropertyManager._setPropValue(self, id, value) - self.ZCacheable_invalidate() - - - security.declareProtected(change_page_templates, 'pt_upload') - def pt_upload(self, REQUEST, file='', encoding='utf-8'): - """Replace the document with the text in file.""" - - if self.wl_isLocked(): - raise ResourceLockedError("File is locked via WebDAV") - - if isinstance(file, str): - filename = None - text = file - else: - if not file: - raise ValueError('File not specified') - filename = file.filename - text = file.read() - - content_type, dummy = guess_content_type(filename, text) - if not content_type in ('text/html', 'text/xml'): - raise ValueError('Unsupported mimetype: %s' % content_type) - - encoding = sniffEncoding(text, encoding) - self.pt_edit(text, content_type, encoding) - return self.pt_editForm(manage_tabs_message='Saved changes') - - security.declareProtected(change_page_templates, 'pt_changePrefs') - def pt_changePrefs(self, REQUEST, height=None, width=None, - dtpref_cols="100%", dtpref_rows="20"): - """Change editing preferences.""" - dr = {"Taller":5, "Shorter":-5}.get(height, 0) - dc = {"Wider":5, "Narrower":-5}.get(width, 0) - if isinstance(height, int): dtpref_rows = height - if isinstance(width, int) or \ - isinstance(width, str) and width.endswith('%'): - dtpref_cols = width - 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() - - def ZScriptHTML_tryParams(self): - """Parameters to test the script with.""" - return [] - -# def manage_historyCompare(self, rev1, rev2, REQUEST, -# historyComparisonResults=''): -# return ZopePageTemplate.inheritedAttribute( -# 'manage_historyCompare')( -# self, rev1, rev2, REQUEST, -# historyComparisonResults=html_diff(rev1._text, rev2._text) ) - - def pt_getContext(self, *args, **kw): - root = self.getPhysicalRoot() - context = self._getContext() - c = {'template': self, - 'here': context, - 'context': context, - 'container': self._getContainer(), - 'nothing': None, - 'options': {}, - 'root': root, - 'request': getattr(root, 'REQUEST', None), - 'modules': SecureModuleImporter, - } - return c - - security.declareProtected(view_management_screens, 'manage_main', 'read', - 'ZScriptHTML_tryForm') - - def _exec(self, bound_names, args, kw): - """Call a Page Template""" - if not kw.has_key('args'): - kw['args'] = args - bound_names['options'] = kw - - try: - response = self.REQUEST.RESPONSE - if not response.headers.has_key('content-type'): - response.setHeader('content-type', self.content_type) - except AttributeError: - pass - - security=getSecurityManager() - bound_names['user'] = security.getUser() - - # Retrieve the value from the cache. - keyset = None - if self.ZCacheable_isCachingEnabled(): - # Prepare a cache key. - keyset = {'here': self._getContext(), - 'bound_names': bound_names} - result = self.ZCacheable_get(keywords=keyset) - if result is not None: - # Got a cached value. - return result - - # Execute the template in a new security context. - security.addContext(self) - - try: - # XXX: check the parameters for pt_render()! (aj) - import pdb - pdb.set_trace() - result = self.pt_render(self.pt_getContext()) - -# result = self.pt_render(extra_context=bound_names) - if keyset is not None: - # Store the result in the cache. - self.ZCacheable_set(result, keywords=keyset) - return result - finally: - security.removeContext(self) - - security.declareProtected(change_page_templates, - 'manage_historyCopy', - 'manage_beforeHistoryCopy', 'manage_afterHistoryCopy') - - security.declareProtected(change_page_templates, 'PUT') - def PUT(self, REQUEST, RESPONSE): - """ Handle HTTP PUT requests """ - self.dav__init(REQUEST, RESPONSE) - self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1) - ## XXX:this should be unicode or we must pass an encoding - self.pt_edit(REQUEST.get('BODY', '')) - RESPONSE.setStatus(204) - return RESPONSE - - security.declareProtected(change_page_templates, 'manage_FTPput') - manage_FTPput = PUT - - security.declareProtected(ftp_access, 'manage_FTPstat','manage_FTPlist') - - security.declareProtected(ftp_access, 'manage_FTPget') - def manage_FTPget(self): - "Get source for FTP download" - self.REQUEST.RESPONSE.setHeader('Content-Type', self.content_type) - return self.read() - - security.declareProtected(view_management_screens, 'html') - def html(self): - return self.content_type == 'text/html' - - security.declareProtected(view_management_screens, 'get_size') - def get_size(self): - return len(self.read()) - - security.declareProtected(view_management_screens, 'getSize') - getSize = get_size - - 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 expanded document source.""" - - print 'src', self.read() - - - if RESPONSE is not None: - RESPONSE.setHeader('Content-Type', 'text/plain') - if REQUEST is not None and REQUEST.get('raw'): - return self._text - return self.read() - - def om_icons(self): - """Return a list of icon URLs to be displayed by an ObjectManager""" - icons = ({'path': 'misc_/PageTemplates/zpt.gif', - 'alt': self.meta_type, 'title': self.meta_type},) - if not self._v_cooked: - self._cook() - if self._v_errors: - icons = icons + ({'path': 'misc_/PageTemplates/exclamation.gif', - 'alt': 'Error', - 'title': 'This template has an error'},) - return icons - - security.declareProtected(view, 'pt_source_file') - def pt_source_file(self): - """Returns a file name to be compiled into the TAL code.""" - try: - return '/'.join(self.getPhysicalPath()) - except: - # This page template is being compiled without an - # acquisition context, so we don't know where it is. :-( - return None - - def wl_isLocked(self): - return 0 - - security.declareProtected(view_management_screens, 'getSource') - getSource = Src() - source_dot_xml = Src() - -InitializeClass(ZPT) - - -setattr(ZPT, 'source.xml', ZPT.source_dot_xml) -setattr(ZPT, 'source.html', ZPT.source_dot_xml) - - -def _newZPT(id, filename): - """ factory to generate ZPT instances from the file-system - based templates (basically for internal purposes) - """ - zpt = ZPT(id, open(filename).read(), 'text/html') - zpt.__name__= id - return zpt - -class FSZPT(ZPT): - """ factory to generate ZPT instances from the file-system - based templates (basically for internal purposes) - """ - - def __init__(self, id, filename): - ZPT.__init__(self, id, open(filename).read(), 'text/html') - self.__name__= id - -InitializeClass(FSZPT) - - -ZPT.pt_editForm = FSZPT('pt_editForm', os.path.join(package_home(globals()),'pt', 'ptEdit.pt')) -# this is scary, do we need this? -ZPT.manage = ZPT.manage_main = ZPT.pt_editForm - -manage_addZPTForm= FSZPT('manage_addZPTForm', os.path.join(package_home(globals()), 'pt', 'ptAdd.pt')) - -def manage_addZPT(self, id, title='', file=None, encoding='utf-8', submit=None, RESPONSE=None): - "Add a Page Template with optional file content." - - if file: - filename = file.filename - text = file.read() - encoding = sniffEncoding(text) - content_type, dummy = guess_content_type(filename, text) - else: - text = open(_default_content_fn).read() - encoding = 'utf-8' - content_type = 'text/html' - - zpt = ZPT(id, text, content_type, encoding) - zpt.pt_setTitle(title, encoding) - self._setObject(id, zpt) - zpt = getattr(self, id) - - if RESPONSE: - if submit == " Add and Edit ": - RESPONSE.redirect(zpt.absolute_url() + '/manage_main') - else: - RESPONSE.redirect(self.absolute_url() + '/manage_main') - else: - return zpt - -from Products.ZPT import misc_ -misc_['exclamation.gif'] = ImageFile('pt/exclamation.gif', globals()) - -def initialize(context): - context.registerClass( - ZPT, - permission='Add Page Templates', - constructors=(manage_addZPTForm, - manage_addZPT), - icon='pt/zpt.gif', - ) - context.registerHelp() - context.registerHelpTitle('Zope Help') - _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins