Example #1
0
 def _get_dav_eprop_hlpr(self, cr, ns, prop, par_class, prop_model,
                         prop_ref_field, res_id):
     """ Helper for get dav eprop, usable in subclasses
     
     @param namespace the one to search for
     @param name Name to search for
     @param par_class The parent class
     @param prop_model The name of the orm model holding the properties
     @param prop_ref_field The name of the field at prop_model pointing to us
     @param res_id the id of self in the corresponing orm table, that should
                     match prop_model.prop_ref_field
     """
     ret = par_class.get_dav_eprop(self, cr, ns, prop)
     if ret is not None:
         return ret
     if prop_model:
         propobj = self.context._dirobj.pool.get(prop_model)
         uid = self.context.uid
         ctx = self.context.context.copy()
         ctx.update(self.dctx)
         ctx.update({'uid': uid, 'dbname': self.context.dbname})
         ctx['node_classname'] = "%s.%s" % (self.__class__.__module__,
                                            self.__class__.__name__)
         dict_filter(self.context.extra_ctx,
                     ['username', 'groupname', 'webdav_path'], ctx)
         sdomain = [(prop_ref_field, '=', False), ('namespace', '=', ns),
                    ('name', '=', prop)]
         if res_id:
             sdomain = ['|', (prop_ref_field, '=', res_id)] + sdomain
         prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
         if prop_ids:
             pbro = propobj.browse(cr, uid, prop_ids[0], context=ctx)
             val = pbro.value
             if pbro.do_subst:
                 if val.startswith("('") and val.endswith(")"):
                     glbls = {
                         'urlquote': urllib.quote,
                     }
                     val = eval(val, glbls, ctx)
                 else:
                     val = val % ctx
             return val
     return None
Example #2
0
 def _get_dav_eprop_hlpr(self, cr, ns, prop,
                         par_class, prop_model, 
                         prop_ref_field, res_id):
     """ Helper for get dav eprop, usable in subclasses
     
     @param namespace the one to search for
     @param name Name to search for
     @param par_class The parent class
     @param prop_model The name of the orm model holding the properties
     @param prop_ref_field The name of the field at prop_model pointing to us
     @param res_id the id of self in the corresponing orm table, that should
                     match prop_model.prop_ref_field
     """
     ret = par_class.get_dav_eprop(self, cr, ns, prop)
     if ret is not None:
         return ret
     if prop_model:
         propobj = self.context._dirobj.pool.get(prop_model)
         uid = self.context.uid
         ctx = self.context.context.copy()
         ctx.update(self.dctx)
         ctx.update({'uid': uid, 'dbname': self.context.dbname })
         ctx['node_classname'] = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
         dict_filter(self.context.extra_ctx, ['username', 'groupname', 'webdav_path'], ctx)
         sdomain = [(prop_ref_field, '=', False),('namespace', '=', ns), ('name','=', prop)]
         if res_id:
             sdomain = ['|', (prop_ref_field, '=', res_id)] + sdomain
         prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
         if prop_ids:
             pbro = propobj.browse(cr, uid, prop_ids[0], context=ctx)
             val = pbro.value
             if pbro.do_subst:
                 if val.startswith("('") and val.endswith(")"):
                     glbls = { 'urlquote': urllib.quote, }
                     val = eval(val, glbls, ctx)
                 else:
                     val = val % ctx
             return val
     return None
Example #3
0
    def _dav_lock_hlpr(self, cr, lock_data, par_class, prop_model,
                            prop_ref_field, res_id):
        """ Helper, which uses the dav properties table for placing locks
        
        @param lock_data a dictionary of input to this function.
        @return list of tuples, DAV:activelock _contents_ structure.
                See webdav.py:class Prop2Xml() for semantics
        
        Note: although the DAV response shall be an <activelock/>, this
        function will only return the elements inside the activelock,
        because the calling function needs to append the <lockroot/> in
        it. See webdav.py:mk_lock_response()
        
        In order to reuse code, this function can be called with 
        lock_data['unlock_mode']=True, in order to unlock.
        
        @return bool in unlock mode, (davstruct, prop_id, token) in lock/refresh,
                    or (False, prop_id, token) if already locked,
                    or (False, False, False) if lock not found to refresh
        """
        assert prop_model
        assert res_id
        assert isinstance(lock_data, dict), '%r' % lock_data
        propobj = self.context._dirobj.pool.get(prop_model)
        uid = self.context.uid
        ctx = self.context.context.copy()
        ctx.update(self.dctx)
        ctx.update({'uid': uid, 'dbname': self.context.dbname })
        ctx['node_classname'] = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
        dict_filter(self.context.extra_ctx, ['username', 'groupname', 'webdav_path'], ctx)
        sdomain = [(prop_ref_field, '=', res_id), ('namespace', '=', 'DAV:'),
                    ('name','=', 'lockdiscovery')]
        props_to_delete = []
        lock_found = False
        lock_val = None
        tmout2 = int(lock_data.get('timeout', 3*3600))
        
        prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
        if prop_ids:
            for pbro in propobj.browse(cr, uid, prop_ids, context=ctx):
                val = pbro.value
                if pbro.do_subst:
                    if val.startswith("('") and val.endswith(")"):
                        glbls = { 'urlquote': urllib.quote, }
                        val = eval(val, glbls, ctx)
                    else:
                        # all locks should be at "subst" format
                        continue
                if not (val and isinstance(val, tuple) 
                        and val[0:2] == ( 'activelock','DAV:')):
                    # print "Value is not activelock:", val
                    continue
                
                old_token = False
                old_owner = False
                try:
                    # discover the timeout. If anything goes wrong, delete
                    # the lock (cleanup)
                    tmout = False
                    for parm in val[2]:
                        if parm[1] != 'DAV:':
                            continue
                        if parm[0] == 'timeout':
                            if isinstance(parm[2], basestring) \
                                    and parm[2].startswith('Second-'):
                                tmout = int(parm[2][7:])
                        elif parm[0] == 'locktoken':
                            if isinstance(parm[2], basestring):
                                old_token = parm[2]
                            elif isinstance(parm[2], tuple) and \
                                parm[2][0:2] == ('href','DAV:'):
                                    old_token = parm[2][2]
                            else:
                                # print "Mangled token in DAV property: %r" % parm[2]
                                props_to_delete.append(pbro.id)
                                continue
                        elif parm[0] == 'owner':
                            old_owner = parm[2] # not used yet
                    if tmout:
                        mdate = pbro.write_date or pbro.create_date
                        mdate = time.mktime(time.strptime(mdate,'%Y-%m-%d %H:%M:%S'))
                        if mdate + tmout < time.time():
                            props_to_delete.append(pbro.id)
                            continue
                    else:
                        props_to_delete.append(pbro.id)
                        continue
                except ValueError:
                    props_to_delete.append(pbro.id)
                    continue
                
                # A valid lock is found here
                if lock_data.get('refresh', False):
                    if old_token != lock_data.get('token'):
                        continue
                    # refresh mode. Just touch anything and the ORM will update
                    # the write uid+date, won't it?
                    # Note: we don't update the owner, because incoming refresh
                    # wouldn't have a body, anyway.
                    propobj.write(cr, uid, [pbro.id,], { 'name': 'lockdiscovery'})
                elif lock_data.get('unlock_mode', False):
                    if old_token != lock_data.get('token'):
                        continue
                    props_to_delete.append(pbro.id)
                
                lock_found = pbro.id
                lock_val = val

        if tmout2 > 3*3600: # 3 hours maximum
            tmout2 = 3*3600
        elif tmout2 < 300:
            # 5 minutes minimum, but an unlock request can always
            # break it at any time. Ensures no negative values, either.
            tmout2 = 300
        
        if props_to_delete:
            # explicitly delete, as admin, any of the ids we have identified.
            propobj.unlink(cr, SUPERUSER_ID, props_to_delete)
        
        if lock_data.get('unlock_mode', False):
            return lock_found and True
        elif (not lock_found) and not (lock_data.get('refresh', False)):
            # Create a new lock, attach and return it.
            new_token = uuid.uuid4().urn
            lock_val = ('activelock', 'DAV:', 
                    [ ('locktype', 'DAV:', (lock_data.get('locktype',False) or 'write','DAV:')),
                      ('lockscope', 'DAV:', (lock_data.get('lockscope',False) or 'exclusive','DAV:')),
                      # ? ('depth', 'DAV:', lock_data.get('depth','0') ),
                      ('timeout','DAV:', 'Second-%d' % tmout2),
                      ('locktoken', 'DAV:', ('href', 'DAV:', new_token)),
                      # ('lockroot', 'DAV: ..., we don't store that, appended by caller
                    ])
            new_owner = lock_data.get('lockowner',False) or ctx.get('username', False)
            if new_owner:
                lock_val[2].append( ('owner', 'DAV:',  new_owner) )
            prop_id = propobj.create(cr, uid, { prop_ref_field: res_id,
                    'namespace': 'DAV:', 'name': 'lockdiscovery',
                    'do_subst': True, 'value': repr(lock_val) })
            return (lock_val[2], prop_id, new_token )
        elif not lock_found: # and refresh
            return (False, False, False)
        elif lock_found and not lock_data.get('refresh', False):
            # already locked
            return (False, lock_found, old_token)
        else:
            return (lock_val[2], lock_found, old_token )
Example #4
0
    def _dav_lock_hlpr(self, cr, lock_data, par_class, prop_model,
                            prop_ref_field, res_id):
        """ Helper, which uses the dav properties table for placing locks
        
        @param lock_data a dictionary of input to this function.
        @return list of tuples, DAV:activelock _contents_ structure.
                See webdav.py:class Prop2Xml() for semantics
        
        Note: although the DAV response shall be an <activelock/>, this
        function will only return the elements inside the activelock,
        because the calling function needs to append the <lockroot/> in
        it. See webdav.py:mk_lock_response()
        
        In order to reuse code, this function can be called with 
        lock_data['unlock_mode']=True, in order to unlock.
        
        @return bool in unlock mode, (davstruct, prop_id, token) in lock/refresh,
                    or (False, prop_id, token) if already locked,
                    or (False, False, False) if lock not found to refresh
        """
        assert prop_model
        assert res_id
        assert isinstance(lock_data, dict), '%r' % lock_data
        propobj = self.context._dirobj.pool.get(prop_model)
        uid = self.context.uid
        ctx = self.context.context.copy()
        ctx.update(self.dctx)
        ctx.update({'uid': uid, 'dbname': self.context.dbname })
        ctx['node_classname'] = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
        dict_filter(self.context.extra_ctx, ['username', 'groupname', 'webdav_path'], ctx)
        sdomain = [(prop_ref_field, '=', res_id), ('namespace', '=', 'DAV:'),
                    ('name','=', 'lockdiscovery')]
        props_to_delete = []
        lock_found = False
        lock_val = None
        tmout2 = int(lock_data.get('timeout', 3*3600))
        
        prop_ids = propobj.search(cr, uid, sdomain, context=ctx)
        if prop_ids:
            for pbro in propobj.browse(cr, uid, prop_ids, context=ctx):
                val = pbro.value
                if pbro.do_subst:
                    if val.startswith("('") and val.endswith(")"):
                        glbls = { 'urlquote': urllib.quote, }
                        val = eval(val, glbls, ctx)
                    else:
                        # all locks should be at "subst" format
                        continue
                if not (val and isinstance(val, tuple) 
                        and val[0:2] == ( 'activelock','DAV:')):
                    # print "Value is not activelock:", val
                    continue
                
                old_token = False
                old_owner = False
                try:
                    # discover the timeout. If anything goes wrong, delete
                    # the lock (cleanup)
                    tmout = False
                    for parm in val[2]:
                        if parm[1] != 'DAV:':
                            continue
                        if parm[0] == 'timeout':
                            if isinstance(parm[2], basestring) \
                                    and parm[2].startswith('Second-'):
                                tmout = int(parm[2][7:])
                        elif parm[0] == 'locktoken':
                            if isinstance(parm[2], basestring):
                                old_token = parm[2]
                            elif isinstance(parm[2], tuple) and \
                                parm[2][0:2] == ('href','DAV:'):
                                    old_token = parm[2][2]
                            else:
                                # print "Mangled token in DAV property: %r" % parm[2]
                                props_to_delete.append(pbro.id)
                                continue
                        elif parm[0] == 'owner':
                            old_owner = parm[2] # not used yet
                    if tmout:
                        mdate = pbro.write_date or pbro.create_date
                        mdate = time.mktime(time.strptime(mdate,'%Y-%m-%d %H:%M:%S'))
                        if mdate + tmout < time.time():
                            props_to_delete.append(pbro.id)
                            continue
                    else:
                        props_to_delete.append(pbro.id)
                        continue
                except ValueError:
                    props_to_delete.append(pbro.id)
                    continue
                
                # A valid lock is found here
                if lock_data.get('refresh', False):
                    if old_token != lock_data.get('token'):
                        continue
                    # refresh mode. Just touch anything and the ORM will update
                    # the write uid+date, won't it?
                    # Note: we don't update the owner, because incoming refresh
                    # wouldn't have a body, anyway.
                    propobj.write(cr, uid, [pbro.id,], { 'name': 'lockdiscovery'})
                elif lock_data.get('unlock_mode', False):
                    if old_token != lock_data.get('token'):
                        continue
                    props_to_delete.append(pbro.id)
                
                lock_found = pbro.id
                lock_val = val

        if tmout2 > 3*3600: # 3 hours maximum
            tmout2 = 3*3600
        elif tmout2 < 300:
            # 5 minutes minimum, but an unlock request can always
            # break it at any time. Ensures no negative values, either.
            tmout2 = 300
        
        if props_to_delete:
            # explicitly delete, as admin, any of the ids we have identified.
            propobj.unlink(cr, 1, props_to_delete)
        
        if lock_data.get('unlock_mode', False):
            return lock_found and True
        elif (not lock_found) and not (lock_data.get('refresh', False)):
            # Create a new lock, attach and return it.
            new_token = uuid.uuid4().urn
            lock_val = ('activelock', 'DAV:', 
                    [ ('locktype', 'DAV:', (lock_data.get('locktype',False) or 'write','DAV:')),
                      ('lockscope', 'DAV:', (lock_data.get('lockscope',False) or 'exclusive','DAV:')),
                      # ? ('depth', 'DAV:', lock_data.get('depth','0') ),
                      ('timeout','DAV:', 'Second-%d' % tmout2),
                      ('locktoken', 'DAV:', ('href', 'DAV:', new_token)),
                      # ('lockroot', 'DAV: ..., we don't store that, appended by caller
                    ])
            new_owner = lock_data.get('lockowner',False) or ctx.get('username', False)
            if new_owner:
                lock_val[2].append( ('owner', 'DAV:',  new_owner) )
            prop_id = propobj.create(cr, uid, { prop_ref_field: res_id,
                    'namespace': 'DAV:', 'name': 'lockdiscovery',
                    'do_subst': True, 'value': repr(lock_val) })
            return (lock_val[2], prop_id, new_token )
        elif not lock_found: # and refresh
            return (False, False, False)
        elif lock_found and not lock_data.get('refresh', False):
            # already locked
            return (False, lock_found, old_token)
        else:
            return (lock_val[2], lock_found, old_token )