Ejemplo n.º 1
0
    def occurrences(self, start=None, end=None): # XXX fit-to-period
        recurrences = self.recurrences
        if start and end:
            start = _timezone._tz2(start, LOCAL, self._tzinfo)
            end = _timezone._tz2(end, LOCAL, self._tzinfo)
            recurrences = recurrences.between(start, end)

        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(calendar.timegm(d.timetuple()))

            subject = self.item.subject
            location = self.item.location
            exception = False
            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)
                basedate_val = exc['original_start_date']
                exception = True
            else:
                minutes = self._endtime_offset - self._starttime_offset
                basedate_val = startdatetime_val

            d = _timezone._to_utc(d, self._tzinfo)
            e = d + datetime.timedelta(minutes=minutes)

            occ = Occurrence(self.item, d, e, subject, location, basedate_val=basedate_val, exception=exception)
            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 _delete_exception(self, basedate, item, copytags):
        basedate2 = _timezone._from_utc(basedate, self._tzinfo)
        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['original_start_date']]

            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.º 4
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.º 5
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.º 6
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()
Ejemplo n.º 7
0
    def _update_exception(self, cal_item, item, basedate_val, exception, extended_exception, copytags=None, create=False, orig_item=None, **kwargs): # XXX kill copytags, create args, just pass all properties as in php
        # TODO get start/end from cal_item if not in item?

        startdate = kwargs.get('start')
        if orig_item or (startdate is None and 'start_datetime' not in exception):
            startdate = item.get(PidLidAppointmentStartWhole)

        if startdate is not None:
            startdate_val = _utils.unixtime_to_rectime(time.mktime(_timezone._from_utc(startdate, self._tzinfo).timetuple()))
            exception['start_datetime'] = startdate_val

        enddate = kwargs.get('end')
        if orig_item or (enddate is None and 'end_datetime' not in exception):
            enddate = item.get(PidLidAppointmentEndWhole)

        if enddate is not None:
            enddate_val = _utils.unixtime_to_rectime(time.mktime(_timezone._from_utc(enddate, self._tzinfo).timetuple()))
            exception['end_datetime'] = enddate_val

        exception['original_start_date'] = basedate_val # TODO why set again?
        exception['override_flags'] = 0

        extended = False

        subject = kwargs.get('subject')
        if orig_item or (subject is None and 'subject' not in exception):
            subject = item.get(PR_NORMALIZED_SUBJECT_W)
        if subject is not None or 'subject' in exception:
            exception['override_flags'] |= ARO_SUBJECT
        if subject is not None:
            exception['subject'] = subject.encode('cp1252', 'replace')
            extended = True
            extended_exception['subject'] = subject

        location = kwargs.get('location')
        if orig_item or (location is None and 'location' not in exception):
            location = item.get(PidLidLocation)
        if location is not None or 'location' in exception:
            exception['override_flags'] |= ARO_LOCATION
        if location is not None:
            exception['location'] = location.encode('cp1252', 'replace')
            extended = True
            extended_exception['location'] = location

        # skip ARO_MEETINGTYPE (like php)

        reminder_delta = item.get(PidLidReminderDelta)
        if reminder_delta is not None:
            exception['override_flags'] |= ARO_REMINDERDELTA
            exception['reminder_delta'] = reminder_delta

        reminder_set = item.get(PidLidReminderSet)
        if reminder_set is not None:
            exception['override_flags'] |= ARO_REMINDERSET
            exception['reminder_set'] = reminder_set

        busy_status = item.get(PidLidBusyStatus)
        if busy_status is not None:
            exception['override_flags'] |= ARO_BUSYSTATUS
            exception['busy_status'] = busy_status

        # skip ARO_ATTACHMENT (like php)

        # XXX php doesn't set the following by accident? ("alldayevent" not in copytags..)
        if not copytags or not create:
            sub_type = item.get(PidLidAppointmentSubType)
            if sub_type is not None:
                exception['override_flags'] |= ARO_SUBTYPE
                exception['sub_type'] = sub_type

        appointment_color = item.get(PidLidAppointmentColor)
        if appointment_color is not None:
            exception['override_flags'] |= ARO_APPTCOLOR
            exception['appointment_color'] = appointment_color

        if extended:
            if startdate:
                extended_exception['start_datetime'] = startdate_val
            if enddate:
                extended_exception['end_datetime'] = enddate_val
            extended_exception['original_start_date'] = basedate_val
Ejemplo n.º 8
0
    def end(self, value):
        self._end_date = _utils.unixtime_to_rectime(calendar.timegm(value.timetuple()))

        self.item[PidLidClipEnd] = self.end
Ejemplo n.º 9
0
    def start(self, value):
        self._start_date = _utils.unixtime_to_rectime(calendar.timegm(value.timetuple()))

        self.item[PidLidClipStart] = self.start
Ejemplo n.º 10
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()
Ejemplo n.º 11
0
 def _end(self, value):
     self.end_date = _utils.unixtime_to_rectime(
         time.mktime(value.date().timetuple()))
     end = self.item.end
     self.endtime_offset = end.hour * 60 + end.minute
Ejemplo n.º 12
0
 def _start(self, value):
     self.start_date = _utils.unixtime_to_rectime(
         time.mktime(value.date().timetuple()))
     start = self.item.start
     self.starttime_offset = start.hour * 60 + start.minute
Ejemplo n.º 13
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.º 14
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)