static gboolean get_ical_is_all_day (icalcomponent *ical, time_t start_time, icaltimezone *default_zone) { icalproperty *prop; struct tm *start_tm; time_t end_time; struct icaldurationtype duration; struct icaltimetype start_icaltime; start_icaltime = icalcomponent_get_dtstart (ical); if (start_icaltime.is_date) return TRUE; start_tm = gmtime (&start_time); if (start_tm->tm_sec != 0 || start_tm->tm_min != 0 || start_tm->tm_hour != 0) return FALSE; if ((end_time = get_ical_end_time (ical, default_zone))) return (end_time - start_time) % 86400 == 0; prop = icalcomponent_get_first_property (ical, ICAL_DURATION_PROPERTY); if (!prop) return FALSE; duration = icalproperty_get_duration (prop); return icaldurationtype_as_int (duration) % 86400 == 0; }
struct icaltriggertype icaltriggertype_from_string(const char* str) { struct icaltriggertype tr, null_tr; int old_ieaf = icalerror_errors_are_fatal; tr.time= icaltime_null_time(); tr.duration = icaldurationtype_from_int(0); null_tr = tr; if(str == 0) goto error; icalerror_errors_are_fatal = 0; tr.time = icaltime_from_string(str); icalerror_errors_are_fatal = old_ieaf; if (icaltime_is_null_time(tr.time)){ tr.duration = icaldurationtype_from_string(str); if(icaldurationtype_as_int(tr.duration) == 0) goto error; } return tr; error: icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return null_tr; }
struct icalperiodtype icalperiodtype_from_string (const char* str) { struct icalperiodtype p, null_p; char *s = icalmemory_strdup(str); char *start, *end = s; icalerrorstate es; /* Errors are normally generated in the following code, so save the error state for resoration later */ icalerrorenum e = icalerrno; p.start = p.end = icaltime_null_time(); p.duration = icaldurationtype_from_int(0); null_p = p; if(s == 0) goto error; start = s; end = strchr(s, '/'); if(end == 0) goto error; *end = 0; end++; p.start = icaltime_from_string(start); if (icaltime_is_null_time(p.start)) goto error; es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR); icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL); p.end = icaltime_from_string(end); icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); if (icaltime_is_null_time(p.end)) { p.duration = icaldurationtype_from_string(end); if(icaldurationtype_as_int(p.duration) == 0) goto error; } icalerrno = e; icalmemory_free_buffer(s); return p; error: icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); if (s) icalmemory_free_buffer (s); return null_p; }
int icaldurationtype_is_null_duration(struct icaldurationtype d) { if(icaldurationtype_as_int(d) == 0){ return 1; } else { return 0; } }
char* icaldurationtype_as_ical_string(struct icaldurationtype d) { char *buf, *output_line; size_t buf_size = 256; char* buf_ptr = 0; int seconds; buf = (char*)icalmemory_new_buffer(buf_size); buf_ptr = buf; seconds = icaldurationtype_as_int(d); if(seconds !=0){ if(d.is_neg == 1){ icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-'); } icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P'); if (d.weeks != 0 ) { append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks); } if (d.days != 0 ) { append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days); } if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) { icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T"); if (d.hours != 0 ) { append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours); } if (d.minutes != 0 ) { append_duration_segment(&buf, &buf_ptr, &buf_size, "M", d.minutes); } if (d.seconds != 0 ) { append_duration_segment(&buf, &buf_ptr, &buf_size, "S", d.seconds); } } } else { icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PT0S"); } output_line = icalmemory_tmp_copy(buf); icalmemory_free_buffer(buf); return output_line; }
VALUE duration_to_fixnum( VALUE self, VALUE duration ) { struct icaldurationtype dur_struct; char * _duration; ID to_string = rb_intern( "to_string" ); if( TYPE( duration ) != T_STRING && rb_respond_to( duration, to_string ) ) duration = rb_funcall( duration, to_string, 0 ); Check_Type(duration, T_STRING); _duration = RSTRING(duration)->ptr; icalerror_clear_errno(); icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL); dur_struct = icaldurationtype_from_string( _duration ); if( icaldurationtype_is_bad_duration( dur_struct ) ) rb_raise(rb_eArgError, "Malformed Duration"); return LONG2FIX(icaldurationtype_as_int( dur_struct )); }
/* Generates the absolute triggers for a component */ static void generate_absolute_triggers (ECalComponent *comp, struct alarm_occurrence_data *aod, ECalRecurResolveTimezoneFn resolve_tzid, gpointer user_data, icaltimezone *default_timezone) { GList *l; ECalComponentDateTime dt_start, dt_end; e_cal_component_get_dtstart (comp, &dt_start); e_cal_component_get_dtend (comp, &dt_end); for (l = aod->alarm_uids; l; l = l->next) { const gchar *auid; ECalComponentAlarm *alarm; ECalComponentAlarmAction action; ECalComponentAlarmRepeat repeat; ECalComponentAlarmTrigger trigger; time_t abs_time; time_t occur_start, occur_end; icaltimezone *zone; gint i; auid = l->data; alarm = e_cal_component_get_alarm (comp, auid); g_return_if_fail (alarm != NULL); e_cal_component_alarm_get_action (alarm, &action); e_cal_component_alarm_get_trigger (alarm, &trigger); e_cal_component_alarm_get_repeat (alarm, &repeat); e_cal_component_alarm_free (alarm); for (i = 0; aod->omit[i] != -1; i++) { if (aod->omit[i] == action) break; } if (aod->omit[i] != -1) continue; if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) continue; /* Absolute triggers are always in UTC; * see RFC 2445 section 4.8.6.3 */ zone = icaltimezone_get_utc_timezone (); abs_time = icaltime_as_timet_with_zone (trigger.u.abs_time, zone); /* No particular occurrence, so just use the times from the * component */ if (dt_start.value) { if (dt_start.tzid && !dt_start.value->is_date) zone = (* resolve_tzid) (dt_start.tzid, user_data); else zone = default_timezone; occur_start = icaltime_as_timet_with_zone ( *dt_start.value, zone); } else occur_start = -1; if (dt_end.value) { if (dt_end.tzid && !dt_end.value->is_date) zone = (* resolve_tzid) (dt_end.tzid, user_data); else zone = default_timezone; occur_end = icaltime_as_timet_with_zone (*dt_end.value, zone); } else occur_end = -1; /* Add repeating alarms */ if (repeat.repetitions != 0) { gint i; time_t repeat_time; repeat_time = icaldurationtype_as_int (repeat.duration); for (i = 0; i < repeat.repetitions; i++) { time_t t; t = abs_time + (i + 1) * repeat_time; if (t >= aod->start && t < aod->end) add_trigger ( aod, auid, t, occur_start, occur_end); } } /* Add the trigger itself */ if (abs_time >= aod->start && abs_time < aod->end) add_trigger (aod, auid, abs_time, occur_start, occur_end); } e_cal_component_free_datetime (&dt_start); e_cal_component_free_datetime (&dt_end); }
/* Callback used from cal_recur_generate_instances(); generates triggers for all * of a component's RELATIVE alarms. */ static gboolean add_alarm_occurrences_cb (ECalComponent *comp, time_t start, time_t end, gpointer data) { struct alarm_occurrence_data *aod; GList *l; aod = data; for (l = aod->alarm_uids; l; l = l->next) { const gchar *auid; ECalComponentAlarm *alarm; ECalComponentAlarmAction action; ECalComponentAlarmTrigger trigger; ECalComponentAlarmRepeat repeat; struct icaldurationtype *dur; time_t dur_time; time_t occur_time, trigger_time; gint i; auid = l->data; alarm = e_cal_component_get_alarm (comp, auid); g_return_val_if_fail (alarm != NULL, FALSE); e_cal_component_alarm_get_action (alarm, &action); e_cal_component_alarm_get_trigger (alarm, &trigger); e_cal_component_alarm_get_repeat (alarm, &repeat); e_cal_component_alarm_free (alarm); for (i = 0; aod->omit[i] != -1; i++) { if (aod->omit[i] == action) break; } if (aod->omit[i] != -1) continue; if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START && trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END) continue; dur = &trigger.u.rel_duration; dur_time = icaldurationtype_as_int (*dur); if (trigger.type == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START) occur_time = start; else occur_time = end; /* If dur->is_neg is true then dur_time will already be * negative. So we do not need to test for dur->is_neg here; we * can simply add the dur_time value to the occur_time and get * the correct result. */ trigger_time = occur_time + dur_time; /* Add repeating alarms */ if (repeat.repetitions != 0) { gint i; time_t repeat_time; repeat_time = icaldurationtype_as_int (repeat.duration); for (i = 0; i < repeat.repetitions; i++) { time_t t; t = trigger_time + (i + 1) * repeat_time; if (t >= aod->start && t < aod->end) add_trigger (aod, auid, t, start, end); } } /* Add the trigger itself */ if (trigger_time >= aod->start && trigger_time < aod->end) add_trigger (aod, auid, trigger_time, start, end); } return TRUE; }
/* Computes the range of time in which recurrences should be generated for a * component in order to compute alarm trigger times. */ static void compute_alarm_range (ECalComponent *comp, GList *alarm_uids, time_t start, time_t end, time_t *alarm_start, time_t *alarm_end) { GList *l; time_t repeat_time; *alarm_start = start; *alarm_end = end; repeat_time = 0; for (l = alarm_uids; l; l = l->next) { const gchar *auid; ECalComponentAlarm *alarm; ECalComponentAlarmTrigger trigger; struct icaldurationtype *dur; time_t dur_time; ECalComponentAlarmRepeat repeat; auid = l->data; alarm = e_cal_component_get_alarm (comp, auid); g_return_if_fail (alarm != NULL); e_cal_component_alarm_get_trigger (alarm, &trigger); e_cal_component_alarm_get_repeat (alarm, &repeat); e_cal_component_alarm_free (alarm); switch (trigger.type) { case E_CAL_COMPONENT_ALARM_TRIGGER_NONE: case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE: break; case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START: case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END: dur = &trigger.u.rel_duration; dur_time = icaldurationtype_as_int (*dur); if (repeat.repetitions != 0) { gint rdur; rdur = repeat.repetitions * icaldurationtype_as_int (repeat.duration); repeat_time = MAX (repeat_time, rdur); } if (dur->is_neg) /* If the duration is negative then dur_time * will be negative as well; that is why we * subtract to expand the range. */ *alarm_end = MAX (*alarm_end, end - dur_time); else *alarm_start = MIN (*alarm_start, start - dur_time); break; default: g_return_if_reached (); } } *alarm_start -= repeat_time; g_warn_if_fail (*alarm_start <= *alarm_end); }
/* * Construct an iCalendar property value from XML content. */ static icalvalue *xml_element_to_icalvalue(xmlNodePtr xtype, icalvalue_kind kind) { icalvalue *value = NULL; xmlNodePtr node; xmlChar *content = NULL; switch (kind) { case ICAL_GEO_VALUE: { struct icalgeotype geo; node = xmlFirstElementChild(xtype); if (!node) { syslog(LOG_WARNING, "Missing <latitude> XML element"); break; } else if (xmlStrcmp(node->name, BAD_CAST "latitude")) { syslog(LOG_WARNING, "Expected <latitude> XML element, received %s", node->name); break; } content = xmlNodeGetContent(node); geo.lat = atof((const char *) content); node = xmlNextElementSibling(node); if (!node) { syslog(LOG_WARNING, "Missing <longitude> XML element"); break; } else if (xmlStrcmp(node->name, BAD_CAST "longitude")) { syslog(LOG_WARNING, "Expected <longitude> XML element, received %s", node->name); break; } xmlFree(content); content = xmlNodeGetContent(node); geo.lon = atof((const char *) content); value = icalvalue_new_geo(geo); break; } case ICAL_PERIOD_VALUE: { struct icalperiodtype p; p.start = p.end = icaltime_null_time(); p.duration = icaldurationtype_from_int(0); node = xmlFirstElementChild(xtype); if (!node) { syslog(LOG_WARNING, "Missing <start> XML element"); break; } else if (xmlStrcmp(node->name, BAD_CAST "start")) { syslog(LOG_WARNING, "Expected <start> XML element, received %s", node->name); break; } content = xmlNodeGetContent(node); p.start = icaltime_from_string((const char *) content); if (icaltime_is_null_time(p.start)) break; node = xmlNextElementSibling(node); if (!node) { syslog(LOG_WARNING, "Missing <end> / <duration> XML element"); break; } else if (!xmlStrcmp(node->name, BAD_CAST "end")) { xmlFree(content); content = xmlNodeGetContent(node); p.end = icaltime_from_string((const char *) content); if (icaltime_is_null_time(p.end)) break; } else if (!xmlStrcmp(node->name, BAD_CAST "duration")) { xmlFree(content); content = xmlNodeGetContent(node); p.duration = icaldurationtype_from_string((const char *) content); if (icaldurationtype_as_int(p.duration) == 0) break; } else { syslog(LOG_WARNING, "Expected <end> / <duration> XML element, received %s", node->name); break; } value = icalvalue_new_period(p); break; } case ICAL_RECUR_VALUE: { struct buf rrule = BUF_INITIALIZER; struct hash_table byrules; struct icalrecurrencetype rt; char *sep = ""; construct_hash_table(&byrules, 10, 1); /* create an iCal RRULE string from xCal <recur> sub-elements */ for (node = xmlFirstElementChild(xtype); node; node = xmlNextElementSibling(node)) { content = xmlNodeGetContent(node); if (!xmlStrncmp(node->name, BAD_CAST "by", 2)) { /* BY* rules can have a list of values - assemble them using a hash table */ struct buf *vals = hash_lookup((const char *) node->name, &byrules); if (vals) { /* append this value to existing list */ buf_printf(vals, ",%s", (char *) content); } else { /* create new list with this valiue */ vals = xzmalloc(sizeof(struct buf)); buf_setcstr(vals, (char *) content); hash_insert((char *) node->name, vals, &byrules); } } else { /* single value rpart */ buf_printf(&rrule, "%s%s=%s", sep, ucase((char *) node->name), (char *) content); sep = ";"; } xmlFree(content); content = NULL; } /* append the BY* rules to RRULE buffer */ hash_enumerate(&byrules, (void (*)(const char*, void*, void*)) &append_byrule, &rrule); free_hash_table(&byrules, NULL); /* parse our iCal RRULE string */ rt = icalrecurrencetype_from_string(buf_cstring(&rrule)); buf_free(&rrule); if (rt.freq != ICAL_NO_RECURRENCE) value = icalvalue_new_recur(rt); break; } case ICAL_REQUESTSTATUS_VALUE: { struct icalreqstattype rst = { ICAL_UNKNOWN_STATUS, NULL, NULL }; short maj, min; node = xmlFirstElementChild(xtype); if (!node) { syslog(LOG_WARNING, "Missing <code> XML element"); break; } else if (xmlStrcmp(node->name, BAD_CAST "code")) { syslog(LOG_WARNING, "Expected <code> XML element, received %s", node->name); break; } content = xmlNodeGetContent(node); if (sscanf((const char *) content, "%hd.%hd", &maj, &min) == 2) { rst.code = icalenum_num_to_reqstat(maj, min); } if (rst.code == ICAL_UNKNOWN_STATUS) { syslog(LOG_WARNING, "Unknown request-status code"); break; } node = xmlNextElementSibling(node); if (!node) { syslog(LOG_WARNING, "Missing <description> XML element"); break; } else if (xmlStrcmp(node->name, BAD_CAST "description")) { syslog(LOG_WARNING, "Expected <description> XML element, received %s", node->name); break; } xmlFree(content); content = xmlNodeGetContent(node); rst.desc = (const char *) content; node = xmlNextElementSibling(node); if (node) { if (xmlStrcmp(node->name, BAD_CAST "data")) { syslog(LOG_WARNING, "Expected <data> XML element, received %s", node->name); break; } xmlFree(content); content = xmlNodeGetContent(node); rst.debug = (const char *) content; } value = icalvalue_new_requeststatus(rst); break; } case ICAL_UTCOFFSET_VALUE: { int n, utcoffset, hours, minutes, seconds = 0; char sign; content = xmlNodeGetContent(xtype); n = sscanf((const char *) content, "%c%02d:%02d:%02d", &sign, &hours, &minutes, &seconds); if (n < 3) { syslog(LOG_WARNING, "Unexpected utc-offset format"); break; } utcoffset = hours*3600 + minutes*60 + seconds; if (sign == '-') utcoffset = -utcoffset; value = icalvalue_new_utcoffset(utcoffset); break; } default: content = xmlNodeGetContent(xtype); value = icalvalue_new_from_string(kind, (const char *) content); break; } if (content) xmlFree(content); return value; }
int asInt() { return icaldurationtype_as_int( *this ); }