commit
dc658546bd
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <prop>value</prop>
|
||||
|
||||
And a little smarter than that, it will consider namespace and
|
||||
also allow nested properties etc.
|
||||
|
||||
:param ns the namespace of the <prop/> node
|
||||
:param prop the name of the property
|
||||
:param value the value. Can be:
|
||||
string: text node
|
||||
tuple ('elem', 'ns') for empty sub-node <ns:elem />
|
||||
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")
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue