Back to index

plone3  3.1.7
file.py
Go to the documentation of this file.
00001 #  ATContentTypes http://plone.org/products/atcontenttypes/
00002 #  Archetypes reimplementation of the CMF core types
00003 #  Copyright (c) 2003-2006 AT Content Types development team
00004 #
00005 #  This program is free software; you can redistribute it and/or modify
00006 #  it under the terms of the GNU General Public License as published by
00007 #  the Free Software Foundation; either version 2 of the License, or
00008 #  (at your option) any later version.
00009 #
00010 #  This program is distributed in the hope that it will be useful,
00011 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 #  GNU General Public License for more details.
00014 #
00015 #  You should have received a copy of the GNU General Public License
00016 #  along with this program; if not, write to the Free Software
00017 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 #
00019 """
00020 
00021 """
00022 __author__  = 'Christian Heimes <tiran@cheimes.de>'
00023 __docformat__ = 'restructuredtext'
00024 __old_name__ = 'Products.ATContentTypes.types.ATFile'
00025 
00026 import logging
00027 from urllib import quote
00028 
00029 from Products.CMFCore.permissions import View
00030 from Products.CMFCore.permissions import ModifyPortalContent
00031 from Products.CMFCore.utils import getToolByName
00032 from AccessControl import ClassSecurityInfo
00033 
00034 from Products.Archetypes.atapi import Schema
00035 from Products.Archetypes.atapi import FileField
00036 from Products.Archetypes.atapi import FileWidget
00037 from Products.Archetypes.atapi import PrimaryFieldMarshaller
00038 from Products.Archetypes.atapi import AnnotationStorage
00039 from Products.Archetypes.BaseContent import BaseContent
00040 from Products.PortalTransforms.utils import TransformException
00041 from Products.MimetypesRegistry.common import MimeTypeException
00042 
00043 from Products.ATContentTypes.config import PROJECTNAME
00044 from Products.ATContentTypes.configuration import zconf
00045 from Products.ATContentTypes.config import ICONMAP
00046 from Products.ATContentTypes.content.base import registerATCT
00047 from Products.ATContentTypes.content.base import ATCTFileContent
00048 from Products.ATContentTypes.interfaces import IATFile
00049 from Products.ATContentTypes.content.schemata import ATContentTypeSchema
00050 from Products.ATContentTypes.content.schemata import finalizeATCTSchema
00051 
00052 from Products.ATContentTypes import ATCTMessageFactory as _
00053 
00054 from Products.validation.validators.SupplValidators import MaxSizeValidator
00055 from Products.validation.config import validation
00056 from Products.validation import V_REQUIRED
00057 
00058 LOG = logging.getLogger('ATCT')
00059 
00060 validation.register(MaxSizeValidator('checkFileMaxSize',
00061                                      maxsize=zconf.ATFile.max_file_size))
00062 
00063 ATFileSchema = ATContentTypeSchema.copy() + Schema((
00064     FileField('file',
00065               required=True,
00066               primary=True,
00067               searchable=True,
00068               languageIndependent=True,
00069               storage = AnnotationStorage(migrate=True),
00070               validators = (('isNonEmptyFile', V_REQUIRED),
00071                              ('checkFileMaxSize', V_REQUIRED)),
00072               widget = FileWidget(
00073                         description = '',
00074                         label=_(u'label_file', default=u'File'),
00075                         show_content_type = False,)),
00076     ), marshall=PrimaryFieldMarshaller()
00077     )
00078 
00079 # Title is pulled from the file name if we don't specify anything,
00080 # so it's not strictly required, unlike in the rest of ATCT.
00081 ATFileSchema['title'].required = False
00082 
00083 finalizeATCTSchema(ATFileSchema)
00084 
00085 class ATFile(ATCTFileContent):
00086     """An external file uploaded to the site."""
00087 
00088     schema         =  ATFileSchema
00089 
00090     portal_type    = 'File'
00091     archetype_name = 'File'
00092     _atct_newTypeFor = {'portal_type' : 'CMF File', 'meta_type' : 'Portal File'}
00093     assocMimetypes = ('application/*', 'audio/*', 'video/*', )
00094     assocFileExt   = ()
00095     cmf_edit_kws   = ()
00096     inlineMimetypes= ('application/msword',
00097                       'application/x-msexcel', # ?
00098                       'application/vnd.ms-excel',
00099                       'application/vnd.ms-powerpoint',
00100                       'application/pdf')
00101 
00102     __implements__ = ATCTFileContent.__implements__, IATFile
00103 
00104     security       = ClassSecurityInfo()
00105 
00106     security.declareProtected(View, 'index_html')
00107     def index_html(self, REQUEST=None, RESPONSE=None):
00108         """Download the file
00109         """
00110         field = self.getPrimaryField()
00111 
00112         if field.getContentType(self) in self.inlineMimetypes:
00113             # return the PDF and Office file formats inline
00114             return ATCTFileContent.index_html(self, REQUEST, RESPONSE)
00115         # otherwise return the content as an attachment 
00116         # Please note that text/* cannot be returned inline as
00117         # this is a security risk (IE renders anything as HTML).
00118         return field.download(self)
00119 
00120     security.declareProtected(ModifyPortalContent, 'setFile')
00121     def setFile(self, value, **kwargs):
00122         """Set id to uploaded id
00123         """
00124         self._setATCTFileContent(value, **kwargs)
00125 
00126     def __str__(self):
00127         """cmf compatibility
00128         """
00129         return self.get_data()
00130 
00131     security.declarePublic('getIcon')
00132     def getIcon(self, relative_to_portal=0):
00133         """Calculate the icon using the mime type of the file
00134         """
00135         field = self.getField('file')
00136         if not field or not self.get_size():
00137             # field is empty
00138             return BaseContent.getIcon(self, relative_to_portal)
00139 
00140         contenttype       = field.getContentType(self)
00141         contenttype_major = contenttype and contenttype.split('/')[0] or ''
00142 
00143         mtr   = getToolByName(self, 'mimetypes_registry', None)
00144         utool = getToolByName( self, 'portal_url' )
00145 
00146         if ICONMAP.has_key(contenttype):
00147             icon = quote(ICONMAP[contenttype])
00148         elif ICONMAP.has_key(contenttype_major):
00149             icon = quote(ICONMAP[contenttype_major])
00150         else:
00151             mimetypeitem = None
00152             try:
00153                 mimetypeitem = mtr.lookup(contenttype)
00154             except MimeTypeException, msg:
00155                 LOG.error('MimeTypeException for %s. Error is: %s' % (self.absolute_url(), str(msg)))
00156             if not mimetypeitem:
00157                 return BaseContent.getIcon(self, relative_to_portal)
00158             icon = mimetypeitem[0].icon_path
00159 
00160         if relative_to_portal:
00161             return icon
00162         else:
00163             # Relative to REQUEST['BASEPATH1']
00164             res = utool(relative=1) + '/' + icon
00165             while res[:1] == '/':
00166                 res = res[1:]
00167             return res
00168 
00169     security.declareProtected(View, 'icon')
00170     def icon(self):
00171         """for ZMI
00172         """
00173         return self.getIcon()
00174 
00175     security.declarePrivate('txng_get')
00176     def txng_get(self, attr=('SearchableText',)):
00177         """Special searchable text source for text index ng 2
00178         """
00179         if attr[0] != 'SearchableText':
00180             # only a hook for searchable text
00181             return
00182 
00183         source   = ''
00184         mimetype = 'text/plain'
00185         encoding = 'utf-8'
00186 
00187         # stage 1: get the searchable text and convert it to utf8
00188         sp    = getToolByName(self, 'portal_properties').site_properties
00189         stEnc = getattr(sp, 'default_charset', 'utf-8')
00190         st    = self.SearchableText()
00191         source+=unicode(st, stEnc).encode('utf-8')
00192 
00193         # get the file and try to convert it to utf8 text
00194         ptTool = getToolByName(self, 'portal_transforms')
00195         f  = self.getFile()
00196         if f:
00197             mt = f.getContentType()
00198             try:
00199                 result = ptTool.convertTo('text/plain', str(f), mimetype=mt)
00200                 if result:
00201                     data = result.getData()
00202                 else:
00203                     data = ''
00204             except TransformException:
00205                 data = ''
00206             source+=data
00207 
00208         return source, mimetype, encoding
00209 
00210     security.declarePrivate('cmf_edit')
00211     def cmf_edit(self, precondition='', file=None):
00212         if file is not None:
00213             self.setFile(file)
00214 
00215 registerATCT(ATFile, PROJECTNAME)