[IMP+REF] caldav
authorHarry (Open ERP) <hmo@tinyerp.com>
Thu, 22 Apr 2010 12:50:41 +0000 (18:20 +0530)
committerHarry (Open ERP) <hmo@tinyerp.com>
Thu, 22 Apr 2010 12:50:41 +0000 (18:20 +0530)
bzr revid: hmo@tinyerp.com-20100422125041-2x1fkswvf2gab05p

addons/caldav/caldav.py
addons/caldav/caldav_node.py
addons/caldav/calendar.py
addons/document_webdav/dav_fs.py
addons/project_caldav/project_caldav.py

index 730bfda..f760421 100644 (file)
@@ -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')
index 8113575..e8887e1 100644 (file)
@@ -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,22 +87,102 @@ 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
+    
+    
+
+    def _child_get(self, cr, name=False, parent_id=False, domain=None):        
+        dirobj = self.context._dirobj
         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)
-        
+        ctx = self.context.context.copy()
+        ctx.update(self.dctx)
+        where = [('collection_id','=',self.dir_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 = []
+        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):
+        return False
+
+    
+    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)
+
+    def _get_ttag(self, cr):
+        return 'calendar collection-%d' % self.dir_id
+
+    def _get_dav_getctag(self, cr):
+        result = self.get_etag(cr)        
+        return str(result)   
+        
+
+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
@@ -141,14 +207,13 @@ class node_calendar_collection(nodes.node_dir):
                                     if vevent_filter.nodeType == vevent_filter.TEXT_NODE:
                                         continue
                                     if vevent_filter.localName == 'comp-filter':
-                                        if vevent_filter.getAttribute('name') == 'VEVENT':
+                                        if vevent_filter.getAttribute('name') == 'VEVENT':    
                                             res = [('type','=','vevent')]
                                         if vevent_filter.getAttribute('name') == 'VTODO':
-                                            res = [('type','=','vtodo')]                               
-            
+                                            res = [('type','=','vtodo')]                                           
             return res
         elif filters.localName == 'calendar-multiget':
-            ids = []
+            names = []
             for filter_child in filters.childNodes:
                 if filter_child.nodeType == filter_child.TEXT_NODE:
                     continue
@@ -158,37 +223,90 @@ class node_calendar_collection(nodes.node_dir):
                     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
+                        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 = [('collection_id','=',self.dir_id)]                              
-        if name:
-            name, res_id = tuple(name.split('_'))
-            ctx.update({'res_id':res_id})
-            where.append(('name','=',name))
+        ctx.update(self.dctx)   
+        where = []                               
+        if name:            
+            where.append(('id','=',int(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)        
-        return res
+            domain = []
+        #for opr1, opt, opr2 in domain:
+        #    if opr1 == 'type' and opr2 != self.cal_type:
+        #        return []
 
-    def _get_dav_owner(self, cr):
-        return False
+        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.
 
@@ -200,17 +318,10 @@ class node_calendar_collection(nodes.node_dir):
         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)   
 
-    def _get_ttag(self, cr):
-        return 'calendar collection-%d' % self.dir_id
-
-    def _get_dav_getctag(self, cr):
-        result = self.get_etag(cr)        
-        return str(result)   
-        
 
-class node_calendar(nodes.node_class):
+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
index d657cc4..3e4701a 100644 (file)
@@ -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:
index d8e6547..bfe9729 100644 (file)
@@ -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
 
index 6757861..62e1878 100644 (file)
@@ -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'),
                 }