[Zope-Checkins] CVS: Zope3/lib/python/Zope/PageTemplate - Expressions.py:1.1.2.1 PageTemplate.py:1.1.2.1 PageTemplateFile.py:1.1.2.1 PythonExpr.py:1.1.2.1 SafeMapping.py:1.1.2.1 TALES.py:1.1.2.1 ZopePageTemplate.py:1.1.2.1 __init__.py:1.1.2.1
Fred Drake Jr
fdrake@acm.org
Mon, 19 Nov 2001 18:46:10 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/PageTemplate
In directory cvs.zope.org:/tmp/cvs-serv32307
Added Files:
Tag: Zope-3x-branch
Expressions.py PageTemplate.py PageTemplateFile.py
PythonExpr.py SafeMapping.py TALES.py ZopePageTemplate.py
__init__.py
Log Message:
Version of page templates that work in the Zope 3 world, at least partly.
=== Added File Zope3/lib/python/Zope/PageTemplate/Expressions.py ===
##############################################################################
#
# 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.
#
##############################################################################
"""Page Template Expression Engine
Page Template-specific implementation of TALES, with handlers
for Python expressions, string literals, and paths.
"""
__version__='$Revision: 1.1.2.1 $'[11:-2]
import re, sys
from TALES import Engine, CompilerError, _valid_name, NAME_RE, \
TALESError, Undefined, Default
from string import strip, split, join, replace, lstrip
def aq_base(ob):
return ob
_engine = None
def getEngine():
global _engine
if _engine is None:
_engine = Engine()
installHandlers(_engine)
_engine._nocatch = (TALESError, 'Redirect')
return _engine
def installHandlers(engine):
reg = engine.registerType
pe = PathExpr
for pt in ('standard', 'path', 'exists', 'nocall'):
reg(pt, pe)
reg('string', StringExpr)
reg('python', PythonExpr)
reg('not', NotExpr)
reg('defer', DeferExpr)
if 0 and sys.modules.has_key('Zope'):
import AccessControl
from AccessControl import getSecurityManager, Unauthorized
if hasattr(AccessControl, 'full_read_guard'):
from ZRPythonExpr import PythonExpr, _SecureModuleImporter, \
call_with_ns
else:
from ZPythonExpr import PythonExpr, _SecureModuleImporter, \
call_with_ns
SecureModuleImporter = _SecureModuleImporter()
else:
from PythonExpr import getSecurityManager, PythonExpr
try:
from zExceptions import Unauthorized
except ImportError:
Unauthorized = "Unauthorized"
def call_with_ns(f, ns, arg=1):
if arg==2:
return f(None, ns)
else:
return f(ns)
class SecureModuleImporter:
def __getitem__(self, module):
__import__(module)
return sys.modules[module]
SecureModuleImporter = SecureModuleImporter()
def render(ob, ns):
"""
Calls the object, possibly a document template, or just returns it if
not callable. (From DT_Util.py)
"""
if hasattr(ob, '__render_with_namespace__'):
ob = call_with_ns(ob.__render_with_namespace__, ns)
else:
base = aq_base(ob)
if callable(base):
try:
if getattr(base, 'isDocTemp', 0):
ob = call_with_ns(ob, ns, 2)
else:
ob = ob()
except AttributeError, n:
if str(n) != '__call__':
raise
return ob
class PathExpr:
def __init__(self, name, expr, engine):
self._s = expr
self._name = name
self._paths = map(self._prepPath, split(expr, '|'))
def _prepPath(self, path):
path = split(strip(path), '/')
base = path.pop(0)
if not _valid_name(base):
raise CompilerError, 'Invalid variable name "%s"' % base
# Parse path
dp = []
for i in range(len(path)):
e = path[i]
if e[:1] == '?' and _valid_name(e[1:]):
dp.append((i, e[1:]))
dp.reverse()
return base, path, dp
def _eval(self, econtext, securityManager,
list=list, isinstance=isinstance, StringType=type(''),
render=render):
vars = econtext.vars
exists = 0
for base, path, dp in self._paths:
# Expand dynamic path parts from right to left.
if dp:
path = list(path) # Copy!
for i, varname in dp:
val = vars[varname]
if isinstance(val, StringType):
path[i] = val
else:
# If the value isn't a string, assume it's a sequence
# of path names.
path[i:i+1] = list(val)
try:
__traceback_info__ = base
if base == 'CONTEXTS':
ob = econtext.contexts
else:
ob = vars[base]
if isinstance(ob, DeferWrapper):
ob = ob()
if path:
ob = restrictedTraverse(ob, path, securityManager)
exists = 1
break
except Undefined, e:
ob = e
except (AttributeError, KeyError, TypeError, IndexError,
Unauthorized), e:
ob = Undefined(self._s, sys.exc_info())
if self._name == 'exists':
# All we wanted to know is whether one of the paths exist.
return exists
if self._name == 'nocall' or isinstance(ob, StringType):
return ob
# Return the rendered object
return render(ob, vars)
def __call__(self, econtext):
return self._eval(econtext, getSecurityManager())
def __str__(self):
return '%s expression %s' % (self._name, `self._s`)
def __repr__(self):
return '%s:%s' % (self._name, `self._s`)
_interp = re.compile(r'\$(%(n)s)|\${(%(n)s(?:/%(n)s)*)}' % {'n': NAME_RE})
class StringExpr:
def __init__(self, name, expr, engine):
self._s = expr
if '%' in expr:
expr = replace(expr, '%', '%%')
self._vars = vars = []
if '$' in expr:
parts = []
for exp in split(expr, '$$'):
if parts: parts.append('$')
m = _interp.search(exp)
while m is not None:
parts.append(exp[:m.start()])
parts.append('%s')
vars.append(PathExpr('path', m.group(1) or m.group(2),
engine))
exp = exp[m.end():]
m = _interp.search(exp)
if '$' in exp:
raise CompilerError, (
'$ must be doubled or followed by a simple path')
parts.append(exp)
expr = join(parts, '')
self._expr = expr
def __call__(self, econtext):
vvals = []
for var in self._vars:
v = var(econtext)
if isinstance(v, Exception):
raise v
vvals.append(v)
return self._expr % tuple(vvals)
def __str__(self):
return 'string expression %s' % `self._s`
def __repr__(self):
return 'string:%s' % `self._s`
class NotExpr:
def __init__(self, name, expr, compiler):
self._s = expr = lstrip(expr)
self._c = compiler.compile(expr)
def __call__(self, econtext):
return not econtext.evaluateBoolean(self._c)
def __repr__(self):
return 'not:%s' % `self._s`
class DeferWrapper:
def __init__(self, expr, econtext):
self._expr = expr
self._econtext = econtext
def __str__(self):
return str(self())
def __call__(self):
return self._expr(self._econtext)
class DeferExpr:
def __init__(self, name, expr, compiler):
self._s = expr = lstrip(expr)
self._c = compiler.compile(expr)
def __call__(self, econtext):
return DeferWrapper(self._c, econtext)
def __repr__(self):
return 'defer:%s' % `self._s`
def restrictedTraverse(self, path, securityManager,
get=getattr, has=hasattr, N=None, M=[]):
i = 0
if not path[0]:
# If the path starts with an empty string, go to the root first.
self = self.getPhysicalRoot()
if not securityManager.validateValue(self):
raise Unauthorized, name
i = 1
plen = len(path)
REQUEST={'TraversalRequestNameStack': path}
validate = securityManager.validate
object = self
while i < plen:
__traceback_info__ = (path, i)
name = path[i]
i = i + 1
if name[0] == '_':
# Never allowed in a URL.
raise AttributeError, name
if name=='..':
o = get(object, 'aq_parent', M)
if o is not M:
if not validate(object, object, name, o):
raise Unauthorized, name
object=o
continue
t=get(object, '__bobo_traverse__', N)
if t is not N:
o=t(REQUEST, name)
container = None
if has(o, 'im_self'):
container = o.im_self
elif (has(get(object, 'aq_base', object), name)
and get(object, name) == o):
container = object
if not validate(object, container, name, o):
raise Unauthorized, name
else:
o=get(object, name, M)
if o is not M:
# Check security.
if has(object, 'aq_acquire'):
object.aq_acquire(
name, validate2, validate)
else:
if not validate(object, object, name, o):
raise Unauthorized, name
else:
try:
o=object[name]
except (AttributeError, TypeError):
raise AttributeError, name
if not validate(object, object, name, o):
raise Unauthorized, name
object = o
return object
def validate2(orig, inst, name, v, real_validate):
if not real_validate(orig, inst, name, v):
raise Unauthorized, name
return 1
=== Added File Zope3/lib/python/Zope/PageTemplate/PageTemplate.py ===
##############################################################################
#
# 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.
#
##############################################################################
"""Page Template module
HTML- and XML-based template objects using TAL, TALES, and METAL.
"""
__version__ = '$Revision: 1.1.2.1 $'[11:-2]
import os, sys, traceback, pprint
from Zope.TAL.TALParser import TALParser
from Zope.TAL.HTMLTALParser import HTMLTALParser
from Zope.TAL.TALGenerator import TALGenerator
from Zope.TAL.TALInterpreter import TALInterpreter
from Zope.ComponentArchitecture import getPresentation
from Zope.Publisher.Browser.IBrowserPublisher import IBrowserPublisher
from Expressions import getEngine
from string import join, strip, rstrip, split, replace, lower, find
from cStringIO import StringIO
Z_DEBUG_MODE = os.environ.get('Z_DEBUG_MODE') == '1'
class MacroCollection:
def __of__(self, parent):
return parent._v_macros
class PageTemplate(object):
"Page Templates using TAL, TALES, and METAL"
content_type = 'text/html'
expand = 1
_v_errors = ()
_v_warnings = ()
_text = ''
_error_start = '<!-- Page Template Diagnostics'
macros = MacroCollection()
def pt_edit(self, text, content_type):
if content_type:
self.content_type = str(content_type)
if hasattr(text, 'read'):
text = text.read()
self.write(text)
def pt_getContext(self, inst=None):
c = {'template': self,
'options': {},
'nothing': None,
'modules': ModuleImporter,
}
if inst is not None:
c['presentation'] = PresentationMapper(inst.getContext())
parent = getattr(self, 'aq_parent', None)
if parent is not None:
c['here'] = parent
c['container'] = self.aq_inner.aq_parent
while parent is not None:
self = parent
parent = getattr(self, 'aq_parent', None)
c['root'] = self
return c
def pt_render(self, source=0, extra_context={}):
"""Render this Page Template"""
if self._v_errors:
raise PTRuntimeError, 'Page Template %s has errors.' % self.id
output = StringIO()
c = self.pt_getContext()
c.update(extra_context)
if Z_DEBUG_MODE:
__traceback_info__ = pprint.pformat(c)
TALInterpreter(self._v_program, self._v_macros,
getEngine().getContext(c),
output,
tal=not source, strictinsert=0)()
return output.getvalue()
def __call__(self, *args, **kwargs):
if not kwargs.has_key('args'):
kwargs['args'] = args
return self.pt_render(extra_context={'options': kwargs})
def pt_errors(self):
err = self._v_errors
if err:
return err
try:
self.pt_render(source=1)
except:
return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
def pt_warnings(self):
return self._v_warnings
def write(self, text):
assert type(text) is type('')
if text[:len(self._error_start)] == self._error_start:
errend = find(text, '-->')
if errend >= 0:
text = text[errend + 4:]
if self._text != text:
self._text = text
self._cook()
def read(self):
if not self._v_errors:
if not self.expand:
return self._text
try:
return self.pt_render(source=1)
except:
return ('%s\n Macro expansion failed\n %s\n-->\n%s' %
(self._error_start, "%s: %s" % sys.exc_info()[:2],
self._text) )
return ('%s\n %s\n-->\n%s' % (self._error_start,
join(self._v_errors, '\n '),
self._text))
def _cook(self):
"""Compile the TAL and METAL statments.
A Page Template must always be cooked, and cooking must not
fail due to user input.
"""
if self.html():
gen = TALGenerator(getEngine(), xml=0)
parser = HTMLTALParser(gen)
else:
gen = TALGenerator(getEngine())
parser = TALParser(gen)
self._v_errors = ()
try:
parser.parseString(self._text)
self._v_program, self._v_macros = parser.getCode()
self.macros = self._v_macros
except:
self._v_errors = ["Compilation failed",
"%s: %s" % sys.exc_info()[:2]]
self._v_warnings = parser.getWarnings()
def html(self):
if not hasattr(getattr(self, 'aq_base', self), 'is_html'):
return self.content_type == 'text/html'
return self.is_html
class PresentationMapper:
def __init__(self, ob):
self.ob = ob
def __getitem__(self, name):
return getPresentation(self.ob, name, IBrowserPublish)
class _ModuleImporter:
def __getitem__(self, module):
mod = __import__(module)
path = split(module, '.')
for name in path[1:]:
mod = getattr(mod, name)
return mod
ModuleImporter = _ModuleImporter()
class PTRuntimeError(RuntimeError):
'''The Page Template has template errors that prevent it from rendering.'''
pass
=== Added File Zope3/lib/python/Zope/PageTemplate/PageTemplateFile.py ===
##############################################################################
#
# 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.
#
##############################################################################
"""Filesystem Page Template module
Zope object encapsulating a Page Template from the filesystem.
"""
__metatype__ = type
__version__='$Revision: 1.1.2.1 $'[11:-2]
import os, sys
from zLOG import LOG, ERROR, INFO
from string import join, strip, rstrip, split, lower
from PageTemplate import PageTemplate
from Expressions import SecureModuleImporter
def package_home(gdict):
filename = gdict["__file__"]
return os.path.dirname(filename)
class MacroCollection:
def __of__(self, parent):
parent._cook_check()
return parent._v_macros
class PageTemplateFile(PageTemplate):
"Zope wrapper for filesystem Page Template using TAL, TALES, and METAL"
meta_type = 'Page Template (File)'
_need__name__=1
_v_last_read=0
_default_bindings = {'name_subpath': 'traverse_subpath'}
def __init__(self, filename, _prefix):
assert _prefix is not None
if not isinstance(_prefix, str):
_prefix = package_home(_prefix)
if not os.path.splitext(filename)[1]:
filename = filename + '.zpt'
self.filename = os.path.join(_prefix, filename)
def pt_getContext(self, inst=None):
#root = self.getPhysicalRoot()
root = None
c = {'template': self,
'nothing': None,
'options': {},
'root': root,
'request': getattr(root, 'REQUEST', None),
'modules': SecureModuleImporter,
}
if inst is not None:
c['here'] = inst.getContext()
c['container'] = inst
return c
def __call__(self, inst, REQUEST=None, **kw):
"""Call a Page Template"""
self._cook_check()
if not kw.has_key('args'):
kw['args'] = args
bound_names = {'options': kw, 'request': REQUEST}
bound_names.update(self.pt_getContext(inst))
try:
self.REQUEST.RESPONSE.setHeader('content-type',
self.content_type)
except AttributeError:
pass
# Execute the template in a new security context.
return self.pt_render(extra_context=bound_names)
def _cook_check(self):
if self._v_last_read and not DevelopmentMode:
return
__traceback_info__ = self.filename
try: mtime=os.stat(self.filename)[8]
except: mtime=0
if hasattr(self, '_v_program') and mtime == self._v_last_read:
return
self.pt_edit(open(self.filename), None)
self._cook()
if self._v_errors:
LOG('PageTemplateFile', ERROR, 'Error in template',
join(self._v_errors, '\n'))
return
self._v_last_read = mtime
def document_src(self, REQUEST=None, RESPONSE=None):
"""Return expanded document source."""
if RESPONSE is not None:
RESPONSE.setHeader('Content-Type', self.content_type)
return self.read()
def __setstate__(self, state):
raise StorageError, ("Instance of AntiPersistent class %s "
"cannot be stored." % self.__class__.__name__)
def __get__(self, instance, type=None):
return BoundPageTemplateFile(self, instance)
class BoundPageTemplateFile:
def __init__(self, pt, ob):
self.im_func = pt
self.im_self = ob
def __call__(self, REQUEST=None, **kw):
return self.im_func(self.im_self, REQUEST=REQUEST, **kw)
def __getattr__(self, name):
return getattr(self.im_func, name)
def __repr__(self):
return "<BoundPageTemplateFile of %r>" % self.im_self
=== Added File Zope3/lib/python/Zope/PageTemplate/PythonExpr.py ===
##############################################################################
#
# 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.
#
##############################################################################
"""Generic Python Expression Handler"""
__version__ = '$Revision: 1.1.2.1 $'[11:-2]
from TALES import CompilerError
from string import strip, split, join, replace, lstrip
from sys import exc_info
class getSecurityManager:
'''Null security manager'''
def validate(self, *args, **kwargs):
return 1
addContext = removeContext = validateValue = validate
class PythonExpr:
def __init__(self, name, expr, engine):
self.expr = expr = replace(strip(expr), '\n', ' ')
try:
d = {}
exec 'def f():\n return %s\n' % strip(expr) in d
self._f = d['f']
except:
raise CompilerError, ('Python expression error:\n'
'%s: %s') % exc_info()[:2]
self._get_used_names()
def _get_used_names(self):
self._f_varnames = vnames = []
for vname in self._f.func_code.co_names:
if vname[0] not in '$_':
vnames.append(vname)
def _bind_used_names(self, econtext):
# Bind template variables
names = {}
vars = econtext.vars
getType = econtext._engine.getTypes().get
for vname in self._f_varnames:
has, val = vars.has_get(vname)
if not has:
has = val = getType(vname)
if has:
val = ExprTypeProxy(vname, val, econtext)
if has:
names[vname] = val
return names
def __call__(self, econtext):
__traceback_info__ = self.expr
f = self._f
f.func_globals.update(self._bind_used_names(econtext))
return f()
def __str__(self):
return 'Python expression "%s"' % self.expr
def __repr__(self):
return '<PythonExpr %s>' % self.expr
class ExprTypeProxy:
'''Class that proxies access to an expression type handler'''
def __init__(self, name, handler, econtext):
self._name = name
self._handler = handler
self._econtext = econtext
def __call__(self, text):
return self._handler(self._name, text,
self._econtext._engine)(self._econtext)
=== Added File Zope3/lib/python/Zope/PageTemplate/SafeMapping.py ===
"""Simple variation of MultiMapping used to support layers of variable
declarations in TAL."""
class SafeMapping:
def __init__(self, *dicts):
self._mappings = list(dicts)
self._mappings.reverse()
def __getitem__(self, key):
for d in self._mappings:
if d.has_key(key):
return d[key]
raise KeyError, key
def has_get(self, key, _marker=[]):
for d in self._mappings:
if d.has_key(key):
return 1, d[key]
return 0, None
def has_key(self, key):
for d in self._mappings:
if d.has_key(key):
return 1
return 0
def get(self, key, default=None):
for d in self._mappings:
if d.has_key(key):
return d[key]
return default
def _push(self, dict):
self._mappings.insert(0, dict)
def _pop(self, count=1):
del self._mappings[:count]
=== Added File Zope3/lib/python/Zope/PageTemplate/TALES.py ===
##############################################################################
#
# 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.
#
##############################################################################
"""TALES
An implementation of a generic TALES engine
"""
__version__ = '$Revision: 1.1.2.1 $'[11:-2]
import re, sys
StringType = type('')
NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*"
_parse_expr = re.compile(r"(%s):" % NAME_RE).match
_valid_name = re.compile('%s$' % NAME_RE).match
class TALESError(Exception):
__allow_access_to_unprotected_subobjects__ = 1
def __init__(self, expression, info=(None, None, None),
position=(None, None)):
self.type, self.value, self.traceback = info
self.expression = expression
self.setPosition(position)
def setPosition(self, position):
self.lineno = position[0]
self.offset = position[1]
def takeTraceback(self):
t = self.traceback
self.traceback = None
return t
def __str__(self):
if self.type is None:
s = self.expression
else:
s = '%s on %s in %s' % (self.type, self.value,
`self.expression`)
if self.lineno is not None:
s = "%s, at line %d" % (s, self.lineno)
if self.offset is not None:
s = "%s, column %d" % (s, self.offset + 1)
return s
def __nonzero__(self):
return 0
class Undefined(TALESError):
'''Exception raised on traversal of an undefined path'''
def __str__(self):
if self.type is None:
s = self.expression
else:
s = '%s not found in %s' % (self.value,
`self.expression`)
if self.lineno is not None:
s = "%s, at line %d" % (s, self.lineno)
if self.offset is not None:
s = "%s, column %d" % (s, self.offset + 1)
return s
class RegistrationError(Exception):
'''TALES Type Registration Error'''
class CompilerError(Exception):
'''TALES Compiler Error'''
class Default:
'''Retain Default'''
def __nonzero__(self):
return 0
Default = Default()
_marker = []
from SafeMapping import SafeMapping
class Iterator:
def __init__(self, name, seq, context):
self.seq = seq
self.nextIndex = 0
self.name = name
self._context = context
def __iter__(self):
return self
def _next(self):
i = self.nextIndex
try:
self.seq[i]
except IndexError:
return 0
self.index = i
self.nextIndex = i+1
return 1
def next(self):
try:
if self._next():
self._context.setLocal(self.name, self.seq[self.index])
return 1
except TALESError:
raise
except:
raise TALESError, ('repeat/%s' % self.name,
sys.exc_info()), sys.exc_info()[2]
return 0
class Engine:
'''Expression Engine
An instance of this class keeps a mutable collection of expression
type handlers. It can compile expression strings by delegating to
these handlers. It can provide an expression Context, which is
capable of holding state and evaluating compiled expressions.
'''
Iterator = Iterator
def __init__(self, Iterator=None):
self.types = {}
if Iterator is not None:
self.Iterator = Iterator
def registerType(self, name, handler):
if not _valid_name(name):
raise RegistrationError, 'Invalid Expression type "%s".' % name
types = self.types
if types.has_key(name):
raise RegistrationError, (
'Multiple registrations for Expression type "%s".' %
name)
types[name] = handler
def getTypes(self):
return self.types
def compile(self, expression):
m = _parse_expr(expression)
if m:
type = m.group(1)
expr = expression[m.end():]
else:
type = "standard"
expr = expression
try:
handler = self.types[type]
except KeyError:
raise CompilerError, (
'Unrecognized expression type "%s".' % type)
return handler(type, expr, self)
def getContext(self, contexts=None, **kwcontexts):
if contexts is not None:
if kwcontexts:
kwcontexts.update(contexts)
else:
kwcontexts = contexts
return Context(self, kwcontexts)
def getCompilerError(self):
return CompilerError
class Context:
'''Expression Context
An instance of this class holds context information that it can
use to evaluate compiled expressions.
'''
_context_class = SafeMapping
_nocatch = TALESError
position = (None, None)
def __init__(self, engine, contexts):
self._engine = engine
if hasattr(engine, '_nocatch'):
self._nocatch = engine._nocatch
self.contexts = contexts
contexts['nothing'] = None
contexts['default'] = Default
self.repeat_vars = rv = {}
# Wrap this, as it is visible to restricted code
contexts['repeat'] = rep = self._context_class(rv)
contexts['loop'] = rep # alias
self.global_vars = gv = contexts.copy()
self.local_vars = lv = {}
self.vars = self._context_class(gv, lv)
# Keep track of what needs to be popped as each scope ends.
self._scope_stack = []
def beginScope(self):
self._scope_stack.append([self.local_vars.copy()])
def endScope(self):
scope = self._scope_stack.pop()
self.local_vars = lv = scope[0]
v = self.vars
v._pop()
v._push(lv)
# Pop repeat variables, if any
i = len(scope) - 1
while i:
name, value = scope[i]
if value is None:
del self.repeat_vars[name]
else:
self.repeat_vars[name] = value
i = i - 1
def setLocal(self, name, value):
self.local_vars[name] = value
def setGlobal(self, name, value):
self.global_vars[name] = value
def setRepeat(self, name, expr):
expr = self.evaluate(expr)
if not expr:
return self._engine.Iterator(name, (), self)
it = self._engine.Iterator(name, expr, self)
old_value = self.repeat_vars.get(name)
self._scope_stack[-1].append((name, old_value))
self.repeat_vars[name] = it
return it
def evaluate(self, expression,
isinstance=isinstance, StringType=StringType):
if isinstance(expression, StringType):
expression = self._engine.compile(expression)
try:
v = expression(self)
if isinstance(v, Exception):
if isinstance(v, TALESError):
raise v, None, v.takeTraceback()
raise v
except TALESError, err:
err.setPosition(self.position)
raise err, None, sys.exc_info()[2]
except self._nocatch:
raise
except:
raise TALESError, (`expression`, sys.exc_info(),
self.position), sys.exc_info()[2]
else:
return v
evaluateValue = evaluate
def evaluateBoolean(self, expr):
return not not self.evaluate(expr)
def evaluateText(self, expr, None=None):
text = self.evaluate(expr)
if text is Default or text is None:
return text
return str(text)
def evaluateStructure(self, expr):
return self.evaluate(expr)
evaluateStructure = evaluate
def evaluateMacro(self, expr):
# XXX Should return None or a macro definition
return self.evaluate(expr)
evaluateMacro = evaluate
def getTALESError(self):
return TALESError
def getDefault(self):
return Default
def setPosition(self, position):
self.position = position
class SimpleExpr:
'''Simple example of an expression type handler'''
def __init__(self, name, expr, engine):
self._name = name
self._expr = expr
def __call__(self, econtext):
return self._name, self._expr
def __repr__(self):
return '<SimpleExpr %s %s>' % (self._name, `self._expr`)
=== Added File Zope3/lib/python/Zope/PageTemplate/ZopePageTemplate.py ===
"""Zope Page Template module
Zope object encapsulating a Page Template.
"""
__version__='$Revision: 1.1.2.1 $'[11:-2]
import os, AccessControl, Acquisition, sys
from Globals import DTMLFile, ImageFile, MessageDialog, package_home
from zLOG import LOG, ERROR, INFO
from OFS.SimpleItem import SimpleItem
from DateTime.DateTime import DateTime
from string import join, strip, rstrip, split, replace, lower
from Shared.DC.Scripts.Script import Script, BindingsUI
from Shared.DC.Scripts.Signature import FuncCode
from AccessControl import getSecurityManager, Unauthorized
from OFS.History import Historical, html_diff
from OFS.Cache import Cacheable
from OFS.Traversable import Traversable
from OFS.PropertyManager import PropertyManager
from PageTemplate import PageTemplate
from TALES import TALESError
from Expressions import SecureModuleImporter
from PageTemplateFile import PageTemplateFile
try:
from webdav.Lockable import ResourceLockedError
from webdav.WriteLockInterface import WriteLockInterface
SUPPORTS_WEBDAV_LOCKS = 1
except ImportError:
SUPPORTS_WEBDAV_LOCKS = 0
class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable,
Traversable, PropertyManager):
"Zope wrapper for Page Template using TAL, TALES, and METAL"
if SUPPORTS_WEBDAV_LOCKS:
__implements__ = (WriteLockInterface,)
meta_type = 'Page Template'
func_defaults = None
func_code = FuncCode((), 0)
_default_bindings = {'name_subpath': 'traverse_subpath'}
_default_content_fn = os.path.join(package_home(globals()),
'www', 'default.html')
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': 'string', 'mode': 'w'},
{'id':'content_type', 'type':'string', 'mode': 'w'},
{'id':'expand', 'type':'boolean', 'mode': 'w'},
)
def __init__(self, id, text=None, content_type=None):
self.id = str(id)
self.ZBindings_edit(self._default_bindings)
if text is None:
text = open(self._default_content_fn).read()
self.pt_edit(text, content_type)
def _setPropValue(self, id, value):
PropertyManager._setPropValue(self, id, value)
self.ZCacheable_invalidate()
security = AccessControl.ClassSecurityInfo()
security.declareObjectProtected('View')
security.declareProtected('View', '__call__')
security.declareProtected('View management screens',
'pt_editForm', 'manage_main', 'read',
'ZScriptHTML_tryForm', 'PrincipiaSearchSource',
'document_src', 'source.html', 'source.xml')
pt_editForm = PageTemplateFile('www/ptEdit', globals(),
__name__='pt_editForm')
pt_editForm._owner = None
manage = manage_main = pt_editForm
security.declareProtected('Change Page Templates',
'pt_editAction', 'pt_setTitle', 'pt_edit',
'pt_upload', 'pt_changePrefs')
def pt_editAction(self, REQUEST, title, text, content_type, expand):
"""Change the title and document."""
if SUPPORTS_WEBDAV_LOCKS and self.wl_isLocked():
raise ResourceLockedError, "File is locked via WebDAV"
self.expand=expand
self.pt_setTitle(title)
self.pt_edit(text, content_type)
REQUEST.set('text', self.read()) # May not equal 'text'!
message = "Saved changes."
if getattr(self, '_v_warnings', None):
message = ("<strong>Warning:</strong> <i>%s</i>"
% join(self._v_warnings, '<br>'))
return self.pt_editForm(manage_tabs_message=message)
def pt_setTitle(self, title):
self._setPropValue('title', str(title))
def pt_upload(self, REQUEST, file=''):
"""Replace the document with the text in file."""
if SUPPORTS_WEBDAV_LOCKS and self.wl_isLocked():
raise ResourceLockedError, "File is locked via WebDAV"
if type(file) is not type(''): file = file.read()
self.write(file)
message = 'Saved changes.'
return self.pt_editForm(manage_tabs_message=message)
def pt_changePrefs(self, REQUEST, height=None, width=None,
dtpref_cols='50', dtpref_rows='20'):
"""Change editing preferences."""
szchh = {'Taller': 1, 'Shorter': -1, None: 0}
szchw = {'Wider': 5, 'Narrower': -5, None: 0}
try: rows = int(height)
except: rows = max(1, int(dtpref_rows) + szchh.get(height, 0))
try: cols = int(width)
except: cols = max(40, int(dtpref_cols) + szchw.get(width, 0))
e = (DateTime('GMT') + 365).rfc822()
setc = REQUEST['RESPONSE'].setCookie
setc('dtpref_rows', str(rows), path='/', expires=e)
setc('dtpref_cols', str(cols), path='/', expires=e)
REQUEST.form.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):
root = self.getPhysicalRoot()
c = {'template': self,
'here': self._getContext(),
'container': self._getContainer(),
'nothing': None,
'options': {},
'root': root,
'request': getattr(root, 'REQUEST', None),
'modules': SecureModuleImporter,
}
return c
def write(self, text):
self.ZCacheable_invalidate()
ZopePageTemplate.inheritedAttribute('write')(self, text)
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:
self.REQUEST.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:
try:
result = self.pt_render(extra_context=bound_names)
except TALESError, err:
if (err.type == Unauthorized or
(isinstance(Unauthorized, Exception) and
isinstance(err.type, Unauthorized))):
raise err.type, err.value, err.takeTraceback()
err.takeTraceback()
raise
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',
'PUT', 'manage_FTPput', 'write',
'manage_historyCopy',
'manage_beforeHistoryCopy', 'manage_afterHistoryCopy')
def PUT(self, REQUEST, RESPONSE):
""" Handle HTTP PUT requests """
self.dav__init(REQUEST, RESPONSE)
if SUPPORTS_WEBDAV_LOCKS:
self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
self.write(REQUEST.get('BODY', ''))
RESPONSE.setStatus(204)
return RESPONSE
manage_FTPput = PUT
def manage_FTPget(self):
"Get source for FTP download"
self.REQUEST.RESPONSE.setHeader('Content-Type', self.content_type)
return self.read()
def get_size(self):
return len(self.read())
getSize = get_size
def PrincipiaSearchSource(self):
"Support for searching - the document's contents are searched."
return self.read()
def document_src(self, REQUEST=None, RESPONSE=None):
"""Return expanded document source."""
if RESPONSE is not None:
RESPONSE.setHeader('Content-Type', 'text/plain')
if 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 self._v_errors:
icons = icons + ({'path': 'misc_/PageTemplates/exclamation.gif',
'alt': 'Error',
'title': 'This template has an error'},)
return icons
def __setstate__(self, state):
ZopePageTemplate.inheritedAttribute('__setstate__')(self, state)
self._cook()
if not SUPPORTS_WEBDAV_LOCKS:
def wl_isLocked(self):
return 0
class Src(Acquisition.Explicit):
" "
PUT = document_src = Acquisition.Acquired
index_html = None
def __call__(self, REQUEST, RESPONSE):
" "
return self.document_src(REQUEST, RESPONSE)
d = ZopePageTemplate.__dict__
d['source.xml'] = d['source.html'] = Src()
# Product registration and Add support
manage_addPageTemplateForm = PageTemplateFile(
'www/ptAdd', globals(), __name__='manage_addPageTemplateForm')
from urllib import quote
def manage_addPageTemplate(self, id, title=None, text=None,
REQUEST=None, submit=None):
"Add a Page Template with optional file content."
id = str(id)
if REQUEST is None:
self._setObject(id, ZopePageTemplate(id, text))
ob = getattr(self, id)
if title:
ob.pt_setTitle(title)
return ob
else:
file = REQUEST.form.get('file')
headers = getattr(file, 'headers', None)
if headers is None or not file.filename:
zpt = ZopePageTemplate(id)
else:
zpt = ZopePageTemplate(id, file, headers.get('content_type'))
self._setObject(id, zpt)
try: u = self.DestinationURL()
except: u = REQUEST['URL1']
if submit==" Add and Edit ": u="%s/%s" % (u,quote(id))
REQUEST.RESPONSE.redirect(u+'/manage_main')
return ''
from Products.PageTemplates import misc_
misc_['exclamation.gif'] = ImageFile('www/exclamation.gif', globals())
def initialize(context):
context.registerClass(
ZopePageTemplate,
permission='Add Page Templates',
constructors=(manage_addPageTemplateForm,
manage_addPageTemplate),
icon='www/zpt.gif',
)
context.registerHelp()
context.registerHelpTitle('Zope Help')
=== Added File Zope3/lib/python/Zope/PageTemplate/__init__.py ===
"""Page Templates for Zope 3."""