void ical_property_DESCRIPTION(struct exchange2ical *exchange2ical)
{
	icalproperty	*prop;

	if (exchange2ical->method == ICAL_METHOD_REPLY) return;
	if (!exchange2ical->body) return;

	prop = icalproperty_new_description(exchange2ical->body);
	icalcomponent_add_property(exchange2ical->vevent, prop);
}
示例#2
0
void Todo::updateIcalFromData() {

    // clean event
    if (_ptrIcal) {
        assert(icalcomponent_isa(_ptrIcal) == ICAL_VTODO_COMPONENT);
        removeProperty(ICAL_SUMMARY_PROPERTY);
        removeProperty(ICAL_LOCATION_PROPERTY);
        removeProperty(ICAL_DESCRIPTION_PROPERTY);
    }
    else {
        _ptrIcal = icalcomponent_new(ICAL_VTODO_COMPONENT);
        assert(_ptrIcal);
    }

    // add new properties
    if (not _summary.empty())
        icalcomponent_add_property(_ptrIcal, icalproperty_new_summary(_summary.c_str()));

    if (not _location.empty())
        icalcomponent_add_property(_ptrIcal, icalproperty_new_location(_location.c_str()));

    if (not _description.empty())
        icalcomponent_add_property(_ptrIcal, icalproperty_new_description(_description.c_str()));
}
示例#3
0
icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size, 
						       void *d),
				void *data)
{
    struct sspm_part *parts;
    int i, last_level=0;
    icalcomponent *root=0, *parent=0, *comp=0, *last = 0;

    if ( (parts = (struct sspm_part *)
	  malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
	icalerror_set_errno(ICAL_NEWFAILED_ERROR);
	return 0;
    }

    memset(parts,0,sizeof(parts));

    sspm_parse_mime(parts, 
		    NUM_PARTS, /* Max parts */
		    icalmime_local_action_map, /* Actions */ 
		    get_string,
		    data, /* data for get_string*/
		    0 /* First header */);



    for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){

#define TMPSZ 1024
	char mimetype[TMPSZ];			       
	const char* major = sspm_major_type_string(parts[i].header.major);
	const char* minor = sspm_minor_type_string(parts[i].header.minor);

	if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){
	    assert(parts[i].header.minor_text !=0);
	    minor = parts[i].header.minor_text;
	}
	
	snprintf(mimetype,sizeof(mimetype),"%s/%s",major,minor);

	comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT);

	if(comp == 0){
	    /* HACK Handle Error */
	    assert(0);
	}

	if(parts[i].header.error!=SSPM_NO_ERROR){
	    const char *str="Unknown error";
	    char temp[256];
	    if(parts[i].header.error==SSPM_MALFORMED_HEADER_ERROR){
		str = "Malformed header, possibly due to input not in MIME format";
	    }

	    if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){
		str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line";
	    }

	    if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){
		str = "Got the wrong boundary for the opening of a MULTIPART part.";
	    }

	    if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){
		str = "Got a multipart header that did not specify a boundary";
	    }

	    if(parts[i].header.error==SSPM_NO_HEADER_ERROR){
		str = "Did not get a header for the part. Is there a blank\
line between the header and the previous boundary\?";

	    }

	    if(parts[i].header.error_text != 0){
		snprintf(temp,256,
			 "%s: %s",str,parts[i].header.error_text);
	    } else {
		strcpy(temp,str);
	    }

	    icalcomponent_add_property
		(comp,
		 icalproperty_vanew_xlicerror(
		     temp,
		     icalparameter_new_xlicerrortype(
			 ICAL_XLICERRORTYPE_MIMEPARSEERROR),
		     0));  
	}

	if(parts[i].header.major != SSPM_NO_MAJOR_TYPE &&
	   parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){

	    icalcomponent_add_property(comp,
		icalproperty_new_xlicmimecontenttype((char*)
				icalmemory_strdup(mimetype)));

	}

	if (parts[i].header.encoding != SSPM_NO_ENCODING){

	    icalcomponent_add_property(comp,
	       icalproperty_new_xlicmimeencoding(
		   sspm_encoding_string(parts[i].header.encoding)));
	}

	if (parts[i].header.filename != 0){
	    icalcomponent_add_property(comp,
	       icalproperty_new_xlicmimefilename(parts[i].header.filename));
	}

	if (parts[i].header.content_id != 0){
	    icalcomponent_add_property(comp,
	       icalproperty_new_xlicmimecid(parts[i].header.content_id));
	}

	if (parts[i].header.charset != 0){
	    icalcomponent_add_property(comp,
	       icalproperty_new_xlicmimecharset(parts[i].header.charset));
	}

	/* Add iCal components as children of the component */
	if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
	   parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE &&
	   parts[i].data != 0){

	    icalcomponent_add_component(comp,
					(icalcomponent*)parts[i].data);
	    parts[i].data = 0;

	} else 	if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
	   parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE &&
	   parts[i].data != 0){

	    /* Add other text components as "DESCRIPTION" properties */

	    icalcomponent_add_property(comp,
               icalproperty_new_description(
		   (char*)icalmemory_strdup((char*)parts[i].data)));

	    parts[i].data = 0;
	}
	

	if(root!= 0 && parts[i].level == 0){
	    /* We've already assigned the root, but there is another
               part at the root level. This is probably a parse
               error*/
	    icalcomponent_free(comp);
	    continue;
	}

	if(parts[i].level == last_level && last_level != 0){
	    icalerror_assert(parent!=0,"No parent for adding component");

	    icalcomponent_add_component(parent,comp);

	} else if (parts[i].level == last_level && last_level == 0 &&
	    root == 0) {

	    root = comp;
	    parent = comp;

	} else if (parts[i].level > last_level){	    

	    parent = last;
	    icalcomponent_add_component(parent,comp);

	    last_level = parts[i].level;

	} else if (parts[i].level < last_level){

	    if (parent) 
	        parent = icalcomponent_get_parent(parent);
	    icalcomponent_add_component(parent,comp);

	    last_level = parts[i].level;
	} else { 
	    assert(0);
	}

	last = comp;
	last_level = parts[i].level;
	assert(parts[i].data == 0);
    }

    sspm_free_parts(parts,NUM_PARTS);
    free(parts);

    return root;
}
示例#4
0
文件: vcal.c 项目: ihipop/I-GNOKII
/*
	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 */
}
示例#5
0
void add_class(icalcomponent* calendar, vector<string>& classes)
{
  cout << "What is the name of the class?" << endl;
  string class_name;
  cin >> class_name;
  classes.push_back(class_name);
  
  
  //List each property field one at a time
  string all_props[] = {"ATTACH", "ATTENDEE", "CATEGORIES", "CLASS", "COMMENT", "CONTACT", "CREATED", "DESCRIPTION", "DTEND", "DTSTAMP", "DTSTART", "DURATION", "EXDATE", "EXRULE", "GEO", "LAST-MOD", "LOCATION", "ORGANIZER", "PRIORITY", "RDATE", "RECURID", "RELATED", "RESOURCES", "RRULE", "RSTATUS", "SEQ", "STATUS", "SUMMARY", "TRANSP", "UID", "URL"};
  
  //FIXME Start/end dates rely on default start/end of semester if user okays default
  
  vector<string> values;
  
  for (int i = 0; i < 31; i++)
  {
    cout << all_props[i] << ": ";
    std::flush(cout);
    
    string value = "";
    getline(cin, value);
    
    if (cin.fail())
    {
      throw cin_fail_ex;
    }

    //FIXME Take user input and validate 
    values.push_back(value);
    cout << endl;
  }
   
  struct icaltimetype atime = icaltime_from_timet(time(0), 0);
  
  //Add the values to the event
  icalcomponent* class_event = icalcomponent_vanew(
		ICAL_VEVENT_COMPONENT,
		icalproperty_new_dtstamp(atime),
    icalproperty_new_contact(values[5].c_str()),
    icalproperty_new_comment(values[4].c_str()),
    icalproperty_vanew_attach(
      NULL, //FIXME icalattach *icalattach_new_from_url (const char *url);
      values[0].c_str(),  //FIXME?
      0
      ),
    //FIXME icalproperty_new_duration(values[11].c_str()), //needs right type
    //FIXME icalproperty_new_exdate(values[13].c_str()),  //needs struct icaltimetype v
    //FIXME icalproperty_new_geo(values[14].c_str()), //needs right type
    //FIXME icalproperty_new_lastmodified(values[15].c_str()),
    icalproperty_new_priority(atoi(values[18].c_str())),
    //FIXME icalproperty_vanew_recurid(),
    //FIXME icalproperty_vanew_related(),
    //FIXME icalproperty_vanew_resources(),
    //FIXME icalproperty_vanew_sequence(),
    //FIXME icalproperty_new_rrule(values[23].c_str()),
    //FIXME icalproperty_new_status(values[26].c_str()),
    //FIXME icalproperty_new_rstatus()  may not exist...
    /*FIXME icalproperty_vanew_rdate(
      values[15].c_str(),
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),*/
    /*FIXME icalproperty_vanew_exdate(  //FIXME exceptions to recurrences
      values[12].c_str(), //FIXME struct icaltimetype v
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),*/
    icalproperty_new_transp(ICAL_TRANSP_NONE), //FIXME values[28]... This is a six-way selector between ICAL_TRANSP_X, ICAL_TRANSP_OPAQUE, ICAL_TRANSP_OPAQUENOCONFLICT, ICAL_TRANSP_TRANSPARENT,  ICAL_TRANSP_TRANSPARENTNOCONFLICT, ICAL_TRANSP_NONE... Relates to free/busy conflicts
		icalproperty_new_uid(values[29].c_str()),
    icalproperty_new_url(values[30].c_str()),
		icalproperty_vanew_organizer(
		    values[17].c_str(),
		    icalparameter_new_role(ICAL_ROLE_CHAIR),
		    0
		    ),
		icalproperty_vanew_attendee(
      values[1].c_str(),
      icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT),  //FIXME overwrites user settings. Either ICAL_ROLE_REQPARTICIPANT, ICAL_ROLE_OPTPARTICIPANT, ICAL_ROLE_NONPARTICIPANT
      //FIXME icalparameter_new_rsvp(1),  //FIXME overwrites user settings
      icalparameter_new_cutype(ICAL_CUTYPE_GROUP),  //FIXME overwrites user settings. Type of calendar user specified by property?
      0
      ),
		icalproperty_new_description(values[7].c_str()),

		icalproperty_new_categories(values[2].c_str()),
		icalproperty_new_class(ICAL_CLASS_PUBLIC),  //FIXME overwrites user settings
		icalproperty_new_created(atime),  //FIXME overwrites user settings
		icalproperty_new_summary(values[27].c_str()),
		icalproperty_vanew_dtstart(
      atime,                  //FIXME overwrites user settings
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),
		icalproperty_vanew_dtend(
      atime,                //FIXME overwrites user settings
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),
		icalproperty_new_location(values[16].c_str()),
		0
		);  
  
  //FIXME Handle alarm threads (to be implemented later)
 
  //Add the class component to calendar
  icalcomponent_add_component(calendar, class_event);
  
  append_action_to_closed_log("Add Class", true);
}
示例#6
0
void add_event(icalcomponent* calendar)
{
  string class_name;

  //Ask if the event is for a class
  bool is_class_event = yes_no_prompt("Is this event for a class? (y/n)");
  
  //FIXME Following not implemented in this sprint
  if (is_class_event)
  {
    //FIXME If event for class, make sure the semester is not over
    //FIXME If the semester is over, notify the user
    
    //If event for class, prompt for class id
    cout << "What is the name of this class?" << endl;
    cin >> class_name;
  }
    
    
  //List each property field one at a time
  cout << "Enter information for each of the following properties." << endl;
  string all_props[] = {"ATTACH", "ATTENDEE", "CATEGORIES", "CLASS", "COMMENT", "CONTACT", "CREATED", "DESCRIPTION", "DTEND", "DTSTAMP", "DTSTART", "DURATION", "EXDATE", "EXRULE", "GEO", "LAST-MOD", "LOCATION", "ORGANIZER", "PRIORITY", "RDATE", "RECURID", "RELATED", "RESOURCES", "RRULE", "RSTATUS", "SEQ", "STATUS", "SUMMARY", "TRANSP", "UID", "URL"};
  
  vector<string> values;
  
  for (int i = 0; i < 31; i++)
  {
    cout << all_props[i] << ": ";
    flush(cout);
    
    string value = "";
    getline(cin, value); //FIXME Check for failbit
    
    //FIXME Take user input and validate 
    values.push_back(value);
    cout << endl;
  }
  
  //If event for class, add property X-CLASS
  string value = "";
  if (is_class_event)
  {
    cout << "X-CLASS: ";
    flush(cout);
      
    getline(cin, value); //FIXME Check for failbit
    //FIXME Take user input and validate
    values.push_back(value);
      
    cout << endl;
  }
  
  struct icaltimetype atime = icaltime_from_timet(time(0), 0);
  
  //Add the values to the event
  icalcomponent* event = icalcomponent_vanew(
		ICAL_VEVENT_COMPONENT,
		icalproperty_new_dtstamp(atime),
    icalproperty_new_contact(values[5].c_str()),
    icalproperty_new_comment(values[4].c_str()),
    icalproperty_vanew_attach(
      NULL, //FIXME is this the file encoding?
      values[0].c_str(),
      0
      ),
    //FIXME icalproperty_new_duration(values[11].c_str()),
    //FIXME icalproperty_new_exdate(values[13].c_str()),
    //FIXME icalproperty_new_geo(values[14].c_str()),
    //FIXME icalproperty_new_lastmod(values[15].c_str()),
    icalproperty_new_priority(atoi(values[18].c_str())),
    //FIXME icalproperty_vanew_recurid(),
    //FIXME icalproperty_vanew_related(),
    //FIXME icalproperty_vanew_resources(),
    //FIXME icalproperty_vanew_sequence(),
    //FIXME icalproperty_new_rrule(values[23].c_str()),
    //FIXME icalproperty_new_status(values[26].c_str()),
    //FIXME icalproperty_new_rstatus()  may not exist...
    /*FIXME icalproperty_vanew_rdate(
      values[15].c_str(),
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),*/
    /*FIXME icalproperty_vanew_exdate(
      values[12].c_str(),
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),*/
    //FIXME icalproperty_new_transp(values[28].c_str()),
		icalproperty_new_uid(values[29].c_str()),
    icalproperty_new_url(values[30].c_str()),
		icalproperty_vanew_organizer(
		    values[17].c_str(),
		    icalparameter_new_role(ICAL_ROLE_CHAIR),  //FIXME overwrites user settings
		    0
		    ),
		icalproperty_vanew_attendee(
      values[1].c_str(),
      icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT),  //FIXME overwrites user settings
      //FIXME icalparameter_new_rsvp(1),  //FIXME overwrites user settings
      icalparameter_new_cutype(ICAL_CUTYPE_GROUP),  //FIXME overwrites user settings
      0
      ),
		icalproperty_new_description(values[7].c_str()),

		icalproperty_new_categories(values[2].c_str()),
		icalproperty_new_class(ICAL_CLASS_PUBLIC),  //FIXME overwrites user settings
		icalproperty_new_created(atime),  //FIXME overwrites user settings
		icalproperty_new_summary(values[27].c_str()),
		icalproperty_vanew_dtstart(
      atime,                  //FIXME overwrites user settings
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),
		icalproperty_vanew_dtend(
      atime,                //FIXME overwrites user settings
      icalparameter_new_tzid("US-Central"), //FIXME should get timezone from user
      0
      ),
		icalproperty_new_location(values[16].c_str()),
		0
		);  
  
  if (is_class_event)
  {
    icalproperty* p;
    icalproperty_set_x(p, value.c_str());
    icalcomponent_add_property(event, p);
  }
  
  //Add component event to calendar
  icalcomponent_add_component(calendar,event);
  
  //FIXME Handle alarm threads (to be implemented later)
  
  append_action_to_closed_log("Add Event", true);
}
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;
}
icalcomponent* create_new_component_with_va_args()
{

    /* This is a similar set up to the last routine */
    icalcomponent* calendar;
    struct icaltimetype atime = icaltime_from_timet( time(0),0);
    struct icalperiodtype rtime;
    
    rtime.start = icaltime_from_timet( time(0),0);
    rtime.end = icaltime_from_timet( time(0),0);
    rtime.end.hour++;

    /* Some of these routines are the same as those in the previous
       routine, but we've also added several 'vanew' routines. These
       'vanew' routines take a list of properties, parameters or
       values and add each of them to the parent property or
       component. */

    calendar = 
	icalcomponent_vanew(
	    ICAL_VCALENDAR_COMPONENT,
	    icalproperty_new_version("2.0"),
	    icalproperty_new_prodid("-//RDU Software//NONSGML HandCal//EN"),
	    icalcomponent_vanew(
		ICAL_VEVENT_COMPONENT,
		icalproperty_new_dtstamp(atime),
		icalproperty_new_uid("guid-1.host1.com"),
		icalproperty_vanew_organizer(
		    "mailto:[email protected]",
		    icalparameter_new_role(ICAL_ROLE_CHAIR),
		    0
		    ),
		icalproperty_vanew_attendee(
		    "mailto:[email protected]",
		    icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT),
		    icalparameter_new_rsvp(1),
		    icalparameter_new_cutype(ICAL_CUTYPE_GROUP),
		    0
		    ),
		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("US-Eastern"),
		    0
		    ),
		icalproperty_vanew_dtend(
		    atime,
		    icalparameter_new_tzid("US-Eastern"),
		    0
		    ),
		icalproperty_new_location("1CP Conference Room 4350"),
		0
		),
	    0
	    );

   
    /* Note that properties with no parameters can use the regular
       'new' constructor, while those with parameters use the 'vanew'
       constructor. And, be sure that the last argument in the 'vanew'
       call is a zero. Without, your program will probably crash. */

    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);

}
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);

}