[IMP+REF] caldav
bzr revid: hmo@tinyerp.com-20100422125041-2x1fkswvf2gab05p
This commit is contained in:
@@ -26,10 +26,13 @@ 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):
|
||||
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('/')
|
||||
if uri[-1] in ('Calendars'):
|
||||
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')
|
||||
|
||||
+217
-102
@@ -57,29 +57,15 @@ class node_calendar_collection(nodes.node_dir):
|
||||
}
|
||||
M_NS = {
|
||||
"http://calendarserver.org/ns/" : '_get_dav',
|
||||
}
|
||||
headers = None
|
||||
}
|
||||
|
||||
|
||||
def get_dav_props(self, cr):
|
||||
return self.PROPS
|
||||
|
||||
def match_dav_eprop(self, cr, match, ns, prop):
|
||||
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(':'))
|
||||
title, cal_id, 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 dav_time <= wtime:
|
||||
return True
|
||||
return False
|
||||
res = super(node_calendar_collection, self).match_dav_eprop(cr, match, ns, prop)
|
||||
return res
|
||||
|
||||
|
||||
def get_dav_eprop(self,cr, ns, propname):
|
||||
def get_dav_eprop(self,cr, ns, propname):
|
||||
if self.M_NS.has_key(ns):
|
||||
prefix = self.M_NS[ns]
|
||||
else:
|
||||
@@ -101,88 +87,27 @@ class node_calendar_collection(nodes.node_dir):
|
||||
return None
|
||||
|
||||
def _file_get(self,cr, nodename=False):
|
||||
return []
|
||||
return []
|
||||
|
||||
def set_data(self, cr, data, fil_obj = None):
|
||||
res = None
|
||||
uid = self.context.uid
|
||||
calendar_obj = self.context._dirobj.pool.get('basic.calendar')
|
||||
if self.headers and self.headers.has_key('If-Match'):
|
||||
for match in self.headers['If-Match'].split(','):
|
||||
if match != '*':
|
||||
tem, dav_time = tuple(match.split(':'))
|
||||
title, cal_id, model, res_id = tuple(tem.split('-'))
|
||||
res = calendar_obj.import_cal(cr, uid, base64.encodestring(data), cal_id)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
|
||||
|
||||
def get_domain(self, cr, filters):
|
||||
res = []
|
||||
dirobj = self.context._dirobj
|
||||
uid = self.context.uid
|
||||
ctx = self.context.context.copy()
|
||||
ctx.update(self.dctx)
|
||||
calendar_obj = dirobj.pool.get('basic.calendar')
|
||||
if not filters:
|
||||
return res
|
||||
if filters.localName == 'calendar-query':
|
||||
res = []
|
||||
for filter_child in filters.childNodes:
|
||||
if filter_child.nodeType == filter_child.TEXT_NODE:
|
||||
continue
|
||||
if filter_child.localName == 'filter':
|
||||
for vcalendar_filter in filter_child.childNodes:
|
||||
if vcalendar_filter.nodeType == vcalendar_filter.TEXT_NODE:
|
||||
continue
|
||||
if vcalendar_filter.localName == 'comp-filter':
|
||||
if vcalendar_filter.getAttribute('name') == 'VCALENDAR':
|
||||
for vevent_filter in vcalendar_filter.childNodes:
|
||||
if vevent_filter.nodeType == vevent_filter.TEXT_NODE:
|
||||
continue
|
||||
if vevent_filter.localName == 'comp-filter':
|
||||
if vevent_filter.getAttribute('name') == 'VEVENT':
|
||||
res = [('type','=','vevent')]
|
||||
if vevent_filter.getAttribute('name') == 'VTODO':
|
||||
res = [('type','=','vtodo')]
|
||||
|
||||
return res
|
||||
elif filters.localName == 'calendar-multiget':
|
||||
ids = []
|
||||
for filter_child in filters.childNodes:
|
||||
if filter_child.nodeType == filter_child.TEXT_NODE:
|
||||
continue
|
||||
if filter_child.localName == 'href':
|
||||
if not filter_child.firstChild:
|
||||
continue
|
||||
uri = filter_child.firstChild.data
|
||||
caluri = uri.split('/')
|
||||
if len(caluri):
|
||||
caluri = caluri[-1]
|
||||
caluri, res_id = tuple(caluri.split('_'))
|
||||
calendar = calendar_obj.name_search(cr, uid, caluri)
|
||||
if calendar:
|
||||
calendar_id, calendar_name = calendar[0]
|
||||
if calendar_id not in ids: ids.append(calendar_id)
|
||||
return [('id', 'in', ids)]
|
||||
return res
|
||||
|
||||
def _child_get(self, cr, name=False, parent_id=False, domain=None):
|
||||
def _child_get(self, cr, name=False, parent_id=False, domain=None):
|
||||
dirobj = self.context._dirobj
|
||||
uid = self.context.uid
|
||||
ctx = self.context.context.copy()
|
||||
ctx.update(self.dctx)
|
||||
where = [('collection_id','=',self.dir_id)]
|
||||
if name:
|
||||
name, res_id = tuple(name.split('_'))
|
||||
ctx.update({'res_id':res_id})
|
||||
if name:
|
||||
where.append(('name','=',name))
|
||||
if not domain:
|
||||
domain = []
|
||||
where = where + domain
|
||||
fil_obj = dirobj.pool.get('basic.calendar')
|
||||
ids = fil_obj.search(cr,uid,where,context=ctx)
|
||||
res = fil_obj.get_calendar_object(cr, uid, ids, parent=self, context=ctx)
|
||||
res = []
|
||||
for calender in fil_obj.browse(cr, uid, ids, context=ctx):
|
||||
res.append(node_calendar(calender.name, self, self.context, calender))
|
||||
return res
|
||||
|
||||
def _get_dav_owner(self, cr):
|
||||
@@ -210,7 +135,193 @@ class node_calendar_collection(nodes.node_dir):
|
||||
return str(result)
|
||||
|
||||
|
||||
class node_calendar(nodes.node_class):
|
||||
class node_calendar(nodes.node_class):
|
||||
our_type = 'collection'
|
||||
PROPS = {
|
||||
"http://calendarserver.org/ns/" : ('getctag'),
|
||||
"urn:ietf:params:xml:ns:caldav" : (
|
||||
'calendar-description',
|
||||
'calendar-data',
|
||||
'calendar-home-set',
|
||||
'calendar-user-address-set',
|
||||
'schedule-inbox-URL',
|
||||
'schedule-outbox-URL',)}
|
||||
M_NS = {
|
||||
"DAV:" : '_get_dav',
|
||||
"http://calendarserver.org/ns/" : '_get_dav',
|
||||
"urn:ietf:params:xml:ns:caldav" : '_get_caldav'}
|
||||
|
||||
def __init__(self,path, parent, context, calendar):
|
||||
super(node_calendar,self).__init__(path, parent,context)
|
||||
self.calendar_id = calendar.id
|
||||
self.mimetype = 'application/x-directory'
|
||||
self.create_date = calendar.create_date
|
||||
self.write_date = calendar.write_date or calendar.create_date
|
||||
self.content_length = 0
|
||||
self.displayname = calendar.name
|
||||
self.cal_type = calendar.type
|
||||
|
||||
def _get_dav_getctag(self, cr):
|
||||
result = self.get_etag(cr)
|
||||
return str(result)
|
||||
|
||||
def match_dav_eprop(self, cr, match, ns, prop):
|
||||
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 dav_time <= wtime:
|
||||
return True
|
||||
return False
|
||||
res = super(node_calendar, self).match_dav_eprop(cr, match, ns, prop)
|
||||
return res
|
||||
|
||||
|
||||
def get_domain(self, cr, filters):
|
||||
res = []
|
||||
dirobj = self.context._dirobj
|
||||
uid = self.context.uid
|
||||
ctx = self.context.context.copy()
|
||||
ctx.update(self.dctx)
|
||||
calendar_obj = dirobj.pool.get('basic.calendar')
|
||||
if not filters:
|
||||
return res
|
||||
if filters.localName == 'calendar-query':
|
||||
res = []
|
||||
for filter_child in filters.childNodes:
|
||||
if filter_child.nodeType == filter_child.TEXT_NODE:
|
||||
continue
|
||||
if filter_child.localName == 'filter':
|
||||
for vcalendar_filter in filter_child.childNodes:
|
||||
if vcalendar_filter.nodeType == vcalendar_filter.TEXT_NODE:
|
||||
continue
|
||||
if vcalendar_filter.localName == 'comp-filter':
|
||||
if vcalendar_filter.getAttribute('name') == 'VCALENDAR':
|
||||
for vevent_filter in vcalendar_filter.childNodes:
|
||||
if vevent_filter.nodeType == vevent_filter.TEXT_NODE:
|
||||
continue
|
||||
if vevent_filter.localName == 'comp-filter':
|
||||
if vevent_filter.getAttribute('name') == 'VEVENT':
|
||||
res = [('type','=','vevent')]
|
||||
if vevent_filter.getAttribute('name') == 'VTODO':
|
||||
res = [('type','=','vtodo')]
|
||||
return res
|
||||
elif filters.localName == 'calendar-multiget':
|
||||
names = []
|
||||
for filter_child in filters.childNodes:
|
||||
if filter_child.nodeType == filter_child.TEXT_NODE:
|
||||
continue
|
||||
if filter_child.localName == 'href':
|
||||
if not filter_child.firstChild:
|
||||
continue
|
||||
uri = filter_child.firstChild.data
|
||||
caluri = uri.split('/')
|
||||
if len(caluri):
|
||||
caluri = caluri[-2]
|
||||
if caluri not in names : names.append(caluri)
|
||||
res = [('name','in',names)]
|
||||
return res
|
||||
return res
|
||||
|
||||
def children(self, cr, domain=None):
|
||||
return self._child_get(cr, domain=domain)
|
||||
|
||||
def child(self,cr, name, domain=None):
|
||||
res = self._child_get(cr, name, domain=domain)
|
||||
if res:
|
||||
return res[0]
|
||||
return None
|
||||
|
||||
|
||||
def _child_get(self, cr, name=False, parent_id=False, domain=None):
|
||||
dirobj = self.context._dirobj
|
||||
uid = self.context.uid
|
||||
ctx = self.context.context.copy()
|
||||
ctx.update(self.dctx)
|
||||
where = []
|
||||
if name:
|
||||
where.append(('id','=',int(name)))
|
||||
if not domain:
|
||||
domain = []
|
||||
#for opr1, opt, opr2 in domain:
|
||||
# if opr1 == 'type' and opr2 != self.cal_type:
|
||||
# return []
|
||||
|
||||
fil_obj = dirobj.pool.get('basic.calendar')
|
||||
ids = fil_obj.search(cr, uid, domain)
|
||||
res = []
|
||||
if self.calendar_id in ids:
|
||||
res = fil_obj.get_calendar_objects(cr, uid, [self.calendar_id], self, domain=where, context=ctx)
|
||||
return res
|
||||
|
||||
|
||||
|
||||
def get_dav_props(self, cr):
|
||||
return self.PROPS
|
||||
|
||||
def get_dav_eprop(self,cr, ns, propname):
|
||||
if self.M_NS.has_key(ns):
|
||||
prefix = self.M_NS[ns]
|
||||
else:
|
||||
print "No namespace:",ns, "( for prop:", propname,")"
|
||||
return None
|
||||
propname = propname.replace('-','_')
|
||||
mname = prefix + "_" + propname
|
||||
if not hasattr(self, mname):
|
||||
return None
|
||||
|
||||
try:
|
||||
m = getattr(self, mname)
|
||||
r = m(cr)
|
||||
return r
|
||||
except AttributeError, e:
|
||||
print 'Property %s not supported' % propname
|
||||
print "Exception:", e
|
||||
return None
|
||||
|
||||
|
||||
def create_child(self,cr,path,data):
|
||||
""" API function to create a child file object and node
|
||||
Return the node_* created
|
||||
"""
|
||||
return self.set_data(cr, data)
|
||||
|
||||
|
||||
def set_data(self, cr, data, fil_obj = None):
|
||||
uid = self.context.uid
|
||||
calendar_obj = self.context._dirobj.pool.get('basic.calendar')
|
||||
return calendar_obj.import_cal(cr, uid, base64.encodestring(data), self.calendar_id)
|
||||
|
||||
def get_data_len(self, cr, fil_obj = None):
|
||||
return self.content_length
|
||||
|
||||
|
||||
def _get_ttag(self,cr):
|
||||
return 'calendar-%d' % (self.calendar_id,)
|
||||
|
||||
|
||||
|
||||
def get_etag(self, cr):
|
||||
""" Get a tag, unique per object + modification.
|
||||
|
||||
see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """
|
||||
return self._get_ttag(cr) + ':' + self._get_wtag(cr)
|
||||
|
||||
def _get_wtag(self, cr):
|
||||
""" Return the modification time as a unique, compact string """
|
||||
if self.write_date:
|
||||
wtime = time.mktime(time.strptime(self.write_date, '%Y-%m-%d %H:%M:%S'))
|
||||
else: wtime = time.time()
|
||||
return str(wtime)
|
||||
|
||||
|
||||
class res_node_calendar(nodes.node_class):
|
||||
our_type = 'file'
|
||||
PROPS = {
|
||||
"http://calendarserver.org/ns/" : ('getctag'),
|
||||
@@ -225,23 +336,27 @@ class node_calendar(nodes.node_class):
|
||||
"http://calendarserver.org/ns/" : '_get_dav',
|
||||
"urn:ietf:params:xml:ns:caldav" : '_get_caldav'}
|
||||
|
||||
def __init__(self,path, parent, context, calendar):
|
||||
super(node_calendar,self).__init__(path, parent,context)
|
||||
self.calendar_id = calendar.id
|
||||
def __init__(self,path, parent, context, res_obj, res_model, res_id=None):
|
||||
super(res_node_calendar,self).__init__(path, parent, context)
|
||||
self.calendar_id = parent.calendar_id
|
||||
self.mimetype = 'text/calendar'
|
||||
self.create_date = calendar.create_date
|
||||
self.write_date = calendar.write_date or calendar.create_date
|
||||
self.create_date = parent.create_date
|
||||
self.write_date = parent.write_date or parent.create_date
|
||||
if res_obj:
|
||||
self.create_date = res_obj.create_date
|
||||
self.write_date = res_obj.write_date or res_obj.create_date
|
||||
self.displayname = res_obj.name
|
||||
|
||||
self.content_length = 0
|
||||
self.displayname = calendar.name
|
||||
self.model = False
|
||||
self.res_id = False
|
||||
|
||||
self.model = res_model
|
||||
self.res_id = res_id
|
||||
|
||||
def open(self, cr, mode=False):
|
||||
uid = self.context.uid
|
||||
if self.type in ('collection','database'):
|
||||
return False
|
||||
fobj = self.context._dirobj.pool.get('basic.calendar').browse(cr, uid, self.calendar_id, context=self.context.context)
|
||||
s = StringIO.StringIO(self.get_data(cr, fobj))
|
||||
return False
|
||||
s = StringIO.StringIO(self.get_data(cr))
|
||||
s.name = self
|
||||
return s
|
||||
|
||||
@@ -288,7 +403,7 @@ class node_calendar(nodes.node_class):
|
||||
return calendar_obj.import_cal(cr, uid, base64.encodestring(data), self.calendar_id)
|
||||
|
||||
def _get_ttag(self,cr):
|
||||
return 'calendar-%d-%s-%d' % (self.calendar_id, self.model, self.res_id)
|
||||
return '%s_%d' % (self.model, self.res_id)
|
||||
|
||||
|
||||
|
||||
@@ -370,5 +485,5 @@ class node_calendar(nodes.node_class):
|
||||
if self.write_date:
|
||||
wtime = time.mktime(time.strptime(self.write_date, '%Y-%m-%d %H:%M:%S'))
|
||||
else: wtime = time.time()
|
||||
return str(wtime)
|
||||
return str(wtime)
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4
|
||||
|
||||
+14
-14
@@ -31,7 +31,7 @@ import pytz
|
||||
import re
|
||||
import tools
|
||||
import time
|
||||
from caldav_node import node_calendar
|
||||
from caldav_node import res_node_calendar
|
||||
|
||||
try:
|
||||
import vobject
|
||||
@@ -258,7 +258,7 @@ class CalDAV(object):
|
||||
if not datas:
|
||||
return
|
||||
timezones = []
|
||||
for data in datas:
|
||||
for data in datas:
|
||||
tzval = None
|
||||
vevent = ical.add(name)
|
||||
for field in self.__attribute__.keys():
|
||||
@@ -438,9 +438,11 @@ class Calendar(CalDAV, osv.osv):
|
||||
'write_date': fields.datetime('Modifided Date'),
|
||||
}
|
||||
|
||||
def get_calendar_object(self, cr, uid, ids, parent=None, context=None):
|
||||
def get_calendar_objects(self, cr, uid, ids, parent=None, domain=None, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
if not domain:
|
||||
domain = []
|
||||
res = []
|
||||
ctx_res_id = context.get('res_id', None)
|
||||
ctx_model = context.get('model', None)
|
||||
@@ -450,16 +452,15 @@ class Calendar(CalDAV, osv.osv):
|
||||
continue
|
||||
if line.name in ('valarm', 'attendee'):
|
||||
continue
|
||||
domain = eval(line.domain)
|
||||
line_domain = eval(line.domain)
|
||||
line_domain += domain
|
||||
if ctx_res_id:
|
||||
domain += [('id','=',ctx_res_id)]
|
||||
line_domain += [('id','=',ctx_res_id)]
|
||||
mod_obj = self.pool.get(line.object_id.model)
|
||||
data_ids = mod_obj.search(cr, uid, domain, context=context)
|
||||
for data_id in data_ids:
|
||||
data_ids = mod_obj.search(cr, uid, line_domain, context=context)
|
||||
for data in mod_obj.browse(cr, uid, data_ids, context):
|
||||
ctx = parent and parent.context or None
|
||||
node = node_calendar('%s_%s' %(cal.name, data_id), parent, ctx, cal)
|
||||
node.model = line.object_id.model
|
||||
node.res_id = data_id
|
||||
node = res_node_calendar('%s' %data.id, parent, ctx, data, line.object_id.model, data.id)
|
||||
res.append(node)
|
||||
return res
|
||||
|
||||
@@ -510,12 +511,11 @@ class Calendar(CalDAV, osv.osv):
|
||||
ical_data = base64.decodestring(content)
|
||||
parsedCal = vobject.readOne(ical_data)
|
||||
if not data_id:
|
||||
data_id = self.search(cr, uid, [])[0]
|
||||
|
||||
cal = self.read(cr, uid, data_id, context=context)[0]
|
||||
data_id = self.search(cr, uid, [])[0]
|
||||
cal = self.browse(cr, uid, data_id, context=context)
|
||||
cal_children = {}
|
||||
count = 0
|
||||
for line in self.pool.get('basic.calendar.lines').browse(cr, uid, cal['line_ids']):
|
||||
for line in cal.line_ids:
|
||||
cal_children[line.name] = line.object_id.model
|
||||
for child in parsedCal.getChildren():
|
||||
if child.name.lower() in cal_children:
|
||||
|
||||
@@ -404,7 +404,7 @@ class openerp_dav_handler(dav_interface):
|
||||
node = self.uri2object(cr,uid,pool, uri2[:])
|
||||
except:
|
||||
node = False
|
||||
node.headers = self.parent.headers
|
||||
|
||||
objname = uri2[-1]
|
||||
ext = objname.find('.') >0 and objname.split('.')[1] or False
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ class project_task(osv.osv):
|
||||
_name = "project.task"
|
||||
_inherit = ["calendar.todo", "project.task"]
|
||||
_columns = {
|
||||
'write_date' : fields.datetime('Write Date'),
|
||||
'create_date' : fields.datetime('Create Date'),
|
||||
'attendee_ids': fields.many2many('calendar.attendee', \
|
||||
'task_attendee_rel', 'task_id', 'attendee_id', 'Attendees'),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user