~jelmer/ubuntu/natty/evolution-mapi/513394-recurring-events

« back to all changes in this revision

Viewing changes to src/libexchangemapi/exchange-mapi-cal-recur-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-03 16:33:05 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20101103163305-yguad4zc3n3tza8c
Tags: 0.32.0-0ubuntu1
* New upstream release.
  - Evolution forgets password on any error (LP: #245589) (LP: #272414)
* debian/control: update Depends/Build-Depends for evolution packages 
* debian/patches/newer-openchange.patch: dropped, included upstream.
* debian/control: add a missing explicit Build-Depends for libgtk2.0-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 * Lesser General Public License for more details.
12
12
 *
13
13
 * You should have received a copy of the GNU Lesser General Public
14
 
 * License along with the program; if not, see <http://www.gnu.org/licenses/>  
 
14
 * License along with the program; if not, see <http://www.gnu.org/licenses/>
15
15
 *
16
16
 *
17
17
 * Authors:
28
28
#include "exchange-mapi-cal-recur-utils.h"
29
29
 
30
30
/* Reader/Writer versions */
31
 
#define READER_VERSION  0x3004
32
 
#define WRITER_VERSION  0x3004
 
31
#define READER_VERSION  0x3004
 
32
#define WRITER_VERSION  0x3004
33
33
#define READER_VERSION2 0x3006
34
34
#define WRITER_VERSION2 0x3009
35
35
 
36
36
#if 0
37
37
struct ChangeHighlight {
38
 
        uint32_t Size; 
39
 
        uint32_t Value; 
40
 
        uint32_t Reserved; 
 
38
        uint32_t Size;
 
39
        uint32_t Value;
 
40
        uint32_t Reserved;
41
41
};
42
42
 
43
43
struct ExtendedException {
44
 
        struct ChangeHighlight ch; 
 
44
        struct ChangeHighlight ch;
45
45
        uint32_t ReservedEE1Size;
46
46
        uint32_t ReservedEE1;
47
 
        uint32_t StartDateTime; 
48
 
        uint32_t EndDateTime; 
49
 
        uint32_t OrigStartDate; 
50
 
        uint16_t WideCharSubjectLength; 
51
 
        gchar *WideCharSubject; 
52
 
        uint16_t WideCharLocationLength; 
53
 
        gchar *WideCharLocation; 
 
47
        uint32_t StartDateTime;
 
48
        uint32_t EndDateTime;
 
49
        uint32_t OrigStartDate;
 
50
        uint16_t WideCharSubjectLength;
 
51
        gchar *WideCharSubject;
 
52
        uint16_t WideCharLocationLength;
 
53
        gchar *WideCharLocation;
54
54
        uint32_t ReservedEE2Size;
55
55
        uint32_t ReservedEE2;
56
56
};
57
57
 
58
58
struct ExceptionInfo {
59
 
        uint32_t StartDateTime; 
60
 
        uint32_t EndDateTime; 
61
 
        uint32_t OrigStartDate; 
62
 
        uint16_t OverrideFlags; 
63
 
        uint16_t SubjectLength; 
64
 
        uint16_t SubjectLength2; 
65
 
        gchar *Subject; 
66
 
        uint32_t MeetingType; 
67
 
        uint32_t ReminderDelta; 
68
 
        uint32_t ReminderSet; 
69
 
        uint16_t LocationLength; 
70
 
        uint16_t LocationLength2; 
71
 
        gchar *Location; 
72
 
        uint32_t BusyStatus; 
73
 
        uint32_t Attachment; 
74
 
        uint32_t SubType; 
75
 
        uint32_t AppointmentColor; 
 
59
        uint32_t StartDateTime;
 
60
        uint32_t EndDateTime;
 
61
        uint32_t OrigStartDate;
 
62
        uint16_t OverrideFlags;
 
63
        uint16_t SubjectLength;
 
64
        uint16_t SubjectLength2;
 
65
        gchar *Subject;
 
66
        uint32_t MeetingType;
 
67
        uint32_t ReminderDelta;
 
68
        uint32_t ReminderSet;
 
69
        uint16_t LocationLength;
 
70
        uint16_t LocationLength2;
 
71
        gchar *Location;
 
72
        uint32_t BusyStatus;
 
73
        uint32_t Attachment;
 
74
        uint32_t SubType;
 
75
        uint32_t AppointmentColor;
76
76
};
77
77
#endif
78
78
 
79
 
static icalrecurrencetype_weekday 
80
 
get_ical_weekstart (uint32_t fdow) 
 
79
static icalrecurrencetype_weekday
 
80
get_ical_weekstart (uint32_t fdow)
81
81
{
82
82
        switch (fdow) {
83
 
                case FirstDOW_Sunday    : return ICAL_SUNDAY_WEEKDAY;
84
 
                case FirstDOW_Monday    : return ICAL_MONDAY_WEEKDAY;
85
 
                case FirstDOW_Tuesday   : return ICAL_TUESDAY_WEEKDAY;
 
83
                case FirstDOW_Sunday    : return ICAL_SUNDAY_WEEKDAY;
 
84
                case FirstDOW_Monday    : return ICAL_MONDAY_WEEKDAY;
 
85
                case FirstDOW_Tuesday   : return ICAL_TUESDAY_WEEKDAY;
86
86
                case FirstDOW_Wednesday : return ICAL_WEDNESDAY_WEEKDAY;
87
 
                case FirstDOW_Thursday  : return ICAL_THURSDAY_WEEKDAY;
88
 
                case FirstDOW_Friday    : return ICAL_FRIDAY_WEEKDAY;
89
 
                case FirstDOW_Saturday  : return ICAL_SATURDAY_WEEKDAY;
90
 
                default                 : return ICAL_SUNDAY_WEEKDAY;
 
87
                case FirstDOW_Thursday  : return ICAL_THURSDAY_WEEKDAY;
 
88
                case FirstDOW_Friday    : return ICAL_FRIDAY_WEEKDAY;
 
89
                case FirstDOW_Saturday  : return ICAL_SATURDAY_WEEKDAY;
 
90
                default                 : return ICAL_SUNDAY_WEEKDAY;
91
91
        }
92
92
}
93
93
 
94
 
static uint32_t 
95
 
get_mapi_weekstart (icalrecurrencetype_weekday weekstart) 
 
94
static uint32_t
 
95
get_mapi_weekstart (icalrecurrencetype_weekday weekstart)
96
96
{
97
97
        switch (weekstart) {
98
98
                case ICAL_SUNDAY_WEEKDAY   : return FirstDOW_Sunday;
102
102
                case ICAL_THURSDAY_WEEKDAY : return FirstDOW_Thursday;
103
103
                case ICAL_FRIDAY_WEEKDAY   : return FirstDOW_Friday;
104
104
                case ICAL_SATURDAY_WEEKDAY : return FirstDOW_Saturday;
105
 
                default                    : return FirstDOW_Sunday;
 
105
                default                    : return FirstDOW_Sunday;
106
106
        }
107
107
}
108
108
 
109
 
static uint32_t 
 
109
static uint32_t
110
110
get_mapi_day (icalrecurrencetype_weekday someday)
111
111
{
112
112
        switch (someday) {
117
117
                case ICAL_THURSDAY_WEEKDAY : return olThursday;
118
118
                case ICAL_FRIDAY_WEEKDAY   : return olFriday;
119
119
                case ICAL_SATURDAY_WEEKDAY : return olSaturday;
120
 
                default                    : return 0;
 
120
                default                    : return 0;
121
121
        }
122
122
}
123
123
 
124
 
static int32_t 
125
 
get_ical_pos (uint32_t pos) 
 
124
static int32_t
 
125
get_ical_pos (uint32_t pos)
126
126
{
127
127
        switch (pos) {
128
 
                case RecurrenceN_First  : return 1;
 
128
                case RecurrenceN_First  : return 1;
129
129
                case RecurrenceN_Second : return 2;
130
 
                case RecurrenceN_Third  : return 3;
 
130
                case RecurrenceN_Third  : return 3;
131
131
                case RecurrenceN_Fourth : return 4;
132
 
                case RecurrenceN_Last   : return (-1);
133
 
                default                 : return 0;
 
132
                case RecurrenceN_Last   : return (-1);
 
133
                default                 : return 0;
134
134
        }
135
135
}
136
136
 
137
 
static uint32_t 
138
 
get_mapi_pos (int32_t pos) 
 
137
static uint32_t
 
138
get_mapi_pos (int32_t pos)
139
139
{
140
140
        switch (pos) {
141
 
                case 1  : return RecurrenceN_First;
142
 
                case 2  : return RecurrenceN_Second;
143
 
                case 3  : return RecurrenceN_Third;
144
 
                case 4  : return RecurrenceN_Fourth;
 
141
                case 1  : return RecurrenceN_First;
 
142
                case 2  : return RecurrenceN_Second;
 
143
                case 3  : return RecurrenceN_Third;
 
144
                case 4  : return RecurrenceN_Fourth;
145
145
                case -1 : return RecurrenceN_Last;
146
146
                default : return 0;
147
147
        }
153
153
static void
154
154
convert_recurrence_minutes_to_date (uint32_t minutes, struct FILETIME *ft)
155
155
{
156
 
        NTTIME nt; 
157
 
 
158
 
        nt = (NTTIME) minutes * (60 * cFileTimeUnitsPerSecond); 
159
 
 
160
 
        ft->dwLowDateTime = (uint32_t)((nt << 32) >> 32); 
161
 
        ft->dwHighDateTime = (uint32_t)(nt >> 32); 
 
156
        NTTIME nt;
 
157
 
 
158
        nt = (NTTIME) minutes * (60 * cFileTimeUnitsPerSecond);
 
159
 
 
160
        ft->dwLowDateTime = (uint32_t)((nt << 32) >> 32);
 
161
        ft->dwHighDateTime = (uint32_t)(nt >> 32);
162
162
}
163
163
 
164
164
static uint32_t
166
166
{
167
167
        NTTIME minutes;
168
168
 
169
 
        minutes = ft->dwHighDateTime; 
 
169
        minutes = ft->dwHighDateTime;
170
170
        minutes = minutes << 32;
171
171
        minutes |= ft->dwLowDateTime;
172
172
 
173
 
        minutes = minutes / (60 * cFileTimeUnitsPerSecond); 
 
173
        minutes = minutes / (60 * cFileTimeUnitsPerSecond);
174
174
 
175
175
        return (uint32_t)(minutes);
176
176
}
177
177
 
178
 
static time_t 
 
178
static time_t
179
179
convert_filetime_to_timet (const struct FILETIME *ft)
180
180
{
181
 
        NTTIME time; 
 
181
        NTTIME time;
182
182
 
183
183
        time = ft->dwHighDateTime;
184
184
        time = time << 32;
187
187
        return nt_time_to_unix (time);
188
188
}
189
189
 
190
 
static void 
 
190
static void
191
191
convert_timet_to_filetime (time_t t, struct FILETIME *ft)
192
192
{
193
 
        NTTIME nt; 
 
193
        NTTIME nt;
194
194
 
195
195
        unix_to_nt_time (&nt, t);
196
196
 
197
 
        ft->dwLowDateTime = (uint32_t)((nt << 32) >> 32); 
198
 
        ft->dwHighDateTime = (uint32_t)(nt >> 32); 
 
197
        ft->dwLowDateTime = (uint32_t)((nt << 32) >> 32);
 
198
        ft->dwHighDateTime = (uint32_t)(nt >> 32);
199
199
}
200
200
#endif
201
201
 
202
202
static time_t
203
203
convert_recurrence_minutes_to_timet (uint32_t minutes)
204
204
{
205
 
        NTTIME nt; 
 
205
        NTTIME nt;
206
206
 
207
 
        nt = (NTTIME) minutes * (60 * cFileTimeUnitsPerSecond); 
 
207
        nt = (NTTIME) minutes * (60 * cFileTimeUnitsPerSecond);
208
208
 
209
209
        return nt_time_to_unix (nt);
210
210
}
216
216
 
217
217
        unix_to_nt_time (&minutes, t);
218
218
 
219
 
        minutes = minutes / (60 * cFileTimeUnitsPerSecond); 
 
219
        minutes = minutes / (60 * cFileTimeUnitsPerSecond);
220
220
 
221
221
        return (uint32_t)(minutes);
222
222
}
223
223
 
224
 
static gboolean 
225
 
check_calendar_type (guint16 type) 
 
224
static gboolean
 
225
check_calendar_type (guint16 type)
226
226
{
227
227
        /* Calendar Type - We support Gregorian only. */
228
228
        if (type == CAL_DEFAULT || type == CAL_GREGORIAN)
229
 
                return TRUE; 
 
229
                return TRUE;
230
230
        else {
231
 
                g_warning ("Calendar type = 0x%04X - Evolution does not handle such calendar types.", type); 
232
 
                return FALSE; 
 
231
                g_warning ("Calendar type = 0x%04X - Evolution does not handle such calendar types.", type);
 
232
                return FALSE;
233
233
        }
234
234
}
235
235
 
242
242
        guint8 *ptr = ba->data;
243
243
        gint i;
244
244
        GSList *exdate_list = NULL;
245
 
        gboolean repeats_until_date = FALSE; 
 
245
        gboolean repeats_until_date = FALSE;
246
246
 
247
247
        icalrecurrencetype_clear (&rt);
248
248
 
299
299
                        if (!check_calendar_type (flag16))
300
300
                                return FALSE;
301
301
 
302
 
        /* NOTE: Evolution does not handle daily-every-weekday any different 
 
302
        /* NOTE: Evolution does not handle daily-every-weekday any different
303
303
         * from a weekly recurrence.
304
304
         */
305
305
                        rt.freq = ICAL_WEEKLY_RECURRENCE;
399
399
                                return FALSE;
400
400
 
401
401
                        /* FIXME: we don't handle regenerating tasks */
402
 
                        g_warning ("Evolution does not handle recurring tasks."); 
 
402
                        g_warning ("Evolution does not handle recurring tasks.");
403
403
                        return FALSE;
404
404
                }
405
405
 
409
409
                flag16 = *((guint16 *)ptr);
410
410
                ptr += sizeof (guint16);
411
411
                if (flag16 == PatternType_Month || flag16 == PatternType_MonthEnd) {
412
 
                        guint16 pattern = flag16; 
 
412
                        guint16 pattern = flag16;
413
413
                        /* Monthly every N months on day D or last day. */
414
414
 
415
415
                        /* Calendar Type */
433
433
                        if (flag32)
434
434
                                return FALSE;
435
435
 
436
 
                        /* MONTH_DAY */ 
 
436
                        /* MONTH_DAY */
437
437
                        flag32 = *((guint32 *)ptr);
438
438
                        ptr += sizeof (guint32);
439
439
                        if (pattern == PatternType_Month)
442
442
                                rt.by_month_day[0] = (short) (-1);
443
443
 
444
444
                } else if (flag16 == PatternType_MonthNth) {
445
 
                        gboolean post_process = FALSE; 
 
445
                        gboolean post_process = FALSE;
446
446
                        guint32 mask = 0;
447
447
                        /* Monthly every N months on the Xth Y */
448
448
 
466
466
                        ptr += sizeof (guint32);
467
467
                        if (flag32)
468
468
                                return FALSE;
469
 
                        
 
469
 
470
470
                        /* BITMASK */
471
471
                        flag32 = *((guint32 *)ptr);
472
472
                        ptr += sizeof (guint32);
485
485
                        else if (flag32 == olSaturday)
486
486
                                rt.by_day[0] = ICAL_SATURDAY_WEEKDAY;
487
487
                        else {
488
 
                                post_process = TRUE; 
489
 
                                mask = flag32; 
 
488
                                post_process = TRUE;
 
489
                                mask = flag32;
490
490
                        }
491
 
                                
 
491
 
492
492
                        /* RecurrenceN */
493
493
                        flag32 = *((guint32 *)ptr);
494
494
                        ptr += sizeof (guint32);
495
495
                        if (!post_process) {
496
 
                                rt.by_set_pos[0] = get_ical_pos (flag32); 
 
496
                                rt.by_set_pos[0] = get_ical_pos (flag32);
497
497
                                if (rt.by_set_pos[0] == 0)
498
 
                                        return FALSE; 
 
498
                                        return FALSE;
499
499
                        } else {
500
500
                                if (mask == (olSunday | olMonday | olTuesday | olWednesday | olThursday | olFriday | olSaturday)) {
501
 
                                        rt.by_month_day[0] = get_ical_pos (flag32); 
 
501
                                        rt.by_month_day[0] = get_ical_pos (flag32);
502
502
                                        if (rt.by_month_day[0] == 0)
503
 
                                                return FALSE; 
 
503
                                                return FALSE;
504
504
                                } else {
505
505
                                /* FIXME: Can we/LibICAL support any other types here? Namely, weekday and weekend-day */
506
 
                                        g_warning ("Encountered a recurrence type Evolution cannot handle. "); 
 
506
                                        g_warning ("Encountered a recurrence type Evolution cannot handle. ");
507
507
                                        return FALSE;
508
508
                                }
509
509
                        }
579
579
                        /* TODO: Add support for this kinda recurrence in Evolution */
580
580
                        return FALSE;
581
581
                }
582
 
        } else 
 
582
        } else
583
583
                return FALSE;
584
584
 
585
585
        /* End Type - followed by Occurence count */
610
610
        ptr += sizeof (guint32);
611
611
        if (flag32) {
612
612
                for (i = 0; i < flag32; ++i) {
613
 
                        uint32_t exdate; 
614
 
                        struct icaltimetype tt, *val; 
615
 
                        ECalComponentDateTime *dt = g_new0 (ECalComponentDateTime, 1); 
 
613
                        uint32_t exdate;
 
614
                        struct icaltimetype tt, *val;
 
615
                        ECalComponentDateTime *dt = g_new0 (ECalComponentDateTime, 1);
616
616
 
617
617
                        exdate = *((guint32 *)ptr);
618
618
                        ptr += sizeof (guint32);
619
619
 
620
620
                        tt = icaltime_from_timet_with_zone (convert_recurrence_minutes_to_timet (exdate), 1, 0);
621
621
 
622
 
                        val = g_new0(struct icaltimetype, 1); 
623
 
                        memcpy (val, &tt, sizeof(struct icaltimetype)); 
624
 
 
625
 
                        dt->value = val; 
626
 
                        dt->tzid = g_strdup ("UTC"); 
627
 
 
628
 
                        exdate_list = g_slist_append (exdate_list, dt); 
 
622
                        val = g_new0(struct icaltimetype, 1);
 
623
                        memcpy (val, &tt, sizeof(struct icaltimetype));
 
624
 
 
625
                        dt->value = val;
 
626
                        dt->tzid = g_strdup ("UTC");
 
627
 
 
628
                        exdate_list = g_slist_append (exdate_list, dt);
629
629
                }
630
630
        }
631
631
 
633
633
        flag32 = *((guint32 *)ptr);
634
634
        ptr += sizeof (guint32);
635
635
        /* FIXME: Parse modified instances */
636
 
        if (flag32) 
 
636
        if (flag32)
637
637
                ptr += flag32 * sizeof (guint32);
638
 
        
 
638
 
639
639
        /* start date */
640
640
        flag32 = *((guint32 *)ptr);
641
641
        ptr += sizeof (guint32);
689
689
        {
690
690
                GSList l;
691
691
 
692
 
                l.data = &rt; 
 
692
                l.data = &rt;
693
693
                l.next = NULL;
694
694
 
695
695
                e_cal_component_set_rrule_list (comp, &l);
696
696
        }
697
697
 
698
698
        /* FIXME: this also has modified instances */
699
 
        e_cal_component_set_exdate_list (comp, exdate_list); 
 
699
        e_cal_component_set_exdate_list (comp, exdate_list);
700
700
 
701
701
        g_print ("\n== MAPI to ICAL == The recurrence blob data is as follows:\n");
702
702
        for (i = 0; i < ba->len; ++i)
703
703
                g_print ("0x%02X ", ba->data[i]);
704
 
        g_print("\n== End of stream ==\n"); 
 
704
        g_print("\n== End of stream ==\n");
705
705
 
706
706
        return TRUE;
707
707
}
709
709
static guint32
710
710
compute_startdate (ECalComponent *comp)
711
711
{
712
 
        ECalComponentDateTime dtstart; 
713
 
        guint32 flag32; 
 
712
        ECalComponentDateTime dtstart;
 
713
        guint32 flag32;
714
714
 
715
715
        e_cal_component_get_dtstart (comp, &dtstart);
716
 
        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0; 
 
716
        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0;
717
717
        flag32 = convert_timet_to_recurrence_minutes (icaltime_as_timet_with_zone (*(dtstart.value), 0));
718
718
 
719
 
        e_cal_component_free_datetime (&dtstart); 
 
719
        e_cal_component_free_datetime (&dtstart);
720
720
 
721
 
        return flag32; 
 
721
        return flag32;
722
722
}
723
723
 
724
724
static guint32
730
730
static guint32
731
731
compute_rweekly_firstdatetime (ECalComponent *comp, icalrecurrencetype_weekday week_start, guint32 period)
732
732
{
733
 
        ECalComponentDateTime dtstart; 
734
 
        guint32 flag32; 
735
 
        int cur_weekday = 0, weekstart_weekday = 0, diff = 0;
736
 
        time_t t; 
 
733
        ECalComponentDateTime dtstart;
 
734
        guint32 flag32;
 
735
        gint cur_weekday = 0, weekstart_weekday = 0, diff = 0;
 
736
        time_t t;
737
737
 
738
738
        e_cal_component_get_dtstart (comp, &dtstart);
739
 
        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0; 
 
739
        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0;
740
740
        cur_weekday = icaltime_day_of_week (*(dtstart.value));
741
741
        t = icaltime_as_timet_with_zone (*(dtstart.value), 0);
742
 
        e_cal_component_free_datetime (&dtstart); 
 
742
        e_cal_component_free_datetime (&dtstart);
743
743
 
744
744
        switch (week_start) {
745
 
                case ICAL_SUNDAY_WEEKDAY        : weekstart_weekday = 1; break; 
746
 
                case ICAL_MONDAY_WEEKDAY        : weekstart_weekday = 2; break; 
747
 
                case ICAL_TUESDAY_WEEKDAY       : weekstart_weekday = 3; break; 
748
 
                case ICAL_WEDNESDAY_WEEKDAY     : weekstart_weekday = 4; break; 
749
 
                case ICAL_THURSDAY_WEEKDAY      : weekstart_weekday = 5; break; 
750
 
                case ICAL_FRIDAY_WEEKDAY        : weekstart_weekday = 6; break; 
751
 
                case ICAL_SATURDAY_WEEKDAY      : weekstart_weekday = 7; break; 
752
 
                default                         : weekstart_weekday = 1; break; 
 
745
                case ICAL_SUNDAY_WEEKDAY        : weekstart_weekday = 1; break;
 
746
                case ICAL_MONDAY_WEEKDAY        : weekstart_weekday = 2; break;
 
747
                case ICAL_TUESDAY_WEEKDAY       : weekstart_weekday = 3; break;
 
748
                case ICAL_WEDNESDAY_WEEKDAY     : weekstart_weekday = 4; break;
 
749
                case ICAL_THURSDAY_WEEKDAY      : weekstart_weekday = 5; break;
 
750
                case ICAL_FRIDAY_WEEKDAY        : weekstart_weekday = 6; break;
 
751
                case ICAL_SATURDAY_WEEKDAY      : weekstart_weekday = 7; break;
 
752
                default                         : weekstart_weekday = 1; break;
753
753
        };
754
754
 
755
 
        diff = cur_weekday - weekstart_weekday; 
 
755
        diff = cur_weekday - weekstart_weekday;
756
756
 
757
 
        if (diff == 0); 
 
757
        if (diff == 0);
758
758
        else if (diff > 0)
759
759
                t -= (diff * 24 * 60 * 60);
760
760
        else if (diff < 0)
770
770
compute_rmonthly_firstdatetime (ECalComponent *comp, guint32 period)
771
771
{
772
772
        const guint8 dinm[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
773
 
        ECalComponentDateTime dtstart; 
774
 
        guint32 flag32, monthindex, i; 
 
773
        ECalComponentDateTime dtstart;
 
774
        guint32 flag32, monthindex, i;
775
775
 
776
776
        e_cal_component_get_dtstart (comp, &dtstart);
777
 
        monthindex = (guint32)((((guint64)(12) * (dtstart.value->year - 1601)) + (dtstart.value->month - 1)) % period); 
778
 
        e_cal_component_free_datetime (&dtstart); 
 
777
        monthindex = (guint32)((((guint64)(12) * (dtstart.value->year - 1601)) + (dtstart.value->month - 1)) % period);
 
778
        e_cal_component_free_datetime (&dtstart);
779
779
 
780
780
        for (flag32 = 0, i = 0; i < monthindex; ++i)
781
781
                flag32 += dinm[(i % 12) + 1] * 24 * 60;
782
782
 
783
 
        return flag32; 
 
783
        return flag32;
784
784
}
785
785
 
786
786
static guint32
787
787
calculate_no_of_occurrences (ECalComponent *comp, const struct icalrecurrencetype *rt)
788
788
{
789
 
        ECalComponentDateTime dtstart; 
790
 
        icalrecur_iterator *iter; 
791
 
        struct icaltimetype next; 
792
 
        guint32 count = 1; 
 
789
        ECalComponentDateTime dtstart;
 
790
        icalrecur_iterator *iter;
 
791
        struct icaltimetype next;
 
792
        guint32 count = 1;
793
793
 
794
794
        e_cal_component_get_dtstart (comp, &dtstart);
795
795
 
796
 
        for (iter = icalrecur_iterator_new (*rt, *(dtstart.value)), 
 
796
        for (iter = icalrecur_iterator_new (*rt, *(dtstart.value)),
797
797
             next = icalrecur_iterator_next(iter);
798
798
             !icaltime_is_null_time(next);
799
799
             next = icalrecur_iterator_next(iter))
800
 
                ++count; 
801
 
 
802
 
        icalrecur_iterator_free (iter); 
803
 
        e_cal_component_free_datetime (&dtstart); 
804
 
 
805
 
        return count; 
 
800
                ++count;
 
801
 
 
802
        icalrecur_iterator_free (iter);
 
803
        e_cal_component_free_datetime (&dtstart);
 
804
 
 
805
        return count;
806
806
}
807
807
 
808
 
static gint 
 
808
static gint
809
809
compare_guint32 (gconstpointer a, gconstpointer b, gpointer user_data)
810
810
{
811
811
        return (*((guint32 *) a) - *((guint32 *) b));
817
817
        struct icalrecurrencetype *rt;
818
818
        guint16 flag16;
819
819
        guint32 flag32, end_type;
820
 
        gint i; 
821
 
        GSList *rrule_list = NULL, *exdate_list = NULL; 
 
820
        gint i;
 
821
        GSList *rrule_list = NULL, *exdate_list = NULL;
822
822
        GByteArray *ba = NULL;
823
823
 
824
824
        if (!e_cal_component_has_recurrences (comp))
825
 
                return NULL; 
 
825
                return NULL;
826
826
 
827
 
        e_cal_component_get_rrule_list (comp, &rrule_list); 
828
 
        e_cal_component_get_exdate_list (comp, &exdate_list); 
 
827
        e_cal_component_get_rrule_list (comp, &rrule_list);
 
828
        e_cal_component_get_exdate_list (comp, &exdate_list);
829
829
 
830
830
        if (g_slist_length (rrule_list) != 1)
831
 
                goto cleanup; 
 
831
                goto cleanup;
832
832
 
833
833
        rt = (struct icalrecurrencetype *)(rrule_list->data);
834
834
 
835
 
        ba = g_byte_array_new (); 
 
835
        ba = g_byte_array_new ();
836
836
 
837
837
        /* Reader Version */
838
838
        flag16 = READER_VERSION;
846
846
                flag16 = RecurFrequency_Daily;
847
847
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
848
848
 
849
 
                /* Pattern Type - it would be PatternType_Day since we have only "Daily every N days" 
850
 
                 * The other type would be parsed as a weekly recurrence. 
 
849
                /* Pattern Type - it would be PatternType_Day since we have only "Daily every N days"
 
850
                 * The other type would be parsed as a weekly recurrence.
851
851
                 */
852
852
                flag16 = PatternType_Day;
853
853
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
854
854
 
855
855
                /* Calendar Type */
856
 
                flag16 = CAL_DEFAULT; 
 
856
                flag16 = CAL_DEFAULT;
857
857
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
858
858
 
859
859
                /* FirstDateTime */
861
861
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
862
862
 
863
863
                /* INTERVAL */
864
 
                flag32 = (rt->interval * (60 * 24)); 
 
864
                flag32 = (rt->interval * (60 * 24));
865
865
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
866
866
 
867
867
                /* This would be 0 for the stuff we handle */
879
879
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
880
880
 
881
881
                /* Calendar Type */
882
 
                flag16 = CAL_DEFAULT; 
 
882
                flag16 = CAL_DEFAULT;
883
883
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
884
884
 
885
885
                /* FirstDateTime */
887
887
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
888
888
 
889
889
                /* INTERVAL */
890
 
                flag32 = rt->interval; 
 
890
                flag32 = rt->interval;
891
891
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
892
892
 
893
893
                /* This would be 0 for the stuff we handle */
897
897
                /* BITMASK */
898
898
                for (flag32 = 0x0, i = 0; i < ICAL_BY_DAY_SIZE; ++i) {
899
899
                        if (rt->by_day[i] == ICAL_SUNDAY_WEEKDAY)
900
 
                                flag32 |= olSunday; 
 
900
                                flag32 |= olSunday;
901
901
                        else if (rt->by_day[i] == ICAL_MONDAY_WEEKDAY)
902
 
                                flag32 |= olMonday; 
 
902
                                flag32 |= olMonday;
903
903
                        else if (rt->by_day[i] == ICAL_TUESDAY_WEEKDAY)
904
 
                                flag32 |= olTuesday; 
 
904
                                flag32 |= olTuesday;
905
905
                        else if (rt->by_day[i] == ICAL_WEDNESDAY_WEEKDAY)
906
 
                                flag32 |= olWednesday; 
 
906
                                flag32 |= olWednesday;
907
907
                        else if (rt->by_day[i] == ICAL_THURSDAY_WEEKDAY)
908
 
                                flag32 |= olThursday; 
 
908
                                flag32 |= olThursday;
909
909
                        else if (rt->by_day[i] == ICAL_FRIDAY_WEEKDAY)
910
 
                                flag32 |= olFriday; 
 
910
                                flag32 |= olFriday;
911
911
                        else if (rt->by_day[i] == ICAL_SATURDAY_WEEKDAY)
912
 
                                flag32 |= olSaturday; 
913
 
                        else 
914
 
                                break; 
 
912
                                flag32 |= olSaturday;
 
913
                        else
 
914
                                break;
915
915
                }
916
916
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
917
917
 
918
918
        } else if (rt->freq == ICAL_MONTHLY_RECURRENCE) {
919
 
                guint16 pattern = 0x0; guint32 mask = 0x0, flag = 0x0; 
 
919
                guint16 pattern = 0x0; guint32 mask = 0x0, flag = 0x0;
920
920
 
921
921
                flag16 = RecurFrequency_Monthly;
922
922
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
923
923
 
924
924
                if (rt->by_month_day[0] >= 1 && rt->by_month_day[0] <= 31) {
925
925
                        pattern = PatternType_Month;
926
 
                        flag = rt->by_month_day[0]; 
 
926
                        flag = rt->by_month_day[0];
927
927
                } else if (rt->by_month_day[0] == -1) {
928
 
                        pattern = PatternType_MonthNth; 
929
 
                        mask = (olSunday | olMonday | olTuesday | olWednesday | olThursday | olFriday | olSaturday); 
930
 
                        flag = RecurrenceN_Last; 
 
928
                        pattern = PatternType_MonthNth;
 
929
                        mask = (olSunday | olMonday | olTuesday | olWednesday | olThursday | olFriday | olSaturday);
 
930
                        flag = RecurrenceN_Last;
931
931
                } else if (rt->by_day[0] >= ICAL_SUNDAY_WEEKDAY && rt->by_day[0] <= ICAL_SATURDAY_WEEKDAY) {
932
932
                        pattern = PatternType_MonthNth;
933
933
                        mask = get_mapi_day (rt->by_day[0]);
939
939
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
940
940
 
941
941
                /* Calendar Type */
942
 
                flag16 = CAL_DEFAULT; 
 
942
                flag16 = CAL_DEFAULT;
943
943
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
944
944
 
945
945
                /* FirstDateTime */
947
947
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
948
948
 
949
949
                /* INTERVAL */
950
 
                flag32 = rt->interval; 
 
950
                flag32 = rt->interval;
951
951
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
952
952
 
953
953
                /* This would be 0 for the stuff we handle */
959
959
                        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
960
960
 
961
961
                        if (!(flag))
962
 
                                g_warning ("Possibly setting incorrect values in the stream. "); 
 
962
                                g_warning ("Possibly setting incorrect values in the stream. ");
963
963
                } else if (pattern == PatternType_MonthNth) {
964
964
                        flag32 = mask;
965
965
                        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
968
968
                        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
969
969
 
970
970
                        if (!(flag && mask))
971
 
                                g_warning ("Possibly setting incorrect values in the stream. "); 
972
 
                } else 
973
 
                        g_warning ("Possibly setting incorrect values in the stream. "); 
 
971
                                g_warning ("Possibly setting incorrect values in the stream. ");
 
972
                } else
 
973
                        g_warning ("Possibly setting incorrect values in the stream. ");
974
974
 
975
975
        } else if (rt->freq == ICAL_YEARLY_RECURRENCE) {
976
976
                flag16 = RecurFrequency_Yearly;
981
981
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
982
982
 
983
983
                /* Calendar Type */
984
 
                flag16 = CAL_DEFAULT; 
 
984
                flag16 = CAL_DEFAULT;
985
985
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
986
986
 
987
987
                /* FirstDateTime - uses the same function as monthly recurrence */
989
989
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
990
990
 
991
991
                /* INTERVAL - should be 12 for yearly recurrence */
992
 
                flag32 = 0xC; 
 
992
                flag32 = 0xC;
993
993
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
994
994
 
995
995
                /* This would be 0 for the stuff we handle */
998
998
 
999
999
                /* MONTH_DAY */
1000
1000
                {
1001
 
                        ECalComponentDateTime dtstart; 
 
1001
                        ECalComponentDateTime dtstart;
1002
1002
                        e_cal_component_get_dtstart (comp, &dtstart);
1003
 
                        flag32 = dtstart.value->day; 
1004
 
                        e_cal_component_free_datetime (&dtstart); 
 
1003
                        flag32 = dtstart.value->day;
 
1004
                        e_cal_component_free_datetime (&dtstart);
1005
1005
                }
1006
1006
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1007
1007
 
1008
 
        } 
 
1008
        }
1009
1009
 
1010
1010
        /* End Type followed by Occurence count */
1011
1011
        if (!icaltime_is_null_time (rt->until)) {
1012
1012
                flag32 = END_AFTER_DATE;
1013
1013
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1014
1014
 
1015
 
                flag32 = calculate_no_of_occurrences (comp, rt); 
 
1015
                flag32 = calculate_no_of_occurrences (comp, rt);
1016
1016
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1017
1017
 
1018
1018
                end_type = END_AFTER_DATE;
1035
1035
        }
1036
1036
 
1037
1037
        /* FirstDOW */
1038
 
        flag32 = get_mapi_weekstart (rt->week_start); 
 
1038
        flag32 = get_mapi_weekstart (rt->week_start);
1039
1039
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1040
1040
 
1041
1041
        /* DeletedInstances */
1042
1042
        flag32 = g_slist_length (exdate_list);
1043
1043
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1044
1044
        if (flag32) {
1045
 
                GSList *l; 
 
1045
                GSList *l;
1046
1046
                guint32 *sorted_list = g_new0(guint32, flag32);
1047
1047
                /* FIXME: This should include modified dates */
1048
1048
                for (i = 0, l = exdate_list; l; ++i, l = l->next) {
1049
 
                        ECalComponentDateTime *dt = (ECalComponentDateTime *)(l->data); 
1050
 
                        dt->value->hour = dt->value->minute = dt->value->second = 0; 
1051
 
                        sorted_list[i] = convert_timet_to_recurrence_minutes (icaltime_as_timet_with_zone (*(dt->value), 0)); 
 
1049
                        ECalComponentDateTime *dt = (ECalComponentDateTime *)(l->data);
 
1050
                        dt->value->hour = dt->value->minute = dt->value->second = 0;
 
1051
                        sorted_list[i] = convert_timet_to_recurrence_minutes (icaltime_as_timet_with_zone (*(dt->value), 0));
1052
1052
                }
1053
1053
 
1054
 
                g_qsort_with_data (sorted_list, flag32, sizeof (guint32), compare_guint32, NULL); 
 
1054
                g_qsort_with_data (sorted_list, flag32, sizeof (guint32), compare_guint32, NULL);
1055
1055
 
1056
1056
                for (i = 0; i < flag32; ++i)
1057
1057
                        ba = g_byte_array_append (ba, (const guint8 *)&(sorted_list[i]), sizeof (guint32));
1067
1067
        }
1068
1068
 
1069
1069
        /* StartDate */
1070
 
        flag32 = compute_startdate (comp); 
 
1070
        flag32 = compute_startdate (comp);
1071
1071
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1072
1072
 
1073
1073
        /* EndDate */
1074
1074
        {
1075
 
                if (end_type == END_NEVER_END) 
1076
 
                        flag32 = 0x5AE980DF; 
 
1075
                if (end_type == END_NEVER_END)
 
1076
                        flag32 = 0x5AE980DF;
1077
1077
                else if (end_type == END_AFTER_N_OCCURRENCES) {
1078
 
                        ECalComponentDateTime dtstart; 
1079
 
                        gchar *rrule_str = icalrecurrencetype_as_string_r (rt); 
1080
 
                        time_t *array = g_new0 (time_t, rt->count); 
 
1078
                        ECalComponentDateTime dtstart;
 
1079
                        gchar *rrule_str = icalrecurrencetype_as_string_r (rt);
 
1080
                        time_t *array = g_new0 (time_t, rt->count);
1081
1081
 
1082
1082
                        e_cal_component_get_dtstart (comp, &dtstart);
1083
 
                        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0; 
1084
 
 
1085
 
                        icalrecur_expand_recurrence (rrule_str, icaltime_as_timet_with_zone (*(dtstart.value), 0), rt->count, array); 
1086
 
 
1087
 
                        flag32 = convert_timet_to_recurrence_minutes (array[(rt->count) - 1]); 
1088
 
 
1089
 
                        g_free (array); 
1090
 
                        g_free (rrule_str); 
1091
 
                        e_cal_component_free_datetime (&dtstart); 
 
1083
                        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0;
 
1084
 
 
1085
                        icalrecur_expand_recurrence (rrule_str, icaltime_as_timet_with_zone (*(dtstart.value), 0), rt->count, array);
 
1086
 
 
1087
                        flag32 = convert_timet_to_recurrence_minutes (array[(rt->count) - 1]);
 
1088
 
 
1089
                        g_free (array);
 
1090
                        g_free (rrule_str);
 
1091
                        e_cal_component_free_datetime (&dtstart);
1092
1092
                } else if (end_type == END_AFTER_DATE) {
1093
 
                        struct icaltimetype until; 
 
1093
                        struct icaltimetype until;
1094
1094
                        memcpy (&until, &(rt->until), sizeof(struct icaltimetype));
1095
 
                        until.hour = until.minute = until.second = 0; 
 
1095
                        until.hour = until.minute = until.second = 0;
1096
1096
                        flag32 = convert_timet_to_recurrence_minutes (icaltime_as_timet_with_zone (until, 0));
1097
 
                } else 
1098
 
                        flag32 = 0x0; 
 
1097
                } else
 
1098
                        flag32 = 0x0;
1099
1099
        }
1100
1100
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1101
1101
 
1109
1109
 
1110
1110
        /* StartTimeOffset */
1111
1111
        {
1112
 
                ECalComponentDateTime dtstart; 
 
1112
                ECalComponentDateTime dtstart;
1113
1113
                e_cal_component_get_dtstart (comp, &dtstart);
1114
 
                flag32 = (dtstart.value->hour * 60) + dtstart.value->minute; 
1115
 
                e_cal_component_free_datetime (&dtstart); 
 
1114
                flag32 = (dtstart.value->hour * 60) + dtstart.value->minute;
 
1115
                e_cal_component_free_datetime (&dtstart);
1116
1116
        }
1117
1117
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1118
1118
 
1119
1119
        /* EndTimeOffset */
1120
1120
        {
1121
 
                ECalComponentDateTime dtend; 
 
1121
                ECalComponentDateTime dtend;
1122
1122
                e_cal_component_get_dtend (comp, &dtend);
1123
 
                flag32 = (dtend.value->hour * 60) + dtend.value->minute; 
1124
 
                e_cal_component_free_datetime (&dtend); 
 
1123
                flag32 = (dtend.value->hour * 60) + dtend.value->minute;
 
1124
                e_cal_component_free_datetime (&dtend);
1125
1125
        }
1126
1126
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1127
1127
 
1128
1128
        /* FIXME: Add support for modified instances */
1129
1129
        /* ModifiedExceptionCount */
1130
 
        flag16 = 0x0; 
 
1130
        flag16 = 0x0;
1131
1131
        ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
1132
1132
 
1133
1133
        /* FIXME: Add the ExceptionInfo here */
1142
1142
        flag32 = 0x0;
1143
1143
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
1144
1144
 
1145
 
cleanup: 
 
1145
cleanup:
1146
1146
        e_cal_component_free_exdate_list (exdate_list);
1147
1147
        e_cal_component_free_recur_list (rrule_list);
1148
1148
 
1149
1149
        g_print ("\n== ICAL to MAPI == The recurrence blob data is as follows:\n");
1150
1150
        for (i = 0; i < ba->len; ++i)
1151
1151
                g_print ("0x%02X ", ba->data[i]);
1152
 
        g_print("\n== End of stream ==\n"); 
 
1152
        g_print("\n== End of stream ==\n");
1153
1153
 
1154
 
        return ba; 
 
1154
        return ba;
1155
1155
}
1156
1156