bzr revid: hmo@tinyerp.com-20100803070555-sos3jnng6mdz6juh
This commit is contained in:
Harry (OpenERP) 2010-08-03 12:35:55 +05:30
commit dc658546bd
6 changed files with 140 additions and 64 deletions

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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)