~ubuntu-branches/ubuntu/karmic/evolution-mapi/karmic

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2009-02-06 01:15:32 UTC
  • Revision ID: james.westby@ubuntu.com-20090206011532-eat2f3r2koynqpkd
Tags: upstream-0.25.91
ImportĀ upstreamĀ versionĀ 0.25.91

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/*
 
3
 * This program is free software; you can redistribute it and/or
 
4
 * modify it under the terms of the GNU Lesser General Public
 
5
 * License as published by the Free Software Foundation; either
 
6
 * version 2 of the License, or (at your option) version 3.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
 * Lesser General Public License for more details.
 
12
 *
 
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/>  
 
15
 *
 
16
 *
 
17
 * Authors:
 
18
 *    Suman Manjunath <msuman@novell.com>
 
19
 *
 
20
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 
21
 *
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include "exchange-mapi-cal-recur-utils.h"
 
29
 
 
30
/* Reader/Writer versions */
 
31
#define READER_VERSION  0x3004
 
32
#define WRITER_VERSION  0x3004
 
33
#define READER_VERSION2 0x3006
 
34
#define WRITER_VERSION2 0x3009
 
35
 
 
36
#if 0
 
37
struct ChangeHighlight {
 
38
        uint32_t Size; 
 
39
        uint32_t Value; 
 
40
        uint32_t Reserved; 
 
41
};
 
42
 
 
43
struct ExtendedException {
 
44
        struct ChangeHighlight ch; 
 
45
        uint32_t ReservedEE1Size;
 
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; 
 
54
        uint32_t ReservedEE2Size;
 
55
        uint32_t ReservedEE2;
 
56
};
 
57
 
 
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; 
 
76
};
 
77
#endif
 
78
 
 
79
static icalrecurrencetype_weekday 
 
80
get_ical_weekstart (uint32_t fdow) 
 
81
{
 
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;
 
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;
 
91
        }
 
92
}
 
93
 
 
94
static uint32_t 
 
95
get_mapi_weekstart (icalrecurrencetype_weekday weekstart) 
 
96
{
 
97
        switch (weekstart) {
 
98
                case ICAL_SUNDAY_WEEKDAY   : return FirstDOW_Sunday;
 
99
                case ICAL_MONDAY_WEEKDAY   : return FirstDOW_Monday;
 
100
                case ICAL_TUESDAY_WEEKDAY  : return FirstDOW_Tuesday;
 
101
                case ICAL_WEDNESDAY_WEEKDAY: return FirstDOW_Wednesday;
 
102
                case ICAL_THURSDAY_WEEKDAY : return FirstDOW_Thursday;
 
103
                case ICAL_FRIDAY_WEEKDAY   : return FirstDOW_Friday;
 
104
                case ICAL_SATURDAY_WEEKDAY : return FirstDOW_Saturday;
 
105
                default                    : return FirstDOW_Sunday;
 
106
        }
 
107
}
 
108
 
 
109
static uint32_t 
 
110
get_mapi_day (icalrecurrencetype_weekday someday)
 
111
{
 
112
        switch (someday) {
 
113
                case ICAL_SUNDAY_WEEKDAY   : return olSunday;
 
114
                case ICAL_MONDAY_WEEKDAY   : return olMonday;
 
115
                case ICAL_TUESDAY_WEEKDAY  : return olTuesday;
 
116
                case ICAL_WEDNESDAY_WEEKDAY: return olWednesday;
 
117
                case ICAL_THURSDAY_WEEKDAY : return olThursday;
 
118
                case ICAL_FRIDAY_WEEKDAY   : return olFriday;
 
119
                case ICAL_SATURDAY_WEEKDAY : return olSaturday;
 
120
                default                    : return 0;
 
121
        }
 
122
}
 
123
 
 
124
static int32_t 
 
125
get_ical_pos (uint32_t pos) 
 
126
{
 
127
        switch (pos) {
 
128
                case RecurrenceN_First  : return 1;
 
129
                case RecurrenceN_Second : return 2;
 
130
                case RecurrenceN_Third  : return 3;
 
131
                case RecurrenceN_Fourth : return 4;
 
132
                case RecurrenceN_Last   : return (-1);
 
133
                default                 : return 0;
 
134
        }
 
135
}
 
136
 
 
137
static uint32_t 
 
138
get_mapi_pos (int32_t pos) 
 
139
{
 
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;
 
145
                case -1 : return RecurrenceN_Last;
 
146
                default : return 0;
 
147
        }
 
148
}
 
149
 
 
150
#define cFileTimeUnitsPerSecond 10000000
 
151
 
 
152
static void
 
153
convert_recurrence_minutes_to_date (uint32_t minutes, struct FILETIME *ft)
 
154
{
 
155
        NTTIME nt; 
 
156
 
 
157
        nt = (NTTIME) minutes * (60 * cFileTimeUnitsPerSecond); 
 
158
 
 
159
        ft->dwLowDateTime = (uint32_t)((nt << 32) >> 32); 
 
160
        ft->dwHighDateTime = (uint32_t)(nt >> 32); 
 
161
}
 
162
 
 
163
static uint32_t
 
164
convert_date_to_recurrence_minutes (const struct FILETIME *ft)
 
165
{
 
166
        NTTIME minutes;
 
167
 
 
168
        minutes = ft->dwHighDateTime; 
 
169
        minutes = minutes << 32;
 
170
        minutes |= ft->dwLowDateTime;
 
171
 
 
172
        minutes = minutes / (60 * cFileTimeUnitsPerSecond); 
 
173
 
 
174
        return (uint32_t)(minutes);
 
175
}
 
176
 
 
177
static time_t 
 
178
convert_filetime_to_timet (const struct FILETIME *ft)
 
179
{
 
180
        NTTIME time; 
 
181
 
 
182
        time = ft->dwHighDateTime;
 
183
        time = time << 32;
 
184
        time |= ft->dwLowDateTime;
 
185
 
 
186
        return nt_time_to_unix (time);
 
187
}
 
188
 
 
189
static void 
 
190
convert_timet_to_filetime (time_t t, struct FILETIME *ft)
 
191
{
 
192
        NTTIME nt; 
 
193
 
 
194
        unix_to_nt_time (&nt, t);
 
195
 
 
196
        ft->dwLowDateTime = (uint32_t)((nt << 32) >> 32); 
 
197
        ft->dwHighDateTime = (uint32_t)(nt >> 32); 
 
198
}
 
199
 
 
200
static time_t
 
201
convert_recurrence_minutes_to_timet (uint32_t minutes)
 
202
{
 
203
        NTTIME nt; 
 
204
 
 
205
        nt = (NTTIME) minutes * (60 * cFileTimeUnitsPerSecond); 
 
206
 
 
207
        return nt_time_to_unix (nt);
 
208
}
 
209
 
 
210
static uint32_t
 
211
convert_timet_to_recurrence_minutes (time_t t)
 
212
{
 
213
        NTTIME minutes;
 
214
 
 
215
        unix_to_nt_time (&minutes, t);
 
216
 
 
217
        minutes = minutes / (60 * cFileTimeUnitsPerSecond); 
 
218
 
 
219
        return (uint32_t)(minutes);
 
220
}
 
221
 
 
222
static gboolean 
 
223
check_calendar_type (guint16 type) 
 
224
{
 
225
        /* Calendar Type - We support Gregorian only. */
 
226
        if (type == CAL_DEFAULT || type == CAL_GREGORIAN)
 
227
                return TRUE; 
 
228
        else {
 
229
                g_warning ("Calendar type = 0x%04X - Evolution does not handle such calendar types.", type); 
 
230
                return FALSE; 
 
231
        }
 
232
}
 
233
 
 
234
gboolean
 
235
exchange_mapi_cal_util_bin_to_rrule (GByteArray *ba, ECalComponent *comp)
 
236
{
 
237
        struct icalrecurrencetype rt;
 
238
        guint16 flag16;
 
239
        guint32 flag32;
 
240
        guint8 *ptr = ba->data;
 
241
        gint i;
 
242
        GSList *exdate_list = NULL;
 
243
        gboolean repeats_until_date = FALSE; 
 
244
 
 
245
        icalrecurrencetype_clear (&rt);
 
246
 
 
247
        /* Reader version */
 
248
        flag16 = *((guint16 *)ptr);
 
249
        ptr += sizeof (guint16);
 
250
        if (READER_VERSION != flag16)
 
251
                return FALSE;
 
252
 
 
253
        /* Writer version */
 
254
        flag16 = *((guint16 *)ptr);
 
255
        ptr += sizeof (guint16);
 
256
        if (WRITER_VERSION != flag16)
 
257
                return FALSE;
 
258
 
 
259
        /* FREQUENCY */
 
260
        flag16 = *((guint16 *)ptr);
 
261
        ptr += sizeof (guint16);
 
262
        if (flag16 == RecurFrequency_Daily) {
 
263
                rt.freq = ICAL_DAILY_RECURRENCE;
 
264
 
 
265
                flag16 = *((guint16 *)ptr);
 
266
                ptr += sizeof (guint16);
 
267
                if (flag16 == PatternType_Day) {
 
268
                        /* Daily every N days */
 
269
 
 
270
                        /* Calendar Type */
 
271
                        flag16 = *((guint16 *)ptr);
 
272
                        ptr += sizeof (guint16);
 
273
                        if (!check_calendar_type (flag16))
 
274
                                return FALSE;
 
275
 
 
276
                        /* FirstDateTime (some crappy mod here) */
 
277
                        flag32 = *((guint32 *)ptr);
 
278
                        ptr += sizeof (guint32);
 
279
 
 
280
                        /* INTERVAL */
 
281
                        flag32 = *((guint32 *)ptr);
 
282
                        ptr += sizeof (guint32);
 
283
                        rt.interval = (short) (flag32 / (24 * 60));
 
284
 
 
285
                        /* some constant 0 for the stuff we handle */
 
286
                        flag32 = *((guint32 *)ptr);
 
287
                        ptr += sizeof (guint32);
 
288
                        if (flag32)
 
289
                                return FALSE;
 
290
 
 
291
                } else if (flag16 == PatternType_Week) {
 
292
                        /* Daily every weekday */
 
293
 
 
294
                        /* Calendar Type */
 
295
                        flag16 = *((guint16 *)ptr);
 
296
                        ptr += sizeof (guint16);
 
297
                        if (!check_calendar_type (flag16))
 
298
                                return FALSE;
 
299
 
 
300
        /* NOTE: Evolution does not handle daily-every-weekday any different 
 
301
         * from a weekly recurrence.
 
302
         */
 
303
                        rt.freq = ICAL_WEEKLY_RECURRENCE;
 
304
 
 
305
                        /* FirstDateTime (some crappy mod here) */
 
306
                        flag32 = *((guint32 *)ptr);
 
307
                        ptr += sizeof (guint32);
 
308
 
 
309
                        /* INTERVAL */
 
310
                        flag32 = *((guint32 *)ptr);
 
311
                        ptr += sizeof (guint32);
 
312
                        rt.interval = (short) (flag32);
 
313
 
 
314
                        /* some constant 0 for the stuff we handle */
 
315
                        flag32 = *((guint32 *)ptr);
 
316
                        ptr += sizeof (guint32);
 
317
                        if (flag32)
 
318
                                return FALSE;
 
319
 
 
320
                        /* BITMASK */
 
321
                        flag32 = *((guint32 *)ptr);
 
322
                        ptr += sizeof (guint32);
 
323
 
 
324
                        i = 0;
 
325
                        if (flag32 & olSunday)
 
326
                                rt.by_day[i++] = ICAL_SUNDAY_WEEKDAY;
 
327
                        if (flag32 & olMonday)
 
328
                                rt.by_day[i++] = ICAL_MONDAY_WEEKDAY;
 
329
                        if (flag32 & olTuesday)
 
330
                                rt.by_day[i++] = ICAL_TUESDAY_WEEKDAY;
 
331
                        if (flag32 & olWednesday)
 
332
                                rt.by_day[i++] = ICAL_WEDNESDAY_WEEKDAY;
 
333
                        if (flag32 & olThursday)
 
334
                                rt.by_day[i++] = ICAL_THURSDAY_WEEKDAY;
 
335
                        if (flag32 & olFriday)
 
336
                                rt.by_day[i++] = ICAL_FRIDAY_WEEKDAY;
 
337
                        if (flag32 & olSaturday)
 
338
                                rt.by_day[i++] = ICAL_SATURDAY_WEEKDAY;
 
339
                }
 
340
 
 
341
        } else if (flag16 == RecurFrequency_Weekly) {
 
342
                rt.freq = ICAL_WEEKLY_RECURRENCE;
 
343
 
 
344
                flag16 = *((guint16 *)ptr);
 
345
                ptr += sizeof (guint16);
 
346
                if (flag16 == PatternType_Week) {
 
347
                        /* weekly every N weeks (for all events and non-regenerating tasks) */
 
348
 
 
349
                        /* Calendar Type */
 
350
                        flag16 = *((guint16 *)ptr);
 
351
                        ptr += sizeof (guint16);
 
352
                        if (!check_calendar_type (flag16))
 
353
                                return FALSE;
 
354
 
 
355
                        /* FirstDateTime (some crappy mod here) */
 
356
                        flag32 = *((guint32 *)ptr);
 
357
                        ptr += sizeof (guint32);
 
358
 
 
359
                        /* INTERVAL */
 
360
                        flag32 = *((guint32 *)ptr);
 
361
                        ptr += sizeof (guint32);
 
362
                        rt.interval = (short) (flag32);
 
363
 
 
364
                        /* some constant 0 */
 
365
                        flag32 = *((guint32 *)ptr);
 
366
                        ptr += sizeof (guint32);
 
367
                        if (flag32)
 
368
                                return FALSE;
 
369
 
 
370
                        /* BITMASK */
 
371
                        flag32 = *((guint32 *)ptr);
 
372
                        ptr += sizeof (guint32);
 
373
 
 
374
                        i = 0;
 
375
                        if (flag32 & olSunday)
 
376
                                rt.by_day[i++] = ICAL_SUNDAY_WEEKDAY;
 
377
                        if (flag32 & olMonday)
 
378
                                rt.by_day[i++] = ICAL_MONDAY_WEEKDAY;
 
379
                        if (flag32 & olTuesday)
 
380
                                rt.by_day[i++] = ICAL_TUESDAY_WEEKDAY;
 
381
                        if (flag32 & olWednesday)
 
382
                                rt.by_day[i++] = ICAL_WEDNESDAY_WEEKDAY;
 
383
                        if (flag32 & olThursday)
 
384
                                rt.by_day[i++] = ICAL_THURSDAY_WEEKDAY;
 
385
                        if (flag32 & olFriday)
 
386
                                rt.by_day[i++] = ICAL_FRIDAY_WEEKDAY;
 
387
                        if (flag32 & olSaturday)
 
388
                                rt.by_day[i++] = ICAL_SATURDAY_WEEKDAY;
 
389
 
 
390
                } else if (flag16 == 0x0) {
 
391
                        /* weekly every N weeks (for all regenerating tasks) */
 
392
 
 
393
                        /* Calendar Type */
 
394
                        flag16 = *((guint16 *)ptr);
 
395
                        ptr += sizeof (guint16);
 
396
                        if (!check_calendar_type (flag16))
 
397
                                return FALSE;
 
398
 
 
399
                        /* FIXME: we don't handle regenerating tasks */
 
400
                        g_warning ("Evolution does not handle recurring tasks."); 
 
401
                        return FALSE;
 
402
                }
 
403
 
 
404
        } else if (flag16 == RecurFrequency_Monthly) {
 
405
                rt.freq = ICAL_MONTHLY_RECURRENCE;
 
406
 
 
407
                flag16 = *((guint16 *)ptr);
 
408
                ptr += sizeof (guint16);
 
409
                if (flag16 == PatternType_Month || flag16 == PatternType_MonthEnd) {
 
410
                        guint16 pattern = flag16; 
 
411
                        /* Monthly every N months on day D or last day. */
 
412
 
 
413
                        /* Calendar Type */
 
414
                        flag16 = *((guint16 *)ptr);
 
415
                        ptr += sizeof (guint16);
 
416
                        if (!check_calendar_type (flag16))
 
417
                                return FALSE;
 
418
 
 
419
                        /* FirstDateTime (some crappy mod here) */
 
420
                        flag32 = *((guint32 *)ptr);
 
421
                        ptr += sizeof (guint32);
 
422
 
 
423
                        /* INTERVAL */
 
424
                        flag32 = *((guint32 *)ptr);
 
425
                        ptr += sizeof (guint32);
 
426
                        rt.interval = (short) (flag32);
 
427
 
 
428
                        /* some constant 0 for the stuff we handle */
 
429
                        flag32 = *((guint32 *)ptr);
 
430
                        ptr += sizeof (guint32);
 
431
                        if (flag32)
 
432
                                return FALSE;
 
433
 
 
434
                        /* MONTH_DAY */ 
 
435
                        flag32 = *((guint32 *)ptr);
 
436
                        ptr += sizeof (guint32);
 
437
                        if (pattern == PatternType_Month)
 
438
                                rt.by_month_day[0] = (short) (flag32);
 
439
                        else if (pattern == PatternType_MonthEnd)
 
440
                                rt.by_month_day[0] = (short) (-1);
 
441
 
 
442
                } else if (flag16 == PatternType_MonthNth) {
 
443
                        gboolean post_process = FALSE; 
 
444
                        guint32 mask = 0;
 
445
                        /* Monthly every N months on the Xth Y */
 
446
 
 
447
                        /* Calendar Type */
 
448
                        flag16 = *((guint16 *)ptr);
 
449
                        ptr += sizeof (guint16);
 
450
                        if (!check_calendar_type (flag16))
 
451
                                return FALSE;
 
452
 
 
453
                        /* FirstDateTime (some crappy mod here) */
 
454
                        flag32 = *((guint32 *)ptr);
 
455
                        ptr += sizeof (guint32);
 
456
 
 
457
                        /* INTERVAL */
 
458
                        flag32 = *((guint32 *)ptr);
 
459
                        ptr += sizeof (guint32);
 
460
                        rt.interval = (short) (flag32);
 
461
 
 
462
                        /* some constant 0 for the stuff we handle */
 
463
                        flag32 = *((guint32 *)ptr);
 
464
                        ptr += sizeof (guint32);
 
465
                        if (flag32)
 
466
                                return FALSE;
 
467
                        
 
468
                        /* BITMASK */
 
469
                        flag32 = *((guint32 *)ptr);
 
470
                        ptr += sizeof (guint32);
 
471
                        if (flag32 == olSunday)
 
472
                                rt.by_day[0] = ICAL_SUNDAY_WEEKDAY;
 
473
                        else if (flag32 == olMonday)
 
474
                                rt.by_day[0] = ICAL_MONDAY_WEEKDAY;
 
475
                        else if (flag32 == olTuesday)
 
476
                                rt.by_day[0] = ICAL_TUESDAY_WEEKDAY;
 
477
                        else if (flag32 == olWednesday)
 
478
                                rt.by_day[0] = ICAL_WEDNESDAY_WEEKDAY;
 
479
                        else if (flag32 == olThursday)
 
480
                                rt.by_day[0] = ICAL_THURSDAY_WEEKDAY;
 
481
                        else if (flag32 == olFriday)
 
482
                                rt.by_day[0] = ICAL_FRIDAY_WEEKDAY;
 
483
                        else if (flag32 == olSaturday)
 
484
                                rt.by_day[0] = ICAL_SATURDAY_WEEKDAY;
 
485
                        else {
 
486
                                post_process = TRUE; 
 
487
                                mask = flag32; 
 
488
                        }
 
489
                                
 
490
                        /* RecurrenceN */
 
491
                        flag32 = *((guint32 *)ptr);
 
492
                        ptr += sizeof (guint32);
 
493
                        if (!post_process) {
 
494
                                rt.by_set_pos[0] = get_ical_pos (flag32); 
 
495
                                if (rt.by_set_pos[0] == 0)
 
496
                                        return FALSE; 
 
497
                        } else {
 
498
                                if (mask == (olSunday | olMonday | olTuesday | olWednesday | olThursday | olFriday | olSaturday)) {
 
499
                                        rt.by_month_day[0] = get_ical_pos (flag32); 
 
500
                                        if (rt.by_month_day[0] == 0)
 
501
                                                return FALSE; 
 
502
                                } else {
 
503
                                /* FIXME: Can we/LibICAL support any other types here? Namely, weekday and weekend-day */
 
504
                                        g_warning ("Encountered a recurrence type Evolution cannot handle. "); 
 
505
                                        return FALSE;
 
506
                                }
 
507
                        }
 
508
                }
 
509
 
 
510
        } else if (flag16 == RecurFrequency_Yearly) {
 
511
                rt.freq = ICAL_YEARLY_RECURRENCE;
 
512
 
 
513
                flag16 = *((guint16 *)ptr);
 
514
                ptr += sizeof (guint16);
 
515
                if (flag16 == PatternType_Month) {
 
516
                        /* Yearly on day D of month M */
 
517
 
 
518
                        /* Calendar Type */
 
519
                        flag16 = *((guint16 *)ptr);
 
520
                        ptr += sizeof (guint16);
 
521
                        if (!check_calendar_type (flag16))
 
522
                                return FALSE;
 
523
 
 
524
                        /* FirstDateTime (some crappy mod here) */
 
525
                        flag32 = *((guint32 *)ptr);
 
526
                        ptr += sizeof (guint32);
 
527
 
 
528
                        /* INTERVAL */
 
529
                        flag32 = *((guint32 *)ptr);
 
530
                        ptr += sizeof (guint32);
 
531
                        rt.interval = (short) (flag32 / 12);
 
532
 
 
533
                        /* some constant 0 for the stuff we handle */
 
534
                        flag32 = *((guint32 *)ptr);
 
535
                        ptr += sizeof (guint32);
 
536
                        if (flag32)
 
537
                                return FALSE;
 
538
 
 
539
                        /* MONTH_DAY - but we don't need this */
 
540
                        flag32 = *((guint32 *)ptr);
 
541
                        ptr += sizeof (guint32);
 
542
 
 
543
                } else if (flag16 == PatternType_MonthNth) {
 
544
                        /* Yearly on the Xth Y of month M */
 
545
 
 
546
                        g_warning ("Encountered a recurrence pattern Evolution cannot handle.");
 
547
 
 
548
                        /* Calendar Type */
 
549
                        flag16 = *((guint16 *)ptr);
 
550
                        ptr += sizeof (guint16);
 
551
                        if (!check_calendar_type (flag16))
 
552
                                return FALSE;
 
553
 
 
554
                        /* FirstDateTime (some crappy mod here) */
 
555
                        flag32 = *((guint32 *)ptr);
 
556
                        ptr += sizeof (guint32);
 
557
 
 
558
                        /* INTERVAL */
 
559
                        flag32 = *((guint32 *)ptr);
 
560
                        ptr += sizeof (guint32);
 
561
                        rt.interval = (short) (flag32 / 12);
 
562
 
 
563
                        /* some constant 0 */
 
564
                        flag32 = *((guint32 *)ptr);
 
565
                        ptr += sizeof (guint32);
 
566
                        if (flag32)
 
567
                                return FALSE;
 
568
 
 
569
                        /* BITMASK */
 
570
                        flag32 = *((guint32 *)ptr);
 
571
                        ptr += sizeof (guint32);
 
572
 
 
573
                        /* RecurrenceN */
 
574
                        flag32 = *((guint32 *)ptr);
 
575
                        ptr += sizeof (guint32);
 
576
 
 
577
                        /* TODO: Add support for this kinda recurrence in Evolution */
 
578
                        return FALSE;
 
579
                }
 
580
        } else 
 
581
                return FALSE;
 
582
 
 
583
        /* End Type - followed by Occurence count */
 
584
        flag32 = *((guint32 *)ptr);
 
585
        ptr += sizeof (guint32);
 
586
        if (flag32 == END_AFTER_DATE) {
 
587
                flag32 = *((guint32 *)ptr);
 
588
                ptr += sizeof (guint32);
 
589
 
 
590
                repeats_until_date = TRUE;
 
591
        } else if (flag32 == END_AFTER_N_OCCURRENCES) {
 
592
                flag32 = *((guint32 *)ptr);
 
593
                ptr += sizeof (guint32);
 
594
 
 
595
                rt.count = flag32;
 
596
        } else if (flag32 == END_NEVER_END) {
 
597
                flag32 = *((guint32 *)ptr);
 
598
                ptr += sizeof (guint32);
 
599
        }
 
600
 
 
601
        /* week_start */
 
602
        flag32 = *((guint32 *)ptr);
 
603
        ptr += sizeof (guint32);
 
604
        rt.week_start = get_ical_weekstart (flag32);
 
605
 
 
606
        /* number of exceptions */
 
607
        flag32 = *((guint32 *)ptr);
 
608
        ptr += sizeof (guint32);
 
609
        if (flag32) {
 
610
                for (i = 0; i < flag32; ++i) {
 
611
                        uint32_t exdate; 
 
612
                        struct icaltimetype tt, *val; 
 
613
                        ECalComponentDateTime *dt = g_new0 (ECalComponentDateTime, 1); 
 
614
 
 
615
                        exdate = *((guint32 *)ptr);
 
616
                        ptr += sizeof (guint32);
 
617
 
 
618
                        tt = icaltime_from_timet_with_zone (convert_recurrence_minutes_to_timet (exdate), 1, 0);
 
619
 
 
620
                        val = g_new0(struct icaltimetype, 1); 
 
621
                        memcpy (val, &tt, sizeof(struct icaltimetype)); 
 
622
 
 
623
                        dt->value = val; 
 
624
                        dt->tzid = g_strdup ("UTC"); 
 
625
 
 
626
                        exdate_list = g_slist_append (exdate_list, dt); 
 
627
                }
 
628
        }
 
629
 
 
630
        /* number of changed exceptions */
 
631
        flag32 = *((guint32 *)ptr);
 
632
        ptr += sizeof (guint32);
 
633
        /* FIXME: Parse modified instances */
 
634
        if (flag32) 
 
635
                ptr += flag32 * sizeof (guint32);
 
636
        
 
637
        /* start date */
 
638
        flag32 = *((guint32 *)ptr);
 
639
        ptr += sizeof (guint32);
 
640
 
 
641
        /* end date */
 
642
        flag32 = *((guint32 *)ptr);
 
643
        ptr += sizeof (guint32);
 
644
        if (repeats_until_date) {
 
645
                rt.until = icaltime_from_timet_with_zone (convert_recurrence_minutes_to_timet (flag32), 1, 0);
 
646
        }
 
647
 
 
648
        /* some constant */
 
649
        flag32 = *((guint32 *)ptr);
 
650
        ptr += sizeof (guint32);
 
651
        if (flag32 != READER_VERSION2)
 
652
                return FALSE;
 
653
 
 
654
        /* some constant */
 
655
        flag32 = *((guint32 *)ptr);
 
656
        ptr += sizeof (guint32);
 
657
        if (flag32 != WRITER_VERSION2)
 
658
                return FALSE;
 
659
 
 
660
        /* start time in mins */
 
661
        flag32 = *((guint32 *)ptr);
 
662
        ptr += sizeof (guint32);
 
663
 
 
664
        /* end time in mins */
 
665
        flag32 = *((guint32 *)ptr);
 
666
        ptr += sizeof (guint32);
 
667
 
 
668
        /* modified exceptions */
 
669
        flag16 = *((guint16 *)ptr);
 
670
        ptr += sizeof (guint16);
 
671
        if (flag16 != 0x0)
 
672
                return FALSE;
 
673
 
 
674
        /* reserved block1 size - has to be 0 */
 
675
        flag32 = *((guint32 *)ptr);
 
676
        ptr += sizeof (guint32);
 
677
        if (flag32 != 0x0)
 
678
                return FALSE;
 
679
 
 
680
        /* reserved block2 size - has to be 0 */
 
681
        flag32 = *((guint32 *)ptr);
 
682
        ptr += sizeof (guint32);
 
683
        if (flag32 != 0x0)
 
684
                return FALSE;
 
685
 
 
686
        /* Set the recurrence */
 
687
        {
 
688
                GSList l;
 
689
 
 
690
                l.data = &rt; 
 
691
                l.next = NULL;
 
692
 
 
693
                e_cal_component_set_rrule_list (comp, &l);
 
694
        }
 
695
 
 
696
        /* FIXME: this also has modified instances */
 
697
        e_cal_component_set_exdate_list (comp, exdate_list); 
 
698
 
 
699
        g_print ("\n== MAPI to ICAL == The recurrence blob data is as follows:\n");
 
700
        for (i = 0; i < ba->len; ++i)
 
701
                g_print ("0x%02X ", ba->data[i]);
 
702
        g_print("\n== End of stream ==\n"); 
 
703
 
 
704
        return TRUE;
 
705
}
 
706
 
 
707
static guint32
 
708
compute_startdate (ECalComponent *comp)
 
709
{
 
710
        ECalComponentDateTime dtstart; 
 
711
        guint32 flag32; 
 
712
 
 
713
        e_cal_component_get_dtstart (comp, &dtstart);
 
714
        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0; 
 
715
        flag32 = convert_timet_to_recurrence_minutes (icaltime_as_timet_with_zone (*(dtstart.value), 0));
 
716
 
 
717
        e_cal_component_free_datetime (&dtstart); 
 
718
 
 
719
        return flag32; 
 
720
}
 
721
 
 
722
static guint32
 
723
compute_rdaily_firstdatetime (ECalComponent *comp, guint32 period)
 
724
{
 
725
        return (compute_startdate (comp) % period);
 
726
}
 
727
 
 
728
static guint32
 
729
compute_rweekly_firstdatetime (ECalComponent *comp, icalrecurrencetype_weekday week_start, guint32 period)
 
730
{
 
731
        ECalComponentDateTime dtstart; 
 
732
        guint32 flag32; 
 
733
        int cur_weekday = 0, weekstart_weekday = 0, diff = 0;
 
734
        time_t t; 
 
735
 
 
736
        e_cal_component_get_dtstart (comp, &dtstart);
 
737
        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0; 
 
738
        cur_weekday = icaltime_day_of_week (*(dtstart.value));
 
739
        t = icaltime_as_timet_with_zone (*(dtstart.value), 0);
 
740
        e_cal_component_free_datetime (&dtstart); 
 
741
 
 
742
        switch (week_start) {
 
743
                case ICAL_SUNDAY_WEEKDAY        : weekstart_weekday = 1; break; 
 
744
                case ICAL_MONDAY_WEEKDAY        : weekstart_weekday = 2; break; 
 
745
                case ICAL_TUESDAY_WEEKDAY       : weekstart_weekday = 3; break; 
 
746
                case ICAL_WEDNESDAY_WEEKDAY     : weekstart_weekday = 4; break; 
 
747
                case ICAL_THURSDAY_WEEKDAY      : weekstart_weekday = 5; break; 
 
748
                case ICAL_FRIDAY_WEEKDAY        : weekstart_weekday = 6; break; 
 
749
                case ICAL_SATURDAY_WEEKDAY      : weekstart_weekday = 7; break; 
 
750
                default                         : weekstart_weekday = 1; break; 
 
751
        };
 
752
 
 
753
        diff = cur_weekday - weekstart_weekday; 
 
754
 
 
755
        if (diff == 0); 
 
756
        else if (diff > 0)
 
757
                t -= (diff * 24 * 60 * 60);
 
758
        else if (diff < 0)
 
759
                t -= ((diff + 7) * 24 * 60 * 60);
 
760
 
 
761
        flag32 = convert_timet_to_recurrence_minutes (t);
 
762
 
 
763
        return (flag32 % period);
 
764
}
 
765
 
 
766
/* The most fucked up algorithm ever conceived by (..you know who..) */
 
767
static guint32
 
768
compute_rmonthly_firstdatetime (ECalComponent *comp, guint32 period)
 
769
{
 
770
        const guint8 dinm[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
771
        ECalComponentDateTime dtstart; 
 
772
        guint32 flag32, monthindex, i; 
 
773
 
 
774
        e_cal_component_get_dtstart (comp, &dtstart);
 
775
        monthindex = (guint32)((((guint64)(12) * (dtstart.value->year - 1601)) + (dtstart.value->month - 1)) % period); 
 
776
        e_cal_component_free_datetime (&dtstart); 
 
777
 
 
778
        for (flag32 = 0, i = 0; i < monthindex; ++i)
 
779
                flag32 += dinm[(i % 12) + 1] * 24 * 60;
 
780
 
 
781
        return flag32; 
 
782
}
 
783
 
 
784
static guint32
 
785
calculate_no_of_occurrences (ECalComponent *comp, const struct icalrecurrencetype *rt)
 
786
{
 
787
        ECalComponentDateTime dtstart; 
 
788
        icalrecur_iterator *iter; 
 
789
        struct icaltimetype next; 
 
790
        guint32 count = 1; 
 
791
 
 
792
        e_cal_component_get_dtstart (comp, &dtstart);
 
793
 
 
794
        for (iter = icalrecur_iterator_new (*rt, *(dtstart.value)), 
 
795
             next = icalrecur_iterator_next(iter);
 
796
             !icaltime_is_null_time(next);
 
797
             next = icalrecur_iterator_next(iter))
 
798
                ++count; 
 
799
 
 
800
        icalrecur_iterator_free (iter); 
 
801
        e_cal_component_free_datetime (&dtstart); 
 
802
 
 
803
        return count; 
 
804
}
 
805
 
 
806
static gint 
 
807
compare_guint32 (gconstpointer a, gconstpointer b, gpointer user_data)
 
808
{
 
809
        return (*((guint32 *) a) - *((guint32 *) b));
 
810
}
 
811
 
 
812
GByteArray *
 
813
exchange_mapi_cal_util_rrule_to_bin (ECalComponent *comp, GSList *modified_comps)
 
814
{
 
815
        struct icalrecurrencetype *rt;
 
816
        guint16 flag16;
 
817
        guint32 flag32, end_type;
 
818
        gint i; 
 
819
        GSList *rrule_list = NULL, *exdate_list = NULL; 
 
820
        GByteArray *ba = NULL;
 
821
 
 
822
        if (!e_cal_component_has_recurrences (comp))
 
823
                return NULL; 
 
824
 
 
825
        e_cal_component_get_rrule_list (comp, &rrule_list); 
 
826
        e_cal_component_get_exdate_list (comp, &exdate_list); 
 
827
 
 
828
        if (g_slist_length (rrule_list) != 1)
 
829
                goto cleanup; 
 
830
 
 
831
        rt = (struct icalrecurrencetype *)(rrule_list->data);
 
832
 
 
833
        ba = g_byte_array_new (); 
 
834
 
 
835
        /* Reader Version */
 
836
        flag16 = READER_VERSION;
 
837
        ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
838
 
 
839
        /* Writer Version */
 
840
        flag16 = WRITER_VERSION;
 
841
        ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
842
 
 
843
        if (rt->freq == ICAL_DAILY_RECURRENCE) {
 
844
                flag16 = RecurFrequency_Daily;
 
845
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
846
 
 
847
                /* Pattern Type - it would be PatternType_Day since we have only "Daily every N days" 
 
848
                 * The other type would be parsed as a weekly recurrence. 
 
849
                 */
 
850
                flag16 = PatternType_Day;
 
851
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
852
 
 
853
                /* Calendar Type */
 
854
                flag16 = CAL_DEFAULT; 
 
855
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
856
 
 
857
                /* FirstDateTime */
 
858
                flag32 = compute_rdaily_firstdatetime (comp, (rt->interval * (60 * 24)));
 
859
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
860
 
 
861
                /* INTERVAL */
 
862
                flag32 = (rt->interval * (60 * 24)); 
 
863
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
864
 
 
865
                /* This would be 0 for the stuff we handle */
 
866
                flag32 = 0x0;
 
867
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
868
 
 
869
                /* No PatternTypeSpecific for PatternType_Day */
 
870
 
 
871
        } else if (rt->freq == ICAL_WEEKLY_RECURRENCE) {
 
872
                flag16 = RecurFrequency_Weekly;
 
873
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
874
 
 
875
                /* Pattern Type - it would be PatternType_Week since we don't support any other type. */
 
876
                flag16 = PatternType_Week;
 
877
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
878
 
 
879
                /* Calendar Type */
 
880
                flag16 = CAL_DEFAULT; 
 
881
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
882
 
 
883
                /* FirstDateTime */
 
884
                flag32 = compute_rweekly_firstdatetime (comp, rt->week_start, (rt->interval * (60 * 24 * 7)));
 
885
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
886
 
 
887
                /* INTERVAL */
 
888
                flag32 = rt->interval; 
 
889
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
890
 
 
891
                /* This would be 0 for the stuff we handle */
 
892
                flag32 = 0x0;
 
893
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
894
 
 
895
                /* BITMASK */
 
896
                for (flag32 = 0x0, i = 0; i < ICAL_BY_DAY_SIZE; ++i) {
 
897
                        if (rt->by_day[i] == ICAL_SUNDAY_WEEKDAY)
 
898
                                flag32 |= olSunday; 
 
899
                        else if (rt->by_day[i] == ICAL_MONDAY_WEEKDAY)
 
900
                                flag32 |= olMonday; 
 
901
                        else if (rt->by_day[i] == ICAL_TUESDAY_WEEKDAY)
 
902
                                flag32 |= olTuesday; 
 
903
                        else if (rt->by_day[i] == ICAL_WEDNESDAY_WEEKDAY)
 
904
                                flag32 |= olWednesday; 
 
905
                        else if (rt->by_day[i] == ICAL_THURSDAY_WEEKDAY)
 
906
                                flag32 |= olThursday; 
 
907
                        else if (rt->by_day[i] == ICAL_FRIDAY_WEEKDAY)
 
908
                                flag32 |= olFriday; 
 
909
                        else if (rt->by_day[i] == ICAL_SATURDAY_WEEKDAY)
 
910
                                flag32 |= olSaturday; 
 
911
                        else 
 
912
                                break; 
 
913
                }
 
914
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
915
 
 
916
        } else if (rt->freq == ICAL_MONTHLY_RECURRENCE) {
 
917
                guint16 pattern = 0x0; guint32 mask = 0x0, flag = 0x0; 
 
918
 
 
919
                flag16 = RecurFrequency_Monthly;
 
920
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
921
 
 
922
                if (rt->by_month_day[0] >= 1 && rt->by_month_day[0] <= 31) {
 
923
                        pattern = PatternType_Month;
 
924
                        flag = rt->by_month_day[0]; 
 
925
                } else if (rt->by_month_day[0] == -1) {
 
926
                        pattern = PatternType_MonthNth; 
 
927
                        mask = (olSunday | olMonday | olTuesday | olWednesday | olThursday | olFriday | olSaturday); 
 
928
                        flag = RecurrenceN_Last; 
 
929
                } else if (rt->by_day[0] >= ICAL_SUNDAY_WEEKDAY && rt->by_day[0] <= ICAL_SATURDAY_WEEKDAY) {
 
930
                        pattern = PatternType_MonthNth;
 
931
                        mask = get_mapi_day (rt->by_day[0]);
 
932
                        flag = get_mapi_pos (rt->by_set_pos[0]);
 
933
                }
 
934
 
 
935
                /* Pattern Type */
 
936
                flag16 = pattern;
 
937
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
938
 
 
939
                /* Calendar Type */
 
940
                flag16 = CAL_DEFAULT; 
 
941
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
942
 
 
943
                /* FirstDateTime */
 
944
                flag32 = compute_rmonthly_firstdatetime (comp, rt->interval);
 
945
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
946
 
 
947
                /* INTERVAL */
 
948
                flag32 = rt->interval; 
 
949
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
950
 
 
951
                /* This would be 0 for the stuff we handle */
 
952
                flag32 = 0x0;
 
953
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
954
 
 
955
                if (pattern == PatternType_Month) {
 
956
                        flag32 = flag;
 
957
                        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
958
 
 
959
                        if (!(flag))
 
960
                                g_warning ("Possibly setting incorrect values in the stream. "); 
 
961
                } else if (pattern == PatternType_MonthNth) {
 
962
                        flag32 = mask;
 
963
                        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
964
 
 
965
                        flag32 = flag;
 
966
                        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
967
 
 
968
                        if (!(flag && mask))
 
969
                                g_warning ("Possibly setting incorrect values in the stream. "); 
 
970
                } else 
 
971
                        g_warning ("Possibly setting incorrect values in the stream. "); 
 
972
 
 
973
        } else if (rt->freq == ICAL_YEARLY_RECURRENCE) {
 
974
                flag16 = RecurFrequency_Yearly;
 
975
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
976
 
 
977
                /* Pattern Type - it would be PatternType_Month since we don't support any other type. */
 
978
                flag16 = PatternType_Month;
 
979
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
980
 
 
981
                /* Calendar Type */
 
982
                flag16 = CAL_DEFAULT; 
 
983
                ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
984
 
 
985
                /* FirstDateTime - uses the same function as monthly recurrence */
 
986
                flag32 = compute_rmonthly_firstdatetime (comp, 0xC);
 
987
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
988
 
 
989
                /* INTERVAL - should be 12 for yearly recurrence */
 
990
                flag32 = 0xC; 
 
991
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
992
 
 
993
                /* This would be 0 for the stuff we handle */
 
994
                flag32 = 0x0;
 
995
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
996
 
 
997
                /* MONTH_DAY */
 
998
                {
 
999
                        ECalComponentDateTime dtstart; 
 
1000
                        e_cal_component_get_dtstart (comp, &dtstart);
 
1001
                        flag32 = dtstart.value->day; 
 
1002
                        e_cal_component_free_datetime (&dtstart); 
 
1003
                }
 
1004
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1005
 
 
1006
        } 
 
1007
 
 
1008
        /* End Type followed by Occurence count */
 
1009
        if (!icaltime_is_null_time (rt->until)) {
 
1010
                flag32 = END_AFTER_DATE;
 
1011
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1012
 
 
1013
                flag32 = calculate_no_of_occurrences (comp, rt); 
 
1014
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1015
 
 
1016
                end_type = END_AFTER_DATE;
 
1017
        } else if (rt->count) {
 
1018
                flag32 = END_AFTER_N_OCCURRENCES;
 
1019
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1020
 
 
1021
                flag32 = rt->count;
 
1022
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1023
 
 
1024
                end_type = END_AFTER_N_OCCURRENCES;
 
1025
        } else {
 
1026
                flag32 = END_NEVER_END;
 
1027
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1028
 
 
1029
                flag32 = 0x0;
 
1030
                ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1031
 
 
1032
                end_type = END_NEVER_END;
 
1033
        }
 
1034
 
 
1035
        /* FirstDOW */
 
1036
        flag32 = get_mapi_weekstart (rt->week_start); 
 
1037
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1038
 
 
1039
        /* DeletedInstances */
 
1040
        flag32 = g_slist_length (exdate_list);
 
1041
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1042
        if (flag32) {
 
1043
                GSList *l; 
 
1044
                guint32 *sorted_list = g_new0(guint32, flag32);
 
1045
                /* FIXME: This should include modified dates */
 
1046
                for (i = 0, l = exdate_list; l; ++i, l = l->next) {
 
1047
                        ECalComponentDateTime *dt = (ECalComponentDateTime *)(l->data); 
 
1048
                        dt->value->hour = dt->value->minute = dt->value->second = 0; 
 
1049
                        sorted_list[i] = convert_timet_to_recurrence_minutes (icaltime_as_timet_with_zone (*(dt->value), 0)); 
 
1050
                }
 
1051
 
 
1052
                g_qsort_with_data (sorted_list, flag32, sizeof (guint32), compare_guint32, NULL); 
 
1053
 
 
1054
                for (i = 0; i < flag32; ++i)
 
1055
                        ba = g_byte_array_append (ba, (const guint8 *)&(sorted_list[i]), sizeof (guint32));
 
1056
 
 
1057
                g_free (sorted_list);
 
1058
        }
 
1059
 
 
1060
        /* FIXME: Add support for modified instances */
 
1061
        /* ModifiedInstanceCount */
 
1062
        flag32 = 0x0;
 
1063
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1064
        if (flag32) {
 
1065
        }
 
1066
 
 
1067
        /* StartDate */
 
1068
        flag32 = compute_startdate (comp); 
 
1069
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1070
 
 
1071
        /* EndDate */
 
1072
        {
 
1073
                if (end_type == END_NEVER_END) 
 
1074
                        flag32 = 0x5AE980DF; 
 
1075
                else if (end_type == END_AFTER_N_OCCURRENCES) {
 
1076
                        ECalComponentDateTime dtstart; 
 
1077
                        gchar *rrule_str = icalrecurrencetype_as_string_r (rt); 
 
1078
                        time_t *array = g_new0 (time_t, rt->count); 
 
1079
 
 
1080
                        e_cal_component_get_dtstart (comp, &dtstart);
 
1081
                        dtstart.value->hour = dtstart.value->minute = dtstart.value->second = 0; 
 
1082
 
 
1083
                        icalrecur_expand_recurrence (rrule_str, icaltime_as_timet_with_zone (*(dtstart.value), 0), rt->count, array); 
 
1084
 
 
1085
                        flag32 = convert_timet_to_recurrence_minutes (array[(rt->count) - 1]); 
 
1086
 
 
1087
                        g_free (array); 
 
1088
                        g_free (rrule_str); 
 
1089
                        e_cal_component_free_datetime (&dtstart); 
 
1090
                } else if (end_type == END_AFTER_DATE) {
 
1091
                        struct icaltimetype until; 
 
1092
                        memcpy (&until, &(rt->until), sizeof(struct icaltimetype));
 
1093
                        until.hour = until.minute = until.second = 0; 
 
1094
                        flag32 = convert_timet_to_recurrence_minutes (icaltime_as_timet_with_zone (until, 0));
 
1095
                } else 
 
1096
                        flag32 = 0x0; 
 
1097
        }
 
1098
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1099
 
 
1100
        /* Reader Version 2 */
 
1101
        flag32 = READER_VERSION2;
 
1102
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1103
 
 
1104
        /* Writer Version 2 */
 
1105
        flag32 = WRITER_VERSION2;
 
1106
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1107
 
 
1108
        /* StartTimeOffset */
 
1109
        {
 
1110
                ECalComponentDateTime dtstart; 
 
1111
                e_cal_component_get_dtstart (comp, &dtstart);
 
1112
                flag32 = (dtstart.value->hour * 60) + dtstart.value->minute; 
 
1113
                e_cal_component_free_datetime (&dtstart); 
 
1114
        }
 
1115
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1116
 
 
1117
        /* EndTimeOffset */
 
1118
        {
 
1119
                ECalComponentDateTime dtend; 
 
1120
                e_cal_component_get_dtend (comp, &dtend);
 
1121
                flag32 = (dtend.value->hour * 60) + dtend.value->minute; 
 
1122
                e_cal_component_free_datetime (&dtend); 
 
1123
        }
 
1124
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1125
 
 
1126
        /* FIXME: Add support for modified instances */
 
1127
        /* ModifiedExceptionCount */
 
1128
        flag16 = 0x0; 
 
1129
        ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16));
 
1130
 
 
1131
        /* FIXME: Add the ExceptionInfo here */
 
1132
 
 
1133
        /* Reserved Block 1 Size */
 
1134
        flag32 = 0x0;
 
1135
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1136
 
 
1137
        /* FIXME: Add the ExtendedExceptionInfo here */
 
1138
 
 
1139
        /* Reserved Block 2 Size */
 
1140
        flag32 = 0x0;
 
1141
        ba = g_byte_array_append (ba, (const guint8 *)&flag32, sizeof (guint32));
 
1142
 
 
1143
cleanup: 
 
1144
        e_cal_component_free_exdate_list (exdate_list);
 
1145
        e_cal_component_free_recur_list (rrule_list);
 
1146
 
 
1147
        g_print ("\n== ICAL to MAPI == The recurrence blob data is as follows:\n");
 
1148
        for (i = 0; i < ba->len; ++i)
 
1149
                g_print ("0x%02X ", ba->data[i]);
 
1150
        g_print("\n== End of stream ==\n"); 
 
1151
 
 
1152
        return ba; 
 
1153
}
 
1154