#
##############################################################################
-from osv import osv, fields
-from tools.translate import _
-import pooler
-import tools
-import time
-import base64
-from document import nodes
-import StringIO
-
-class node_database(nodes.node_database):
+from document_webdav import nodes
+from document.nodes import _str2time, nodefd_static
+import logging
+from orm_utils import get_last_modified
+
+try:
+ from tools.dict_tools import dict_merge2
+except ImportError:
+ from document.dict_tools import dict_merge2
+
+# TODO: implement DAV-aware errors, inherit from IOError
+
+# Assuming that we have set global properties right, we mark *all*
+# directories as having calendar-access.
+nodes.node_dir.http_options = dict_merge2(nodes.node_dir.http_options,
+ { 'DAV': ['calendar-access',] })
+
+class node_calendar_collection(nodes.node_dir):
+ DAV_PROPS = dict_merge2(nodes.node_dir.DAV_PROPS,
+ { "http://calendarserver.org/ns/" : ('getctag',), } )
+ DAV_M_NS = dict_merge2(nodes.node_dir.DAV_M_NS,
+ { "http://calendarserver.org/ns/" : '_get_dav', } )
+
+ def _file_get(self,cr, nodename=False):
+ return []
+
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)]
+ ext = False
+ if name and name.endswith('.ics'):
+ name = name[:-4]
+ ext = True
+ if name:
+ where.append(('name','=',name))
if not domain:
domain = []
- domain2 = domain + [('calendar_collection','=', False)]
- res = super(node_database, self)._child_get(cr, name=name, parent_id=parent_id, domain=domain2)
- where = [('parent_id','=',parent_id)]
- domain2 = domain + [('calendar_collection','=', True)]
+ where = where + domain
+ fil_obj = dirobj.pool.get('basic.calendar')
+ ids = fil_obj.search(cr,uid,where,context=ctx)
+ res = []
+ for cal in fil_obj.browse(cr, uid, ids, context=ctx):
+ if (not name) or not ext:
+ res.append(node_calendar(cal.name, self, self.context, cal))
+ if self.context.get('DAV-client', '') in ('iPhone', 'iCalendar'):
+ # these ones must not see the webcal entry.
+ continue
+ if cal.has_webcal and (not name) or ext:
+ res.append(res_node_calendar(cal.name+'.ics', self, self.context, cal))
+ # May be both of them!
+ return res
+
+ def _get_ttag(self, cr):
+ return 'calen-dir-%d' % self.dir_id
+
+ def _get_dav_getctag(self, cr):
+ dirobj = self.context._dirobj
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ where = [('collection_id','=',self.dir_id)]
+ bc_obj = dirobj.pool.get('basic.calendar')
+
+ res = get_last_modified(bc_obj, cr, uid, where, context=ctx)
+ return _str2time(res)
+
+class node_calendar_res_col(nodes.node_res_obj):
+ """ Calendar collection, as a dynamically created node
+
+ This class shall be used instead of node_calendar_collection, when the
+ node is under dynamic ones.
+ """
+ DAV_PROPS = dict_merge2(nodes.node_res_obj.DAV_PROPS,
+ { "http://calendarserver.org/ns/" : ('getctag',), } )
+ DAV_M_NS = dict_merge2(nodes.node_res_obj.DAV_M_NS,
+ { "http://calendarserver.org/ns/" : '_get_dav', } )
+
+ def _file_get(self,cr, nodename=False):
+ return []
+
+ 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)]
+ ext = False
+ if name and name.endswith('.ics'):
+ name = name[:-4]
+ ext = True
if name:
where.append(('name','=',name))
- if domain2:
- where += domain2
-
- where2 = where + [('type', '=', 'directory')]
- ids = dirobj.search(cr, uid, where2, context=ctx)
- for dirr in dirobj.browse(cr,uid,ids,context=ctx):
- res.append(node_calendar_collection(dirr.name,self,self.context,dirr))
+ if not domain:
+ domain = []
+ where = where + domain
+ fil_obj = dirobj.pool.get('basic.calendar')
+ ids = fil_obj.search(cr,uid,where,context=ctx)
+ res = []
+ # TODO: shall we use any of our dynamic information??
+ for cal in fil_obj.browse(cr, uid, ids, context=ctx):
+ if (not name) or not ext:
+ res.append(node_calendar(cal.name, self, self.context, cal))
+ if self.context.get('DAV-client', '') in ('iPhone', 'iCalendar'):
+ # these ones must not see the webcal entry.
+ continue
+ if cal.has_webcal and (not name) or ext:
+ res.append(res_node_calendar(cal.name+'.ics', self, self.context, cal))
+ # May be both of them!
return res
-class node_calendar_collection(nodes.node_dir):
- PROPS = {
- "http://calendarserver.org/ns/" : ('getctag'),
- }
- M_NS = {
- "http://calendarserver.org/ns/" : '_get_dav',
- }
-
- def get_dav_props(self, cr):
- return self.PROPS
+ def _get_ttag(self, cr):
+ return 'calen-dir-%d' % self.dir_id
- 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
+ def _get_dav_getctag(self, cr):
+ dirobj = self.context._dirobj
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ where = [('collection_id','=',self.dir_id)]
+ bc_obj = dirobj.pool.get('basic.calendar')
+
+ res = get_last_modified(bc_obj, cr, uid, where, context=ctx)
+ return _str2time(res)
- mname = prefix + "_" + propname
+class node_calendar(nodes.node_class):
+ our_type = 'collection'
+ DAV_PROPS = {
+ "DAV:": ('supported-report-set',),
+ # "http://cal.me.com/_namespace/" : ('user-state',),
+ "http://calendarserver.org/ns/" : ( 'getctag',),
+ 'http://groupdav.org/': ('resourcetype',),
+ "urn:ietf:params:xml:ns:caldav" : (
+ 'calendar-description',
+ 'supported-calendar-component-set',
+ ),
+ "http://apple.com/ns/ical/": ("calendar-color", "calendar-order"),
+ }
+ DAV_PROPS_HIDDEN = {
+ "urn:ietf:params:xml:ns:caldav" : (
+ 'calendar-data',
+ 'calendar-timezone',
+ 'supported-calendar-data',
+ 'max-resource-size',
+ 'min-date-time',
+ 'max-date-time',
+ )}
+
+ DAV_M_NS = {
+ "DAV:" : '_get_dav',
+ # "http://cal.me.com/_namespace/": '_get_dav',
+ 'http://groupdav.org/': '_get_gdav',
+ "http://calendarserver.org/ns/" : '_get_dav',
+ "urn:ietf:params:xml:ns:caldav" : '_get_caldav',
+ "http://apple.com/ns/ical/": '_get_apple_cal',
+ }
- if not hasattr(self, mname):
- return None
+ http_options = { 'DAV': ['calendar-access'] }
+ 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
+ self.cal_color = calendar.calendar_color or None
+ self.cal_order = calendar.calendar_order or 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 _file_get(self,cr, nodename=False):
- return []
+ self.uuser = (calendar.user_id and calendar.user_id.login) or 'nobody'
+ except Exception:
+ self.uuser = 'nobody'
-
- def get_domain(self, cr, filters):
- res = []
+ def _get_dav_getctag(self, cr):
dirobj = self.context._dirobj
uid = self.context.uid
ctx = self.context.context.copy()
ctx.update(self.dctx)
- calendar_obj = dirobj.pool.get('basic.calendar')
+
+ bc_obj = dirobj.pool.get('basic.calendar')
+ res = bc_obj.get_cal_max_modified(cr, uid, [self.calendar_id], self, domain=[], context=ctx)
+ return _str2time(res)
+
+ def _get_dav_user_state(self, cr):
+ #TODO
+ return 'online'
+
+ def get_dav_resourcetype(self, cr):
+ res = [ ('collection', 'DAV:'),
+ ('calendar', 'urn:ietf:params:xml:ns:caldav'),
+ ]
+ if self.context.get('DAV-client', '') == 'GroupDAV':
+ res.append((str(self.cal_type + '-collection'), 'http://groupdav.org/'))
+ return res
+
+ def get_domain(self, cr, filters):
+ # TODO: doc.
+ res = []
if not filters:
return res
- if filters.localName == 'calendar-query':
+ _log = logging.getLogger('caldav.query')
+ 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':
+ continue
+ if filter_child.localName == 'filter':
for vcalendar_filter in filter_child.childNodes:
- if vcalendar_filter.nodeType == vcalendar_filter.TEXT_NODE:
+ if vcalendar_filter.nodeType == vcalendar_filter.TEXT_NODE:
continue
if vcalendar_filter.localName == 'comp-filter':
if vcalendar_filter.getAttribute('name') == 'VCALENDAR':
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')]
-
+ if vevent_filter.getAttribute('name'):
+ res = [('type','=',vevent_filter.getAttribute('name').lower() )]
+
+ for cfe in vevent_filter.childNodes:
+ if cfe.localName == 'time-range':
+ if cfe.getAttribute('start'):
+ _log.warning("Ignore start.. ")
+ # No, it won't work in this API
+ #val = cfe.getAttribute('start')
+ #res += [('dtstart','=', cfe)]
+ elif cfe.getAttribute('end'):
+ _log.warning("Ignore end.. ")
+ else:
+ _log.debug("Unknown comp-filter: %s", cfe.localName)
+ else:
+ _log.debug("Unknown comp-filter: %s", vevent_filter.localName)
+ else:
+ _log.debug("Unknown filter element: %s", vcalendar_filter.localName)
+ else:
+ _log.debug("Unknown calendar-query element: %s", filter_child.localName)
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]
- calendar = calendar_obj.name_search(cr, uid, caluri)
- if calendar:
- calendar_id, calendar_name = calendar[0]
- ids.append(calendar_id)
- return [('id', 'in', ids)]
+ # this is not the place to process, as it wouldn't support multi-level
+ # hrefs. So, the code is moved to document_webdav/dav_fs.py
+ pass
+ else:
+ _log.debug("Unknown element in REPORT: %s", filters.localName)
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 = [('collection_id','=',self.dir_id)]
+ where = []
+ bc_obj = dirobj.pool.get('basic.calendar')
+
if name:
- where.append(('name','=',name))
+ if name.endswith('.ics'):
+ name = name[:-4]
+ try:
+ if name.isdigit():
+ where.append(('id','=',int(name)))
+ else:
+ bca_obj = dirobj.pool.get('basic.calendar.alias')
+ bc_alias = bca_obj.search(cr, uid,
+ [('cal_line_id.calendar_id', '=', self.calendar_id),
+ ('name', '=', name)] )
+ if not bc_alias:
+ return []
+ bc_val = bca_obj.read(cr, uid, bc_alias, ['res_id',])
+ where.append(('id', '=', bc_val[0]['res_id']))
+ except ValueError:
+ # if somebody requests any other name than the ones we
+ # generate (non-numeric), it just won't exist
+ return []
+
if not domain:
- domain = []
- where = where + domain
- fil_obj = dirobj.pool.get('basic.calendar')
- ids = fil_obj.search(cr,uid,where,context=ctx)
- res = []
- if ids:
- for fil in fil_obj.browse(cr,uid,ids,context=ctx):
- res.append(node_calendar(fil.name,self,self.context,fil))
+ domain = []
+
+ # we /could/ be supplying an invalid calendar id to bc_obj, it has to check
+ res = bc_obj.get_calendar_objects(cr, uid, [self.calendar_id], self, domain=where, context=ctx)
return res
- def _get_dav_owner(self, cr):
- return False
+ def create_child(self, cr, path, data):
+ """ API function to create a child file object and node
+ Return the node_* created
+ """
+ # we ignore the path, it will be re-generated automatically
+ fil_obj = self.context._dirobj.pool.get('basic.calendar')
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ uid = self.context.uid
-
- def get_etag(self, cr):
- """ Get a tag, unique per object + modification.
+ res = self.set_data(cr, data)
+
+ if res and len(res):
+ # We arbitrarily construct only the first node of the data
+ # that have been imported. ICS may have had more elements,
+ # but only one node can be returned here.
+ assert isinstance(res[0], (int, long))
+ fnodes = fil_obj.get_calendar_objects(cr, uid, [self.calendar_id], self,
+ domain=[('id','=',res[0])], context=ctx)
+ if self.context.get('DAV-client','') in ('iPhone', 'iCalendar',):
+ # For those buggy clients, register the alias
+ bca_obj = fil_obj.pool.get('basic.calendar.alias')
+ ourcal = fil_obj.browse(cr, uid, self.calendar_id)
+ line_id = None
+ for line in ourcal.line_ids:
+ if line.name == ourcal.type:
+ line_id = line.id
+ break
+ assert line_id, "Calendar #%d must have at least one %s line" % \
+ (ourcal.id, ourcal.type)
+ if path.endswith('.ics'):
+ path = path[:-4]
+ bca_obj.create(cr, uid, { 'cal_line_id': line_id,
+ 'res_id': res[0], 'name': path}, context=ctx)
+ return fnodes[0]
+ # If we reach this line, it means that we couldn't import any useful
+ # (and matching type vs. our node kind) data from the iCal content.
+ return None
+
+
+ def set_data(self, cr, data, fil_obj = None):
+ uid = self.context.uid
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ res = calendar_obj.import_cal(cr, uid, data, self.calendar_id)
+ return res
- see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """
- return self._get_ttag(cr) + ':' + self._get_wtag(cr)
+ def get_data_len(self, cr, fil_obj = None):
+ return self.content_length
- 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)
+ def _get_ttag(self,cr):
+ return 'calendar-%d' % (self.calendar_id,)
- def _get_ttag(self, cr):
- return 'calendar collection-%d' % self.dir_id
+ def rmcol(self, cr):
+ return False
- def _get_dav_getctag(self, cr):
- result = self.get_etag(cr)
- return str(result)
+ def _get_caldav_calendar_data(self, cr):
+ if self.context.get('DAV-client', '') in ('iPhone', 'iCalendar'):
+ # Never return collective data to iClients, they get confused
+ # because they do propfind on the calendar node with Depth=1
+ # and only expect the childrens' data
+ return None
+ res = []
+ for child in self.children(cr):
+ res.append(child._get_caldav_calendar_data(cr))
+ return res
+
+ def open_data(self, cr, mode):
+ return nodefd_static(self, cr, mode)
+
+ def _get_caldav_calendar_description(self, cr):
+ uid = self.context.uid
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ try:
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ return calendar.description or calendar.name
+ except Exception:
+ return None
+
+ def _get_dav_supported_report_set(self, cr):
+ return ('supported-report', 'DAV:',
+ ('report','DAV:',
+ ('principal-match','DAV:')
+ )
+ )
+
+ def _get_caldav_supported_calendar_component_set(self, cr):
+ return ('comp', 'urn:ietf:params:xml:ns:caldav', None,
+ {'name': self.cal_type.upper()} )
+
+ def _get_caldav_calendar_timezone(self, cr):
+ return None #TODO
+
+ def _get_caldav_supported_calendar_data(self, cr):
+ return ('calendar-data', 'urn:ietf:params:xml:ns:caldav', None,
+ {'content-type': "text/calendar", 'version': "2.0" } )
+
+ def _get_caldav_max_resource_size(self, cr):
+ return 65535
-class node_calendar(nodes.node_class):
+ def _get_caldav_min_date_time(self, cr):
+ return "19700101T000000Z"
+
+ def _get_caldav_max_date_time(self, cr):
+ return "21001231T235959Z" # I will be dead by then
+
+ def _get_apple_cal_calendar_color(self, cr):
+ return self.cal_color
+
+ def _get_apple_cal_calendar_order(self, cr):
+ return self.cal_order
+
+class res_node_calendar(nodes.node_class):
our_type = 'file'
- PROPS = {
- "http://calendarserver.org/ns/" : ('getctag'),
+ DAV_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_M_NS = {
"http://calendarserver.org/ns/" : '_get_dav',
- "urn:ietf:params:xml:ns:caldav" : '_get_caldav'}
+ "urn:ietf:params:xml:ns:caldav" : '_get_caldav'}
+
+ http_options = { 'DAV': ['calendar-access'] }
+
+ def __init__(self,path, parent, context, res_obj, res_model=None, res_id=None):
+ super(res_node_calendar,self).__init__(path, parent, context)
+ self.mimetype = 'text/calendar'
+ self.create_date = parent.create_date
+ self.write_date = parent.write_date or parent.create_date
+ self.calendar_id = hasattr(parent, 'calendar_id') and parent.calendar_id or False
+ if res_obj:
+ if not self.calendar_id: self.calendar_id = res_obj.id
+ pr = res_obj.perm_read(context=context, details=False)[0]
+ self.create_date = pr.get('create_date')
+ self.write_date = pr.get('write_date') or pr.get('create_date')
+ self.displayname = res_obj.name
- def __init__(self,path, parent, context, calendar):
- super(node_calendar,self).__init__(path, parent,context)
- self.calendar_id = calendar.id
- self.mimetype = 'ics'
- self.create_date = calendar.create_date
- self.write_date = calendar.write_date or calendar.create_date
self.content_length = 0
- self.displayname = calendar.name
-
- 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))
- s.name = self
- return s
-
-
-
- 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
+ self.model = res_model
+ self.res_id = res_id
+ def open_data(self, cr, mode):
+ return nodefd_static(self, cr, mode)
- def get_data(self, cr, fil_obj = None):
+ def get_data(self, cr, fil_obj=None):
uid = self.context.uid
calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- res = calendar_obj.export_cal(cr, uid, [self.calendar_id])
+ context = self.context.context.copy()
+ context.update(self.dctx)
+ context.update({'model': self.model, 'res_id':self.res_id})
+ res = calendar_obj.export_cal(cr, uid, [self.calendar_id], context=context)
return res
+
+ def _get_caldav_calendar_data(self, cr):
+ return self.get_data(cr)
- def get_data_len(self, cr, fil_obj = None):
+ def get_data_len(self, cr, fil_obj = None):
return self.content_length
def set_data(self, cr, data, fil_obj = None):
uid = self.context.uid
+ context = self.context.context.copy()
+ context.update(self.dctx)
+ context.update({'model': self.model, 'res_id':self.res_id})
calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- return calendar_obj.import_cal(cr, uid, base64.encodestring(data), self.calendar_id)
+ res = calendar_obj.import_cal(cr, uid, data, self.calendar_id, context=context)
+ return res
def _get_ttag(self,cr):
- return 'calendar-%d' % self.calendar_id
-
-
-
- def _get_caldav_calendar_data(self, cr):
- return self.get_data(cr)
-
-
- def _get_caldav_calendar_description(self, cr):
- uid = self.context.uid
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- return calendar.description
-
+ res = False
+ if self.model and self.res_id:
+ res = '%s_%d' % (self.model, self.res_id)
+ elif self.calendar_id:
+ res = '%d' % (self.calendar_id)
+ return res
- def _get_caldav_calendar_home_set(self, cr):
- import xml.dom.minidom
- import urllib
+ def rm(self, cr):
uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
-
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, calendar.collection_id.name)))
- href = doc.documentElement
- href.tagName = 'D:href'
- href.appendChild(huri)
- return href
-
- def _get_caldav_calendar_user_address_set(self, cr):
- import xml.dom.minidom
- dirobj = self.context._dirobj
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- user_obj = self.context._dirobj.pool.get('res.users')
- user = user_obj.browse(cr, uid, uid, context=ctx)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
- href = doc.documentElement
- href.tagName = 'D:href'
- huri = doc.createTextNode('MAILTO:' + user.email)
- href.appendChild(huri)
- return href
-
-
- def _get_caldav_schedule_inbox_URL(self, cr):
- import xml.dom.minidom
- import urllib
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- res = '%s/%s' %(calendar.name, calendar.collection_id.name)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
- href = doc.documentElement
- href.tagName = 'D:href'
- huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, res)))
- href.appendChild(huri)
- return href
-
-
-
- def _get_caldav_schedule_outbox_URL(self, cr):
- return _get_caldav_schedule_inbox_URL(cr)
-
+ res = False
+ if self.type in ('collection','database'):
+ return False
+ if self.model and self.res_id:
+ document_obj = self.context._dirobj.pool.get(self.model)
+ if document_obj:
+ res = document_obj.unlink(cr, uid, [self.res_id])
- def get_etag(self, cr):
- """ Get a tag, unique per object + modification.
+ return res
- 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)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4