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
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')
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)
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
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())
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
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()
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)
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()
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)
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)
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
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()
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)
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())
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)
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)