Beispiel #1
0
def test_publish_fb(store, freebusy_user):
    eid = store.GetProps([PR_MAILBOX_OWNER_ENTRYID], 0)[0].Value
    update, status = freebusy_user.LoadFreeBusyUpdate([eid], None)
    assert status == 1
    assert update

    timestamp = int(time.time())
    update.PublishFreeBusy([FreeBusyBlock(0, timestamp, 1)])
    update.SaveChanges(unixtime(0), unixtime(timestamp))

    data, status = freebusy_user.LoadFreeBusyData([eid], None)
    start, end = data.GetFBPublishRange()
    assert start
    assert end

    enum = data.EnumBlocks(FileTime(0), FileTime(0xFFFFFFFFFFFFFFFF))
    blocks = enum.Next(100)
    assert blocks
    assert blocks[0].status == 1

    # Reset freebusy
    update.ResetPublishedFreeBusy()
    update.SaveChanges(unixtime(0), unixtime(timestamp))

    data, status = freebusy_user.LoadFreeBusyData([eid], None)
    enum = data.EnumBlocks(FileTime(0), FileTime(0xFFFFFFFFFFFFFFFF))
    blocks = enum.Next(100)
    assert not blocks
Beispiel #2
0
    def occurrences(self, start=None, end=None):
        if start and end:
            startstamp = time.mktime(start.timetuple())
            endstamp = time.mktime(end.timetuple())

            # XXX use shortcuts and default type (database) to avoid MAPI snake wrestling
            NAMED_PROPS = [
                MAPINAMEID(PSETID_Appointment, MNID_ID, x)
                for x in (33293, 33294, 33315)
            ]
            ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS, 0)
            startdate = ids[0] | PT_SYSTIME
            enddate = ids[1] | PT_SYSTIME
            recurring = ids[2] | PT_BOOLEAN

            # only look at non-recurring items which overlap and all recurring items
            restriction = SOrRestriction([
                SAndRestriction([
                    SPropertyRestriction(
                        RELOP_GT, enddate,
                        SPropValue(enddate, unixtime(startstamp))),
                    SPropertyRestriction(
                        RELOP_LT, startdate,
                        SPropValue(startdate, unixtime(endstamp))),
                ]),
                SAndRestriction([
                    SPropertyRestriction(RELOP_EQ, recurring,
                                         SPropValue(recurring, True))
                ])
            ])

            table = Table(
                self.server,
                self.mapiobj,
                self.mapiobj.GetContentsTable(MAPI_DEFERRED_ERRORS),
                PR_CONTAINER_CONTENTS,
                columns=[PR_ENTRYID],
            )
            table.mapitable.Restrict(restriction, 0)
            for row in table.rows():
                entryid = _benc(row[0].value)
                for occurrence in self.item(entryid).occurrences(start, end):
                    yield occurrence

        else:
            for item in self:
                for occurrence in item.occurrences(start, end):
                    yield occurrence
Beispiel #3
0
 def start(self, value):
     if value is None:
         self.store.mapiobj.DeleteProps([PR_EC_OUTOFOFFICE_FROM])
     else:
         value = unixtime(time.mktime(value.timetuple()))
         self.store.mapiobj.SetProps([SPropValue(PR_EC_OUTOFOFFICE_FROM, value)])
     _utils._save(self.store.mapiobj)
Beispiel #4
0
 def start(self, value):
     if value is None:
         self.store.mapiobj.DeleteProps([PR_EC_OUTOFOFFICE_FROM])
     else:
         value = unixtime(time.mktime(value.timetuple()))
         self.store.mapiobj.SetProps(
             [SPropValue(PR_EC_OUTOFOFFICE_FROM, value)])
     self.store.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
Beispiel #5
0
def create_prop(self, mapiobj, proptag, value=None, proptype=None):
    if isinstance(proptag, int) or \
       (isinstance(proptag, str) and ':' not in proptag):
        if isinstance(proptag, str):
            proptag2 = getattr(MAPI.Tags, proptag)
        else:
            proptag2 = proptag
        proptype2 = proptype or PROP_TYPE(proptag)

    else:  # named property
        proptag2, proptype2, _, _ = \
            _name_to_proptag(proptag, mapiobj, proptype)

        if proptype2 is None:
            # TODO exception too general?
            raise Error('Missing type to create named property')

    if value is None:
        if proptype2 in (PT_STRING8, PT_UNICODE):
            value = ''
        elif proptype2 == PT_BINARY:
            value = b''
        elif proptype2 == PT_SYSTIME:
            value = unixtime(0)
        elif proptype2 & MV_FLAG:
            value = []
        else:
            value = 0
    else:
        if proptype2 == PT_SYSTIME:
            if value.tzinfo is None:
                value = _timezone._to_utc(value, _timezone.LOCAL)
            else:
                value = value.astimezone(_timezone.UTC)
            value = unixtime(calendar.timegm(value.utctimetuple()))

    # handle invalid type versus value.
    # For example proptype=PT_UNICODE and value=True
    try:
        mapiobj.SetProps([SPropValue(proptag2, value)])
        _utils._save(mapiobj)
    except TypeError:
        raise Error('Could not create property, type and value did not match')

    return prop(self, mapiobj, proptag, proptype=proptype2)
Beispiel #6
0
def create_prop(self,
                mapiobj,
                proptag,
                value=None,
                proptype=None):  # XXX selfie
    if _is_int(proptag) or \
       (_is_str(proptag) and ':' not in proptag):
        if _is_str(proptag):
            proptag2 = getattr(MAPI.Tags, proptag)
        else:
            proptag2 = proptag
        proptype2 = proptype or PROP_TYPE(proptag)

    else:  # named property
        proptag2, proptype2, _, _ = _name_to_proptag(proptag, mapiobj,
                                                     proptype)

        if proptype2 is None:
            raise Error('Missing type to create named property'
                        )  # XXX exception too general?

    if value is None:
        if proptype2 in (PT_STRING8, PT_UNICODE):
            value = u''
        elif proptype2 == PT_BINARY:
            value = b''
        elif proptype2 == PT_SYSTIME:
            value = unixtime(0)
        elif proptype2 & MV_FLAG:
            value = []
        else:
            value = 0
    else:
        if proptype2 == PT_SYSTIME:
            value = unixtime(time.mktime(value.timetuple()))

    # handle invalid type versus value. For example proptype=PT_UNICODE and value=True
    try:
        mapiobj.SetProps([SPropValue(proptag2, value)])
        _utils._save(mapiobj)
    except TypeError:
        raise Error('Could not create property, type and value did not match')

    return prop(self, mapiobj, proptag, proptype=proptype2)
Beispiel #7
0
 def value(self, value):
     self._value = value
     if self.type_ == PT_SYSTIME:
         # Ensure that time is stored as UTC.
         if value.tzinfo is None:
             value = _timezone._to_utc(value, _timezone.LOCAL)
         else:
             value = value.astimezone(_timezone.UTC)
         value = unixtime(calendar.timegm(value.utctimetuple()))
     self._parent_mapiobj.SetProps([SPropValue(self.proptag, value)])
     _utils._save(self._parent_mapiobj)
Beispiel #8
0
def test_mvtypes2(store, message):
    props = [
            SPropValue(PROP_TAG(PT_MV_SHORT, 0x6601), [-1, -2, -3]),
            SPropValue(PROP_TAG(PT_MV_LONG, 0x6602), [-1, -2, -3]),
            SPropValue(PROP_TAG(PT_MV_FLOAT, 0x6603), [-1, -2, -3]),
            SPropValue(PROP_TAG(PT_MV_DOUBLE, 0x6604), [-1, -2, -3]),
            SPropValue(PROP_TAG(PT_MV_CURRENCY, 0x6605), [-1, -2, -3]),
            SPropValue(PROP_TAG(PT_MV_APPTIME, 0x6606), [-1, -2, -3]),
            SPropValue(PROP_TAG(PT_MV_LONGLONG, 0x6607), [-1, -2, -3]),
            SPropValue(PROP_TAG(PT_MV_STRING8, 0x6608), [b'', b'', b'']),
            SPropValue(PROP_TAG(PT_MV_UNICODE, 0x6609), ['', '', '']),
            SPropValue(PROP_TAG(PT_MV_SYSTIME, 0x660a), [unixtime(0), unixtime(0), unixtime(0)]),
            SPropValue(PROP_TAG(PT_MV_CLSID, 0x660b), [b'0000000000000000', b'AAAAAAAAAAAAAAAA', b'FFFFFFFFFFFFFFFF']),
            SPropValue(PROP_TAG(PT_MV_BINARY, 0x660c), [b'', b'', b''])
    ]

    message.SetProps(props)
    message.SaveChanges(0)

    entryidprops = message.GetProps([PR_ENTRYID], 0)
    entryid = entryidprops[0].Value
    message = store.OpenEntry(entryid, None, 0)

    results = message.GetProps([
        PROP_TAG(PT_MV_SHORT, 0x6601),
        PROP_TAG(PT_MV_LONG, 0x6602),
        PROP_TAG(PT_MV_FLOAT, 0x6603),
        PROP_TAG(PT_MV_DOUBLE, 0x6604),
        PROP_TAG(PT_MV_CURRENCY, 0x6605),
        PROP_TAG(PT_MV_APPTIME, 0x6606),
        PROP_TAG(PT_MV_LONGLONG, 0x6607),
        PROP_TAG(PT_MV_STRING8, 0x6608),
        PROP_TAG(PT_MV_UNICODE, 0x6609),
        PROP_TAG(PT_MV_SYSTIME, 0x660a),
        PROP_TAG(PT_MV_CLSID, 0x660b),
        PROP_TAG(PT_MV_BINARY, 0x660c)], 0)

    assert results == props
Beispiel #9
0
def test_mvprops(store, message):
    props = [
            SPropValue(PROP_TAG(PT_MV_SHORT, 0x6601), [1, 2, 3]),
            SPropValue(PROP_TAG(PT_MV_LONG, 0x6602), [1, 2, 3]),
            SPropValue(PROP_TAG(PT_MV_FLOAT, 0x6603), [1, 2, 3]),
            SPropValue(PROP_TAG(PT_MV_DOUBLE, 0x6604), [1, 2, 3]),
            SPropValue(PROP_TAG(PT_MV_CURRENCY, 0x6605), [1, 2, 3]),
            SPropValue(PROP_TAG(PT_MV_APPTIME, 0x6606), [1, 2, 3]),
            SPropValue(PROP_TAG(PT_MV_LONGLONG, 0x6607), [1, 2, 3]),
            SPropValue(PROP_TAG(PT_MV_STRING8, 0x6608), [b'a', b'b', b'c']),
            SPropValue(PROP_TAG(PT_MV_UNICODE, 0x6609), ['こん', 'に', 'ちは']),
            SPropValue(PROP_TAG(PT_MV_SYSTIME, 0x660a), [unixtime(0), unixtime(1), unixtime(2)]),
            SPropValue(PROP_TAG(PT_MV_CLSID, 0x660b), [b'1234567890123456', b'6543210987654321', b'0000000000000000']),
            SPropValue(PROP_TAG(PT_MV_BINARY, 0x660c), [b'bin', b'', b'data'])]

    message.SetProps(props)
    message.SaveChanges(0)

    entryidprops = message.GetProps([PR_ENTRYID], 0)
    entryid = entryidprops[0].Value
    message = store.OpenEntry(entryid, None, 0)

    results = message.GetProps([
                                PROP_TAG(PT_MV_SHORT, 0x6601),
                                PROP_TAG(PT_MV_LONG, 0x6602),
                                PROP_TAG(PT_MV_FLOAT, 0x6603),
                                PROP_TAG(PT_MV_DOUBLE, 0x6604),
                                PROP_TAG(PT_MV_CURRENCY, 0x6605),
                                PROP_TAG(PT_MV_APPTIME, 0x6606),
                                PROP_TAG(PT_MV_LONGLONG, 0x6607),
                                PROP_TAG(PT_MV_STRING8, 0x6608),
                                PROP_TAG(PT_MV_UNICODE, 0x6609),
                                PROP_TAG(PT_MV_SYSTIME, 0x660a),
                                PROP_TAG(PT_MV_CLSID, 0x660b),
                                PROP_TAG(PT_MV_BINARY, 0x660c)], 0)

    assert results == props
Beispiel #10
0
def test_types2(store, message):
    props = [
            SPropValue(PROP_TAG(PT_NULL, 0x6601), 0),
            SPropValue(PROP_TAG(PT_SHORT, 0x6602), -1),
            SPropValue(PROP_TAG(PT_LONG, 0x6603), -2),
            SPropValue(PROP_TAG(PT_FLOAT, 0x6604), -3),
            SPropValue(PROP_TAG(PT_DOUBLE, 0x6605), -4),
            SPropValue(PROP_TAG(PT_CURRENCY, 0x6606), -5),
            SPropValue(PROP_TAG(PT_APPTIME, 0x6607), -6),
            SPropValue(PROP_TAG(PT_BOOLEAN, 0x6608), False),
            SPropValue(PROP_TAG(PT_LONGLONG, 0x6609), -7),
            SPropValue(PROP_TAG(PT_STRING8, 0x6610), b''),
            SPropValue(PROP_TAG(PT_UNICODE, 0x6611), u'こんにちは'),
            SPropValue(PROP_TAG(PT_SYSTIME, 0x6612), unixtime(0)),
            SPropValue(PROP_TAG(PT_CLSID, 0x6613), b'1234567890123456'),
            SPropValue(PROP_TAG(PT_BINARY, 0x6614), b'')]

    message.SetProps(props)
    message.SaveChanges(0)

    entryidprops = message.GetProps([PR_ENTRYID], 0)
    entryid = entryidprops[0].Value
    message = store.OpenEntry(entryid, None, 0)

    results = message.GetProps([
                                PROP_TAG(PT_NULL, 0x6601),
                                PROP_TAG(PT_SHORT, 0x6602),
                                PROP_TAG(PT_LONG, 0x6603),
                                PROP_TAG(PT_FLOAT, 0x6604),
                                PROP_TAG(PT_DOUBLE, 0x6605),
                                PROP_TAG(PT_CURRENCY, 0x6606),
                                PROP_TAG(PT_APPTIME, 0x6607),
                                PROP_TAG(PT_BOOLEAN, 0x6608),
                                PROP_TAG(PT_LONGLONG, 0x6609),
                                PROP_TAG(PT_STRING8, 0x6610),
                                PROP_TAG(PT_UNICODE, 0x6611),
                                PROP_TAG(PT_SYSTIME, 0x6612),
                                PROP_TAG(PT_CLSID, 0x6613),
                                PROP_TAG(PT_BINARY, 0x6614)], 0)

    props.remove(SPropValue(PROP_TAG(PT_NULL, 0x6601), 0))
    props.insert(0, SPropValue(PROP_TAG(PT_ERROR, 0x6601), MAPI_E_NOT_FOUND))

    assert results == props
Beispiel #11
0
    def occurrences(self,
                    start=None,
                    end=None,
                    page_start=None,
                    page_limit=None,
                    order=None):
        count = 0
        pos = 0
        if start and end:
            startstamp = time.mktime(start.timetuple())
            endstamp = time.mktime(end.timetuple())

            # XXX 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)
            ]
            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

            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))),
                        ]))
                ])
            ])

            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
            ]

            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
Beispiel #12
0
    def _update_embedded(self, basedate, message, item=None, copytags=None, create=False, **kwargs):
        basetime = basedate + datetime.timedelta(minutes=self._starttime_offset)
        cal_item = self.item

        item2 = item or cal_item
        if copytags:
            props = item2.mapiobj.GetProps(copytags, 0)
            message.mapiobj.SetProps(props)
        elif not kwargs:
            props = [p.mapiobj for p in item2.props() if p.proptag != PR_ICON_INDEX]
            message.mapiobj.SetProps(props)
            message.recurring = False

        if not item:
            if kwargs:
                if 'start' in kwargs:
                    message[PidLidAppointmentStartWhole] = kwargs['start']
                if 'end' in kwargs:
                    message[PidLidAppointmentEndWhole] = kwargs['end']
            else:
                message[PidLidAppointmentStartWhole] = basedate + datetime.timedelta(minutes=self._starttime_offset)
                message[PidLidAppointmentEndWhole] = basedate + datetime.timedelta(minutes=self._endtime_offset)

        message[PR_MESSAGE_CLASS_W] = u'IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}'
        message[PidLidExceptionReplaceTime] = basetime

        intended_busystatus = cal_item.get(PidLidIntendedBusyStatus) # XXX tentative? merge with modify_exc?
        if intended_busystatus is not None:
            message[PidLidBusyStatus] = intended_busystatus

        sub_type = cal_item.get(PidLidAppointmentSubType)
        if sub_type is not None:
            message[PidLidAppointmentSubType] = sub_type

        props = [
            SPropValue(PR_ATTACHMENT_FLAGS, 2), # XXX cannot find spec
            SPropValue(PR_ATTACHMENT_HIDDEN, True),
            SPropValue(PR_ATTACHMENT_LINKID, 0),
            SPropValue(PR_ATTACH_FLAGS, 0),
            SPropValue(PR_ATTACH_METHOD, ATTACH_EMBEDDED_MSG),
            SPropValue(PR_DISPLAY_NAME_W, u'Exception'),
        ]

        if 'subject' in kwargs:
            props.append(SPropValue(PR_SUBJECT_W, kwargs['subject']))

        if 'location' in kwargs:
            message[PidLidLocation] = kwargs['location']

        if item is None: # TODO pick up kwargs['start/end']
            start = basetime
            end = basetime + datetime.timedelta(minutes=self._endtime_offset-self._starttime_offset)
        else:
            start = message.get(PidLidAppointmentStartWhole)
            end = message.prop(PidLidAppointmentEndWhole).value

        if start is not None:
            start_local = unixtime(time.mktime(_timezone._from_utc(start, self._tzinfo).timetuple())) # XXX why local??
            props.append(SPropValue(PR_EXCEPTION_STARTTIME, start_local))

        if end is not None:
            end_local = unixtime(time.mktime(_timezone._from_utc(end, self._tzinfo).timetuple())) # XXX why local??
            props.append(SPropValue(PR_EXCEPTION_ENDTIME, end_local))

        message._attobj.SetProps(props)
        if not create: # XXX php bug?
            props = props[:-2]
        message.mapiobj.SetProps(props)

        if 'canceled' in kwargs:
            message[PidLidAppointmentStateFlags] |= ASF_CANCELED

        _utils._save(message.mapiobj)
        _utils._save(message._attobj)
Beispiel #13
0
    def _update_embedded(self,
                         basedate,
                         message,
                         item,
                         copytags=None,
                         create=False):
        basetime = basedate + datetime.timedelta(minutes=self.starttime_offset)
        cal_item = self.item

        if copytags:
            props = item.mapiobj.GetProps(copytags, 0)
        else:  # XXX remove?
            props = [
                p.mapiobj for p in item.props() if p.proptag != PR_ICON_INDEX
            ]

        message.mapiobj.SetProps(props)

        message[
            PR_MESSAGE_CLASS_W] = u'IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}'
        message[PidLidExceptionReplaceTime] = basetime

        intended_busystatus = cal_item.get(
            PidLidIntendedBusyStatus)  # XXX tentative? merge with modify_exc?
        if intended_busystatus is not None:
            message[PidLidBusyStatus] = intended_busystatus

        sub_type = cal_item.get(PidLidAppointmentSubType)
        if sub_type is not None:
            message[PidLidAppointmentSubType] = sub_type

        props = [
            SPropValue(PR_ATTACHMENT_FLAGS, 2),  # XXX cannot find spec
            SPropValue(PR_ATTACHMENT_HIDDEN, True),
            SPropValue(PR_ATTACHMENT_LINKID, 0),
            SPropValue(PR_ATTACH_FLAGS, 0),
            SPropValue(PR_ATTACH_METHOD, ATTACH_EMBEDDED_MSG),
            SPropValue(PR_DISPLAY_NAME_W, u'Exception'),
        ]

        start = message.get(PidLidAppointmentStartWhole)
        if start is not None:
            start_local = unixtime(
                time.mktime(_utils._from_gmt(
                    start, self.tz).timetuple()))  # XXX why local??
            props.append(SPropValue(PR_EXCEPTION_STARTTIME, start_local))

        end = message.prop(PidLidAppointmentEndWhole).value
        if end is not None:
            end_local = unixtime(
                time.mktime(_utils._from_gmt(
                    end, self.tz).timetuple()))  # XXX why local??
            props.append(SPropValue(PR_EXCEPTION_ENDTIME, end_local))

        message._attobj.SetProps(props)
        if not create:  # XXX php bug?
            props = props[:-2]
        message.mapiobj.SetProps(props)

        message.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
        message._attobj.SaveChanges(KEEP_OPEN_READWRITE)
Beispiel #14
0
def sync(server, syncobj, importer, state, log, max_changes, associated=False, window=None, begin=None, end=None, stats=None):
    importer = TrackingContentsImporter(server, importer, log, stats)
    exporter = syncobj.OpenProperty(PR_CONTENTS_SYNCHRONIZER, IID_IExchangeExportChanges, 0, 0)

    stream = IStream()
    stream.Write(_bdec(state))
    stream.Seek(0, STREAM_SEEK_SET)

    restriction = None
    if window:
        # sync window of last N seconds
        propval = SPropValue(PR_MESSAGE_DELIVERY_TIME, unixtime(int(time.time()) - window))
        restriction = SPropertyRestriction(RELOP_GE, PR_MESSAGE_DELIVERY_TIME, propval)

    elif begin or end:
        restrs = []
        if begin:
            propval = SPropValue(PR_MESSAGE_DELIVERY_TIME, unixtime(time.mktime(begin.timetuple())))
            restrs.append(SPropertyRestriction(RELOP_GE, PR_MESSAGE_DELIVERY_TIME, propval))
        if end:
            propval = SPropValue(PR_MESSAGE_DELIVERY_TIME, unixtime(time.mktime(end.timetuple())))
            restrs.append(SPropertyRestriction(RELOP_LT, PR_MESSAGE_DELIVERY_TIME, propval))
        if len(restrs) == 1:
            restriction = restrs[0]
        else:
            restriction = SAndRestriction(restrs)

    flags = SYNC_NORMAL | SYNC_UNICODE
    if associated:
        flags |= SYNC_ASSOCIATED
    try:
        exporter.Config(stream, flags, importer, restriction, None, None, 0)
    except MAPIErrorNotFound: # syncid purged because of 'sync_lifetime' option in server.cfg: get new syncid.
        if log:
            log.warn("Sync state does not exist on server (anymore); requesting new one")

        syncid, changeid = struct.unpack('<II', _bdec(state))
        stream = IStream()
        stream.Write(struct.pack('<II', 0, changeid))
        stream.Seek(0, STREAM_SEEK_SET)

        exporter.Config(stream, flags, importer, restriction, None, None, 0)

    step = retry = changes = 0
    sleep_time = 0.4

    while True:
        try:
            try:
                (steps, step) = exporter.Synchronize(step)
            finally:
                importer.skip = False

            changes += 1
            retry = 0

            if (steps == step) or (max_changes and changes >= max_changes):
                break

        except MAPIError as e:
            if log:
                log.warn("Received a MAPI error or timeout (error=0x%x, retry=%d/5)", e.hr, retry)

            time.sleep(sleep_time)

            if sleep_time < 5.0:
                sleep_time *= 2.0

            if retry < 5:
                retry += 1
            else:
                if log:
                    log.error("Too many retries, skipping change")
                if stats:
                    stats['errors'] += 1

                importer.skip = True # in case of a timeout or other issue, try to skip the change after trying several times

                retry = 0

    exporter.UpdateState(stream)

    stream.Seek(0, STREAM_SEEK_SET)
    return _benc(stream.Read(0xFFFFF))
Beispiel #15
0
def test_Y10K(item):
    # datetime can't handle 4+ digit years, so we cut them off at 9999-1-1
    value = unixtime(10000 * 365 * 24 * 3600)
    item.mapiobj.SetProps([SPropValue(PR_MESSAGE_DELIVERY_TIME, value)])
    item.mapiobj.SaveChanges(0)
    assert item.prop(PR_MESSAGE_DELIVERY_TIME).value == datetime(9999, 1, 1)
Beispiel #16
0
 def value(self, value):
     self._value = value
     if self.type_ == PT_SYSTIME:
         value = unixtime(time.mktime(value.timetuple()))
     self._parent_mapiobj.SetProps([SPropValue(self.proptag, value)])
     _utils._save(self._parent_mapiobj)
Beispiel #17
0
def sync(server,
         syncobj,
         importer,
         state,
         max_changes,
         associated=False,
         window=None,
         begin=None,
         end=None,
         stats=None):
    log = server.log

    importer = TrackingContentsImporter(server, importer, stats)
    exporter = syncobj.OpenProperty(PR_CONTENTS_SYNCHRONIZER,
                                    IID_IExchangeExportChanges, 0, 0)

    stream = IStream()
    stream.Write(_bdec(state))
    stream.Seek(0, STREAM_SEEK_SET)

    restriction = None
    if window:
        # sync window of last N seconds
        propval = SPropValue(PR_MESSAGE_DELIVERY_TIME,
                             unixtime(int(time.time()) - window))
        restriction = SPropertyRestriction(RELOP_GE, PR_MESSAGE_DELIVERY_TIME,
                                           propval)

    elif begin or end:
        restrs = []
        if begin:
            propval = SPropValue(PR_MESSAGE_DELIVERY_TIME,
                                 unixtime(time.mktime(begin.timetuple())))
            restrs.append(
                SPropertyRestriction(RELOP_GE, PR_MESSAGE_DELIVERY_TIME,
                                     propval))
        if end:
            propval = SPropValue(PR_MESSAGE_DELIVERY_TIME,
                                 unixtime(time.mktime(end.timetuple())))
            restrs.append(
                SPropertyRestriction(RELOP_LT, PR_MESSAGE_DELIVERY_TIME,
                                     propval))
        if len(restrs) == 1:
            restriction = restrs[0]
        else:
            restriction = SAndRestriction(restrs)

    flags = SYNC_NORMAL | SYNC_UNICODE | SYNC_READ_STATE
    if associated:
        flags |= SYNC_ASSOCIATED
    try:
        if TESTING and os.getenv('PYKO_TEST_NOT_FOUND'):
            raise MAPIErrorNotFound()
        exporter.Config(stream, flags, importer, restriction, None, None, 0)
    except MAPIErrorNotFound:  # syncid purged because of 'sync_lifetime' option in server.cfg: get new syncid.
        log.warn(
            "Sync state does not exist on server (anymore); requesting new one"
        )

        syncid, changeid = struct.unpack('<II', _bdec(state))
        stream = IStream()
        stream.Write(struct.pack('<II', 0, changeid))
        stream.Seek(0, STREAM_SEEK_SET)

        exporter.Config(stream, flags, importer, restriction, None, None, 0)

    step = retry = changes = 0
    sleep_time = 0.4

    while True:
        try:
            try:
                if TESTING and os.getenv(
                        'PYKO_TEST_NETWORK_ERROR') and not importer.skip:
                    raise MAPIErrorNetworkError()
                (steps, step) = exporter.Synchronize(step)
            finally:
                importer.skip = False

            changes += 1
            retry = 0

            if (steps == step) or (max_changes and changes >= max_changes):
                break

        except MAPIError as e:
            log.warn(
                "Received a MAPI error or timeout (error=0x%x, retry=%d/5)",
                e.hr, retry)

            time.sleep(sleep_time)

            if sleep_time < 5.0:
                sleep_time *= 2.0

            if retry < 5:
                retry += 1
            else:
                log.error("Too many retries, skipping change")
                if stats is not None:
                    stats['errors'] += 1

                importer.skip = True  # in case of a timeout or other issue, try to skip the change after trying several times

                retry = 0

    exporter.UpdateState(stream)

    stream.Seek(0, STREAM_SEEK_SET)

    state = stream.Read(0xFFFFF)

    # because changes may be reordered for efficiency, we are not always
    # linearly following the change journal. so the current state cannot
    # always be represented as a single change id. instead, the current state
    # may contain changes which have been synced, relative to a certain
    # change id (so we have synced until this change id, plus these changes).

    # in pyko though, we always sync until there are no further changes,
    # so this should normally not occur.

    # TODO add an ICS flag to disable reordering!

    if len(state) != 8:
        log.error('sync state %d bytes, expect problems', len(state))

    return _benc(state)
Beispiel #18
0
 def set_value(self, value):
     self._value = value
     if self.type_ == PT_SYSTIME:
         value = unixtime(time.mktime(value.timetuple()))
     self._parent_mapiobj.SetProps([SPropValue(self.proptag, value)])
     self._parent_mapiobj.SaveChanges(KEEP_OPEN_READWRITE)