Commit 5c7d50d5 authored by Julien Muchembled's avatar Julien Muchembled

Fix webdav support when used to upload embedded files

Also cleanup and optimize PUT & ContributionTool

This reverts commit eaf12293.
parent 03f09669
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>Document_setFilenameAndContentType</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Document_PUT</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>PUT</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>document = state_change[\'object\']\n
portal = document.getPortalObject()\n
\n
filename = document.getId()\n
document.setFilename(filename)\n
content_type = portal.mimetypes_registry.lookupExtension(filename)\n
\n
if content_type is not None:\n
document.setContentType(str(content_type))\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>state_change</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Document_setFilenameAndContentType</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
990
\ No newline at end of file
991
\ No newline at end of file
......@@ -151,7 +151,6 @@ class ContributionTool(BaseTool):
kw['filename'] = kw['file_name']
del(kw['file_name'])
filename = kw.get('filename', None)
portal_type = kw.get('portal_type')
temp_object = kw.get('temp_object', False)
document = None
......@@ -161,42 +160,55 @@ class ContributionTool(BaseTool):
# Container may disappear, be smoother by passing default value
container = portal.restrictedTraverse(container_path, None)
# Try to find the filename
content_type = None
if not url:
# check if file was provided
file_object = kw.get('file')
if file_object is not None:
if not filename:
filename = file_object.filename
filename = getattr(file_object, 'filename', None)
else:
# some channels supply data and file-name separately
# this is the case for example for email ingestion
# in this case, we build a file wrapper for it
data = kw.get('data')
if data is not None and filename:
try:
data = kw.pop('data')
except KeyError:
raise ValueError('data must be provided')
if data is not None:
file_object = cStringIO.StringIO()
file_object.write(data)
file_object.seek(0)
kw['file'] = file_object
del kw['data']
else:
raise TypeError, 'data and filename must be provided'
content_type = kw.pop('content_type', None)
else:
file_object, filename, content_type = self._openURL(url)
if content_type:
kw['content_type'] = content_type
content_type = kw.pop('content_type', None) or content_type
kw['file'] = file_object
if not filename:
raise ValueError('filename must be provided')
if not content_type:
# fallback to a default content_type according provided
# filename
content_type = self.guessMimeTypeFromFilename(filename)
if content_type:
kw['content_type'] = content_type
if portal_type and container is not None:
portal_type = kw.pop('portal_type', None)
if not portal_type:
if container is None or container.isModuleType():
# Guess it with help of portal_contribution_registry
portal_type = portal.portal_contribution_registry.findPortalTypeName(
filename=filename, content_type=content_type)
else:
portal_type = 'Embedded File'
if container is not None:
# Simplify things here and return a document immediately
# XXX Nicolas: This will break support of WebDAV
# if _setObject is not called
document = container.newContent(id=document_id, **kw)
document = container.newContent(document_id, portal_type, **kw)
if discover_metadata:
document.activate(after_path_and_method_id=(document.getPath(),
('convertToBaseFormat', 'Document_tryToConvertToBaseFormat')))\
......@@ -206,24 +218,14 @@ class ContributionTool(BaseTool):
return document
# If the portal_type was provided, we can go faster
if portal_type and container is None:
if portal_type:
# We know the portal_type, let us find the default module
# and use it as container
try:
container = portal.getDefaultModule(portal_type)
except ValueError:
container = None
# From here, there is no hope unless a file was provided
if file_object is None:
raise ValueError, "No data provided"
pass
if portal_type is None:
# Guess it with help of portal_contribution_registry
registry = portal.portal_contribution_registry
portal_type = registry.findPortalTypeName(filename=filename,
content_type=content_type)
#
# Check if same file is already exists. if it exists, then update it.
#
......@@ -247,12 +249,9 @@ class ContributionTool(BaseTool):
# Temp objects use the standard newContent from Folder
if temp_object:
# For temp_object creation, use the standard method
kw['portal_type'] = portal_type
return BaseTool.newContent(self, **kw)
return BaseTool.newContent(self, portal_type=portal_type, **kw)
# Then put the file inside ourselves for a short while
if container_path is not None:
container = self.getPortalObject().restrictedTraverse(container_path)
document = self._setObject(document_id, None, portal_type=portal_type,
user_login=user_login, container=container,
discover_metadata=discover_metadata,
......@@ -270,7 +269,7 @@ class ContributionTool(BaseTool):
# Allow reindexing, reindex it and return the document
try:
delattr(document, 'isIndexable')
del document.isIndexable
except AttributeError:
# Document does not have such attribute
pass
......
......@@ -44,7 +44,6 @@ from Products.ERP5Type.CopySupport import CopyContainer
from Products.ERP5Type import PropertySheet
from Products.ERP5Type.XMLExportImport import Folder_asXML
from Products.ERP5Type.Utils import sortValueList
from Products.ERP5Type.WebDAVSupport import Folder as WebDAVFolder
from Products.ERP5Type import Permissions
try:
......@@ -454,7 +453,7 @@ BTREE_HANDLER = 1
HBTREE_HANDLER = 2
class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn, WebDAVFolder):
class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
"""
A Folder is a subclass of Base but not of XMLObject.
Folders are not considered as documents and are therefore
......@@ -518,7 +517,7 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn,
Title = Base.Title
_setPropValue = Base._setPropValue
_propertyMap = Base._propertyMap # are there any others XXX ?
PUT_factory = WebDAVFolder.PUT_factory
PUT_factory = None
# XXX Prevent inheritance from PortalFolderBase
description = None
......
......@@ -200,36 +200,48 @@ class TextContent:
""" Used for FTP and apparently the ZMI now too """
return len(self.manage_FTPget())
class Folder:
"""
Taken from CMFCore.PortalFolder
from webdav.common import Locked, PreconditionFailed
from webdav.interfaces import IWriteLock
from webdav.NullResource import NullResource
from zope.contenttype import guess_content_type
NullResource_PUT = NullResource.PUT
def PUT(self, REQUEST, RESPONSE):
"""Create a new non-collection resource.
"""
def PUT_factory( self, name, typ, body ):
""" Factory for PUT requests to objects which do not yet exist.
if getattr(self.__parent__, 'PUT_factory', None) is not None: # BBB
return NullResource_PUT(self, REQUEST, RESPONSE)
Used by NullResource.PUT.
self.dav__init(REQUEST, RESPONSE)
Returns -- Bare and empty object of the appropriate type (or None, if
we don't know what to do)
"""
portal = self.getPortalObject()
registry = portal.portal_contribution_registry
portal_type = registry.findPortalTypeName(filename=name,
content_type=typ)
if portal_type is None:
return None
# The code bellow is inspired from ERP5Type.Core.Folder.newContent
pt = self._getTypesTool()
myType = pt.getTypeInfo(self)
if myType is not None and not myType.allowType( portal_type ) and \
'portal_contributions' not in self.getPhysicalPath():
raise ValueError('Disallowed subobject type: %s' % portal_type)
container = portal.getDefaultModule(portal_type)
pt.constructContent(type_name=portal_type,
container=container,
id=name)
document = container._getOb(name)
return document
name = self.__name__
parent = self.__parent__
ifhdr = REQUEST.get_header('If', '')
if IWriteLock.providedBy(parent) and parent.wl_isLocked():
if ifhdr:
parent.dav__simpleifhandler(REQUEST, RESPONSE, col=1)
else:
# There was no If header at all, and our parent is locked,
# so we fail here
raise Locked
elif ifhdr:
# There was an If header, but the parent is not locked
raise PreconditionFailed
# <ERP5>
# XXX: Do we really want to force 'id'
# when PUT is called on Contribution Tool ?
kw = {'id': name, 'data': None, 'filename': name}
contribution_tool = parent.getPortalObject().portal_contributions
if aq_base(contribution_tool) is not aq_base(parent):
kw.update(container=parent, discover_metadata=False)
ob = contribution_tool.newContent(**kw)
# </ERP5>
ob.PUT(REQUEST, RESPONSE)
RESPONSE.setStatus(201)
RESPONSE.setBody('')
return RESPONSE
NullResource.PUT = PUT
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment