Back to index

plone3  3.1.7
FSPageTemplate.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """ Customizable page templates that come from the filesystem.
00014 
00015 $Id: FSPageTemplate.py 76464 2007-06-07 15:38:16Z tseaver $
00016 """
00017 
00018 import re
00019 
00020 import Globals
00021 from AccessControl import ClassSecurityInfo
00022 from AccessControl import getSecurityManager
00023 from OFS.Cache import Cacheable
00024 from Products.PageTemplates.PageTemplate import PageTemplate
00025 from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate, Src
00026 from Shared.DC.Scripts.Script import Script
00027 
00028 from DirectoryView import registerFileExtension
00029 from DirectoryView import registerMetaType
00030 from FSObject import FSObject
00031 from permissions import FTPAccess
00032 from permissions import View
00033 from permissions import ViewManagementScreens
00034 from utils import _checkConditionalGET
00035 from utils import _dtmldir
00036 from utils import _setCacheHeaders
00037 
00038 
00039 from Products.PageTemplates.utils import encodingFromXMLPreamble, charsetFromMetaEquiv
00040 
00041 xml_detect_re = re.compile('^\s*<\?xml\s+(?:[^>]*?encoding=["\']([^"\'>]+))?')
00042 _marker = object()
00043 
00044 
00045 class FSPageTemplate(FSObject, Script, PageTemplate):
00046 
00047     """Wrapper for Page Template.
00048     """
00049 
00050     meta_type = 'Filesystem Page Template'
00051     _owner = None  # Unowned
00052 
00053     manage_options=({'label':'Customize', 'action':'manage_main'},
00054                     {'label':'Test', 'action':'ZScriptHTML_tryForm'},
00055                    )
00056 
00057     security = ClassSecurityInfo()
00058     security.declareObjectProtected(View)
00059 
00060     security.declareProtected(ViewManagementScreens, 'manage_main')
00061     manage_main = Globals.DTMLFile('custpt', _dtmldir)
00062 
00063     # Declare security for unprotected PageTemplate methods.
00064     security.declarePrivate('pt_edit', 'write')
00065 
00066     def __init__(self, id, filepath, fullname=None, properties=None):
00067         FSObject.__init__(self, id, filepath, fullname, properties)
00068         self.ZBindings_edit(self._default_bindings)
00069 
00070     def _createZODBClone(self):
00071         """Create a ZODB (editable) equivalent of this object."""
00072         obj = ZopePageTemplate(self.getId(), self._text, self.content_type)
00073         obj.expand = 0
00074         obj.write(self.read())
00075         return obj
00076 
00077 #    def ZCacheable_isCachingEnabled(self):
00078 #        return 0
00079 
00080     def _readFile(self, reparse):
00081         """Read the data from the filesystem.
00082         """
00083         file = open(self._filepath, 'rU') # not 'rb', as this is a text file!
00084         try:
00085             data = file.read()
00086         finally:
00087             file.close()
00088 
00089         if reparse:
00090             # If we already have a content_type set it must come from a
00091             # .metadata file and we should always honor that. The content
00092             # type is initialized as text/html by default, so we only
00093             # attempt further detection if the default is encountered.
00094             # One previous misbehavior remains: It is not possible to
00095             # force a text./html type if parsing detects it as XML.
00096             encoding = None
00097             if getattr(self, 'content_type', 'text/html') == 'text/html':
00098                 xml_info = xml_detect_re.match(data)
00099                 if xml_info:
00100                     # Smells like xml
00101                     # set "content_type" from the XML declaration
00102                     encoding = xml_info.group(1) or 'utf-8'
00103                     self.content_type = 'text/xml; charset=%s' % encoding
00104 
00105 
00106             if encoding is None:
00107                 charset = getattr(self, 'charset', None)
00108                 if charset is None:
00109                     if self.content_type.startswith('text/html'):
00110                         charset = charsetFromMetaEquiv(data) or 'iso-8859-15'
00111                     elif self.content_type.startswith('text/xml'):
00112                         charset = encodingFromXMLPreamble(data)
00113                     else:
00114                         raise ValueError('Unsupported content-type: %s' % self.content_type)
00115 
00116                 if not isinstance(data, unicode):
00117                     data = unicode(data, charset)
00118             else:
00119                 if not isinstance(data, unicode):
00120                     data = unicode(data, encoding)
00121 
00122             self.write(data)
00123 
00124 
00125     security.declarePrivate('read')
00126     def read(self):
00127         # Tie in on an opportunity to auto-update
00128         self._updateFromFS()
00129         return FSPageTemplate.inheritedAttribute('read')(self)
00130 
00131     ### The following is mainly taken from ZopePageTemplate.py ###
00132 
00133     expand = 0
00134 
00135     func_defaults = None
00136     func_code = ZopePageTemplate.func_code
00137     _default_bindings = ZopePageTemplate._default_bindings
00138 
00139     security.declareProtected(View, '__call__')
00140 
00141     def pt_macros(self):
00142         # Tie in on an opportunity to auto-reload
00143         self._updateFromFS()
00144         return FSPageTemplate.inheritedAttribute('pt_macros')(self)
00145 
00146     def pt_render(self, source=0, extra_context={}):
00147         self._updateFromFS()  # Make sure the template has been loaded.
00148 
00149         if not source:
00150             # If we have a conditional get, set status 304 and return
00151             # no content
00152             if _checkConditionalGET(self, extra_context):
00153                 return ''
00154 
00155         result = FSPageTemplate.inheritedAttribute('pt_render')(
00156                                 self, source, extra_context
00157                                 )
00158         if not source:
00159             _setCacheHeaders(self, extra_context)
00160         return result
00161 
00162     security.declareProtected(ViewManagementScreens, 'pt_source_file')
00163     def pt_source_file(self):
00164 
00165         """ Return a file name to be compiled into the TAL code.
00166         """
00167         return 'file:%s' % self._filepath
00168 
00169     security.declarePrivate( '_ZPT_exec' )
00170     _ZPT_exec = ZopePageTemplate._exec.im_func
00171 
00172     security.declarePrivate( '_exec' )
00173     def _exec(self, bound_names, args, kw):
00174         """Call a FSPageTemplate"""
00175         try:
00176             response = self.REQUEST.RESPONSE
00177         except AttributeError:
00178             response = None
00179         # Read file first to get a correct content_type default value.
00180         self._updateFromFS()
00181 
00182         if not kw.has_key('args'):
00183             kw['args'] = args
00184         bound_names['options'] = kw
00185 
00186         try:
00187             response = self.REQUEST.RESPONSE
00188             if not response.headers.has_key('content-type'):
00189                 response.setHeader('content-type', self.content_type)
00190         except AttributeError:
00191             pass
00192 
00193         security=getSecurityManager()
00194         bound_names['user'] = security.getUser()
00195 
00196         # Retrieve the value from the cache.
00197         keyset = None
00198         if self.ZCacheable_isCachingEnabled():
00199             # Prepare a cache key.
00200             keyset = {
00201                       # Why oh why?
00202                       # All this code is cut and paste
00203                       # here to make sure that we
00204                       # dont call _getContext and hence can't cache
00205                       # Annoying huh?
00206                       'here': self.aq_parent.getPhysicalPath(),
00207                       'bound_names': bound_names}
00208             result = self.ZCacheable_get(keywords=keyset)
00209             if result is not None:
00210                 # Got a cached value.
00211                 return result
00212 
00213         # Execute the template in a new security context.
00214         security.addContext(self)
00215         try:
00216             result = self.pt_render(extra_context=bound_names)
00217             if keyset is not None:
00218                 # Store the result in the cache.
00219                 self.ZCacheable_set(result, keywords=keyset)
00220             return result
00221         finally:
00222             security.removeContext(self)
00223 
00224         return result
00225 
00226     # Copy over more methods
00227     security.declareProtected(FTPAccess, 'manage_FTPget')
00228     manage_FTPget = ZopePageTemplate.manage_FTPget.im_func
00229 
00230     security.declareProtected(View, 'get_size')
00231     get_size = ZopePageTemplate.get_size.im_func
00232     getSize = get_size
00233 
00234     security.declareProtected(ViewManagementScreens, 'PrincipiaSearchSource')
00235     PrincipiaSearchSource = ZopePageTemplate.PrincipiaSearchSource.im_func
00236 
00237     security.declareProtected(ViewManagementScreens, 'document_src')
00238     document_src = ZopePageTemplate.document_src.im_func
00239 
00240     pt_getContext = ZopePageTemplate.pt_getContext.im_func
00241 
00242     ZScriptHTML_tryParams = ZopePageTemplate.ZScriptHTML_tryParams.im_func
00243 
00244     source_dot_xml = Src()
00245 
00246 setattr(FSPageTemplate, 'source.xml',  FSPageTemplate.source_dot_xml)
00247 setattr(FSPageTemplate, 'source.html', FSPageTemplate.source_dot_xml)
00248 Globals.InitializeClass(FSPageTemplate)
00249 
00250 registerFileExtension('pt', FSPageTemplate)
00251 registerFileExtension('zpt', FSPageTemplate)
00252 registerFileExtension('html', FSPageTemplate)
00253 registerFileExtension('htm', FSPageTemplate)
00254 registerMetaType('Page Template', FSPageTemplate)