예제 #1
0
class Link( PortalContent
          , DefaultDublinCoreImpl
          ):
    """
        A Link
    """

    __implements__ = ( PortalContent.__implements__
                     , DefaultDublinCoreImpl.__implements__
                     )

    meta_type='Link'
    effective_date = expiration_date = None
    _isDiscussable = 1

    __ac_permissions__=(
        (CMFCorePermissions.View, ('', 'view', 'getRemoteUrl')),
        (CMFCorePermissions.ModifyPortalContent, ('edit',)),
        )

    def __init__( self
                , id
                , title=''
                , remote_url=''
                , description=''
                ):
        DefaultDublinCoreImpl.__init__(self)
        self.id=id
        self.title=title
        self.remote_url=remote_url
        self.description=description

    def edit( self, remote_url ):
        """
            Edit the Link
        """
        self.remote_url=remote_url
    edit = WorkflowAction(edit)

    def SearchableText(self):
        """
            text for indexing
        """
        return "%s %s" % (self.title, self.description)

    def getRemoteUrl(self):
        """
            returns the remote URL of the Link
        """
        return self.remote_url
예제 #2
0
class ApparelMeasurement(XMLObject, XMLMatrix, Image):
    """
     XXX  A matrix which provides default mesure_code and mesure_name
    """
    meta_type = 'ERP5 Apparel Measurement'
    portal_type = 'Apparel Measurement'

    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    # Declarative properties
    property_sheets = (PropertySheet.Base, PropertySheet.XMLObject,
                       PropertySheet.CategoryCore, PropertySheet.DublinCore,
                       PropertySheet.VariationRange, PropertySheet.Arrow)

    def __init__(self, id, **kw):
        Image.__init__(self, id, **kw)
        XMLObject.__init__(self, id, **kw)

    # Inheritance
    _edit = Image._edit
    security.declareProtected(Permissions.ModifyPortalContent, 'edit')
    edit = WorkflowAction(_edit)

    security.declareProtected(Permissions.View, 'index_html')
    index_html = Image.index_html

    security.declareProtected(Permissions.AccessContentsInformation,
                              'content_type')
    content_type = Image.content_type

    def manage_afterClone(self, item):
        XMLObject.manage_afterClone(self, item)
        Image.manage_afterClone(self, item)

    def manage_afterAdd(self, item, container):
        XMLObject.manage_afterAdd(self, item, container)
        Image.manage_afterAdd(self, item, container)

    def manage_beforeDelete(self, item, container):
        Image.manage_beforeDelete(self, item, container)

    security.declareProtected(Permissions.ModifyPortalContent,
                              '_setMeasureList')

    def _setMeasureList(self, value):
        self._categorySetMeasureList(value)
        # XXX Use interaction workflow instead
        self.updateCellRange(base_id='measure')
예제 #3
0
파일: NewsItem.py 프로젝트: bendavis78/zope
class NewsItem(Document):
    """
        A News Item
    """

    meta_type = 'News Item'

    security = ClassSecurityInfo()

    def _edit(self, text, description=None, text_format=None):
        """
            Edit the News Item
        """
        if text_format is None:
            text_format = getattr(self, 'text_format', 'html')
        if description is not None:
            self.setDescription(description)
        Document._edit(self, text_format, text)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent, 'edit')
    edit = WorkflowAction(_edit)
예제 #4
0
파일: Document.py 프로젝트: bendavis78/zope
class Document(PortalContent, DefaultDublinCoreImpl):
    """ A Document - Handles both StructuredText and HTML """

    __implements__ = (PortalContent.__implements__,
                      DefaultDublinCoreImpl.__implements__)

    meta_type = 'Document'
    effective_date = expiration_date = None
    cooked_text = text = text_format = ''
    _isDiscussable = 1

    _stx_level = 1  # Structured text level

    _last_safety_belt_editor = ''
    _last_safety_belt = ''
    _safety_belt = ''

    # Declarative security (replaces __ac_permissions__)
    security = ClassSecurityInfo()

    def __init__(self, id, title='', description='', text_format='', text=''):
        DefaultDublinCoreImpl.__init__(self)
        self.id = id
        self.title = title
        self.description = description
        self._edit(text=text, text_format=text_format)
        self.setFormat(text_format)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'manage_edit')
    manage_edit = DTMLFile('zmi_editDocument', _dtmldir)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'manage_editDocument')

    def manage_editDocument(self, text, text_format, file='', REQUEST=None):
        """ A ZMI (Zope Management Interface) level editing method """
        Document.edit(self, text_format=text_format, text=text, file=file)
        if REQUEST is not None:
            REQUEST['RESPONSE'].redirect(
                self.absolute_url() + '/manage_edit' +
                '?manage_tabs_message=Document+updated')

    def _edit(self, text, text_format='', safety_belt=''):
        """ Edit the Document - Parses headers and cooks the body"""
        headers = {}
        level = self._stx_level
        if not text_format:
            text_format = self.text_format
        if not safety_belt:
            safety_belt = headers.get('SafetyBelt', '')
        if not self._safety_belt_update(safety_belt=safety_belt):
            msg = ("Intervening changes from elsewhere detected."
                   " Please refetch the document and reapply your changes."
                   " (You may be able to recover your version using the"
                   " browser 'back' button, but will have to apply them"
                   " to a freshly fetched copy.)")
            raise 'EditingConflict', msg
        if text_format == 'html':
            self.text = self.cooked_text = text
        elif text_format == 'plain':
            self.text = text
            self.cooked_text = html_quote(text).replace('\n', '<br>')
        else:
            self.cooked_text = _format_stx(text=text, level=level)
            self.text = text

    security.declareProtected(CMFCorePermissions.ModifyPortalContent, 'edit')

    def edit(self, text_format, text, file='', safety_belt=''):
        """
        *used to be WorkflowAction(_edit)
        To add webDav support, we need to check if the content is locked, and if
        so return ResourceLockedError if not, call _edit.

        Note that this method expects to be called from a web form, and so
        disables header processing
        """
        self.failIfLocked()
        if file and (type(file) is not type('')):
            contents = file.read()
            if contents:
                text = self.text = contents
        text = bodyfinder(text)
        self.setFormat(value=text_format)
        self._edit(text=text, text_format=text_format, safety_belt=safety_belt)
        self.reindexObject()

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setMetadata')

    def setMetadata(self, headers):
        headers['Format'] = self.Format()
        new_subject = keywordsplitter(headers)
        headers['Subject'] = new_subject or self.Subject()
        haveheader = headers.has_key
        for key, value in self.getMetadataHeaders():
            if key != 'Format' and not haveheader(key):
                headers[key] = value
        self._editMetadata(
            title=headers['Title'],
            subject=headers['Subject'],
            description=headers['Description'],
            contributors=headers['Contributors'],
            effective_date=headers['Effective_date'],
            expiration_date=headers['Expiration_date'],
            format=headers['Format'],
            language=headers['Language'],
            rights=headers['Rights'],
        )

    security.declarePrivate('guessFormat')

    def guessFormat(self, text):
        """ Simple stab at guessing the inner format of the text """
        if utils.html_headcheck(text): return 'html'
        else: return 'structured-text'

    security.declarePrivate('handleText')

    def handleText(self, text, format=None, stx_level=None):
        """ Handles the raw text, returning headers, body, cooked, format """
        headers = {}
        level = stx_level or self._stx_level
        if not format:
            format = self.guessFormat(text)
        if format == 'html':
            parser = SimpleHTMLParser()
            parser.feed(text)
            headers.update(parser.metatags)
            if parser.title:
                headers['Title'] = parser.title
            bodyfound = bodyfinder(text)
            if bodyfound:
                body = bodyfound
        else:
            headers, body = parseHeadersBody(text, headers)
            self._stx_level = level

        return headers, body, format

    security.declarePublic('getMetadataHeaders')

    def getMetadataHeaders(self):
        """Return RFC-822-style header spec."""
        hdrlist = DefaultDublinCoreImpl.getMetadataHeaders(self)
        hdrlist.append(('SafetyBelt', self._safety_belt))
        return hdrlist

    security.declarePublic('SafetyBelt')

    def SafetyBelt(self):
        """Return the current safety belt setting.
        For web form hidden button."""
        return self._safety_belt

    def _safety_belt_update(self, safety_belt=''):
        """Check validity of safety belt and update tracking if valid.

        Return 0 if safety belt is invalid, 1 otherwise.

        Note that the policy is deliberately lax if no safety belt value is
        present - "you're on your own if you don't use your safety belt".

        When present, either the safety belt token:
         - ... is the same as the current one given out, or
         - ... is the same as the last one given out, and the person doing the
           edit is the same as the last editor."""

        this_belt = safety_belt
        this_user = getSecurityManager().getUser().getUserName()

        if (  # we have a safety belt value:
                this_belt
                # and the current object has a safety belt (ie - not freshly made)
                and (self._safety_belt is not None)
                # and the safety belt doesn't match the current one:
                and (this_belt != self._safety_belt)
                # and safety belt and user don't match last safety belt and user:
                and not ((this_belt == self._last_safety_belt) and
                         (this_user == self._last_safety_belt_editor))):
            # Fail.
            return 0

        # We qualified - either:
        #  - the edit was submitted with safety belt stripped, or
        #  - the current safety belt was used, or
        #  - the last one was reused by the last person who did the last edit.
        # In any case, update the tracking.

        self._last_safety_belt_editor = this_user
        self._last_safety_belt = this_belt
        self._safety_belt = str(self._p_mtime)

        return 1

    ### Content accessor methods
    security.declareProtected(CMFCorePermissions.View, 'SearchableText')

    def SearchableText(self):
        """ Used by the catalog for basic full text indexing """
        return "%s %s %s" % (self.Title(), self.Description(),
                             self.EditableBody())

    security.declareProtected(CMFCorePermissions.View, 'CookedBody')

    def CookedBody(self, stx_level=None, setlevel=0):
        """\
        The prepared basic rendering of an object.  For Documents, this
        means pre-rendered structured text, or what was between the
        <BODY> tags of HTML.

        If the format is html, and 'stx_level' is not passed in or is the
        same as the object's current settings, return the cached cooked
        text.  Otherwise, recook.  If we recook and 'setlevel' is true,
        then set the recooked text and stx_level on the object.
        """
        if (self.text_format == 'html' or self.text_format == 'plain'
                or (stx_level is None) or (stx_level == self._stx_level)):
            return self.cooked_text
        else:
            cooked = _format_stx(self.text, stx_level)
            if setlevel:
                self._stx_level = stx_level
                self.cooked_text = cooked
            return cooked

    security.declareProtected(CMFCorePermissions.View, 'EditableBody')

    def EditableBody(self):
        """\
        The editable body of text.  This is the raw structured text, or
        in the case of HTML, what was between the <BODY> tags.
        """
        return self.text

    security.declareProtected(CMFCorePermissions.View, 'Description')

    def Description(self):
        """ Dublin core description, also important for indexing """
        return self.description

    security.declareProtected(CMFCorePermissions.View, 'Format')

    def Format(self):
        """ Returns a content-type style format of the underlying source """
        if self.text_format == 'html':
            return 'text/html'
        else:
            return 'text/plain'

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setFormat')

    def setFormat(self, value):
        value = str(value)
        if value == 'text/html' or value == 'html':
            self.text_format = 'html'
        elif value == 'plain':
            self.text_format = 'plain'
        else:
            self.text_format = 'structured-text'

    setFormat = WorkflowAction(setFormat)

    ## FTP handlers
    security.declareProtected(CMFCorePermissions.ModifyPortalContent, 'PUT')

    def PUT(self, REQUEST, RESPONSE):
        """ Handle HTTP (and presumably FTP?) PUT requests """
        if not NoWL:
            self.dav__init(REQUEST, RESPONSE)
            self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
        body = REQUEST.get('BODY', '')
        guessedformat = REQUEST.get_header('Content-Type', 'text/plain')
        ishtml = (guessedformat == 'text/html') or utils.html_headcheck(body)

        if ishtml: self.setFormat('text/html')
        else: self.setFormat('text/plain')

        try:
            headers, body, format = self.handleText(text=body)
            safety_belt = headers.get('SafetyBelt', '')
            self.setMetadata(headers)
            self._edit(text=body, safety_belt=safety_belt)
        except 'EditingConflict', msg:
            # XXX Can we get an error msg through?  Should we be raising an
            #     exception, to be handled in the FTP mechanism?  Inquiring
            #     minds...
            get_transaction().abort()
            RESPONSE.setStatus(450)
            return RESPONSE
        except ResourceLockedError, msg:
            get_transaction().abort()
            RESPONSE.setStatus(423)
            return RESPONSE
예제 #5
0
class Link( PortalContent
          , DefaultDublinCoreImpl
          ):
    """
        A Link
    """

    __implements__ = ( PortalContent.__implements__
                     , DefaultDublinCoreImpl.__implements__
                     )

    meta_type='Link'
    effective_date = expiration_date = None
    _isDiscussable = 1

    __ac_permissions__=(
        (CMFCorePermissions.View, ('', 'view', 'getRemoteUrl')),
        (CMFCorePermissions.ModifyPortalContent, ('edit',)),
        )

    security = ClassSecurityInfo()

    def __init__( self
                , id
                , title=''
                , remote_url=''
                , description=''
                ):
        DefaultDublinCoreImpl.__init__(self)
        self.id=id
        self.title=title
        self.remote_url=remote_url
        self.description=description

    security.declareProtected(CMFCorePermissions.ModifyPortalContent, 'edit')
    def edit( self, remote_url ):
        """
            Edit the Link
        """
        tokens = urlparse.urlparse( remote_url, 'http' )
        if tokens[0] and tokens[1]:
            self.remote_url = urlparse.urlunparse( tokens )
        else:
            self.remote_url = 'http://' + remote_url
        if self.remote_url[-1] == '/':
            self.remote_url = self.remote_url[:-1]

    edit = WorkflowAction(edit)

    security.declareProtected( CMFCorePermissions.View, 'SearchableText' )
    def SearchableText(self):
        """
            text for indexing
        """
        return "%s %s" % (self.title, self.description)

    security.declareProtected( CMFCorePermissions.View, 'getRemoteUrl' )
    def getRemoteUrl(self):
        """
            returns the remote URL of the Link
        """
        return self.remote_url

    def _writeFromPUT( self, body ):

        headers = {}
        headers, body = parseHeadersBody(body, headers)
        lines = string.split( body, '\n' )
        self.edit( lines[0] )

        headers['Format'] = 'text/url'
        new_subject = keywordsplitter(headers)
        headers['Subject'] = new_subject or self.Subject()
        haveheader = headers.has_key
        for key, value in self.getMetadataHeaders():
            if key != 'Format' and not haveheader(key):
                headers[key] = value
        
        self.editMetadata(title=headers['Title'],
                          subject=headers['Subject'],
                          description=headers['Description'],
                          contributors=headers['Contributors'],
                          effective_date=headers['Effective_date'],
                          expiration_date=headers['Expiration_date'],
                          format=headers['Format'],
                          language=headers['Language'],
                          rights=headers['Rights'],
                          )
        
    ## FTP handlers
    security.declareProtected(CMFCorePermissions.ModifyPortalContent, 'PUT')
    def PUT(self, REQUEST, RESPONSE):
        """
            Handle HTTP (and presumably FTP?) PUT requests.
        """
        self.dav__init(REQUEST, RESPONSE)
        body = REQUEST.get('BODY', '')
        self._writeFromPUT( body )
        RESPONSE.setStatus(204)
        return RESPONSE

    security.declareProtected( CMFCorePermissions.View, 'manage_FTPget' )
    def manage_FTPget(self):
        "Get the link as text for FTP download (also used for the WebDAV SRC)"
        join = string.join
        lower = string.lower
        hdrlist = self.getMetadataHeaders()
        hdrtext = join( map( lambda x: '%s: %s' % ( x[0], x[1] )
                           , hdrlist), '\n' )
        bodytext = '%s\n\n%s' % ( hdrtext, self.getRemoteUrl() )

        return bodytext

    security.declareProtected( CMFCorePermissions.View, 'get_size' )
    def get_size( self ):
        """ Used for FTP and apparently the ZMI now too """
        return len(self.manage_FTPget())
예제 #6
0
class Link( PortalContent
          , DefaultDublinCoreImpl
          ):
    """
        A Link
    """

    __implements__ = ( PortalContent.__implements__
                     , DefaultDublinCoreImpl.__implements__
                     )

    meta_type = 'Link'
    URL_FORMAT = format = 'text/url'
    effective_date = expiration_date = None
    _isDiscussable = 1

    security = ClassSecurityInfo()

    def __init__( self
                , id
                , title=''
                , remote_url=''
                , description=''
                ):
        DefaultDublinCoreImpl.__init__(self)
        self.id=id
        self.title=title
        self.description=description
        self._edit(remote_url)
        self.format=self.URL_FORMAT

    security.declareProtected( CMFCorePermissions.ModifyPortalContent
                             , 'manage_edit' )
    manage_edit = DTMLFile( 'zmi_editLink', _dtmldir )

    security.declareProtected( CMFCorePermissions.ModifyPortalContent
                             , 'manage_editLink' )
    def manage_editLink( self, remote_url, REQUEST=None ):
        """
            Update the Link via the ZMI.
        """
        self._edit( remote_url )
        if REQUEST is not None:
            REQUEST['RESPONSE'].redirect( self.absolute_url()
                                        + '/manage_edit'
                                        + '?manage_tabs_message=Link+updated'
                                        )

    security.declareProtected( CMFCorePermissions.ModifyPortalContent
                             , 'manage_edit' )
    manage_edit = DTMLFile( 'zmi_editLink', _dtmldir )

    security.declareProtected( CMFCorePermissions.ModifyPortalContent
                             , 'manage_editLink' )
    def manage_editLink( self, remote_url, REQUEST=None ):
        """
            Update the Link via the ZMI.
        """
        self._edit( remote_url )
        if REQUEST is not None:
            REQUEST['RESPONSE'].redirect( self.absolute_url()
                                        + '/manage_edit'
                                        + '?manage_tabs_message=Link+updated'
                                        )

    security.declarePrivate( '_edit' )
    def _edit( self, remote_url ):
        """
            Edit the Link
        """
        tokens = urlparse.urlparse( remote_url, 'http' )
        if tokens[0] == 'http':
            if tokens[1]:
                # We have a nethost. All is well.
                url = urlparse.urlunparse(tokens)
            elif tokens[2:] == ('', '', '', ''):
                # Empty URL
                url = ''
            else:
                # Relative URL, keep it that way, without http:
                tokens = ('', '') + tokens[2:]
                url = urlparse.urlunparse(tokens)
        else:
            # Other scheme, keep original
            url = urlparse.urlunparse(tokens)
        self.remote_url = url

    security.declareProtected( CMFCorePermissions.ModifyPortalContent, 'edit' )
    edit = WorkflowAction( _edit )

    security.declareProtected( CMFCorePermissions.View, 'SearchableText' )
    def SearchableText(self):
        """
            text for indexing
        """
        return "%s %s" % (self.title, self.description)

    security.declareProtected( CMFCorePermissions.View, 'getRemoteUrl' )
    def getRemoteUrl(self):
        """
            returns the remote URL of the Link
        """
        return self.remote_url

    security.declarePrivate( '_writeFromPUT' )
    def _writeFromPUT( self, body ):
        headers = {}
        headers, body = parseHeadersBody(body, headers)
        lines = string.split( body, '\n' )
        self.edit( lines[0] )
        headers['Format'] = self.URL_FORMAT
        new_subject = keywordsplitter(headers)
        headers['Subject'] = new_subject or self.Subject()
        haveheader = headers.has_key
        for key, value in self.getMetadataHeaders():
            if key != 'Format' and not haveheader(key):
                headers[key] = value
        
        self._editMetadata(title=headers['Title'],
                          subject=headers['Subject'],
                          description=headers['Description'],
                          contributors=headers['Contributors'],
                          effective_date=headers['Effective_date'],
                          expiration_date=headers['Expiration_date'],
                          format=headers['Format'],
                          language=headers['Language'],
                          rights=headers['Rights'],
                          )
        
    ## FTP handlers
    security.declareProtected( CMFCorePermissions.ModifyPortalContent, 'PUT')
    def PUT(self, REQUEST, RESPONSE):
        """
            Handle HTTP / WebDAV / FTP PUT requests.
        """
        if not NoWL:
            self.dav__init(REQUEST, RESPONSE)
            self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
        body = REQUEST.get('BODY', '')
        try:
            self._writeFromPUT( body )
            RESPONSE.setStatus(204)
            return RESPONSE
        except ResourceLockedError, msg:
            get_transaction().abort()
            RESPONSE.setStatus(423)
            return RESPONSE
예제 #7
0
파일: File.py 프로젝트: bendavis78/zope
class File(OFS.Image.File, PortalContent, DefaultDublinCoreImpl):
    """
        A Portal-managed File
    """

    # The order of base classes is very significant in this case.
    # Image.File does not store it's id in it's 'id' attribute.
    # Rather, it has an 'id' method which returns the contents of the
    # instnace's __name__ attribute.  Inheriting in the other order
    # obscures this method, resulting in much pulling of hair and
    # gnashing of teeth and fraying of nerves.  Don't do it.
    #
    # Really.
    #
    # Note that if you use getId() to retrieve an object's ID, you will avoid
    # this problem altogether. getId is the new way, accessing .id is
    # deprecated.

    __implements__ = (PortalContent.__implements__,
                      DefaultDublinCoreImpl.__implements__)

    meta_type = 'Portal File'
    effective_date = expiration_date = None
    _isDiscussable = 1
    icon = PortalContent.icon

    security = ClassSecurityInfo()

    def __init__(self,
                 id,
                 title='',
                 file='',
                 content_type='',
                 precondition='',
                 subject=(),
                 description='',
                 contributors=(),
                 effective_date=None,
                 expiration_date=None,
                 format='text/html',
                 language='en-US',
                 rights=''):
        OFS.Image.File.__init__(self, id, title, file, content_type,
                                precondition)
        DefaultDublinCoreImpl.__init__(self, title, subject, description,
                                       contributors, effective_date,
                                       expiration_date, format, language,
                                       rights)

    security.declareProtected(View, 'SearchableText')

    def SearchableText(self):
        """
        SeachableText is used for full text seraches of a portal.  It
        should return a concatenation of all useful text.
        """
        return "%s %s" % (self.title, self.description)

    security.declarePrivate('manage_afterAdd')

    def manage_afterAdd(self, item, container):
        """Both of my parents have an afterAdd method"""
        OFS.Image.File.manage_afterAdd(self, item, container)
        PortalContent.manage_afterAdd(self, item, container)

    security.declarePrivate('manage_beforeDelete')

    def manage_beforeDelete(self, item, container):
        """Both of my parents have a beforeDelete method"""
        PortalContent.manage_beforeDelete(self, item, container)
        OFS.Image.File.manage_beforeDelete(self, item, container)

    security.declarePrivate('_isNotEmpty')

    def _isNotEmpty(self, file):
        """ Do various checks on 'file' to try to determine non emptiness. """
        if not file:
            return 0  # Catches None, Missing.Value, ''
        elif file and (type(file) is type('')):
            return 1
        elif getattr(file, 'filename', None):
            return 1
        elif not hasattr(file, 'read'):
            return 0
        else:
            file.seek(0, 2)  # 0 bytes back from end of file
            t = file.tell()  # Report the location
            file.seek(0)  # and return pointer back to 0
            if t: return 1
            else: return 0

    security.declarePrivate('_edit')

    def _edit(self, precondition='', file=''):
        """ Perform changes for user """
        if precondition: self.precondition = precondition
        elif self.precondition: del self.precondition

        if self._isNotEmpty(file):
            self.manage_upload(file)

        self.setFormat(self.content_type)

    security.declareProtected(ModifyPortalContent, 'edit')

    def edit(self, precondition='', file=''):
        """ Update and reindex. """
        self._edit(precondition, file)
        self.reindexObject()

    edit = WorkflowAction(edit)

    security.declareProtected(View, 'download')

    def download(self, REQUEST, RESPONSE):
        """Download this item.
        
        Calls OFS.Image.File.index_html to perform the actual transfer after
        first setting Content-Disposition to suggest a filename.
        
        This method is deprecated, use the URL of this object itself. Because
        the default view of a File object is to download, rather than view,
        this method is obsolete. Also note that certain browsers do not deal
        well with a Content-Disposition header.

        """

        RESPONSE.setHeader('Content-Disposition',
                           'attachment; filename=%s' % self.getId())
        return OFS.Image.File.index_html(self, REQUEST, RESPONSE)

    security.declareProtected(ModifyPortalContent, 'PUT')

    def PUT(self, REQUEST, RESPONSE):
        """ Handle HTTP (and presumably FTP?) PUT requests """
        OFS.Image.File.PUT(self, REQUEST, RESPONSE)
        self.reindexObject()
예제 #8
0
파일: Image.py 프로젝트: bendavis78/zope
class Image(OFS.Image.Image, PortalContent, DefaultDublinCoreImpl):
    """
        A Portal-managed Image
    """

    # The order of base classes is very significant in this case.
    # Image.Image does not store it's id in it's 'id' attribute.
    # Rather, it has an 'id' method which returns the contents of the
    # instnace's __name__ attribute.  Inheriting in the other order
    # obscures this method, resulting in much pulling of hair and
    # gnashing of teeth and fraying of nerves.  Don't do it.
    #
    # Really.

    meta_type = 'Portal Image'
    effective_date = expiration_date = None
    _isDiscussable = 1
    icon = PortalContent.icon

    __ac_permissions__ = ((CMFCorePermissions.ModifyPortalContent,
                           ('edit', )), )

    def __init__(self,
                 id,
                 title='',
                 file='',
                 content_type='',
                 precondition='',
                 subject=(),
                 description='',
                 contributors=(),
                 effective_date=None,
                 expiration_date=None,
                 format='text/html',
                 language='en-US',
                 rights=''):
        OFS.Image.File.__init__(self, id, title, file, content_type,
                                precondition)
        DefaultDublinCoreImpl.__init__(self, title, subject, description,
                                       contributors, effective_date,
                                       expiration_date, format, language,
                                       rights)

    def SearchableText(self):
        """
            SeachableText is used for full text seraches of a portal.
            It should return a concatanation of all useful text.
        """
        return "%s %s" % (self.title, self.description)

    def manage_afterAdd(self, item, container):
        """Both of my parents have an afterAdd method"""
        OFS.Image.Image.manage_afterAdd(self, item, container)
        PortalContent.manage_afterAdd(self, item, container)

    def manage_beforeDelete(self, item, container):
        """Both of my parents have a beforeDelete method"""
        PortalContent.manage_beforeDelete(self, item, container)
        OFS.Image.Image.manage_beforeDelete(self, item, container)

    def edit(self, precondition='', file=''):
        """
            Update image.
        """
        if precondition: self.precondition = precondition
        elif self.precondition: del self.precondition

        if file.filename != '' and file.read() != '':
            self.manage_upload(file)

        self.setFormat(self.content_type)

    edit = WorkflowAction(edit)

    def index_html(self, REQUEST, RESPONSE):
        """
        Display the image, with our without standard_html_[header|footer],
        as appropreate.
        """
        #if REQUEST['PATH_INFO'][-10:] == 'index_html':
        #    return self.view(self, REQUEST)
        return OFS.Image.Image.index_html(self, REQUEST, RESPONSE)
예제 #9
0
파일: Image.py 프로젝트: bendavis78/zope
class Image(OFS.Image.Image, PortalContent, DefaultDublinCoreImpl):
    """
        A Portal-managed Image
    """

    # The order of base classes is very significant in this case.
    # Image.Image does not store it's id in it's 'id' attribute.
    # Rather, it has an 'id' method which returns the contents of the
    # instnace's __name__ attribute.  Inheriting in the other order
    # obscures this method, resulting in much pulling of hair and
    # gnashing of teeth and fraying of nerves.  Don't do it.
    #
    # Really.
    #
    # Note that if you use getId() to retrieve an object's ID, you will avoid
    # this problem altogether. getId is the new way, accessing .id is
    # deprecated.

    __implements__ = (PortalContent.__implements__,
                      DefaultDublinCoreImpl.__implements__)

    meta_type = 'Portal Image'
    effective_date = expiration_date = None
    _isDiscussable = 1
    icon = PortalContent.icon

    security = ClassSecurityInfo()

    def __init__(self,
                 id,
                 title='',
                 file='',
                 content_type='',
                 precondition='',
                 subject=(),
                 description='',
                 contributors=(),
                 effective_date=None,
                 expiration_date=None,
                 format='image/png',
                 language='en-US',
                 rights=''):
        OFS.Image.File.__init__(self, id, title, file, content_type,
                                precondition)
        DefaultDublinCoreImpl.__init__(self, title, subject, description,
                                       contributors, effective_date,
                                       expiration_date, format, language,
                                       rights)

    security.declareProtected(View, 'SearchableText')

    def SearchableText(self):
        """
            SeachableText is used for full text seraches of a portal.
            It should return a concatanation of all useful text.
        """
        return "%s %s" % (self.title, self.description)

    security.declarePrivate('manage_afterAdd')

    def manage_afterAdd(self, item, container):
        """Both of my parents have an afterAdd method"""
        OFS.Image.Image.manage_afterAdd(self, item, container)
        PortalContent.manage_afterAdd(self, item, container)

    security.declarePrivate('manage_afterClone')

    def manage_afterClone(self, item):
        """Both of my parents have an afterClone method"""
        OFS.Image.Image.manage_afterClone(self, item)
        PortalContent.manage_afterClone(self, item)

    security.declarePrivate('manage_beforeDelete')

    def manage_beforeDelete(self, item, container):
        """Both of my parents have a beforeDelete method"""
        PortalContent.manage_beforeDelete(self, item, container)
        OFS.Image.Image.manage_beforeDelete(self, item, container)

    security.declarePrivate('_isNotEmpty')

    def _isNotEmpty(self, file):
        """ Do various checks on 'file' to try to determine non emptiness. """
        if not file:
            return 0  # Catches None, Missing.Value, ''
        elif file and (type(file) is type('')):
            return 1
        elif getattr(file, 'filename', None):
            return 1
        elif not hasattr(file, 'read'):
            return 0
        else:
            file.seek(0, 2)  # 0 bytes back from end of file
            t = file.tell()  # Report the location
            file.seek(0)  # and return pointer back to 0
            if t: return 1
            else: return 0

    security.declarePrivate('_edit')

    def _edit(self, precondition='', file=''):
        """ Update image. """
        if precondition: self.precondition = precondition
        elif self.precondition: del self.precondition

        if self._isNotEmpty(file):
            self.manage_upload(file)

    security.declareProtected(ModifyPortalContent, 'edit')

    def edit(self, precondition='', file=''):
        """ Update and reindex. """
        self._edit(precondition, file)
        self.reindexObject()

    edit = WorkflowAction(edit)

    security.declareProtected(View, 'index_html')

    def index_html(self, REQUEST, RESPONSE):
        """
        Display the image, with or without standard_html_[header|footer],
        as appropriate.
        """
        #if REQUEST['PATH_INFO'][-10:] == 'index_html':
        #    return self.view(self, REQUEST)
        return OFS.Image.Image.index_html(self, REQUEST, RESPONSE)

    security.declareProtected(View, 'Format')

    def Format(self):
        """ Dublin Core element - resource format """
        return self.content_type

    security.declareProtected(ModifyPortalContent, 'setFormat')

    def setFormat(self, format):
        """ Dublin Core element - resource format """
        self.manage_changeProperties(content_type=format)

    security.declareProtected(ModifyPortalContent, 'PUT')

    def PUT(self, REQUEST, RESPONSE):
        """ Handle HTTP (and presumably FTP?) PUT requests """
        OFS.Image.Image.PUT(self, REQUEST, RESPONSE)
        self.reindexObject()
예제 #10
0
class DefaultDublinCoreImpl(PropertyManager):
    """
        Mix-in class which provides Dublin Core methods
    """

    security = ClassSecurityInfo()

    def __init__(self,
                 title='',
                 subject=(),
                 description='',
                 contributors=(),
                 effective_date=None,
                 expiration_date=None,
                 format='text/html',
                 language='',
                 rights=''):
        self.creation_date = DateTime()
        self._editMetadata(title, subject, description, contributors,
                           effective_date, expiration_date, format, language,
                           rights)

    #
    #  DublinCore interface query methods
    #
    security.declarePublic('Title')

    def Title(self):
        "Dublin Core element - resource name"
        return self.title

    security.declarePublic('Creator')

    def Creator(self):
        # XXX: fixme using 'portal_membership' -- should iterate over
        #       *all* owners
        "Dublin Core element - resource creator"
        owner = self.getOwner()
        if hasattr(owner, 'getUserName'):
            return owner.getUserName()
        return 'No owner'

    security.declarePublic('Subject')

    def Subject(self):
        "Dublin Core element - resource keywords"
        return self.subject

    security.declarePublic('Publisher')

    def Publisher(self):
        "Dublin Core element - resource publisher"
        # XXX: fixme using 'portal_metadata'
        return 'No publisher'

    security.declarePublic('Description')

    def Description(self):
        "Dublin Core element - resource summary"
        return self.description

    security.declarePublic('Contributors')

    def Contributors(self):
        "Dublin Core element - additional contributors to resource"
        # XXX: fixme
        return self.contributors

    security.declarePublic('Date')

    def Date(self):
        "Dublin Core element - default date"
        # Return effective_date if set, modification date otherwise
        date = getattr(self, 'effective_date', None)
        if date is None:
            date = self.bobobase_modification_time()
        return date.ISO()

    security.declarePublic('CreationDate')

    def CreationDate(self):
        """
            Dublin Core element - date resource created.
        """
        return self.creation_date.ISO()

    security.declarePublic('EffectiveDate')

    def EffectiveDate(self):
        """
            Dublin Core element - date resource becomes effective.
        """
        return self.effective_date and self.effective_date.ISO() or 'None'

    security.declarePublic('ExpirationDate')

    def ExpirationDate(self):
        """
            Dublin Core element - date resource expires.
        """
        return self.expiration_date and self.expiration_date.ISO() or 'None'

    security.declarePublic('ModificationDate')

    def ModificationDate(self):
        """
            Dublin Core element - date resource last modified.
        """
        return self.bobobase_modification_time().ISO()

    security.declarePublic('Type')

    def Type(self):
        "Dublin Core element - Object type"
        if hasattr(aq_base(self), 'getTypeInfo'):
            ti = self.getTypeInfo()
            if ti is not None:
                return ti.Type()
        return self.meta_type

    security.declarePublic('Format')

    def Format(self):
        """
            Dublin Core element - resource format
        """
        return self.format

    security.declarePublic('Identifier')

    def Identifier(self):
        "Dublin Core element - Object ID"
        # XXX: fixme using 'portal_metadata' (we need to prepend the
        #      right prefix to self.getPhysicalPath().
        return self.absolute_url()

    security.declarePublic('Language')

    def Language(self):
        """
            Dublin Core element - resource language
        """
        return self.language

    security.declarePublic('Rights')

    def Rights(self):
        """
            Dublin Core element - resource copyright
        """
        return self.rights

    #
    #  DublinCore utility methods
    #
    def content_type(self):
        """
            WebDAV needs this to do the Right Thing (TM).
        """
        return self.Format()

    security.declarePublic('isEffective')

    def isEffective(self, date):
        """
            Is the date within the resource's effective range?
        """
        pastEffective = (self.effective_date is None
                         or self.effective_date <= date)
        beforeExpiration = (self.expiration_date is None
                            or self.expiration_date >= date)
        return pastEffective and beforeExpiration

    #
    #  CatalogableDublinCore methods
    #
    security.declarePublic('created')

    def created(self):
        """
            Dublin Core element - date resource created,
              returned as DateTime.
        """
        return self.creation_date

    __FLOOR_DATE = DateTime(1000, 0)  # alwasy effective

    security.declarePublic('effective')

    def effective(self):
        """
            Dublin Core element - date resource becomes effective,
              returned as DateTime.
        """
        marker = []
        date = getattr(self, 'effective_date', marker)
        if date is marker:
            date = getattr(self, 'creation_date', None)
        return date is None and self.__FLOOR_DATE or date

    __CEILING_DATE = DateTime(9999, 0)  # never expires

    security.declarePublic('expires')

    def expires(self):
        """
            Dublin Core element - date resource expires,
              returned as DateTime.
        """
        date = getattr(self, 'expiration_date', None)
        return date is None and self.__CEILING_DATE or date

    security.declarePublic('modified')

    def modified(self):
        """
            Dublin Core element - date resource last modified,
              returned as DateTime.
        """
        return self.bobobase_modification_time()

    security.declarePublic('getMetadataHeaders')

    def getMetadataHeaders(self):
        """
            Return RFC-822-style headers.
        """
        hdrlist = []
        hdrlist.append(('Title', self.Title()))
        hdrlist.append(('Subject', string.join(self.Subject(), ', ')))
        hdrlist.append(('Publisher', self.Publisher()))
        hdrlist.append(('Description', self.Description()))
        hdrlist.append(('Contributors', string.join(self.Contributors(),
                                                    '; ')))
        hdrlist.append(('Effective_date', self.EffectiveDate()))
        hdrlist.append(('Expiration_date', self.ExpirationDate()))
        hdrlist.append(('Type', self.Type()))
        hdrlist.append(('Format', self.Format()))
        hdrlist.append(('Language', self.Language()))
        hdrlist.append(('Rights', self.Rights()))
        return hdrlist

    #
    #  MutableDublinCore methods
    #
    security.declarePrivate('_datify')

    def _datify(self, attrib):
        if attrib == 'None':
            attrib = None
        elif not isinstance(attrib, DateTime):
            if attrib is not None:
                attrib = DateTime(attrib)
        return attrib

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setTitle')

    def setTitle(self, title):
        "Dublin Core element - resource name"
        self.title = title

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setSubject')

    def setSubject(self, subject):
        "Dublin Core element - resource keywords"
        self.subject = tuplize('subject', subject)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setDescription')

    def setDescription(self, description):
        "Dublin Core element - resource summary"
        self.description = description

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setContributors')

    def setContributors(self, contributors):
        "Dublin Core element - additional contributors to resource"
        # XXX: fixme
        self.contributors = tuplize('contributors', contributors, semi_split)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setEffectiveDate')

    def setEffectiveDate(self, effective_date):
        """
            Dublin Core element - date resource becomes effective.
        """
        self.effective_date = self._datify(effective_date)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setExpirationDate')

    def setExpirationDate(self, expiration_date):
        """
            Dublin Core element - date resource expires.
        """
        self.expiration_date = self._datify(expiration_date)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setFormat')

    def setFormat(self, format):
        """
            Dublin Core element - resource format
        """
        self.format = format

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setLanguage')

    def setLanguage(self, language):
        """
            Dublin Core element - resource language
        """
        self.language = language

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'setRights')

    def setRights(self, rights):
        """
            Dublin Core element - resource copyright
        """
        self.rights = rights

    #
    #  Management tab methods
    #

    security.declarePrivate('_editMetadata')

    def _editMetadata(self,
                      title='',
                      subject=(),
                      description='',
                      contributors=(),
                      effective_date=None,
                      expiration_date=None,
                      format='text/html',
                      language='en-US',
                      rights=''):
        """
            Update the editable metadata for this resource.
        """
        self.setTitle(title)
        self.setSubject(subject)
        self.setDescription(description)
        self.setContributors(contributors)
        self.setEffectiveDate(effective_date)
        self.setExpirationDate(expiration_date)
        self.setFormat(format)
        self.setLanguage(language)
        self.setRights(rights)
        self.reindexObject()

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'manage_metadata')
    manage_metadata = DTMLFile('zmi_metadata', _dtmldir)

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'manage_editMetadata')

    def manage_editMetadata(self, title, subject, description, contributors,
                            effective_date, expiration_date, format, language,
                            rights, REQUEST):
        """
            Update metadata from the ZMI.
        """
        self._editMetadata(title, subject, description, contributors,
                           effective_date, expiration_date, format, language,
                           rights)
        REQUEST['RESPONSE'].redirect(self.absolute_url() + '/manage_metadata' +
                                     '?manage_tabs_message=Metadata+updated.')

    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
                              'editMetadata')
    editMetadata = WorkflowAction(_editMetadata)
예제 #11
0
파일: NewsItem.py 프로젝트: bendavis78/zope
class NewsItem(PortalContent, DefaultDublinCoreImpl):
    """
        A News Item
    """

    meta_type = 'News Item'
    effective_date = expiration_date = None
    _isDiscussable = 1

    __ac_permissions__ = (
        (CMFCorePermissions.View, ('')),
        (CMFCorePermissions.ModifyPortalContent, ('edit', )),
    )

    def __init__(self, id, title='', text='', description=''):
        DefaultDublinCoreImpl.__init__(self)
        self.id = id
        self.title = title
        self.text = text
        self.description = description
        self._parse()

    def edit(self, text, description):
        """
            Edit the News Item
        """
        self.text = text
        self.description = description
        self._parse()

    edit = WorkflowAction(edit)

    def _parse(self):
        self.cooked_text = self._format_text(self)

    _format_text = HTML('''<dtml-var text fmt="structured-text">''')

    def SearchableText(self):
        """
            text for indexing
        """
        return "%s %s %s" % (self.title, self.description, self.text)

    def Description(self):
        """
            description for indexing
        """
        return self.description

    ## FTP handlers

    def PUT(self, REQUEST, RESPONSE):
        """Handle HTTP (and presumably FTP?) PUT requests"""
        try:
            self.dav__init(REQUEST, RESPONSE)

            headers = {}
            for k, v in self.getMetadataHeaders():
                if k != 'Format':
                    headers[k] = v

            body = REQUEST.get('BODY', '')
            headers, body = parseHeadersBody(body, headers)

            if not headers.has_key('Format'):  # not supplied in headers
                from NullPortalResource import sniffContentType
                sniffFmt = sniffContentType(self.getId(), body)
                fmt = REQUEST.get_header('content-type', sniffFmt)
                headers['Format'] = fmt

            self.editMetadata(title=headers['Title'],
                              subject=headers['Subject'],
                              description=headers['Description'],
                              contributors=headers['Contributors'],
                              effective_date=headers['Effective_date'],
                              expiration_date=headers['Expiration_date'],
                              format=headers['Format'],
                              language=headers['Language'],
                              rights=headers['Rights'])
            self.edit(title=self.Title(),
                      description=self.Description(),
                      text=body)
            RESPONSE.setStatus(204)
            return RESPONSE
        except:
            import traceback
            traceback.print_exc()
            raise

    def manage_FTPget(self):
        "Get the document body for FTP download"
        from string import join
        hdrlist = self.getMetadataHeaders()
        hdrtext = join(map(lambda x: '%s: %s' % (x[0], x[1]), hdrlist), '\n')
        return '%s\n\n%s' % (hdrtext, self.text)
예제 #12
0
파일: Event.py 프로젝트: bendavis78/zope
class Event(PortalContent, DefaultDublinCoreImpl):
    """
    Events are objects for the Calendar topical query.
    """
    meta_type='CMF Event'

    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(View)

    __implements__ = ( PortalContent.__implements__
                     , DefaultDublinCoreImpl.__implements__
                     )

    def __init__(self
                 , id
                 , title=''
                 , description=''
                 , effective_date = None 
                 , expiration_date = None 
                 , start_date = None
                 , end_date = None
                 , location=''
                 , contact_name=''
                 , contact_email=''
                 , contact_phone=''
                 , event_url=''
                ):
        DefaultDublinCoreImpl.__init__(self)
        self.id=id
        self.setTitle(title)
        self.setDescription(description)
        self.effective_date = effective_date
        self.expiration_date = expiration_date
        self.setStartDate(start_date)

        if start_date is None:
            start_date = DateTime()
        if end_date is None:
            end_date = start_date

        if end_date < start_date:
            end_date = start_date

        self.setEndDate(end_date)
        self.location=location
        self.contact_name=contact_name
        self.contact_email=contact_email
        self.contact_phone=contact_phone
        self.event_url=event_url

    security.declarePrivate( '_datify' )
    def _datify( self, attrib ):
        if attrib == 'None':
            attrib = None
        elif not isinstance( attrib, DateTime ):
            if attrib is not None:
                attrib = DateTime( attrib )
        return attrib

    security.declarePublic('getEndStrings')
    def getEndStrings(self):
        """
        """
        return _dateStrings(self.end())

    security.declarePublic('getStartStrings')
    def getStartStrings(self):
        """
        """
        return _dateStrings(self.start())

    security.declareProtected(ChangeEvents, 'edit')
    def edit(self
             , title=None
             , description=None
             , eventType=None
             , effectiveDay=None
             , effectiveMo=None
             , effectiveYear=None
             , expirationDay=None
             , expirationMo=None
             , expirationYear=None
             , start_time=None
             , startAMPM=None
             , stop_time=None
             , stopAMPM=None
             , location=None
             , contact_name=None
             , contact_email=None
             , contact_phone=None
             , event_url=None
            ):
        """\
        """

        if title is not None: 
            self.setTitle(title)
        if description is not None:
            self.setDescription(description)
        if eventType is not None:
            self.setSubject(eventType)

        start_date = end_date = None

        if effectiveDay and effectiveMo and effectiveYear and start_time:
            efdate = '%s/%s/%s %s %s' % (effectiveYear
                                         , effectiveMo
                                         , effectiveDay
                                         , start_time
                                         , startAMPM
                                         )
            start_date = DateTime( efdate )

        if expirationDay and expirationMo and expirationYear and stop_time:

            exdate = '%s/%s/%s %s %s' % (expirationYear
                                         , expirationMo
                                         , expirationDay
                                         , stop_time
                                         , stopAMPM
                                         )
            end_date = DateTime( exdate )

        if start_date and end_date:

            if end_date < start_date:
                end_date = start_date

            self.setStartDate( start_date )
            self.setEndDate( end_date )

        if location is not None:
            self.location = location
        if contact_name is not None:
            self.contact_name = contact_name
        if contact_email is not None:
            self.contact_email = contact_email
        if contact_phone is not None:
            self.contact_phone = contact_phone
        if event_url is not None:
            self.event_url = event_url
        self.reindexObject()
    edit = WorkflowAction(edit) 

    security.declarePublic('buildTimes')
    def buildTimes(self):
        result = []
        for hour in range (1, 13):
            for min in (00, 30):
                result.append('%02d:%02d' % (hour, min))
        return result

    security.declarePublic('buildDays')
    def buildDays(self):
        result = []
        for day in range (1, 32):
            result.append(str('%d' % (day)))
        return result

    security.declarePublic('buildMonths')
    def buildMonths(self):
        result = []
        for month in range (1, 13):
            result.append(str('%d' % (month)))
        return result

    security.declarePublic('buildYears')
    def buildYears(self):
        result = []
        start = (DateTime().year() - 2)
        end = (DateTime().year() + 5)
        for year in range (start, end):
            result.append(str(year))
        return result

    security.declareProtected(ChangeEvents, 'setStartDate')
    def setStartDate(self, start):
        """
        Setting the event start date, when the event is scheduled to begin.
        """
        self.start_date = self._datify(start)

    security.declareProtected(ChangeEvents, 'setEndDate')
    def setEndDate(self, end):
        """
        Setting the event end date, when the event ends.
        """
        self.end_date = self._datify(end)

    security.declarePublic('start')
    def start(self):
        """
            Return our start time as a string.
        """
        date = getattr( self, 'start_date', None )
        return date is None and self.created() or date

    security.declarePublic('end')
    def end(self):
        """
            Return our stop time as a string.
        """
        date = getattr( self, 'end_date', None )
        return date is None and self.start() or date    

    security.declarePublic('getStartTimeString')
    def getStartTimeString( self ):
        """
            Return our start time as a string.
        """
        return self.start().AMPMMinutes() 

    security.declarePublic('getStopTimeString')
    def getStopTimeString( self ):
        """
            Return our stop time as a string.
        """
        return self.end().AMPMMinutes() 

    security.declarePrivate('handleText')
    def handleText(self, text, format=None):
        """ Handles the raw text, returning headers, body, cooked, format """
        headers = {}
        if format == 'html':
            parser = SimpleHTMLParser()
            parser.feed(text)
            headers.update(parser.metatags)
            if parser.title:
                headers['Title'] = parser.title
            bodyfound = bodyfinder(text)
            if bodyfound:
                body = bodyfound
        else:
            headers, body = parseHeadersBody(text, headers)

        return headers, body, format

    security.declareProtected(ModifyPortalContent, 'setMetadata')
    def setMetadata(self, headers):
        headers['Format'] = self.Format()
        new_subject = keywordsplitter(headers)
        headers['Subject'] = new_subject or self.Subject()
        new_contrib = contributorsplitter(headers)
        headers['Contributors'] = new_contrib or self.Contributors()
        haveheader = headers.has_key
        for key, value in self.getMetadataHeaders():
            if not haveheader(key):
                headers[key] = value
        self._editMetadata(title=headers['Title'],
                          subject=headers['Subject'],
                          description=headers['Description'],
                          contributors=headers['Contributors'],
                          effective_date=headers['Effective_date'],
                          expiration_date=headers['Expiration_date'],
                          format=headers['Format'],
                          language=headers['Language'],
                          rights=headers['Rights'],
                          )

    security.declarePublic( 'getMetadataHeaders' )
    def getMetadataHeaders(self):
        """Return RFC-822-style header spec."""
        hdrlist = DefaultDublinCoreImpl.getMetadataHeaders(self)
        hdrlist.append( ('StartDate', self.start().strftime("%Y-%m-%d %H:%M:%S") ) )
        hdrlist.append( ('EndDate',  self.end().strftime("%Y-%m-%d %H:%M:%S") ) )
        hdrlist.append( ('Location', self.location) )
        hdrlist.append( ('ContactName', self.contact_name) )
        hdrlist.append( ('ContactEmail', self.contact_email) )
        hdrlist.append( ('ContactPhone', self.contact_phone) )
        hdrlist.append( ('EventURL', self.event_url) )

        return hdrlist

    ## FTP handlers
    security.declareProtected(ModifyPortalContent, 'PUT')

    def PUT(self, REQUEST, RESPONSE):
        """ Handle HTTP (and presumably FTP?) PUT requests """
        self.dav__init(REQUEST, RESPONSE)
        self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
        body = REQUEST.get('BODY', '')
        guessedformat = REQUEST.get_header('Content-Type', 'text/plain')
        ishtml = (guessedformat == 'text/html') or html_headcheck(body)

        if ishtml: self.setFormat('text/html')
        else: self.setFormat('text/plain')

        try:
            headers, body, format = self.handleText(text=body)
            self.setMetadata(headers)
            self.setStartDate(headers['StartDate'])
            self.setEndDate(headers['EndDate'])
            self.edit( location=headers['Location']
             , contact_name=headers['ContactName']
             , contact_email=headers['ContactEmail']
             , contact_phone=headers['ContactPhone']
             , event_url=headers['EventURL']
             )

        except ResourceLockedError, msg:
            get_transaction().abort()
            RESPONSE.setStatus(423)
            return RESPONSE

        RESPONSE.setStatus(204)
        self.reindexObject()
        return RESPONSE
예제 #13
0
파일: Event.py 프로젝트: bendavis78/zope
class Event(PortalContent, DefaultDublinCoreImpl):
    """
    Events are objects for the Calendar topical query.
    """
    meta_type = 'CMF Event'

    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(CMFCorePermissions.View)

    def __init__(self,
                 id,
                 title='',
                 description='',
                 effective_date=None,
                 expiration_date=None,
                 start_date=DateTime(),
                 end_date=DateTime(),
                 location='',
                 contact_name='',
                 contact_email='',
                 contact_phone='',
                 event_url=''):
        DefaultDublinCoreImpl.__init__(self)
        self.id = id
        self.setTitle(title)
        self.setDescription(description)
        self.effective_date = effective_date
        self.expiration_date = expiration_date
        self.setStartDate(start_date)
        self.setEndDate(end_date)
        self.location = location
        self.contact_name = contact_name
        self.contact_email = contact_email
        self.contact_phone = contact_phone
        self.event_url = event_url

    security.declarePrivate('_datify')

    def _datify(self, attrib):
        if attrib == 'None':
            attrib = None
        elif not isinstance(attrib, DateTime):
            if attrib is not None:
                attrib = DateTime(attrib)
        return attrib

    security.declarePublic('getEndStrings')

    def getEndStrings(self):
        """
        """
        return _dateStrings(self.end())

    security.declarePublic('getStartStrings')

    def getStartStrings(self):
        """
        """
        return _dateStrings(self.start())

    security.declareProtected(EventPermissions.ChangeEvents, 'edit')

    def edit(self,
             title=None,
             description=None,
             eventType=None,
             effectiveDay=None,
             effectiveMo=None,
             effectiveYear=None,
             expirationDay=None,
             expirationMo=None,
             expirationYear=None,
             start_time=None,
             startAMPM=None,
             stop_time=None,
             stopAMPM=None,
             location=None,
             contact_name=None,
             contact_email=None,
             contact_phone=None,
             event_url=None):
        """\
        """
        if title is not None:
            self.setTitle(title)
        if description is not None:
            self.setDescription(description)
        if eventType is not None:
            self.setSubject(eventType)
        efdate = '%s/%s/%s %s %s' % (effectiveDay, effectiveMo, effectiveYear,
                                     start_time, startAMPM)

        exdate = '%s/%s/%s %s %s' % (expirationDay, expirationMo,
                                     expirationYear, stop_time, stopAMPM)

        self.setStartDate(DateTime(efdate))
        self.setEndDate(DateTime(exdate))
        if location is not None:
            self.location = location
        if contact_name is not None:
            self.contact_name = contact_name
        if contact_email is not None:
            self.contact_email = contact_email
        if contact_phone is not None:
            self.contact_phone = contact_phone
        if event_url is not None:
            self.event_url = event_url
        self.reindexObject()

    edit = WorkflowAction(edit)

    security.declarePublic('buildTimes')

    def buildTimes(self):
        result = []
        for hour in range(1, 13):
            for min in (00, 30):
                result.append('%02d:%02d' % (hour, min))
        return result

    security.declarePublic('buildDays')

    def buildDays(self):
        result = []
        for day in range(1, 32):
            result.append(str('%d' % (day)))
        return result

    security.declarePublic('buildMonths')

    def buildMonths(self):
        result = []
        for month in range(1, 13):
            result.append(str('%d' % (month)))
        return result

    security.declarePublic('buildYears')

    def buildYears(self):
        result = []
        start = (DateTime().year() - 2)
        end = (DateTime().year() + 5)
        for year in range(start, end):
            result.append(str(year))
        return result

    security.declareProtected(EventPermissions.ChangeEvents, 'setStartDate')

    def setStartDate(self, start):
        """
        Setting the event start date, when the event is scheduled to begin.
        """
        self.start_date = self._datify(start)

    security.declareProtected(EventPermissions.ChangeEvents, 'setEndDate')

    def setEndDate(self, end):
        """
        Setting the event end date, when the event ends.
        """
        self.end_date = self._datify(end)

    security.declarePublic('start')

    def start(self):
        """
            Return our start time as a string.
        """
        date = getattr(self, 'start_date', None)
        return date is None and self.created() or date

    security.declarePublic('end')

    def end(self):
        """
            Return our stop time as a string.
        """
        date = getattr(self, 'end_date', None)
        return date is None and self.start() or date

    security.declarePublic('getStartTimeString')

    def getStartTimeString(self):
        """
            Return our start time as a string.
        """
        return self.start().AMPMMinutes()

    security.declarePublic('getStopTimeString')

    def getStopTimeString(self):
        """
            Return our stop time as a string.
        """
        return self.end().AMPMMinutes()
예제 #14
0
파일: File.py 프로젝트: bendavis78/zope
class File( OFS.Image.File
          , PortalContent
          , DefaultDublinCoreImpl
          ):
    """
        A Portal-managed File
    """

    # The order of base classes is very significant in this case.
    # Image.File does not store it's id in it's 'id' attribute.
    # Rather, it has an 'id' method which returns the contents of the
    # instnace's __name__ attribute.  Inheriting in the other order
    # obscures this method, resulting in much pulling of hair and
    # gnashing of teeth and fraying of nerves.  Don't do it.
    #
    # Really.
    # 
    # Note that if you use getId() to retrieve an object's ID, you will avoid
    # this problem altogether. getId is the new way, accessing .id is
    # deprecated.
    
    meta_type='Portal File'
    effective_date = expiration_date = None
    _isDiscussable = 1
    icon = PortalContent.icon

    __ac_permissions__ = (
        (CMFCorePermissions.View, ('download',)),
        (CMFCorePermissions.ModifyPortalContent, ('edit',)),
        )
    
    def __init__( self
                , id
                , title=''
                , file=''
                , content_type=''
                , precondition=''
                , subject=()
                , description=''
                , contributors=()
                , effective_date=None
                , expiration_date=None
                , format='text/html'
                , language='en-US'
                , rights=''
                ):
        OFS.Image.File.__init__( self, id, title, file
                               , content_type, precondition )
        DefaultDublinCoreImpl.__init__( self, title, subject, description
                               , contributors, effective_date, expiration_date
                               , format, language, rights )
    
    def SearchableText(self):
        """
        SeachableText is used for full text seraches of a portal.  It
        should return a concatanation of all useful text.
        """
        return "%s %s" % (self.title, self.description)

    def manage_afterAdd(self, item, container):
        """Both of my parents have an afterAdd method"""
        OFS.Image.File.manage_afterAdd(self, item, container)
        PortalContent.manage_afterAdd(self, item, container)

    def manage_beforeDelete(self, item, container):
        """Both of my parents have a beforeDelete method"""
        PortalContent.manage_beforeDelete(self, item, container)
        OFS.Image.File.manage_beforeDelete(self, item, container)

    def edit(self, precondition='', file=''):
        """
        Perform changes for user
        """
        if precondition: self.precondition = precondition
        elif self.precondition: del self.precondition

        if file.filename != '' and file.read() != '':
            self.manage_upload(file)

        self.setFormat(self.content_type)
    edit = WorkflowAction(edit)

    def download(self, REQUEST, RESPONSE):
        """Download this item.
        
        Calls OFS.Image.File.index_html to perform the actual transfer after
        first setting Content-Disposition to suggest a filename.
        
        This method is deprecated, use the URL of this object itself. Because
        the default view of a File object is to download, rather than view,
        this method is obsolete. Also note that certain browsers do not deal
        well with a Content-Disposition header.

        """

        RESPONSE.setHeader('Content-Disposition',
                           'attachment; filename=%s' % self.getId())
        return OFS.Image.File.index_html(self, REQUEST, RESPONSE)
예제 #15
0
파일: Document.py 프로젝트: bendavis78/zope
class Document(PortalContent, DefaultDublinCoreImpl):
    """
    A Document
    """

    meta_type = 'Document'
    effective_date = expiration_date = None
    _isDiscussable = 1

    # Declarative security (replaces __ac_permissions__)
    security = ClassSecurityInfo()
    security.declareProtected(
        CMFCorePermissions.View,
        'manage_FTPget',
        'Format',
        'Description',
    )
    security.declareProtected(
        CMFCorePermissions.ModifyPortalContent,
        'edit',
        'setFormat',
    )

    def __init__(self, id, title='', description='', text_format='', text=''):
        DefaultDublinCoreImpl.__init__(self)
        self.id = id
        self.title = title
        self.description = description
        self.text = text
        self.text_format = text_format
        self.edit(text_format, text)

    def edit(self, text_format, text, file=''):
        """
        Edit the Document
        """
        self.text = text
        headers = {}
        if file and (type(file) is not type('')):
            contents = file.read()
            if contents:
                text = self.text = contents

        # Now parse out HTML if its applicable, or the plain text,
        # getting any headers passed along in the document
        bodyfound = bodyfinder.search(text)
        ishtml = (text_format == 'html') or (bodyfound is not None)
        if ishtml:
            parser = SimpleHTMLParser()
            parser.feed(text)
            headers.update(parser.metatags)
            if parser.title: headers['Title'] = parser.title
            if bodyfound:
                text = self.text = bodyfound.group('bodycontent')
            text_format = self.text_format = 'html'
        else:
            headers, text = parseHeadersBody(text, headers)
            text_format = self.text_format = 'structured-text'
            self.text = text

        headers['Format'] = self.Format()
        haveheader = headers.has_key
        for key, value in self.getMetadataHeaders():
            if key != 'Format' and not haveheader(key):
                headers[key] = value

        self.editMetadata(
            title=headers['Title'],
            subject=headers['Subject'],
            description=headers['Description'],
            contributors=headers['Contributors'],
            effective_date=headers['Effective_date'],
            expiration_date=headers['Expiration_date'],
            format=headers['Format'],
            language=headers['Language'],
            rights=headers['Rights'],
        )
        self._parse()

    edit = WorkflowAction(edit)

    def _parse(self):
        """\
        If the format is structured text, this method turns our body text
        into HTML for 'cooked_text', used by the default skins for Document.
        """
        if self.text_format == 'structured-text':
            ct = self._format_text(text=self.text)
            if type(ct) is not type(''):
                ct = ct.read()
            self.cooked_text = ct
        else:
            self.cooked_text = self.text

    _format_text = HTML('''<dtml-var text fmt="structured-text">''')

    def SearchableText(self):
        "text for indexing"
        return "%s %s %s" % (self.title, self.description, self.text)

    def Description(self):
        "description for indexing"
        return self.description

    def Format(self):
        """ """
        if self.text_format == 'html':
            return 'text/html'
        else:
            return 'text/plain'

    def setFormat(self, value):
        value = str(value)
        if value == 'text/html':
            self.text_format = 'html'
        else:
            self.text_format = 'structured-text'

    setFormat = WorkflowAction(setFormat)

    ## FTP handlers
    def PUT(self, REQUEST, RESPONSE):
        """Handle HTTP (and presumably FTP?) PUT requests"""
        self.dav__init(REQUEST, RESPONSE)
        body = REQUEST.get('BODY', '')
        ishtml = 0

        if (REQUEST.get_header('Content-Type', '') == 'text/html') or \
           (string.find(body, '</body>') > -1):
            ishtml = 1

        if ishtml: self.setFormat('text/html')
        else: self.setFormat('text/plain')

        self.edit(text_format=self.text_format, text=body)

        RESPONSE.setStatus(204)
        return RESPONSE

    _htmlsrc = ('<html>\n <head>\n'
                ' <title>%(title)s</title>\n'
                ' %(metatags)s'
                ' </head>\n'
                ' <body>\n%(body)s\n </body>\n'
                '</html>\n')

    def manage_FTPget(self):
        "Get the document body for FTP download (also used for the WebDAV SRC)"
        join = string.join
        hdrlist = self.getMetadataHeaders()
        if self.Format() == 'text/html':
            hdrtext = join(
                map(lambda x: '<meta name="%s" content="%s" />' % (x[0], x[1]),
                    hdrlist), '\n')
            bodytext = self._htmlsrc % {
                'title': self.Title(),
                'metatags': hdrtext,
                'body': self.text,
            }
        else:
            hdrtext = join(map(lambda x: '%s: %s' % (x[0], x[1]), hdrlist),
                           '\n')
            bodytext = '%s\n\n%s' % (hdrtext, self.text)

        return bodytext

    def get_size(self):
        " "
        return len(self.manage_FTPget())
예제 #16
0
파일: Favorite.py 프로젝트: bendavis78/zope
class Favorite( Link ):
    """
        A Favorite (special kind of Link)
    """

    __implements__ = Link.__implements__ # redundant, but explicit

    meta_type='Favorite'

    def __init__( self
                , id
                , title=''
                , remote_url=''
                , description=''
                ):
        DefaultDublinCoreImpl.__init__(self)
        self.id=id
        self.title=title
        self.remote_url=remote_url
        self.description = description

    def getRemoteUrl(self):
        """
            returns the remote URL of the Link
        """
        portal_url = getToolByName(self, 'portal_url')
        if self.remote_url:
            return portal_url() + '/' + self.remote_url
        else:
            return portal_url()

    def getIcon(self, relative_to_portal=0):
        """
        Instead of a static icon, like for Link objects, we want
        to display an icon based on what the Favorite links to.
        """
        try:
            return self.getObject().getIcon(relative_to_portal)
        except:
            return 'p_/broken'

    def getObject(self):
        """
        Return the actual object that the Favorite is 
        linking to
        """
        portal_url = getToolByName(self, 'portal_url')
        return portal_url.getPortalObject().restrictedTraverse(self.remote_url)

    def edit( self, remote_url ):
        """
        Edit the Favorite. Unlike Links, Favorites have URLs that are
        relative to the root of the site.
        """
        # strip off scheme and machine from URL if present
        tokens = urlparse.urlparse( remote_url, 'http' )
        if tokens[0] or tokens[1]:
            t=('', '') + tokens[2:]
            remote_url=urlparse.urlunparse(t)
        # if URL begins with site URL, remove site URL
        portal_url = getToolByName(self, 'portal_url').getPortalPath()
        i=string.find(remote_url, portal_url)
        if i==0:
            remote_url=remote_url[len(portal_url):]
        # if site is still absolute, make it relative
        if remote_url[0]=='/':
            remote_url=remote_url[1:]
        self.remote_url=remote_url

    edit=WorkflowAction(edit)
예제 #17
0
class DefaultDublinCoreImpl( PropertyManager ):
    """
        Mix-in class which provides Dublin Core methods
    """

    __ac_permissions__ = (
        ( 'View'
        , ( 'Title'
          , 'Creator'
          , 'Subject'
          , 'Description'
          , 'Publisher'
          , 'Contributors'
          , 'Date'
          , 'CreationDate'
          , 'EffectiveDate'
          , 'ExpirationDate'
          , 'ModificationDate'
          , 'Type'
          , 'Format'
          , 'Identifier'
          , 'Language'
          , 'Rights'
          , 'getMetadataHeaders'
          )
        , ( 'Owner','Manager','Reviewer' )
        ),
        ( 'Modify portal content'
        , ( 'editMetadata', )
        ),
    )

    def __init__( self
                , title=''
                , subject=()
                , description=''
                , contributors=()
                , effective_date=None
                , expiration_date=None
                , format='text/html'
                , language='en-US'
                , rights=''
            ):
            self.creation_date = DateTime()
            self.editMetadata( title
                             , subject
                             , description
                             , contributors
                             , effective_date
                             , expiration_date
                             , format
                             , language
                             , rights
                             )

    #
    #  DublinCore interface query methods
    #
    def Title( self ):
        "Dublin Core element - resource name"
        return self.title

    def Creator( self ):
        # XXX: fixme using 'portal_membership' -- should iterate over
        #       *all* owners
        "Dublin Core element - resource creator"
        owner = self.getOwner()
        if hasattr( owner, 'getUserName' ):
            return owner.getUserName()
        return 'No owner'

    def Subject( self ):
        "Dublin Core element - resource keywords"
        return self.subject

    def Publisher( self ):
        "Dublin Core element - resource publisher"
        # XXX: fixme using 'portal_metadata'
        return 'No publisher'

    def Description( self ):
        "Dublin Core element - resource summary"
        return self.description

    def Contributors( self ):
        "Dublin Core element - additional contributors to resource"
        # XXX: fixme
        return self.contributors
    
    def Date( self ):
        "Dublin Core element - default date"
        # Return effective_date if set, modification date otherwise
        date = getattr(self, 'effective_date', None )
        if date is None:
            date = self.bobobase_modification_time()
        return date.ISO()
    
    def CreationDate( self ):
        """
            Dublin Core element - date resource created.
        """
        return self.creation_date.ISO()
    
    def EffectiveDate( self ):
        """
            Dublin Core element - date resource becomes effective.
        """
        return self.effective_date and self.effective_date.ISO() or 'None'
    
    def ExpirationDate( self ):
        """
            Dublin Core element - date resource expires.
        """
        return self.expiration_date and self.expiration_date.ISO() or 'None'
    
    def ModificationDate( self ):
        """
            Dublin Core element - date resource last modified.
        """
        return self.bobobase_modification_time().ISO()

    def Type( self ):
        "Dublin Core element - Object type"
        if hasattr(aq_base(self), 'getTypeInfo'):
            ti = self.getTypeInfo()
            if ti is not None:
                return ti.Type()
        return self.meta_type

    def Format( self ):
        """
            Dublin Core element - resource format
        """
        return self.format

    def Identifier( self ):
        "Dublin Core element - Object ID"
        # XXX: fixme using 'portal_metadata' (we need to prepend the
        #      right prefix to self.getPhysicalPath().
        return self.absolute_url()

    def Language( self ):
        """
            Dublin Core element - resource language
        """
        return self.language

    def Rights( self ):
        """
            Dublin Core element - resource copyright
        """
        return self.rights

    #
    #  DublinCore utility methods
    #
    def isEffective( self, date ):
        """
            Is the date within the resource's effective range?
        """
        pastEffective = ( self.effective_date is None
                       or self.effective_date <= date )
        beforeExpiration = ( self.expiration_date is None
                          or self.expiration_date >= date )
        return pastEffective and beforeExpiration

    #
    #  CatalogableDublinCore methods
    #
    def created( self ):
        """
            Dublin Core element - date resource created,
              returned as DateTime.
        """
        return self.creation_date
    
    __FLOOR_DATE = DateTime( 1000, 0 ) # alwasy effective

    def effective( self ):
        """
            Dublin Core element - date resource becomes effective,
              returned as DateTime.
        """
        marker = []
        date = getattr( self, 'effective_date', marker )
        if date is marker:
            date = getattr( self, 'creation_date', None )
        return date is None and self.__FLOOR_DATE or date
    
    __CEILING_DATE = DateTime( 9999, 0 ) # never expires

    def expires( self ):
        """
            Dublin Core element - date resource expires,
              returned as DateTime.
        """
        date = getattr( self, 'expiration_date', None )
        return date is None and self.__CEILING_DATE or date
    
    def modified( self ):
        """
            Dublin Core element - date resource last modified,
              returned as DateTime.
        """
        return self.bobobase_modification_time()

    #
    #  MutableDublinCore methods
    #
    def _datify( self, attrib ):
        if attrib == 'None':
            attrib = None
        if attrib is not None:
            attrib = DateTime( attrib )
        return attrib

    def setTitle( self, title ):
        "Dublin Core element - resource name"
        self.title = title

    def setSubject( self, subject ):
        "Dublin Core element - resource keywords"
        self.subject = tuplize( 'subject', subject )

    def setDescription( self, description ):
        "Dublin Core element - resource summary"
        self.description = description

    def setContributors( self, contributors ):
        "Dublin Core element - additional contributors to resource"
        # XXX: fixme
        self.contributors = tuplize( 'contributors', contributors )

    def setEffectiveDate( self, effective_date ):
        """
            Dublin Core element - date resource becomes effective.
        """
        self.effective_date = self._datify( effective_date )
    
    def setExpirationDate( self, expiration_date ):
        """
            Dublin Core element - date resource expires.
        """
        self.expiration_date = self._datify( expiration_date )
    
    def setFormat( self, format ):
        """
            Dublin Core element - resource format
        """
        self.format = format

    def setLanguage( self, language ):
        """
            Dublin Core element - resource language
        """
        self.language = language

    def setRights( self, rights ):
        """
            Dublin Core element - resource copyright
        """
        self.rights = rights

    def getMetadataHeaders( self ):
        """
            Return RFC-822-style headers.
        """
        hdrlist = []
        hdrlist.append( ( 'Title', self.Title() ) )
        hdrlist.append( ( 'Subject', string.join( self.Subject() ) ) )
        hdrlist.append( ( 'Publisher', self.Publisher() ) )
        hdrlist.append( ( 'Description', self.Description() ) )
        hdrlist.append( ( 'Contributors', string.join(
            self.Contributors() ) ) )
        hdrlist.append( ( 'Effective_date', self.EffectiveDate() ) )
        hdrlist.append( ( 'Expiration_date', self.ExpirationDate() ) )
        hdrlist.append( ( 'Type', self.Type() ) )
        hdrlist.append( ( 'Format', self.Format() ) )
        hdrlist.append( ( 'Language', self.Language() ) )
        hdrlist.append( ( 'Rights', self.Rights() ) )
        return hdrlist

    #
    #  Management tab methods
    #

    def editMetadata( self
                    , title=''
                    , subject=()
                    , description=''
                    , contributors=()
                    , effective_date=None
                    , expiration_date=None
                    , format='text/html'
                    , language='en-US'
                    , rights=''
                    ):
        """
            Update the editable metadata for this resource.
        """
        self.setTitle( title )
        self.setSubject( subject )
        self.setDescription( description )
        self.setContributors( contributors )
        self.setEffectiveDate( effective_date )
        self.setExpirationDate( expiration_date )
        self.setFormat( format )
        self.setLanguage( language )
        self.setRights( rights )

    editMetadata = WorkflowAction(editMetadata)