X-Git-Url: https://scm.cri.minesparis.psl.eu/git/Plinn.git/blobdiff_plain/3c4367d8e03450e9a73e61f4247145d2b6c86a33..959d888c17d1403d2eeecc19bc4b5e2c8d1debf6:/AttachmentTool.py?ds=sidebyside diff --git a/AttachmentTool.py b/AttachmentTool.py deleted file mode 100644 index 87535c7..0000000 --- a/AttachmentTool.py +++ /dev/null @@ -1,224 +0,0 @@ -# -*- coding: utf-8 -*- -####################################################################################### -# Plinn - http://plinn.org # -# © 2007-2014 Benoît Pin # -# # -# This program is free software; you can redistribute it and/or # -# modify it under the terms of the GNU General Public License # -# as published by the Free Software Foundation; either version 2 # -# of the License, or (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the Free Software # -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -####################################################################################### -""" Portal attachment management tool. - - - -""" - -from AccessControl import ClassSecurityInfo -from Acquisition import aq_base -from Globals import InitializeClass -from OFS.SimpleItem import SimpleItem -from OFS.Folder import Folder -from OFS.Image import cookId -from Products.Photo.blobbases import File -from zExceptions import Unauthorized -from zExceptions import BadRequest -from Products.Photo import Photo -from Products.CMFCore.utils import UniqueObject, getToolByName, getUtilityByInterfaceName -from Products.CMFCore.permissions import ModifyPortalContent -from Products.CMFCore.exceptions import AccessControl_Unauthorized -from Products.Plinn.utils import makeValidId - -from urllib import unquote -from cgi import escape -from ZServer import LARGE_FILE_THRESHOLD -from webdav.interfaces import IWriteLock -from webdav.common import Locked -from webdav.common import PreconditionFailed -from zope.contenttype import guess_content_type - -from libxml2 import HTML_PARSE_RECOVER, HTML_PARSE_NOERROR, HTML_PARSE_NOWARNING -from libxml2 import htmlReadDoc -PARSE_OPTIONS = HTML_PARSE_RECOVER + HTML_PARSE_NOERROR + HTML_PARSE_NOWARNING - -class AttachmentTool( UniqueObject, SimpleItem): - """ Links attachment objects to contents. - """ - - id = 'portal_attachment' - meta_type = 'Attachment Tool' - manage_options = SimpleItem.manage_options - - security = ClassSecurityInfo() - - security.declarePublic('getAttachmentsFor') - def getAttachmentsFor(self, content): - """getAttachmentsFor returns attachments container of content - """ - if getattr( aq_base(content), 'attachments', None ) is None : - self._createAttachmentContainerFor(content) - - return content.attachments - - security.declarePrivate('_createAttachmentContainerFor') - def _createAttachmentContainerFor(self, content): - """_createAttachmentContainerFor documentation - """ - - content.attachments = AttachmentContainer() - - security.declarePublic('uploadAttachmentFor') - def uploadAttachmentFor(self, content, file, title='', typeName='File') : - "upload attachment inside content's attachment folder." - - mtool = getToolByName(self, 'portal_membership') - if not mtool.checkPermission(ModifyPortalContent, content) : - raise AccessControl_Unauthorized - - utool = getToolByName(self, 'portal_url') - portal = utool.getPortalObject() - - attachments = self.getAttachmentsFor(content) - dummy, title = cookId('', title, file) - id = makeValidId(attachments, title) - - if typeName == 'Photo': - thumbSize = {'thumb_height' : portal.getProperty('thumb_size', 192), - 'thumb_width' : portal.getProperty('thumb_size', 192)} - fileOb = Photo(id, title, file, **thumbSize) - elif typeName == 'File' : - fileOb = File(id, title, '') - fileOb.manage_upload(file) - else : - raise AccessControl_Unauthorized - - content.attachments._setObject(id, fileOb) - fileOb = getattr(content.attachments, id) - return fileOb - - - -InitializeClass( AttachmentTool ) - - -class AttachmentContainer (Folder): - - meta_type = 'Attachment container' - security = ClassSecurityInfo() - - def __init__(self): - self.id = 'attachments' - - security.declarePrivate('checkIdAvailable') - def checkIdAvailable(self, id): - try: - self._checkId(id) - except BadRequest: - return False - else: - return True - - - security.declareProtected(ModifyPortalContent, 'put_upload') - def put_upload(self, REQUEST, RESPONSE): - """ Upload a content thru webdav put method. - The default behavior (NullRessource.PUT + PortalFolder.PUT_factory) - disallow files names with '_' at the begining. - """ - - self.dav__init(REQUEST, RESPONSE) - fileName = unquote(REQUEST.getHeader('X-File-Name', '')) - validId = makeValidId(self, fileName, allow_dup=True) - - ifhdr = REQUEST.get_header('If', '') - if self.wl_isLocked(): - if ifhdr: - self.dav__simpleifhandler(REQUEST, RESPONSE, col=1) - else: - raise Locked - elif ifhdr: - raise PreconditionFailed - - if int(REQUEST.get('CONTENT_LENGTH') or 0) > LARGE_FILE_THRESHOLD: - file = REQUEST['BODYFILE'] - body = file.read(LARGE_FILE_THRESHOLD) - file.seek(0) - else: - body = REQUEST.get('BODY', '') - - typ=REQUEST.get_header('content-type', None) - if typ is None: - typ, enc=guess_content_type(validId, body) - - if self.checkIdAvailable(validId) : - if typ.startswith('image/') : - utool = getUtilityByInterfaceName('Products.CMFCore.interfaces.IURLTool') - portal = utool.getPortalObject() - thumbSize = {'thumb_height' : portal.getProperty('thumb_size', 192), - 'thumb_width' : portal.getProperty('thumb_size', 192)} - ob = Photo(validId, fileName, '', **thumbSize) - else : - ob = File(validId, fileName, '') - - self._setObject(validId, ob) - httpRespCode = 201 - else : - httpRespCode = 200 - ob = self._getOb(validId) - - # We call _verifyObjectPaste with verify_src=0, to see if the - # user can create this type of object (and we don't need to - # check the clipboard. - try: - self._verifyObjectPaste(ob.__of__(self), 0) - except CopyError: - sMsg = 'Unable to create object of class %s in %s: %s' % \ - (ob.__class__, repr(self), sys.exc_info()[1],) - raise Unauthorized, sMsg - - ob.PUT(REQUEST, RESPONSE) - RESPONSE.setStatus(httpRespCode) - RESPONSE.setHeader('Content-Type', 'text/xml;;charset=utf-8') - if ob.meta_type == 'Blob File' : - return '' % (ob.getId(), escape(ob.title_or_id())) - elif ob.meta_type == 'Photo' : - width, height = ob.getResizedImageSize(size=(310, 310)) - return '' % \ - {'src' : 'attachments/%s/getResizedImage?size=%d_%d' % (ob.getId(), width, height), - 'title' : escape(ob.title_or_id()), - 'width' : width, - 'height' : height - } - - security.declareProtected(ModifyPortalContent, 'removeUnusedAttachments') - def removeUnusedAttachments(self, html) : - html = '
%s
' % html - doc = htmlReadDoc(html, '', None, PARSE_OPTIONS) - used = {} - - hrefs = doc.xpathEval('//a/@href') - for href in [a.get_content() for a in hrefs] : - if href.startswith('attachments/') : - used[href[len('attachments/'):]] = True - - srcs = doc.xpathEval('//img/@src') - for src in [a.get_content() for a in srcs] : - if src.startswith('attachments/') : - parts = src.split('/') - if len(parts) >=2 : - used[parts[1]] = True - - unused = [id for id in self.objectIds() if not used.has_key(id)] - if unused : - self.manage_delObjects(unused) - -InitializeClass(AttachmentContainer) \ No newline at end of file