11bdafaeee52e3efa9b8dc630f60d9b77146745c
[Plinn.git] / File.py
1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 BenoƮt PIN <benoit.pin@ensmp.fr> #
5 # #
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. #
10 # #
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. #
15 # #
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
22 attachments.
23
24 $Id: File.py 1261 2008-01-07 01:34:23Z pin $
25 $URL: http://svn.cri.ensmp.fr/svn/Plinn/branches/CMF-2.1/File.py $
26 """
27
28 from Globals import InitializeClass
29 from AccessControl import ClassSecurityInfo
30 import OFS
31 from zope.component.factory import Factory
32
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
37 class File(BaseFile) :
38 """ file class with portal_transforms support """
39
40 security = ClassSecurityInfo()
41
42 _properties = BaseFile._properties + ({'id':'orig_name', 'type':'string', 'mode':'w', 'label':"Original Name"},)
43 orig_name = ''
44
45
46 def __getattr__(self, name) :
47 try : return BaseFile.__getattr__(self, name)
48 except :
49 selfAttrs = self.__dict__
50 if selfAttrs.has_key('_v_transform_cache') :
51 cache = selfAttrs['_v_transform_cache']
52 cacheTuple = cache.get('text_html', None) # (time, value)
53 if cacheTuple :
54 cacheData = cacheTuple[1]
55
56 subObDict = cacheData.getSubObjects()
57 if subObDict.has_key(name) :
58 fileOb = OFS.Image.File(name, name, subObDict[name])
59 return fileOb
60
61 raise AttributeError, name
62
63 security.declareProtected(ModifyPortalContent, 'edit')
64 def edit(self, precondition='', file=''):
65 orig_name = OFS.Image.cookId('', '', file)[0]
66 if orig_name :
67 self.orig_name = orig_name
68 BaseFile.edit(self, precondition=precondition, file=file)
69 if hasattr(self, '_v_transform_cache') :
70 del self._v_transform_cache
71
72
73 security.declareProtected(View, 'SearchableText')
74 def SearchableText(self) :
75 """ Return full text"""
76 baseSearchableText = BaseFile.SearchableText(self)
77 transformTool = getToolByName(self, 'portal_transforms', default=None)
78 if transformTool is None :
79 return baseSearchableText
80 else :
81 datastream_text = transformTool.convertTo('text/plain',
82 str(self.data),
83 mimetype = self.content_type
84 )
85 full_text = ''
86 if datastream_text is not None :
87 full_text = datastream_text.getData()
88
89 return baseSearchableText + full_text
90
91 security.declareProtected(View, 'preview')
92 def preview(self) :
93 """Return HTML preview if it's possible or empty string """
94 transformTool = getToolByName(self, 'portal_transforms', default = None)
95 if transformTool is None :
96 return ''
97 else :
98 filename = self.getId().replace(' ', '_')
99 datastream = transformTool.convertTo('text/html',
100 str(self.data),
101 object=self,
102 mimetype = self.content_type,
103 filename = filename)
104
105 if datastream is not None : return datastream.getData()
106 else : return ''
107
108 security.declareProtected(View, 'download')
109 def download(self, REQUEST, RESPONSE):
110 """Download this item.
111
112 Calls OFS.Image.File.index_html to perform the actual transfer after
113 first setting Content-Disposition to suggest a filename.
114
115 This method is deprecated, use the URL of this object itself. Because
116 the default view of a File object is to download, rather than view,
117 this method is obsolete. Also note that certain browsers do not deal
118 well with a Content-Disposition header.
119
120 """
121
122 RESPONSE.setHeader('Content-Disposition',
123 'attachment; filename=%s' % (self.orig_name or self.getId()))
124 return OFS.Image.File.index_html(self, REQUEST, RESPONSE)
125
126 security.declarePublic('getIcon')
127 def getIcon(self, relative_to_portal=0):
128 """ return icon corresponding to mime-type
129 """
130 regTool = getToolByName(self, 'mimetypes_registry', default=None)
131 if regTool :
132 mime = regTool(str(self.data), mimetype=self.content_type)[2]
133 return mime.icon_path
134 else :
135 return BaseFile.getIcon(self, relative_to_portal=relative_to_portal)
136
137
138 InitializeClass(File)
139 FileFactory = Factory(File)
140
141
142 def addFile( dispatcher
143 , id
144 , title=''
145 , file=''
146 , content_type=''
147 , precondition=''
148 , subject=()
149 , description=''
150 , contributors=()
151 , effective_date=None
152 , expiration_date=None
153 , format='text/html'
154 , language=''
155 , rights=''
156 ):
157 """
158 Add a File
159 """
160
161 # cookId sets the id and title if they are not explicity specified
162 id, title = OFS.Image.cookId(id, title, file)
163
164 container = dispatcher.Destination()
165
166 # Instantiate the object and set its description.
167 fobj = File( id, title=title, file='', content_type=content_type,
168 precondition=precondition, subject=subject, description=description,
169 contributors=contributors, effective_date=effective_date,
170 expiration_date=expiration_date, format=format,
171 language=language, rights=rights
172 )
173
174 # Add the File instance to self
175 container._setObject(id, fobj)
176
177 # 'Upload' the file. This is done now rather than in the
178 # constructor because the object is now in the ZODB and
179 # can span ZODB objects.
180 container._getOb(id).manage_upload(file)