calRecurrenceRule::calRecurrenceRule() : mImmutable(PR_FALSE), mIsNegative(PR_FALSE), mIsByCount(PR_FALSE) { icalrecurrencetype_clear(&mIcalRecur); }
calRecurrenceRule::calRecurrenceRule() : mImmutable(false), mIsNegative(false), mIsByCount(false) { icalrecurrencetype_clear(&mIcalRecur); }
void ical_property_RRULE_Yearly(struct exchange2ical *exchange2ical) { struct icalrecurrencetype recurrence; icalproperty *prop; struct RecurrencePattern *pat = exchange2ical->RecurrencePattern; uint32_t day = pat->PatternTypeSpecific.Day; struct icaltimetype icaltime; icalrecurrencetype_clear(&recurrence); recurrence.freq = ICAL_YEARLY_RECURRENCE; recurrence.interval = (pat->Period / 12); if (day == 0x0000001F) { recurrence.by_month_day[0] = -1; } else { recurrence.by_month_day[0] = day; } recurrence.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX; icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->apptStartWhole); recurrence.by_month[0] = icaltime.month; recurrence.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX; if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) { recurrence.count = pat->OccurrenceCount; } prop = icalproperty_new_rrule(recurrence); icalcomponent_add_property(exchange2ical->vevent, prop); }
void ical_property_RRULE_daylight_standard(icalcomponent* component , struct SYSTEMTIME st) { struct icalrecurrencetype recurrence; icalproperty *prop; icalrecurrencetype_clear(&recurrence); recurrence.freq = ICAL_YEARLY_RECURRENCE; if(st.wYear ==0x0000){ recurrence.by_month[0]=st.wMonth; /* Microsoft day of week = libIcal day of week +1; */ /* Day encode = day + occurrence*8 */ if (st.wDay==5){ /* Last occurrence of day in the month*/ recurrence.by_day[0] = -1 * (st.wDayOfWeek + 9); }else{ /* st.wDay occurrence of day in the month */ recurrence.by_day[0] = (st.wDayOfWeek + 1 + st.wDay*8); } }else{ recurrence.by_month_day[0]=st.wDay; recurrence.by_month[0]=st.wMonth; } prop = icalproperty_new_rrule(recurrence); icalcomponent_add_property(component, prop); }
void ical_property_RRULE_Monthly(struct exchange2ical *exchange2ical) { struct icalrecurrencetype recurrence; icalproperty *prop; struct RecurrencePattern *pat = exchange2ical->RecurrencePattern; uint32_t day = pat->PatternTypeSpecific.Day; icalrecurrencetype_clear(&recurrence); recurrence.freq = ICAL_MONTHLY_RECURRENCE; recurrence.interval = pat->Period; if (day == 0x0000001F) { recurrence.by_month_day[0] = -1; } else { recurrence.by_month_day[0] = day; } recurrence.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX; if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) { recurrence.count = pat->OccurrenceCount; } prop = icalproperty_new_rrule(recurrence); icalcomponent_add_property(exchange2ical->vevent, prop); }
void ical_property_RRULE_Daily(struct exchange2ical *exchange2ical) { struct icalrecurrencetype recurrence; icalproperty *prop; struct RecurrencePattern *pat = exchange2ical->RecurrencePattern; icalrecurrencetype_clear(&recurrence); recurrence.freq = ICAL_DAILY_RECURRENCE; recurrence.interval = (pat->Period / 1440); if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) { recurrence.count = pat->OccurrenceCount; } prop = icalproperty_new_rrule(recurrence); icalcomponent_add_property(exchange2ical->vevent, prop); }
struct icalrecurrencetype icalrecurrencetype_from_string(const char* str) { struct icalrecur_parser parser; memset(&parser,0,sizeof(parser)); icalrecurrencetype_clear(&parser.rt); icalerror_check_arg_re(str!=0,"str",parser.rt); /* Set up the parser struct */ parser.rule = str; parser.copy = _strdup(parser.rule); parser.this_clause = parser.copy; if(parser.copy == 0){ //icalerror_set_errno(ICAL_NEWFAILED_ERROR); return parser.rt; } /* Loop through all of the clauses */ for(icalrecur_first_clause(&parser); parser.this_clause != 0; icalrecur_next_clause(&parser)) { char *name, *value; icalrecur_clause_name_and_value(&parser,&name,&value); if(name == 0){ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); icalrecurrencetype_clear(&parser.rt); free(parser.copy); return parser.rt; } if (strcasecmp(name,"FREQ") == 0){ parser.rt.freq = icalrecur_string_to_freq(value); } else if (strcasecmp(name,"COUNT") == 0){ int v = atoi(value); if (v >= 0) { parser.rt.count = v; } } else if (strcasecmp(name,"UNTIL") == 0){ parser.rt.until = icaltime_from_string(value); } else if (strcasecmp(name,"INTERVAL") == 0){ int v = atoi(value); if (v > 0 && v <= SHRT_MAX) { parser.rt.interval = (short) v; } } else if (strcasecmp(name,"WKST") == 0){ parser.rt.week_start = icalrecur_string_to_weekday(value); sort_bydayrules(parser.rt.by_day, parser.rt.week_start); } else if (strcasecmp(name,"BYSECOND") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_second, ICAL_BY_SECOND_SIZE,value); } else if (strcasecmp(name,"BYMINUTE") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_minute, ICAL_BY_MINUTE_SIZE,value); } else if (strcasecmp(name,"BYHOUR") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_hour, ICAL_BY_HOUR_SIZE,value); } else if (strcasecmp(name,"BYDAY") == 0){ icalrecur_add_bydayrules(&parser,value); } else if (strcasecmp(name,"BYMONTHDAY") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_month_day, ICAL_BY_MONTHDAY_SIZE,value); } else if (strcasecmp(name,"BYYEARDAY") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_year_day, ICAL_BY_YEARDAY_SIZE,value); } else if (strcasecmp(name,"BYWEEKNO") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_week_no, ICAL_BY_WEEKNO_SIZE,value); } else if (strcasecmp(name,"BYMONTH") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_month, ICAL_BY_MONTH_SIZE,value); } else if (strcasecmp(name,"BYSETPOS") == 0){ icalrecur_add_byrules(&parser,parser.rt.by_set_pos, ICAL_BY_SETPOS_SIZE,value); } else { icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); icalrecurrencetype_clear(&parser.rt); free(parser.copy); return parser.rt; } } free(parser.copy); return parser.rt; }
icalcomponent *icaltzutil_fetch_timezone(const char *location) { tzinfo type_cnts; size_t i, num_trans, num_chars, num_leaps, num_isstd, num_isgmt; size_t num_types = 0; size_t size; time_t trans; int dstidx = -1, stdidx = -1, pos, sign, zidx, zp_idx; icalcomponent *std_comp = NULL; const char *zonedir; FILE *f = NULL; char *full_path = NULL; time_t *transitions = NULL; char *r_trans = NULL, *temp; int *trans_idx = NULL; ttinfo *types = NULL; char *znames = NULL; leap *leaps = NULL; char *tzid = NULL; time_t start, end; int idx, prev_idx; icalcomponent *tz_comp = NULL, *comp = NULL, *dst_comp; icalproperty *icalprop; icaltimetype dtstart, icaltime; struct icalrecurrencetype ical_recur; if (icaltimezone_get_builtin_tzdata()) { goto error; } zonedir = icaltzutil_get_zone_directory(); if (!zonedir) { icalerror_set_errno(ICAL_FILE_ERROR); goto error; } size = strlen(zonedir) + strlen(location) + 2; full_path = (char *)malloc(size); if (full_path == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } snprintf(full_path, size, "%s/%s", zonedir, location); if ((f = fopen(full_path, "rb")) == 0) { icalerror_set_errno(ICAL_FILE_ERROR); goto error; } if (fseek(f, 20, SEEK_SET) != 0) { icalerror_set_errno(ICAL_FILE_ERROR); goto error; } EFREAD(&type_cnts, 24, 1, f); num_isgmt = (size_t)decode(type_cnts.ttisgmtcnt); num_leaps = (size_t)decode(type_cnts.leapcnt); num_chars = (size_t)decode(type_cnts.charcnt); num_trans = (size_t)decode(type_cnts.timecnt); num_isstd = (size_t)decode(type_cnts.ttisstdcnt); num_types = (size_t)decode(type_cnts.typecnt); transitions = calloc(num_trans, sizeof(time_t)); if (transitions == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } r_trans = calloc(num_trans, 4); if (r_trans == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } EFREAD(r_trans, 4, num_trans, f); temp = r_trans; if (num_trans) { trans_idx = calloc(num_trans, sizeof(int)); if (trans_idx == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } for (i = 0; i < num_trans; i++) { trans_idx[i] = fgetc(f); transitions[i] = (time_t) decode(r_trans); r_trans += 4; } } r_trans = temp; types = calloc(num_types, sizeof(ttinfo)); if (types == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } for (i = 0; i < num_types; i++) { unsigned char a[4]; int c; EFREAD(a, 4, 1, f); c = fgetc(f); types[i].isdst = (unsigned char)c; if ((c = fgetc(f)) < 0) { break; } types[i].abbr = (unsigned int)c; types[i].gmtoff = decode(a); } znames = (char *)malloc(num_chars); if (znames == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } EFREAD(znames, num_chars, 1, f); /* We got all the information which we need */ leaps = calloc(num_leaps, sizeof(leap)); if (leaps == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } for (i = 0; i < num_leaps; i++) { char c[4]; EFREAD(c, 4, 1, f); leaps[i].transition = (time_t)decode(c); EFREAD(c, 4, 1, f); leaps[i].change = decode(c); } for (i = 0; i < num_isstd; ++i) { int c = getc(f); types[i].isstd = c != 0; } while (i < num_types) { types[i++].isstd = 0; } for (i = 0; i < num_isgmt; ++i) { int c = getc(f); types[i].isgmt = c != 0; } while (i < num_types) { types[i++].isgmt = 0; } /* Read all the contents now */ for (i = 0; i < num_types; i++) { /* coverity[tainted_data] */ types[i].zname = zname_from_stridx(znames, types[i].abbr); } if (!_s_use_exact_timezones) { if (num_trans != 0) { find_transidx(transitions, types, trans_idx, (long int)num_trans, &stdidx, &dstidx); } else { stdidx = 0; } } tz_comp = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT); /* Add tzid property */ size = strlen(icaltimezone_tzid_prefix()) + strlen(location) + 1; tzid = (char *)malloc(size); if (tzid == NULL) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); goto error; } snprintf(tzid, size, "%s%s", icaltimezone_tzid_prefix(), location); icalprop = icalproperty_new_tzid(tzid); icalcomponent_add_property(tz_comp, icalprop); icalprop = icalproperty_new_x(location); icalproperty_set_x_name(icalprop, "X-LIC-LOCATION"); icalcomponent_add_property(tz_comp, icalprop); if (!_s_use_exact_timezones) { if (stdidx != -1) { if (num_trans != 0) { zidx = trans_idx[stdidx]; } else { zidx = 0; } std_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); icalprop = icalproperty_new_tzname(types[zidx].zname); icalcomponent_add_property(std_comp, icalprop); if (dstidx != -1) { zp_idx = trans_idx[stdidx-1]; } else { zp_idx = zidx; } /* DTSTART localtime uses TZOFFSETFROM UTC offset */ if (num_trans != 0) { trans = transitions[stdidx] + types[zp_idx].gmtoff; } else { trans = (time_t)types[zp_idx].gmtoff; } icaltime = icaltime_from_timet_with_zone(trans, 0, NULL); dtstart = icaltime; dtstart.year = 1970; dtstart.minute = dtstart.second = 0; icalprop = icalproperty_new_dtstart(dtstart); icalcomponent_add_property(std_comp, icalprop); /* If DST changes are present use RRULE */ if (dstidx != -1) { icalrecurrencetype_clear(&ical_recur); ical_recur.freq = ICAL_YEARLY_RECURRENCE; ical_recur.by_month[0] = icaltime.month; pos = calculate_pos(icaltime); pos < 0 ? (sign = -1): (sign = 1); ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime)); icalprop = icalproperty_new_rrule(ical_recur); icalcomponent_add_property(std_comp, icalprop); adjust_dtstart_day_to_rrule(std_comp, ical_recur); } icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff); icalcomponent_add_property(std_comp, icalprop); icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff); icalcomponent_add_property(std_comp, icalprop); icalcomponent_add_component(tz_comp, std_comp); } else { icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); } if (dstidx != -1) { zidx = trans_idx[dstidx]; zp_idx = trans_idx[dstidx-1]; dst_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); icalprop = icalproperty_new_tzname(types[zidx].zname); icalcomponent_add_property(dst_comp, icalprop); /* DTSTART localtime uses TZOFFSETFROM UTC offset */ trans = transitions[dstidx] + types[zp_idx].gmtoff; icaltime = icaltime_from_timet_with_zone(trans, 0, NULL); dtstart = icaltime; dtstart.year = 1970; dtstart.minute = dtstart.second = 0; icalprop = icalproperty_new_dtstart(dtstart); icalcomponent_add_property(dst_comp, icalprop); icalrecurrencetype_clear(&ical_recur); ical_recur.freq = ICAL_YEARLY_RECURRENCE; ical_recur.by_month[0] = icaltime.month; pos = calculate_pos(icaltime); pos < 0 ? (sign = -1): (sign = 1); ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime)); icalprop = icalproperty_new_rrule(ical_recur); icalcomponent_add_property(dst_comp, icalprop); adjust_dtstart_day_to_rrule(dst_comp, ical_recur); icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff); icalcomponent_add_property(dst_comp, icalprop); icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff); icalcomponent_add_property(dst_comp, icalprop); icalcomponent_add_component(tz_comp, dst_comp); } } else { /*exact vtimezones*/ prev_idx = 0; if (num_trans == 0) { prev_idx = idx = 0; } else { idx = trans_idx[0]; } start = 0; for (i = 1; i < num_trans; i++, start = end) { prev_idx = idx; idx = trans_idx[i]; end = transitions[i] + types[prev_idx].gmtoff; /* don't bother starting until the epoch */ if (0 > end) continue; if (types[prev_idx].isdst) { comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); } else { comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); } icalprop = icalproperty_new_tzname(types[prev_idx].zname); icalcomponent_add_property(comp, icalprop); dtstart = icaltime_from_timet_with_zone(start, 0, NULL); icalprop = icalproperty_new_dtstart(dtstart); icalcomponent_add_property(comp, icalprop); icalprop = icalproperty_new_tzoffsetfrom(types[idx].gmtoff); icalcomponent_add_property(comp, icalprop); icalprop = icalproperty_new_tzoffsetto(types[prev_idx].gmtoff); icalcomponent_add_property(comp, icalprop); icalcomponent_add_component(tz_comp, comp); } /* finally, add a last zone with no end date */ if (types[idx].isdst) { comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); } else { comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); } icalprop = icalproperty_new_tzname(types[idx].zname); icalcomponent_add_property(comp, icalprop); dtstart = icaltime_from_timet_with_zone(start, 0, NULL); icalprop = icalproperty_new_dtstart(dtstart); icalcomponent_add_property(comp, icalprop); icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff); icalcomponent_add_property(comp, icalprop); icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff); icalcomponent_add_property(comp, icalprop); icalcomponent_add_component(tz_comp, comp); } error: if (f) fclose(f); if (full_path) free(full_path); if (transitions) free(transitions); if (r_trans) free(r_trans); if (trans_idx) free(trans_idx); if (types) { for (i = 0; i < num_types; i++) { if (types[i].zname) { free(types[i].zname); } } free(types); } if (znames) free(znames); if (leaps) free(leaps); if (tzid) free(tzid); return tz_comp; }
void ical_property_RRULE_NthYearly(struct exchange2ical *exchange2ical) { struct icalrecurrencetype recurrence; icalproperty *prop; struct RecurrencePattern *pat = exchange2ical->RecurrencePattern; uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern; short idx = 0; enum RecurrenceN setpos = pat->PatternTypeSpecific.MonthRecurrencePattern.N; struct icaltimetype icaltime; icalrecurrencetype_clear(&recurrence); recurrence.freq = ICAL_YEARLY_RECURRENCE; recurrence.interval = (pat->Period / 12); if (rdfDaysBitmask & Su) { recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & M) { recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & Tu) { recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & W) { recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & Th) { recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & F) { recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & Sa) { recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY; ++idx; } recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX; if (setpos == RecurrenceN_First) { recurrence.by_set_pos[0] = 1; recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX; } else if (setpos == RecurrenceN_Second) { recurrence.by_set_pos[0] = 2; recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX; } else if (setpos == RecurrenceN_Third) { recurrence.by_set_pos[0] = 3; recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX; } else if (setpos == RecurrenceN_Fourth) { recurrence.by_set_pos[0] = 4; recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX; } else if (setpos == RecurrenceN_Last) { recurrence.by_set_pos[0] = -1; recurrence.by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX; } icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole); recurrence.by_month[0] = icaltime.month; recurrence.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX; if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) { recurrence.count = pat->OccurrenceCount; } prop = icalproperty_new_rrule(recurrence); icalcomponent_add_property(exchange2ical->vevent, prop); }
void ical_property_RRULE_Weekly(struct exchange2ical *exchange2ical) { struct icalrecurrencetype recurrence; icalproperty *prop; struct RecurrencePattern *pat = exchange2ical->RecurrencePattern; uint32_t rdfDaysBitmask = pat->PatternTypeSpecific.WeekRecurrencePattern; short idx = 0; icalrecurrencetype_clear(&recurrence); recurrence.freq = ICAL_WEEKLY_RECURRENCE; recurrence.interval = pat->Period; if(pat->Period > 1){ switch(pat->FirstDOW){ case FirstDOW_Sunday: recurrence.week_start=ICAL_SUNDAY_WEEKDAY; break; case FirstDOW_Monday: recurrence.week_start=ICAL_MONDAY_WEEKDAY; break; case FirstDOW_Tuesday: recurrence.week_start=ICAL_TUESDAY_WEEKDAY; break; case FirstDOW_Wednesday: recurrence.week_start=ICAL_WEDNESDAY_WEEKDAY; break; case FirstDOW_Thursday: recurrence.week_start=ICAL_THURSDAY_WEEKDAY; break; case FirstDOW_Friday: recurrence.week_start=ICAL_FRIDAY_WEEKDAY; break; case FirstDOW_Saturday: recurrence.week_start=ICAL_SATURDAY_WEEKDAY; break; } } if (rdfDaysBitmask & Su) { recurrence.by_day[idx] = ICAL_SUNDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & M) { recurrence.by_day[idx] = ICAL_MONDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & Tu) { recurrence.by_day[idx] = ICAL_TUESDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & W) { recurrence.by_day[idx] = ICAL_WEDNESDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & Th) { recurrence.by_day[idx] = ICAL_THURSDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & F) { recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY; ++idx; } if (rdfDaysBitmask & Sa) { recurrence.by_day[idx] = ICAL_FRIDAY_WEEKDAY; ++idx; } recurrence.by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX; if (pat->EndType == END_AFTER_N_OCCURRENCES || pat->EndType == END_AFTER_DATE) { recurrence.count = pat->OccurrenceCount; } prop = icalproperty_new_rrule(recurrence); icalcomponent_add_property(exchange2ical->vevent, prop); }
icalcomponent* icaltzutil_fetch_timezone (const char *location) { int ret = 0; FILE *f; tzinfo type_cnts; unsigned int num_trans, num_types, num_chars, num_leaps, num_isstd, num_isgmt; time_t *transitions = NULL; time_t trans; int *trans_idx = NULL, dstidx = -1, stdidx = -1, pos, sign, zidx, zp_idx, i; ttinfo *types = NULL; char *znames = NULL, *full_path, *tzid, *r_trans, *temp; leap *leaps = NULL; icalcomponent *tz_comp = NULL, *dst_comp = NULL, *std_comp = NULL; icalproperty *icalprop; icaltimetype dtstart, icaltime; struct icalrecurrencetype ical_recur; if (!zdir) set_zone_directory (); full_path = (char *) malloc (strlen (zdir) + strlen (location) + 2); sprintf (full_path,"%s/%s",zdir, location); if ((f = fopen (full_path, "rb")) == 0) { icalerror_set_errno (ICAL_FILE_ERROR); free (full_path); return NULL; } if ((ret = fseek (f, 20, SEEK_SET)) != 0) { icalerror_set_errno (ICAL_FILE_ERROR); goto error; } EFREAD(&type_cnts, 24, 1, f); num_isgmt = decode (type_cnts.ttisgmtcnt); num_leaps = decode (type_cnts.leapcnt); num_chars = decode (type_cnts.charcnt); num_trans = decode (type_cnts.timecnt); num_isstd = decode (type_cnts.ttisstdcnt); num_types = decode (type_cnts.typecnt); transitions = calloc (num_trans, sizeof (time_t)); r_trans = calloc (num_trans, 4); EFREAD(r_trans, 4, num_trans, f); temp = r_trans; if (num_trans) { trans_idx = calloc (num_trans, sizeof (int)); for (i = 0; i < num_trans; i++) { trans_idx [i] = fgetc (f); transitions [i] = decode (r_trans); r_trans += 4; } } free (temp); types = calloc (num_types, sizeof (ttinfo)); for (i = 0; i < num_types; i++) { unsigned char a [4]; int c; EFREAD(a, 4, 1, f); c = fgetc (f); types [i].isdst = c; if((c = fgetc (f)) < 0) { c = 0; break; } types [i].abbr = c; types [i].gmtoff = decode (a); } znames = (char *) malloc (num_chars); EFREAD(znames, num_chars, 1, f); /* We got all the information which we need */ leaps = calloc (num_leaps, sizeof (leap)); for (i = 0; i < num_leaps; i++) { char c [4]; EFREAD (c, 4, 1, f); leaps [i].transition = decode (c); EFREAD (c, 4, 1, f); leaps [i].change = decode (c); } for (i = 0; i < num_isstd; ++i) { int c = getc (f); types [i].isstd = c != 0; } while (i < num_types) types [i++].isstd = 0; for (i = 0; i < num_isgmt; ++i) { int c = getc (f); types [i].isgmt = c != 0; } while (i < num_types) types [i++].isgmt = 0; /* Read all the contents now */ for (i = 0; i < num_types; i++) types [i].zname = zname_from_stridx (znames, types [i].abbr); if (num_trans != 0) find_transidx (transitions, types, trans_idx, num_trans, &stdidx, &dstidx); else stdidx = 0; tz_comp = icalcomponent_new (ICAL_VTIMEZONE_COMPONENT); /* Add tzid property */ tzid = (char *) malloc (strlen (ical_tzid_prefix) + strlen (location) + 8); sprintf (tzid, "%sTzfile/%s", ical_tzid_prefix, location); icalprop = icalproperty_new_tzid (tzid); icalcomponent_add_property (tz_comp, icalprop); free (tzid); icalprop = icalproperty_new_x (location); icalproperty_set_x_name (icalprop, "X-LIC-LOCATION"); icalcomponent_add_property (tz_comp, icalprop); if (stdidx != -1) { if (num_trans != 0) zidx = trans_idx [stdidx]; else zidx = 0; std_comp = icalcomponent_new (ICAL_XSTANDARD_COMPONENT); icalprop = icalproperty_new_tzname (types [zidx].zname); icalcomponent_add_property (std_comp, icalprop); if (dstidx != -1) zp_idx = trans_idx [stdidx-1]; else zp_idx = zidx; /* DTSTART localtime uses TZOFFSETFROM UTC offset */ trans = transitions [stdidx] + types [zp_idx].gmtoff; icaltime = icaltime_from_timet (trans, 0); dtstart = icaltime; dtstart.year = 1970; dtstart.minute = dtstart.second = 0; icalprop = icalproperty_new_dtstart (dtstart); icalcomponent_add_property (std_comp, icalprop); /* If DST changes are present use RRULE */ if (dstidx != -1) { icalrecurrencetype_clear (&ical_recur); ical_recur.freq = ICAL_YEARLY_RECURRENCE; ical_recur.by_month [0] = icaltime.month; pos = calculate_pos (icaltime); pos < 0 ? (sign = -1): (sign = 1); ical_recur.by_day [0] = sign * ((abs (pos) * 8) + icaltime_day_of_week (icaltime)); icalprop = icalproperty_new_rrule (ical_recur); icalcomponent_add_property (std_comp, icalprop); adjust_dtstart_day_to_rrule (std_comp, ical_recur); } icalprop = icalproperty_new_tzoffsetfrom (types [zp_idx].gmtoff); icalcomponent_add_property (std_comp, icalprop); icalprop = icalproperty_new_tzoffsetto (types [zidx].gmtoff); icalcomponent_add_property (std_comp, icalprop); icalcomponent_add_component (tz_comp, std_comp); } else icalerror_set_errno (ICAL_MALFORMEDDATA_ERROR); if (dstidx != -1) { zidx = trans_idx [dstidx]; zp_idx = trans_idx [dstidx-1]; dst_comp = icalcomponent_new (ICAL_XDAYLIGHT_COMPONENT); icalprop = icalproperty_new_tzname (types [zidx].zname); icalcomponent_add_property (dst_comp, icalprop); /* DTSTART localtime uses TZOFFSETFROM UTC offset */ trans = transitions [dstidx] + types [zp_idx].gmtoff; icaltime = icaltime_from_timet (trans, 0); dtstart = icaltime; dtstart.year = 1970; dtstart.minute = dtstart.second = 0; icalprop = icalproperty_new_dtstart (dtstart); icalcomponent_add_property (dst_comp, icalprop); icalrecurrencetype_clear (&ical_recur); ical_recur.freq = ICAL_YEARLY_RECURRENCE; ical_recur.by_month [0] = icaltime.month; pos = calculate_pos (icaltime); pos < 0 ? (sign = -1): (sign = 1); ical_recur.by_day [0] = sign * ((abs (pos) * 8) + icaltime_day_of_week (icaltime)); icalprop = icalproperty_new_rrule (ical_recur); icalcomponent_add_property (dst_comp, icalprop); adjust_dtstart_day_to_rrule (dst_comp, ical_recur); icalprop = icalproperty_new_tzoffsetfrom (types [zp_idx].gmtoff); icalcomponent_add_property (dst_comp, icalprop); icalprop = icalproperty_new_tzoffsetto (types [zidx].gmtoff); icalcomponent_add_property (dst_comp, icalprop); icalcomponent_add_component (tz_comp, dst_comp); } error: if (f) fclose (f); if (transitions) free (transitions); if (trans_idx) free (trans_idx); if (types) { for (i = 0; i < num_types; i++) if (types [i].zname) free (types [i].zname); free (types); } if (znames) free (znames); free (full_path); if (leaps) free (leaps); return tz_comp; }