Beispiel #1
0
    def search_start(self, folders, text, recurse=False):
        # specific restriction format, needed to reach indexer
        restriction = SOrRestriction([
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE,
                PR_SUBJECT_W,
                SPropValue(PR_SUBJECT_W, str(text))),
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE,
                PR_BODY_W,
                SPropValue(PR_BODY_W, str(text))),
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE,
                PR_DISPLAY_TO_W,
                SPropValue(PR_DISPLAY_TO_W, str(text))),
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE,
                PR_DISPLAY_NAME_W,
                SPropValue(PR_DISPLAY_NAME_W, str(text))),
            # TODO add all default fields..
            # BUT perform full-text search by default!
        ])
        if isinstance(folders, Folder):
            folders = [folders]

        search_flags = 0
        if recurse:
            search_flags = SEARCH_RECURSIVE
        self.mapiobj.SetSearchCriteria(restriction,
            [_bdec(f.entryid) for f in folders], search_flags)
def test_optimize_doubleor(root):
    restriction = SOrRestriction([
            SOrRestriction([
                    SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown')),
                    SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown'))
                    ])
            ])
    assert_no_results(root, restriction)
def test_optimize_ormultianndfalse(root):
    restriction = SOrRestriction([
    SAndRestriction([
            SNotRestriction(SExistRestriction(PR_SUBJECT)),
            SExistRestriction(PR_SUBJECT)
            ]),
    SAndRestriction([
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown')),
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown'))
            ])
    ])
    assert_no_results(root, restriction)
Beispiel #4
0
    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
Beispiel #5
0
def GetAbObjectList(session, restriction=None, companyname=None, flags=0):
    gab = GetGab(session)
    table = gab.GetHierarchyTable(0)
    if companyname is None or len(companyname) == 0:
        companyCount = table.GetRowCount(0)
        if companyCount == 0:
            users = _GetAbObjectList(gab, restriction, flags)
        else:
            table.SetColumns([PR_ENTRYID], TBL_BATCH)
            users = []
            for row in table.QueryRows(companyCount, 0):
                company = gab.OpenEntry(row[0].Value, None, 0)
                companyUsers = _GetAbObjectList(company, restriction, flags)
                users.extend(companyUsers)
    else:
        if isinstance(companyname, str):
            tag_dispname = PR_DISPLAY_NAME_W
        else:
            tag_dispname = PR_DISPLAY_NAME_A
        table.FindRow(
            SContentRestriction(FL_FULLSTRING | FL_IGNORECASE, tag_dispname,
                                SPropValue(tag_dispname, companyname)),
            BOOKMARK_BEGINNING, 0)
        table.SetColumns([PR_ENTRYID], TBL_BATCH)
        row = table.QueryRows(1, 0)[0]
        users = _GetAbObjectList(gab.OpenEntry(row[0].Value, None, 0),
                                 restriction, flags)

    return users
Beispiel #6
0
    def restriction(self, type_, store):
        if self.field:
            # determine proptag for term, eg 'subject'
            proptag = TYPE_KEYWORD_PROPMAP[type_][self.field]
            flag = None
            subobj = None
            recipient_type = None

            # property in sub-object (attachments/recipient): use sub-restriction
            if isinstance(proptag, tuple):
                if(proptag[0]) == PR_MESSAGE_ATTACHMENTS:
                    subobj, proptag = proptag
                elif(proptag[0]) == PR_MESSAGE_RECIPIENTS:
                    subobj, proptag, recipient_type = proptag
                elif len(proptag) == 2:
                    proptag, flag = proptag

                # named property: resolve local proptag
                elif len(proptag) == 4:
                    proptag = store._name_id(proptag[:3]) | proptag[3]

            # make restriction on proptag(s)
            if isinstance(proptag, list):
                restr = SOrRestriction([
                    self.prop_restriction(proptag, flag) for proptag in proptag
                ])
            else:
                restr = self.prop_restriction(proptag, flag)

            # turn restriction into sub-restriction
            if subobj:
                if recipient_type is not None:
                    restr = SAndRestriction([
                        restr,
                        SPropertyRestriction(
                                RELOP_EQ,
                                PR_RECIPIENT_TYPE,
                                SPropValue(PR_RECIPIENT_TYPE, recipient_type)
                        )
                    ])
                restr = SSubRestriction(subobj, restr)

        else:
            defaults = [(store._name_id(proptag[:3]) | proptag[3])
                           if isinstance(proptag, tuple) else proptag
                               for proptag in DEFAULT_PROPTAGS[type_]]

            restr = SOrRestriction([
                       SContentRestriction(
                           FL_SUBSTRING | FL_IGNORECASE,
                           p,
                           SPropValue(p, self.value)
                       ) for p in defaults
                   ])

        if self.sign == '-':
            restr = SNotRestriction(restr)

        return restr
Beispiel #7
0
    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)
Beispiel #8
0
    def restriction(self, type_, store):
        if self.field:
            # determine proptag for term, eg 'subject'
            proptag = TYPE_KEYWORD_PROPMAP[type_][self.field]
            flag = None
            subobj = None
            recipient_type = None

            # property in sub-object (attachments/recipient): use sub-restriction
            if isinstance(proptag, tuple) and len(proptag) == 2:
                if(proptag[0]) == PR_MESSAGE_ATTACHMENTS:
                    subobj, proptag = proptag
                elif(proptag[0]) == PR_MESSAGE_RECIPIENTS:
                    subobj, recipient_type = proptag
                    proptag = PR_DISPLAY_NAME_W # TODO email
                else:
                    proptag, flag = proptag

            # named property: resolve local proptag
            elif isinstance(proptag, tuple) and len(proptag) == 4:
                proptag = store._name_id(proptag[:3]) | proptag[3]

            # comparison operator
            if self.op in ('<', '>', '>=', '<=', '<>'):
                if PROP_TYPE(proptag) == PT_SYSTIME:
                    d = dateutil.parser.parse(self.value, dayfirst=True)
                    d = datetime_to_filetime(d)
                    restr = SPropertyRestriction(
                                OP_RELOP[self.op],
                                proptag,
                                SPropValue(proptag, d)
                            )
                else:
                    value = self.value
                    unit = ''
                    if [x for x in ('KB', 'MB', 'GB') if value.endswith(x)]:
                        value, unit = value[:-2], value[-2:]

                    if PROP_TYPE(proptag) in (PT_FLOAT, PT_DOUBLE):
                        value = float(value)
                    else:
                        value = int(value)

                    if unit == 'KB':
                        value *= 1024
                    elif unit == 'MB':
                        value *= 1024**2
                    elif unit == 'GB':
                        value *= 1024**3

                    restr = SPropertyRestriction(
                                OP_RELOP[self.op],
                                proptag,
                                SPropValue(proptag, value)
                            )

            # contains/equals operator
            elif self.op in (':', '='):
                if PROP_TYPE(proptag) == PT_UNICODE:
                    restr = SContentRestriction(
                                FL_SUBSTRING | FL_IGNORECASE,
                                proptag,
                                SPropValue(proptag, self.value)
                            )

                elif flag or PROP_TYPE(proptag) == PT_BOOLEAN:
                    if flag:
                        restr = SBitMaskRestriction(
                                    BMR_NEZ if self.value in ('yes', 'true') else BMR_EQZ,
                                    proptag,
                                    flag
                                )
                    else:
                        restr = SPropertyRestriction(
                                    RELOP_EQ,
                                    proptag,
                                    SPropValue(proptag, self.value in ('yes', 'true'))
                                )

                elif PROP_TYPE(proptag) == PT_MV_UNICODE:
                    proptag2 = (proptag ^ PT_MV_UNICODE) | PT_UNICODE # funky!
                    restr = SContentRestriction(
                                FL_SUBSTRING | FL_IGNORECASE,
                                proptag,
                                SPropValue(proptag2, self.value)
                            )

                elif PROP_TYPE(proptag) in (PT_SHORT, PT_LONG, PT_LONGLONG, PT_FLOAT, PT_DOUBLE):
                    conv = float if PROP_TYPE(proptag) in (PT_FLOAT, PT_DOUBLE) else int
                    if '..' in self.value:
                        val1, val2 = self.value.split('..')
                        restr = SAndRestriction([
                            SPropertyRestriction(
                                RELOP_GE,
                                proptag,
                                SPropValue(proptag, conv(val1))
                            ),
                            SPropertyRestriction(
                                RELOP_LT,
                                proptag,
                                SPropValue(proptag, conv(val2))
                            )
                        ])
                    else:
                        restr = SPropertyRestriction(
                                    RELOP_EQ,
                                    proptag,
                                    SPropValue(proptag, conv(self.value))
                                )

                elif PROP_TYPE(proptag) == PT_SYSTIME:
                    if self.value == 'today':
                        d = datetime.datetime.now().date()
                        d2 = d + datetime.timedelta(days=1)
                        restr = _interval_restriction(proptag, d, d2)

                    elif self.value == 'yesterday':
                        d2 = datetime.datetime.now().date()
                        d = d2 - datetime.timedelta(days=1)
                        restr = _interval_restriction(proptag, d, d2)

                    elif self.value == 'this week':
                        d2 = datetime.datetime.now()
                        d = d2.date() - datetime.timedelta(days=d2.weekday())
                        restr = _interval_restriction(proptag, d, d2)

                    elif self.value == 'this month':
                        d2 = datetime.datetime.now()
                        d = d2.date() - datetime.timedelta(days=d2.day-1)
                        restr = _interval_restriction(proptag, d, d2)

                    elif self.value == 'last month':
                        now = datetime.datetime.now()
                        d2 = now.date() - datetime.timedelta(days=now.day-1)
                        d = (d2 - datetime.timedelta(days=1)).replace(day=1)
                        restr = _interval_restriction(proptag, d, d2)

                    elif self.value == 'this year':
                        d2 = datetime.datetime.now()
                        d = datetime.datetime(d2.year, 1, 1)
                        restr = _interval_restriction(proptag, d, d2)

                    elif self.value == 'last year':
                        now = datetime.datetime.now()
                        d2 = datetime.datetime(now.year, 1, 1)
                        d = datetime.datetime(d2.year-1, 1, 1)
                        restr = _interval_restriction(proptag, d, d2)

                    elif '..' in self.value:
                        date1, date2 = self.value.split('..') # TODO hours etc
                        d = dateutil.parser.parse(date1, dayfirst=True)
                        d2 = dateutil.parser.parse(date2, dayfirst=True)
                        restr = _interval_restriction(proptag, d, d2)

                    else:
                        d = dateutil.parser.parse(self.value, dayfirst=True) # TODO hours etc
                        d2 = d + datetime.timedelta(days=1)
                        restr = _interval_restriction(proptag, d, d2)

            # turn restriction into sub-restriction
            if subobj:
                if recipient_type is not None:
                    restr = SAndRestriction([
                        restr,
                        SPropertyRestriction(
                                RELOP_EQ,
                                PR_RECIPIENT_TYPE,
                                SPropValue(PR_RECIPIENT_TYPE, recipient_type)
                        )
                    ])
                restr = SSubRestriction(subobj, restr)

        else:
            defaults = [(store._name_id(proptag[:3]) | proptag[3])
                           if isinstance(proptag, tuple) else proptag
                               for proptag in DEFAULT_PROPTAGS[type_]]
            restr = SOrRestriction([
                       SContentRestriction(
                           FL_SUBSTRING | FL_IGNORECASE,
                           p,
                           SPropValue(p, self.value)
                       ) for p in defaults
                   ])

        if self.sign == '-':
            restr = SNotRestriction(restr)

        return restr
Beispiel #9
0
    def prop_restriction(self, proptag, flag):
        # comparison operator
        if self.op in ('<', '>', '>=', '<=', '<>'):
            if PROP_TYPE(proptag) == PT_SYSTIME:
                d = dateutil.parser.parse(self.value)
                d = datetime_to_filetime(d)
                restr = SPropertyRestriction(
                            OP_RELOP[self.op],
                            proptag,
                            SPropValue(proptag, d)
                        )
            else:
                value = self.value
                unit = ''
                if [x for x in ('KB', 'MB', 'GB') if value.endswith(x)]:
                    value, unit = value[:-2], value[-2:]

                value = int(value)

                if unit == 'KB':
                    value *= 1024
                elif unit == 'MB':
                    value *= 1024**2
                elif unit == 'GB':
                    value *= 1024**3

                restr = SPropertyRestriction(
                            OP_RELOP[self.op],
                            proptag,
                            SPropValue(proptag, value)
                        )

        # contains/equals operator
        elif self.op in (':', '='):
            if PROP_TYPE(proptag) == PT_UNICODE:
                restr = SContentRestriction(
                            FL_SUBSTRING | FL_IGNORECASE,
                            proptag,
                            SPropValue(proptag, self.value)
                        )

            elif flag or PROP_TYPE(proptag) == PT_BOOLEAN:
                if flag:
                    restr = SBitMaskRestriction(
                                BMR_NEZ if self.value in ('yes', 'true') else BMR_EQZ,
                                proptag,
                                flag
                            )
                else:
                    restr = SPropertyRestriction(
                                RELOP_EQ,
                                proptag,
                                SPropValue(proptag, self.value in ('yes', 'true'))
                            )

            elif PROP_TYPE(proptag) == PT_MV_UNICODE:
                proptag2 = (proptag ^ PT_MV_UNICODE) | PT_UNICODE # funky!
                restr = SContentRestriction(
                            FL_SUBSTRING | FL_IGNORECASE,
                            proptag,
                            SPropValue(proptag2, self.value)
                        )

            elif PROP_TYPE(proptag) in (PT_SHORT, PT_LONG, PT_LONGLONG, PT_FLOAT, PT_DOUBLE):
                conv = float if PROP_TYPE(proptag) in (PT_FLOAT, PT_DOUBLE) else int
                if '..' in self.value:
                    val1, val2 = self.value.split('..')
                    restr = SAndRestriction([
                        SPropertyRestriction(
                            RELOP_GE,
                            proptag,
                            SPropValue(proptag, conv(val1))
                        ),
                        SPropertyRestriction(
                            RELOP_LT,
                            proptag,
                            SPropValue(proptag, conv(val2))
                        )
                    ])
                else:
                    restr = SPropertyRestriction(
                                RELOP_EQ,
                                proptag,
                                SPropValue(proptag, conv(self.value))
                            )

            elif PROP_TYPE(proptag) == PT_SYSTIME:
                if self.value == 'today':
                    d = datetime.datetime.now().date()
                    d2 = d + datetime.timedelta(days=1)
                    restr = _interval_restriction(proptag, d, d2)

                elif self.value == 'yesterday':
                    d2 = datetime.datetime.now().date()
                    d = d2 - datetime.timedelta(days=1)
                    restr = _interval_restriction(proptag, d, d2)

                elif self.value == 'this week':
                    d2 = datetime.datetime.now()
                    d = d2.date() - datetime.timedelta(days=d2.weekday())
                    restr = _interval_restriction(proptag, d, d2)

                elif self.value == 'this month':
                    d2 = datetime.datetime.now()
                    d = d2.date() - datetime.timedelta(days=d2.day-1)
                    restr = _interval_restriction(proptag, d, d2)

                elif self.value == 'last month':
                    now = datetime.datetime.now()
                    d2 = now.date() - datetime.timedelta(days=now.day-1)
                    d = (d2 - datetime.timedelta(days=1)).replace(day=1)
                    restr = _interval_restriction(proptag, d, d2)

                elif self.value == 'this year':
                    d2 = datetime.datetime.now()
                    d = datetime.datetime(d2.year, 1, 1)
                    restr = _interval_restriction(proptag, d, d2)

                elif self.value == 'last year':
                    now = datetime.datetime.now()
                    d2 = datetime.datetime(now.year, 1, 1)
                    d = datetime.datetime(d2.year-1, 1, 1)
                    restr = _interval_restriction(proptag, d, d2)

                elif '..' in self.value:
                    date1, date2 = self.value.split('..') # TODO hours etc
                    d = dateutil.parser.parse(date1)
                    d2 = dateutil.parser.parse(date2)
                    restr = _interval_restriction(proptag, d, d2)

                else:
                    d = dateutil.parser.parse(self.value) # TODO hours etc
                    d2 = d + datetime.timedelta(days=1)
                    restr = _interval_restriction(proptag, d, d2)

        return restr
Beispiel #10
0
    def users(self, remote=False, system=False, parse=True, page_start=None,
              page_limit=None, order=None, hidden=True, inactive=True,
              _server=None, _company=None, query=None):
        """Return all :class:`users <User>` on server.

        :param remote: Include users on remote server nodes (default False)
        :param system: Include system users (default False)
        :param hidden: Include hidden users (default True)
        :param inactive: Include inactive users (default True)
        :param query: Search query (optional)
        """

        # users specified on command-line
        if parse and getattr(self.options, 'users', None):
            for username in self.options.users:
                yield _user.User(username, self)
            return

        # global listing on multitenant setup
        if self.multitenant and not _company:
            if (page_limit is None and page_start is None and \
                query is None and order is None):
                for company in self.companies():
                    for user in company.users(remote=remote, system=system,
                            parse=parse, hidden=hidden, inactive=inactive):
                        yield user
                return
            else:
                raise NotSupportedError('unsupported method of user listing')

        # find right addressbook container (global or for company)
        gab = self.gab

        restriction = SAndRestriction([
            SPropertyRestriction(RELOP_EQ, PR_OBJECT_TYPE,
                SPropValue(PR_OBJECT_TYPE, MAPI_MAILUSER)),
            SPropertyRestriction(RELOP_NE, PR_DISPLAY_TYPE,
                SPropValue(PR_DISPLAY_TYPE, DT_REMOTE_MAILUSER))
        ])

        if _company and _company.name != 'Default':
            htable = gab.GetHierarchyTable(0)
            htable.SetColumns([PR_ENTRYID], TBL_BATCH)
            # TODO(longsleep): Find a way to avoid finding the limited table,
            # if the gab is itself already limited to the same.
            try:
                htable.FindRow(SContentRestriction(
                        FL_FULLSTRING | FL_IGNORECASE,
                        PR_DISPLAY_NAME_W,
                        SPropValue(PR_DISPLAY_NAME_W, _company.name)),
                    BOOKMARK_BEGINNING, 0)
            except MAPIErrorNotFound:
                # If not, found we do not have permission to access that row. and
                # instead fall back to the gab and let it handle access and
                # limits based on user authentication.
                container = gab
            else:
                row = htable.QueryRows(1, 0)[0]
                container = gab.OpenEntry(row[0].Value, None, 0)
        else:
            container = gab

        table = container.GetContentsTable(0)
        table.SetColumns([PR_ENTRYID], MAPI_UNICODE)

        # apply query restriction
        if query is not None:
            store = _store.Store(mapiobj=self.mapistore, server=self)
            restriction.lpRes.append(
                _query_to_restriction(query, 'user', store).mapiobj)

        table.Restrict(restriction, TBL_BATCH)

        # TODO apply order argument here

        def include(user, ecuser):
            return ((system or user.name != 'SYSTEM') and
                    (remote or ecuser.Servername in (self.name, '')) and
                    (hidden or not user.hidden) and
                    (inactive or user.active))

        # TODO simpler/faster if sa.GetUserList could do restrictions,
        # ordering, pagination..
        # since then we can always work with ecuser objects in bulk
        userid_ecuser = None
        if page_limit is None and page_start is None and query is None:
            userid_ecuser = {}
            if _company and _company.name != 'Default':
                ecusers = self.sa.GetUserList(
                    _company._eccompany.CompanyID, MAPI_UNICODE)
            else:
                ecusers = self.sa.GetUserList(None, MAPI_UNICODE)
            for ecuser in ecusers:
                userid_ecuser[ecuser.UserID] = ecuser

                # fast path: just get all users
                if order is None:
                    user = _user.User(server=self, ecuser=ecuser)
                    if include(user, ecuser):
                        yield user
            if order is None:
                return

        # loop over rows and paginate
        pos = 0
        count = 0

        while True:
            rows = table.QueryRows(50, 0)
            if not rows:
                break
            for row in rows:
                userid = row[0].Value
                if userid_ecuser is None:
                    try:
                        user = _user.User(server=self, userid=_benc(userid))
                    except NotFoundError:
                        continue
                else:
                    try:
                        user = _user.User(
                            server=self, ecuser=userid_ecuser[userid])
                    except KeyError:
                        continue

                if include(user, user._ecuser):
                    if page_start is None or pos >= page_start:
                        yield user
                        count += 1
                    if page_limit is not None and count >= page_limit:
                        return
                    pos += 1
Beispiel #11
0
    def occurrences(self, start=None, end=None, page_start=None,
                    page_limit=None, order=None):
        """For applicable folder types (e.g., calendars), return
        all :class:`occurrences <Occurrence>`.

        :param start: start time (optional)
        :param end: end time (optional)
        """
        count = 0
        pos = 0
        if start and end:
            startstamp = time.mktime(start.timetuple())
            endstamp = time.mktime(end.timetuple())

            # TODO use shortcuts and default type (database) to avoid
            # MAPI snake wrestling
            NAMED_PROPS = [MAPINAMEID(PSETID_Appointment, MNID_ID, x)
                           for x in (33285, 33293, 33294, 33315, 33301, 33333, 33334, 33331, 33302)]
            ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS, MAPI_CREATE)
            busystatus = ids[0] | PT_LONG
            startdate = ids[1] | PT_SYSTIME
            enddate = ids[2] | PT_SYSTIME
            recurring = ids[3] | PT_BOOLEAN
            all_day = ids[4] | PT_BOOLEAN
            clip_start = ids[5] | PT_SYSTIME
            clip_end = ids[6] | PT_SYSTIME
            tzinfo = ids[7] | PT_BINARY
            blob = ids[8] | PT_BINARY

            restriction = SOrRestriction([
                # non-recurring: normal start/end
                SAndRestriction([
                    SPropertyRestriction(RELOP_GT, enddate, SPropValue(enddate, unixtime(startstamp))),
                    SPropertyRestriction(RELOP_LT, startdate, SPropValue(startdate, unixtime(endstamp))),
                ]),
                # recurring: range start/end
                SAndRestriction([
                    SPropertyRestriction(RELOP_GT, clip_end, SPropValue(clip_end, unixtime(startstamp))),
                    SPropertyRestriction(RELOP_LT, clip_start, SPropValue(clip_start, unixtime(endstamp))),
                ]),
                # exceptions: exception start/end in attachment
                SAndRestriction([
                    SPropertyRestriction(RELOP_EQ, recurring, SPropValue(recurring, True)),
                    SSubRestriction(
                        PR_MESSAGE_ATTACHMENTS,
                        SAndRestriction([
                            SPropertyRestriction(RELOP_LT,
                                PR_EXCEPTION_STARTTIME,
                                SPropValue(PR_EXCEPTION_STARTTIME, unixtime(endstamp))),
                            SPropertyRestriction(RELOP_GT, PR_EXCEPTION_ENDTIME, SPropValue(PR_EXCEPTION_ENDTIME, unixtime(startstamp))),
                        ])
                    )
                ])
            ])

            # Restrict occurences to real calendar items.
            restriction = SAndRestriction([
                SContentRestriction(FL_PREFIX, PR_MESSAGE_CLASS_W, SPropValue(PR_MESSAGE_CLASS_W, 'IPM.Appointment')),
                restriction,
            ])

            columns = [
                PR_ENTRYID,
                PR_SUBJECT_W,  # watch out: table unicode data is max 255 chars
                PR_LAST_MODIFICATION_TIME,
                PR_CHANGE_KEY,
                startdate,
                enddate,
                recurring,
                all_day,
                busystatus,
                tzinfo,
                blob,  # watch out: can be larger than 255 chars.
            ]

            table = Table(
                self.server,
                self.mapiobj,
                self.mapiobj.GetContentsTable(MAPI_DEFERRED_ERRORS),
                PR_CONTAINER_CONTENTS,
                columns=columns,
            )
            table.mapitable.Restrict(restriction, 0)
            for row in table.rows():
                item = _item.Item(
                    self,
                    entryid=row[0].value,
                    content_flag=self._content_flag,
                    cache=dict(zip(columns, row))
                )
                for occurrence in item.occurrences(start, end):
                    if page_start is None or pos >= page_start:
                        yield occurrence
                        count += 1
                    if page_limit is not None and count >= page_limit:
                        break
                    pos += 1
                if page_limit is not None and count >= page_limit:
                    break

        else:
            for item in self:
                for occurrence in item.occurrences(start, end):
                    if page_start is None or pos >= page_start:
                        yield occurrence
                        count += 1
                    if page_limit is not None and count >= page_limit:
                        break
                    pos += 1
                if page_limit is not None and count >= page_limit:
                    break