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);
}
Example #7
0
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;

}
Example #8
0
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;
}