Beispiel #1
0
 def ImportMessageChange(self, props, flags):
     if self.skip:
         raise MAPIError(SYNC_E_IGNORE)
     try:
         entryid = PpropFindProp(props, PR_ENTRYID)
         if self.importer.store:
             mapistore = self.importer.store.mapiobj
         else:
             store_entryid = PpropFindProp(props, PR_STORE_ENTRYID).Value
             store_entryid = WrapStoreEntryID(0, b'zarafa6client.dll', store_entryid[:-4]) + self.server.pseudo_url + b'\x00'
             mapistore = self.server._store2(store_entryid)
         item = _item.Item()
         item.server = self.server
         item.store = _store.Store(mapiobj=mapistore, server=self.server)
         try:
             item.mapiobj = _utils.openentry_raw(mapistore, entryid.Value, 0)
             props = item.mapiobj.GetProps([PR_EC_HIERARCHYID, PR_EC_PARENT_HIERARCHYID, PR_STORE_RECORD_KEY], 0) # XXX properties don't exist?
             item.docid = props[0].Value
             item.storeid = _benc(props[2].Value)
             if hasattr(self.importer, 'update'):
                 self.importer.update(item, flags)
         except (MAPIErrorNotFound, MAPIErrorNoAccess): # XXX, mail already deleted, can we do this in a cleaner way?
             self.log.debug('received change for entryid %s, but it could not be opened', _benc(entryid.Value))
     except Exception:
         self.log.error('could not process change for entryid %s (%r):', _benc(entryid.Value), props)
         self.log.error(traceback.format_exc())
         if self.stats:
             self.stats['errors'] += 1
     raise MAPIError(SYNC_E_IGNORE)
Beispiel #2
0
def _organizer_props(cal_item, item):
    has_organizer = False

    table = cal_item.mapiobj.OpenProperty(
        PR_MESSAGE_RECIPIENTS, IID_IMAPITable, MAPI_UNICODE, 0)
    for row in table.QueryRows(2147483647, 0):
        recipient_flags = PpropFindProp(row, PR_RECIPIENT_FLAGS)
        if (recipient_flags and \
            recipient_flags.Value == (recipOrganizer | recipSendable)):
            has_organizer = True
            break

    if not has_organizer:
        orgprops = [
            SPropValue(PR_ENTRYID,
                item.prop(PR_SENT_REPRESENTING_ENTRYID).value),
            SPropValue(PR_DISPLAY_NAME_W,
                item.prop(PR_SENT_REPRESENTING_NAME_W).value),
            SPropValue(PR_EMAIL_ADDRESS_W,
                item.prop(PR_SENT_REPRESENTING_EMAIL_ADDRESS_W).value),
            SPropValue(PR_RECIPIENT_TYPE, MAPI_TO),
            SPropValue(PR_RECIPIENT_DISPLAY_NAME_W,
                item.prop(PR_SENT_REPRESENTING_NAME_W).value),
            SPropValue(PR_ADDRTYPE_W,
                item.prop(PR_SENT_REPRESENTING_ADDRTYPE_W).value), # TODO php
            SPropValue(PR_RECIPIENT_TRACKSTATUS, 0),
            SPropValue(PR_RECIPIENT_FLAGS, (recipOrganizer | recipSendable)),
        ]
        # TODO not in exception message?
        repr_search_key = item.get(PR_SENT_REPRESENTING_SEARCH_KEY)
        if repr_search_key:
            orgprops.append(SPropValue(PR_SEARCH_KEY, repr_search_key))
        return orgprops
Beispiel #3
0
 def index(self, key):
     """Return key->row dictionary keyed on given column (proptag)."""
     d = {}
     for row in self.mapitable.QueryRows(2147483647, 0):
         d[PpropFindProp(row, key).Value] = \
             dict((c.ulPropTag, c.Value) for c in row)
     return d
Beispiel #4
0
def _organizer_props(cal_item, item):
    has_organizer = False

    table = cal_item.mapiobj.OpenProperty(PR_MESSAGE_RECIPIENTS,
                                          IID_IMAPITable, MAPI_UNICODE, 0)
    for row in table.QueryRows(-1, 0):
        recipient_flags = PpropFindProp(row, PR_RECIPIENT_FLAGS)
        if recipient_flags and recipient_flags.Value == (recipOrganizer |
                                                         recipSendable):  # XXX
            has_organizer = True
            break

    if not has_organizer:
        return [
            SPropValue(PR_ENTRYID,
                       item.prop(PR_SENT_REPRESENTING_ENTRYID).value),
            SPropValue(PR_DISPLAY_NAME_W,
                       item.prop(PR_SENT_REPRESENTING_NAME_W).value),
            SPropValue(PR_EMAIL_ADDRESS_W,
                       item.prop(PR_SENT_REPRESENTING_EMAIL_ADDRESS_W).value),
            SPropValue(PR_RECIPIENT_TYPE, MAPI_TO),
            SPropValue(PR_RECIPIENT_DISPLAY_NAME_W,
                       item.prop(PR_SENT_REPRESENTING_NAME_W).value),
            SPropValue(
                PR_ADDRTYPE_W,
                item.prop(PR_SENT_REPRESENTING_ADDRTYPE_W).value),  # XXX php
            SPropValue(PR_RECIPIENT_TRACKSTATUS, 0),
            SPropValue(PR_RECIPIENT_FLAGS, (recipOrganizer | recipSendable)),
            SPropValue(PR_SEARCH_KEY,
                       item.prop(PR_SENT_REPRESENTING_SEARCH_KEY).value),
        ]
Beispiel #5
0
 def company(self):
     """Store :class:`company <Company>`."""
     if self.server.multitenant:
         table = self.server.sa.OpenUserStoresTable(MAPI_UNICODE)
         table.Restrict(SPropertyRestriction(RELOP_EQ, PR_EC_STOREGUID, SPropValue(PR_EC_STOREGUID, _bdec(self.guid))), TBL_BATCH)
         for row in table.QueryRows(1, 0):
             storetype = PpropFindProp(row, PR_EC_STORETYPE)
             if storetype.Value == ECSTORE_TYPE_PUBLIC:
                 companyname = PpropFindProp(row, PR_EC_USERNAME_W) # XXX bug in ECUserStoreTable.cpp?
                 if not companyname:
                     companyname = PpropFindProp(row, PR_EC_COMPANY_NAME_W) # XXX
             else:
                 companyname = PpropFindProp(row, PR_EC_COMPANY_NAME_W)
             return self.server.company(companyname.Value)
     else:
         return next(self.server.companies())
Beispiel #6
0
 def ImportFolderChange(self, props):
     if hasattr(self.importer, 'update'):
         eid = _benc(PpropFindProp(props, PR_ENTRYID).Value)
         try:
             folder = _folder.Folder(store=self.importer.store, entryid=eid)
         except NotFoundError:
             self.log.debug(
                 "received folderchange but could not find folder with entryid: '%s'",
                 eid)
             return
         self.importer.update(folder)
Beispiel #7
0
 def type_(self):
     """Store type (*private*, *public*, *archive*)."""
     table = self.server.sa.OpenUserStoresTable(MAPI_UNICODE)
     table.Restrict(SPropertyRestriction(RELOP_EQ, PR_EC_STOREGUID,
         SPropValue(PR_EC_STOREGUID, _bdec(self.guid))), TBL_BATCH)
     for row in table.QueryRows(1, 0):
         storetype = PpropFindProp(row, PR_EC_STORETYPE)
         if storetype:
             return {
                 ECSTORE_TYPE_PRIVATE: 'private',
                 ECSTORE_TYPE_ARCHIVE: 'archive',
                 ECSTORE_TYPE_PUBLIC: 'public',
             }[storetype.Value]
Beispiel #8
0
 def _parse_rule(store):
     userids, deletion = [], False
     for rule in store.inbox.rules():
         if PR_RULE_PROVIDER_W in rule.mapirow and PR_RULE_ACTIONS in rule.mapirow:
             if rule.mapirow[PR_RULE_PROVIDER_W] == u'Schedule+ EMS Interface':
                 actions = rule.mapirow[PR_RULE_ACTIONS].lpAction
                 if actions and actions[0].acttype == ACTTYPE.OP_DELEGATE:
                     for addrentry in actions[0].actobj.lpadrlist:
                         entryid = PpropFindProp(addrentry, PR_ENTRYID)
                         if entryid:
                             userids.append(entryid.Value)
                 if len(actions) >= 2 and actions[1].acttype == ACTTYPE.OP_DELETE:
                     deletion = True
     return userids, deletion
Beispiel #9
0
 def stores(self):
     """Return all company :class:`stores <Store>`."""
     if self.server.multitenant:
         table = self.server.sa.OpenUserStoresTable(MAPI_UNICODE)
         restriction = SPropertyRestriction(RELOP_EQ, PR_EC_COMPANY_NAME_W,
             SPropValue(PR_EC_COMPANY_NAME_W, self.name))
         table.Restrict(restriction, TBL_BATCH)
         for row in table.QueryRows(-1, 0):
             prop = PpropFindProp(row, PR_EC_STOREGUID)
             if prop:
                 yield _store.Store(_hex(prop.Value), self.server)
     else:
         for store in self.server.stores():
             yield store
Beispiel #10
0
 def ImportFolderChange(self, props):
     if hasattr(self.importer, 'update'):
         eid = _benc(PpropFindProp(props, PR_ENTRYID).Value)
         folder = _folder.Folder(store=self.importer.store, entryid=eid)
         self.importer.update(folder)
Beispiel #11
0
    def _create_exception(self, basedate, item=None, copytags=None, merge=False, recips_from=None):
        cal_item = self.item

        # create embedded item
        message_flags = MSGFLAG_READ
        if item and item.get(PR_MESSAGE_FLAGS) == 0: # XXX wut/php compat
            message_flags |= MSGFLAG_UNSENT
        message = cal_item.create_item(message_flags, hidden=True)

        self._update_embedded(basedate, message, item, copytags, create=True)

        message[PidLidResponseStatus] = respDeclined | respOrganized # XXX php bug for merge case?
        if copytags:
            message[PidLidBusyStatus] = 0

        # copy over recipients (XXX check php delta stuff..)
        item = item or recips_from
        if item:
            table = item.mapiobj.OpenProperty(PR_MESSAGE_RECIPIENTS, IID_IMAPITable, MAPI_UNICODE, 0)
            table.SetColumns(_meetingrequest.RECIP_PROPS, 0)
            recips = list(table.QueryRows(-1, 0))

            for recip in recips:
                flags = PpropFindProp(recip, PR_RECIPIENT_FLAGS)
                if not flags:
                    recip.append(SPropValue(PR_RECIPIENT_FLAGS, recipExceptionalResponse | recipSendable))

            if copytags:
                for recip in recips:
                    recip.append(SPropValue(PR_RECIPIENT_FLAGS, recipExceptionalDeleted | recipSendable))
                    recip.append(SPropValue(PR_RECIPIENT_TRACKSTATUS, 0))

            organiser = _meetingrequest._organizer_props(cal_item, item)
            if organiser and not merge: # XXX merge -> initialize?
                recips.insert(0, organiser)

            message.mapiobj.ModifyRecipients(MODRECIP_ADD, recips)

        _utils._save(message.mapiobj)
        _utils._save(message._attobj)
        _utils._save(cal_item.mapiobj)

        # XXX attachments?

        # update blob
        self.deleted_instance_count += 1
        deldate = _timezone._from_utc(basedate, self._tzinfo)
        deldate_val = _utils.unixtime_to_rectime(time.mktime(deldate.timetuple()))
        self._deleted_instance_dates.append(deldate_val)
        self._deleted_instance_dates.sort()

        self._modified_instance_count += 1
        moddate = message.prop(PidLidAppointmentStartWhole).value
        daystart = moddate - datetime.timedelta(hours=moddate.hour, minutes=moddate.minute) # XXX different approach in php? seconds?
        localdaystart = _timezone._from_utc(daystart, self._tzinfo)
        moddate_val = _utils.unixtime_to_rectime(time.mktime(localdaystart.timetuple()))
        self._modified_instance_dates.append(moddate_val)
        self._modified_instance_dates.sort()

        exception = {}
        extended_exception = {}
        self._update_exception(cal_item, message, deldate_val, exception, extended_exception, copytags, create=True, orig_item=item)
        self._exceptions.append(exception) # no evidence of sorting
        self._extended_exceptions.append(extended_exception)

        self._save()

        # update calitem
        self._update_calitem()
Beispiel #12
0
 def ImportFolderChange(self, props):
     eid = _benc(PpropFindProp(props, PR_ENTRYID).Value)
     folder = self.importer.store.folder(entryid=eid)
     self.importer.update(folder)
Beispiel #13
0
 def dict_(self, key, value):
     d = {}
     for row in self.mapitable.QueryRows(-1, 0):
         d[PpropFindProp(row, key).Value] = PpropFindProp(row, value).Value
     return d
Beispiel #14
0
    def process_response(self):
        """ Process meeting request response """

        if not self.is_response:
            raise Error('item is not a meeting request response')
        if self._check_processed():
            return

        cal_item = self.calendar_item
        basedate = self.basedate

        # modify calendar item or embedded message (in case of exception)
        attach = None
        message = None
        if basedate:
            if cal_item.recurring:
                recurrence = cal_item.recurrence

                recurrence._update_calitem(
                    self.item)  # XXX via create/modify exception

                if recurrence.is_exception(basedate):
                    message = recurrence.exception_message(basedate)

                    owner_appt_id = self.item.get_value(PR_OWNER_APPT_ID)
                    if owner_appt_id is not None:
                        message.set_value(PR_OWNER_APPT_ID, owner_appt_id)
                    attach = message._attobj
        else:
            message = cal_item
        if not message:
            return

        # update recipient track status
        table = message.mapiobj.OpenProperty(PR_MESSAGE_RECIPIENTS,
                                             IID_IMAPITable, MAPI_UNICODE, 0)
        table.SetColumns(RECIP_PROPS,
                         0)  # XXX why do things get lot witout this

        rows = table.QueryRows(-1, 0)
        for row in rows:
            if self._compare_ab_entryids(
                    PpropFindProp(row, PR_ENTRYID).Value,
                    self.item.prop(PR_SENT_REPRESENTING_ENTRYID).value):
                trackstatus = PpropFindProp(row, PR_RECIPIENT_TRACKSTATUS)
                trackstatus_time = PpropFindProp(
                    row, PR_RECIPIENT_TRACKSTATUS_TIME)

                attendee_crit_change = self.item.get_prop(
                    PidLidAttendeeCriticalChange)
                if trackstatus_time and attendee_crit_change and \
                    attendee_crit_change.mapiobj.Value <= trackstatus_time.Value:
                    continue

                if trackstatus_time:
                    trackstatus_time.Value = attendee_crit_change.mapiobj.Value
                else:
                    row.append(
                        SPropValue(PR_RECIPIENT_TRACKSTATUS_TIME,
                                   attendee_crit_change.mapiobj.Value))

                if trackstatus:
                    trackstatus.Value = self.track_status
                else:
                    row.append(
                        SPropValue(PR_RECIPIENT_TRACKSTATUS,
                                   self.track_status))

                if self.item.get_value(
                        PidLidAppointmentCounterProposal) is True:
                    row.extend([
                        SPropValue(PR_PROPOSED_NEWTIME, True),
                        SPropValue(
                            PR_PROPOSED_NEWTIME_START,
                            self.item.prop(PidLidAppointmentProposedStartWhole
                                           ).mapiobj.Value),
                        SPropValue(
                            PR_PROPOSED_NEWTIME_END,
                            self.item.prop(PidLidAppointmentProposedEndWhole).
                            mapiobj.Value),
                    ])

        message.mapiobj.ModifyRecipients(MODRECIP_MODIFY, rows)

        # counter proposal
        if self.item.get_value(PidLidAppointmentCounterProposal):
            message.set_value(PidLidAppointmentCounterProposal, True)

        # save all the things
        message.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)

        if attach:
            attach.SaveChanges(KEEP_OPEN_READWRITE)
            cal_item.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
Beispiel #15
0
def _create_meetingrequest(cal_item, item, basedate=None):
    # TODO Update the calendar item, for tracking status
    # TODO Set the body of the message like WebApp / OL does.
    # TODO Whitelist properties?

    item2 = item.copy(item.store.outbox)
    cancel = item.canceled

    # remove meeting organizer TODO just copy correct ones? or why is the
    # organizer MAPI_TO?
    table = item2.mapiobj.OpenProperty(
        PR_MESSAGE_RECIPIENTS, IID_IMAPITable, MAPI_UNICODE, 0)
    table.SetColumns(RECIP_PROPS, 0)
    orgs = []
    for row in table.QueryRows(2147483647, 0):
        recipient_flags = PpropFindProp(row, PR_RECIPIENT_FLAGS)
        if recipient_flags and recipient_flags.Value & recipOrganizer:
            orgs.append(row)
    item2.mapiobj.ModifyRecipients(MODRECIP_REMOVE, orgs)

    # set meeting request props
    if cancel:
        item2.message_class = 'IPM.Schedule.Meeting.Canceled'
    else:
        item2.message_class = 'IPM.Schedule.Meeting.Request'

    stateflags = ASF_MEETING | ASF_RECEIVED
    if cancel:
        stateflags |= ASF_CANCELED
        item2.subject = 'Canceled: '+item2.subject
    item2[PidLidAppointmentStateFlags] = stateflags

    # create appointment goid if not there
    cleangoid = cal_item.get(PidLidCleanGlobalObjectId)
    if cleangoid is None:
        cleangoid = _generate_goid()
        cal_item[PidLidGlobalObjectId] = cleangoid
        cal_item[PidLidCleanGlobalObjectId] = cleangoid

    # update sequence props
    sequence = cal_item.get(PidLidAppointmentSequence)
    if sequence is None:
        cal_item[PidLidAppointmentSequence] = 0
        cal_item[PidLidAppointmentLastSequence] = 0
    else:
        cal_item[PidLidAppointmentSequence] = sequence+1
        cal_item[PidLidAppointmentLastSequence] = sequence+1
    item2[PidLidAppointmentSequence] = \
        cal_item[PidLidAppointmentSequence]
    item2[PidLidAppointmentLastSequence] = \
        cal_item[PidLidAppointmentLastSequence]
    item2[PidLidResponseStatus] = respNotResponded

    # set item goids
    item2[PidLidCleanGlobalObjectId] = cleangoid
    if basedate:
        datefield = struct.pack('>H2B',
            basedate.year, basedate.month, basedate.day)
        goid = cleangoid[:16] + datefield + cleangoid[20:]

        item2[PidLidGlobalObjectId] = goid
        item2[PidLidRecurring] = False

        # update for non-exception TODO don't overwrite if exception
        if cancel:
            item2[PidLidAppointmentStartWhole] = basedate
            item2[PidLidAppointmentEndWhole] = \
                basedate + (cal_item.end - cal_item.start)

            item2[PR_START_DATE] = basedate
            item2[PR_END_DATE] = basedate + (cal_item.end - cal_item.start)

            item2[PidLidExceptionReplaceTime] = \
                datetime.datetime(basedate.year, basedate.month, basedate.day)

    return item2
Beispiel #16
0
    def process_response(self):
        """Process meeting request response."""
        if not self.is_response:
            raise Error('item is not a meeting request response')
        if self._check_processed():
            self.log.warning('response already processed')
            return

        cal_item = self.calendar_item
        basedate = self.basedate

        # modify calendar item or embedded message (in case of exception)
        attach = None
        message = None
        if basedate:
            if cal_item.recurring:
                recurrence = cal_item.recurrence

                recurrence._update_calitem() # TODO via create/modify exception

                if recurrence._is_exception(basedate):
                    message = recurrence._exception_message(basedate)

                    owner_appt_id = self.item.get(PR_OWNER_APPT_ID)
                    if owner_appt_id is not None:
                        message[PR_OWNER_APPT_ID] = owner_appt_id
                    attach = message._attobj
        else:
            message = cal_item
        if not message:
            self.log.debug('no appointment matches response')
            return

        # update recipient track status
        table = message.mapiobj.OpenProperty(
            PR_MESSAGE_RECIPIENTS, IID_IMAPITable, MAPI_UNICODE, 0)
        # TODO things seem to get lost without this
        table.SetColumns(RECIP_PROPS, 0)

        rows = table.QueryRows(2147483647, 0)
        for row in rows:
            if self._compare_ab_entryids(
                PpropFindProp(row, PR_ENTRYID).Value,
                self.item.prop(PR_SENT_REPRESENTING_ENTRYID).value
            ):
                trackstatus = PpropFindProp(row,
                    PR_RECIPIENT_TRACKSTATUS)
                trackstatus_time = PpropFindProp(row,
                    PR_RECIPIENT_TRACKSTATUS_TIME)

                attendee_crit_change = \
                    self.item.get_prop(PidLidAttendeeCriticalChange)
                if (trackstatus_time and \
                    attendee_crit_change and \
                    attendee_crit_change.mapiobj.Value <= \
                       trackstatus_time.Value):
                    continue

                if trackstatus_time:
                    trackstatus_time.Value = attendee_crit_change.mapiobj.Value
                else:
                    row.append(SPropValue(PR_RECIPIENT_TRACKSTATUS_TIME,
                                          attendee_crit_change.mapiobj.Value))

                if trackstatus:
                    trackstatus.Value = self.track_status
                else:
                    row.append(SPropValue(
                        PR_RECIPIENT_TRACKSTATUS, self.track_status))

                if self.item.get(PidLidAppointmentCounterProposal) is True:
                    start = self.item.prop(PidLidAppointmentProposedStartWhole)
                    end = self.item.prop(PidLidAppointmentProposedEndWhole)
                    row.extend([
                        SPropValue(PR_PROPOSED_NEWTIME,
                            True),
                        SPropValue(PR_PROPOSED_NEWTIME_START,
                            start.mapiobj.Value),
                        SPropValue(PR_PROPOSED_NEWTIME_END,
                            end.mapiobj.Value),
                    ])

        message.mapiobj.ModifyRecipients(MODRECIP_MODIFY, rows)

        # counter proposal
        if self.item.get(PidLidAppointmentCounterProposal):
            message[PidLidAppointmentCounterProposal] = True

        # save all the things
        _utils._save(message.mapiobj)

        if attach:
            _utils._save(attach)
            _utils._save(cal_item.mapiobj)
Beispiel #17
0
    def _modify_exception(self, basedate, item=None, copytags=None, **kwargs): # XXX 'item' too MR specific
        cal_item = self.item

        # update embedded item
        for message in cal_item.items(): # XXX no cal_item? to helper
            replacetime = message.get(PidLidExceptionReplaceTime)
            if replacetime and replacetime.date() == basedate.date():
                self._update_embedded(basedate, message, item, copytags, **kwargs)

                if item:
                    icon_index = item.get(PR_ICON_INDEX)
                    if not copytags and icon_index is not None:
                        message[PR_ICON_INDEX] = icon_index

                _utils._save(message._attobj)
                break
        else:
            return # XXX exception

        if copytags: # XXX bug in php code? (setallrecipients, !empty..)
            message[PidLidBusyStatus] = 0

            table = message.mapiobj.OpenProperty(PR_MESSAGE_RECIPIENTS, IID_IMAPITable, MAPI_UNICODE, 0)
            table.SetColumns(_meetingrequest.RECIP_PROPS, 0)

            recips = list(table.QueryRows(-1, 0))
            for recip in recips:
                flags = PpropFindProp(recip, PR_RECIPIENT_FLAGS)
                if flags and flags.Value != (recipOrganizer | recipSendable):
                    flags.Value = recipExceptionalDeleted | recipSendable
                    trackstatus = PpropFindProp(recip, PR_RECIPIENT_TRACKSTATUS)
                    if not trackstatus:
                        recip.append(SPropValue(PR_RECIPIENT_TRACKSTATUS, 0))

            message.mapiobj.ModifyRecipients(MODRECIP_MODIFY, recips)

            _utils._save(message.mapiobj)
            _utils._save(message._attobj)
            _utils._save(cal_item.mapiobj)

        # update blob
        basedate_val = _utils.unixtime_to_rectime(time.mktime(_timezone._from_utc(basedate, self._tzinfo).timetuple()))

        startdate = _timezone._from_utc(message.prop(PidLidAppointmentStartWhole).value, self._tzinfo)
        startdate_val = _utils.unixtime_to_rectime(time.mktime(startdate.timetuple()))

        for i, exception in enumerate(self._exceptions):
            if exception['original_start_date'] == basedate_val: # TODO offset, as below?
                current_startdate_val = exception['start_datetime'] - self._starttime_offset

                for j, val in enumerate(self._modified_instance_dates):
                    if val == current_startdate_val:
                        self._modified_instance_dates[j] = startdate_val - self._starttime_offset
                        self._modified_instance_dates.sort()
                        break

                extended_exception = self._extended_exceptions[i]
                self._update_exception(cal_item, message, basedate_val, exception, extended_exception, copytags, create=False, orig_item=item, **kwargs)

        self._save()

        # update calitem
        self._update_calitem()
Beispiel #18
0
 def index(self, key):
     d = {}
     for row in self.mapitable.QueryRows(-1, 0):
         d[PpropFindProp(row, key).Value] = dict(
             (c.ulPropTag, c.Value) for c in row)
     return d
Beispiel #19
0
    def modify_exception(self,
                         basedate,
                         item,
                         copytags=None):  # XXX 'item' too MR specific
        tz = item.get_value(PidLidTimeZoneStruct)
        cal_item = self.item

        # update embedded item
        for message in cal_item.items():  # XXX no cal_item? to helper
            replacetime = message.get_value(PidLidExceptionReplaceTime)
            if replacetime and replacetime.date() == basedate.date():
                self._update_embedded(basedate, message, item, copytags)

                icon_index = item.get_value(PR_ICON_INDEX)
                if not copytags and icon_index is not None:
                    message.set_value(PR_ICON_INDEX, icon_index)

                message._attobj.SaveChanges(KEEP_OPEN_READWRITE)
                break
        else:
            return  # XXX exception

        if copytags:  # XXX bug in php code? (setallrecipients, !empty..)
            message.set_value(PidLidBusyStatus, 0)

            table = message.mapiobj.OpenProperty(PR_MESSAGE_RECIPIENTS,
                                                 IID_IMAPITable, MAPI_UNICODE,
                                                 0)
            table.SetColumns(_meetingrequest.RECIP_PROPS, 0)

            recips = list(table.QueryRows(-1, 0))
            for recip in recips:
                flags = PpropFindProp(recip, PR_RECIPIENT_FLAGS)
                if flags and flags.Value != (recipOrganizer | recipSendable):
                    flags.Value = recipExceptionalDeleted | recipSendable
                    trackstatus = PpropFindProp(recip,
                                                PR_RECIPIENT_TRACKSTATUS)
                    recip.append(SPropValue(PR_RECIPIENT_TRACKSTATUS, 0))

            message.mapiobj.ModifyRecipients(MODRECIP_MODIFY, recips)

            message.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
            message._attobj.SaveChanges(KEEP_OPEN_READWRITE)
            cal_item.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)

        # update blob
        basedate_val = _utils.unixtime_to_rectime(
            time.mktime(_utils._from_gmt(basedate, tz).timetuple()))

        startdate = _utils._from_gmt(
            message.prop(PidLidAppointmentStartWhole).value, tz)
        startdate_val = _utils.unixtime_to_rectime(
            time.mktime(startdate.timetuple()))

        enddate = _utils._from_gmt(
            message.prop(PidLidAppointmentEndWhole).value, tz)
        enddate_val = _utils.unixtime_to_rectime(
            time.mktime(enddate.timetuple()))

        for i, exception in enumerate(self.exceptions):
            if exception['original_start_date'] == basedate_val:
                current_startdate_val = exception[
                    'start_datetime'] - self.starttime_offset

                for j, val in enumerate(self.modified_instance_dates):
                    if val == current_startdate_val:
                        self.modified_instance_dates[
                            j] = startdate_val - self.starttime_offset
                        self.modified_instance_dates.sort()
                        break

                extended_exception = self.extended_exceptions[i]
                self._update_exceptions(cal_item,
                                        message,
                                        startdate_val,
                                        enddate_val,
                                        basedate_val,
                                        exception,
                                        extended_exception,
                                        copytags,
                                        create=False)

        self._save()

        # update calitem
        self._update_calitem(item)