def delete(self, objects, soft=False): # XXX associated """Delete items, subfolders, properties or permissions from folder. :param objects: The object(s) to delete :param soft: In case of items or folders, are they soft-deleted """ objects = _utils.arg_objects(objects, (_item.Item, Folder, Permission, Property, Occurrence, Rule), 'Folder.delete') item_entryids, folder_entryids, perms, props, occs, rules = self._get_entryids(objects) if item_entryids: if soft: self.mapiobj.DeleteMessages(item_entryids, 0, None, 0) else: self.mapiobj.DeleteMessages(item_entryids, 0, None, DELETE_HARD_DELETE) for entryid in folder_entryids: if soft: self.mapiobj.DeleteFolder(entryid, 0, None, DEL_FOLDERS | DEL_MESSAGES) else: self.mapiobj.DeleteFolder(entryid, 0, None, DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE) for perm in perms: acl_table = self.mapiobj.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, 0) acl_table.ModifyTable(0, [ROWENTRY(ROW_REMOVE, [SPropValue(PR_MEMBER_ID, perm.mapirow[PR_MEMBER_ID])])]) for rule in rules: rule_table = self.mapiobj.OpenProperty(PR_RULES_TABLE, IID_IExchangeModifyTable, MAPI_UNICODE, 0) rule_table.ModifyTable(0, [ROWENTRY(ROW_REMOVE, [SPropValue(PR_RULE_ID, rule.mapirow[PR_RULE_ID])])]) if props: self.mapiobj.DeleteProps([prop.proptag for prop in props]) for occ in occs: if occ.item.recurring: occ.item.delete(occ) else: self.delete(occ.item)
def _save_rule(store, userids, deletion): # remove existing rule # XXX update for rule in store.inbox.rules(): if rule.mapirow[PR_RULE_PROVIDER_W] == u'Schedule+ EMS Interface' and \ PR_RULE_ID in rule.mapirow: pr_rule_id = rule.mapirow[PR_RULE_ID] rulerows = [ ROWENTRY(ROW_REMOVE, [SPropValue(PR_RULE_ID, pr_rule_id)]) ] table = store.inbox.mapiobj.OpenProperty( PR_RULES_TABLE, IID_IExchangeModifyTable, 0, 0) table.ModifyTable(0, rulerows) # create new rule row = [ SPropValue(PR_RULE_LEVEL, 0), SPropValue(PR_RULE_NAME_W, u"Delegate Meetingrequest service"), SPropValue(PR_RULE_PROVIDER_W, u"Schedule+ EMS Interface"), SPropValue(PR_RULE_SEQUENCE, 0), SPropValue(PR_RULE_STATE, 1), SPropValue(PR_RULE_PROVIDER_DATA, b''), ] actions = [] userprops = [] for userid in userids: user = store.server.gab.OpenEntry(userid, None, MAPI_BEST_ACCESS) props = user.GetProps(USERPROPS, MAPI_UNICODE) # Hardcode recipient type to TO props.append(SPropValue(PR_RECIPIENT_TYPE, MAPI_TO)) userprops.append(props) actions.append( ACTION(ACTTYPE.OP_DELEGATE, 0, None, None, 0, actFwdDelegate(userprops))) if deletion: actions.append(ACTION(ACTTYPE.OP_DELETE, 0, None, None, 0, None)) row.append(SPropValue(PR_RULE_ACTIONS, ACTIONS(1, actions))) cond = SAndRestriction([ SContentRestriction( FL_PREFIX, PR_MESSAGE_CLASS_W, SPropValue(PR_MESSAGE_CLASS_W, u"IPM.Schedule.Meeting")), SNotRestriction(SExistRestriction(PR_DELEGATED_BY_RULE)), SOrRestriction([ SNotRestriction(SExistRestriction(PR_SENSITIVITY)), SPropertyRestriction(RELOP_NE, PR_SENSITIVITY, SPropValue(PR_SENSITIVITY, 2)) ]) ]) row.append(SPropValue(PR_RULE_CONDITION, cond)) rulerows = [ROWENTRY(ROW_ADD, row)] table = store.inbox.mapiobj.OpenProperty(PR_RULES_TABLE, IID_IExchangeModifyTable, 0, 0) table.ModifyTable(0, rulerows)
def gab_shared_contacts(providersession): user = os.getenv('KOPANO_TEST_USER2') password = os.getenv('KOPANO_TEST_PASSWORD2') socket = os.getenv('KOPANO_SOCKET') session = OpenECSession(user, password, socket, providers=[b'ZARAFA6', b'ZCONTACTS']) store = GetDefaultStore(session) seid = store.GetProps([PR_ENTRYID], 0)[0] usereid = store.GetProps([PR_MAILBOX_OWNER_ENTRYID], 0)[0].Value root = store.OpenEntry(None, None, 0) ceid = root.GetProps([PR_IPM_CONTACT_ENTRYID], 0)[0].Value sharedfolder = session.OpenEntry(ceid, None, 0) shared_eid = sharedfolder.GetProps([PR_ENTRYID], 0)[0] add_folder_to_provider(providersession, seid.Value, shared_eid.Value, 'Shared Contacts') acltab = sharedfolder.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, MAPI_MODIFY) rowlist = [ ROWENTRY(ROW_ADD, [ SPropValue(PR_MEMBER_ENTRYID, usereid), SPropValue(PR_MEMBER_RIGHTS, ecRightsFolderVisible | ecRightsReadAny) ]) ] acltab.ModifyTable(ROWLIST_REPLACE, rowlist) yield sharedfolder # Reset ACL's acltab.ModifyTable(ROWLIST_REPLACE, [])
def PreRuleProcess(self, session, addrbook, store, rulestable): props = store.GetProps([PR_ENTRYID, PR_IPM_WASTEBASKET_ENTRYID], 0) storeid = props[0].Value folderid = props[1].Value rowlist = [ ROWENTRY(ROW_ADD, [ SPropValue(PR_RULE_LEVEL, 0), SPropValue(PR_RULE_NAME, "dagenttest"), SPropValue(PR_RULE_PROVIDER, "RuleOrganizer"), SPropValue(PR_RULE_STATE, ST_ENABLED), SPropValue(PR_RULE_SEQUENCE, 1), SPropValue( PR_RULE_ACTIONS, ACTIONS(EDK_RULES_VERSION, [ ACTION(ACTTYPE.OP_MOVE, 0x00000000, None, None, 0x00000000, actMoveCopy(storeid, folderid)) ])), SPropValue( PR_RULE_CONDITION, SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, 'rulestest'))) ]) ] rulestable.ModifyTable(0, rowlist) return MP_CONTINUE
def create_rule(self, name=None, restriction=None): if name: name = _unicode(name) propid = len(list(self.rules())) + 1 row = [ SPropValue(PR_RULE_STATE, ST_ENABLED), # TODO configurable SPropValue( PR_RULE_PROVIDER_DATA, codecs.decode('010000000000000074da402772c2e440', 'hex')), SPropValue(PR_RULE_SEQUENCE, propid), # TODO max+1? SPropValue(0x6681001f, u'RuleOrganizer'), # TODO name SPropValue(PR_RULE_ID, propid), # TODO max+1 ] if name: row.append(SPropValue(PR_RULE_NAME_W, name)) if restriction: row.append(SPropValue(PR_RULE_CONDITION, restriction.mapiobj)) table = self.mapiobj.OpenProperty(PR_RULES_TABLE, IID_IExchangeModifyTable, MAPI_UNICODE, 0) table.ModifyTable(0, [ROWENTRY(ROW_ADD, row)]) mapirow = dict((p.ulPropTag, p.Value) for p in row) return Rule(mapirow, table)
def delete(self, objects, soft=False): """Delete properties, delegations, permissions, folders or items from store. :param objects: The object(s) to delete :param soft: Soft-delete items and folders (default False) """ objects = _utils.arg_objects(objects, (_folder.Folder, _item.Item, Property, Delegation, Permission), 'Store.delete') # TODO directly delete inbox rule? props = [o for o in objects if isinstance(o, Property)] if props: self.mapiobj.DeleteProps([p.proptag for p in props]) _utils._save(self.mapiobj) delgs = [o for o in objects if isinstance(o, Delegation)] for d in delgs: d._delete() perms = [o for o in objects if isinstance(o, Permission)] for perm in perms: acl_table = self.mapiobj.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, 0) acl_table.ModifyTable(0, [ROWENTRY(ROW_REMOVE, [SPropValue(PR_MEMBER_ID, perm.mapirow[PR_MEMBER_ID])])]) others = [o for o in objects \ if isinstance(o, (_item.Item, _folder.Folder))] if others: self.root.delete(others, soft=soft)
def _permissions_loads(obj, data, stats=None): """ load permissions for given store or folder """ server = obj.server log = server.log with log_exc(log, stats): data = _utils.pickle_loads(data) if isinstance(data, dict): data = data[b'data'] rows = [] for row in data: try: member_type, value = row[1].Value if member_type == b'user': entryid = server.user(value).userid else: entryid = server.group(value).groupid row[1].Value = _bdec(entryid) rows.append(row) except kopano.NotFoundError: log.warning( "skipping access control entry for unknown user/group '%s'", value) acltab = obj.mapiobj.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, MAPI_MODIFY) acltab.ModifyTable(0, [ROWENTRY(ROW_ADD, row) for row in rows])
def add_rule(rules, condition, ruleaction): rules.ModifyTable(0, [ ROWENTRY(ROW_ADD, [ SPropValue(PR_RULE_LEVEL, 0), SPropValue(PR_RULE_NAME, b'test_rule'), SPropValue(PR_RULE_PROVIDER, b'RuleOrganizer'), SPropValue(PR_RULE_STATE, ST_ENABLED), SPropValue(PR_RULE_SEQUENCE, 1), SPropValue(PR_RULE_CONDITION, condition), SPropValue(PR_RULE_ACTIONS, ruleaction) ]) ])
def rights(self, value): r = 0 for name in value: try: r |= NAME_RIGHT[name] except KeyError: raise NotFoundError("no such right: '%s'" % name) self.mapitable.ModifyTable(0, [ROWENTRY(ROW_MODIFY, [SPropValue(PR_MEMBER_ID, self.mapirow[PR_MEMBER_ID]), SPropValue(PR_MEMBER_ENTRYID, self.mapirow[PR_MEMBER_ENTRYID]), SPropValue(PR_MEMBER_RIGHTS, r)] )]) # PR_MEMBER_ID needed, or it becomes ROW_ADD
def permission(obj, member, create): for permission in obj.permissions(): if permission.member == member: return permission if create: acl_table = obj.mapiobj.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, 0) if isinstance(member, _user.User): # XXX *.id_ or something..? memberid = member.userid elif isinstance(member, _group.Group): memberid = member.groupid else: memberid = member.companyid acl_table.ModifyTable(0, [ROWENTRY(ROW_ADD, [SPropValue(PR_MEMBER_ENTRYID, _bdec(memberid)), SPropValue(PR_MEMBER_RIGHTS, 0)])]) return obj.permission(member) else: raise NotFoundError("no permission entry for '%s'" % member.name)
def load_acl(obj, user, server, data, stats, log): """ load acl for given store or folder """ with log_exc(log, stats): data = pickle_loads(data) rows = [] for row in data: try: member_type, value = row[1].Value if member_type == b'user': entryid = server.user(value).userid else: entryid = server.group(value).groupid row[1].Value = _unhex(entryid) rows.append(row) except kopano.NotFoundError: log.warning("skipping access control entry for unknown user/group '%s'", value) acltab = obj.mapiobj.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, MAPI_MODIFY) acltab.ModifyTable(0, [ROWENTRY(ROW_ADD, row) for row in rows])
def create_action(self, type_, folder=None): if type_ == 'move': # TODO other types action = ACTION( 1, 0, None, None, 0x0, actMoveCopy(_bdec(folder.store.entryid), _bdec(folder.entryid))) row = [] found = False for proptag, value in self.mapirow.items(): if proptag == PR_RULE_ACTIONS: found = True value.lpAction.append(action) row.append(SPropValue(proptag, value)) if not found: row.append(SPropValue(PR_RULE_ACTIONS, ACTIONS(1, [action]))) self.table.ModifyTable(0, [ROWENTRY(ROW_MODIFY, row)]) return Action(action)
def test_delegate_permissions_owner(publicfolder, session3, kind, rights, folder_access, message_access): print(kind) access = publicfolder.GetProps([PR_ACCESS], 0)[0].Value defaultAccess = MAPI_ACCESS_MODIFY | MAPI_ACCESS_READ | MAPI_ACCESS_DELETE | MAPI_ACCESS_CREATE_HIERARCHY | MAPI_ACCESS_CREATE_CONTENTS assert defaultAccess == access store = GetDefaultStore(session3) userid = session3.QueryIdentity() folderid = publicfolder.GetProps([PR_ENTRYID], 0)[0].Value acls = publicfolder.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, MAPI_MODIFY) rowlist = [ ROWENTRY(ROW_ADD, [ SPropValue(PR_MEMBER_ENTRYID, userid), SPropValue(PR_MEMBER_RIGHTS, rights) ]) ] acls.ModifyTable(ROWLIST_REPLACE, rowlist) message = publicfolder.CreateMessage(None, 0) message.SetProps([SPropValue(PR_SUBJECT, b'acl test')]) message.SaveChanges(0) eid = message.GetProps([PR_ENTRYID], 0)[0].Value access = message.GetProps([PR_ACCESS], 0)[0].Value assert access == MAPI_ACCESS_MODIFY | MAPI_ACCESS_READ | MAPI_ACCESS_DELETE # as user3, open public and get folder access public = GetPublicStore(session3) folder = public.OpenEntry(folderid, None, MAPI_BEST_ACCESS) access = folder.GetProps([PR_ACCESS], 0)[0].Value assert access == folder_access message = folder.OpenEntry(eid, None, 0) access = message.GetProps([PR_ACCESS], 0)[0].Value assert access == message_access