diff --git a/addons/caldav/caldav.py b/addons/caldav/caldav.py
index 3aa5dfd14dc..2517f88f789 100644
--- a/addons/caldav/caldav.py
+++ b/addons/caldav/caldav.py
@@ -20,26 +20,8 @@
##############################################################################
from document_webdav import webdav
-import tools
-from DAV.propfind import PROPFIND
import urlparse
urlparse.uses_netloc.append('caldav')
urlparse.uses_netloc.append('caldavs')
-super_mk_prop_response = webdav.mk_prop_response
-def mk_prop_response(self,uri,good_props,bad_props,doc):
- res = super_mk_prop_response(self, uri,good_props,bad_props,doc)
- uris = uri.split('/')
- calendar = False
- if 'http://calendarserver.org/ns/' in good_props or 'http://calendarserver.org/ns/' in bad_props:
- calendar = True
- if calendar:
- ad = doc.createElement('calendar')
- ad.setAttribute('xmlns', 'urn:ietf:params:xml:ns:caldav')
- cols = res.getElementsByTagName('D:collection')
- if cols:
- cols[0].parentNode.appendChild(ad)
- #cols[0].parentNode.appendChild(vc)
- return res
-
-PROPFIND.mk_prop_response = mk_prop_response
+#EOF
diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py
index 3ae37ea3e7e..b931b0f0328 100644
--- a/addons/caldav/caldav_node.py
+++ b/addons/caldav/caldav_node.py
@@ -133,25 +133,10 @@ class node_calendar(nodes.node_class):
result = self._get_ttag(cr) + ':' + str(time.time())
return str(result)
- def _get_gdav_resourcetype(self, cr):
- return (str(self.cal_type + '-collection'), 'http://groupdav.org/')
-
- def removeme_match_dav_eprop(self, cr, match, ns, prop):
- # Why?
- if ns == "DAV:" and prop == "getetag":
- dirobj = self.context._dirobj
- uid = self.context.uid
- ctx = self.context.context.copy()
- tem, dav_time = tuple(match.split(':'))
- model, res_id = tuple(tem.split('_'))
- model_obj = dirobj.pool.get(model)
- model = model_obj.browse(cr, uid, res_id, context=ctx)
- write_time = model.write_date or model.create_date
- wtime = time.mktime(time.strptime(write_time,'%Y-%m-%d %H:%M:%S'))
- if float(dav_time) == float(wtime):
- return True
- return False
- res = super(node_calendar, self).match_dav_eprop(cr, match, ns, prop)
+ def get_dav_resourcetype(self, cr):
+ res = [ ('collection', 'DAV:'),
+ (str(self.cal_type + '-collection'), 'http://groupdav.org/'),
+ ('calendar', 'urn:ietf:params:xml:ns:caldav') ]
return res
def get_domain(self, cr, filters):
diff --git a/addons/document/nodes.py b/addons/document/nodes.py
index de2a83285f9..228f104574d 100644
--- a/addons/document/nodes.py
+++ b/addons/document/nodes.py
@@ -314,6 +314,14 @@ class node_class(object):
logger.debug('Property %s not supported' % prop, exc_info=True)
return None
+ def get_dav_resourcetype(self, cr):
+ """ Get the DAV resource type.
+
+ Is here because some nodes may exhibit special behaviour, like
+ CalDAV/GroupDAV collections
+ """
+ raise NotImplementedError
+
def move_to(self, cr, ndir_node, new_name=False, fil_obj=None, ndir_obj=None, in_write=False):
""" Move this node to a new parent directory.
@param ndir_node the collection that this node should be moved under
@@ -456,6 +464,9 @@ class node_database(node_class):
def _get_ttag(self,cr):
return 'db-%s' % cr.dbname
+ def get_dav_resourcetype(self, cr):
+ return ('collection', 'DAV:')
+
def mkdosname(company_name, default='noname'):
""" convert a string to a dos-like name"""
if not company_name:
@@ -778,6 +789,9 @@ class node_res_dir(node_class):
def _get_ttag(self,cr):
return 'rdir-%d' % self.dir_id
+ def get_dav_resourcetype(self, cr):
+ return ('collection', 'DAV:')
+
class node_res_obj(node_class):
""" A special sibling to node_dir, which does only contain dynamically
created folders foreach resource in the foreign model.
@@ -1034,6 +1048,9 @@ class node_res_obj(node_class):
def _get_ttag(self,cr):
return 'rodir-%d-%d' % (self.dir_id, self.res_id)
+ def get_dav_resourcetype(self, cr):
+ return ('collection', 'DAV:')
+
class node_file(node_class):
our_type = 'file'
def __init__(self, path, parent, context, fil):
@@ -1168,6 +1185,9 @@ class node_file(node_class):
def _get_ttag(self,cr):
return 'file-%d' % self.file_id
+ def get_dav_resourcetype(self, cr):
+ return ''
+
def move_to(self, cr, ndir_node, new_name=False, fil_obj=None, ndir_obj=None, in_write=False):
if ndir_node.context != self.context:
raise NotImplementedError("Cannot move files between contexts")
@@ -1313,6 +1333,8 @@ class node_content(node_class):
def _get_ttag(self,cr):
return 'cnt-%d%s' % (self.cnt_id,(self.act_id and ('-' + str(self.act_id))) or '')
+ def get_dav_resourcetype(self, cr):
+ return ''
class nodefd_content(StringIO, node_descriptor):
""" A descriptor to content nodes
diff --git a/addons/document_webdav/dav_fs.py b/addons/document_webdav/dav_fs.py
index 78812ff8cf5..af8738ef0da 100644
--- a/addons/document_webdav/dav_fs.py
+++ b/addons/document_webdav/dav_fs.py
@@ -370,19 +370,22 @@ class openerp_dav_handler(dav_interface):
if cr: cr.close()
@memoize(CACHE_SIZE)
- def _get_dav_resourcetype(self,uri):
+ def _get_dav_resourcetype(self, uri):
""" return type of object """
self.parent.log_message('get RT: %s' % uri)
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
return COLLECTION
- node = self.uri2object(cr,uid,pool, uri2)
+ node = self.uri2object(cr, uid, pool, uri2)
if not node:
raise DAV_NotFound2(uri2)
- if node.type in ('collection','database'):
- return COLLECTION
- return OBJECT
+ try:
+ return node.get_dav_resourcetype(cr)
+ except NotImplementedError:
+ if node.type in ('collection','database'):
+ return ('collection', 'DAV:')
+ return ''
finally:
if cr: cr.close()
@@ -739,6 +742,17 @@ class openerp_dav_handler(dav_interface):
@memoize(CACHE_SIZE)
def is_collection(self, uri):
""" test if the given uri is a collection """
- return self._get_dav_resourcetype(uri)==COLLECTION
+ cr, uid, pool, dbname, uri2 = self.get_cr(uri)
+ try:
+ if not dbname:
+ return True
+ node = self.uri2object(cr,uid,pool, uri2)
+ if not node:
+ raise DAV_NotFound2(uri2)
+ if node.type in ('collection','database'):
+ return True
+ return False
+ finally:
+ if cr: cr.close()
#eof
diff --git a/addons/document_webdav/webdav.py b/addons/document_webdav/webdav.py
index 1502ff204f8..1fd530cbdca 100644
--- a/addons/document_webdav/webdav.py
+++ b/addons/document_webdav/webdav.py
@@ -48,6 +48,70 @@ def mk_prop_response(self, uri, good_props, bad_props, doc):
re.setAttribute("xmlns:ns"+str(nsnum),nsname)
nsnum=nsnum+1
+ def _prop_child(xnode, ns, prop, value):
+ """Append a property xml node to xnode, with value
+
+ And a little smarter than that, it will consider namespace and
+ also allow nested properties etc.
+
+ :param ns the namespace of the node
+ :param prop the name of the property
+ :param value the value. Can be:
+ string: text node
+ tuple ('elem', 'ns') for empty sub-node
+ tuple ('elem', 'ns', sub-elems) for sub-node with elements
+ list, of above tuples
+ """
+ if ns == 'DAV:':
+ ns_prefix = 'D:'
+ else:
+ ns_prefix="ns"+str(namespaces.index(ns))+":"
+
+ pe=doc.createElement(ns_prefix+str(prop))
+ if hasattr(value, '__class__') and value.__class__.__name__ == 'Element':
+ pe.appendChild(value)
+ else:
+ if ns == 'DAV:' and prop=="resourcetype" and isinstance(value, int):
+ # hack, to go..
+ if value == 1:
+ ve=doc.createElement("D:collection")
+ pe.appendChild(ve)
+ else:
+ _prop_elem_child(pe, ns, value, ns_prefix)
+
+ xnode.appendChild(pe)
+
+ def _prop_elem_child(pnode, pns, v, pns_prefix):
+
+ if isinstance(v, list):
+ for vit in v:
+ _prop_elem_child(pnode, pns, vit, pns_prefix)
+ elif isinstance(v,tuple):
+ need_ns = False
+ if v[1] == pns:
+ ns_prefix = pns_prefix
+ elif v[1] == 'DAV:':
+ ns_prefix = 'D:'
+ elif v[1] in namespaces:
+ ns_prefix="ns"+str(namespaces.index(v[1]))+":"
+ else:
+ # namespaces.append(v[1])
+ # nsnum += 1
+ ns_prefix="ns"+str(nsnum)+":"
+ need_ns = True
+
+ ve=doc.createElement(ns_prefix+v[0])
+ if need_ns:
+ ve.setAttribute("xmlns:ns"+str(nsnum), v[1])
+ if len(v) > 2 and isinstance(v[2], list):
+ # support nested elements like:
+ # ( 'elem', 'ns:', [('sub-elem1', 'ns1'), ...]
+ _prop_elem_child(ve, v[1], v[2], ns_prefix)
+ pnode.appendChild(ve)
+ else:
+ ve=doc.createTextNode(tools.ustr(v))
+ pnode.appendChild(ve)
+
# write href information
uparts=urlparse.urlparse(uri)
fileloc=uparts[2]
@@ -74,22 +138,7 @@ def mk_prop_response(self, uri, good_props, bad_props, doc):
for p,v in good_props[ns].items():
if not v:
continue
- pe=doc.createElement(ns_prefix+str(p))
- if hasattr(v, '__class__') and v.__class__.__name__ == 'Element':
- pe.appendChild(v)
- else:
- if ns == 'DAV:' and p=="resourcetype":
- if v == 1:
- ve=doc.createElement("D:collection")
- pe.appendChild(ve)
- elif isinstance(v,tuple) and v[1] == ns:
- ve=doc.createElement(ns_prefix+v[0])
- pe.appendChild(ve)
- else:
- ve=doc.createTextNode(tools.ustr(v))
- pe.appendChild(ve)
-
- gp.appendChild(pe)
+ _prop_child(gp, ns, p, v)
ps.appendChild(gp)
s=doc.createElement("D:status")
diff --git a/addons/document_webdav/webdav_server.py b/addons/document_webdav/webdav_server.py
index 0f306a70612..34c255a2b3e 100644
--- a/addons/document_webdav/webdav_server.py
+++ b/addons/document_webdav/webdav_server.py
@@ -131,6 +131,22 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
self.close_connection = 1
DAVRequestHandler.send_header(self, key, value)
+ def send_body(self, DATA, code = None, msg = None, desc = None, ctype='application/octet-stream', headers=None):
+ if headers and 'Connection' in headers:
+ pass
+ elif self.request_version in ('HTTP/1.0', 'HTTP/0.9'):
+ pass
+ elif self.close_connection == 1: # close header already sent
+ pass
+ else:
+ if headers is None:
+ headers = {}
+ if self.headers.get('Connection',False) == 'Keep-Alive':
+ headers['Connection'] = 'keep-alive'
+
+ DAVRequestHandler.send_body(self, DATA, code=code, msg=msg, desc=desc,
+ ctype=ctype, headers=headers)
+
def do_PUT(self):
dc=self.IFACE_CLASS
uri=urlparse.urljoin(self.get_baseuri(dc), self.path)
@@ -141,6 +157,8 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
etag = None
for match in self.headers['If-Match'].split(','):
+ if match.startswith('"') and match.endswith('"'):
+ match = match[1:-1]
if match == '*':
if dc.exists(uri):
test = True
@@ -150,6 +168,7 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
test = True
break
if not test:
+ self._get_body()
self.send_status(412)
return
@@ -167,6 +186,7 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
test = False
break
if not test:
+ self._get_body()
self.send_status(412)
return
@@ -179,10 +199,7 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
self._flush()
# read the body
- body=None
- if self.headers.has_key("Content-Length"):
- l=self.headers['Content-Length']
- body=self.rfile.read(atoi(l))
+ body=self._get_body()
# locked resources are not allowed to be overwritten
if self._l_isLocked(uri):
@@ -208,6 +225,13 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
self.send_body(None, '201', 'Created', '', headers=headers)
+ def _get_body(self):
+ body = None
+ if self.headers.has_key("Content-Length"):
+ l=self.headers['Content-Length']
+ body=self.rfile.read(atoi(l))
+ return body
+
def do_DELETE(self):
try:
DAVRequestHandler.do_DELETE(self)