vendor/CMF/1.6.3/CMFCore

view FSPageTemplate.py @ 2:4c712d7bd1d7

Added tag 1.6.3 for changeset 1babb9d61518
author Georges Racinet on purity.racinet.fr <georges@racinet.fr>
date Fri, 09 Sep 2011 12:44:00 +0200
parents
children
line source
1 ##############################################################################
2 #
3 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
4 #
5 # This software is subject to the provisions of the Zope Public License,
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # FOR A PARTICULAR PURPOSE.
11 #
12 ##############################################################################
13 """ Customizable page templates that come from the filesystem.
15 $Id$
16 """
18 import re, sys
20 import Globals
21 from DocumentTemplate.DT_Util import html_quote
22 from AccessControl import getSecurityManager, ClassSecurityInfo
23 from OFS.Cache import Cacheable
24 from Shared.DC.Scripts.Script import Script
25 from Products.PageTemplates.PageTemplate import PageTemplate
26 from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate, Src
28 from permissions import FTPAccess
29 from permissions import View
30 from permissions import ViewManagementScreens
31 from DirectoryView import registerFileExtension
32 from DirectoryView import registerMetaType
33 from FSObject import FSObject
34 from utils import _setCacheHeaders, _checkConditionalGET
35 from utils import expandpath
37 xml_detect_re = re.compile('^\s*<\?xml\s+(?:[^>]*?encoding=["\']([^"\'>]+))?')
38 _marker = [] # Create a new marker object.
41 class FSPageTemplate(FSObject, Script, PageTemplate):
42 "Wrapper for Page Template"
44 meta_type = 'Filesystem Page Template'
46 _owner = None # Unowned
48 manage_options=(
49 (
50 {'label':'Customize', 'action':'manage_main'},
51 {'label':'Test', 'action':'ZScriptHTML_tryForm'},
52 )
53 +Cacheable.manage_options
54 )
56 security = ClassSecurityInfo()
57 security.declareObjectProtected(View)
59 security.declareProtected(ViewManagementScreens, 'manage_main')
60 manage_main = Globals.DTMLFile('dtml/custpt', globals())
62 # Declare security for unprotected PageTemplate methods.
63 security.declarePrivate('pt_edit', 'write')
65 def __init__(self, id, filepath, fullname=None, properties=None):
66 FSObject.__init__(self, id, filepath, fullname, properties)
67 self.ZBindings_edit(self._default_bindings)
69 def _createZODBClone(self):
70 """Create a ZODB (editable) equivalent of this object."""
71 obj = ZopePageTemplate(self.getId(), self._text, self.content_type)
72 obj.expand = 0
73 obj.write(self.read())
74 return obj
76 # def ZCacheable_isCachingEnabled(self):
77 # return 0
79 def _readFile(self, reparse):
80 fp = expandpath(self._filepath)
81 file = open(fp, 'rU') # not 'rb', as this is a text file!
82 try:
83 data = file.read()
84 finally:
85 file.close()
87 if reparse:
88 # If we already have a content_type set it must come from a
89 # .metadata file and we should always honor that. The content
90 # type is initialized as text/html by default, so we only
91 # attempt further detection if the default is encountered.
92 # One previous misbehavior remains: It is not possible to
93 # force a text./html type if parsing detects it as XML.
94 if getattr(self, 'content_type', 'text/html') == 'text/html':
95 xml_info = xml_detect_re.match(data)
96 if xml_info:
97 # Smells like xml
98 # set "content_type" from the XML declaration
99 encoding = xml_info.group(1) or 'utf-8'
100 self.content_type = 'text/xml; charset=%s' % encoding
102 self.write(data)
104 security.declarePrivate('read')
105 def read(self):
106 # Tie in on an opportunity to auto-update
107 self._updateFromFS()
108 return FSPageTemplate.inheritedAttribute('read')(self)
110 ### The following is mainly taken from ZopePageTemplate.py ###
112 expand = 0
114 func_defaults = None
115 func_code = ZopePageTemplate.func_code
116 _default_bindings = ZopePageTemplate._default_bindings
118 security.declareProtected(View, '__call__')
120 def pt_macros(self):
121 # Tie in on an opportunity to auto-reload
122 self._updateFromFS()
123 return FSPageTemplate.inheritedAttribute('pt_macros')(self)
125 def pt_render(self, source=0, extra_context={}):
126 self._updateFromFS() # Make sure the template has been loaded.
128 if not source:
129 # If we have a conditional get, set status 304 and return
130 # no content
131 if _checkConditionalGET(self, extra_context):
132 return ''
134 result = FSPageTemplate.inheritedAttribute('pt_render')(
135 self, source, extra_context
136 )
137 if not source:
138 _setCacheHeaders(self, extra_context)
139 return result
141 security.declareProtected(ViewManagementScreens, 'pt_source_file')
142 def pt_source_file(self):
144 """ Return a file name to be compiled into the TAL code.
145 """
146 return 'file:%s' % self._filepath
148 security.declarePrivate( '_ZPT_exec' )
149 _ZPT_exec = ZopePageTemplate._exec.im_func
151 security.declarePrivate( '_exec' )
152 def _exec(self, bound_names, args, kw):
153 """Call a FSPageTemplate"""
154 try:
155 response = self.REQUEST.RESPONSE
156 except AttributeError:
157 response = None
158 # Read file first to get a correct content_type default value.
159 self._updateFromFS()
161 if not kw.has_key('args'):
162 kw['args'] = args
163 bound_names['options'] = kw
165 try:
166 response = self.REQUEST.RESPONSE
167 if not response.headers.has_key('content-type'):
168 response.setHeader('content-type', self.content_type)
169 except AttributeError:
170 pass
172 security=getSecurityManager()
173 bound_names['user'] = security.getUser()
175 # Retrieve the value from the cache.
176 keyset = None
177 if self.ZCacheable_isCachingEnabled():
178 # Prepare a cache key.
179 keyset = {
180 # Why oh why?
181 # All this code is cut and paste
182 # here to make sure that we
183 # dont call _getContext and hence can't cache
184 # Annoying huh?
185 'here': self.aq_parent.getPhysicalPath(),
186 'bound_names': bound_names}
187 result = self.ZCacheable_get(keywords=keyset)
188 if result is not None:
189 # Got a cached value.
190 return result
192 # Execute the template in a new security context.
193 security.addContext(self)
194 try:
195 result = self.pt_render(extra_context=bound_names)
196 if keyset is not None:
197 # Store the result in the cache.
198 self.ZCacheable_set(result, keywords=keyset)
199 return result
200 finally:
201 security.removeContext(self)
203 return result
205 # Copy over more methods
206 security.declareProtected(FTPAccess, 'manage_FTPget')
207 manage_FTPget = ZopePageTemplate.manage_FTPget.im_func
209 security.declareProtected(View, 'get_size')
210 get_size = ZopePageTemplate.get_size.im_func
211 getSize = get_size
213 security.declareProtected(ViewManagementScreens, 'PrincipiaSearchSource')
214 PrincipiaSearchSource = ZopePageTemplate.PrincipiaSearchSource.im_func
216 security.declareProtected(ViewManagementScreens, 'document_src')
217 document_src = ZopePageTemplate.document_src.im_func
219 pt_getContext = ZopePageTemplate.pt_getContext.im_func
221 ZScriptHTML_tryParams = ZopePageTemplate.ZScriptHTML_tryParams.im_func
223 source_dot_xml = Src()
225 setattr(FSPageTemplate, 'source.xml', FSPageTemplate.source_dot_xml)
226 setattr(FSPageTemplate, 'source.html', FSPageTemplate.source_dot_xml)
227 Globals.InitializeClass(FSPageTemplate)
229 registerFileExtension('pt', FSPageTemplate)
230 registerFileExtension('zpt', FSPageTemplate)
231 registerFileExtension('html', FSPageTemplate)
232 registerFileExtension('htm', FSPageTemplate)
233 registerMetaType('Page Template', FSPageTemplate)