This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/web/UploadFilesWeb.py

407 lines
14 KiB
Python

# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
__doc__ = """Glasnost Upload Files Web"""
__version__ = '$Revision$'[11:-2]
import cStringIO
import copy
import zipfile
# From Python Imaging Library.
import Image as PILImage
import glasnost.common.context as context
import glasnost.common.faults as faults
import glasnost.common.slots as slots
from glasnost.proxy.UploadFilesProxy import *
from ObjectsWeb import register, AdminMixin, ObjectWebMixin, ObjectsWebMixin
from tools import *
class AdminUploadFiles(AdminMixin, AdminUploadFiles):
pass
register(AdminUploadFiles)
class UploadFile(ObjectWebMixin, UploadFile):
comment_kind_widget_fieldLabel = N_('Comment')
comment_kind_widget_cols = 40
comment_kind_widget_rows = 5
comment_kind_widgetName = 'TextArea'
data_kindName = 'UploadFile'
data_kind_widget_fieldLabel = N_('File')
data_kind_widget_fileName = None
data_kind_widgetName = 'UploadFile'
dataFileName_kind_stateInEditMode = 'read-only'
dataFileName_kind_widget_fieldLabel = N_('File Name')
dataFileName_kind_widget_size = 40
dataFileName_kind_widgetName = 'InputText'
dataType_kind_stateInEditMode = 'read-only'
dataType_kind_widget_fieldLabel = N_('Mime Type')
dataType_kind_widgetName = 'InputText'
height_kind_hasToRepairField = 0
height_kind_hasToSubmitField = 0
height_kind_stateInEditMode = 'read-only'
height_kind_min = 0
height_kind_textMaxLength = 4
height_kind_widget_fieldLabel = N_('Height')
height_kind_widget_size = 4
height_kind_widgetName = 'InputText'
size_kind_hasToSubmitField = 0
size_kind_stateInEditMode = 'read-only'
size_kind_min = 0
size_kind_textMaxLength = 6
size_kind_widget_fieldLabel = N_('Size')
size_kind_widget_size = 6
size_kind_widgetName = 'InputText'
title_kind_widget_fieldLabel = N_('Title')
title_kind_widget_size = 40
title_kind_widgetName = 'InputText'
width_kind_hasToRepairField = 0
width_kind_hasToSubmitField = 0
width_kind_stateInEditMode = 'read-only'
width_kind_min = 0
width_kind_textMaxLength = 4
width_kind_widget_fieldLabel = N_('Width')
width_kind_widget_size = 4
width_kind_widgetName = 'InputText'
def getEditLayoutSlotNames(self, fields, parentSlot = None):
slotNames = ObjectWebMixin.getViewLayoutSlotNames(
self, fields, parentSlot = parentSlot)
slotNames = slotNames[:]
hiddenSlotNames = []
for slotName in ('height', 'size', 'width'):
hiddenSlotNames.append(slotName)
if self.id is None:
for slotName in ('creationTime', 'dataFileName', 'dataType',
'modificationTime'):
hiddenSlotNames.append(slotName)
for slotName in hiddenSlotNames:
if slotName in slotNames:
slotNames.remove(slotName)
return slotNames
def getViewLayoutSlotNames(self, fields, parentSlot = None):
slotNames = ObjectWebMixin.getViewLayoutSlotNames(
self, fields, parentSlot = parentSlot)
slotNames = slotNames[:]
dataType = self.getSlot('dataType').getValue()
if not isTypeOfMimeType(dataType, 'image'):
if 'height' in slotNames:
slotNames.remove('height')
if 'width' in slotNames:
slotNames.remove('width')
userToken = context.getVar('userToken', default = '')
if not userToken or context.getVar('useCompactLayout', default = 0):
for slotName in [
'creationTime', 'dataFileName', 'dataType', 'height',
'size', 'modificationTime', 'readersSet', 'width',
'writersSet']:
if slotName in slotNames:
slotNames.remove(slotName)
return slotNames
def getViewLayout(self, fields, parentSlot = None):
if self.dataFileName:
slot = self.getSlot('data', parentSlot = parentSlot)
self.data_kind = copy.copy(self.data_kind) # Deleted below.
self.data_kind.widget = copy.copy(slot.getWidget())
self.data_kind.widget.fileName = self.dataFileName
layout = X.array()
if self.dataType == 'application/vnd.sun.xml.writer':
try:
import ooo
css, body = ooo.oo2html(self.data,
X.idUrl(self.id, 'zip').getAsUrl())
webTools.addContextualHeader(
'<style type="text/css">\n%s</style>\n' % css)
layout += X.asIs(body)
except ImportError:
pass
layout += ObjectWebMixin.getViewLayout(
self, fields, parentSlot = parentSlot)
if self.dataFileName:
del self.data_kind
return layout
def submitFields(self, fields, parentSlot = None):
ObjectWebMixin.submitFields(self, fields, parentSlot = parentSlot)
upload = context.getVar('UploadFilesXXX')
if upload:
self.dataFileName = upload.dataFileName
self.dataType = upload.dataType
register(UploadFile)
class UploadFilesWeb(ObjectsWebMixin, UploadFilesProxy):
def all(self):
return ObjectsWebMixin.viewAll(self)
all.isPublicForWeb = 1
#uploadFileFile = cStringIO.StringIO(data)
#uploadFileObject = PILImage.open(uploadFileFile)
#width, height = uploadFileObject.size
def image(self, id, fileName = None):
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
object = self.getPartialObject(
id, ['modificationTime', 'dataFileName'])
rememberObject(id)
if fileName and object.dataFileName != fileName:
pageNotFound()
if not fileName and object.dataFileName:
uri = X.idUrl(id, 'download/%s' % object.dataFileName)
return redirect(uri)
req = context.getVar('req')
req.depends.append(id)
object = self.getObject(id)
if object.dataFileName:
req.headers_out['Content-Disposition'] = \
'inline; filename="%s"' % object.dataFileName
req.headers_out['Content-Length'] = str(object.size or 0)
if object.dataType:
req.content_type = object.dataType
setHttpCookie()
req.send_http_header()
if req.method == 'HEAD':
return OK
if req.caching:
req.openCachePage()
req.write(object.data or '')
if req.caching:
req.closeCachePage()
return OK
image.isPublicForWeb = 1
download = image
download.isPublicForWeb = 1
def file(self, id):
try:
object = self.getObject(id)
except faults.FaultMissingItem:
return pageNotFound()
if not self.canModifyObject(id):
return accessForbidden()
req = context.getVar('req')
object.data = req.read()
if req.headers_in.has_key('Content-Type'):
object.dataType = req.headers_in['Content-Type']
else:
object.dataType = 'application/octet-stream'
self.modifyObject(object)
return HTTP_NO_CONTENT
file.isPublicForWeb = ('PUT',)
def imageEdit(self, dataToken, path = ''):
sessionsProxy = getProxyForServerRole('sessions')
data = sessionsProxy.getTemporaryData(dataToken)
req = context.getVar('req')
req.content_type = data['type']
setHttpCookie()
req.send_http_header()
if req.method == 'HEAD':
return OK
req.write(data['data'])
return OK
imageEdit.isPublicForWeb = 1
def thumbnail(self, id, width = '', height = ''):
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
try:
width = int(width)
except ValueError:
width = 128
try:
height = int(height)
except ValueError:
height = 128
object = self.getObjectThumbnail(
id, width, height)
rememberObject(id)
req = context.getVar('req')
req.content_type = object.dataType
setHttpCookie()
req.send_http_header()
if req.method == 'HEAD':
return OK
req.write(object.data)
return OK
thumbnail.isPublicForWeb = 1
def view(self, id):
if not self.hasObject(id):
return pageNotFound()
if not self.canGetObject(id):
return accessForbidden()
object = UploadFile()
slotNames = [x for x in object.getSlotNames() if x != 'data']
object = self.getPartialObject(id, slotNames)
# Force the presence of the download link in
# web/widgets.py/UploadFile.getHtmlViewValue().
# note that it fucks up previewing inline OpenOffice.org documents
# that could be converted to html
object.data = 'fake data'
if object.dataType == 'application/vnd.sun.xml.writer':
object = self.getObject(id)
rememberObject(id)
if isTypeOfMimeType(object.dataType, 'image'):
fullUri = X.idUrl(id, 'image')
else:
fullUri = X.idUrl(id, 'download')
uri = X.idUrl(id, 'thumbnail')
uri.add('width', 256)
uri.add('height', 256)
label = object.getLabelTranslated(context.getVar('readLanguages'))
layout = X.array()
slot = slots.Root(object)
widget = slot.getWidget()
layout += widget.getModelPageBodyLayout(slot, None)
layout += self.getViewAboveButtonsBarLayout(object, None)
layout += self.getViewButtonsBarLayout(object, None)
layout += self.getViewBelowButtonsBarLayout(object, None)
return writePageLayout(
layout, '%s - %s' % (_(self.objectNameCapitalized), label))
view.isPublicForWeb = 1
def viewAll(self):
context.push(_level = 'viewAll',
defaultDispatcherId = context.getVar('dispatcherId'))
try:
userId = context.getVar('userId', default = '')
if not self.canGetObjects():
return accessForbidden()
isAdmin = self.isAdmin()
if userId:
userSet = [userId]
else:
userSet = None
layout = X.array()
requiredSlotNames = ['dataType', 'size', 'title']
displayedSlotNames = ['dataType', 'size']
if userSet:
lastUploadFiles = self.getLastObjects(
10, None, userSet, requiredSlotNames)
layout += self.getObjectsSectionLayout(
lastUploadFiles,
_("""Your last files"""),
displayedSlotNames)
lastUploadFiles = self.getLastObjects(
10, userSet, None, requiredSlotNames)
layout += self.getObjectsSectionLayout(
lastUploadFiles,
_("""The last files"""),
displayedSlotNames)
layout += self.getViewAllButtonsBarLayout()
finally:
context.pull(_level = 'viewAll')
return writePageLayout(layout, _('Files'))
viewAll.isPublicForWeb = 1
def zip(self, id, *filepath):
filepath = '/'.join(filepath)
object = self.getObject(id)
fd = cStringIO.StringIO(object.data)
zf = zipfile.ZipFile(fd)
data = zf.read(filepath)
req = context.getVar('req')
# TODO: function that gets contentType from extension (or better)
if filepath.endswith('.jpg'):
req.content_type = 'image/jpeg'
else:
req.content_type = 'application/octet-stream'
req.depends.append(id)
object = self.getObject(id)
if object.dataFileName:
req.headers_out['Content-Disposition'] = \
'inline; filename="%s"' % filepath.split('/')[-1]
req.headers_out['Content-Length'] = str(len(data))
setHttpCookie()
req.send_http_header()
if req.method == 'HEAD':
return OK
if req.caching:
req.openCachePage()
req.write(data)
if req.caching:
req.closeCachePage()
return OK
pass
zip.isPublicForWeb = 1