static int gn_ical2calnote_real(icalcomponent *comp, gn_calnote *calnote, int id) { int retval = GN_ERR_FAILED; struct icaltimetype dtstart = {0}, dtend = {0}; icalcomponent *compresult = NULL; if (id < 1) id = 1; /* iterate through the component */ iterate_cal(comp, 0, &id, &compresult, ICAL_VEVENT_COMPONENT); if (!compresult) { dprintf("No component found.\n"); retval = GN_ERR_EMPTYLOCATION; } else { const char *str; icalcomponent *alarm = {0}; icalproperty *rrule; struct icalrecurrencetype recur; retval = GN_ERR_NONE; calnote->phone_number[0] = 0; /* type */ str = comp_get_category(compresult); calnote->type = str2calnote_type(str); switch (calnote->type) { case GN_CALNOTE_CALL: /* description goes into text */ /* TODO: UTF8 --> ascii */ snprintf(calnote->phone_number, GN_CALNOTE_NUMBER_MAX_LENGTH-1, "%s", icalcomponent_get_summary(compresult)); str = icalcomponent_get_description(compresult); break; default: /* summary goes into text */ /* TODO: UTF8 --> ascii */ str = icalcomponent_get_summary(compresult); break; } if (str) { snprintf(calnote->text, GN_CALNOTE_MAX_LENGTH - 1, "%s", str); } /* start time */ dtstart = icalcomponent_get_dtstart(compresult); if (!icaltime_is_null_time(dtstart)) { calnote->time.year = dtstart.year; calnote->time.month = dtstart.month; calnote->time.day = dtstart.day; if (!icaltime_is_date(dtstart)) { calnote->time.hour = dtstart.hour; calnote->time.minute = dtstart.minute; calnote->time.second = dtstart.second; /* TODO: what about time zones? */ } } /* end time */ memset(&calnote->end_time, 0, sizeof(calnote->end_time)); dtend = icalcomponent_get_dtend(compresult); if (!icaltime_is_null_time(dtend)) { calnote->end_time.year = dtend.year; calnote->end_time.month = dtend.month; calnote->end_time.day = dtend.day; if (!icaltime_is_date(dtend)) { calnote->end_time.hour = dtend.hour; calnote->end_time.minute = dtend.minute; calnote->end_time.second = dtend.second; /* TODO: what about time zones? */ } } /* alarm */ alarm = icalcomponent_get_first_component(compresult, ICAL_VALARM_COMPONENT); if (alarm) { icalproperty *trigger = NULL; trigger = icalcomponent_get_first_property(alarm, ICAL_TRIGGER_PROPERTY); if (trigger) { struct icaltriggertype trigger_value; struct icaltimetype alarm_start; icalproperty *property; trigger_value = icalvalue_get_trigger(icalproperty_get_value(trigger)); if (icaltriggertype_is_null_trigger(trigger_value) || icaltriggertype_is_bad_trigger(trigger_value)) { calnote->alarm.enabled = 0; } else { if (icaltime_is_null_time(trigger_value.time)) { memcpy(&alarm_start, &dtstart, sizeof(struct icaltimetype)); } else { memcpy(&alarm_start, &trigger_value.time, sizeof(struct icaltimetype)); } if (!(icaldurationtype_is_bad_duration(trigger_value.duration) || icaldurationtype_is_null_duration(trigger_value.duration))) { alarm_start = icaltime_add(alarm_start, trigger_value.duration); } calnote->alarm.enabled = 1; calnote->alarm.timestamp.year = alarm_start.year; calnote->alarm.timestamp.month = alarm_start.month; calnote->alarm.timestamp.day = alarm_start.day; calnote->alarm.timestamp.hour = alarm_start.hour; calnote->alarm.timestamp.minute = alarm_start.minute; calnote->alarm.timestamp.second = alarm_start.second; /* TODO: time zone? */ property = icalcomponent_get_first_property(alarm, ICAL_ACTION_PROPERTY); calnote->alarm.tone = icalproperty_get_action(property) == ICAL_ACTION_AUDIO ? 1 : 0; } } } /* recurrence */ rrule = icalcomponent_get_first_property(compresult, ICAL_RRULE_PROPERTY); if (rrule) { recur = icalproperty_get_rrule(rrule); calnote->occurrences = recur.count; switch (recur.freq) { case ICAL_SECONDLY_RECURRENCE: dprintf("Not supported recurrence type. Approximating recurrence\n"); calnote->recurrence = recur.interval / 3600; if (!calnote->recurrence) calnote->recurrence = 1; break; case ICAL_MINUTELY_RECURRENCE: dprintf("Not supported recurrence type. Approximating recurrence\n"); calnote->recurrence = recur.interval / 60; if (!calnote->recurrence) calnote->recurrence = 1; break; case ICAL_HOURLY_RECURRENCE: calnote->recurrence = recur.interval; break; case ICAL_DAILY_RECURRENCE: calnote->recurrence = recur.interval * 24; break; case ICAL_WEEKLY_RECURRENCE: calnote->recurrence = recur.interval * 24 * 7; break; case ICAL_MONTHLY_RECURRENCE: calnote->recurrence = GN_CALNOTE_MONTHLY; break; case ICAL_YEARLY_RECURRENCE: calnote->recurrence = GN_CALNOTE_YEARLY; break; case ICAL_NO_RECURRENCE: calnote->recurrence = GN_CALNOTE_NEVER; break; default: dprintf("Not supported recurrence type. Assuming never\n"); calnote->recurrence = GN_CALNOTE_NEVER; break; } } str = icalcomponent_get_location(compresult); if (!str) str = ""; snprintf(calnote->mlocation, sizeof(calnote->mlocation), "%s", str); } if (compresult) { #ifdef DEBUG char *temp; temp = icalcomponent_as_ical_string(compresult); dprintf("Component found\n%s\n", temp); free(temp); #endif icalcomponent_free(compresult); } return retval; }
void parse_iCal(icalcomponent* comp) { icalcomponent * c; icalproperty * rrule; icalproperty * exdate; icalrecur_iterator * data; struct icaldurationtype offset; struct icaltimetype time_start; struct icaltimetype time_end; struct icaltimetype time_next; struct icaltimetype exdatetime; struct icaltimetype now; struct icalrecurrencetype recur; int i = 0; double duration; // Get offset: time_t t = time(NULL); struct tm lt = {0}; localtime_r(&t, <); if (debug_flag) { printf("Offset to GMT is %lds.\n", lt.tm_gmtoff); } offset.days = 0; offset.weeks = 0; offset.hours = 0; offset.minutes = 0; offset.seconds = 0; offset.hours = lt.tm_gmtoff / 3600; if (lt.tm_gmtoff < 0) { offset.is_neg = 1; } else { offset.is_neg = 0; } // Get time now: now = icaltime_today(); // Read each event: for (c = icalcomponent_get_first_component(comp,ICAL_VEVENT_COMPONENT) ; c != 0 ; c = icalcomponent_get_next_component(comp,ICAL_VEVENT_COMPONENT) ) { // Get details about the event: const char * summary = icalcomponent_get_summary(c); const char * description = icalcomponent_get_description(c); // Help: if (debug_flag) { if (summary != NULL) { printf("summary: %s\n", summary); } if (description != NULL) { printf("description: %s\n", description); } } // Ranging time: time_start = icalcomponent_get_dtstart (c); time_end = icalcomponent_get_dtend (c); duration = difftime(icaltime_as_timet(time_end), icaltime_as_timet(time_start)); // Rules: rrule = icalcomponent_get_first_property(c,ICAL_RRULE_PROPERTY); recur = icalproperty_get_rrule(rrule); data = icalrecur_iterator_new (recur, time_start); // Find next event: while (1) { time_next = icalrecur_iterator_next (data); if (icaltime_is_null_time(time_next) == 1) break; if (icaltime_compare(time_next, now) >= 0) break; } // Help: if (debug_flag) { dump_icaltimetype("time start", time_start); dump_icaltimetype("time end", time_end); dump_icaltimetype("until", recur.until); dump_icaltimetype("time next", time_next); } // One shot event: if ( icaltime_is_null_time(time_next) == 1 && icaltime_compare(time_start, now) < 0 ) { if (debug_flag) printf ("event (one shot) is in the past\n"); continue; } // Old event: discard recurent events finished before today... if ( icaltime_is_null_time(recur.until) == 0 && icaltime_compare(recur.until, now) < 0 ) { if (debug_flag) printf ("event is recurent in the past ...\n"); continue; } // Some help: if (debug_flag > 2) { dump_icalrecurrencetype(recur); } // Set time and hours: struct icaltimetype local_time_start = icaltime_add(time_start, offset); printf ("%d %d ", local_time_start.minute, local_time_start.hour); // Set option depending of recurence: switch (recur.freq) { // Weekly: OK but need to remove days not needed... ? case ICAL_WEEKLY_RECURRENCE: printf ("%s", "* * "); for (i = 0; recur.by_day[i] != 32639; i++) { printf ("%02d", icalrecurrencetype_day_day_of_week(recur.by_day[i]) -1); if (recur.by_day[i+1] != 32639) { printf ("%s", ","); } } printf ("%s", " "); break; // Happening each month: case ICAL_MONTHLY_RECURRENCE: // The Xth of the month: if (recur.by_month_day[0] != 32639) { printf ("%02d * * ", recur.by_month_day[0]); } // Day of the week: else { printf ("%d %d * ", time_next.day, time_next.month); } break; // Event happening each year ... OK??? // OK: one shoot. case ICAL_YEARLY_RECURRENCE: case ICAL_NO_RECURRENCE: default: printf ("%02d %02d * ", local_time_start.day, local_time_start.month ); } // How many valid exclude dates: exdate = icalcomponent_get_first_property(c, ICAL_EXDATE_PROPERTY); unsigned int num_ex = 0; if (exdate != NULL) { for (; exdate != NULL; exdate = icalcomponent_get_next_property(c, ICAL_EXDATE_PROPERTY) ) { exdatetime = icalvalue_get_datetime(icalproperty_get_value(exdate)); if (icaltime_compare(exdatetime, now) >= 0) { num_ex++; } } } if (num_ex > 0) { exdate = icalcomponent_get_first_property(c, ICAL_EXDATE_PROPERTY); for (; exdate != NULL; exdate = icalcomponent_get_next_property(c, ICAL_EXDATE_PROPERTY) ) { exdatetime = icalvalue_get_datetime(icalproperty_get_value(exdate)); if (icaltime_compare(exdatetime, now) >= 0) { struct icaltimetype local_exdatetime = icaltime_add(exdatetime, offset); printf ("%s", "[ \"$(date \"+\\\%Y\\\%m\\\%d\")\" = \""); printf ("%04d%02d%02d", local_exdatetime.year, local_exdatetime.month, local_exdatetime.day); printf ("%s", "\" ] || "); } } } // And the action: printf ("%s %.0f\n", summary, duration ); icalrecur_iterator_free (data); } }