/* * Add an XML element for an iCalendar Period. */ static void icalperiodtype_add_as_xml_element(xmlNodePtr xtype, struct icalperiodtype p) { const char *start; const char *end; start = icaltime_as_iso_string(p.start); xmlNewTextChild(xtype, NULL, BAD_CAST "start", BAD_CAST start); if (!icaltime_is_null_time(p.end)) { end = icaltime_as_iso_string(p.end); xmlNewTextChild(xtype, NULL, BAD_CAST "end", BAD_CAST end); } else { end = icaldurationtype_as_ical_string(p.duration); xmlNewTextChild(xtype, NULL, BAD_CAST "duration", BAD_CAST end); } }
/* * Construct a JSON string for an iCalendar Period. */ static char *icalperiodtype_as_json_string(struct icalperiodtype p) { static char str[42]; const char *start; const char *end; start = icaltime_as_iso_string(p.start); snprintf(str, sizeof(str), "%s/", start); if (!icaltime_is_null_time(p.end)) end = icaltime_as_iso_string(p.end); else end = icaldurationtype_as_ical_string(p.duration); strlcat(str, end, sizeof(str)); return str; }
/* * Add iCalendar recur-rule-parts to a structured element. */ void icalrecurrencetype_add_as_xxx(struct icalrecurrencetype *recur, void *obj, void (*add_int)(void *, const char *, int), void (*add_str)(void *, const char *, const char *)) { char *rrule, *rpart; tok_t rparts; /* generate an iCal RRULE string */ rrule = icalrecurrencetype_as_string_r(recur); /* split string into rparts & values */ tok_initm(&rparts, rrule, "=;", TOK_TRIMLEFT|TOK_TRIMRIGHT); while ((rpart = tok_next(&rparts))) { if (!strcmp(rpart, "UNTIL")) { /* need to translate date format to ISO */ struct icaltimetype until = icaltime_from_string(tok_next(&rparts)); add_str(obj, "until", icaltime_as_iso_string(until)); } else { /* assume the rpart has multiple values - split them */ tok_t vlist; char *val, *p; tok_init(&vlist, tok_next(&rparts), ",", TOK_TRIMLEFT|TOK_TRIMRIGHT); while ((val = tok_next(&vlist))) { if (add_int) { /* try converting value to integer */ int n = strtol(val, &p, 10); if (n && !*p) { add_int(obj, lcase(rpart), n); continue; } } add_str(obj, lcase(rpart), val); } tok_fini(&vlist); } } tok_fini(&rparts); free(rrule); }
/* * 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)); }
/* * 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); }