Ejemplo n.º 1
0
    def occurrences(self, start=None, end=None):  # XXX fit-to-period
        tz = self.item.get_value(PidLidTimeZoneStruct)

        recurrences = self.recurrences
        if start and end:
            recurrences = recurrences.between(_utils._from_gmt(start, tz),
                                              _utils._from_gmt(end, tz))

        start_exc_ext = {}
        for exc, ext in zip(self.exceptions, self.extended_exceptions):
            start_exc_ext[exc['start_datetime']] = exc, ext

        for d in recurrences:
            startdatetime_val = _utils.unixtime_to_rectime(
                time.mktime(d.timetuple()))

            subject = self.item.subject
            location = self.item.location
            if startdatetime_val in start_exc_ext:
                exc, ext = start_exc_ext[startdatetime_val]
                minutes = exc['end_datetime'] - startdatetime_val
                subject = ext.get('subject', subject)
                location = ext.get('location', location)
            else:
                minutes = self.endtime_offset - self.starttime_offset

            d = _utils._to_gmt(d, tz)

            occ = Occurrence(self.item, d,
                             d + datetime.timedelta(minutes=minutes), subject,
                             location)
            if (not start or occ.end > start) and (not end or occ.start < end):
                yield occ
Ejemplo n.º 2
0
    def delete_exception(self, basedate, item, copytags):
        tz = item.get(PidLidTimeZoneStruct)

        basedate2 = _utils._from_gmt(basedate, tz)
        basedate_val = _utils.unixtime_to_rectime(
            time.mktime(basedate2.timetuple()))

        if self.is_exception(basedate):
            self.modify_exception(basedate, item, copytags)

            for i, exc in enumerate(self.exceptions):
                if exc['original_start_date'] == basedate_val:
                    break

            self.modified_instance_count -= 1
            self.modified_instance_dates = [
                m for m in self.modified_instance_dates
                if m != exc['start_datetime']
            ]

            del self.exceptions[i]
            del self.extended_exceptions[i]

        else:
            self.deleted_instance_count += 1

            self.deleted_instance_dates.append(basedate_val)
            self.deleted_instance_dates.sort()

        self._save()
        self._update_calitem()
Ejemplo n.º 3
0
    def create_exception2(self, basedate):
        # TODO merge with create_exception
        # TODO create embedded item

        tz = self.item.get(PidLidTimeZoneStruct)

        basedate = _utils._from_gmt(basedate, tz)
        basedate_val = _utils.unixtime_to_rectime(
            time.mktime(basedate.timetuple())) - self.starttime_offset

        # update blob
        self.deleted_instance_count += 1
        self.deleted_instance_dates.append(basedate_val)
        self.deleted_instance_dates.sort()

        self.modified_instance_count += 1
        self.modified_instance_dates.append(basedate_val)
        self.modified_instance_dates.sort()

        exception = {
            'start_datetime': basedate_val + self.starttime_offset,
            'end_datetime': basedate_val + self.starttime_offset + 30,  # TODO
            'original_start_date': basedate_val,
            'override_flags': 0,
        }
        self.exceptions.append(exception)  # no evidence of sorting
        self.extended_exceptions.append({})

        self._save()

        # update calitem
        self._update_calitem()
Ejemplo n.º 4
0
    def create_exception(self, basedate, item, copytags=None, merge=False):
        tz = item.get(PidLidTimeZoneStruct)
        cal_item = self.item

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

        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..)
        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(message, item)
        if organiser and not merge:  # XXX merge -> initialize?
            recips.insert(0, organiser)

        message.mapiobj.ModifyRecipients(MODRECIP_ADD, recips)

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

        # XXX attachments?

        # update blob
        self.deleted_instance_count += 1
        deldate = _utils._from_gmt(basedate, tz)
        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 = _utils._from_gmt(daystart, tz)
        moddate_val = _utils.unixtime_to_rectime(
            time.mktime(localdaystart.timetuple()))
        self.modified_instance_dates.append(moddate_val)
        self.modified_instance_dates.sort()

        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()))

        exception = {}
        extended_exception = {}
        self._update_exceptions(cal_item,
                                message,
                                startdate_val,
                                enddate_val,
                                deldate_val,
                                exception,
                                extended_exception,
                                copytags,
                                create=True)
        self.exceptions.append(exception)  # no evidence of sorting
        self.extended_exceptions.append(extended_exception)

        self._save()

        # update calitem
        self._update_calitem()
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def modify_exception2(self,
                          basedate,
                          subject=None,
                          start=None,
                          end=None,
                          location=None):
        # TODO merge with modify_exception
        tz = self.item.get(PidLidTimeZoneStruct)

        # update embedded item
        for message in self.item.items():  # XXX no cal_item? to helper
            replacetime = message.get(PidLidExceptionReplaceTime)
            if replacetime and replacetime.date() == basedate.date():
                if subject is not None:
                    message.subject = subject
                # TODO set other args
                message._attobj.SaveChanges(KEEP_OPEN_READWRITE)
                break

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

        for i, exception in enumerate(self.exceptions):
            if exception['original_start_date'] in (
                    basedate_val,
                    basedate_val - self.starttime_offset):  # TODO pick one
                extended_exception = self.extended_exceptions[i]
                break

        if subject is not None:
            exception['override_flags'] |= ARO_SUBJECT
            exception['subject'] = subject.encode('cp1252', 'replace')
            extended_exception['subject'] = subject

        if location is not None:
            exception['override_flags'] |= ARO_LOCATION
            exception['location'] = location.encode('cp1252', 'replace')
            extended_exception['location'] = location

        if start:
            startdate_val = _utils.unixtime_to_rectime(
                time.mktime(_utils._from_gmt(start, tz).timetuple()))
            exception['start_datetime'] = startdate_val
            extended_exception['start_datetime'] = startdate_val

        if end:
            enddate_val = _utils.unixtime_to_rectime(
                time.mktime(_utils._from_gmt(end, tz).timetuple()))
            exception['end_datetime'] = enddate_val
            extended_exception['end_datetime'] = enddate_val

        extended_exception['start_datetime'] = exception[
            'start_datetime']  # TODO on creation?
        extended_exception['end_datetime'] = exception['end_datetime']
        extended_exception['original_start_date'] = exception[
            'original_start_date']

        self._save()

        # update calitem
        self._update_calitem()
Ejemplo n.º 7
0
    def modify_exception(self,
                         basedate,
                         item,
                         copytags=None):  # XXX 'item' too MR specific
        tz = item.get(PidLidTimeZoneStruct)
        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)

                icon_index = item.get(PR_ICON_INDEX)
                if not copytags and icon_index is not None:
                    message[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[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:  # 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_exceptions(cal_item,
                                        message,
                                        startdate_val,
                                        enddate_val,
                                        basedate_val,
                                        exception,
                                        extended_exception,
                                        copytags,
                                        create=False)

        self._save()

        # update calitem
        self._update_calitem()