/* * Construct the proper JSON object for an iCalendar value. */ static json_t *icalvalue_as_json_object(const icalvalue *value) { const char *str = NULL; json_t *obj; switch (icalvalue_isa(value)) { case ICAL_BOOLEAN_VALUE: return json_boolean(icalvalue_get_integer(value)); case ICAL_DATE_VALUE: str = icaltime_as_iso_string(icalvalue_get_date(value)); break; case ICAL_DATETIME_VALUE: str = icaltime_as_iso_string(icalvalue_get_datetime(value)); break; case ICAL_DATETIMEPERIOD_VALUE: { struct icaldatetimeperiodtype dtp = icalvalue_get_datetimeperiod(value); if (!icaltime_is_null_time(dtp.time)) str = icaltime_as_iso_string(dtp.time); else str = icalperiodtype_as_json_string(dtp.period); break; } case ICAL_FLOAT_VALUE: return json_real(icalvalue_get_float(value)); case ICAL_GEO_VALUE: { struct icalgeotype geo = icalvalue_get_geo(value); obj = json_array(); json_array_append_new(obj, json_real(geo.lat)); json_array_append_new(obj, json_real(geo.lon)); return obj; } case ICAL_INTEGER_VALUE: return json_integer(icalvalue_get_integer(value)); case ICAL_PERIOD_VALUE: str = icalperiodtype_as_json_string(icalvalue_get_period(value)); break; case ICAL_RECUR_VALUE: { struct icalrecurrencetype recur = icalvalue_get_recur(value); obj = json_object(); icalrecurrencetype_add_as_xxx(&recur, obj, &icalrecur_add_int_to_json_object, &icalrecur_add_string_to_json_object); return obj; } case ICAL_REQUESTSTATUS_VALUE: return icalreqstattype_as_json_array(icalvalue_get_requeststatus(value)); case ICAL_TRIGGER_VALUE: { struct icaltriggertype trig = icalvalue_get_trigger(value); if (!icaltime_is_null_time(trig.time)) str = icaltime_as_iso_string(trig.time); else str = icaldurationtype_as_ical_string(trig.duration); break; } case ICAL_UTCOFFSET_VALUE: str = icalvalue_utcoffset_as_iso_string(value); break; default: str = icalvalue_as_ical_string(value); break; } return (str ? json_string(str) : NULL); }
/* * Add the proper XML element for an iCalendar value. */ static void icalproperty_add_value_as_xml_element(xmlNodePtr xprop, icalproperty *prop) { const char *type, *str = NULL; xmlNodePtr xtype; const icalvalue *value; char buf[40]; /* Add type */ type = lcase(icalmemory_tmp_copy( icalproperty_value_kind_as_string(prop))); xtype = xmlNewChild(xprop, NULL, BAD_CAST type, NULL); /* Add value */ value = icalproperty_get_value(prop); switch (icalvalue_isa(value)) { case ICAL_DATE_VALUE: str = icaltime_as_iso_string(icalvalue_get_date(value)); break; case ICAL_DATETIME_VALUE: str = icaltime_as_iso_string(icalvalue_get_datetime(value)); break; case ICAL_DATETIMEPERIOD_VALUE: { struct icaldatetimeperiodtype dtp = icalvalue_get_datetimeperiod(value); if (!icaltime_is_null_time(dtp.time)) { str = icaltime_as_iso_string(dtp.time); break; } else { icalperiodtype_add_as_xml_element(xtype, dtp.period); return; } } case ICAL_GEO_VALUE: { struct icalgeotype geo = icalvalue_get_geo(value); snprintf(buf, sizeof(buf), "%f", geo.lat); xmlNewTextChild(xtype, NULL, BAD_CAST "latitude", BAD_CAST buf); snprintf(buf, sizeof(buf), "%f", geo.lon); xmlNewTextChild(xtype, NULL, BAD_CAST "longitude", BAD_CAST buf); return; } case ICAL_PERIOD_VALUE: icalperiodtype_add_as_xml_element(xtype, icalvalue_get_period(value)); return; case ICAL_RECUR_VALUE: { struct icalrecurrencetype recur = icalvalue_get_recur(value); icalrecurrencetype_add_as_xxx(&recur, xtype, NULL, &icalrecur_add_string_as_xml_element); return; } case ICAL_REQUESTSTATUS_VALUE: { struct icalreqstattype stat = icalvalue_get_requeststatus(value); if (!stat.desc) stat.desc = icalenum_reqstat_desc(stat.code); snprintf(buf, sizeof(buf), "%u.%u", icalenum_reqstat_major(stat.code), icalenum_reqstat_minor(stat.code)); xmlNewTextChild(xtype, NULL, BAD_CAST "code", BAD_CAST buf); xmlNewTextChild(xtype, NULL, BAD_CAST "description", BAD_CAST stat.desc); if (stat.debug) xmlNewTextChild(xtype, NULL, BAD_CAST "data", BAD_CAST stat.debug); return; } case ICAL_TRIGGER_VALUE: { struct icaltriggertype trig = icalvalue_get_trigger(value); if (!icaltime_is_null_time(trig.time)) str = icaltime_as_iso_string(trig.time); else str = icaldurationtype_as_ical_string(trig.duration); break; } case ICAL_UTCOFFSET_VALUE: str = icalvalue_utcoffset_as_iso_string(value); break; default: str = icalvalue_as_ical_string(value); switch (icalproperty_isa(prop)) { case ICAL_CATEGORIES_PROPERTY: case ICAL_RESOURCES_PROPERTY: case ICAL_POLLPROPERTIES_PROPERTY: if (strchr(str, ',')) { /* Handle multi-valued properties */ tok_t tok; tok_init(&tok, str, ",", TOK_TRIMLEFT|TOK_TRIMRIGHT|TOK_EMPTY); str = tok_next(&tok); xmlAddChild(xtype, xmlNewText(BAD_CAST str)); while ((str = tok_next(&tok))) { if (*str) { xtype = xmlNewChild(xprop, NULL, BAD_CAST type, NULL); xmlAddChild(xtype, xmlNewText(BAD_CAST str)); } } tok_fini(&tok); return; } default: break; } break; } if (str) xmlAddChild(xtype, xmlNewText(BAD_CAST str)); }
static int gn_ical2calnote_real(icalcomponent *comp, gn_calnote *calnote, int id) { int retval = GN_ERR_FAILED; struct icaltimetype dtstart = {0}, dtend = {0}; icalcomponent *compresult = NULL; if (id < 1) id = 1; /* iterate through the component */ iterate_cal(comp, 0, &id, &compresult, ICAL_VEVENT_COMPONENT); if (!compresult) { dprintf("No component found.\n"); retval = GN_ERR_EMPTYLOCATION; } else { const char *str; icalcomponent *alarm = {0}; icalproperty *rrule; struct icalrecurrencetype recur; retval = GN_ERR_NONE; calnote->phone_number[0] = 0; /* type */ str = comp_get_category(compresult); calnote->type = str2calnote_type(str); switch (calnote->type) { case GN_CALNOTE_CALL: /* description goes into text */ /* TODO: UTF8 --> ascii */ snprintf(calnote->phone_number, GN_CALNOTE_NUMBER_MAX_LENGTH-1, "%s", icalcomponent_get_summary(compresult)); str = icalcomponent_get_description(compresult); break; default: /* summary goes into text */ /* TODO: UTF8 --> ascii */ str = icalcomponent_get_summary(compresult); break; } if (str) { snprintf(calnote->text, GN_CALNOTE_MAX_LENGTH - 1, "%s", str); } /* start time */ dtstart = icalcomponent_get_dtstart(compresult); if (!icaltime_is_null_time(dtstart)) { calnote->time.year = dtstart.year; calnote->time.month = dtstart.month; calnote->time.day = dtstart.day; if (!icaltime_is_date(dtstart)) { calnote->time.hour = dtstart.hour; calnote->time.minute = dtstart.minute; calnote->time.second = dtstart.second; /* TODO: what about time zones? */ } } /* end time */ memset(&calnote->end_time, 0, sizeof(calnote->end_time)); dtend = icalcomponent_get_dtend(compresult); if (!icaltime_is_null_time(dtend)) { calnote->end_time.year = dtend.year; calnote->end_time.month = dtend.month; calnote->end_time.day = dtend.day; if (!icaltime_is_date(dtend)) { calnote->end_time.hour = dtend.hour; calnote->end_time.minute = dtend.minute; calnote->end_time.second = dtend.second; /* TODO: what about time zones? */ } } /* alarm */ alarm = icalcomponent_get_first_component(compresult, ICAL_VALARM_COMPONENT); if (alarm) { icalproperty *trigger = NULL; trigger = icalcomponent_get_first_property(alarm, ICAL_TRIGGER_PROPERTY); if (trigger) { struct icaltriggertype trigger_value; struct icaltimetype alarm_start; icalproperty *property; trigger_value = icalvalue_get_trigger(icalproperty_get_value(trigger)); if (icaltriggertype_is_null_trigger(trigger_value) || icaltriggertype_is_bad_trigger(trigger_value)) { calnote->alarm.enabled = 0; } else { if (icaltime_is_null_time(trigger_value.time)) { memcpy(&alarm_start, &dtstart, sizeof(struct icaltimetype)); } else { memcpy(&alarm_start, &trigger_value.time, sizeof(struct icaltimetype)); } if (!(icaldurationtype_is_bad_duration(trigger_value.duration) || icaldurationtype_is_null_duration(trigger_value.duration))) { alarm_start = icaltime_add(alarm_start, trigger_value.duration); } calnote->alarm.enabled = 1; calnote->alarm.timestamp.year = alarm_start.year; calnote->alarm.timestamp.month = alarm_start.month; calnote->alarm.timestamp.day = alarm_start.day; calnote->alarm.timestamp.hour = alarm_start.hour; calnote->alarm.timestamp.minute = alarm_start.minute; calnote->alarm.timestamp.second = alarm_start.second; /* TODO: time zone? */ property = icalcomponent_get_first_property(alarm, ICAL_ACTION_PROPERTY); calnote->alarm.tone = icalproperty_get_action(property) == ICAL_ACTION_AUDIO ? 1 : 0; } } } /* recurrence */ rrule = icalcomponent_get_first_property(compresult, ICAL_RRULE_PROPERTY); if (rrule) { recur = icalproperty_get_rrule(rrule); calnote->occurrences = recur.count; switch (recur.freq) { case ICAL_SECONDLY_RECURRENCE: dprintf("Not supported recurrence type. Approximating recurrence\n"); calnote->recurrence = recur.interval / 3600; if (!calnote->recurrence) calnote->recurrence = 1; break; case ICAL_MINUTELY_RECURRENCE: dprintf("Not supported recurrence type. Approximating recurrence\n"); calnote->recurrence = recur.interval / 60; if (!calnote->recurrence) calnote->recurrence = 1; break; case ICAL_HOURLY_RECURRENCE: calnote->recurrence = recur.interval; break; case ICAL_DAILY_RECURRENCE: calnote->recurrence = recur.interval * 24; break; case ICAL_WEEKLY_RECURRENCE: calnote->recurrence = recur.interval * 24 * 7; break; case ICAL_MONTHLY_RECURRENCE: calnote->recurrence = GN_CALNOTE_MONTHLY; break; case ICAL_YEARLY_RECURRENCE: calnote->recurrence = GN_CALNOTE_YEARLY; break; case ICAL_NO_RECURRENCE: calnote->recurrence = GN_CALNOTE_NEVER; break; default: dprintf("Not supported recurrence type. Assuming never\n"); calnote->recurrence = GN_CALNOTE_NEVER; break; } } str = icalcomponent_get_location(compresult); if (!str) str = ""; snprintf(calnote->mlocation, sizeof(calnote->mlocation), "%s", str); } if (compresult) { #ifdef DEBUG char *temp; temp = icalcomponent_as_ical_string(compresult); dprintf("Component found\n%s\n", temp); free(temp); #endif icalcomponent_free(compresult); } return retval; }