void ical_property_DTSTART(struct exchange2ical *exchange2ical) { icalproperty *prop; icalparameter *tzid; struct icaltimetype icaltime; /* Sanity check */ if (!exchange2ical->apptStartWhole) return; /* If this is an all-day appointment */ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) { icaltime = get_icaldate_from_FILETIME(exchange2ical->apptStartWhole); prop = icalproperty_new_dtstart(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); } else { if (exchange2ical->TimeZoneDesc) { icaltime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole); prop = icalproperty_new_dtstart(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc); icalproperty_add_parameter(prop, tzid); } else { icaltime = get_icaltime_from_FILETIME_UTC(exchange2ical->apptStartWhole); prop = icalproperty_new_dtstart(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); } } }
icalcomponent *icalspanlist_as_vfreebusy(icalspanlist* sl, const char* organizer, const char* attendee) { icalcomponent *comp; icalproperty *p; struct icaltimetype atime = icaltime_from_timet( time(0),0); pvl_elem itr; icaltimezone *utc_zone; icalparameter *param; if (!attendee) { icalerror_set_errno(ICAL_USAGE_ERROR); return 0; } utc_zone = icaltimezone_get_utc_timezone (); comp = icalcomponent_new_vfreebusy(); icalcomponent_add_property(comp, icalproperty_new_dtstart(sl->start)); icalcomponent_add_property(comp, icalproperty_new_dtend(sl->end)); icalcomponent_add_property(comp, icalproperty_new_dtstamp(atime)); if (organizer) { icalcomponent_add_property(comp, icalproperty_new_organizer(organizer)); } icalcomponent_add_property(comp, icalproperty_new_attendee(attendee)); /* now add the freebusy sections.. */ for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) { struct icalperiodtype period; struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr); if (s->is_busy == 1) { period.start = icaltime_from_timet_with_zone (s->start, 0, utc_zone); period.end = icaltime_from_timet_with_zone (s->end, 0, utc_zone); period.duration = icaldurationtype_null_duration(); p = icalproperty_new_freebusy(period); param = icalparameter_new_fbtype(ICAL_FBTYPE_BUSY); icalproperty_add_parameter(p, param); icalcomponent_add_property(comp, p); } } return comp; }
void MainWindow::createIcalEvent(Event *event) { icalcomponent *iEvent; icalproperty *prop; iEvent = icalcomponent_new(ICAL_VEVENT_COMPONENT); prop = icalproperty_new_summary(event->icalSummary().c_str()); icalcomponent_add_property(iEvent, prop); prop = icalproperty_new_uid(event->icalUid().c_str()); icalcomponent_add_property(iEvent, prop); prop = icalproperty_new_relatedto(event->icalRelatedTo().c_str()); icalcomponent_add_property(iEvent, prop); prop = icalproperty_new_dtstart(event->icalDtStart()); icalcomponent_add_property(iEvent, prop); prop = icalproperty_new_dtend(event->icalDtEnd()); icalcomponent_add_property(iEvent, prop); saveToIcsFile(iEvent, event->icalUid()); }
/* ICALENDAR Reading functions */ GNOKII_API char *gn_calnote2icalstr(gn_calnote *calnote) { ical_string str; #ifdef HAVE_LIBICAL icalcomponent *pIcal = NULL, *vevent; struct icaltimetype stime = {0}, etime = {0}; char compuid[64]; memset(&str, 0, sizeof (str)); /* In at least some Nokia phones it is possible to skip the year of birth, in this case year == 0xffff, so we set it to the arbitrary value of 1800 */ stime.year = (calnote->time.year == 0xffff ? 1800 : calnote->time.year); stime.month = calnote->time.month; stime.day = calnote->time.day; stime.hour = calnote->time.hour; stime.minute = calnote->time.minute; stime.second = calnote->time.second; stime.is_daylight = 1; snprintf(compuid, sizeof(compuid), "guid.gnokii.org_%d_%d", calnote->location, rand()); vevent = icalcomponent_vanew(ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(stime), icalproperty_new_uid(compuid), icalproperty_new_categories("GNOKII"), 0); if (!vevent) { dprintf("ERROR in icalcomponent_vanew() creating VEVENT\n"); return NULL; } if (calnote->end_time.year) { etime.year = (calnote->end_time.year == 0xffff ? 1800 : calnote->end_time.year); etime.month = calnote->end_time.month; etime.day = calnote->end_time.day; etime.hour = calnote->end_time.hour; etime.minute = calnote->end_time.minute; etime.second = calnote->end_time.second; etime.is_daylight = 1; icalcomponent_add_property(vevent, icalproperty_new_dtend(etime)); } /* TODO: should the strings be configurable? */ switch(calnote->type) { case GN_CALNOTE_MEMO: icalcomponent_add_property(vevent, icalproperty_new_categories("MISCELLANEOUS")); icalcomponent_add_property(vevent, icalproperty_new_summary(calnote->text)); break; case GN_CALNOTE_REMINDER: icalcomponent_add_property(vevent, icalproperty_new_categories("REMINDER")); icalcomponent_add_property(vevent, icalproperty_new_summary(calnote->text)); break; case GN_CALNOTE_CALL: icalcomponent_add_property(vevent, icalproperty_new_categories("PHONE CALL")); icalcomponent_add_property(vevent, icalproperty_new_summary(calnote->phone_number)); icalcomponent_add_property(vevent, icalproperty_new_description(calnote->text)); break; case GN_CALNOTE_MEETING: icalcomponent_add_property(vevent, icalproperty_new_categories("MEETING")); icalcomponent_add_property(vevent, icalproperty_new_summary(calnote->text)); if (calnote->mlocation[0]) icalcomponent_add_property(vevent, icalproperty_new_location(calnote->mlocation)); break; case GN_CALNOTE_BIRTHDAY: icalcomponent_add_property(vevent, icalproperty_new_categories("ANNIVERSARY")); icalcomponent_add_property(vevent, icalproperty_new_summary(calnote->text)); stime.is_date = 1; calnote->recurrence = GN_CALNOTE_YEARLY; break; default: icalcomponent_add_property(vevent, icalproperty_new_categories("UNKNOWN")); icalcomponent_add_property(vevent, icalproperty_new_summary(calnote->text)); break; } if (calnote->recurrence) { char rrule[64]; char *freq; int interval = 1; switch (calnote->recurrence) { case GN_CALNOTE_NEVER: goto norecurrence; case GN_CALNOTE_DAILY: freq = "DAILY"; break; case GN_CALNOTE_WEEKLY: freq = "WEEKLY"; break; case GN_CALNOTE_2WEEKLY: freq = "WEEKLY"; interval = 2; break; case GN_CALNOTE_MONTHLY: freq = "MONTHLY"; break; case GN_CALNOTE_YEARLY: freq = "YEARLY"; break; default: freq = "HOURLY"; interval = calnote->recurrence; break; } if (calnote->type == GN_CALNOTE_BIRTHDAY) snprintf(rrule, sizeof(rrule), "FREQ=YEARLY;INTERVAL=1;BYMONTH=%d", stime.month); else if (calnote->occurrences == 0) snprintf(rrule, sizeof(rrule), "FREQ=%s;INTERVAL=%d", freq, interval); else snprintf(rrule, sizeof(rrule), "FREQ=%s;COUNT=%d;INTERVAL=%d", freq, calnote->occurrences, interval); icalcomponent_add_property(vevent, icalproperty_new_rrule(icalrecurrencetype_from_string(rrule))); } norecurrence: if (calnote->alarm.enabled) { icalcomponent *valarm; struct icaltriggertype trig; trig.time.year = (calnote->alarm.timestamp.year == 0xffff ? 1800 : calnote->alarm.timestamp.year); trig.time.month = calnote->alarm.timestamp.month; trig.time.day = calnote->alarm.timestamp.day; trig.time.hour = calnote->alarm.timestamp.hour; trig.time.minute = calnote->alarm.timestamp.minute; trig.time.second = calnote->alarm.timestamp.second; trig.time.is_daylight = 1; valarm = icalcomponent_new_valarm(); icalcomponent_add_property(valarm, icalproperty_new_trigger(trig)); /* FIXME: with ICAL_ACTION_DISPLAY a DESCRIPTION property is mandatory */ icalcomponent_add_property(valarm, icalproperty_new_action(calnote->alarm.tone ? ICAL_ACTION_AUDIO : ICAL_ACTION_DISPLAY)); icalcomponent_add_component(vevent, valarm); } pIcal = icalcomponent_vanew(ICAL_VCALENDAR_COMPONENT, icalproperty_new_version("2.0"), icalproperty_new_prodid(get_prodid()), vevent, 0); if (pIcal) { char *icalstrbuf = NULL; const char *icalstr = icalcomponent_as_ical_string(pIcal); /* conversion to UTF-8 */ if (string_base64(icalstr)) { int icalstrlen = strlen(icalstr); icalstrbuf = malloc(icalstrlen * 2 + 1); utf8_encode(icalstrbuf, icalstrlen * 2, icalstr, icalstrlen); icalstr = icalstrbuf; } ical_append_printf(&str, "%s\n", icalstr); dprintf("%s\n", icalstr); if (icalstrbuf) free(icalstrbuf); icalcomponent_free(pIcal); pIcal = NULL; } else { dprintf("ERROR in icalcomponent_vanew() creating VCALENDAR\n"); } return str.str; #else memset(&str, 0, sizeof (str)); ical_append_printf(&str, "BEGIN:VCALENDAR\r\n"); ical_append_printf(&str, "VERSION:1.0\r\n"); ical_append_printf(&str, "BEGIN:VEVENT\r\n"); ical_append_printf(&str, "CATEGORIES:"); switch (calnote->type) { case GN_CALNOTE_MEMO: ical_append_printf(&str, "MISCELLANEOUS\r\n"); break; case GN_CALNOTE_REMINDER: ical_append_printf(&str, "REMINDER\r\n"); break; case GN_CALNOTE_CALL: ical_append_printf(&str, "PHONE CALL\r\n"); ical_append_printf(&str, "SUMMARY:%s\r\n", calnote->phone_number); ical_append_printf(&str, "DESCRIPTION:%s\r\n", calnote->text); break; case GN_CALNOTE_MEETING: ical_append_printf(&str, "MEETING\r\n"); if (calnote->mlocation[0]) ical_append_printf(&str, "LOCATION:%s\r\n", calnote->mlocation); break; case GN_CALNOTE_BIRTHDAY: ical_append_printf(&str, "SPECIAL OCCASION\r\n"); break; default: ical_append_printf(&str, "UNKNOWN\r\n"); break; } if (calnote->type != GN_CALNOTE_CALL) ical_append_printf(&str, "SUMMARY:%s\r\n", calnote->text); ical_append_printf(&str, "DTSTART:%04d%02d%02dT%02d%02d%02d\r\n", calnote->time.year, calnote->time.month, calnote->time.day, calnote->time.hour, calnote->time.minute, calnote->time.second); if (calnote->end_time.year) { ical_append_printf(&str, "DTEND:%04d%02d%02dT%02d%02d%02d\r\n", calnote->end_time.year, calnote->end_time.month, calnote->end_time.day, calnote->end_time.hour, calnote->end_time.minute, calnote->end_time.second); } if (calnote->alarm.enabled) { ical_append_printf(&str, "%sALARM:%04d%02d%02dT%02d%02d%02d\r\n", (calnote->alarm.tone ? "A" : "D"), calnote->alarm.timestamp.year, calnote->alarm.timestamp.month, calnote->alarm.timestamp.day, calnote->alarm.timestamp.hour, calnote->alarm.timestamp.minute, calnote->alarm.timestamp.second); } switch (calnote->recurrence) { case GN_CALNOTE_NEVER: break; case GN_CALNOTE_DAILY: calnote->occurrences ? ical_append_printf(&str, "RRULE:FREQ=DAILY\r\n") : ical_append_printf(&str, "RRULE:FREQ=DAILY;COUNT=%d\r\n", calnote->occurrences); break; case GN_CALNOTE_WEEKLY: calnote->occurrences ? ical_append_printf(&str, "RRULE:FREQ=WEEKLY\r\n") : ical_append_printf(&str, "RRULE:FREQ=WEEKLY;COUNT=%d\r\n", calnote->occurrences); break; case GN_CALNOTE_2WEEKLY: calnote->occurrences ? ical_append_printf(&str, "RRULE:FREQ=WEEKLY;INTERVAL=2\r\n") : ical_append_printf(&str, "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=%d\r\n", calnote->occurrences); break; case GN_CALNOTE_MONTHLY: calnote->occurrences ? ical_append_printf(&str, "RRULE:FREQ=MONTHLY\r\n") : ical_append_printf(&str, "RRULE:FREQ=MONTHLY;COUNT=%d\r\n", calnote->occurrences); break; case GN_CALNOTE_YEARLY: calnote->occurrences ? ical_append_printf(&str, "RRULE:FREQ=YEARLY\r\n") : ical_append_printf(&str, "RRULE:FREQ=YEARLY;COUNT=%d\r\n", calnote->occurrences); break; default: calnote->occurrences ? ical_append_printf(&str, "RRULE:FREQ=HOURLY;INTERVAL=%d\r\n", calnote->recurrence) : ical_append_printf(&str, "RRULE:FREQ=HOURLY;INTERVAL=%d;COUNT=%d\r\n", calnote->recurrence, calnote->occurrences); break; } ical_append_printf(&str, "END:VEVENT\r\n"); ical_append_printf(&str, "END:VCALENDAR\r\n"); return str.str; #endif /* HAVE_LIBICAL */ }
static uint8_t exchange2ical_exception_from_ExceptionInfo(struct exchange2ical *exchange2ical, struct exchange2ical_check *exchange2ical_check) { uint32_t i; icalproperty *prop; icalparameter *param; icaltimetype icaltime; /*sanity checks*/ if(!exchange2ical->AppointmentRecurrencePattern) return 1; if(!exchange2ical->AppointmentRecurrencePattern->ExceptionInfo) return 1; if(!exchange2ical->AppointmentRecurrencePattern->ExceptionCount) return 1; for(i=0; i<exchange2ical->AppointmentRecurrencePattern->ExceptionCount; i++) { /*Check to see if event is acceptable*/ struct tm apptStart=get_tm_from_minutes_UTC(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->StartDateTime); if (!checkEvent(exchange2ical, exchange2ical_check, &apptStart)){ return 0; } /*Create a new vevent*/ exchange2ical->vevent = icalcomponent_new_vevent(); if ( ! (exchange2ical->vevent) ) { return 1; } icalcomponent_add_component(exchange2ical->vcalendar, exchange2ical->vevent); /*dtstart from StartDateTime*/ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) { struct tm tm; tm = get_tm_from_minutes_UTC(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->StartDateTime); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_dtstart(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); }else { if(exchange2ical->TimeZoneDesc){ struct tm tm; tm = get_tm_from_minutes(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->StartDateTime); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_dtstart(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); param = icalparameter_new_tzid(exchange2ical->TimeZoneDesc); icalproperty_add_parameter(prop, param); } else { struct tm tm; tm = get_tm_from_minutes_UTC(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->StartDateTime); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_dtstart(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); } } /*dtend from EndDateTime*/ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) { struct tm tm; tm = get_tm_from_minutes_UTC(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->EndDateTime); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_dtend(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); }else { if(exchange2ical->TimeZoneDesc){ struct tm tm; tm = get_tm_from_minutes(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->EndDateTime); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_dtend(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); param = icalparameter_new_tzid(exchange2ical->TimeZoneDesc); icalproperty_add_parameter(prop, param); } else { struct tm tm; tm = get_tm_from_minutes_UTC(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->EndDateTime); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_dtend(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); } } /*recurrence-id from OriginalStartDate*/ if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) { struct tm tm; tm = get_tm_from_minutes_UTC(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OriginalStartDate); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_recurrenceid(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); }else { if(exchange2ical->TimeZoneDesc){ struct tm tm; tm = get_tm_from_minutes(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OriginalStartDate); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_recurrenceid(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); param = icalparameter_new_tzid(exchange2ical->TimeZoneDesc); icalproperty_add_parameter(prop, param); } else { struct tm tm; tm = get_tm_from_minutes_UTC(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OriginalStartDate); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_recurrenceid(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); } } /*summary from Subject if subject is set*/ if (exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OverrideFlags & 0x0001) { exchange2ical->Subject=(const char *) &exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->Subject.subjectMsg.msg; ical_property_SUMMARY(exchange2ical); } /*Valarm*/ /*ReminderSet*/ if(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OverrideFlags & 0x0008){ exchange2ical->ReminderSet=(uint8_t *) &exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->ReminderDelta.rSet; /*Reminder Delta*/ if(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OverrideFlags & 0x0004){ exchange2ical->ReminderDelta=&exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->ReminderDelta.rDelta; } else { exchange2ical->ReminderDelta=NULL; } ical_component_VALARM(exchange2ical); } /*Location*/ if(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OverrideFlags & 0x0010){ exchange2ical->Location=(const char *) &exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->Location.locationMsg.msg; ical_property_LOCATION(exchange2ical); } /*Busy Status*/ if(exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->OverrideFlags & 0x0020){ exchange2ical->BusyStatus=&exchange2ical->AppointmentRecurrencePattern->ExceptionInfo->BusyStatus.bStatus; ical_property_X_MICROSOFT_CDO_BUSYSTATUS(exchange2ical); } } return 0; }
icalcomponent* create_new_component() { /* variable definitions */ icalcomponent* calendar; icalcomponent* event; struct icaltimetype atime = icaltime_from_timet( time(0),0); struct icalperiodtype rtime; icalproperty* property; /* Define a time type that will use as data later. */ rtime.start = icaltime_from_timet( time(0),0); rtime.end = icaltime_from_timet( time(0),0); rtime.end.hour++; /* Create calendar and add properties */ calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); /* Nearly every libical function call has the same general form. The first part of the name defines the 'class' for the function, and the first argument will be a pointer to a struct of that class. So, icalcomponent_ functions will all take icalcomponent* as their first argument. */ /* The next call creates a new proeprty and immediately adds it to the 'calendar' component. */ icalcomponent_add_property( calendar, icalproperty_new_version("2.0") ); /* Here is the short version of the memory rules: If the routine name has "new" in it: Caller owns the returned memory. If you pass in a string, the routine takes the memory. If the routine name has "add" in it: The routine takes control of the component, property, parameter or value memory. If the routine returns a string ( "get" and "as_ical_string" ) The library owns the returned memory. There are more rules, so refer to the documentation for more details. */ icalcomponent_add_property( calendar, icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN") ); /* Add an event */ event = icalcomponent_new(ICAL_VEVENT_COMPONENT); icalcomponent_add_property( event, icalproperty_new_dtstamp(atime) ); /* In the previous call, atime is a struct, and it is passed in by value. This is how all compound types of values are handled. */ icalcomponent_add_property( event, icalproperty_new_uid("guid-1.host1.com") ); /* add a property that has parameters */ property = icalproperty_new_organizer("mailto:[email protected]"); icalproperty_add_parameter( property, icalparameter_new_role(ICAL_ROLE_CHAIR) ); icalcomponent_add_property(event,property); /* In this style of component creation, you need to use an extra call to add parameters to properties, but the form of this operation is the same as adding a property to a component */ /* add another property that has parameters */ property = icalproperty_new_attendee("mailto:[email protected]"); icalproperty_add_parameter( property, icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT) ); icalproperty_add_parameter( property, icalparameter_new_rsvp(1) ); icalproperty_add_parameter( property, icalparameter_new_cutype(ICAL_CUTYPE_GROUP) ); icalcomponent_add_property(event,property); /* more properties */ icalcomponent_add_property( event, icalproperty_new_description("Project XYZ Review Meeting") ); icalcomponent_add_property( event, icalproperty_new_categories("MEETING") ); icalcomponent_add_property( event, icalproperty_new_class(ICAL_CLASS_PUBLIC) ); icalcomponent_add_property( event, icalproperty_new_created(atime) ); icalcomponent_add_property( event, icalproperty_new_summary("XYZ Project Review") ); property = icalproperty_new_dtstart(atime); icalproperty_add_parameter( property, icalparameter_new_tzid("US-Eastern") ); icalcomponent_add_property(event,property); property = icalproperty_new_dtend(atime); icalproperty_add_parameter( property, icalparameter_new_tzid("US-Eastern") ); icalcomponent_add_property(event,property); icalcomponent_add_property( event, icalproperty_new_location("1CP Conference Room 4350") ); icalcomponent_add_component(calendar,event); return calendar; }
// utility function to create a VCALENDAR from a single RideItem static icalcomponent *createEvent(RideItem *rideItem) { // calendar icalcomponent *root = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); // calendar version icalproperty *version = icalproperty_new_version("2.0"); icalcomponent_add_property(root, version); icalcomponent *event = icalcomponent_new(ICAL_VEVENT_COMPONENT); // // Unique ID // QString id = rideItem->ride()->id(); if (id == "") { id = QUuid::createUuid().toString() + "@" + "goldencheetah.org"; } icalproperty *uid = icalproperty_new_uid(id.toLatin1()); icalcomponent_add_property(event, uid); // // START DATE // struct icaltimetype atime; QDateTime utc = QDateTime::currentDateTime().toUTC(); atime.year = utc.date().year(); atime.month = utc.date().month(); atime.day = utc.date().day(); atime.hour = utc.time().hour(); atime.minute = utc.time().minute(); atime.second = utc.time().second(); // this is UTC is_utc is redundant but kept for completeness atime.is_utc = 1; atime.is_date = 0; // this is a date AND time atime.is_daylight = 0; // no daylight savings - its UTC atime.zone = icaltimezone_get_utc_timezone(); // set UTC timezone icalproperty *dtstart = icalproperty_new_dtstart(atime); icalcomponent_add_property(event, dtstart); // // Duration // // override values? QMap<QString, QString> lookup; lookup = rideItem->ride()->metricOverrides.value("workout_time"); int secs = lookup.value("value", "0.0").toDouble(); // from last - first timestamp? if (!rideItem->ride()->datePoints().isEmpty() && rideItem->ride()->datePoints().last() != NULL) { if (!secs) { secs = rideItem->ride()->datePoints().last()->secs; } } // ok, got seconds so now create in vcard struct icaldurationtype dur; dur.is_neg = 0; dur.days = dur.weeks = 0; dur.hours = secs / 3600; dur.minutes = secs % 3600 / 60; dur.seconds = secs % 60; icalcomponent_set_duration(event, dur); // set title & description QString title = rideItem->ride()->getTag("Title", ""); if (title == "") { title = rideItem->ride()->getTag("Sport", "") + " Workout"; } icalcomponent_set_summary(event, title.toLatin1()); icalcomponent_set_description(event, rideItem->ride()->getTag("Calendar Text", "").toLatin1()); // put the event into root icalcomponent_add_component(root, event); return root; }
/* Create a new component */ void create_new_component() { icalcomponent* calendar; icalcomponent* timezone; icalcomponent* tzc; icalcomponent* event; struct icaltimetype atime = icaltime_from_timet( 1023398689, 0); struct icaldatetimeperiodtype rtime; icalproperty* property; char *calendar_as_string; rtime.period.start = icaltime_from_timet( 1023398689,0); rtime.period.end = icaltime_from_timet( 1023409689,0); rtime.period.end.hour++; rtime.time = icaltime_null_time(); /* Create calendar and add properties */ calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); icalcomponent_add_property( calendar, icalproperty_new_version("2.0") ); icalcomponent_add_property( calendar, icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN") ); /* Create a timezone object and add it to the calendar */ timezone = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT); icalcomponent_add_property( timezone, icalproperty_new_tzid("America/New_York") ); /* Add a sub-component of the timezone */ tzc = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT); icalcomponent_add_property( tzc, icalproperty_new_dtstart(atime) ); icalcomponent_add_property( tzc, icalproperty_new_rdate(rtime) ); icalcomponent_add_property( tzc, icalproperty_new_tzoffsetfrom(-5*3600) ); icalcomponent_add_property( tzc, icalproperty_new_tzoffsetto(-4*3600) ); icalcomponent_add_property( tzc, icalproperty_new_tzname("EST") ); icalcomponent_add_component(timezone,tzc); icalcomponent_add_component(calendar,timezone); /* Add a second subcomponent */ tzc = icalcomponent_new(ICAL_XSTANDARD_COMPONENT); icalcomponent_add_property( tzc, icalproperty_new_dtstart(atime) ); icalcomponent_add_property( tzc, icalproperty_new_rdate(rtime) ); icalcomponent_add_property( tzc, icalproperty_new_tzoffsetfrom(-4*3600) ); icalcomponent_add_property( tzc, icalproperty_new_tzoffsetto(-5*3600) ); icalcomponent_add_property( tzc, icalproperty_new_tzname("EST") ); icalcomponent_add_component(timezone,tzc); /* Add an event */ event = icalcomponent_new(ICAL_VEVENT_COMPONENT); icalcomponent_add_property( event, icalproperty_new_dtstamp(atime) ); icalcomponent_add_property( event, icalproperty_new_uid("guid-1.host1.com") ); /* add a property that has parameters */ property = icalproperty_new_organizer("*****@*****.**"); icalproperty_add_parameter( property, icalparameter_new_role(ICAL_ROLE_CHAIR) ); icalcomponent_add_property(event,property); /* add another property that has parameters */ property = icalproperty_new_attendee("*****@*****.**"); icalproperty_add_parameter( property, icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT) ); icalproperty_add_parameter( property, icalparameter_new_rsvp(ICAL_RSVP_TRUE) ); icalproperty_add_parameter( property, icalparameter_new_cutype(ICAL_CUTYPE_GROUP) ); icalcomponent_add_property(event,property); /* more properties */ icalcomponent_add_property( event, icalproperty_new_description("Project XYZ Review Meeting") ); icalcomponent_add_property( event, icalproperty_new_categories("MEETING") ); icalcomponent_add_property( event, icalproperty_new_class(ICAL_CLASS_PRIVATE) ); icalcomponent_add_property( event, icalproperty_new_created(atime) ); icalcomponent_add_property( event, icalproperty_new_summary("XYZ Project Review") ); property = icalproperty_new_dtstart(atime); icalproperty_add_parameter( property, icalparameter_new_tzid("America/New_York") ); icalcomponent_add_property(event,property); property = icalproperty_new_dtend(atime); icalproperty_add_parameter( property, icalparameter_new_tzid("America/New_York") ); icalcomponent_add_property(event,property); icalcomponent_add_property( event, icalproperty_new_location("1CP Conference Room 4350") ); icalcomponent_add_component(calendar,event); calendar_as_string = icalcomponent_as_ical_string(calendar); is("build large, complex component", calendar_as_string, create_new_component_str); if (VERBOSE && calendar) printf("%s\n",icalcomponent_as_ical_string(calendar)); if (calendar) icalcomponent_free(calendar); }
/** Test icalcomponent_get_span() * */ void test_icalcomponent_get_span() { time_t tm1 = 973378800; /*Sat Nov 4 23:00:00 UTC 2000, Sat Nov 4 15:00:00 PST 2000 */ time_t tm2 = 973382400; /*Sat Nov 5 00:00:00 UTC 2000 Sat Nov 4 16:00:00 PST 2000 */ struct icaldurationtype dur; struct icaltime_span span; icalcomponent *c; icaltimezone *azone, *bzone; int tnum = 0; /** test 0 * Direct assigning time_t means they will be interpreted as UTC */ span.start = tm1; span.end = tm2; if (VERBOSE) print_span(tnum++,span); /** test 1 * We specify times in a timezone, the returned span is in UTC */ azone = icaltimezone_get_builtin_timezone("America/Los_Angeles"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/Los_Angeles"),0), icalproperty_vanew_dtend( icaltime_from_timet_with_zone(tm2,0,azone), icalparameter_new_tzid("America/Los_Angeles"),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/Los_Angeles", span.start, 973407600); icalcomponent_free(c); /** test 2 * We specify times as floating, the returned span is in UTC * with no conversion applied - so result should be as test 0 */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart(icaltime_from_timet(tm1,0),0), icalproperty_vanew_dtend(icaltime_from_timet(tm2,0),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("floating time", span.start, tm1); icalcomponent_free(c); /** test 3 * We specify times in a timezone, the returned span is in UTC */ azone = icaltimezone_get_builtin_timezone("America/New_York"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/New_York"),0), icalproperty_vanew_dtend( icaltime_from_timet_with_zone(tm2,0,azone), icalparameter_new_tzid("America/New_York"),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/New_York", span.start, 973396800); icalcomponent_free(c); /** test 4 * We specify times in two different timezones, the returned span * is in UTC */ azone = icaltimezone_get_builtin_timezone("America/New_York"); bzone = icaltimezone_get_builtin_timezone("America/Los_Angeles"); c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/New_York"),0), icalproperty_vanew_dtend( icaltime_from_timet_with_zone(tm2,0,bzone), icalparameter_new_tzid("America/Los_Angeles"),0), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/New_York", span.start, 973396800); icalcomponent_free(c); /** test 5 * We specify start time in a timezone and a duration, the returned span * is in UTC */ azone = icaltimezone_get_builtin_timezone("America/Los_Angeles"); memset(&dur,0,sizeof(dur)); dur.minutes = 30; c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_vanew_dtstart( icaltime_from_timet_with_zone(tm1,0,azone), icalparameter_new_tzid("America/Los_Angeles"),0), icalproperty_new_duration(dur), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("America/Los_Angeles w/ duration", span.end, 973409400); icalcomponent_free(c); icalerror_errors_are_fatal = 0; /** test 6 * We specify only start time, should return a null span with no error */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,0)), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("null span", span.start, 0); icalcomponent_free(c); /** test 7 * We specify start and end date */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,1)), icalproperty_new_dtend(icaltime_from_timet(tm1,1)), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("UTC", span.start, 973296000); icalcomponent_free(c); /** test 8 * We specify start and end date */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,1)), icalproperty_new_dtend(icaltime_from_timet(tm2,1)), 0 ); span = icalcomponent_get_span(c); int_is("UTC #2", span.start, 973296000); if (VERBOSE) print_span(tnum++,span); icalcomponent_free(c); /** test 9 * We specify start date */ c = icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstart(icaltime_from_timet(tm1,1)), 0 ); span = icalcomponent_get_span(c); if (VERBOSE) print_span(tnum++,span); int_is("start date only", span.end, 973382399); icalcomponent_free(c); /* assert(icalerrno == ICAL_MALFORMEDDATA_ERROR); */ icalerror_errors_are_fatal = 1; }
void create_new_component_with_va_args() { icalcomponent* calendar; struct icaltimetype atime = icaltime_from_timet( time(0),0); struct icaldatetimeperiodtype rtime; rtime.period.start = icaltime_from_timet( time(0),0); rtime.period.end = icaltime_from_timet( time(0),0); rtime.period.end.hour++; rtime.time = icaltime_null_time(); calendar = icalcomponent_vanew( ICAL_VCALENDAR_COMPONENT, icalproperty_new_version("2.0"), icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN"), icalcomponent_vanew( ICAL_VTIMEZONE_COMPONENT, icalproperty_new_tzid("America/New_York"), icalcomponent_vanew( ICAL_XDAYLIGHT_COMPONENT, icalproperty_new_dtstart(atime), icalproperty_new_rdate(rtime), icalproperty_new_tzoffsetfrom(-4.0), icalproperty_new_tzoffsetto(-5.0), icalproperty_new_tzname("EST"), NULL ), icalcomponent_vanew( ICAL_XSTANDARD_COMPONENT, icalproperty_new_dtstart(atime), icalproperty_new_rdate(rtime), icalproperty_new_tzoffsetfrom(-5.0), icalproperty_new_tzoffsetto(-4.0), icalproperty_new_tzname("EST"), NULL ), NULL ), icalcomponent_vanew( ICAL_VEVENT_COMPONENT, icalproperty_new_dtstamp(atime), icalproperty_new_uid("guid-1.host1.com"), icalproperty_vanew_organizer( "*****@*****.**", icalparameter_new_role(ICAL_ROLE_CHAIR), NULL ), icalproperty_vanew_attendee( "*****@*****.**", icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT), icalparameter_new_rsvp(ICAL_RSVP_TRUE), icalparameter_new_cutype(ICAL_CUTYPE_GROUP), NULL ), icalproperty_new_description("Project XYZ Review Meeting"), icalproperty_new_categories("MEETING"), icalproperty_new_class(ICAL_CLASS_PUBLIC), icalproperty_new_created(atime), icalproperty_new_summary("XYZ Project Review"), icalproperty_vanew_dtstart( atime, icalparameter_new_tzid("America/New_York"), NULL ), icalproperty_vanew_dtend( atime, icalparameter_new_tzid("America/New_York"), NULL ), icalproperty_new_location("1CP Conference Room 4350"), NULL ), NULL ); ok("creating a complex vcalendar", (calendar != NULL)); if (VERBOSE && calendar) printf("%s\n",icalcomponent_as_ical_string(calendar)); icalcomponent_free(calendar); }
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; }
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; }