1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 BenoƮt PIN <benoit.pin@ensmp.fr> #
6 # This program is free software; you can redistribute it and/or #
7 # modify it under the terms of the GNU General Public License #
8 # as published by the Free Software Foundation; either version 2 #
9 # of the License, or (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program; if not, write to the Free Software #
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #
19 #######################################################################################
20 """ This module implements a portal-managed File class that's inherits of CMFDefault
21 File. If exists, portal_transforms is called to extract text content, and publish
24 $Id: File.py 1549 2010-02-04 13:04:22Z pin $
25 $URL: http://svn.cri.ensmp.fr/svn/Plinn/branches/CMF-2.1/File.py $
28 from Globals
import InitializeClass
29 from AccessControl
import ClassSecurityInfo
31 from zope
.component
.factory
import Factory
33 from Products
.CMFDefault
.File
import File
as BaseFile
34 from Products
.CMFCore
.permissions
import View
, ModifyPortalContent
35 from Products
.CMFCore
.utils
import getToolByName
36 from swfheader
import parse
as parseswf
38 class File(BaseFile
) :
39 """ file class with portal_transforms support """
41 security
= ClassSecurityInfo()
43 _properties
= BaseFile
._properties
+ ({'id':'orig_name', 'type':'string', 'mode':'w', 'label':"Original Name"},)
47 def __getattr__(self
, name
) :
48 try : return BaseFile
.__getattr
__(self
, name
)
50 selfAttrs
= self
.__dict
__
51 if selfAttrs
.has_key('_v_transform_cache') :
52 cache
= selfAttrs
['_v_transform_cache']
53 cacheTuple
= cache
.get('text_html', None) # (time, value)
55 cacheData
= cacheTuple
[1]
57 subObDict
= cacheData
.getSubObjects()
58 if subObDict
.has_key(name
) :
59 fileOb
= OFS
.Image
.File(name
, name
, subObDict
[name
])
62 raise AttributeError, name
64 def manage_upload(self
,file='',REQUEST
=None):
65 ret
= super(File
, self
).manage_upload(file=file, REQUEST
=REQUEST
)
67 orig_name
= OFS
.Image
.cookId('', '', file)[0]
69 self
.orig_name
= orig_name
71 print self
.absolute_url(), self
.Format()
72 if self
.Format() == 'application/x-shockwave-flash' :
75 swfmetadata
= parseswf(file)
77 swfmetadata
= {'width':600, 'height':600}
79 for name
in ('width', 'height') :
80 value
= swfmetadata
[name
]
81 if self
.hasProperty(name
) :
82 self
._updateProperty
(name
, value
)
84 self
.manage_addProperty(name
, value
, 'int')
90 security
.declareProtected(ModifyPortalContent
, 'edit')
91 def edit(self
, precondition
='', file=''):
92 orig_name
= OFS
.Image
.cookId('', '', file)[0]
94 self
.orig_name
= orig_name
95 BaseFile
.edit(self
, precondition
=precondition
, file=file)
96 if hasattr(self
, '_v_transform_cache') :
97 del self
._v
_transform
_cache
100 security
.declareProtected(View
, 'SearchableText')
101 def SearchableText(self
) :
102 """ Return full text"""
103 baseSearchableText
= BaseFile
.SearchableText(self
)
104 transformTool
= getToolByName(self
, 'portal_transforms', default
=None)
105 if transformTool
is None :
106 return baseSearchableText
108 datastream_text
= transformTool
.convertTo('text/plain',
110 mimetype
= self
.content_type
113 if datastream_text
is not None :
114 full_text
= datastream_text
.getData()
116 return baseSearchableText
+ full_text
118 security
.declareProtected(View
, 'preview')
120 """Return HTML preview if it's possible or empty string """
121 transformTool
= getToolByName(self
, 'portal_transforms', default
= None)
122 if transformTool
is None :
125 filename
= self
.getId().replace(' ', '_')
126 datastream
= transformTool
.convertTo('text/html',
129 mimetype
= self
.content_type
,
132 if datastream
is not None : return datastream
.getData()
135 security
.declareProtected(View
, 'download')
136 def download(self
, REQUEST
, RESPONSE
):
137 """Download this item.
139 Calls OFS.Image.File.index_html to perform the actual transfer after
140 first setting Content-Disposition to suggest a filename.
142 This method is deprecated, use the URL of this object itself. Because
143 the default view of a File object is to download, rather than view,
144 this method is obsolete. Also note that certain browsers do not deal
145 well with a Content-Disposition header.
149 RESPONSE
.setHeader('Content-Disposition',
150 'attachment; filename=%s' % (self
.orig_name
or self
.getId()))
151 return OFS
.Image
.File
.index_html(self
, REQUEST
, RESPONSE
)
153 security
.declarePublic('getIcon')
154 def getIcon(self
, relative_to_portal
=0):
155 """ return icon corresponding to mime-type
157 regTool
= getToolByName(self
, 'mimetypes_registry', default
=None)
159 mime
= regTool(str(self
.data
), mimetype
=self
.content_type
)[2]
160 return mime
.icon_path
162 return BaseFile
.getIcon(self
, relative_to_portal
=relative_to_portal
)
165 InitializeClass(File
)
166 FileFactory
= Factory(File
)
169 def addFile( dispatcher
178 , effective_date
=None
179 , expiration_date
=None
188 # cookId sets the id and title if they are not explicity specified
189 id, title
= OFS
.Image
.cookId(id, title
, file)
191 container
= dispatcher
.Destination()
193 # Instantiate the object and set its description.
194 fobj
= File( id, title
=title
, file='', content_type
=content_type
,
195 precondition
=precondition
, subject
=subject
, description
=description
,
196 contributors
=contributors
, effective_date
=effective_date
,
197 expiration_date
=expiration_date
, format
=format
,
198 language
=language
, rights
=rights
201 # Add the File instance to self
202 container
._setObject
(id, fobj
)
204 # 'Upload' the file. This is done now rather than in the
205 # constructor because the object is now in the ZODB and
206 # can span ZODB objects.
207 container
._getOb
(id).manage_upload(file)