2 Convert Exchange appointments and meetings to ICAL files
6 Copyright (C) Julien Kerihuel 2008
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "libexchange2ical/libexchange2ical.h"
30 static const struct RRULE_byday RRULE_byday[] = {
41 static const char *get_filename(const char *filename)
45 if (!filename) return NULL;
47 substr = rindex(filename, '/');
48 if (substr) return substr;
54 void ical_property_ATTACH(struct exchange2ical *exchange2ical)
56 mapi_object_t obj_tb_attach;
57 mapi_object_t obj_attach;
58 mapi_object_t obj_stream;
59 struct SRowSet rowset_attach;
60 struct SPropTagArray *SPropTagArray = NULL;
61 const uint32_t *attach_num = NULL;
62 struct SPropValue *lpProps;
63 enum MAPISTATUS retval;
69 mapi_object_init(&obj_tb_attach);
70 retval = GetAttachmentTable(&exchange2ical->obj_message, &obj_tb_attach);
71 if (retval == MAPI_E_SUCCESS) {
72 SPropTagArray = set_SPropTagArray(exchange2ical->mem_ctx, 0x1, PR_ATTACH_NUM);
73 retval = SetColumns(&obj_tb_attach, SPropTagArray);
74 MAPIFreeBuffer(SPropTagArray);
75 retval = QueryRows(&obj_tb_attach, 0xa, TBL_ADVANCE, &rowset_attach);
77 for (i = 0; i < rowset_attach.cRows; i++) {
78 attach_num = (const uint32_t *)find_SPropValue_data(&(rowset_attach.aRow[i]), PR_ATTACH_NUM);
79 retval = OpenAttach(&exchange2ical->obj_message, *attach_num, &obj_attach);
81 if (retval == MAPI_E_SUCCESS) {
83 SPropTagArray = set_SPropTagArray(exchange2ical->mem_ctx, 0x7,
85 PR_ATTACH_LONG_FILENAME,
93 lpProps = talloc_zero(exchange2ical->mem_ctx, struct SPropValue);
94 retval = GetProps(&obj_attach, MAPI_UNICODE, SPropTagArray, &lpProps, &count);
95 MAPIFreeBuffer(SPropTagArray);
96 if (retval == MAPI_E_SUCCESS) {
98 uint32_t *attachmentFlags = NULL;
99 uint32_t *attachMethod = NULL;
100 uint8_t *attachmentHidden = NULL;
101 const char *data = NULL;
102 const char *fmttype = NULL;
103 const char *attach_filename = NULL;
105 icalattach *icalattach = NULL;
106 icalproperty *prop = NULL;
107 icalparameter *param = NULL;
110 aRow2.ulAdrEntryPad = 0;
111 aRow2.cValues = count;
112 aRow2.lpProps = lpProps;
114 attachmentFlags = octool_get_propval(&aRow2, PR_ATTACHMENT_FLAGS);
115 attachMethod = octool_get_propval(&aRow2, PR_ATTACH_METHOD);
116 attachmentHidden = octool_get_propval(&aRow2, PR_ATTACHMENT_HIDDEN);
118 if(attachmentFlags && !(*attachmentFlags & 0x00000007)
119 && (*attachMethod == 0x00000001)
120 && (!attachmentHidden || !(*attachmentHidden))) {
122 /* Get data of attachment */
123 retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 0, &obj_stream);
124 retval = octool_get_stream(exchange2ical->mem_ctx, &obj_stream, &body);
125 data=ldb_base64_encode(exchange2ical->mem_ctx, (const char *)body.data, body.length);
127 /*Create a new icalattach from above data*/
129 /* the function signature for icalattach_new_from_data() changed in 0.46, released 2010-08-30 */
130 /* we can switch to just using the new signature after everyone has had a reasonable chance to update (say end of 2011) */
131 icalattach = icalattach_new_from_data(data, 0, 0);
133 icalattach = icalattach_new_from_data((unsigned char *)data,0,0);
135 /*Add attach property to vevent component*/
136 prop = icalproperty_new_attach(icalattach);
137 icalcomponent_add_property(exchange2ical->vevent, prop);
139 /* Attachment filename for X-FILENAME parameter*/
140 attach_filename = get_filename(octool_get_propval(&aRow2, PR_ATTACH_LONG_FILENAME));
141 if (!attach_filename || (attach_filename && !strcmp(attach_filename, ""))) {
142 attach_filename = get_filename(octool_get_propval(&aRow2, PR_ATTACH_FILENAME));
145 /* fmttype parameter */
146 fmttype = (const char *) octool_get_propval(&aRow2, PR_ATTACH_MIME_TAG);
148 param = icalparameter_new_fmttype(fmttype);
149 icalproperty_add_parameter(prop, param);
152 /* ENCODING parameter */
153 param =icalparameter_new_encoding(ICAL_ENCODING_BASE64);
154 icalproperty_add_parameter(prop,param);
156 /* VALUE parameter */
157 param=icalparameter_new_value(ICAL_VALUE_BINARY);
158 icalproperty_add_parameter(prop,param);
160 /* X-FILENAME parameter */
161 param = icalparameter_new_x(attach_filename);
162 icalparameter_set_xname(param,"X-FILENAME");
163 icalproperty_add_parameter(prop,param);
165 MAPIFreeBuffer(lpProps);
170 mapi_object_release(&obj_tb_attach);
174 // TODO: check this - need an example
175 void ical_property_ATTENDEE(struct exchange2ical *exchange2ical)
179 const char *display_name;
180 uint32_t *RecipientFlags;
181 uint32_t *RecipientType;
182 uint32_t *TrackStatus;
183 struct SRowSet *SRowSet;
186 if (!exchange2ical->apptStateFlags) return;
187 if (!(*exchange2ical->apptStateFlags & 0x1)) return;
188 SRowSet = &(exchange2ical->Recipients.SRowSet);
190 /* Loop over the recipient table */
191 for (i = 0; i < SRowSet->cRows; i++) {
192 smtp = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_SMTP_ADDRESS);
193 display_name = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_DISPLAY_NAME);
194 RecipientFlags = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_FLAGS);
195 RecipientType = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_TYPE);
196 TrackStatus = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_TRACKSTATUS);
199 if (RecipientFlags && !(*RecipientFlags & 0x20) && !(*RecipientFlags & 0x2) &&
200 (RecipientType && *RecipientType)) {
203 icalparameter *participantType;
204 enum icalparameter_partstat partstat = ICAL_PARTSTAT_NONE;
208 mailtoURL = talloc_strdup(exchange2ical->mem_ctx, "mailto:");
209 mailtoURL = talloc_strdup_append(mailtoURL, smtp);
210 prop = icalproperty_new_attendee(mailtoURL);
211 icalcomponent_add_property(exchange2ical->vevent, prop);
213 prop = icalproperty_new_attendee("invalid:nomail");
214 icalcomponent_add_property(exchange2ical->vevent, prop);
218 cn = icalparameter_new_cn(display_name);
219 icalproperty_add_parameter(prop, cn);
222 if (*RecipientType == 0x3) {
223 icalparameter *cutype = icalparameter_new_cutype(ICAL_CUTYPE_RESOURCE);
224 icalproperty_add_parameter(prop, cutype);
227 switch (*RecipientType) {
229 participantType = icalparameter_new_role(ICAL_ROLE_OPTPARTICIPANT);
230 icalproperty_add_parameter(prop, participantType);
233 participantType = icalparameter_new_role(ICAL_ROLE_NONPARTICIPANT);
234 icalproperty_add_parameter(prop, participantType);
240 if((exchange2ical->method==ICAL_METHOD_REPLY) || (exchange2ical->method==ICAL_METHOD_COUNTER)){
241 partstat = exchange2ical->partstat;
242 }else if(exchange2ical->method==ICAL_METHOD_PUBLISH){
244 partstat = get_ical_partstat_from_status(*TrackStatus);
245 }else if(exchange2ical->ResponseStatus){
246 partstat = get_ical_partstat_from_status(*exchange2ical->ResponseStatus);
250 if (partstat != ICAL_PARTSTAT_NONE) {
251 icalparameter *param;
252 param = icalparameter_new_partstat(partstat);
253 icalproperty_add_parameter(prop, param);
256 if (exchange2ical->ResponseRequested) {
258 if (*(exchange2ical->ResponseRequested)) {
259 rsvp = icalparameter_new_rsvp(ICAL_RSVP_TRUE);
261 rsvp = icalparameter_new_rsvp(ICAL_RSVP_FALSE);
263 icalproperty_add_parameter(prop, rsvp);
270 void ical_property_CATEGORIES(struct exchange2ical *exchange2ical)
276 if (!exchange2ical->Keywords) return;
277 if (!exchange2ical->Keywords->cValues) return;
279 for (i = 0; i < exchange2ical->Keywords->cValues; i++) {
280 prop = icalproperty_new_categories(exchange2ical->Keywords->lppszA[i]);
281 icalcomponent_add_property(exchange2ical->vevent, prop);
287 void ical_property_CLASS(struct exchange2ical *exchange2ical)
292 if (!exchange2ical->sensitivity) return;
294 prop = icalproperty_new_class(get_ical_class(*exchange2ical->sensitivity));
295 icalcomponent_add_property(exchange2ical->vevent, prop);
299 void ical_property_CONTACT(struct exchange2ical *exchange2ical)
305 if (!exchange2ical->Contacts) return;
306 if (!exchange2ical->Contacts->cValues) return;
308 for (i = 0; i < exchange2ical->Contacts->cValues; i++) {
309 prop = icalproperty_new_contact(exchange2ical->Contacts->lppszA[i]);
310 icalcomponent_add_property(exchange2ical->vevent, prop);
315 void ical_property_CREATED(struct exchange2ical *exchange2ical)
318 struct icaltimetype icaltime;
321 if (!exchange2ical->created) return;
323 icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->created);
325 prop = icalproperty_new_created(icaltime);
326 icalcomponent_add_property(exchange2ical->vevent, prop);
329 void ical_property_DTSTART(struct exchange2ical *exchange2ical)
333 struct icaltimetype icaltime;
336 if (!exchange2ical->apptStartWhole) return;
338 /* If this is an all-day appointment */
339 if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
340 icaltime = get_icaldate_from_FILETIME(exchange2ical->apptStartWhole);
341 prop = icalproperty_new_dtstart(icaltime);
342 icalcomponent_add_property(exchange2ical->vevent, prop);
344 if (exchange2ical->TimeZoneDesc) {
345 icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole);
346 prop = icalproperty_new_dtstart(icaltime);
347 icalcomponent_add_property(exchange2ical->vevent, prop);
348 tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
349 icalproperty_add_parameter(prop, tzid);
351 icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->apptStartWhole);
352 prop = icalproperty_new_dtstart(icaltime);
353 icalcomponent_add_property(exchange2ical->vevent, prop);
361 void ical_property_DTEND(struct exchange2ical *exchange2ical)
365 struct icaltimetype icaltime;
368 if (!exchange2ical->apptEndWhole) return;
370 /* If this is an all-day appointment */
371 if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
372 icaltime = get_icaldate_from_FILETIME(exchange2ical->apptEndWhole);
373 prop = icalproperty_new_dtend(icaltime);
374 icalcomponent_add_property(exchange2ical->vevent, prop);
376 if (exchange2ical->TimeZoneDesc) {
377 icaltime = get_icaltime_from_FILETIME(exchange2ical->apptEndWhole);
378 prop = icalproperty_new_dtend(icaltime);
379 icalcomponent_add_property(exchange2ical->vevent, prop);
380 tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
381 icalproperty_add_parameter(prop, tzid);
383 icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->apptEndWhole);
384 prop = icalproperty_new_dtend(icaltime);
385 icalcomponent_add_property(exchange2ical->vevent, prop);
392 void ical_property_DTSTAMP(struct exchange2ical *exchange2ical)
395 struct icaltimetype icaltime;
401 /*If OwnerCriticalChange field is null, get time system time*/
402 if (!exchange2ical->OwnerCriticalChange) {
405 icaltime = get_icaltimetype_from_tm_UTC(tm);
406 prop = icalproperty_new_dtstamp(icaltime);
407 icalcomponent_add_property(exchange2ical->vevent, prop);
410 icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->OwnerCriticalChange);
411 prop = icalproperty_new_dtstamp(icaltime);
412 icalcomponent_add_property(exchange2ical->vevent, prop);
413 if (exchange2ical->TimeZoneDesc) {
414 tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
415 icalproperty_add_parameter(prop, tzid);
421 void ical_property_DESCRIPTION(struct exchange2ical *exchange2ical)
425 if (exchange2ical->method == ICAL_METHOD_REPLY) return;
426 if (!exchange2ical->body) return;
428 prop = icalproperty_new_description(exchange2ical->body);
429 icalcomponent_add_property(exchange2ical->vevent, prop);
433 void ical_property_EXDATE(struct exchange2ical *exchange2ical)
438 struct icaltimetype icaltime;
439 struct icaltimetype dttime;
442 struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
445 if (exchange2ical->Recurring && (*exchange2ical->Recurring == 0x0)) return;
447 if (!pat->DeletedInstanceCount) return;
449 for (i = 0; i < pat->DeletedInstanceCount; i++) {
451 if(pat->ModifiedInstanceDates && pat->ModifiedInstanceCount){
452 for(j=0; j < pat->ModifiedInstanceCount; j++){
453 if(pat->ModifiedInstanceDates[j]==pat->DeletedInstanceDates[i]){
459 /* If this is an all-day appointment */
460 if (!modified && exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
462 tm = get_tm_from_minutes_UTC(pat->DeletedInstanceDates[i]);
463 icaltime= get_icaldate_from_tm(&tm);
464 prop = icalproperty_new_exdate(icaltime);
465 icalcomponent_add_property(exchange2ical->vevent, prop);
466 } else if (!modified){
467 /* number of minutes between midnight of the specified
468 * day and midnight, January 1, 1601 */
470 tm = get_tm_from_minutes_UTC(pat->DeletedInstanceDates[i]);
471 icaltime= get_icaltimetype_from_tm(&tm);
473 if (exchange2ical->TimeZoneDesc) {
474 /*Get time from dtstart*/
475 if (exchange2ical->apptEndWhole){
476 dttime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole);
477 icaltime.hour = dttime.hour;
478 icaltime.minute = dttime.minute;
481 prop = icalproperty_new_exdate(icaltime);
482 icalcomponent_add_property(exchange2ical->vevent, prop);
483 icalparameter *tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
484 icalproperty_add_parameter(prop, tzid);
486 /*Get time from dtstart*/
488 if (exchange2ical->apptEndWhole){
489 dttime = get_icaltime_from_FILETIME_UTC(exchange2ical->apptStartWhole);
490 icaltime.hour = dttime.hour;
491 icaltime.minute = dttime.minute;
493 prop = icalproperty_new_exdate(icaltime);
494 icalcomponent_add_property(exchange2ical->vevent, prop);
502 void ical_property_LAST_MODIFIED(struct exchange2ical *exchange2ical)
505 struct icaltimetype icaltime;
510 if (!exchange2ical->LastModified) return;
511 if (exchange2ical->TimeZoneDesc) {
512 icaltime=get_icaltime_from_FILETIME(exchange2ical->LastModified);
513 prop = icalproperty_new_lastmodified(icaltime);
514 tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
515 icalproperty_add_parameter(prop, tzid);
517 icaltime=get_icaltime_from_FILETIME_UTC(exchange2ical->LastModified);
518 prop = icalproperty_new_lastmodified(icaltime);
520 icalcomponent_add_property(exchange2ical->vevent, prop);
524 void ical_property_LOCATION(struct exchange2ical *exchange2ical)
528 if (!exchange2ical->Location) return;
530 prop = icalproperty_new_location(exchange2ical->Location);
531 icalcomponent_add_property(exchange2ical->vevent, prop);
535 void ical_property_ORGANIZER(struct exchange2ical *exchange2ical)
538 const char *display_name;
539 uint32_t *RecipientFlags;
540 uint32_t *RecipientType;
542 struct SRowSet *SRowSet;
545 if (!exchange2ical->apptStateFlags) return;
546 if (!(*exchange2ical->apptStateFlags & 0x1)) return;
548 SRowSet = &(exchange2ical->Recipients.SRowSet);
550 /* Loop over the recipient table */
551 for (i = 0; i < SRowSet->cRows; i++) {
552 smtp = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_SMTP_ADDRESS);
553 display_name = (const char *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_DISPLAY_NAME);
554 RecipientFlags = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_FLAGS);
555 RecipientType = (uint32_t *) octool_get_propval(&(SRowSet->aRow[i]), PR_RECIPIENT_TYPE);
557 if (RecipientFlags && !(*RecipientFlags & 0x20) &&
558 ((*RecipientFlags & 0x2) || (RecipientType && !*RecipientType))) {
564 mailtoURL = talloc_strdup(exchange2ical->mem_ctx, "mailto:");
565 mailtoURL = talloc_strdup_append(mailtoURL, smtp);
566 prop = icalproperty_new_organizer(mailtoURL);
567 icalcomponent_add_property(exchange2ical->vevent, prop);
568 talloc_free(mailtoURL);
570 prop = icalproperty_new_organizer("invalid:nomail");
571 icalcomponent_add_property(exchange2ical->vevent, prop);
575 cn = icalparameter_new_cn(display_name);
576 icalproperty_add_parameter(prop, cn);
583 void ical_property_PRIORITY(struct exchange2ical *exchange2ical)
587 if (!exchange2ical->Importance) return;
589 switch (*exchange2ical->Importance) {
591 prop = icalproperty_new_priority(9);
594 prop = icalproperty_new_priority(5);
597 prop = icalproperty_new_priority(1);
600 prop = icalproperty_new_priority(5);
602 icalcomponent_add_property(exchange2ical->vevent, prop);
606 void ical_property_RRULE_Daily(struct exchange2ical *exchange2ical)
608 struct icalrecurrencetype recurrence;
610 struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
613 icalrecurrencetype_clear(&recurrence);
614 recurrence.freq = ICAL_DAILY_RECURRENCE;
615 recurrence.interval = (pat->Period / 1440);
617 if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) {
618 recurrence.count = pat->OccurrenceCount;
620 prop = icalproperty_new_rrule(recurrence);
621 icalcomponent_add_property(exchange2ical->vevent, prop);
625 void ical_property_RRULE_Weekly(struct exchange2ical *exchange2ical)
627 struct icalrecurrencetype recurrence;
629 struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
630 uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.WeekRecurrencePattern;
633 icalrecurrencetype_clear(&recurrence);
634 recurrence.freq = ICAL_WEEKLY_RECURRENCE;
635 recurrence.interval = pat->Period;
638 switch(pat->FirstDOW){
639 case FirstDOW_Sunday:
640 recurrence.week_start=ICAL_SUNDAY_WEEKDAY;
642 case FirstDOW_Monday:
643 recurrence.week_start=ICAL_MONDAY_WEEKDAY;
645 case FirstDOW_Tuesday:
646 recurrence.week_start=ICAL_TUESDAY_WEEKDAY;
648 case FirstDOW_Wednesday:
649 recurrence.week_start=ICAL_WEDNESDAY_WEEKDAY;
651 case FirstDOW_Thursday:
652 recurrence.week_start=ICAL_THURSDAY_WEEKDAY;
654 case FirstDOW_Friday:
655 recurrence.week_start=ICAL_FRIDAY_WEEKDAY;
657 case FirstDOW_Saturday:
658 recurrence.week_start=ICAL_SATURDAY_WEEKDAY;
663 if (rdfDaysBitmask & Su) {
664 recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY;
667 if (rdfDaysBitmask & M) {
668 recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY;
671 if (rdfDaysBitmask & Tu) {
672 recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY;
675 if (rdfDaysBitmask & W) {
676 recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY;
679 if (rdfDaysBitmask & Th) {
680 recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY;
683 if (rdfDaysBitmask & F) {
684 recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
687 if (rdfDaysBitmask & Sa) {
688 recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
691 recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX;
693 if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) {
694 recurrence.count = pat->OccurrenceCount;
697 prop = icalproperty_new_rrule(recurrence);
698 icalcomponent_add_property(exchange2ical->vevent, prop);
702 void ical_property_RRULE_Monthly(struct exchange2ical *exchange2ical)
704 struct icalrecurrencetype recurrence;
706 struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
707 uint32_t day = pat->PatternTypeSpecific.Day;
709 icalrecurrencetype_clear(&recurrence);
710 recurrence.freq = ICAL_MONTHLY_RECURRENCE;
711 recurrence.interval = pat->Period;
713 if (day == 0x0000001F) {
714 recurrence.by_month_day[0] = -1;
716 recurrence.by_month_day[0] = day;
718 recurrence.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
720 if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) {
721 recurrence.count = pat->OccurrenceCount;
724 prop = icalproperty_new_rrule(recurrence);
725 icalcomponent_add_property(exchange2ical->vevent, prop);
729 void ical_property_RRULE_NthMonthly(struct exchange2ical *exchange2ical)
731 struct icalrecurrencetype recurrence;
733 struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
734 uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern;
736 enum RecurrenceN setpos = pat->PatternTypeSpecific.MonthRecurrencePattern.N;
738 icalrecurrencetype_clear(&recurrence);
739 recurrence.freq = ICAL_MONTHLY_RECURRENCE;
740 recurrence.interval = pat->Period;
742 if (rdfDaysBitmask & Su) {
743 recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY;
746 if (rdfDaysBitmask & M) {
747 recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY;
750 if (rdfDaysBitmask & Tu) {
751 recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY;
754 if (rdfDaysBitmask & W) {
755 recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY;
758 if (rdfDaysBitmask & Th) {
759 recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY;
762 if (rdfDaysBitmask & F) {
763 recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
766 if (rdfDaysBitmask & Sa) {
767 recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
770 recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX;
772 if (setpos == RecurrenceN_First) {
773 recurrence.by_set_pos[0] = 1;
774 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
775 } else if (setpos == RecurrenceN_Second) {
776 recurrence.by_set_pos[0] = 2;
777 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
778 } else if (setpos == RecurrenceN_Third) {
779 recurrence.by_set_pos[0] = 3;
780 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
781 } else if (setpos == RecurrenceN_Fourth) {
782 recurrence.by_set_pos[0] = 4;
783 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
784 } else if (setpos == RecurrenceN_Last) {
785 recurrence.by_set_pos[0] = -1;
786 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
789 if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) {
790 recurrence.count = pat->OccurrenceCount;
793 prop = icalproperty_new_rrule(recurrence);
794 icalcomponent_add_property(exchange2ical->vevent, prop);
798 void ical_property_RRULE_Yearly(struct exchange2ical *exchange2ical)
800 struct icalrecurrencetype recurrence;
802 struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
803 uint32_t day = pat->PatternTypeSpecific.Day;
804 struct icaltimetype icaltime;
806 icalrecurrencetype_clear(&recurrence);
807 recurrence.freq = ICAL_YEARLY_RECURRENCE;
808 recurrence.interval = (pat->Period / 12);
810 if (day == 0x0000001F) {
811 recurrence.by_month_day[0] = -1;
813 recurrence.by_month_day[0] = day;
815 recurrence.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
817 icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->apptStartWhole);
818 recurrence.by_month[0] = icaltime.month;
819 recurrence.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
823 if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) {
824 recurrence.count = pat->OccurrenceCount;
827 prop = icalproperty_new_rrule(recurrence);
828 icalcomponent_add_property(exchange2ical->vevent, prop);
831 void ical_property_RRULE_NthYearly(struct exchange2ical *exchange2ical)
833 struct icalrecurrencetype recurrence;
835 struct RecurrencePattern *pat = exchange2ical->RecurrencePattern;
836 uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern;
838 enum RecurrenceN setpos = pat->PatternTypeSpecific.MonthRecurrencePattern.N;
840 struct icaltimetype icaltime;
842 icalrecurrencetype_clear(&recurrence);
843 recurrence.freq = ICAL_YEARLY_RECURRENCE;
844 recurrence.interval = (pat->Period / 12);
846 if (rdfDaysBitmask & Su) {
847 recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY;
850 if (rdfDaysBitmask & M) {
851 recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY;
854 if (rdfDaysBitmask & Tu) {
855 recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY;
858 if (rdfDaysBitmask & W) {
859 recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY;
862 if (rdfDaysBitmask & Th) {
863 recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY;
866 if (rdfDaysBitmask & F) {
867 recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
870 if (rdfDaysBitmask & Sa) {
871 recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY;
874 recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX;
876 if (setpos == RecurrenceN_First) {
877 recurrence.by_set_pos[0] = 1;
878 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
879 } else if (setpos == RecurrenceN_Second) {
880 recurrence.by_set_pos[0] = 2;
881 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
882 } else if (setpos == RecurrenceN_Third) {
883 recurrence.by_set_pos[0] = 3;
884 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
885 } else if (setpos == RecurrenceN_Fourth) {
886 recurrence.by_set_pos[0] = 4;
887 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
888 } else if (setpos == RecurrenceN_Last) {
889 recurrence.by_set_pos[0] = -1;
890 recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
893 icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole);
894 recurrence.by_month[0] = icaltime.month;
895 recurrence.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
897 if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) {
898 recurrence.count = pat->OccurrenceCount;
901 prop = icalproperty_new_rrule(recurrence);
902 icalcomponent_add_property(exchange2ical->vevent, prop);
906 void ical_property_RRULE(struct exchange2ical *exchange2ical)
908 struct RecurrencePattern *pat;
911 if (!(exchange2ical->RecurrencePattern)) return;
913 pat = exchange2ical->RecurrencePattern;
915 switch(pat->PatternType) {
916 case PatternType_Day:
917 ical_property_RRULE_Daily(exchange2ical);
919 case PatternType_Week:
920 ical_property_RRULE_Weekly(exchange2ical);
922 case PatternType_Month:
923 if ((pat->Period % 12 ) == 0) {
924 ical_property_RRULE_Yearly(exchange2ical);
926 ical_property_RRULE_Monthly(exchange2ical);
929 case PatternType_MonthNth:
930 if ((pat->Period % 12 ) == 0) {
931 ical_property_RRULE_NthYearly(exchange2ical);
933 ical_property_RRULE_NthMonthly(exchange2ical);
937 printf("RRULE pattern type not implemented yet!:0x%x\n", pat->PatternType);
941 void ical_property_RRULE_daylight_standard(icalcomponent* component , struct SYSTEMTIME st)
943 struct icalrecurrencetype recurrence;
946 icalrecurrencetype_clear(&recurrence);
947 recurrence.freq = ICAL_YEARLY_RECURRENCE;
949 if(st.wYear ==0x0000){
950 recurrence.by_month[0]=st.wMonth;
951 /* Microsoft day of week = libIcal day of week +1; */
952 /* Day encode = day + occurrence*8 */
954 /* Last occurrence of day in the month*/
955 recurrence.by_day[0] = -1 * (st.wDayOfWeek + 9);
957 /* st.wDay occurrence of day in the month */
958 recurrence.by_day[0] = (st.wDayOfWeek + 1 + st.wDay*8);
962 recurrence.by_month_day[0]=st.wDay;
963 recurrence.by_month[0]=st.wMonth;
967 prop = icalproperty_new_rrule(recurrence);
968 icalcomponent_add_property(component, prop);
972 void ical_property_RECURRENCE_ID(struct exchange2ical *exchange2ical)
974 struct icaltimetype icaltime;
977 struct GlobalObjectId *GlbObjId;
980 if (exchange2ical->ExceptionReplaceTime){
981 /*if parent has an all day event*/
982 if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
983 icaltime = get_icaldate_from_FILETIME(exchange2ical->ExceptionReplaceTime);
984 prop = icalproperty_new_recurrenceid(icaltime);
985 icalcomponent_add_property(exchange2ical->vevent, prop);
987 if (exchange2ical->TimeZoneDesc) {
988 icaltime=get_icaltime_from_FILETIME(exchange2ical->ExceptionReplaceTime);
989 prop = icalproperty_new_recurrenceid(icaltime);
990 icalcomponent_add_property(exchange2ical->vevent, prop);
991 tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc);
992 icalproperty_add_parameter(prop, tzid);
994 icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->ExceptionReplaceTime);
995 prop = icalproperty_new_recurrenceid(icaltime);
996 icalcomponent_add_property(exchange2ical->vevent, prop);
999 } else if (exchange2ical->GlobalObjectId){
1000 GlbObjId = get_GlobalObjectId(exchange2ical->mem_ctx, exchange2ical->GlobalObjectId);
1002 icaltime=get_icaldate_from_GlobalObjectId(GlbObjId);
1003 prop = icalproperty_new_recurrenceid(icaltime);
1004 icalcomponent_add_property(exchange2ical->vevent, prop);
1005 talloc_free(GlbObjId);
1013 void ical_property_RESOURCES(struct exchange2ical *exchange2ical)
1015 char *NonSendableBcc = NULL;
1019 if (!exchange2ical->NonSendableBcc) return;
1021 NonSendableBcc = talloc_strdup(exchange2ical->mem_ctx, exchange2ical->NonSendableBcc);
1022 all_string_sub(NonSendableBcc, ";", ",", 0);
1023 prop = icalproperty_new_resources(NonSendableBcc);
1024 icalcomponent_add_property(exchange2ical->vevent, prop);
1025 talloc_free(NonSendableBcc);
1029 void ical_property_SEQUENCE(struct exchange2ical *exchange2ical)
1032 if (!exchange2ical->Sequence) {
1033 prop = icalproperty_new_sequence(0);
1035 prop = icalproperty_new_sequence(*(exchange2ical->Sequence));
1037 icalcomponent_add_property(exchange2ical->vevent, prop);
1041 void ical_property_SUMMARY(struct exchange2ical *exchange2ical)
1044 icalparameter *language;
1046 if (exchange2ical->Subject) {
1047 prop = icalproperty_new_summary(exchange2ical->Subject);
1049 prop = icalproperty_new_summary("");
1052 if (exchange2ical->MessageLocaleId) {
1053 const char *langtag = mapi_get_locale_from_lcid( *(exchange2ical->MessageLocaleId) );
1054 language = icalparameter_new_language( langtag );
1055 icalproperty_add_parameter(prop, language);
1058 icalcomponent_add_property(exchange2ical->vevent, prop);
1062 void ical_property_TRANSP(struct exchange2ical *exchange2ical)
1067 if (!exchange2ical->BusyStatus) return;
1069 switch (*exchange2ical->BusyStatus) {
1071 prop = icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT);
1076 prop = icalproperty_new_transp(ICAL_TRANSP_OPAQUE);
1079 prop = icalproperty_new_transp(ICAL_TRANSP_NONE);
1081 icalcomponent_add_property(exchange2ical->vevent, prop);
1085 void ical_property_TRIGGER(struct exchange2ical *exchange2ical)
1087 struct icaltriggertype duration;
1089 if (!exchange2ical->ReminderDelta) return;
1090 if (*exchange2ical->ReminderDelta == 0x5AE980E1) {
1091 duration = icaltriggertype_from_int(-15 * 60);
1092 prop = icalproperty_new_trigger(duration);
1093 icalcomponent_add_property(exchange2ical->valarm, prop);
1095 duration = icaltriggertype_from_int(*(exchange2ical->ReminderDelta) * -1 * 60);
1096 prop = icalproperty_new_trigger(duration);
1097 icalcomponent_add_property(exchange2ical->valarm, prop);
1102 #define GLOBAL_OBJECT_ID_DATA_START "\x76\x43\x61\x6c\x2d\x55\x69\x64\x01\x00\x00\x00"
1104 void ical_property_UID(struct exchange2ical *exchange2ical)
1109 struct GlobalObjectId *GlbObjId;
1112 outstr = talloc_strdup(exchange2ical->mem_ctx, "");
1114 if(exchange2ical->GlobalObjectId){
1115 GlbObjId = get_GlobalObjectId(exchange2ical->mem_ctx, exchange2ical->GlobalObjectId);
1119 if (exchange2ical->GlobalObjectId && (exchange2ical->GlobalObjectId->cb >= 36) && GlbObjId) {
1120 if (GlbObjId->Size >= 16 && (0 == memcmp(GlbObjId->Data, GLOBAL_OBJECT_ID_DATA_START, 12))) {
1122 for (i = 12; i < exchange2ical->GlobalObjectId->cb; i++) {
1124 snprintf(objID, 6, "%.2X", exchange2ical->GlobalObjectId->lpb[i]);
1125 outstr = talloc_strdup_append(outstr, objID);
1128 uid = (const char *)&(GlbObjId->Data[13]);
1129 outstr = talloc_strdup_append(outstr, uid);
1132 for (i = 0; i < 16; i++) {
1134 snprintf(objID, 6, "%.2X", exchange2ical->GlobalObjectId->lpb[i]);
1135 outstr = talloc_strdup_append(outstr, objID);
1137 /* YH, YL, Month and D must be set to 0 */
1138 outstr = talloc_strdup_append(outstr, "00000000");
1140 for (i = 20; i < exchange2ical->GlobalObjectId->cb; i++) {
1142 snprintf(objID, 6, "%.2X", exchange2ical->GlobalObjectId->lpb[i]);
1143 outstr = talloc_strdup_append(outstr, objID);
1146 talloc_free(GlbObjId);
1149 snprintf(objID, 32, "%i", exchange2ical->idx);
1150 outstr = talloc_strdup(outstr, objID);
1153 prop = icalproperty_new_uid(outstr);
1154 icalcomponent_add_property(exchange2ical->vevent, prop);
1155 talloc_free(outstr);
1159 static icalproperty * ical_property_add_x_property_value(icalcomponent *parent, const char* propname, const char* value)
1162 icalvalue *icalText;
1165 if (!parent) return NULL;
1166 if (!propname) return NULL;
1167 if (!value) return NULL;
1169 icalText = icalvalue_new_text(value);
1170 prop = icalproperty_new_x(icalvalue_as_ical_string(icalText));
1171 icalvalue_free(icalText);
1172 icalproperty_set_x_name(prop, propname);
1173 icalcomponent_add_property(parent, prop);
1177 void ical_property_X_ALT_DESC(struct exchange2ical *exchange2ical)
1180 icalparameter *param;
1183 if(!exchange2ical->bodyHTML) return;
1184 prop = ical_property_add_x_property_value(exchange2ical->vevent, "X-ALT-DESC",exchange2ical->bodyHTML);
1185 param = icalparameter_new_fmttype("text/html");
1186 icalproperty_add_parameter(prop, param);
1189 void ical_property_X_MICROSOFT_CDO_ATTENDEE_CRITICAL_CHANGE(struct exchange2ical *exchange2ical)
1195 if (!exchange2ical->AttendeeCriticalChange) return;
1197 tm = get_tm_from_FILETIME(exchange2ical->AttendeeCriticalChange);
1198 strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
1199 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-ATTENDEE-CRITICAL-CHANGE", outstr);
1203 void ical_property_X_MICROSOFT_CDO_BUSYSTATUS(struct exchange2ical *exchange2ical)
1206 if(!exchange2ical->BusyStatus) return;
1208 switch (*exchange2ical->BusyStatus) {
1210 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "FREE");
1213 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "TENTATIVE");
1216 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "BUSY");
1219 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-BUSYSTATUS", "OOF");
1223 void ical_property_X_MICROSOFT_MSNCALENDAR_IMPORTANCE(struct exchange2ical *exchange2ical)
1226 if (!exchange2ical->Importance) return;
1228 switch (*exchange2ical->Importance) {
1230 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-MSNCALENDAR-IMPORTANCE", "0");
1233 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-MSNCALENDAR-IMPORTANCE", "1");
1236 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-MSNCALENDAR-IMPORTANCE", "2");
1241 void ical_property_X_MICROSOFT_CDO_INTENDEDSTATUS(struct exchange2ical *exchange2ical)
1243 if (!exchange2ical->IntendedBusyStatus) return;
1245 switch (*exchange2ical->IntendedBusyStatus) {
1247 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "FREE");
1250 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "TENTATIVE");
1253 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "BUSY");
1256 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-INTENDEDSTATUS", "OOF");
1262 void ical_property_X_MICROSOFT_CDO_OWNERAPPTID(struct exchange2ical *exchange2ical)
1266 if (!exchange2ical->OwnerApptId) return;
1267 snprintf(outstr, 200, "%d", *(exchange2ical->OwnerApptId));
1268 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-OWNERAPPTID", outstr);
1272 void ical_property_X_MICROSOFT_CDO_OWNER_CRITICAL_CHANGE(struct exchange2ical *exchange2ical)
1278 if (!exchange2ical->OwnerCriticalChange) return;
1281 tm = get_tm_from_FILETIME(exchange2ical->OwnerCriticalChange);
1284 strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
1285 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-OWNER-CRITICAL-CHANGE", outstr);
1289 void ical_property_X_MICROSOFT_CDO_REPLYTIME(struct exchange2ical *exchange2ical)
1295 if (!exchange2ical->apptReplyTime) return;
1297 tm = get_tm_from_FILETIME(exchange2ical->apptReplyTime);
1298 strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
1299 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-CDO-REPLYTIME", outstr);
1303 void ical_property_X_MICROSOFT_DISALLOW_COUNTER(struct exchange2ical *exchange2ical)
1306 if (!exchange2ical->NotAllowPropose) return;
1308 if (*(exchange2ical->NotAllowPropose) == true) {
1309 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-DISALLOW-COUNTER", "TRUE");
1311 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-DISALLOW-COUNTER", "FALSE");
1316 void ical_property_X_MS_OLK_ALLOWEXTERNCHECK(struct exchange2ical *exchange2ical)
1319 if (!exchange2ical->AllowExternCheck) return;
1321 if (*(exchange2ical->AllowExternCheck) == true) {
1322 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-ALLOWEXTERNCHECK", "TRUE");
1324 ical_property_add_x_property_value(exchange2ical->vevent, "X-MICROSOFT-ALLOWEXTERNCHECK", "FALSE");
1329 void ical_property_X_MS_OLK_APPTLASTSEQUENCE(struct exchange2ical *exchange2ical)
1333 if (!exchange2ical->apptLastSequence) return;
1335 snprintf(outstr, 20, "%d", *exchange2ical->apptLastSequence);
1336 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-APPTLASTSEQUENCE", outstr);
1340 void ical_property_X_MS_OLK_APPTSEQTIME(struct exchange2ical *exchange2ical)
1342 struct tm *tm = NULL;
1346 if (!exchange2ical->apptSeqTime) return;
1348 tm = get_tm_from_FILETIME(exchange2ical->apptSeqTime);
1349 strftime(outstr, sizeof(outstr), "%Y%m%dT%H%M%SZ", tm);
1350 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-APPTSEQTIME", outstr);
1354 void ical_property_X_MS_OLK_AUTOFILLLOCATION(struct exchange2ical *exchange2ical)
1357 if (!exchange2ical->AutoFillLocation) return;
1359 if (*(exchange2ical->AutoFillLocation) == true) {
1360 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOFILLLOCATION", "TRUE");
1362 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOFILLLOCATION", "FALSE");
1367 void ical_property_X_MS_OLK_AUTOSTARTCHECK(struct exchange2ical *exchange2ical)
1370 if (!exchange2ical->AutoStartCheck) return;
1371 if (*(exchange2ical->AutoStartCheck) == true) {
1372 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOSTARTCHECK", "TRUE");
1374 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-AUTOSTARTCHECK", "FALSE");
1379 void ical_property_X_MS_OLK_COLLABORATEDOC(struct exchange2ical *exchange2ical)
1382 if (!exchange2ical->CollaborateDoc) return;
1383 if(!(*exchange2ical->CollaborateDoc)) return;
1385 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-COLLABORATEDOC", exchange2ical->CollaborateDoc);
1389 void ical_property_X_MS_OLK_CONFCHECK(struct exchange2ical *exchange2ical)
1392 if (!exchange2ical->ConfCheck) return;
1394 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-CONFCHECK", (*exchange2ical->ConfCheck == true) ? "TRUE" : "FALSE");
1398 void ical_property_X_MS_OLK_CONFTYPE(struct exchange2ical *exchange2ical)
1402 if (!exchange2ical->ConfType) return;
1404 snprintf(outstr, 20, "%d", *exchange2ical->ConfType);
1405 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-CONFTYPE", outstr);
1409 void ical_property_X_MS_OLK_DIRECTORY(struct exchange2ical *exchange2ical)
1412 if(!exchange2ical->Directory) return;
1413 if(!(*exchange2ical->Directory)) return;
1415 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-DIRECTORY", exchange2ical->Directory);
1419 void ical_property_X_MS_OLK_MWSURL(struct exchange2ical *exchange2ical)
1422 if(!exchange2ical->MWSURL) return;
1424 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-MWSURL", exchange2ical->MWSURL);
1428 void ical_property_X_MS_OLK_NETSHOWURL(struct exchange2ical *exchange2ical)
1431 if(!exchange2ical->NetShowURL) return;
1432 if(!(*exchange2ical->NetShowURL)) return;
1434 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-NETSHOWURL", exchange2ical->NetShowURL);
1437 void ical_property_X_MS_OLK_ONLINEPASSWORD(struct exchange2ical *exchange2ical)
1440 if(!exchange2ical->OnlinePassword) return;
1441 if(!(*exchange2ical->OnlinePassword)) return;
1443 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-ONLINEPASSWORD", exchange2ical->OnlinePassword);
1446 void ical_property_X_MS_OLK_ORGALIAS(struct exchange2ical *exchange2ical)
1449 if(!exchange2ical->OrgAlias) return;
1450 if(!(*exchange2ical->OrgAlias)) return;
1452 ical_property_add_x_property_value(exchange2ical->vevent, "X-MS-OLK-ORGALIAS", exchange2ical->OrgAlias);
1456 // TODO: double check this - need an example.
1457 void ical_property_X_MS_OLK_SENDER(struct exchange2ical *exchange2ical)
1460 icalparameter *param;
1464 if (!exchange2ical->apptStateFlags) return;
1465 if (!(*exchange2ical->apptStateFlags & 0x1)) return;
1466 if (!exchange2ical->SenderName) return;
1468 if (exchange2ical->SenderEmailAddress) {
1469 snprintf(outstr, 200, "mailto:%s",exchange2ical->SenderEmailAddress);
1470 prop = icalproperty_new_x(outstr);
1472 prop = icalproperty_new_x("invalid:nomail");
1475 icalproperty_set_x_name(prop, "X-MS-OLK-SENDER");
1476 icalcomponent_add_property(exchange2ical->vevent, prop);
1478 param = icalparameter_new_cn(exchange2ical->SenderName);
1479 icalproperty_add_parameter(prop, param);