Exemple #1
0
def test_success_conversion(store, icaltomapi, message):
    ical = open(os.path.join(dir_path, 'ics/success.ics'), 'rb').read()

    # As defined in namedprops.h
    DISPID_APPT_TS_REF = 0x25

    NAMED_PROP_UID = MAPINAMEID(PSETID_Kopano_CalDav, MNID_ID,
                                DISPID_APPT_TS_REF)
    NAMED_PROP_CATEGORY = MAPINAMEID(PS_PUBLIC_STRINGS, MNID_STRING,
                                     'Keywords')
    properties = store.GetIDsFromNames([NAMED_PROP_UID, NAMED_PROP_CATEGORY],
                                       MAPI_CREATE)

    EXPECTED_MESSAGES = 1
    UID = CHANGE_PROP_TYPE(properties[0], PT_BINARY)  #0x85100102
    CATEGORY = CHANGE_PROP_TYPE(properties[1], PT_MV_UNICODE)  #0x850B101E
    START_DATE_PT_SYSTIME = 135547524000000000
    END_DATE_PT_SYSTIME = 135547920000000000

    prop_dic = {
        UID: [b'*****@*****.**'],
        PR_SUBJECT: [b'A dream holiday in the mountains'],
        CATEGORY: [['Holidays']],
        PR_SENDER_NAME_W: ['John Holidays'],
        PR_SENDER_EMAIL_ADDRESS_W: ['*****@*****.**'],
        PR_START_DATE: [FileTime(START_DATE_PT_SYSTIME)],
        PR_END_DATE: [FileTime(END_DATE_PT_SYSTIME)],
    }

    assert_item_count_from_ical(icaltomapi, ical, EXPECTED_MESSAGES)
    assert_properties_from_ical(icaltomapi, message, prop_dic)
Exemple #2
0
    def _arch_item(
        self
    ):  # open archive store explicitly so we can handle otherwise silenced errors (MAPI errors in mail bodies for example)
        if self._architem is None:
            if self.stubbed:
                ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, 0)
                PROP_STORE_ENTRYIDS = CHANGE_PROP_TYPE(ids[0], PT_MV_BINARY)
                PROP_ITEM_ENTRYIDS = CHANGE_PROP_TYPE(ids[1], PT_MV_BINARY)

                # support for multiple archives was a mistake, and is not and _should not_ be used. so we just pick nr 0.
                arch_storeid = HrGetOneProp(self.mapiobj,
                                            PROP_STORE_ENTRYIDS).Value[0]
                item_entryid = HrGetOneProp(self.mapiobj,
                                            PROP_ITEM_ENTRYIDS).Value[0]

                try:
                    arch_store = self.server._store2(arch_storeid)
                except MAPIErrorUnconfigured:
                    raise Error(
                        'could not open archive store (check SSL settings?)')

                self._architem = arch_store.OpenEntry(item_entryid, None, 0)
            else:
                self._architem = self.mapiobj
        return self._architem
Exemple #3
0
    def archive_store(self, store):
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, 0) # XXX merge namedprops stuff
        PROP_STORE_ENTRYIDS = CHANGE_PROP_TYPE(ids[0], PT_MV_BINARY)
        PROP_ITEM_ENTRYIDS = CHANGE_PROP_TYPE(ids[1], PT_MV_BINARY)

        # XXX only for detaching atm
        if store is None:
            self.mapiobj.DeleteProps([PROP_STORE_ENTRYIDS, PROP_ITEM_ENTRYIDS])
            self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
Exemple #4
0
    def archive_store(self, store):
        # TODO merge namedprops stuff
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, MAPI_CREATE)
        PROP_STORE_ENTRYIDS = CHANGE_PROP_TYPE(ids[0], PT_MV_BINARY)
        PROP_ITEM_ENTRYIDS = CHANGE_PROP_TYPE(ids[1], PT_MV_BINARY)

        # TODO only for detaching atm
        if store is None:
            self.mapiobj.DeleteProps([PROP_STORE_ENTRYIDS, PROP_ITEM_ENTRYIDS])
            _utils._save(self.mapiobj)
def test_round_trip_all_day_dstart_dend_style_not_date_incorrect(store, icaltomapi, mapitoical, message):
    ical = open(os.path.join(dir_path, 'ics/allday_dstart_dend_style_incorrect.ics'), 'rb').read()

    # As defined in namedprops.h
    DISPID_ALL_DAY_EVENT = 0x8215

    EXPECTED_MESSAGES = 1
    START_DATE_PT_SYSTIME = 132587712000000000
    END_DATE_PT_SYSTIME = 132588576000000000

    ALL_DAY_NAMEID = MAPINAMEID(PSETID_Appointment, MNID_ID, DISPID_ALL_DAY_EVENT)
    ALL_DAY_PROP = CHANGE_PROP_TYPE(
        store.GetIDsFromNames([ALL_DAY_NAMEID], MAPI_CREATE)[0],
        PT_BOOLEAN
    )

    prop_dic = {
        PR_START_DATE: [FileTime(START_DATE_PT_SYSTIME)],
        PR_END_DATE: [FileTime(END_DATE_PT_SYSTIME)],
        ALL_DAY_PROP: [False]
    }

    assert_item_count_from_ical(icaltomapi, ical, EXPECTED_MESSAGES)
    assert_properties_from_ical(icaltomapi, message, prop_dic)

    # Reverting back to ical.
    mapitoical.AddMessage(message, '', 0)
    method, converted_ical = mapitoical.Finalize(icalmapi.M2IC_NO_VTIMEZONE)
    split_ical = converted_ical.split(b'\r\n')
    assert b'PUBLISH' == method
    assert b'DTSTART:20210226T000000Z' in split_ical
    assert b'DTEND:20210227T000000Z' in split_ical
Exemple #6
0
def _name_to_proptag(proptag, mapiobj, proptype=None):
    ptype, namespace, name = _split_proptag(proptag)
    proptype = proptype or ptype

    if name.isdigit():  # XXX
        name = int(name)
    elif name.startswith('0x'):
        name = int(name, 16)

    if namespace in NAMESPACE_GUID:
        guid = NAMESPACE_GUID[namespace]
    elif namespace in STR_GUID:
        guid = STR_GUID[namespace]

    if proptype is None:
        return None, proptype, namespace, name

    nameid = MAPINAMEID(guid,
                        MNID_ID if isinstance(name, int) else MNID_STRING,
                        name)
    lpname = mapiobj.GetIDsFromNames(
        [nameid], 0
    )  # TODO MAPI_CREATE, or too dangerous because of potential db overflow?
    proptag = CHANGE_PROP_TYPE(lpname[0], proptype)

    return proptag, proptype, namespace, name
Exemple #7
0
    def __init__(self, parent_mapiobj, mapiobj):
        self._parent_mapiobj = parent_mapiobj
        self.proptag = mapiobj.ulPropTag

        if PROP_TYPE(
                mapiobj.ulPropTag
        ) == PT_ERROR and mapiobj.Value == MAPI_E_NOT_ENOUGH_MEMORY:
            if PROP_ID(
                    self.proptag) == PROP_ID(PR_BODY_W):  # avoid slow guessing
                self.proptag = PR_BODY_W
                mapiobj = SPropDelayedValue(parent_mapiobj, self.proptag)
            elif PROP_ID(self.proptag) in (PROP_ID(PR_RTF_COMPRESSED),
                                           PROP_ID(PR_HTML)):
                self.proptag = CHANGE_PROP_TYPE(self.proptag, PT_BINARY)
                mapiobj = SPropDelayedValue(parent_mapiobj, self.proptag)
            else:  # XXX possible to use above trick to infer all proptags?
                for proptype in (PT_BINARY,
                                 PT_UNICODE):  # XXX slow, incomplete?
                    proptag = (mapiobj.ulPropTag & 0xffff0000) | proptype
                    try:
                        HrGetOneProp(
                            parent_mapiobj, proptag
                        )  # XXX: Unicode issue?? calls GetProps([proptag], 0)
                        self.proptag = proptag  # XXX isn't it strange we can get here
                    except MAPIErrorNotEnoughMemory:
                        mapiobj = SPropDelayedValue(parent_mapiobj, proptag)
                        self.proptag = proptag
                        break
                    except MAPIErrorNotFound:
                        pass

        self.mapiobj = mapiobj

        self._value = None
        self.__lpname = None
Exemple #8
0
 def enabled(self):
     """Auto-processing is enabled."""
     prop = CHANGE_PROP_TYPE(self._ids[0], PT_BOOLEAN)
     try:
         return HrGetOneProp(self._fb, prop).Value
     except MAPIErrorNotFound:
         return True
Exemple #9
0
    def archive_folder(self):
        """ Archive :class:`Folder` """

        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, 0) # XXX merge namedprops stuff
        PROP_STORE_ENTRYIDS = CHANGE_PROP_TYPE(ids[0], PT_MV_BINARY)
        PROP_ITEM_ENTRYIDS = CHANGE_PROP_TYPE(ids[1], PT_MV_BINARY)

        try:
            # support for multiple archives was a mistake, and is not and _should not_ be used. so we just pick nr 0.
            arch_storeid = HrGetOneProp(self.mapiobj, PROP_STORE_ENTRYIDS).Value[0]
            arch_folderid = HrGetOneProp(self.mapiobj, PROP_ITEM_ENTRYIDS).Value[0]
        except MAPIErrorNotFound:
            return

        archive_store = self.server._store2(arch_storeid)
        return _store.Store(mapiobj=archive_store, server=self.server).folder(entryid=_benc(arch_folderid))
Exemple #10
0
    def __init__(self, parent_mapiobj, mapiobj):
        self._parent_mapiobj = parent_mapiobj
        #: MAPI proptag, for example 0x37001f for PR_SUBJECT_W
        self.proptag = mapiobj.ulPropTag

        if (PROP_TYPE(mapiobj.ulPropTag) == PT_ERROR and \
            mapiobj.Value == MAPI_E_NOT_ENOUGH_MEMORY):
            # avoid slow guessing
            if PROP_ID(self.proptag) == PROP_ID(PR_BODY_W):
                self.proptag = PR_BODY_W
                mapiobj = SPropDelayedValue(parent_mapiobj, self.proptag)
            elif PROP_ID(self.proptag) in \
                (PROP_ID(PR_RTF_COMPRESSED), PROP_ID(PR_HTML)):
                self.proptag = CHANGE_PROP_TYPE(self.proptag, PT_BINARY)
                mapiobj = SPropDelayedValue(parent_mapiobj, self.proptag)
            else:  # TODO possible to use above trick to infer all proptags?
                # TODO slow, incomplete?
                for proptype in (PT_BINARY, PT_UNICODE):
                    proptag = (mapiobj.ulPropTag & 0xffff0000) | proptype
                    try:
                        # TODO: Unicode issue?? calls GetProps([proptag], 0)
                        HrGetOneProp(parent_mapiobj, proptag)
                        # TODO how did we end up here, why is this possible
                        self.proptag = proptag
                    except MAPIErrorNotEnoughMemory:
                        mapiobj = SPropDelayedValue(parent_mapiobj, proptag)
                        self.proptag = proptag
                        break
                    except MAPIErrorNotFound:
                        pass

        self.mapiobj = mapiobj

        self._value = None
        self.__lpname = None
Exemple #11
0
    def primary_item(self):
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, MAPI_CREATE) # XXX merge namedprops stuff
        PROP_REF_ITEM_ENTRYID = CHANGE_PROP_TYPE(ids[4], PT_BINARY)
        entryid = HrGetOneProp(self.mapiobj, PROP_REF_ITEM_ENTRYID).Value

        try:
            return self.folder.primary_store.item(entryid=_benc(entryid))
        except NotFoundError:
            pass
Exemple #12
0
 def categories(self):
     """Categories."""
     proptag = self.mapiobj.GetIDsFromNames([NAMED_PROP_CATEGORY], MAPI_CREATE)[0]
     proptag = CHANGE_PROP_TYPE(proptag, PT_MV_UNICODE)
     try:
         value = self.prop(proptag).value
     except NotFoundError:
         value = []
     return PersistentList(self.mapiobj, proptag, value)
Exemple #13
0
    def primary_store(self):
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, 0) # XXX merge namedprops stuff
        PROP_REF_STORE_ENTRYID = CHANGE_PROP_TYPE(ids[3], PT_BINARY)
        try:
            entryid = HrGetOneProp(self.mapiobj, PROP_REF_STORE_ENTRYID).Value
        except MAPIErrorNotFound:
            return

        return _store.Store(entryid=_benc(entryid), server=self.server)
Exemple #14
0
    def restore(self):
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER,
                                           0)  # XXX cache folder.GetIDs..?
        PROP_STUBBED = CHANGE_PROP_TYPE(ids[2], PT_BOOLEAN)
        PROP_REF_STORE_ENTRYID = CHANGE_PROP_TYPE(ids[3], PT_BINARY)
        PROP_REF_ITEM_ENTRYID = CHANGE_PROP_TYPE(ids[4], PT_BINARY)
        PROP_REF_PREV_ENTRYID = CHANGE_PROP_TYPE(ids[5], PT_BINARY)
        PROP_FLAGS = CHANGE_PROP_TYPE(ids[6], PT_LONG)

        # get/create primary item
        primary_item = self.primary_item
        if not primary_item:
            mapiobj = self.folder.primary_folder.mapiobj.CreateMessage(None, 0)
            new = True
        else:
            mapiobj = primary_item.mapiobj
            new = False

        if not new and not primary_item.stubbed:
            return
        # cleanup primary item
        mapiobj.DeleteProps([PROP_STUBBED, PR_ICON_INDEX])
        at = Table(self.server,
                   mapiobj.GetAttachmentTable(0),
                   columns=[PR_ATTACH_NUM])
        for row in at.rows():
            mapiobj.DeleteAttach(row[0].value, 0, None, 0)

        # copy contents into it
        exclude_props = [
            PROP_REF_STORE_ENTRYID, PROP_REF_ITEM_ENTRYID,
            PROP_REF_PREV_ENTRYID, PROP_FLAGS
        ]
        self.mapiobj.CopyTo(None, exclude_props, 0, None, IID_IMessage,
                            mapiobj, 0)

        mapiobj.SaveChanges(KEEP_OPEN_READWRITE)

        # update backref
        if new:
            entryid = HrGetOneProp(mapiobj, PR_ENTRYID).Value
            self.mapiobj.SetProps([SPropValue(PROP_REF_ITEM_ENTRYID, entryid)])
            self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
Exemple #15
0
 def stubbed(self):
     """Item is stubbed by archiver."""
     # TODO caching folder.GetIDs..?
     ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, MAPI_CREATE)
     PROP_STUBBED = CHANGE_PROP_TYPE(ids[2], PT_BOOLEAN)
     try:
         # False means destubbed
         return HrGetOneProp(self.mapiobj, PROP_STUBBED).Value
     except MAPIErrorNotFound:
         return False
Exemple #16
0
    def stubbed(self):
        """ Is item stubbed by archiver? """

        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER,
                                           0)  # XXX cache folder.GetIDs..?
        PROP_STUBBED = CHANGE_PROP_TYPE(ids[2], PT_BOOLEAN)
        try:
            return HrGetOneProp(self.mapiobj,
                                PROP_STUBBED).Value  # False means destubbed
        except MAPIErrorNotFound:
            return False
Exemple #17
0
    def primary_store(self):
        """Primary :class:`store <Store>` (for archive folders)."""
        # TODO merge namedprops stuff
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, MAPI_CREATE)
        PROP_REF_STORE_ENTRYID = CHANGE_PROP_TYPE(ids[3], PT_BINARY)
        try:
            entryid = HrGetOneProp(self.mapiobj, PROP_REF_STORE_ENTRYID).Value
        except MAPIErrorNotFound:
            return

        return _store.Store(entryid=_benc(entryid), server=self.server)
Exemple #18
0
    def primary_folder(self):
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER,
                                           0)  # XXX merge namedprops stuff
        PROP_REF_ITEM_ENTRYID = CHANGE_PROP_TYPE(ids[4], PT_BINARY)
        entryid = HrGetOneProp(self.mapiobj, PROP_REF_ITEM_ENTRYID).Value

        if self.primary_store:
            try:
                return self.primary_store.folder(entryid=_hex(entryid))
            except NotFoundError:
                pass
Exemple #19
0
    def archive_store(self):
        """Archive :class:`Store`."""
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, 0) # XXX merge namedprops stuff
        PROP_STORE_ENTRYIDS = CHANGE_PROP_TYPE(ids[0], PT_MV_BINARY)

        try:
            # support for multiple archives was a mistake, and is not and _should not_ be used. so we just pick nr 0.
            entryid = HrGetOneProp(self.mapiobj, PROP_STORE_ENTRYIDS).Value[0]
        except MAPIErrorNotFound:
            return

        return Store(entryid=_benc(entryid), server=self.server) # XXX server?
Exemple #20
0
    def primary_folder(self):
        """Primary :class:`folder <Folder>` (for archive folders)."""
        # TODO merge namedprops stuff
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, MAPI_CREATE)
        PROP_REF_ITEM_ENTRYID = CHANGE_PROP_TYPE(ids[4], PT_BINARY)
        try:
            entryid = HrGetOneProp(self.mapiobj, PROP_REF_ITEM_ENTRYID).Value
        except MAPIErrorNotFound:
            return

        if self.primary_store:
            try:
                return self.primary_store.folder(entryid=_benc(entryid))
            except NotFoundError:
                pass
Exemple #21
0
    def archive_folder(self):
        """Archive :class:`Folder` (in case multiple stores are archived
        to a single archive store)."""
        # TODO merge namedprops stuff
        ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, MAPI_CREATE)
        PROP_ITEM_ENTRYIDS = CHANGE_PROP_TYPE(ids[1], PT_MV_BINARY)

        try:
            # support for multiple archives was a mistake, and is not and
            # _should not_ be used. so we just pick nr 0.
            arch_folderid = HrGetOneProp(self.mapiobj,
                                         PROP_ITEM_ENTRYIDS).Value[0]
        except MAPIErrorNotFound:
            return

        return self.archive_store.folder(entryid=_benc(arch_folderid))
Exemple #22
0
def test_microsoft_style_not_all_day_if_not_midnight_incorrect(store, icaltomapi, message):
    ical = open(os.path.join(dir_path, 'ics/allday_ms_style_incorrect.ics'), 'rb').read()

    # As defined in namedprops.h
    DISPID_ALL_DAY_EVENT = 0x8215

    ALL_DAY_NAMEID = MAPINAMEID(PSETID_Appointment, MNID_ID, DISPID_ALL_DAY_EVENT)
    ALL_DAY_PROP = CHANGE_PROP_TYPE(
        store.GetIDsFromNames([ALL_DAY_NAMEID], MAPI_CREATE)[0],
        PT_BOOLEAN
    )

    EXPECTED_MESSAGES = 1
    IS_ALL_DAY = [False]

    assert_item_count_from_ical(icaltomapi, ical, EXPECTED_MESSAGES)
    assert_property_value_from_ical(icaltomapi, message, ALL_DAY_PROP, IS_ALL_DAY)
Exemple #23
0
 def licenseinfo(self):
     ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_KC, MAPI_CREATE)
     proptype = CHANGE_PROP_TYPE(ids[1], PT_TSTRING)
     prop = HrGetOneProp(self.mapiobj, proptype)
     return json.loads(prop.Value)
Exemple #24
0
    def restore(self, data_path):
        """ restore data from backup """

        self.restored_sourcekeys = set()
        self.options.sourcekeys = [sk.upper() for sk in self.options.sourcekeys]

        # determine store to restore to
        self.log.info('starting restore of %s', data_path)
        username = os.path.split(data_path)[1]

        try:
            if self.options.users:
                store = self._store(self.options.users[0])
            elif self.options.stores:
                store = self.server.store(self.options.stores[0])
            else:
                store = self._store(username)
        except kopano.NotFoundError:
            store = None

        if not store:
            fatal('unable to open store (username: %s)' % username)

        user = store.user

        # determine stored and specified folders
        path_folder = folder_struct(data_path, self.options)
        paths = self.options.folders or sorted(path_folder.keys())
        if self.options.recursive:
            paths = [path2 for path2 in path_folder for path in paths if (path2+'//').startswith(path+'/')]
        for path in paths:
            if path not in path_folder:
                fatal('no such folder: %s' % path)

        # start restore
        self.log.info('restoring to store %s', store.entryid)
        t0 = time.time()
        stats = {'changes': 0, 'errors': 0}

        # determine restore root
        if self.options.restore_root:
            restore_root = store.folder(self.options.restore_root, create=True)
        else:
            restore_root = store.subtree

        # check existing folders
        sk_folder = {}
        for folder in restore_root.folders():
            orig_sk = folder.get(PR_EC_BACKUP_SOURCE_KEY)
            if orig_sk:
                sk_folder[orig_sk] = folder

        # restore specified (parts of) folders
        meta_folders = []
        sks = set()
        for path in paths:
            fpath = path_folder[path]
            folderprops = pickle_loads(open('%s/folder' % fpath, 'rb').read())
            folder_sk = folderprops[PR_SOURCE_KEY]

            # determine folder to restore
            if self.options.sourcekeys:
                with closing(dbopen(fpath+'/items')) as db:
                    if not [sk for sk in self.options.sourcekeys if sk.encode('ascii') in db]:
                        continue
            else:
                if self.options.deletes in (None, 'no') and folder_deleted(fpath):
                    continue

                sks.add(folder_sk)

                folder = restore_root.get_folder(path)
                if (folder and not store.public and \
                    ((self.options.skip_junk and folder == store.junk) or \
                    (self.options.skip_deleted and folder == store.wastebasket))):
                        continue

            # restore folder
            if self.options.only_meta: # TODO create empty folders with acls/rules, or skip non-existing folders?
                folder = restore_root.get_folder(path)
            else:
                # differential folder move
                folder = sk_folder.get(folder_sk)
                if folder and self.options.differential:
                    restore_path = self.options.restore_root+'/'+path if self.options.restore_root else path
                    restore_parent_path = '/'.join(UNESCAPED_SLASH_RE.split(restore_path)[:-1])
                    if folder.parent.path != restore_parent_path:
                        newparent = store.get_folder(restore_parent_path)
                        if newparent:
                            self.log.info('moving folder %s to %s', folder.path, restore_path)
                            folder.parent.move(folder, newparent)
                else:
                    folder = restore_root.folder(path, create=True)

                if self.options.clean_folders:
                    self.log.info('emptying folder %s', folder.path)
                    folder.empty()
                self.restore_folder(folder, path, fpath, store, store.subtree, stats, user, self.server)
            if folder:
                meta_folders.append((folder, fpath))

        # differential folder deletes
        if self.options.differential:
            for sk in set(sk_folder)-sks:
                path = sk_folder[sk].path
                parent = store.get_folder('/'.join(UNESCAPED_SLASH_RE.split(path)[:-1]))
                if parent:
                    self.log.info('deleting folder %s', path)
                    parent.delete(sk_folder[sk])

        # restore folder-level metadata
        if not (self.options.sourcekeys or self.options.skip_meta):
            self.log.info('restoring metadata')
            for (folder, fpath) in meta_folders:
                folder.permissions_loads(open(fpath+'/acl', 'rb').read(), stats=stats)
                folder.rules_loads(open(fpath+'/rules', 'rb').read(), stats=stats)

        # restore store-level metadata (webapp/mapi settings)
        if user and not (self.options.folders or self.options.restore_root or self.options.skip_meta or self.options.sourcekeys):
            if os.path.exists('%s/store' % data_path):
                storeprops = pickle_loads(open('%s/store' % data_path, 'rb').read())
                for proptag in SETTINGS_PROPTAGS:
                    if PROP_TYPE(proptag) == PT_TSTRING:
                        proptag = CHANGE_PROP_TYPE(proptag, PT_UNICODE)
                    value = storeprops.get(proptag)
                    if not value:
                        continue
                    store.mapiobj.SetProps([SPropValue(proptag, value)])
                store.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
            if os.path.exists('%s/delegates' % data_path):
                store.delegations_loads(open('%s/delegates' % data_path, 'rb').read(), stats=stats)
            if os.path.exists('%s/acl' % data_path):
                store.permissions_loads(open('%s/acl' % data_path, 'rb').read(), stats=stats)

        for sourcekey in self.options.sourcekeys:
            if sourcekey not in self.restored_sourcekeys:
                self.log.error('could not restore sourcekey: %s', sourcekey)

        self.log.info('restore completed in %.2f seconds (%d changes, ~%.2f/sec, %d errors)',
            time.time()-t0, stats['changes'], stats['changes']/(time.time()-t0), stats['errors'])
Exemple #25
0
 def enabled(self, b):
     prop = CHANGE_PROP_TYPE(self._ids[0], PT_BOOLEAN)
     self._fb.SetProps([SPropValue(prop, b)])
     _utils._save(self._fb)
Exemple #26
0
 def categories(self, value):
     proptag = self.mapiobj.GetIDsFromNames([NAMED_PROP_CATEGORY], MAPI_CREATE)[0]
     proptag = CHANGE_PROP_TYPE(proptag, PT_MV_UNICODE)
     data = [_unicode(x) for x in value]
     self.mapiobj.SetProps([SPropValue(proptag, data)])
     _utils._save(self.mapiobj)
Exemple #27
0
 def categories(self, value):
     proptag = self.mapiobj.GetIDsFromNames([NAMED_PROP_CATEGORY],
                                            MAPI_CREATE)[0]
     proptag = CHANGE_PROP_TYPE(proptag, PT_MV_STRING8)
     self.mapiobj.SetProps([SPropValue(proptag, list(value))])
     self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
Exemple #28
0
    def restore(self, data_path):
        """ restore data from backup """

        # determine store to restore to
        self.log.info('starting restore of %s', data_path)
        username = os.path.split(data_path)[1]

        try:
            if self.options.users:
                store = self._store(self.options.users[0])
            elif self.options.stores:
                store = self.server.store(self.options.stores[0])
            else:
                store = self._store(username)
        except kopano.NotFoundError:
            store = None

        if not store:
            fatal('unable to open store (username: %s)' % username)

        user = store.user

        # determine stored and specified folders
        path_folder = folder_struct(data_path, self.options)
        paths = self.options.folders or sorted(path_folder.keys())
        if self.options.recursive:
            paths = [path2 for path2 in path_folder for path in paths if (path2+'//').startswith(path+'/')]
        for path in paths:
            if path not in path_folder:
                fatal('no such folder: %s' % path)

        # start restore
        self.log.info('restoring to store %s', store.entryid)
        t0 = time.time()
        stats = {'changes': 0, 'errors': 0}

        # restore specified (parts of) folders
        restored = []
        for path in paths:
            fpath = path_folder[path]
            restore_path = _decode(self.options.restore_root)+'/'+path if self.options.restore_root else path

            if self.options.sourcekeys:
                with closing(dbopen(fpath+'/items')) as db:
                    if not [sk for sk in self.options.sourcekeys if sk.encode('ascii') in db]:
                        continue
            else:
                if self.options.deletes in (None, 'no') and folder_deleted(fpath):
                    continue

                folder = store.subtree.get_folder(restore_path)
                if (folder and not store.public and \
                    ((self.options.skip_junk and folder == store.junk) or \
                    (self.options.skip_deleted and folder == store.wastebasket))):
                        continue

            if not self.options.only_meta:
                folder = store.subtree.folder(restore_path, create=True)
                self.restore_folder(folder, path, fpath, store, store.subtree, stats, user, self.server)
            restored.append((folder, fpath))

        # restore folder-level metadata
        if not (self.options.sourcekeys or self.options.skip_meta):
            self.log.info('restoring metadata')
            for (folder, fpath) in restored:
                load_acl(folder, user, self.server, open(fpath+'/acl', 'rb').read(), stats, self.log)
                load_rules(folder, user, self.server, open(fpath+'/rules', 'rb').read(), stats, self.log)

        # restore store-level metadata (webapp/mapi settings)
        if user and not self.options.folders and not self.options.restore_root and not self.options.skip_meta:
            if os.path.exists('%s/store' % data_path):
                storeprops = pickle_loads(open('%s/store' % data_path, 'rb').read())
                for proptag in WEBAPP_SETTINGS + (PR_EC_OUTOFOFFICE_SUBJECT, PR_EC_OUTOFOFFICE_MSG,
                                PR_EC_OUTOFOFFICE, PR_EC_OUTOFOFFICE_FROM, PR_EC_OUTOFOFFICE_UNTIL):
                    if PROP_TYPE(proptag) == PT_TSTRING:
                        proptag = CHANGE_PROP_TYPE(proptag, PT_UNICODE)
                    value = storeprops.get(proptag)
                    if not value:
                        continue
                    store.mapiobj.SetProps([SPropValue(proptag, value)])
                store.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
            if os.path.exists('%s/delegates' % data_path):
                load_delegates(user, self.server, open('%s/delegates' % data_path, 'rb').read(), stats, self.log)
            if os.path.exists('%s/acl' % data_path):
                load_acl(store, user, self.server, open('%s/acl' % data_path, 'rb').read(), stats, self.log)

        self.log.info('restore completed in %.2f seconds (%d changes, ~%.2f/sec, %d errors)',
            time.time()-t0, stats['changes'], stats['changes']/(time.time()-t0), stats['errors'])