19#include "icalerror_p.h"
26#include "icaltime_p.h"
28#include "icaltypes_p.h"
34struct icalcomponent_impl {
38 icalpvl_list properties;
39 icalpvl_elem property_iterator;
40 icalpvl_list components;
41 icalpvl_elem component_iterator;
42 struct icalcomponent_impl *parent;
52static void icalcomponent_add_children(icalcomponent *impl, va_list args);
55static bool icalcomponent_merge_vtimezone(icalcomponent *comp,
56 icalcomponent *vtimezone, icalstrarray *tzids_to_rename);
57static void icalcomponent_handle_conflicting_vtimezones(icalcomponent *comp,
58 icalcomponent *vtimezone,
59 icalproperty *tzid_prop,
61 icalstrarray *tzids_to_rename);
62static size_t icalcomponent_get_tzid_prefix_len(
const char *tzid);
63static void icalcomponent_rename_tzids(icalcomponent *comp, icalarray *rename_table);
64static void icalcomponent_rename_tzids_callback(icalparameter *param,
void *data);
65static int icalcomponent_compare_vtimezones(icalcomponent *vtimezone1, icalcomponent *vtimezone2);
66static int icalcomponent_compare_timezone_fn(
const void *elem1,
const void *elem2);
68void icalcomponent_add_children(icalcomponent *impl, va_list args)
72 while ((vp = va_arg(args,
void *)) != 0) {
97 memset(comp, 0,
sizeof(icalcomponent));
99 comp->id = ICAL_STRUCTURE_TYPE_COMPONENT;
101 comp->properties = icalpvl_newlist();
102 comp->components = icalpvl_newlist();
103 comp->timezones_sorted = 1;
110 return icalcomponent_new_impl(kind);
119 icalcomponent *impl = icalcomponent_new_impl(kind);
125 va_start(args, kind);
126 icalcomponent_add_children(impl, args);
139 icalcomponent *clone;
140 const icalcomponent *c;
141 const icalproperty *p;
144 icalerror_check_arg_rz((old != 0),
"component");
146 clone = icalcomponent_new_impl(old->kind);
156 for (itr = icalpvl_head(old->properties); itr != 0; itr = icalpvl_next(itr)) {
157 p = (icalproperty *)icalpvl_data(itr);
161 for (itr = icalpvl_head(old->components); itr != 0; itr = icalpvl_next(itr)) {
162 c = (icalcomponent *)icalpvl_data(itr);
195 icalerror_check_arg_rv((c != 0),
"component");
197 if (c->parent != 0) {
201 if (c->properties != 0) {
203 while ((prop = icalpvl_pop(c->properties)) != 0) {
207 icalpvl_free(c->properties);
210 while ((comp = icalpvl_data(icalpvl_head(c->components))) != 0) {
215 icalpvl_free(c->components);
219 icaltimezone_array_free(c->timezones);
224 c->property_iterator = 0;
226 c->component_iterator = 0;
228 c->id = ICAL_STRUCTURE_TYPE_COMPONENT_EMPTY;
248 size_t buf_size = 1024;
253 const char newline[] =
"\r\n";
255 const icalcomponent *c;
259 const char *kind_string;
261 icalerror_check_arg_rz((component != 0),
"component");
262 icalerror_check_arg_rz((kind !=
ICAL_NO_COMPONENT),
"component kind is ICAL_NO_COMPONENT");
265 kind_string = component->x_name;
270 icalerror_check_arg_rz((kind_string != 0),
"Unknown kind of component");
283 for (itr = icalpvl_head(component->properties); itr != 0; itr = icalpvl_next(itr)) {
286 p = (icalproperty *)icalpvl_data(itr);
288 icalerror_assert((p != 0),
"Got a null property");
295 for (itr = icalpvl_head(component->components); itr != 0; itr = icalpvl_next(itr)) {
298 c = (icalcomponent *)icalpvl_data(itr);
301 if (tmp_buf != NULL) {
317 if ((component->id == ICAL_STRUCTURE_TYPE_COMPONENT) && component->kind !=
ICAL_NO_COMPONENT) {
328 return component->kind;
333 const icalcomponent *impl = component;
335 icalerror_check_arg_rz((component != 0),
"component");
337 return (impl->id == ICAL_STRUCTURE_TYPE_COMPONENT);
342 icalerror_check_arg_rv((name != 0),
"name");
343 icalerror_check_arg_rv((comp != 0),
"comp");
348 if (comp->x_name == 0) {
355 icalerror_check_arg_rz((comp != 0),
"comp");
362 icalerror_check_arg_rv((name != 0),
"name");
363 icalerror_check_arg_rv((comp != 0),
"comp");
369 if (comp->x_name == 0) {
376 icalerror_check_arg_rz((comp != 0),
"comp");
393 const char *component_name = 0;
394 size_t buf_size = 256;
398 icalerror_check_arg_rz((comp != 0),
"comp");
405 component_name = comp->x_name;
410 if (component_name == 0) {
426 icalerror_check_arg_rv((component != 0),
"component");
427 icalerror_check_arg_rv((property != 0),
"property");
430 "The property has already been added to a component. "
431 "Remove the property with icalcomponent_remove_property "
432 "before calling icalcomponent_add_property");
436 icalpvl_push(component->properties, property);
441 icalpvl_elem itr, next_itr;
443 icalerror_check_arg_rv((component != 0),
"component");
444 icalerror_check_arg_rv((property != 0),
"property");
450 for (itr = icalpvl_head(component->properties); itr != 0; itr = next_itr) {
451 next_itr = icalpvl_next(itr);
453 if (icalpvl_data(itr) == (
void *)property) {
454 if (component->property_iterator == itr) {
455 component->property_iterator = icalpvl_next(itr);
458 (void)icalpvl_remove(component->properties, itr);
466 icalpvl_elem itr, next_itr;
468 icalerror_check_arg_rv((component != 0),
"component");
470 for (itr = icalpvl_head(component->properties); itr != 0; itr = next_itr) {
471 next_itr = icalpvl_next(itr);
473 icalproperty *
property = icalpvl_data(itr);
475 if (component->property_iterator == itr) {
476 component->property_iterator = icalpvl_next(itr);
479 (void)icalpvl_remove(component->properties, itr);
491 icalerror_check_arg_rz((component != 0),
"component");
493 for (itr = icalpvl_head(component->properties); itr != 0; itr = icalpvl_next(itr)) {
494 if (kind ==
icalproperty_isa((icalproperty *)icalpvl_data(itr)) || kind == ICAL_ANY_PROPERTY) {
504 icalerror_check_arg_rz((component != 0),
"component");
506 if (component->property_iterator == 0) {
510 return (icalproperty *)icalpvl_data(component->property_iterator);
515 icalerror_check_arg_rz((c != 0),
"component");
517 for (c->property_iterator = icalpvl_head(c->properties);
518 c->property_iterator != 0; c->property_iterator = icalpvl_next(c->property_iterator)) {
519 icalproperty *p = (icalproperty *)icalpvl_data(c->property_iterator);
530 icalerror_check_arg_rz((c != 0),
"component");
532 if (c->property_iterator == 0) {
536 for (c->property_iterator = icalpvl_next(c->property_iterator);
537 c->property_iterator != 0; c->property_iterator = icalpvl_next(c->property_iterator)) {
538 icalproperty *p = (icalproperty *)icalpvl_data(c->property_iterator);
550 icalerror_check_arg_rv((parent != 0),
"parent");
551 icalerror_check_arg_rv((child != 0),
"child");
553 if (child->parent != 0) {
557 child->parent = parent;
561 icalpvl_push(parent->components, child);
564 icalpvl_unshift(parent->components, child);
569 if (!parent->timezones) {
570 parent->timezones = icaltimezone_array_new();
573 if (parent->timezones) {
574 icaltimezone_array_append_from_vtimezone(parent->timezones, child);
578 parent->timezones_sorted = 0;
584 icalpvl_elem itr, next_itr;
586 icalerror_check_arg_rv((parent != 0),
"parent");
587 icalerror_check_arg_rv((child != 0),
"child");
592 size_t i, num_elements;
594 num_elements = parent->timezones ? parent->timezones->num_elements : 0;
595 for (i = 0; i < num_elements; i++) {
605 for (itr = icalpvl_head(parent->components); itr != 0; itr = next_itr) {
606 next_itr = icalpvl_next(itr);
608 if (icalpvl_data(itr) == (
void *)child) {
609 if (parent->component_iterator == itr) {
613 parent->component_iterator = icalpvl_next(parent->component_iterator);
615 (void)icalpvl_remove(parent->components, itr);
627 icalerror_check_arg_rz((component != 0),
"component");
629 for (itr = icalpvl_head(component->components); itr != 0; itr = icalpvl_next(itr)) {
641 icalerror_check_arg_rz((component != 0),
"component");
643 if (component->component_iterator == 0) {
647 return (icalcomponent *)icalpvl_data(component->component_iterator);
652 icalerror_check_arg_rz((c != 0),
"component");
654 for (c->component_iterator = icalpvl_head(c->components);
655 c->component_iterator != 0; c->component_iterator = icalpvl_next(c->component_iterator)) {
656 icalcomponent *p = (icalcomponent *)icalpvl_data(c->component_iterator);
668 icalerror_check_arg_rz((c != 0),
"component");
670 if (c->component_iterator == 0) {
674 for (c->component_iterator = icalpvl_next(c->component_iterator);
675 c->component_iterator != 0; c->component_iterator = icalpvl_next(c->component_iterator)) {
676 icalcomponent *p = (icalcomponent *)icalpvl_data(c->component_iterator);
689 icalcomponent *cin = (icalcomponent *)c;
711 const icalcomponent *inner;
781 icalproperty *exdate, *exrule;
782 icalpvl_elem property_iterator;
789 property_iterator = comp->property_iterator;
800 comp->property_iterator = property_iterator;
823 comp->property_iterator = property_iterator;
838 comp->property_iterator = property_iterator;
850static bool icalcomponent_is_busy(icalcomponent *comp)
852 const icalproperty *transp;
853 enum icalproperty_status status;
865 switch (icalvalue_get_transp(transp_val)) {
866 case ICAL_TRANSP_OPAQUE:
867 case ICAL_TRANSP_OPAQUENOCONFLICT:
868 case ICAL_TRANSP_NONE:
871 case ICAL_TRANSP_TRANSPARENT:
872 case ICAL_TRANSP_TRANSPARENTNOCONFLICT:
881 if (ret && status != ICAL_STATUS_NONE) {
883 case ICAL_STATUS_CANCELLED:
884 case ICAL_STATUS_TENTATIVE:
896 struct icaltimetype ret = t;
906 return icaltime_with_time(t, 0, 0, 0);
911 icaltime_span ret = {0};
928 icaltime_span ret = {0};
957static int icaldatetimeperiod_start_compare(
const void *a,
const void *b)
969 void (*callback)(icalcomponent *comp,
970 const struct icaltime_span *span,
975 icaltime_span recurspan, basespan, limit_span,
976 rrule_span, rdate_span;
977 icaltime_t limit_start, limit_end, last_start;
982 size_t rdate_idx = 0;
984 icalproperty *rrule, *rdate;
985 icalpvl_elem property_iterator;
987 if (comp == NULL || callback == NULL) {
1010 basespan = icaltime_span_new(dtstart, dtend, 1);
1012 basespan.is_busy = icalcomponent_is_busy(comp);
1018 start = icaltime_at_midnight(start);
1027 end = icaltime_at_midnight(end);
1033#if (SIZEOF_ICALTIME_T > 4)
1034 limit_end = (icaltime_t)LONG_MAX;
1036 limit_end = (icaltime_t)INT_MAX;
1039 limit_span.start = limit_start;
1040 limit_span.end = limit_end;
1042 rrule_span.start = rdate_span.start =
1043 last_start = end_timet + 1;
1048 if ((rrule == NULL) &&
1050 last_start = basespan.start;
1052 if (icaltime_span_overlaps(&basespan, &limit_span)) {
1053 (*callback)(comp, &basespan, callback_data);
1060 icalrecur_iterator *rrule_itr = NULL;
1061 if (rrule != NULL) {
1067 if (recur->
count == 0) {
1080 rrule_span = icaltime_span_from_time(rrule_time, dtduration);
1091 rdate_period = icalproperty_get_rdate(rdate);
1094 if (rdates->num_elements > 0) {
1097 rdate_span = icaltime_span_from_datetimeperiod(rdate_period, dtduration);
1101 if (rdate_idx >= rdates->num_elements ||
1103 rrule_span.start < rdate_span.start)) {
1105 recurspan = rrule_span;
1106 recur_time = rrule_time;
1110 rrule_span = icaltime_span_from_time(rrule_time, dtduration);
1114 recurspan = rdate_span;
1115 recur_time = rdate_period.
time;
1121 if (rdate_idx < rdates->num_elements) {
1123 rdate_span = icaltime_span_from_datetimeperiod(rdate_period, dtduration);
1127 if (recurspan.start > end_timet) {
1131 if (last_start == recurspan.start) {
1134 last_start = recurspan.start;
1137 property_iterator = comp->property_iterator;
1140 &dtstart, &recur_time)) {
1142 if (icaltime_span_overlaps(&recurspan, &limit_span)) {
1143 (*callback)(comp, &recurspan, callback_data);
1146 comp->property_iterator = property_iterator;
1151 if (rrule_itr != NULL) {
1158 icalerror_check_arg_rz(comp != 0,
"comp");
1167 icalerror_check_arg_rz((component != 0),
"component");
1169 for (itr = icalpvl_head(component->properties); itr != 0; itr = icalpvl_next(itr)) {
1170 const icalproperty *p = (icalproperty *)icalpvl_data(itr);
1176 for (itr = icalpvl_head(component->components); itr != 0; itr = icalpvl_next(itr)) {
1177 icalcomponent *c = (icalcomponent *)icalpvl_data(itr);
1186 icalpvl_elem itr, next_itr;
1188 icalerror_check_arg_rv((component != 0),
"component");
1190 for (itr = icalpvl_head(component->properties); itr != 0; itr = next_itr) {
1191 icalproperty *p = (icalproperty *)icalpvl_data(itr);
1192 next_itr = icalpvl_next(itr);
1200 for (itr = icalpvl_head(component->components); itr != 0; itr = icalpvl_next(itr)) {
1201 icalcomponent *c = (icalcomponent *)icalpvl_data(itr);
1209 icalproperty *p, *next_p;
1217 icalparameter *param =
1223 switch (icalparameter_get_xlicerrortype(param)) {
1224 case ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR: {
1228 case ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR: {
1232 case ICAL_XLICERRORTYPE_PROPERTYPARSEERROR: {
1236 case ICAL_XLICERRORTYPE_VALUEPARSEERROR: {
1240 case ICAL_XLICERRORTYPE_COMPONENTPARSEERROR: {
1250 rst.
debug = icalproperty_get_xlicerror(p);
1266icalcomponent *icalcomponent_get_parent(
const icalcomponent *component)
1268 return component->parent;
1271void icalcomponent_set_parent(icalcomponent *component, icalcomponent *parent)
1273 component->parent = parent;
1279static const icalpropiter icalpropiter_null = {ICAL_NO_PROPERTY, 0};
1281struct icalcomponent_kind_map {
1286static const struct icalcomponent_kind_map component_map[] = {
1342 if (component_map[i].kind == kind) {
1355 if (component_map[i].kind == kind) {
1356 return component_map[i].name;
1376 if (strncasecmp(
string, component_map[i].name, strlen(component_map[i].name)) == 0) {
1377 return component_map[i].kind;
1381 if (strncasecmp(
string,
"X-", 2) == 0) {
1405 icalerror_check_arg_re(component != 0,
"component", icalcompiter_null);
1407 for (i = icalpvl_head(component->components); i != 0; i = icalpvl_next(i)) {
1408 const icalcomponent *c = (icalcomponent *)icalpvl_data(i);
1417 return icalcompiter_null;
1427 icalerror_check_arg_re(component != 0,
"component", icalcompiter_null);
1429 for (i = icalpvl_tail(component->components); i != 0; i = icalpvl_prior(i)) {
1430 const icalcomponent *c = (icalcomponent *)icalpvl_data(i);
1433 itr.iter = icalpvl_next(i);
1439 return icalcompiter_null;
1444 icalerror_check_arg_rz((i != 0),
"i");
1450 for (i->iter = icalpvl_next(i->iter); i->iter != 0; i->iter = icalpvl_next(i->iter)) {
1451 const icalcomponent *c = (icalcomponent *)icalpvl_data(i->iter);
1463 icalerror_check_arg_rz((i != 0),
"i");
1469 for (i->iter = icalpvl_prior(i->iter); i->iter != 0; i->iter = icalpvl_prior(i->iter)) {
1470 const icalcomponent *c = (icalcomponent *)icalpvl_data(i->iter);
1482 icalerror_check_arg_rz((i != 0),
"i");
1488 return icalpvl_data(i->iter);
1493 icalerror_check_arg_re(component != 0,
"component", icalpropiter_null);
1497 for (i = icalpvl_head(component->properties); i != 0; i = icalpvl_next(i)) {
1498 const icalproperty *p = (icalproperty *)icalpvl_data(i);
1501 icalpropiter itr = {kind, i};
1506 return icalpropiter_null;
1515 return !((i->kind == ICAL_NO_PROPERTY) && (i->iter == 0));
1520 icalerror_check_arg_rz((i != 0),
"i");
1526 for (i->iter = icalpvl_next(i->iter); i->iter != 0; i->iter = icalpvl_next(i->iter)) {
1527 const icalproperty *p = (icalproperty *)icalpvl_data(i->iter);
1539 icalerror_check_arg_rz((i != 0),
"i");
1545 return icalpvl_data(i->iter);
1562 prop = icalproperty_new_method(method);
1566 icalproperty_set_method(prop, method);
1574 return ICAL_METHOD_NONE;
1577 return icalproperty_get_method(prop);
1581#define ICALSETUPSET(p_kind) \
1582 icalcomponent *inner; \
1583 icalproperty *prop; \
1584 icalerror_check_arg_rv(comp != 0, "comp"); \
1585 inner = icalcomponent_get_inner(comp); \
1587 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); \
1590 prop = icalcomponent_get_first_property(inner, p_kind);
1597 ICALSETUPSET(ICAL_DTSTART_PROPERTY);
1600 prop = icalproperty_new_dtstart(v);
1606 icalproperty_set_dtstart(prop, v);
1630 icalproperty *end_prop, *dur_prop;
1646 if (end_prop != 0 && dur_prop == 0) {
1648 }
else if (end_prop == 0 && dur_prop != 0) {
1654 duration = icalproperty_get_duration(dur_prop);
1660 }
else if (end_prop == 0 && dur_prop == 0) {
1686 ICALSETUPSET(ICAL_DTEND_PROPERTY);
1694 prop = icalproperty_new_dtend(v);
1700 icalproperty_set_dtend(prop, v);
1709 ICALSETUPSET(ICAL_DURATION_PROPERTY);
1717 prop = icalproperty_new_duration(v);
1720 icalproperty_set_duration(prop, v);
1728 icalproperty *end_prop, *dur_prop;
1747 if (dur_prop != 0 && end_prop == 0) {
1748 ret = icalproperty_get_duration(dur_prop);
1750 }
else if (end_prop != 0 && dur_prop == 0) {
1756 }
else if (end_prop == 0 && dur_prop == 0) {
1772 ICALSETUPSET(ICAL_DTSTAMP_PROPERTY);
1775 prop = icalproperty_new_dtstamp(v);
1779 icalproperty_set_dtstamp(prop, v);
1791 return icalproperty_get_dtstamp(prop);
1796 ICALSETUPSET(ICAL_SUMMARY_PROPERTY)
1799 prop = icalproperty_new_summary(v);
1803 icalproperty_set_summary(prop, v);
1808 icalcomponent *inner;
1811 icalerror_check_arg_rz(comp != 0,
"comp");
1826 return icalproperty_get_summary(prop);
1831 ICALSETUPSET(ICAL_COMMENT_PROPERTY);
1834 prop = icalproperty_new_comment(v);
1838 icalproperty_set_comment(prop, v);
1843 icalcomponent *inner;
1846 icalerror_check_arg_rz(comp != 0,
"comp");
1861 return icalproperty_get_comment(prop);
1866 ICALSETUPSET(ICAL_UID_PROPERTY);
1869 prop = icalproperty_new_uid(v);
1873 icalproperty_set_uid(prop, v);
1878 icalcomponent *inner;
1881 icalerror_check_arg_rz(comp != 0,
"comp");
1896 return icalproperty_get_uid(prop);
1903 ICALSETUPSET(ICAL_RECURRENCEID_PROPERTY);
1906 prop = icalproperty_new_recurrenceid(v);
1912 icalproperty_set_recurrenceid(prop, v);
1921 icalcomponent *inner;
1947 ICALSETUPSET(ICAL_DESCRIPTION_PROPERTY);
1950 prop = icalproperty_new_description(v);
1954 icalproperty_set_description(prop, v);
1959 icalcomponent *inner;
1962 icalerror_check_arg_rz(comp != 0,
"comp");
1977 return icalproperty_get_description(prop);
1982 ICALSETUPSET(ICAL_LOCATION_PROPERTY)
1985 prop = icalproperty_new_location(v);
1989 icalproperty_set_location(prop, v);
1994 icalcomponent *inner;
1997 icalerror_check_arg_rz(comp != 0,
"comp");
2012 return icalproperty_get_location(prop);
2017 ICALSETUPSET(ICAL_SEQUENCE_PROPERTY);
2020 prop = icalproperty_new_sequence(v);
2024 icalproperty_set_sequence(prop, v);
2029 icalcomponent *inner;
2032 icalerror_check_arg_rz(comp != 0,
"comp");
2047 return icalproperty_get_sequence(prop);
2052 ICALSETUPSET(ICAL_STATUS_PROPERTY);
2055 prop = icalproperty_new_status(v);
2059 icalproperty_set_status(prop, v);
2064 icalcomponent *inner;
2067 icalerror_check_arg_rz(comp != 0,
"comp");
2073 return ICAL_STATUS_NONE;
2079 return ICAL_STATUS_NONE;
2082 return icalproperty_get_status(prop);
2201 icalcomponent *subcomp, *next_subcomp;
2202 icalstrarray *tzids_to_rename;
2212 if (!tzids_to_rename) {
2221 if (!icalcomponent_merge_vtimezone(comp, subcomp, tzids_to_rename)) {
2224 subcomp = next_subcomp;
2228 if (tzids_to_rename->num_elements != 0) {
2229 icalcomponent_rename_tzids(comp_to_merge, tzids_to_rename);
2232 tzids_to_rename = 0;
2242 subcomp = next_subcomp;
2250static bool icalcomponent_merge_vtimezone(icalcomponent *comp,
2251 icalcomponent *vtimezone, icalstrarray *tzids_to_rename)
2253 icalproperty *tzid_prop;
2264 tzid = icalproperty_get_tzid(tzid_prop);
2274 if (!existing_vtimezone) {
2282 if (tzid[0] ==
'/') {
2296 const int match = icalcomponent_compare_vtimezones(comp, vtimezone);
2299 icalcomponent_handle_conflicting_vtimezones(comp, vtimezone, tzid_prop,
2300 tzid_copy, tzids_to_rename);
2310static void icalcomponent_handle_conflicting_vtimezones(icalcomponent *comp,
2311 icalcomponent *vtimezone,
2312 icalproperty *tzid_prop,
2314 icalstrarray *tzids_to_rename)
2317 size_t i, num_elements, tzid_len;
2318 char *new_tzid, suffix_buf[32];
2323 tzid_len = icalcomponent_get_tzid_prefix_len(tzid);
2332 num_elements = comp->timezones ? comp->timezones->num_elements : 0;
2333 for (i = 0; i < num_elements; i++) {
2335 const char *existing_tzid;
2336 size_t existing_tzid_len;
2342 existing_tzid_len = icalcomponent_get_tzid_prefix_len(existing_tzid);
2345 if (tzid_len == existing_tzid_len && (strncmp(tzid, existing_tzid, tzid_len) != 0)) {
2356 if (!existing_tzid_copy) {
2371 int suffix = atoi(existing_tzid + existing_tzid_len);
2372 if (max_suffix < suffix) {
2373 max_suffix = suffix;
2387 snprintf(suffix_buf,
sizeof(suffix_buf),
"%i", max_suffix + 1);
2388 const size_t len_new_tzid = tzid_len + strlen(suffix_buf) + 1;
2395 strncpy(new_tzid, tzid, tzid_len);
2396 new_tzid[tzid_len] =
'\0';
2397 strncat(new_tzid, suffix_buf, len_new_tzid);
2398 new_tzid[len_new_tzid - 1] =
'\0';
2406static size_t icalcomponent_get_tzid_prefix_len(
const char *tzid)
2413 while (len > 0 && *p >=
'0' && *p <=
'9') {
2426static void icalcomponent_rename_tzids(icalcomponent *comp, icalarray *rename_table)
2431static void icalcomponent_rename_tzids_callback(icalparameter *param,
void *data)
2433 icalarray *rename_table = data;
2437 tzid = icalparameter_get_tzid(param);
2444 for (i = 0; i < rename_table->num_elements - 1; i += 2) {
2453 void (*callback)(icalparameter *param,
void *data),
2454 void *callback_data)
2457 icalcomponent *subcomp;
2466 if (kind == ICAL_DTSTART_PROPERTY ||
2467 kind == ICAL_DTEND_PROPERTY ||
2468 kind == ICAL_DUE_PROPERTY ||
2469 kind == ICAL_EXDATE_PROPERTY ||
2470 kind == ICAL_RDATE_PROPERTY) {
2473 (*callback)(param, callback_data);
2491 size_t lower, upper;
2493 if (!comp->timezones) {
2498 if (!comp->timezones_sorted) {
2499 icalarray_sort(comp->timezones, icalcomponent_compare_timezone_fn);
2500 comp->timezones_sorted = 1;
2505 upper = comp->timezones->num_elements;
2507 while (lower < upper) {
2508 size_t middle = (lower + upper) >> 1;
2511 if (zone_tzid != NULL) {
2512 int cmp = strcmp(tzid, zone_tzid);
2515 }
else if (cmp < 0) {
2529static int icalcomponent_compare_timezone_fn(
const void *elem1,
const void *elem2)
2532 const char *zone1_tzid = 0, *zone2_tzid = 0;
2540 if (zone1_is_valid && !zone2_is_valid) {
2543 if (!zone1_is_valid) {
2544 if (zone2_is_valid) {
2551 return strcmp(zone1_tzid, zone2_tzid);
2558static int icalcomponent_compare_vtimezones(icalcomponent *vtimezone1, icalcomponent *vtimezone2)
2560 icalproperty *prop1, *prop2;
2561 const char *tzid1, *tzid2;
2562 char *tzid2_copy, *string1, *string2;
2571 tzid1 = icalproperty_get_tzid(prop1);
2582 tzid2 = icalproperty_get_tzid(prop2);
2595 icalproperty_set_tzid(prop2, tzid1);
2611 cmp = strcmp(string1, string2);
2617 icalproperty_set_tzid(prop2, tzid2_copy);
2620 return (cmp == 0) ? 1 : 0;
2625 ICALSETUPSET(ICAL_RELCALID_PROPERTY);
2628 prop = icalproperty_new_relcalid(v);
2632 icalproperty_set_relcalid(prop, v);
2637 icalcomponent *inner;
2640 icalerror_check_arg_rz(comp != 0,
"comp");
2654 return icalproperty_get_relcalid(prop);
2665 if (due_prop != 0) {
2667 }
else if (dur_prop != 0) {
2688 if (due_prop == 0 && dur_prop == 0) {
2689 due_prop = icalproperty_new_due(v);
2691 }
else if (due_prop != 0) {
2692 icalproperty_set_due(due_prop, v);
2694 }
else if (dur_prop != 0) {
2701 icalproperty_set_duration(dur_prop, dur);
2709static int strcmpsafe(
const char *a,
const char *b)
2711 return strcmp((a == NULL ?
"" : a),
2712 (b == NULL ?
"" : b));
2715static int prop_compare(
void *a,
void *b)
2717 const icalproperty *p1 = (icalproperty *)a;
2718 const icalproperty *p2 = (icalproperty *)b;
2721 int r = (int)(k1 - k2);
2724 if (k1 == ICAL_X_PROPERTY) {
2738static inline int compare_nullptr(
const void *a,
const void *b)
2748static int comp_compare(
void *a,
void *b)
2750 icalcomponent *c1 = (icalcomponent *)a;
2751 icalcomponent *c2 = (icalcomponent *)b;
2754 int r = (int)(k1 - k2);
2758 (c1->x_name && c2->x_name)) {
2759 r = strcmp(c1->x_name, c2->x_name);
2774 const icalproperty *p1, *p2;
2779 ICAL_TRIGGER_PROPERTY);
2781 ICAL_TRIGGER_PROPERTY);
2787 ICAL_ACTION_PROPERTY);
2789 ICAL_ACTION_PROPERTY);
2794 r = compare_nullptr(p1, p2);
2798 r = compare_nullptr(p1, p2);
2805 ICAL_TZID_PROPERTY);
2807 ICAL_TZID_PROPERTY);
2812 r = compare_nullptr(p1, p2);
2819 ICAL_DTSTART_PROPERTY);
2821 ICAL_DTSTART_PROPERTY);
2827 r = compare_nullptr(p1, p2);
2833 ICAL_VOTER_PROPERTY);
2835 ICAL_VOTER_PROPERTY);
2841 r = compare_nullptr(p1, p2);
2847 ICAL_POLLITEMID_PROPERTY);
2849 ICAL_POLLITEMID_PROPERTY);
2855 r = compare_nullptr(p1, p2);
2881 icalpvl_list sorted_props;
2882 icalpvl_list sorted_comps;
2885 icalerror_check_arg(comp != 0,
"comp");
2890 sorted_props = icalpvl_newlist();
2891 sorted_comps = icalpvl_newlist();
2898 while ((++cnt < max_properties) && ((prop = icalpvl_pop(comp->properties)) != 0)) {
2899 int nparams, remove = 0;
2908 case ICAL_CALSCALE_PROPERTY:
2909 if (strcmp(
"GREGORIAN", icalproperty_get_calscale(prop)) == 0) {
2914 case ICAL_CLASS_PROPERTY:
2915 if (icalproperty_get_class(prop) == ICAL_CLASS_PUBLIC) {
2920 case ICAL_PRIORITY_PROPERTY:
2921 if (icalproperty_get_priority(prop) == 0) {
2926 case ICAL_TRANSP_PROPERTY:
2927 if (icalproperty_get_transp(prop) == ICAL_TRANSP_OPAQUE) {
2932 case ICAL_REPEAT_PROPERTY:
2933 if (icalproperty_get_repeat(prop) == 0) {
2938 case ICAL_SEQUENCE_PROPERTY:
2939 if (icalproperty_get_sequence(prop) == 0) {
2953 icalpvl_insert_ordered(sorted_props, prop_compare, prop);
2958 if (cnt == max_properties) {
2959 while ((prop = icalpvl_pop(comp->properties)) != 0) {
2965 icalpvl_free(comp->properties);
2966 comp->properties = sorted_props;
2969 while ((sub = icalpvl_pop(comp->components)) != 0) {
2971 icalpvl_insert_ordered(sorted_comps, comp_compare, sub);
2974 icalpvl_free(comp->components);
2975 comp->components = sorted_comps;
void * icalarray_element_at(icalarray *array, size_t position)
Access an array element.
void icalarray_free(icalarray *array)
void icalarray_sort(icalarray *array, int(*compare)(const void *, const void *))
Sorts the elements of an icalarray using the given comparison function.
void icalarray_append(icalarray *array, const void *element)
Appends an element to an array.
icalarray * icalarray_new(size_t element_size, size_t increment_size)
void icalarray_remove_element_at(icalarray *array, size_t position)
Removes a given element from an array.
void icalcomponent_remove_property_by_kind(icalcomponent *component, icalproperty_kind kind)
void icalcomponent_convert_errors(icalcomponent *component)
icalcomponent * icalcomponent_new_xstandard(void)
void icalcomponent_set_relcalid(icalcomponent *comp, const char *v)
bool icalcomponent_is_valid(const icalcomponent *component)
icalproperty * icalpropiter_deref(icalpropiter *i)
icalcomponent * icalcomponent_new_vagenda(void)
void icalcomponent_set_uid(icalcomponent *comp, const char *v)
icalcomponent_kind icalcomponent_string_to_kind(const char *string)
void icalcomponent_set_x_name(icalcomponent *comp, const char *name)
struct icaltimetype icalcomponent_get_dtend(icalcomponent *comp)
struct icaltimetype icalcomponent_get_dtstart(icalcomponent *comp)
icalcomponent * icalcomponent_new_vlocation(void)
icalproperty * icalcomponent_get_first_property(icalcomponent *c, icalproperty_kind kind)
bool icalcomponent_check_restrictions(icalcomponent *comp)
icalcomponent * icalcomponent_new_vpoll(void)
int icalcomponent_count_properties(icalcomponent *component, icalproperty_kind kind)
icalcomponent * icalcomponent_new_vavailability(void)
icalcomponent * icalcomponent_new_xpatch(void)
icalproperty_method icalcomponent_get_method(icalcomponent *comp)
bool icalcompiter_is_valid(const icalcompiter *i)
icalcomponent * icalcomponent_new_vreply(void)
void icalcomponent_set_recurrenceid(icalcomponent *comp, struct icaltimetype v)
icalcomponent * icalcomponent_new_xvote(void)
struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent *comp)
icalcomponent * icalcompiter_next(icalcompiter *i)
void icalcomponent_set_location(icalcomponent *comp, const char *v)
const char * icalcomponent_get_description(icalcomponent *comp)
void icalcomponent_set_iana_name(icalcomponent *comp, const char *name)
icalcomponent * icalcomponent_get_next_component(icalcomponent *c, icalcomponent_kind kind)
icalcomponent * icalcomponent_get_first_component(icalcomponent *c, icalcomponent_kind kind)
void icalcomponent_set_dtstart(icalcomponent *comp, struct icaltimetype v)
void icalcomponent_set_dtstamp(icalcomponent *comp, struct icaltimetype v)
void icalcomponent_strip_errors(icalcomponent *component)
icalcomponent * icalcomponent_new_vcalendar(void)
void icalcomponent_normalize(icalcomponent *comp)
icalpropiter icalcomponent_begin_property(icalcomponent *component, icalproperty_kind kind)
icalcomponent * icalcomponent_get_current_component(icalcomponent *component)
void icalcomponent_remove_property(icalcomponent *component, icalproperty *property)
char * icalcomponent_as_ical_string(const icalcomponent *component)
const char * icalcomponent_kind_to_string(icalcomponent_kind kind)
enum icalproperty_status icalcomponent_get_status(icalcomponent *comp)
icalcomponent * icalcomponent_new_vjournal(void)
void icalcomponent_remove_component(icalcomponent *parent, icalcomponent *child)
icalcomponent * icalcomponent_new_vpatch(void)
icalcomponent * icalcomponent_new_vfreebusy(void)
icalproperty * icalpropiter_next(icalpropiter *i)
icalcomponent * icalcompiter_deref(icalcompiter *i)
icalcomponent * icalcomponent_vanew(icalcomponent_kind kind,...)
void icalcomponent_set_method(icalcomponent *comp, icalproperty_method method)
icalcomponent * icalcomponent_new(icalcomponent_kind kind)
void icalcomponent_set_summary(icalcomponent *comp, const char *v)
void icalcomponent_set_sequence(icalcomponent *comp, int v)
icalcomponent * icalcomponent_get_inner(icalcomponent *comp)
const char * icalcomponent_get_comment(icalcomponent *comp)
const char * icalcomponent_get_summary(icalcomponent *comp)
icaltime_span icalcomponent_get_span(icalcomponent *comp)
const char * icalcomponent_get_relcalid(icalcomponent *comp)
icalcomponent * icalcomponent_get_first_real_component(const icalcomponent *c)
icalcomponent * icalcomponent_new_vtimezone(void)
struct icaltimetype icalcomponent_get_due(icalcomponent *comp)
void icalcomponent_merge_component(icalcomponent *comp, icalcomponent *comp_to_merge)
bool icalpropiter_is_valid(const icalpropiter *i)
icalcomponent * icalcomponent_new_vresource(void)
bool icalproperty_recurrence_is_excluded(icalcomponent *comp, struct icaltimetype *dtstart, struct icaltimetype *recurtime)
Decides if a recurrence is acceptable.
const char * icalcomponent_get_x_name(const icalcomponent *comp)
int icalcomponent_count_errors(icalcomponent *component)
struct icaldurationtype icalcomponent_get_duration(icalcomponent *comp)
icalcomponent * icalcomponent_clone(const icalcomponent *old)
icalcomponent * icalcomponent_new_iana(const char *iana_name)
icalcomponent * icalcomponent_new_xavailable(void)
icalcomponent * icalcomponent_new_participant(void)
const char * icalcomponent_get_iana_name(const icalcomponent *comp)
icalproperty * icalcomponent_get_current_property(icalcomponent *component)
icaltimezone * icalcomponent_get_timezone(icalcomponent *comp, const char *tzid)
void icalcomponent_set_dtend(icalcomponent *comp, struct icaltimetype v)
const char * icalcomponent_get_uid(icalcomponent *comp)
int icalcomponent_get_sequence(icalcomponent *comp)
icalcompiter icalcomponent_end_component(icalcomponent *component, icalcomponent_kind kind)
const char * icalcomponent_get_component_name(const icalcomponent *comp)
icalcomponent * icalcomponent_new_xdaylight(void)
icalcomponent * icalcomponent_new_valarm(void)
icalcomponent * icalcomponent_new_x(const char *x_name)
void icalcomponent_add_property(icalcomponent *component, icalproperty *property)
void icalcomponent_set_duration(icalcomponent *comp, struct icaldurationtype v)
icalcompiter icalcomponent_begin_component(icalcomponent *component, icalcomponent_kind kind)
char * icalcomponent_as_ical_string_r(const icalcomponent *component)
icalcomponent_kind icalcomponent_isa(const icalcomponent *component)
icalcomponent * icalcompiter_prior(icalcompiter *i)
icalcomponent * icalcomponent_new_vtodo(void)
bool icalcomponent_kind_is_valid(const icalcomponent_kind kind)
char * icalcomponent_get_component_name_r(const icalcomponent *comp)
void icalcomponent_set_status(icalcomponent *comp, enum icalproperty_status v)
void icalcomponent_foreach_tzid(icalcomponent *comp, void(*callback)(icalparameter *param, void *data), void *callback_data)
const char * icalcomponent_get_location(icalcomponent *comp)
void icalcomponent_free(icalcomponent *c)
icalcomponent * icalcomponent_new_vevent(void)
void icalcomponent_set_due(icalcomponent *comp, struct icaltimetype v)
void icalcomponent_foreach_recurrence(icalcomponent *comp, struct icaltimetype start, struct icaltimetype end, void(*callback)(icalcomponent *comp, const struct icaltime_span *span, void *data), void *callback_data)
void icalcomponent_add_component(icalcomponent *parent, icalcomponent *child)
icalproperty * icalcomponent_get_next_property(icalcomponent *c, icalproperty_kind kind)
void icalcomponent_set_description(icalcomponent *comp, const char *v)
icalcomponent * icalcomponent_new_from_string(const char *str)
int icalcomponent_count_components(icalcomponent *component, icalcomponent_kind kind)
void icalcomponent_set_comment(icalcomponent *comp, const char *v)
icalcomponent * icalcomponent_new_vquery(void)
bool icalcomponent_isa_component(const void *component)
icalcomponent * icalcomponent_new_vvoter(void)
struct icaltimetype icalcomponent_get_dtstamp(icalcomponent *comp)
Defines the data structure for iCalendar components.
icalcomponent * icalproperty_get_parent(const icalproperty *property)
struct icaltimetype icalproperty_get_datetime_with_component(icalproperty *prop, icalcomponent *comp)
void icalproperty_set_parent(icalproperty *property, icalcomponent *component)
struct icaldurationtype icalduration_from_times(struct icaltimetype t1, struct icaltimetype t2)
Creates a duration from two icaltimetype endpoints.
struct icaltimetype icalduration_extend(struct icaltimetype t, struct icaldurationtype d)
Extends a time duration.
bool icaldurationtype_is_null_duration(struct icaldurationtype d)
Checks if a duration is a null duration.
struct icaldurationtype icaldurationtype_null_duration(void)
Creates a duration with zero length.
@ ICAL_XDAYLIGHT_COMPONENT
@ ICAL_VLOCATION_COMPONENT
@ ICAL_XSTANDARD_COMPONENT
@ ICAL_VFREEBUSY_COMPONENT
@ ICAL_PARTICIPANT_COMPONENT
@ ICAL_VCALENDAR_COMPONENT
@ ICAL_VAVAILABILITY_COMPONENT
@ ICAL_VSCHEDULE_COMPONENT
@ ICAL_VTIMEZONE_COMPONENT
@ ICAL_VJOURNAL_COMPONENT
@ ICAL_VCOMMAND_COMPONENT
@ ICAL_XLICMIMEPART_COMPONENT
@ ICAL_XAVAILABLE_COMPONENT
@ ICAL_XLICINVALID_COMPONENT
@ ICAL_VRESOURCE_COMPONENT
@ ICAL_3_2_INVPARAM_STATUS
@ ICAL_3_0_INVPROPNAME_STATUS
@ ICAL_3_1_INVPROPVAL_STATUS
@ ICAL_3_4_INVCOMP_STATUS
@ ICAL_3_3_INVPARAMVAL_STATUS
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Error handling for libical.
@ ICAL_MALFORMEDDATA_ERROR
size_t icallimit_get(icallimits_kind kind)
Defines the interface for getting/setting internal library limits.
void icalmemory_free_buffer(void *buf)
Releases a buffer.
char * icalmemory_strdup(const char *s)
Creates a duplicate of a string.
void icalmemory_append_string(char **buf, char **pos, size_t *buf_size, const char *string)
Appends a string to a buffer.
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Common memory management routines.
icalcomponent * icalparser_parse_string(const char *str)
Parses a string and returns the parsed icalcomponent.
icalvalue * icalproperty_get_value(const icalproperty *prop)
bool icalproperty_isa_property(void *property)
void icalproperty_free(icalproperty *p)
char * icalproperty_as_ical_string_r(icalproperty *prop)
icalproperty_kind icalproperty_isa(const icalproperty *p)
int icalproperty_count_parameters(const icalproperty *prop)
const char * icalproperty_get_value_as_string(const icalproperty *prop)
void icalproperty_remove_parameter_by_kind(icalproperty *prop, icalparameter_kind kind)
Removes all parameters with the specified kind.
icalparameter * icalproperty_get_first_parameter(icalproperty *p, icalparameter_kind kind)
void icalproperty_add_parameter(icalproperty *p, icalparameter *parameter)
void icalproperty_normalize(icalproperty *prop)
icalproperty * icalproperty_clone(const icalproperty *old)
const char * icalproperty_get_x_name(const icalproperty *prop)
void icalproperty_set_parameter(icalproperty *prop, icalparameter *parameter)
bool icalrecur_iterator_set_start(icalrecur_iterator *impl, struct icaltimetype start)
void icalrecur_iterator_free(icalrecur_iterator *impl)
icalrecur_iterator * icalrecur_iterator_new(struct icalrecurrencetype *rule, struct icaltimetype dtstart)
struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *impl)
Functions to check if an icalcomponent meets the restrictions imposed by the standard.
bool icalrestriction_check(icalcomponent *comp)
Checks if a given VCALENDAR meets all the restrictions imposed by the standard.
void icalstrarray_append(icalstrarray *array, const char *elem)
Appends a string to the array.
void icalstrarray_free(icalstrarray *array)
Frees this array's memory and all its elements.
#define icalstrarray_new(increment_size)
Creates a new icalstrarray object.
bool icaltime_is_date(const struct icaltimetype t)
const char * icaltime_get_tzid(const struct icaltimetype t)
bool icaltime_is_utc(const struct icaltimetype t)
int icaltime_compare_date_only(const struct icaltimetype a_in, const struct icaltimetype b_in)
bool icaltime_is_null_time(const struct icaltimetype t)
icaltime_t icaltime_as_timet_with_zone(const struct icaltimetype tt, const icaltimezone *zone)
int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in)
struct icaltimetype icaltime_null_time(void)
icalcomponent * icaltimezone_get_component(icaltimezone *zone)
const char * icaltimezone_get_tzid(icaltimezone *zone)
icaltimezone * icaltimezone_get_utc_timezone(void)
void icaltimezone_free(icaltimezone *zone, int free_struct)
Frees all memory used for the icaltimezone.
Timezone handling routines.
struct _icaltimezone icaltimezone
struct icalperiodtype period
struct icaldurationtype duration
struct icaltimetype start
const icaltimezone * zone