예제 #1
0
class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable,
                       Traversable, PropertyManager):
    "Zope wrapper for Page Template using TAL, TALES, and METAL"

    meta_type = 'Page Template'
    output_encoding = 'iso-8859-15'  # provide default for old instances

    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': 'ustring', 'mode': 'w'},
                 {'id':'content_type', 'type':'string', 'mode': 'w'},
                 {'id':'output_encoding', 'type':'string', 'mode': 'w'},
                 {'id':'expand', 'type':'boolean', 'mode': 'w'},
                 )

    security = ClassSecurityInfo()
    security.declareObjectProtected(view)

    # protect methods from base class(es)
    security.declareProtected(view, '__call__')
    security.declareProtected(view_management_screens,
                              'read', 'ZScriptHTML_tryForm')

    def __init__(self, id, text=None, content_type='text/html', strict=True, 
                 output_encoding='utf-8'):
        self.id = id
        self.expand = 0                                                               
        self.ZBindings_edit(self._default_bindings)
        self.output_encoding = output_encoding
        # default content
        if not text:
            text = open(self._default_content_fn).read()
            content_type = 'text/html'
        self.pt_edit(text, content_type)


    security.declareProtected(change_page_templates, 'pt_edit')
    def pt_edit(self, text, content_type, keep_output_encoding=False):

        text = text.strip()
        
        is_unicode = isinstance(text, unicode)
        encoding = None
        output_encoding = None

        if content_type.startswith('text/xml'):

            if is_unicode:
                encoding = None
                output_encoding = 'utf-8'
            else:
                encoding = encodingFromXMLPreamble(text)
                output_encoding = 'utf-8'

        elif content_type.startswith('text/html'):

            charset = charsetFromMetaEquiv(text)

            if is_unicode:
                if charset:
                    encoding = None
                    output_encoding = charset
                else:
                    encoding = None
                    output_encoding = 'iso-8859-15'
            else:
                if charset:
                    encoding = charset
                    output_encoding = charset
                else:
                    encoding = 'iso-8859-15'
                    output_encoding = 'iso-8859-15'

        else:
            utext, encoding = convertToUnicode(text,
                                               content_type,
                                               preferred_encodings)
            output_encoding = encoding

        # for content updated through WebDAV, FTP 
        if not keep_output_encoding:
            self.output_encoding = output_encoding

        if not is_unicode:
            text = unicode(text, encoding)

        self.ZCacheable_invalidate()
        super(ZopePageTemplate, self).pt_edit(text, content_type)

    pt_editForm = PageTemplateFile('www/ptEdit', globals(),
                                   __name__='pt_editForm')
    pt_editForm._owner = None
    manage = manage_main = pt_editForm

    source_dot_xml = Src()

    security.declareProtected(change_page_templates, 'pt_editAction')
    def pt_editAction(self, REQUEST, title, text, content_type, expand):
        """Change the title and document."""

        if self.wl_isLocked():
            raise ResourceLockedError("File is locked via WebDAV")

        self.expand = expand

        # The ZMI edit view uses utf-8! So we can safely assume
        # that 'title' and 'text' are utf-8 encoded strings - hopefully

        self.pt_setTitle(title, 'utf-8') 
        text = unicode(text, 'utf-8')

        self.pt_edit(text, content_type, True)
        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 = guess_type(filename, text)   
#        if not content_type in ('text/html', 'text/xml'):
#            raise ValueError('Unsupported mimetype: %s' % content_type)

        self.pt_edit(text, content_type)
        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.pt_editForm()

    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 = None
        meth = aq_get(self, 'getPhysicalRoot', None)
        if meth is not None:
            root = meth()
        context = self._getContext()
        c = {'template': self,
             'here': context,
             'context': context,
             'container': self._getContainer(),
             'nothing': None,
             'options': {},
             'root': root,
             'request': aq_get(root, 'REQUEST', None),
             'modules': SecureModuleImporter,
             }
        return c

    def write(self, text):

        if not isinstance(text, unicode):
            text, encoding = convertToUnicode(text, 
                                              self.content_type,
                                              preferred_encodings)
            self.output_encoding = encoding

        self.ZCacheable_invalidate()
        ZopePageTemplate.inheritedAttribute('write')(self, text)

    def _exec(self, bound_names, args, kw):
        """Call a Page Template"""
        if 'args' not in kw:
            kw['args'] = args
        bound_names['options'] = kw

        request = aq_get(self, 'REQUEST', None)
        if request is not None:
            response = request.response
            if not response.headers.has_key('content-type'):
                response.setHeader('content-type', self.content_type)

        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:
            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)
        text = REQUEST.get('BODY', '')
        content_type = guess_type('', text) 
        self.pt_edit(text, content_type)
        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"
        result = self.read()
        return result.encode(self.output_encoding)

    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."""
        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 __setstate__(self, state):
        # Perform on-the-fly migration to unicode.
        # Perhaps it might be better to work with the 'generation' module 
        # here?
        _text = state.get('_text')
        if _text is not None and not isinstance(state['_text'], unicode):
            text, encoding = convertToUnicode(state['_text'], 
                                    state.get('content_type', 'text/html'), 
                                    preferred_encodings)
            state['_text'] = text
            state['output_encoding'] = encoding
        self.__dict__.update(state) 


    def pt_render(self, source=False, extra_context={}):
        result = PageTemplate.pt_render(self, source, extra_context)
        assert isinstance(result, unicode)
        return result


    def wl_isLocked(self):
        return 0
예제 #2
0
class ZopeSimplate(Script, Simplate, Historical, Cacheable, Traversable,
                   PropertyManager):
    "Zope wrapper for Simplate using python string replacement"

    if SUPPORTS_WEBDAV_LOCKS:
        __implements__ = (WriteLockInterface, )

    meta_type = 'Simplate'

    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':'simplate_editForm',
         'help': ('Simplates', 'Simplate_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'},
        {
            'id': 'value_paths',
            'type': 'lines',
            'mode': 'w'
        },
    )

    def __init__(self, id, text='(empty)', content_type=None, value_paths=[]):
        self.id = str(id)
        self.ZBindings_edit(self._default_bindings)
        if text is None:
            text = open(self._default_content_fn).read()
        self.simplate_edit(text, content_type)
        self.simplate_setValue_paths(value_paths)

    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',
        'simplate_editForm',
        'manage_main',
        'read',
        'ZScriptHTML_tryForm',
        'PrincipiaSearchSource',
        'document_src',
        #                              'source.html',
        #                              'source.xml',
    )

    security.declareProtected(
        'FTP access',
        'manage_FTPstat',
        'manage_FTPget',
        'manage_FTPlist',
    )

    simplate_editForm = PageTemplateFile('www/simplateEdit.pt',
                                         globals(),
                                         __name__='simplate_editForm')
    simplate_editForm._owner = None
    manage = manage_main = simplate_editForm

    security.declareProtected(
        'Change simplates',
        'simplate_editAction',
        'simplate_setTitle',
        'simplate_setValue_paths',
        'simplate_edit',
        'simplate_upload',
        'simplate_changePrefs',
    )

    def simplate_editAction(self, REQUEST, title, text, content_type,
                            value_paths):
        """Change the title and document."""
        if SUPPORTS_WEBDAV_LOCKS and self.wl_isLocked():
            raise ResourceLockedError, "File is locked via WebDAV"
        self.simplate_setTitle(title)
        self.simplate_setValue_paths(value_paths)
        self.simplate_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>" %
                       '<br>'.join(self._v_warnings))
        return self.simplate_editForm(manage_tabs_message=message)

    def simplate_setTitle(self, title):
        self._setPropValue('title', str(title))

    def simplate_setValue_paths(self, value_paths):
        self._setPropValue('value_paths', list(value_paths))
        self._cook()

    def simplate_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 StringType:
            if not file: raise ValueError, 'File not specified'
            file = file.read()

        self.write(file)
        message = 'Saved changes.'
        return self.simplate_editForm(manage_tabs_message=message)

    def simplate_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 ZopeSimplate.inheritedAttribute('manage_historyCompare')(
            self,
            rev1,
            rev2,
            REQUEST,
            historyComparisonResults=html_diff(rev1._text, rev2._text))

    def simplate_getContext(self):
        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

    def write(self, text):
        self.ZCacheable_invalidate()
        ZopeSimplate.inheritedAttribute('write')(self, text)

    def _exec(self, bound_names, args, kw):
        """Call a simplate"""
        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:
            result = self.simplate_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 simplates',
        '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 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_/Simplates/simplate.png',
            'alt': self.meta_type,
            'title': self.meta_type
        }, )
        if not self._v_cooked:
            self._cook()
        if self._v_errors:
            icons = icons + ({
                'path': 'misc_/Simplates/exclamation.gif',
                'alt': 'Error',
                'title': 'This simplate has an error'
            }, )
        return icons

    def __setstate__(self, state):
        # This is here for backward compatibility. :-(
        ZopeSimplate.inheritedAttribute('__setstate__')(self, state)

    def simplate_source_file(self):
        """Returns a file name to be compiled into the TAL code."""
        try:
            return '/'.join(self.getPhysicalPath())
        except:
            # This simplate is being compiled without an
            # acquisition context, so we don't know where it is. :-(
            return None

    if not SUPPORTS_WEBDAV_LOCKS:

        def wl_isLocked(self):
            return 0
예제 #3
0
class ZopePageTemplate(Script, PageTemplate, Cacheable,
                       Traversable, PropertyManager):
    "Zope wrapper for Page Template using TAL, TALES, and METAL"

    meta_type = 'Page Template'
    zmi_icon = 'far fa-file-code'
    output_encoding = 'utf-8'  # provide default for old instances

    __code__ = FuncCode((), 0)
    __defaults__ = None

    _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'},
        {'label': 'Test', 'action': 'ZScriptHTML_tryForm'},
    ) + PropertyManager.manage_options + \
        SimpleItem.manage_options + \
        Cacheable.manage_options

    _properties = (
        {'id': 'title', 'type': 'ustring', 'mode': 'w'},
        {'id': 'content_type', 'type': 'string', 'mode': 'w'},
        {'id': 'output_encoding', 'type': 'string', 'mode': 'w'},
        {'id': 'expand', 'type': 'boolean', 'mode': 'w'},
    )

    security = ClassSecurityInfo()
    security.declareObjectProtected(view)

    # protect methods from base class(es)
    security.declareProtected(view, '__call__')  # NOQA: D001
    security.declareProtected(view_management_screens,  # NOQA: D001
                              'read', 'ZScriptHTML_tryForm')

    def __init__(self, id, text=None, content_type='text/html', strict=True,
                 output_encoding='utf-8'):
        self.id = id
        self.expand = 0
        self.ZBindings_edit(self._default_bindings)
        self.output_encoding = output_encoding
        # default content
        if not text:
            with open(self._default_content_fn) as fd:
                text = fd.read()
            content_type = 'text/html'
        self.pt_edit(text, content_type)

    @security.protected(change_page_templates)
    def pt_edit(self, text, content_type, keep_output_encoding=False):
        if not isinstance(text, text_type):
            (text_decoded,
             source_encoding) = convertToUnicode(text, content_type,
                                                 preferred_encodings)
            output_encoding = source_encoding
        else:
            text_decoded = text
            source_encoding = None
            output_encoding = 'utf-8'

        # for content updated through WebDAV, FTP
        if not keep_output_encoding:
            self.output_encoding = output_encoding

        text_decoded = text_decoded.strip()

        self.ZCacheable_invalidate()
        super(ZopePageTemplate, self).pt_edit(text_decoded, content_type)

    pt_editForm = PageTemplateFile('www/ptEdit', globals(),
                                   __name__='pt_editForm')
    pt_editForm._owner = None
    manage = manage_main = pt_editForm

    source_dot_xml = Src()

    @security.protected(change_page_templates)
    def pt_editAction(self, REQUEST, title, text, content_type, expand=0):
        """Change the title and document."""

        if self.wl_isLocked():
            raise ResourceLockedError("File is locked.")

        self.expand = expand

        # The ZMI edit view uses utf-8! So we can safely assume
        # that 'title' and 'text' are utf-8 encoded strings - hopefully

        self.pt_setTitle(title, 'utf-8')
        self.pt_edit(text, content_type, True)
        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.protected(change_page_templates)
    def pt_setTitle(self, title, encoding='utf-8'):
        if not isinstance(title, text_type):
            title = title.decode(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.protected(change_page_templates)
    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.")

        if not file:
            return self.pt_editForm(manage_tabs_message='No file specified',
                                    manage_tabs_type='warning')

        if hasattr(file, 'read'):
            text = file.read()
            filename = file.filename
        else:
            filename = None
            text = file

        if isinstance(text, binary_type):
            content_type = guess_type(filename, text)
            (text,
             source_encoding) = convertToUnicode(text, content_type,
                                                 preferred_encodings)
        elif isinstance(text, text_type):
            content_type = guess_type(filename, text.encode('utf-8'))

        self.pt_edit(text, content_type)
        return self.pt_editForm(manage_tabs_message='Saved changes')

    def ZScriptHTML_tryParams(self):
        """Parameters to test the script with."""
        return []

    def pt_getContext(self, *args, **kw):
        root = None
        meth = aq_get(self, 'getPhysicalRoot', None)
        if meth is not None:
            root = meth()
        context = self._getContext()
        c = {'template': self,
             'here': context,
             'context': context,
             'container': self._getContainer(),
             'nothing': None,
             'options': {},
             'root': root,
             'request': aq_get(root, 'REQUEST', None),
             'modules': SecureModuleImporter,
             }
        return c

    def write(self, text):
        if not isinstance(text, text_type):
            text, encoding = convertToUnicode(text,
                                              self.content_type,
                                              preferred_encodings)
            self.output_encoding = encoding

        self.ZCacheable_invalidate()
        ZopePageTemplate.inheritedAttribute('write')(self, text)

    def _exec(self, bound_names, args, kw):
        """Call a Page Template"""
        if 'args' not in kw:
            kw['args'] = args
        bound_names['options'] = kw

        request = aq_get(self, 'REQUEST', None)
        if request is not None:
            response = request.response
            if 'content-type' not in response.headers:
                response.setHeader('content-type', self.content_type)

        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:
            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)

    if bbb.HAS_ZSERVER:
        @security.protected(change_page_templates)
        def PUT(self, REQUEST, RESPONSE):
            """ Handle HTTP PUT requests """

            self.dav__init(REQUEST, RESPONSE)
            self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
            text = REQUEST.get('BODY', '')
            content_type = guess_type('', text)
            self.pt_edit(text, content_type)
            RESPONSE.setStatus(204)
            return RESPONSE

        security.declareProtected(change_page_templates,  # NOQA: D001
                                  'manage_FTPput')
        manage_FTPput = PUT

        @security.protected(ftp_access)
        def manage_FTPget(self):
            "Get source for FTP download"
            result = self.read()
            return result.encode(self.output_encoding)

    @security.protected(view_management_screens)
    def html(self):
        return self.content_type == 'text/html'

    @security.protected(view_management_screens)
    def get_size(self):
        return len(self.read())

    security.declareProtected(view_management_screens, 'getSize')  # NOQA: D001
    getSize = get_size

    @security.protected(view_management_screens)
    def PrincipiaSearchSource(self):
        "Support for searching - the document's contents are searched."
        return self.read()

    @security.protected(view_management_screens)
    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 is not None and REQUEST.get('raw'):
            return self._text
        return self.read()

    @security.protected(view)
    def pt_source_file(self):
        """Returns a file name to be compiled into the TAL code."""
        try:
            return '/'.join(self.getPhysicalPath())
        except Exception:
            # This page template is being compiled without an
            # acquisition context, so we don't know where it is. :-(
            return None

    def __setstate__(self, state):
        # Perform on-the-fly migration to text_type.
        # Perhaps it might be better to work with the 'generation' module
        # here?
        _text = state.get('_text')
        if _text is not None and not isinstance(state['_text'], text_type):
            text, encoding = convertToUnicode(
                state['_text'],
                state.get('content_type', 'text/html'),
                preferred_encodings)
            state['_text'] = text
            state['output_encoding'] = encoding
        self.__dict__.update(state)

    def pt_render(self, source=False, extra_context={}):
        result = PageTemplate.pt_render(self, source, extra_context)
        assert isinstance(result, text_type)
        return result

    def wl_isLocked(self):
        return 0
예제 #4
0
class PageTemplateFile(SimpleItem, Script, PageTemplate, Traversable):
    """Zope 2 implementation of a PageTemplate loaded from a file."""

    meta_type = 'Page Template (File)'

    func_defaults = None
    func_code = FuncCode((), 0)
    _v_last_read = 0

    # needed by AccessControl.class_init.InitializeClass
    _need__name__ = 1

    _default_bindings = {'name_subpath': 'traverse_subpath'}

    security = ClassSecurityInfo()
    security.declareProtected('View management screens', 'read',
                              'document_src')

    def __init__(self, filename, _prefix=None, **kw):
        name = kw.pop('__name__', None)

        basepath, ext = os.path.splitext(filename)

        if name:
            self.id = self.__name__ = name
            self._need__name__ = 0
        else:
            self.id = self.__name__ = os.path.basename(basepath)

        if _prefix:
            if isinstance(_prefix, str):
                filename = os.path.join(_prefix, filename)
            else:
                filename = os.path.join(package_home(_prefix), filename)

        if not ext:
            filename = filename + '.zpt'

        self.filename = filename

    def pt_getContext(self):
        root = None
        meth = aq_get(self, 'getPhysicalRoot', None)
        if meth is not None:
            root = meth()
        context = self._getContext()
        c = {
            'template': self,
            'here': context,
            'context': context,
            'container': self._getContainer(),
            'nothing': None,
            'options': {},
            'root': root,
            'request': aq_get(root, 'REQUEST', None),
            'modules': SecureModuleImporter,
        }
        return c

    def _exec(self, bound_names, args, kw):
        """Call a Page Template"""
        self._cook_check()
        if 'args' not in kw:
            kw['args'] = args
        bound_names['options'] = kw

        request = aq_get(self, 'REQUEST', None)
        if request is not None:
            response = request.response
            if not response.headers.has_key('content-type'):
                response.setHeader('content-type', self.content_type)

        # Execute the template in a new security context.
        security = getSecurityManager()
        bound_names['user'] = security.getUser()
        security.addContext(self)

        try:
            context = self.pt_getContext()
            context.update(bound_names)
            return self.pt_render(extra_context=bound_names)
        finally:
            security.removeContext(self)

    def pt_macros(self):
        self._cook_check()
        return PageTemplate.pt_macros(self)

    def pt_source_file(self):
        """Returns a file name to be compiled into the TAL code."""
        return self.__name__  # Don't reveal filesystem paths

    def _cook_check(self):
        import Globals  # for data
        if self._v_last_read and not Globals.DevelopmentMode:
            return
        __traceback_info__ = self.filename
        try:
            mtime = os.path.getmtime(self.filename)
        except OSError:
            mtime = 0
        if self._v_program is not None and mtime == self._v_last_read:
            return
        f = open(self.filename, "rb")
        try:
            text = f.read(XML_PREFIX_MAX_LENGTH)
        except:
            f.close()
            raise
        t = sniff_type(text)
        if t != "text/xml":
            # For HTML, we really want the file read in text mode:
            f.close()
            f = open(self.filename, 'U')
            text = ''
        text += f.read()
        f.close()
        self.pt_edit(text, t)
        self._cook()
        if self._v_errors:
            LOG.error('Error in template %s' % '\n'.join(self._v_errors))
            return
        self._v_last_read = mtime

    def document_src(self, REQUEST=None, RESPONSE=None):
        """Return expanded document source."""

        if RESPONSE is not None:
            # Since _cook_check() can cause self.content_type to change,
            # we have to make sure we call it before setting the
            # Content-Type header.
            self._cook_check()
            RESPONSE.setHeader('Content-Type', 'text/plain')
        return self.read()

    def _get__roles__(self):
        imp = getattr(aq_parent(aq_inner(self)), '%s__roles__' % self.__name__)
        if hasattr(imp, '__of__'):
            return imp.__of__(self)
        return imp

    __roles__ = ComputedAttribute(_get__roles__, 1)

    def getOwner(self, info=0):
        """Gets the owner of the executable object.

        This method is required of all objects that go into
        the security context stack.  Since this object came from the
        filesystem, it is owned by no one managed by Zope.
        """
        return None

    def __getstate__(self):
        from ZODB.POSException import StorageError
        raise StorageError, ("Instance of AntiPersistent class %s "
                             "cannot be stored." % self.__class__.__name__)
예제 #5
0
class PageTemplateFile(SimpleItem, Script, PageTemplate, Traversable):
    """Zope 2 implementation of a PageTemplate loaded from a file."""

    meta_type = 'Page Template (File)'

    __code__ = FuncCode((), 0)
    __defaults__ = None
    _v_last_read = 0

    # needed by AccessControl.class_init.InitializeClass
    _need__name__ = 1

    _default_bindings = {'name_subpath': 'traverse_subpath'}

    security = ClassSecurityInfo()
    security.declareProtected(  # NOQA: D001
        'View management screens', 'read', 'document_src')

    def __init__(self,
                 filename,
                 _prefix=None,
                 encoding=DEFAULT_ENCODING,
                 **kw):
        name = kw.pop('__name__', None)
        self.encoding = encoding
        basepath, ext = os.path.splitext(filename)

        if name:
            self.id = self.__name__ = name
            self._need__name__ = 0
        else:
            self.id = self.__name__ = os.path.basename(basepath)

        if _prefix:
            if isinstance(_prefix, str):
                filename = os.path.join(_prefix, filename)
            else:
                filename = os.path.join(package_home(_prefix), filename)

        if not ext:
            filename = filename + '.zpt'

        self.filename = filename

    def pt_getContext(self):
        root = None
        meth = aq_get(self, 'getPhysicalRoot', None)
        if callable(meth):
            root = meth()
        context = self._getContext()
        c = {
            'template': self,
            'here': context,
            'context': context,
            'container': self._getContainer(),
            'nothing': None,
            'options': {},
            'root': root,
            'request': aq_get(root, 'REQUEST', None),
            'modules': SecureModuleImporter,
        }
        return c

    def _exec(self, bound_names, args, kw):
        """Call a Page Template"""
        self._cook_check()
        if 'args' not in kw:
            kw['args'] = args
        bound_names['options'] = kw

        request = aq_get(self, 'REQUEST', None)
        if request is not None:
            response = request.response
            if 'content-type' not in response.headers:
                response.setHeader('content-type', self.content_type)

        # Execute the template in a new security context.
        security = getSecurityManager()
        bound_names['user'] = security.getUser()
        security.addContext(self)

        try:
            context = self.pt_getContext()
            context.update(bound_names)
            return self.pt_render(extra_context=bound_names)
        finally:
            security.removeContext(self)

    def pt_macros(self):
        self._cook_check()
        return PageTemplate.pt_macros(self)

    def pt_source_file(self):
        """Returns a file name to be compiled into the TAL code."""
        return self.__name__  # Don't reveal filesystem paths

    def _cook_check(self):
        if self._v_last_read and not getConfiguration().debug_mode:
            return
        __traceback_info__ = self.filename
        try:
            mtime = os.path.getmtime(self.filename)
        except OSError:
            mtime = 0
        if self._v_program is not None and mtime == self._v_last_read:
            return
        text, type_ = self._read_file()
        self.pt_edit(text, type_)
        self._cook()
        if self._v_errors:
            LOG.error('Error in template %s' % '\n'.join(self._v_errors))
            return
        self._v_last_read = mtime

    def _prepare_html(self, text):
        match = meta_pattern.search(text)
        if match is not None:
            type_, encoding = (x.decode(self.encoding) for x in match.groups())
            # TODO: Shouldn't <meta>/<?xml?> stripping
            # be in PageTemplate.__call__()?
            text = meta_pattern.sub(b"", text)
        else:
            type_ = None
            encoding = self.encoding
        text = text.decode(encoding)
        return text, type_

    def _prepare_xml(self, text):
        if not isinstance(text, six.text_type):
            encoding = encodingFromXMLPreamble(text, default=self.encoding)
            text = text.decode(encoding)
        return text, 'text/xml'

    def _read_file(self):
        __traceback_info__ = self.filename
        with open(self.filename, "rb") as f:
            text = f.read(XML_PREFIX_MAX_LENGTH)
            type_ = sniff_type(text)
            text += f.read()
        if type_ != "text/xml":
            text, type_ = self._prepare_html(text)
        else:
            text, type_ = self._prepare_xml(text)
        f.close()
        return text, type_

    def document_src(self, REQUEST=None, RESPONSE=None):
        """Return expanded document source."""

        if RESPONSE is not None:
            # Since _cook_check() can cause self.content_type to change,
            # we have to make sure we call it before setting the
            # Content-Type header.
            self._cook_check()
            RESPONSE.setHeader('Content-Type', 'text/plain')
        return self.read()

    def _get__roles__(self):
        imp = getattr(aq_parent(aq_inner(self)), '%s__roles__' % self.__name__)
        if hasattr(imp, '__of__'):
            return imp.__of__(self)
        return imp

    __roles__ = ComputedAttribute(_get__roles__, 1)

    def getOwner(self, info=0):
        """Gets the owner of the executable object.

        This method is required of all objects that go into
        the security context stack.  Since this object came from the
        filesystem, it is owned by no one managed by Zope.
        """
        return None

    def __getstate__(self):
        from ZODB.POSException import StorageError
        raise StorageError("Instance of AntiPersistent class %s "
                           "cannot be stored." % self.__class__.__name__)