예제 #1
0
class FSFile(FSObject):
    """FSFiles act like images but are not directly
    modifiable from the management interface."""
    # Note that OFS.Image.File is not a base class because it is mutable.

    meta_type = 'Filesystem File'

    manage_options = ({
        'label': 'Customize',
        'action': 'manage_main'
    }, ) + Cacheable.manage_options

    security = ClassSecurityInfo()
    security.declareObjectProtected(View)

    def __init__(self, id, filepath, fullname=None, properties=None):
        id = fullname or id  # Use the whole filename.
        FSObject.__init__(self, id, filepath, fullname, properties)

    security.declareProtected(ViewManagementScreens, 'manage_main')
    manage_main = Globals.DTMLFile('custfile', _dtmldir)
    content_type = 'unknown/unknown'

    def _createZODBClone(self):
        return File(self.getId(), '', self._readFile(1))

    def _get_content_type(self, file, body, id, content_type=None):
        headers = getattr(file, 'headers', None)
        if headers and headers.has_key('content-type'):
            content_type = headers['content-type']
        else:
            if type(body) is not type(''): body = body.data
            content_type, enc = guess_content_type(
                getattr(file, 'filename', id), body, content_type)
        return content_type

    def _readFile(self, reparse):
        fp = expandpath(self._filepath)
        file = open(fp, 'rb')
        try:
            data = file.read()
        finally:
            file.close()
        if reparse or self.content_type == 'unknown/unknown':
            self.ZCacheable_invalidate()
            self.content_type = self._get_content_type(file, data, self.id)
        return data

    #### The following is mainly taken from OFS/File.py ###

    __str__ = File.__str__

    security.declareProtected(View, 'index_html')

    def index_html(self, REQUEST, RESPONSE):
        """
        The default view of the contents of a File or Image.

        Returns the contents of the file or image.  Also, sets the
        Content-Type HTTP header to the objects content type.
        """
        self._updateFromFS()
        data = self._readFile(0)
        # HTTP If-Modified-Since header handling.
        header = REQUEST.get_header('If-Modified-Since', None)
        if header is not None:
            header = string.split(header, ';')[0]
            # Some proxies seem to send invalid date strings for this
            # header. If the date string is not valid, we ignore it
            # rather than raise an error to be generally consistent
            # with common servers such as Apache (which can usually
            # understand the screwy date string as a lucky side effect
            # of the way they parse it).
            try:
                mod_since = long(DateTime(header).timeTime())
            except:
                mod_since = None
            if mod_since is not None:
                last_mod = self._file_mod_time
                if last_mod > 0 and last_mod <= mod_since:
                    # Set header values since apache caching will return
                    # Content-Length of 0 in response if size is not set here
                    RESPONSE.setHeader('Last-Modified', rfc1123_date(last_mod))
                    RESPONSE.setHeader('Content-Type', self.content_type)
                    RESPONSE.setHeader('Content-Length', self.get_size())
                    RESPONSE.setStatus(304)
                    return ''

        RESPONSE.setHeader('Last-Modified', rfc1123_date(self._file_mod_time))
        RESPONSE.setHeader('Content-Type', self.content_type)
        RESPONSE.setHeader('Content-Length', len(data))

        self.ZCacheable_set(None)
        return data

    security.declareProtected(View, 'getContentType')

    def getContentType(self):
        """Get the content type of a file or image.

        Returns the content type (MIME type) of a file or image.
        """
        self._updateFromFS()
        return self.content_type

    security.declareProtected(FTPAccess, 'manage_FTPget')
    manage_FTPget = index_html
예제 #2
0
class FSSTXMethod( FSObject ):
    """
        A chunk of StructuredText, rendered as a skin method of a
        CMFSite.
    """

    meta_type = 'Filesystem STX Method'

    manage_options=( { 'label'      : 'Customize'
                     , 'action'     : 'manage_main'
                     }
                   , { 'label'      : 'View'
                     , 'action'     : ''
                     , 'help'       : ('OFSP'
                                      ,'DTML-DocumentOrMethod_View.stx'
                                      )
                     }
                   )

    security = ClassSecurityInfo()
    security.declareObjectProtected( View )

    security.declareProtected( ViewManagementScreens, 'manage_main')
    manage_main = Globals.DTMLFile( 'custstx', _dtmldir )

    #
    #   FSObject interface
    #
    def _createZODBClone(self):
        """
            Create a ZODB (editable) equivalent of this object.
        """
        raise NotImplementedError, "See next week's model."

    def _readFile( self, reparse ):

        fp = expandpath( self._filepath )
        file = open( fp, 'r' )  # not binary, we want CRLF munging here.

        try:
            data = file.read()
        finally:
            file.close()

        self.raw = data

        if reparse:
            self.cook()

    #
    #   "Wesleyan" interface (we need to be "methodish").
    #
    class func_code:
        pass

    func_code=func_code()
    func_code.co_varnames= ()
    func_code.co_argcount=0
    func_code.__roles__=()

    func_defaults__roles__=()
    func_defaults=()

    index_html = None   # No accidental acquisition

    default_content_type = 'text/html'

    def cook( self ):
        if not hasattr( self, '_v_cooked' ):
            self._v_cooked = HTML(self.raw, level=1, header=0)
        return self._v_cooked

    _default_template = Globals.HTML( """\
<dtml-var standard_html_header>
<div class="Desktop">
<dtml-var cooked>
</div>
<dtml-var standard_html_footer>""" )

    def __call__( self, REQUEST={}, RESPONSE=None, **kw ):
        """
            Return our rendered StructuredText.
        """
        self._updateFromFS()

        if RESPONSE is not None:
            RESPONSE.setHeader( 'Content-Type', 'text/html' )
        return self._render(REQUEST, RESPONSE, **kw)

    security.declarePrivate( '_render' )
    def _render( self, REQUEST={}, RESPONSE=None, **kw ):
        """
            Find the appropriate rendering template and use it to
            render us.
        """
        template = getattr( self, 'stxmethod_view', self._default_template )

        if getattr( template, 'isDocTemp', 0 ):
            posargs = ( self, REQUEST, RESPONSE )
        else:
            posargs = ()

        return template(*posargs, **{ 'cooked' : self.cook() } )

    security.declareProtected( FTPAccess, 'manage_FTPget' )
    def manage_FTPget( self ):
        """
            Fetch our source for delivery via FTP.
        """
        return self.raw

    security.declareProtected( ViewManagementScreens, 'PrincipiaSearchSource' )
    def PrincipiaSearchSource( self ):
        """
            Fetch our source for indexing in a catalog.
        """
        return self.raw

    security.declareProtected( ViewManagementScreens, 'document_src' )
    def document_src( self ):
        """
            Fetch our source for indexing in a catalog.
        """
        return self.raw
예제 #3
0
class FSPythonScript (FSObject, Script):
    """FSPythonScripts act like Python Scripts but are not directly
    modifiable from the management interface."""

    meta_type = 'Filesystem Script (Python)'
    _params = _body = ''
    _v_f = None

    manage_options=(
        (
            {'label':'Customize', 'action':'manage_main'},
            {'label':'Test',
             'action':'ZScriptHTML_tryForm',
             'help': ('PythonScripts', 'PythonScript_test.stx')},
            )
        )

    # Use declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(View)
    security.declareProtected(View, 'index_html',)
    # Prevent the bindings from being edited TTW
    security.declarePrivate('ZBindings_edit','ZBindingsHTML_editForm','ZBindingsHTML_editAction')

    security.declareProtected(ViewManagementScreens, 'manage_main')
    manage_main = Globals.DTMLFile('custpy', _dtmldir)

    def _createZODBClone(self):
        """Create a ZODB (editable) equivalent of this object."""
        obj = PythonScript(self.getId())
        obj.write(self.read())
        return obj

    def _readFile(self, reparse):
        """Read the data from the filesystem.
        
        Read the file (indicated by exandpath(self._filepath), and parse the
        data if necessary.
        """
        fp = expandpath(self._filepath)
        file = open(fp, 'r')
        try: data = file.read()
        finally: file.close()
        if reparse:
            self._write(data, reparse)

    def _validateProxy(self, roles=None):
        pass

    def __render_with_namespace__(self, namespace):
        '''Calls the script.'''
        self._updateFromFS()
        return Script.__render_with_namespace__(self, namespace)

    def __call__(self, *args, **kw):
        '''Calls the script.'''
        self._updateFromFS()
        return Script.__call__(self, *args, **kw)

    #### The following is mainly taken from PythonScript.py ###

    def _exec(self, bound_names, args, kw):
        """Call a Python Script

        Calling a Python Script is an actual function invocation.
        """
        # Prepare the function.
        f = self._v_f
        if f is None:
            # The script has errors.
            raise RuntimeError, '%s has errors.' % self._filepath

        __traceback_info__ = bound_names, args, kw, self.func_defaults

        if bound_names:
            # Updating func_globals directly is not thread safe here.
            # In normal PythonScripts, every thread has its own
            # copy of the function.  But in FSPythonScripts
            # there is only one copy.  So here's another way.
            new_globals = f.func_globals.copy()
            new_globals.update(bound_names)
            if f.func_defaults:
                f = new.function(f.func_code, new_globals, f.func_name,
                                 f.func_defaults)
            else:
                f = new.function(f.func_code, new_globals, f.func_name)

        # Execute the function in a new security context.
        security=getSecurityManager()
        security.addContext(self)
        try:
            result = apply(f, args, kw)
            return result
        finally:
            security.removeContext(self)

    security.declareProtected(ViewManagementScreens,
      'read', 'getModTime', 'get_size',
      'ZScriptHTML_tryForm', 'PrincipiaSearchSource',
      'document_src', 'params', 'body')

    def ZScriptHTML_tryParams(self):
        """Parameters to test the script with."""
        param_names = []
        for name in split(self._params, ','):
            name = strip(name)
            if name and name[0] != '*':
                param_names.append(split(name, '=', 1)[0])
        return param_names

    def read(self):
        self._updateFromFS()
        return self._source
                
    def document_src(self, REQUEST=None, RESPONSE=None):
        """Return unprocessed document source."""

        if RESPONSE is not None:
            RESPONSE.setHeader('Content-Type', 'text/plain')
        return self._source

    def PrincipiaSearchSource(self):
        "Support for searching - the document's contents are searched."
        return "%s\n%s" % (self._params, self._body)

    def params(self): return self._params
    def body(self): return self._body
    def get_size(self): return len(self.read())

    security.declareProtected(FTPAccess, 'manage_FTPget')
    def manage_FTPget(self):
        "Get source for FTP download"
        self.REQUEST.RESPONSE.setHeader('Content-Type', 'text/plain')
        return self.read()

    def _write(self, text, compile):
        '''
        Parses the source, storing the body, params, title, bindings,
        and source in self.  If compile is set, compiles the
        function.
        '''
        ps = PythonScript(self.id)
        ps.write(text)
        if compile:
            ps._makeFunction(1)
            self._v_f = f = ps._v_f
            if f is not None:
                self.func_code = f.func_code
                self.func_defaults = f.func_defaults
            else:
                # There were errors in the compile.
                # No signature.
                self.func_code = None
                self.func_defaults = None
        self._body = ps._body
        self._params = ps._params
        self.title = ps.title
        self._setupBindings(ps.getBindingAssignments().getAssignedNames())
        self._source = ps.read()  # Find out what the script sees.

    def func_defaults(self):
        # This ensures func_code and func_defaults are
        # set when the code hasn't been compiled yet,
        # just in time for mapply().  Truly odd, but so is mapply(). :P
        self._updateFromFS()
        return self.__dict__.get('func_defaults', None)
    func_defaults = ComputedAttribute(func_defaults, 1)

    def func_code(self):
        # See func_defaults.
        self._updateFromFS()
        return self.__dict__.get('func_code', None)
    func_code = ComputedAttribute(func_code, 1)

    def title(self):
        # See func_defaults.
        self._updateFromFS()
        return self.__dict__.get('title', None)
    title = ComputedAttribute(title, 1)
예제 #4
0
파일: FSFile.py 프로젝트: bendavis78/zope
class FSFile(FSObject):
    """FSFiles act like images but are not directly
    modifiable from the management interface."""
    # Note that OFS.Image.File is not a base class because it is mutable.

    meta_type = 'Filesystem File'

    manage_options = ({
        'label': 'Customize',
        'action': 'manage_main'
    }, ) + Cacheable.manage_options

    security = ClassSecurityInfo()
    security.declareObjectProtected(View)

    def __init__(self, id, filepath, fullname=None, properties=None):
        id = fullname or id  # Use the whole filename.
        FSObject.__init__(self, id, filepath, fullname, properties)

    security.declareProtected(ViewManagementScreens, 'manage_main')
    manage_main = Globals.DTMLFile('custfile', _dtmldir)
    content_type = 'unknown/unknown'

    def _createZODBClone(self):
        return File(self.getId(), '', self._readFile(1))

    def _get_content_type(self, file, body, id, content_type=None):
        # Consult self.content_type first, this is either
        # the default (unknown/unknown) or it got a value from a
        # .metadata file
        default_type = 'unknown/unknown'
        if getattr(self, 'content_type', default_type) != default_type:
            return self.content_type

        # Next, look at file headers
        headers = getattr(file, 'headers', None)
        if headers and headers.has_key('content-type'):
            content_type = headers['content-type']
        else:
            # Last resort: Use the (imperfect) content type guessing
            # mechanism from OFS.Image, which ultimately uses the
            # Python mimetypes module.
            if not isinstance(body, basestring):
                body = body.data
            content_type, enc = guess_content_type(
                getattr(file, 'filename', id), body, content_type)
            if (enc is None and (content_type.startswith('text/')
                                 or content_type.startswith('application/'))
                    and body.startswith(codecs.BOM_UTF8)):
                content_type += '; charset=utf-8'

        return content_type

    def _readFile(self, reparse):
        fp = expandpath(self._filepath)
        file = open(fp, 'rb')
        try:
            data = file.read()
        finally:
            file.close()
        if reparse or self.content_type == 'unknown/unknown':
            self.ZCacheable_invalidate()
            self.content_type = self._get_content_type(file, data, self.id)
        return data

    #### The following is mainly taken from OFS/File.py ###

    def __str__(self):
        self._updateFromFS()
        return str(self._readFile(0))

    def modified(self):
        return self.getModTime()

    security.declareProtected(View, 'index_html')

    def index_html(self, REQUEST, RESPONSE):
        """
        The default view of the contents of a File or Image.

        Returns the contents of the file or image.  Also, sets the
        Content-Type HTTP header to the objects content type.
        """
        self._updateFromFS()
        view = _ViewEmulator().__of__(self)

        # If we have a conditional get, set status 304 and return
        # no content
        if _checkConditionalGET(view, extra_context={}):
            return ''

        RESPONSE.setHeader('Content-Type', self.content_type)

        # old-style If-Modified-Since header handling.
        if self._setOldCacheHeaders():
            # Make sure the CachingPolicyManager gets a go as well
            _setCacheHeaders(view, extra_context={})
            return ''

        data = self._readFile(0)
        data_len = len(data)
        RESPONSE.setHeader('Content-Length', data_len)

        #There are 2 Cache Managers which can be in play....
        #need to decide which to use to determine where the cache headers
        #are decided on.
        if self.ZCacheable_getManager() is not None:
            self.ZCacheable_set(None)
        else:
            _setCacheHeaders(view, extra_context={})
        return data

    def _setOldCacheHeaders(self):
        # return False to disable this simple caching behaviour
        return _FSCacheHeaders(self)

    security.declareProtected(View, 'getContentType')

    def getContentType(self):
        """Get the content type of a file or image.

        Returns the content type (MIME type) of a file or image.
        """
        self._updateFromFS()
        return self.content_type

    security.declareProtected(FTPAccess, 'manage_FTPget')
    manage_FTPget = index_html
예제 #5
0
class FSZSQLMethod(SQL, FSObject):
    """FSZSQLMethods act like Z SQL Methods but are not directly
    modifiable from the management interface."""

    meta_type = 'Filesystem Z SQL Method'

    manage_options = (
        {
            'label': 'Customize',
            'action': 'manage_customise'
        },
        {
            'label': 'Test',
            'action': 'manage_testForm',
            'help': ('ZSQLMethods', 'Z-SQL-Method_Test.stx')
        },
    )

    security = ClassSecurityInfo()
    security.declareObjectProtected(View)

    # Make mutators private
    security.declarePrivate('manage_main')
    security.declarePrivate('manage_edit')
    security.declarePrivate('manage_advanced')
    security.declarePrivate('manage_advancedForm')
    manage = None

    security.declareProtected(ViewManagementScreens, 'manage_customise')
    manage_customise = Globals.DTMLFile('custzsql', _dtmldir)

    def __init__(self, id, filepath, fullname=None, properties=None):
        FSObject.__init__(self, id, filepath, fullname, properties)

    def _createZODBClone(self):
        """Create a ZODB (editable) equivalent of this object."""
        # I guess it's bad to 'reach inside' ourselves like this,
        # but Z SQL Methods don't have accessor methdods ;-)
        s = SQL(self.id, self.title, self.connection_id, self.arguments_src,
                self.src)
        s.manage_advanced(self.max_rows_,
                          self.max_cache_,
                          self.cache_time_,
                          self.class_name_,
                          self.class_file_,
                          connection_hook=self.connection_hook,
                          direct=self.allow_simple_one_argument_traversal)
        return s

    def _readFile(self, reparse):
        """Read the data from the filesystem.
        """
        file = open(self._filepath, 'r')  # not 'rb', as this is a text file!
        try:
            data = file.read()
        finally:
            file.close()

        # parse parameters
        parameters = {}
        start = data.find('<dtml-comment>')
        end = data.find('</dtml-comment>')
        if start == -1 or end == -1 or start > end:
            raise ValueError, 'Could not find parameter block'
        block = data[start + 14:end]

        for line in block.split('\n'):
            pair = line.split(':', 1)
            if len(pair) != 2:
                continue
            parameters[pair[0].strip().lower()] = pair[1].strip()

        # check for required parameters
        try:
            connection_id = (parameters.get('connection id', '')
                             or parameters['connection_id'])
        except KeyError, e:
            raise ValueError("The '%s' parameter is required "
                             "but was not supplied" % e)

        # Optional parameters
        title = parameters.get('title', '')
        arguments = parameters.get('arguments', '')
        max_rows = parameters.get('max_rows', 1000)
        max_cache = parameters.get('max_cache', 100)
        cache_time = parameters.get('cache_time', 0)
        class_name = parameters.get('class_name', '')
        class_file = parameters.get('class_file', '')
        connection_hook = parameters.get('connection_hook', None)
        direct = parameters.get('allow_simple_one_argument_traversal', None)

        self.manage_edit(title, connection_id, arguments, template=data)

        self.manage_advanced(max_rows,
                             max_cache,
                             cache_time,
                             class_name,
                             class_file,
                             connection_hook=connection_hook,
                             direct=direct)
예제 #6
0
class FSDTMLMethod(RestrictedDTML, RoleManager, FSObject, Globals.HTML):
    """FSDTMLMethods act like DTML methods but are not directly
    modifiable from the management interface."""

    meta_type = 'Filesystem DTML Method'

    manage_options = ((
        {
            'label': 'Customize',
            'action': 'manage_main'
        },
        {
            'label': 'View',
            'action': '',
            'help': ('OFSP', 'DTML-DocumentOrMethod_View.stx')
        },
        {
            'label': 'Proxy',
            'action': 'manage_proxyForm',
            'help': ('OFSP', 'DTML-DocumentOrMethod_Proxy.stx')
        },
    ) + Cacheable.manage_options)

    _proxy_roles = ()
    _cache_namespace_keys = ()

    # Use declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(View)

    security.declareProtected(ViewManagementScreens, 'manage_main')
    manage_main = Globals.DTMLFile('custdtml', _dtmldir)

    _reading = 0

    def __init__(self, id, filepath, fullname=None, properties=None):
        FSObject.__init__(self, id, filepath, fullname, properties)
        # Normally called via HTML.__init__ but we don't need the rest that
        # happens there.
        self.initvars(None, {})

    def _createZODBClone(self):
        """Create a ZODB (editable) equivalent of this object."""
        return DTMLMethod(self.read(), __name__=self.getId())

    def _readFile(self, reparse):
        fp = expandpath(self._filepath)
        file = open(fp, 'r')  # not 'rb', as this is a text file!
        try:
            data = file.read()
        finally:
            file.close()
        self.raw = data
        if reparse:
            self._reading = 1  # Avoid infinite recursion
            try:
                self.cook()
            finally:
                self._reading = 0

    # Hook up chances to reload in debug mode
    security.declarePrivate('read_raw')

    def read_raw(self):
        if not self._reading:
            self._updateFromFS()
        return Globals.HTML.read_raw(self)

    #### The following is mainly taken from OFS/DTMLMethod.py ###

    index_html = None  # Prevent accidental acquisition

    # Documents masquerade as functions:
    func_code = DTMLMethod.func_code

    default_content_type = 'text/html'

    def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
        """Render the document given a client object, REQUEST mapping,
        Response, and key word arguments."""

        self._updateFromFS()

        if not self._cache_namespace_keys:
            data = self.ZCacheable_get(default=_marker)
            if data is not _marker:
                # Return cached results.
                return data

        kw['document_id'] = self.getId()
        kw['document_title'] = self.title

        security = getSecurityManager()
        security.addContext(self)
        try:

            if client is None:
                # Called as subtemplate, so don't need error propagation!
                r = Globals.HTML.__call__(self, client, REQUEST, **kw)
                if RESPONSE is None: result = r
                else: result = decapitate(r, RESPONSE)
                if not self._cache_namespace_keys:
                    self.ZCacheable_set(result)
                return result

            r = Globals.HTML.__call__(self, client, REQUEST, **kw)
            if type(r) is not type('') or RESPONSE is None:
                if not self._cache_namespace_keys:
                    self.ZCacheable_set(r)
                return r

        finally:
            security.removeContext(self)

        have_key = RESPONSE.headers.has_key
        if not (have_key('content-type') or have_key('Content-Type')):
            if self.__dict__.has_key('content_type'):
                c = self.content_type
            else:
                c, e = guess_content_type(self.getId(), r)
            RESPONSE.setHeader('Content-Type', c)
        result = decapitate(r, RESPONSE)
        if not self._cache_namespace_keys:
            self.ZCacheable_set(result)
        return result

    def getCacheNamespaceKeys(self):
        '''
        Returns the cacheNamespaceKeys.
        '''
        return self._cache_namespace_keys

    def setCacheNamespaceKeys(self, keys, REQUEST=None):
        '''
        Sets the list of names that should be looked up in the
        namespace to provide a cache key.
        '''
        ks = []
        for key in keys:
            key = strip(str(key))
            if key:
                ks.append(key)
        self._cache_namespace_keys = tuple(ks)
        if REQUEST is not None:
            return self.ZCacheable_manage(self, REQUEST)

    # Zope 2.3.x way:
    def validate(self, inst, parent, name, value, md=None):
        return getSecurityManager().validate(inst, parent, name, value)

    security.declareProtected(FTPAccess, 'manage_FTPget')
    manage_FTPget = DTMLMethod.manage_FTPget

    security.declareProtected(ViewManagementScreens, 'PrincipiaSearchSource')
    PrincipiaSearchSource = DTMLMethod.PrincipiaSearchSource

    security.declareProtected(ViewManagementScreens, 'document_src')
    document_src = DTMLMethod.document_src

    security.declareProtected(ViewManagementScreens, 'manage_haveProxy')
    manage_haveProxy = DTMLMethod.manage_haveProxy
예제 #7
0
class FSImage(FSObject):
    """FSImages act like images but are not directly
    modifiable from the management interface."""
    # Note that OFS.Image.Image is not a base class because it is mutable.

    meta_type = 'Filesystem Image'

    _data = None

    manage_options = ({
        'label': 'Customize',
        'action': 'manage_main'
    }, ) + Cacheable.manage_options

    security = ClassSecurityInfo()
    security.declareObjectProtected(View)

    def __init__(self, id, filepath, fullname=None, properties=None):
        id = fullname or id  # Use the whole filename.
        FSObject.__init__(self, id, filepath, fullname, properties)

    security.declareProtected(ViewManagementScreens, 'manage_main')
    manage_main = Globals.DTMLFile('custimage', _dtmldir)
    content_type = 'unknown/unknown'

    def _createZODBClone(self):
        return Image(self.getId(), '', self._readFile(1))

    def _readFile(self, reparse):
        fp = expandpath(self._filepath)
        file = open(fp, 'rb')
        try:
            data = self._data = file.read()
        finally:
            file.close()
        if reparse or self.content_type == 'unknown/unknown':
            self.ZCacheable_invalidate()
            ct, width, height = getImageInfo(data)
            self.content_type = ct
            self.width = width
            self.height = height
        return data

    #### The following is mainly taken from OFS/Image.py ###

    __str__ = Image.__str__.im_func

    _image_tag = Image.tag
    security.declareProtected(View, 'tag')

    def tag(self, *args, **kw):
        # Hook into an opportunity to reload metadata.
        self._updateFromFS()
        return self._image_tag(*args, **kw)

    security.declareProtected(View, 'index_html')

    def index_html(self, REQUEST, RESPONSE):
        """
        The default view of the contents of a File or Image.

        Returns the contents of the file or image.  Also, sets the
        Content-Type HTTP header to the objects content type.
        """
        self._updateFromFS()
        data = self._data
        # HTTP If-Modified-Since header handling.
        header = REQUEST.get_header('If-Modified-Since', None)
        if header is not None:
            header = string.split(header, ';')[0]
            # Some proxies seem to send invalid date strings for this
            # header. If the date string is not valid, we ignore it
            # rather than raise an error to be generally consistent
            # with common servers such as Apache (which can usually
            # understand the screwy date string as a lucky side effect
            # of the way they parse it).
            try:
                mod_since = long(DateTime(header).timeTime())
            except:
                mod_since = None
            if mod_since is not None:
                last_mod = self._file_mod_time
                if last_mod > 0 and last_mod <= mod_since:
                    # Set header values since apache caching will return
                    # Content-Length of 0 in response if size is not set here
                    RESPONSE.setHeader('Last-Modified', rfc1123_date(last_mod))
                    RESPONSE.setHeader('Content-Type', self.content_type)
                    RESPONSE.setHeader('Content-Length', len(data))
                    RESPONSE.setStatus(304)
                    return ''

        #Last-Modified will get stomped on by a cache policy it there is one set....
        RESPONSE.setHeader('Last-Modified', rfc1123_date(self._file_mod_time))
        RESPONSE.setHeader('Content-Type', self.content_type)
        RESPONSE.setHeader('Content-Length', len(data))

        #There are 2 Cache Managers which can be in play....need to decide which to use
        #to determine where the cache headers are decided on.
        if self.ZCacheable_getManager() is not None:
            self.ZCacheable_set(None)
        else:
            _setCacheHeaders(_ViewEmulator().__of__(self), extra_context={})
        return data

    security.declareProtected(View, 'getContentType')

    def getContentType(self):
        """Get the content type of a file or image.

        Returns the content type (MIME type) of a file or image.
        """
        self._updateFromFS()
        return self.content_type

    security.declareProtected(View, 'get_size')

    def get_size(self):
        """
            Return the size of the image.
        """
        self._updateFromFS()
        return self._data and len(self._data) or 0

    security.declareProtected(FTPAccess, 'manage_FTPget')
    manage_FTPget = index_html
예제 #8
0
class BrowserIdManager(Item, Persistent, Implicit, RoleManager, Owned, Tabs):
    """ browser id management class """

    meta_type = 'Browser Id Manager'

    manage_options = ({
        'label': 'Settings',
        'action': 'manage_browseridmgr',
    }, {
        'label': 'Security',
        'action': 'manage_access'
    }, {
        'label': 'Ownership',
        'action': 'manage_owner'
    })

    __implements__ = (SessionInterfaces.BrowserIdManagerInterface, )

    icon = 'misc_/Sessions/idmgr.gif'

    security = ClassSecurityInfo()
    security.declareObjectPublic()
    ok = {
        'meta_type': 1,
        'id': 1,
        'title': 1,
        'icon': 1,
        'bobobase_modification_time': 1,
        'title_or_id': 1
    }
    security.setDefaultAccess(ok)
    security.setPermissionDefault(MGMT_SCREEN_PERM, ['Manager'])
    security.setPermissionDefault(ACCESS_CONTENTS_PERM,
                                  ['Manager', 'Anonymous'])
    security.setPermissionDefault(CHANGE_IDMGR_PERM, ['Manager'])

    # backwards-compatibility for pre-2.6 instances
    auto_url_encoding = 0

    def __init__(self,
                 id,
                 title='',
                 idname='_ZopeId',
                 location=('cookies', 'form'),
                 cookiepath=('/'),
                 cookiedomain='',
                 cookielifedays=0,
                 cookiesecure=0,
                 auto_url_encoding=0):
        self.id = str(id)
        self.title = str(title)
        self.setBrowserIdName(idname)
        self.setBrowserIdNamespaces(location)
        self.setCookiePath(cookiepath)
        self.setCookieDomain(cookiedomain)
        self.setCookieLifeDays(cookielifedays)
        self.setCookieSecure(cookiesecure)
        self.setAutoUrlEncoding(auto_url_encoding)

    def manage_afterAdd(self, item, container):
        """ Maybe add our traversal hook """
        self.updateTraversalData()

    def manage_beforeDelete(self, item, container):
        """ Remove our traversal hook if it exists """
        self.unregisterTraversalHook()

    security.declareProtected(ACCESS_CONTENTS_PERM, 'hasBrowserId')

    def hasBrowserId(self):
        """ Returns true if there is a current browser id, but does
        not create a browser id for the current request if one doesn't
        already exist """
        if self.getBrowserId(create=0): return 1

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getBrowserId')

    def getBrowserId(self, create=1):
        """
        Examines the request and hands back browser id value or
        None if no id exists.  If there is no browser id
        and if 'create' is true, create one.  If cookies are are
        an allowable id namespace and create is true, set one.  Stuff
        the id and the namespace it was found in into the REQUEST object
        for further reference during this request.
        """
        REQUEST = self.REQUEST
        # let's see if bid has already been attached to request
        bid = getattr(REQUEST, 'browser_id_', None)
        if bid is not None:
            # it's already set in this request so we can just return it
            # if it's well-formed
            if not isAWellFormedBrowserId(bid):
                # somebody screwed with the REQUEST instance during
                # this request.
                raise BrowserIdManagerErr, (
                    'Ill-formed browserid in REQUEST.browser_id_:  %s' %
                    escape(bid))
            return bid
        # fall through & ck form/cookie namespaces if bid is not in request.
        tk = self.browserid_name
        ns = self.browserid_namespaces
        for name in ns:
            if name == 'url':
                continue  # browser ids in url are checked by Traverser class
            current_ns = getattr(REQUEST, name, None)
            if current_ns is None:
                continue
            bid = current_ns.get(tk, None)
            if bid is not None:
                # hey, we got a browser id!
                if isAWellFormedBrowserId(bid):
                    # bid is not "plain old broken"
                    REQUEST.browser_id_ = bid
                    REQUEST.browser_id_ns_ = name
                    return bid
        # fall through if bid is invalid or not in namespaces
        if create:
            # create a brand new bid
            bid = getNewBrowserId()
            if 'cookies' in ns:
                self._setCookie(bid, REQUEST)
            REQUEST.browser_id_ = bid
            REQUEST.browser_id_ns_ = None
            return bid
        # implies a return of None if:
        # (not create=1) and (invalid or ((not in req) and (not in ns)))

    security.declareProtected(ACCESS_CONTENTS_PERM, 'flushBrowserIdCookie')

    def flushBrowserIdCookie(self):
        """ removes the bid cookie from the client browser """
        if 'cookies' not in self.browserid_namespaces:
            raise BrowserIdManagerErr, ('Cookies are not now being used as a '
                                        'browser id namespace, thus the '
                                        'browserid cookie cannot be flushed.')
        self._setCookie('deleted', self.REQUEST, remove=1)

    security.declareProtected(ACCESS_CONTENTS_PERM,
                              'setBrowserIdCookieByForce')

    def setBrowserIdCookieByForce(self, bid):
        """ """
        if 'cookies' not in self.browserid_namespaces:
            raise BrowserIdManagerErr, ('Cookies are not now being used as a '
                                        'browser id namespace, thus the '
                                        'browserid cookie cannot be forced.')
        self._setCookie(bid, self.REQUEST)

    security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdFromCookie')

    def isBrowserIdFromCookie(self):
        """ returns true if browser id is from REQUEST.cookies """
        if not self.getBrowserId():  # make sure the bid is stuck on REQUEST
            raise BrowserIdManagerErr, 'There is no current browser id.'
        if getattr(self.REQUEST, 'browser_id_ns_') == 'cookies':
            return 1

    security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdFromForm')

    def isBrowserIdFromForm(self):
        """ returns true if browser id is from REQUEST.form """
        if not self.getBrowserId():  # make sure the bid is stuck on REQUEST
            raise BrowserIdManagerErr, 'There is no current browser id.'
        if getattr(self.REQUEST, 'browser_id_ns_') == 'form':
            return 1

    security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdFromUrl')

    def isBrowserIdFromUrl(self):
        """ returns true if browser id is from first element of the
        URL """
        if not self.getBrowserId():  # make sure the bid is stuck on REQUEST
            raise BrowserIdManagerErr, 'There is no current browser id.'
        if getattr(self.REQUEST, 'browser_id_ns_') == 'url':
            return 1

    security.declareProtected(ACCESS_CONTENTS_PERM, 'isBrowserIdNew')

    def isBrowserIdNew(self):
        """
        returns true if browser id is 'new', meaning the id exists
        but it has not yet been acknowledged by the client (the client
        hasn't sent it back to us in a cookie or in a formvar).
        """
        if not self.getBrowserId():  # make sure the id is stuck on REQUEST
            raise BrowserIdManagerErr, 'There is no current browser id.'
        # ns will be None if new, negating None below returns 1, which
        # would indicate that it's new on this request
        return getattr(self.REQUEST, 'browser_id_ns_', None) == None

    security.declareProtected(ACCESS_CONTENTS_PERM, 'encodeUrl')

    def encodeUrl(self, url, style='querystring', create=1):
        """
        encode a URL with the browser id as a postfixed query string
        element or inlined into the url depending on the 'style' parameter
        """
        bid = self.getBrowserId(create)
        if bid is None:
            raise BrowserIdManagerErr, 'There is no current browser id.'
        name = self.getBrowserIdName()
        if style == 'querystring':  # encode bid in querystring
            if '?' in url:
                return '%s&amp;%s=%s' % (url, name, bid)
            else:
                return '%s?%s=%s' % (url, name, bid)
        else:  # encode bid as first two URL path segments
            proto, host, path, params, query, frag = urlparse(url)
            path = '/%s/%s%s' % (name, bid, path)
            return urlunparse((proto, host, path, params, query, frag))

    security.declareProtected(MGMT_SCREEN_PERM, 'manage_browseridmgr')
    manage_browseridmgr = Globals.DTMLFile('dtml/manageIdManager', globals())

    security.declareProtected(CHANGE_IDMGR_PERM,
                              'manage_changeBrowserIdManager')

    def manage_changeBrowserIdManager(self,
                                      title='',
                                      idname='_ZopeId',
                                      location=('cookies', 'form'),
                                      cookiepath='/',
                                      cookiedomain='',
                                      cookielifedays=0,
                                      cookiesecure=0,
                                      auto_url_encoding=0,
                                      REQUEST=None):
        """ """
        self.title = str(title)
        self.setBrowserIdName(idname)
        self.setCookiePath(cookiepath)
        self.setCookieDomain(cookiedomain)
        self.setCookieLifeDays(cookielifedays)
        self.setCookieSecure(cookiesecure)
        self.setBrowserIdNamespaces(location)
        self.setAutoUrlEncoding(auto_url_encoding)
        self.updateTraversalData()
        if REQUEST is not None:
            msg = '/manage_browseridmgr?manage_tabs_message=Changes saved'
            REQUEST.RESPONSE.redirect(self.absolute_url() + msg)

    security.declareProtected(CHANGE_IDMGR_PERM, 'setBrowserIdName')

    def setBrowserIdName(self, k):
        """ sets browser id name string """
        if not (type(k) is type('') and k and not badidnamecharsin(k)):
            raise BrowserIdManagerErr, 'Bad id name string %s' % escape(
                repr(k))
        self.browserid_name = k

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getBrowserIdName')

    def getBrowserIdName(self):
        """ """
        return self.browserid_name

    security.declareProtected(CHANGE_IDMGR_PERM, 'setBrowserIdNamespaces')

    def setBrowserIdNamespaces(self, ns):
        """
        accepts list of allowable browser id namespaces 
        """
        for name in ns:
            if name not in ALLOWED_BID_NAMESPACES:
                raise BrowserIdManagerErr, ('Bad browser id namespace %s' %
                                            repr(name))
        self.browserid_namespaces = tuple(ns)

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getBrowserIdNamespaces')

    def getBrowserIdNamespaces(self):
        """ """
        return self.browserid_namespaces

    security.declareProtected(CHANGE_IDMGR_PERM, 'setCookiePath')

    def setCookiePath(self, path=''):
        """ sets cookie 'path' element for id cookie """
        if not (type(path) is type('') and not badcookiecharsin(path)):
            raise BrowserIdManagerErr, 'Bad cookie path %s' % escape(
                repr(path))
        self.cookie_path = path

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookiePath')

    def getCookiePath(self):
        """ """
        return self.cookie_path

    security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieLifeDays')

    def setCookieLifeDays(self, days):
        """ offset for id cookie 'expires' element """
        if type(days) not in (type(1), type(1.0)):
            raise BrowserIdManagerErr, (
                'Bad cookie lifetime in days %s (requires integer value)' %
                escape(repr(days)))
        self.cookie_life_days = int(days)

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookieLifeDays')

    def getCookieLifeDays(self):
        """ """
        return self.cookie_life_days

    security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieDomain')

    def setCookieDomain(self, domain):
        """ sets cookie 'domain' element for id cookie """
        if type(domain) is not type(''):
            raise BrowserIdManagerErr, ('Cookie domain must be string: %s' %
                                        escape(repr(domain)))
        if not domain:
            self.cookie_domain = ''
            return
        if not twodotsin(domain):
            raise BrowserIdManagerErr, (
                'Cookie domain must contain at least two dots (e.g. '
                '".zope.org" or "www.zope.org") or it must be left blank. : '
                '%s' % escape( ` domain `))
        if badcookiecharsin(domain):
            raise BrowserIdManagerErr, ('Bad characters in cookie domain %s' %
                                        escape( ` domain `))
        self.cookie_domain = domain

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookieDomain')

    def getCookieDomain(self):
        """ """
        return self.cookie_domain

    security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieSecure')

    def setCookieSecure(self, secure):
        """ sets cookie 'secure' element for id cookie """
        self.cookie_secure = not not secure

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getCookieSecure')

    def getCookieSecure(self):
        """ """
        return self.cookie_secure

    security.declareProtected(CHANGE_IDMGR_PERM, 'setCookieSecure')

    def setAutoUrlEncoding(self, auto_url_encoding):
        """ sets 'auto url encoding' on or off """
        self.auto_url_encoding = not not auto_url_encoding

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getAutoUrlEncoding')

    def getAutoUrlEncoding(self):
        """ """
        return self.auto_url_encoding

    security.declareProtected(ACCESS_CONTENTS_PERM, 'isUrlInBidNamespaces')

    def isUrlInBidNamespaces(self):
        """ Returns true if 'url' is in the browser id namespaces
        for this browser id """
        return 'url' in self.browserid_namespaces

    security.declareProtected(ACCESS_CONTENTS_PERM, 'getHiddenFormField')

    def getHiddenFormField(self):
        """
        Convenience method which returns a hidden form element
        representing the current browser id name and browser id
        """
        s = '<input type="hidden" name="%s" value="%s">'
        return s % (self.getBrowserIdName(), self.getBrowserId())

    def _setCookie(self,
                   bid,
                   REQUEST,
                   remove=0,
                   now=time.time,
                   strftime=time.strftime,
                   gmtime=time.gmtime):
        """ """
        expires = None
        if remove:
            expires = "Sun, 10-May-1971 11:59:00 GMT"
        elif self.cookie_life_days:
            expires = now() + self.cookie_life_days * 86400
            # Wdy, DD-Mon-YYYY HH:MM:SS GMT
            expires = strftime('%a %d-%b-%Y %H:%M:%S GMT', gmtime(expires))
        d = {
            'domain': self.cookie_domain,
            'path': self.cookie_path,
            'secure': self.cookie_secure,
            'expires': expires
        }

        if self.cookie_secure:
            URL1 = REQUEST.get('URL1', None)
            if URL1 is None:
                return  # should we raise an exception?
            if string.split(URL1, ':')[0] != 'https':
                return  # should we raise an exception?

        cookies = REQUEST.RESPONSE.cookies
        cookie = cookies[self.browserid_name] = {}
        for k, v in d.items():
            if v:
                cookie[k] = v  #only stuff things with true values
        cookie['value'] = bid

    def _setId(self, id):
        if id != self.id:
            raise Globals.MessageDialog(
                title='Cannot rename',
                message='You cannot rename a browser id manager, sorry!',
                action='./manage_main',
            )

    def updateTraversalData(self):
        if self.isUrlInBidNamespaces():
            self.registerTraversalHook()
        else:
            self.unregisterTraversalHook()

    def unregisterTraversalHook(self):
        parent = aq_parent(aq_inner(self))
        name = TRAVERSAL_APPHANDLE
        if self.hasTraversalHook(parent):
            unregisterBeforeTraverse(parent, name)

    def registerTraversalHook(self):
        parent = aq_parent(aq_inner(self))
        if not self.hasTraversalHook(parent):
            hook = BrowserIdManagerTraverser()
            name = TRAVERSAL_APPHANDLE
            priority = 40  # "higher" priority than session data traverser
            registerBeforeTraverse(parent, hook, name, priority)

    def hasTraversalHook(self, parent):
        name = TRAVERSAL_APPHANDLE
        return not not queryBeforeTraverse(parent, name)
예제 #9
0
from urllib import quote
from urlparse import urlparse, urlunparse
from ZPublisher.BeforeTraverse import registerBeforeTraverse, \
    unregisterBeforeTraverse, queryBeforeTraverse
import logging

b64_trans = string.maketrans('+/', '-.')
b64_untrans = string.maketrans('-.', '+/')

badidnamecharsin = re.compile('[\?&;,<> ]').search
badcookiecharsin = re.compile('[;,<>& ]').search
twodotsin = re.compile('(\w*\.){2,}').search

_marker = []

constructBrowserIdManagerForm = Globals.DTMLFile('dtml/addIdManager',
                                                 globals())

BROWSERID_MANAGER_NAME = 'browser_id_manager'  # imported by SessionDataManager
ALLOWED_BID_NAMESPACES = ('form', 'cookies', 'url')
ADD_BROWSER_ID_MANAGER_PERM = "Add Browser Id Manager"
TRAVERSAL_APPHANDLE = 'BrowserIdManager'

LOG = logging.getLogger('Zope.BrowserIdManager')


def constructBrowserIdManager(self,
                              id=BROWSERID_MANAGER_NAME,
                              title='',
                              idname='_ZopeId',
                              location=('cookies', 'form'),
                              cookiepath='/',