Ticket #9909: file.py

File file.py, 8.1 KB (added by inakkhunbi, 4 years ago)

Content type File.py

Line 
1#  ATContentTypes http://plone.org/products/atcontenttypes/
2#  Archetypes reimplementation of the CMF core types
3#  Copyright (c) 2003-2006 AT Content Types development team
4#
5#  This program is free software; you can redistribute it and/or modify
6#  it under the terms of the GNU General Public License as published by
7#  the Free Software Foundation; either version 2 of the License, or
8#  (at your option) any later version.
9#
10#  This program is distributed in the hope that it will be useful,
11#  but WITHOUT ANY WARRANTY; without even the implied warranty of
12#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#  GNU General Public License for more details.
14#
15#  You should have received a copy of the GNU General Public License
16#  along with this program; if not, write to the Free Software
17#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18#
19"""
20
21"""
22__author__  = 'Christian Heimes <tiran@cheimes.de>'
23__docformat__ = 'restructuredtext'
24__old_name__ = 'Products.ATContentTypes.types.ATFile'
25
26import logging
27from urllib import quote
28
29from Products.CMFCore.permissions import View
30from Products.CMFCore.permissions import ModifyPortalContent
31from Products.CMFCore.utils import getToolByName
32from AccessControl import ClassSecurityInfo
33
34from Products.Archetypes.atapi import Schema
35from Products.Archetypes.atapi import FileField
36from Products.Archetypes.atapi import FileWidget
37from Products.Archetypes.atapi import PrimaryFieldMarshaller
38from Products.Archetypes.atapi import AnnotationStorage
39from Products.Archetypes.BaseContent import BaseContent
40from Products.PortalTransforms.utils import TransformException
41from Products.MimetypesRegistry.common import MimeTypeException
42
43from Products.ATContentTypes.config import PROJECTNAME
44from Products.ATContentTypes.configuration import zconf
45from Products.ATContentTypes.config import ICONMAP
46from Products.ATContentTypes.content.base import registerATCT
47from Products.ATContentTypes.content.base import ATCTFileContent
48from Products.ATContentTypes.interfaces import IATFile
49from Products.ATContentTypes.content.schemata import ATContentTypeSchema
50from Products.ATContentTypes.content.schemata import finalizeATCTSchema
51
52from Products.ATContentTypes import ATCTMessageFactory as _
53
54from Products.validation.validators.SupplValidators import MaxSizeValidator
55from Products.validation.config import validation
56from Products.validation import V_REQUIRED
57
58LOG = logging.getLogger('ATCT')
59
60validation.register(MaxSizeValidator('checkFileMaxSize',
61                                     maxsize=zconf.ATFile.max_file_size))
62
63ATFileSchema = ATContentTypeSchema.copy() + Schema((
64    FileField('file',
65              required=True,
66              primary=True,
67              searchable=True,
68              languageIndependent=True,
69              storage = AnnotationStorage(migrate=True),
70              validators = (('isNonEmptyFile', V_REQUIRED),
71                             ('checkFileMaxSize', V_REQUIRED)),
72                                       
73              widget = FileWidget(
74                        description = '',
75                        label=_(u'label_file', default=u'File'),
76                        show_content_type = False,)),
77    ), marshall=PrimaryFieldMarshaller()
78    )
79
80# Title is pulled from the file name if we don't specify anything,
81# so it's not strictly required, unlike in the rest of ATCT.
82ATFileSchema['title'].required = False
83
84finalizeATCTSchema(ATFileSchema)
85
86class ATFile(ATCTFileContent):
87    """An external file uploaded to the site."""
88
89    schema         =  ATFileSchema
90
91    portal_type    = 'File'
92    archetype_name = 'File'
93    _atct_newTypeFor = {'portal_type' : 'CMF File', 'meta_type' : 'Portal File'}
94    assocMimetypes = ('application/pdf', 'audio/mp3', 'video/flv', )
95    assocFileExt   = ('pdf' 'mp3' 'flv')
96    cmf_edit_kws   = ()
97    inlineMimetypes= ('application/msword',
98                      'application/x-msexcel', # ?
99                      'application/vnd.ms-excel',
100                      'application/vnd.ms-powerpoint',
101                      'application/pdf',
102                      'application/x-shockwave-flash')
103
104    __implements__ = ATCTFileContent.__implements__, IATFile
105
106    security       = ClassSecurityInfo()
107
108    security.declareProtected(View, 'index_html')
109    def index_html(self, REQUEST=None, RESPONSE=None):
110        """Download the file
111        """
112        field = self.getPrimaryField()
113
114        if field.getContentType(self) in self.inlineMimetypes:
115            # return the PDF and Office file formats inline
116            return ATCTFileContent.index_html(self, REQUEST, RESPONSE)
117        # otherwise return the content as an attachment
118        # Please note that text/* cannot be returned inline as
119        # this is a security risk (IE renders anything as HTML).
120        return field.download(self)
121
122    security.declareProtected(ModifyPortalContent, 'setFile')
123    def setFile(self, value, **kwargs):
124        """Set id to uploaded id
125        """
126        self._setATCTFileContent(value, **kwargs)
127
128    def __str__(self):
129        """cmf compatibility
130        """
131        return self.get_data()
132
133    security.declarePublic('getIcon')
134    def getIcon(self, relative_to_portal=0):
135        """Calculate the icon using the mime type of the file
136        """
137        field = self.getField('file')
138        if not field or not self.get_size():
139            # field is empty
140            return BaseContent.getIcon(self, relative_to_portal)
141
142        contenttype       = field.getContentType(self)
143        contenttype_major = contenttype and contenttype.split('/')[0] or ''
144
145        mtr   = getToolByName(self, 'mimetypes_registry', None)
146        utool = getToolByName( self, 'portal_url' )
147
148        if ICONMAP.has_key(contenttype):
149            icon = quote(ICONMAP[contenttype])
150        elif ICONMAP.has_key(contenttype_major):
151            icon = quote(ICONMAP[contenttype_major])
152        else:
153            mimetypeitem = None
154            try:
155                mimetypeitem = mtr.lookup(contenttype)
156            except MimeTypeException, msg:
157                LOG.error('MimeTypeException for %s. Error is: %s' % (self.absolute_url(), str(msg)))
158            if not mimetypeitem:
159                return BaseContent.getIcon(self, relative_to_portal)
160            icon = mimetypeitem[0].icon_path
161
162        if relative_to_portal:
163            return icon
164        else:
165            # Relative to REQUEST['BASEPATH1']
166            res = utool(relative=1) + '/' + icon
167            while res[:1] == '/':
168                res = res[1:]
169            return res
170
171    security.declareProtected(View, 'icon')
172    def icon(self):
173        """for ZMI
174        """
175        return self.getIcon()
176
177    security.declarePrivate('txng_get')
178    def txng_get(self, attr=('SearchableText',)):
179        """Special searchable text source for text index ng 2
180        """
181        if attr[0] != 'SearchableText':
182            # only a hook for searchable text
183            return
184
185        source   = ''
186        mimetype = 'text/plain'
187        encoding = 'utf-8'
188
189        # stage 1: get the searchable text and convert it to utf8
190        sp    = getToolByName(self, 'portal_properties').site_properties
191        stEnc = getattr(sp, 'default_charset', 'utf-8')
192        st    = self.SearchableText()
193        source+=unicode(st, stEnc).encode('utf-8')
194
195        # get the file and try to convert it to utf8 text
196        ptTool = getToolByName(self, 'portal_transforms')
197        f  = self.getFile()
198        if f:
199            mt = f.getContentType()
200            try:
201                result = ptTool.convertTo('text/plain', str(f), mimetype=mt)
202                if result:
203                    data = result.getData()
204                else:
205                    data = ''
206            except TransformException:
207                data = ''
208            source+=data
209
210        return source, mimetype, encoding
211
212    security.declarePrivate('cmf_edit')
213    def cmf_edit(self, precondition='', file=None):
214        if file is not None:
215            self.setFile(file)
216
217registerATCT(ATFile, PROJECTNAME)