void ical_property_DTEND(struct exchange2ical *exchange2ical)
{
	icalproperty		*prop;
	icalparameter		*tzid;
	struct icaltimetype	icaltime;

	/* Sanity check */
	if (!exchange2ical->apptEndWhole) return;

	/* If this is an all-day appointment */
	if (exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) {
		icaltime = get_icaldate_from_FILETIME(exchange2ical->apptEndWhole);
		prop = icalproperty_new_dtend(icaltime);
		icalcomponent_add_property(exchange2ical->vevent, prop);
	} else {
		if (exchange2ical->TimeZoneDesc) {
			icaltime = get_icaltime_from_FILETIME(exchange2ical->apptEndWhole);
			prop = icalproperty_new_dtend(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->apptEndWhole);
			prop = icalproperty_new_dtend(icaltime);
			icalcomponent_add_property(exchange2ical->vevent, prop);
		}
		
	}
}
Beispiel #2
0
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;
}
Beispiel #3
0
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());
}
Beispiel #4
0
/*
	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 */
}
Beispiel #5
0
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;
}
/* 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;
}