Libical API Documentation 4.0 STABLE VERSION [Visit the v3.0 documentation]
Loading...
Searching...
No Matches
icalvalue.c
Go to the documentation of this file.
1/*======================================================================
2 FILE: icalvalue.c
3 CREATOR: eric 02 May 1999
4
5 SPDX-FileCopyrightText: 2000, Eric Busboom <eric@civicknowledge.com>
6 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
7
8 Contributions from:
9 Graham Davison <g.m.davison@computer.org>
10======================================================================*/
11
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "icalvalue.h"
22#include "icalvalueimpl.h"
23#include "icalerror_p.h"
24#include "icallimits.h"
25#include "icalmemory.h"
26#include "icaltime.h"
27
28#include <ctype.h>
29#include <errno.h>
30#include <locale.h>
31#include <stdlib.h>
32
34#define TMP_BUF_SIZE 1024
35
36LIBICAL_ICAL_EXPORT struct icalvalue_impl *icalvalue_new_impl(icalvalue_kind kind)
37{
38 struct icalvalue_impl *v;
39
41 return NULL;
42 }
43
44 if ((v = (struct icalvalue_impl *)icalmemory_new_buffer(sizeof(struct icalvalue_impl))) == 0) {
46 return 0;
47 }
48
49 v->id = ICAL_STRUCTURE_TYPE_VALUE;
50
51 v->kind = kind;
52 v->size = 0;
53 v->parent = 0;
54 v->x_value = 0;
55 memset(&(v->data), 0, sizeof(v->data));
56
57 return v;
58}
60
62{
63 return (icalvalue *)icalvalue_new_impl(kind);
64}
65
67{
68 struct icalvalue_impl *clone;
69
70 clone = icalvalue_new_impl(old->kind);
71
72 if (clone == 0) {
73 return 0;
74 }
75 clone->id = old->id;
76 clone->kind = old->kind;
77 clone->size = old->size;
78
79 switch (clone->kind) {
81 case ICAL_BINARY_VALUE: {
82 /* Hmm. We just ref the attach value, which may not be the right
83 * thing to do. We cannot quite copy the data, anyways, since we
84 * don't know how long it is.
85 */
86 clone->data.v_attach = old->data.v_attach;
87 if (clone->data.v_attach) {
88 icalattach_ref(clone->data.v_attach);
89 }
90
91 break;
92 }
96 case ICAL_TEXT_VALUE:
98 case ICAL_UID_VALUE:
100 case ICAL_URI_VALUE: {
101 if (old->data.v_string != 0) {
102 clone->data.v_string = icalmemory_strdup(old->data.v_string);
103
104 if (clone->data.v_string == 0) {
105 clone->parent = 0;
106 icalvalue_free(clone);
107 return 0;
108 }
109 }
110 break;
111 }
112 case ICAL_ACTION_VALUE: {
113 clone->data = old->data;
114
115 if (old->data.v_enum == ICAL_ACTION_X) {
116 //preserve the custom action string
117 if (old->x_value != 0) {
118 clone->x_value = icalmemory_strdup(old->x_value);
119
120 if (clone->x_value == 0) {
121 clone->parent = 0;
122 icalvalue_free(clone);
123 return 0;
124 }
125 }
126 }
127 break;
128 }
129 case ICAL_RECUR_VALUE: {
130 if (old->data.v_recur != 0) {
131 clone->data.v_recur = icalrecurrencetype_clone(old->data.v_recur);
132 if (clone->data.v_recur == 0) {
133 icalvalue_free(clone);
134 return 0;
135 }
136 }
137 break;
138 }
139
140 case ICAL_X_VALUE: {
141 if (old->x_value != 0) {
142 clone->x_value = icalmemory_strdup(old->x_value);
143
144 if (clone->x_value == 0) {
145 clone->parent = 0;
146 icalvalue_free(clone);
147 return 0;
148 }
149 }
150
151 break;
152 }
153
155 clone->data = old->data;
156 if (old->data.v_requeststatus.debug != 0) {
157 clone->data.v_requeststatus.debug = icalmemory_strdup(old->data.v_requeststatus.debug);
158 if (clone->data.v_requeststatus.debug == 0) {
159 clone->parent = 0;
160 icalvalue_free(clone);
161 return 0;
162 }
163 }
164 break;
165 }
166
167 default: {
168 /* all of the other types are stored as values, not
169 pointers, so we can just copy the whole structure. */
170
171 clone->data = old->data;
172 }
173 }
174
175 return clone;
176}
177
178static char *icalmemory_strdup_and_dequote(const char *str)
179{
180 const char *p;
181 char *out = (char *)icalmemory_new_buffer(sizeof(char) * strlen(str) + 1);
182 char *pout;
183 int wroteNull = 0;
184
185 if (out == 0) {
186 return 0;
187 }
188
189 pout = out;
190
191 /* Stop the loop when encountering a terminator in the source string
192 or if a null has been written to the destination. This prevents
193 reading past the end of the source string if the last character
194 is a backslash. */
195 for (p = str; !wroteNull && *p != 0; p++) {
196 if (*p == '\\') {
197 p++;
198 switch (*p) {
199 case 0: {
200 wroteNull = 1; //stops iteration so p isn't incremented past the end of str
201 *pout = '\0';
202 break;
203 }
204 case 'n':
205 case 'N': {
206 *pout = '\n';
207 break;
208 }
209 case 't':
210 case 'T': {
211 *pout = '\t';
212 break;
213 }
214 case 'r':
215 case 'R': {
216 *pout = '\r';
217 break;
218 }
219 case 'b':
220 case 'B': {
221 *pout = '\b';
222 break;
223 }
224 case 'f':
225 case 'F': {
226 *pout = '\f';
227 break;
228 }
229 case ';':
230 case ',':
231 case '"':
232 case '\\': {
233 *pout = *p;
234 break;
235 }
236 default: {
237 *pout = ' ';
238 }
239 }
240 } else {
241 *pout = *p;
242 }
243
244 pout++;
245 }
246
247 *pout = '\0';
248
249 return out;
250}
251
252/*
253 * Returns a quoted copy of a string
254 * @todo This is not RFC5545 compliant.
255 * The RFC only allows:
256 * TSAFE-CHAR = %x20-21 / %x23-2B / %x2D-39 / %x3C-5B / %x5D-7E / NON-US-ASCII
257 * As such, \t\r\b\f are not allowed, not even escaped
258 */
259static char *icalmemory_strdup_and_quote(const icalvalue *value, const char *unquoted_str)
260{
261 char *str;
262 char *str_p;
263 const char *p;
264 size_t buf_sz;
265 size_t cnt = 0; //track iterations
266
267 buf_sz = strlen(unquoted_str) + 1;
268
269 str_p = str = (char *)icalmemory_new_buffer(buf_sz);
270
271 if (str_p == 0) {
272 return 0;
273 }
274
275 const size_t max_value_chars = icallimit_get(ICAL_LIMIT_VALUE_CHARS);
276 for (p = unquoted_str; *p != 0 && cnt < max_value_chars; p++, cnt++) {
277 switch (*p) {
278 case '\n': {
279 icalmemory_append_string(&str, &str_p, &buf_sz, "\\n");
280 break;
281 }
282
283 /*issue74: \t is not escaped, but embedded literally.*/
284 case '\t': {
285 icalmemory_append_string(&str, &str_p, &buf_sz, "\t");
286 break;
287 }
288
289 /*issue74: \r, \b and \f are not whitespace and are trashed.*/
290 case '\r': {
291 /*icalmemory_append_string(&str,&str_p,&buf_sz,"\\r"); */
292 break;
293 }
294 case '\b': {
295 /*icalmemory_append_string(&str,&str_p,&buf_sz,"\\b"); */
296 break;
297 }
298 case '\f': {
299 /*icalmemory_append_string(&str,&str_p,&buf_sz,"\\f"); */
300 break;
301 }
302
303 case ';':
304 case ',':
305 /* unescaped COMMA is allowed in CATEGORIES property as its
306 considered a list delimiter here, see:
307 https://tools.ietf.org/html/rfc5545#section-3.8.1.2 */
308 if ((icalproperty_isa(value->parent) == ICAL_CATEGORIES_PROPERTY) ||
309 (icalproperty_isa(value->parent) == ICAL_RESOURCES_PROPERTY) ||
311 (icalproperty_isa(value->parent) == ICAL_LOCATIONTYPE_PROPERTY) ||
312 ((icalproperty_isa(value->parent) == ICAL_X_PROPERTY ||
313 icalproperty_isa(value->parent) == ICAL_IANA_PROPERTY) &&
314 icalvalue_isa(value) != ICAL_TEXT_VALUE)) {
315 icalmemory_append_char(&str, &str_p, &buf_sz, *p);
316 break;
317 }
318 _fallthrough();
319 /*issue74, we don't escape double quotes
320 case '"':
321*/
322 case '\\': {
323 icalmemory_append_char(&str, &str_p, &buf_sz, '\\');
324 icalmemory_append_char(&str, &str_p, &buf_sz, *p);
325 break;
326 }
327
328 default: {
329 icalmemory_append_char(&str, &str_p, &buf_sz, *p);
330 }
331 }
332 }
333
334 /* Assume the last character is not a '\0' and add one. We could
335 check *str_p != 0, but that would be an uninitialized memory
336 read. */
337
338 icalmemory_append_char(&str, &str_p, &buf_sz, '\0');
339 return str;
340}
341
342/*
343 * FIXME
344 *
345 * This is a bad API, as it forces callers to specify their own X type.
346 * This function should take care of this by itself.
347 */
348static icalvalue *icalvalue_new_enum(icalvalue_kind kind, int x_type, const char *str)
349{
351 struct icalvalue_impl *value;
352
354 value = icalvalue_new_impl(kind);
355 value->data.v_enum = e;
356 } else {
357 /* Make it an X value */
358 value = icalvalue_new_impl(kind);
359 value->data.v_enum = x_type;
360 icalvalue_set_x(value, str);
361 }
362
363 return value;
364}
365
372static bool simple_str_to_doublestr(const char *from, char *result, int result_len, char **to)
373{
374 const char *start = NULL;
375 char *end = NULL, *cur = (char *)from;
376
377 struct lconv *loc_data = localeconv();
378 int i = 0, len;
379 double dtest;
380
381 /*sanity checks */
382 if (!from || !result) {
383 return true;
384 }
385
386 /*skip the white spaces at the beginning */
387 while (*cur && isspace((int)*cur)) {
388 cur++;
389 }
390
391 start = cur;
392 /* copy the part that looks like a double into result.
393 * during the copy, we give ourselves a chance to convert the '.'
394 * into the decimal separator of the current locale.
395 */
396 while (*cur && (isdigit((int)*cur) || *cur == '.' || *cur == '+' || *cur == '-')) {
397 ++cur;
398 }
399 end = cur;
400 len = (int)(ptrdiff_t)(end - start);
401 if (len + 1 >= result_len) {
402 /* huh hoh, number is too big. truncate it */
403 len = result_len - 1;
404 }
405
406 /* copy the float number string into result, and take
407 * care to have the (optional) decimal separator be the one
408 * of the current locale.
409 */
410 for (i = 0; i < len; ++i) {
411 if (start[i] == '.' &&
412 loc_data && loc_data->decimal_point && loc_data->decimal_point[0] && loc_data->decimal_point[0] != '.') {
413 /*replace '.' by the digit separator of the current locale */
414 result[i] = loc_data->decimal_point[0];
415 } else {
416 result[i] = start[i];
417 }
418 }
419 if (to) {
420 *to = end;
421 }
422
423 /* now try to convert to a floating point number, to check for validity only */
424 if (sscanf(result, "%lf", &dtest) != 1) { //NOLINT(bugprone-unchecked-string-to-number-conversion)
425 return true;
426 }
427 return false;
428}
429
430static void free_icalvalue_attach_data(char *data, void *user_data)
431{
432 _unused(user_data);
433 free(data);
434}
435
436static icalvalue *icalvalue_new_from_string_with_error(icalvalue_kind kind,
437 const char *str, icalproperty **error)
438{
439 char temp[TMP_BUF_SIZE] = {};
440 icalparameter *errParam;
441
442 struct icalvalue_impl *value = 0;
443
444 icalerror_check_arg_rz(str != 0, "str");
445
446 if (error != 0) {
447 *error = 0;
448 }
449
450 switch (kind) {
451 case ICAL_ATTACH_VALUE: {
452 icalattach *attach;
453
455 if (!attach) {
456 break;
457 }
458
459 value = icalvalue_new_attach(attach);
460 icalattach_unref(attach);
461 break;
462 }
463
464#if defined(__GNUC__) && !defined(__clang__)
465#pragma GCC diagnostic push
466#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
467#endif
468 case ICAL_BINARY_VALUE: {
469 char *dupStr = strdup(str); // will be freed later on during unref
470 if (dupStr) {
471 icalattach *attach = icalattach_new_from_data(dupStr, free_icalvalue_attach_data, 0);
472 if (!attach) {
473 free(dupStr);
474 break;
475 }
476
477 value = icalvalue_new_attach(attach);
478 icalattach_unref(attach);
479 }
480 break;
481 }
482#if defined(__GNUC__) && !defined(__clang__)
483#pragma GCC diagnostic pop
484#endif
485
486 case ICAL_BOOLEAN_VALUE: {
487 if (!strcmp(str, "TRUE")) {
488 value = icalvalue_new_boolean(1);
489 } else if (!strcmp(str, "FALSE")) {
490 value = icalvalue_new_boolean(0);
491 } else {
492 if (error != 0) {
493 snprintf(temp, sizeof(temp),
494 "Could not parse %s as a %s property",
497 *error = icalproperty_vanew_xlicerror(temp, errParam, (void *)0);
498 }
499 snprintf(temp, TMP_BUF_SIZE,
500 "icalvalue_new_from_string cannot parse value string (%s) for \'%s\'",
502 icalerror_warn(temp);
504 }
505 break;
506 }
507
509 value = icalvalue_new_enum(kind, (int)ICAL_TRANSP_X, str);
510 break;
512 value = icalvalue_new_enum(kind, (int)ICAL_METHOD_X, str);
513 break;
515 value = icalvalue_new_enum(kind, (int)ICAL_STATUS_X, str);
516 break;
518 value = icalvalue_new_enum(kind, (int)ICAL_ACTION_X, str);
519 break;
520
521 case ICAL_QUERY_VALUE:
522 value = icalvalue_new_query(str);
523 break;
524
525 case ICAL_CLASS_VALUE:
526 value = icalvalue_new_enum(kind, (int)ICAL_CLASS_X, str);
527 break;
528 case ICAL_CMD_VALUE:
529 value = icalvalue_new_enum(kind, ICAL_CMD_X, str);
530 break;
532 value = icalvalue_new_enum(kind, ICAL_QUERYLEVEL_X, str);
533 break;
535 value = icalvalue_new_enum(kind, ICAL_CARLEVEL_X, str);
536 break;
538 value = icalvalue_new_enum(kind, ICAL_BUSYTYPE_X, str);
539 break;
541 value = icalvalue_new_enum(kind, ICAL_PROXIMITY_X, str);
542 break;
544 value = icalvalue_new_enum(kind, ICAL_POLLMODE_X, str);
545 break;
547 value = icalvalue_new_enum(kind, ICAL_POLLCOMPLETION_X, str);
548 break;
549
551 value = icalvalue_new_enum(kind, ICAL_PARTICIPANTTYPE_X, str);
552 break;
553
555 value = icalvalue_new_enum(kind, ICAL_RESOURCETYPE_X, str);
556 break;
557
558 case ICAL_INTEGER_VALUE: {
559 errno = 0;
560 char *t_end;
561 const long tmpl = strtol(str, &t_end, 10);
562 if (str != t_end && errno != ERANGE) {
563 value = icalvalue_new_integer(tmpl);
564 }
565 break;
566 }
567 case ICAL_FLOAT_VALUE: {
568 char *t_end;
569 const float tmpf = strtof(str, &t_end);
570 if (str != t_end) {
571 value = icalvalue_new_float(tmpf);
572 }
573 break;
574 }
576 int iOffset;
577 long utcoffset, hours, minutes, seconds;
578
579 /* treat the UTCOFFSET string as a decimal number, disassemble its digits
580 and reconstruct it as sections */
581 long t = strtol(str, 0, 10);
582
583 /* add phantom seconds field */
584 if (strlen(str) < 7) {
585 t *= 100;
586 }
587 hours = (t / 10000);
588 minutes = (t - hours * 10000) / 100;
589 seconds = (t - hours * 10000 - minutes * 100);
590 utcoffset = hours * 3600 + minutes * 60 + seconds;
591 if (utcoffset < INT_MIN) {
592 iOffset = INT_MIN;
593 } else if (utcoffset > INT_MAX) {
594 iOffset = INT_MAX;
595 } else {
596 iOffset = utcoffset;
597 }
598 value = icalvalue_new_utcoffset(iOffset);
599
600 break;
601 }
602
603 case ICAL_TEXT_VALUE: {
604 char *dequoted_str = icalmemory_strdup_and_dequote(str);
605
606 value = icalvalue_new_text(dequoted_str);
607 icalmemory_free_buffer(dequoted_str);
608 break;
609 }
610
612 value = icalvalue_new_string(str);
613 break;
614
615 case ICAL_COLOR_VALUE:
616 value = icalvalue_new_color(str);
617 break;
618
621 break;
622
623 case ICAL_URI_VALUE:
624 value = icalvalue_new_uri(str);
625 break;
626
627 case ICAL_GEO_VALUE: {
628 char *cur = NULL;
629 struct icalgeotype geo = {0};
630 memset(geo.lat, 0, ICAL_GEO_LEN);
631 memset(geo.lon, 0, ICAL_GEO_LEN);
632
633 if (simple_str_to_doublestr(str, geo.lat, ICAL_GEO_LEN, &cur)) {
634 goto geo_parsing_error;
635 }
636 /* skip white spaces */
637 while (cur && isspace((int)*cur)) {
638 ++cur;
639 }
640
641 /*there is a ';' between the latitude and longitude parts */
642 if (!cur || *cur != ';') {
643 goto geo_parsing_error;
644 }
645
646 ++cur;
647
648 /* skip white spaces */
649 while (cur && isspace((int)*cur)) {
650 ++cur;
651 }
652
653 if (simple_str_to_doublestr(cur, geo.lon, ICAL_GEO_LEN, &cur)) {
654 goto geo_parsing_error;
655 }
656 value = icalvalue_new_geo(geo);
657 break;
658
659 geo_parsing_error:
660 if (error != 0) {
661 snprintf(temp, sizeof(temp),
662 "Could not parse %s as a %s property",
665 *error = icalproperty_vanew_xlicerror(temp, errParam, (void *)0);
666 }
667 snprintf(temp, TMP_BUF_SIZE,
668 "icalvalue_new_from_string cannot parse value string (%s) for \'%s\'",
670 icalerror_warn(temp);
672 } break;
673
674 case ICAL_RECUR_VALUE: {
675 struct icalrecurrencetype *rt;
676
678 if (rt) {
679 value = icalvalue_new_recur(rt);
681 }
682 break;
683 }
684
685 case ICAL_DATE_VALUE:
686 case ICAL_DATETIME_VALUE: {
687 struct icaltimetype tt;
688
690 if (!icaltime_is_null_time(tt)) {
691 value = icalvalue_new_impl(kind);
692 value->data.v_time = tt;
693
695 }
696 break;
697 }
698
700 struct icaltimetype tt;
701 struct icalperiodtype p;
702
704
705 if (!icaltime_is_null_time(tt)) {
706 value = icalvalue_new_datetime(tt);
707 break;
708 }
709
712 value = icalvalue_new_period(p);
713 }
714
715 break;
716 }
717
718 case ICAL_DURATION_VALUE: {
720
721 if (!icaldurationtype_is_bad_duration(dur)) { /* failed to parse */
722 value = icalvalue_new_duration(dur);
723 }
724
725 break;
726 }
727
728 case ICAL_PERIOD_VALUE: {
729 struct icalperiodtype p;
730
732
734 value = icalvalue_new_period(p);
735 }
736 break;
737 }
738
739 case ICAL_TRIGGER_VALUE: {
741
743 value = icalvalue_new_trigger(tr);
744 }
745 break;
746 }
747
750
751 if (rst.code != ICAL_UNKNOWN_STATUS) {
752 value = icalvalue_new_requeststatus(rst);
753 }
754 break;
755 }
756
757 case ICAL_UID_VALUE: {
758 char *dequoted_str = icalmemory_strdup_and_dequote(str);
759
760 value = icalvalue_new_uid(dequoted_str);
761 icalmemory_free_buffer(dequoted_str);
762 break;
763 }
764
767 break;
768
769 case ICAL_X_VALUE: {
770 char *dequoted_str = icalmemory_strdup_and_dequote(str);
771
772 value = icalvalue_new_x(dequoted_str);
773 icalmemory_free_buffer(dequoted_str);
774 } break;
775
776 default: {
777 if (error != 0) {
778 snprintf(temp, TMP_BUF_SIZE, "Unknown type for \'%s\'", str);
779
781 *error = icalproperty_vanew_xlicerror(temp, errParam, (void *)0);
782 }
783
784 snprintf(temp, TMP_BUF_SIZE,
785 "icalvalue_new_from_string got an unknown value type (%s) for \'%s\'",
787 icalerror_warn(temp);
789 }
790 }
791
792#if defined(__GNUC__) && !defined(__clang__)
793#pragma GCC diagnostic push
794#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
795#endif
796 if (error != 0 && *error == 0 && value == 0) {
797 snprintf(temp, TMP_BUF_SIZE, "Failed to parse value: \'%s\'", str);
798
799 /* coverity[resource_leak] */
801 *error = icalproperty_vanew_xlicerror(temp, errParam, (void *)0);
802 }
803#if defined(__GNUC__) && !defined(__clang__)
804#pragma GCC diagnostic pop
805#endif
806 return value;
807}
808
810{
811 return icalvalue_new_from_string_with_error(kind, str, (icalproperty **)0);
812}
813
815{
816 icalerror_check_arg_rv((v != 0), "value");
817
818 if (v->parent != 0) {
819 return;
820 }
821
822 if (v->x_value != 0) {
823 icalmemory_free_buffer(v->x_value);
824 }
825
826 switch (v->kind) {
828 case ICAL_ATTACH_VALUE: {
829 if (v->data.v_attach) {
830 icalattach_unref(v->data.v_attach);
831 v->data.v_attach = NULL;
832 }
833
834 break;
835 }
836 case ICAL_TEXT_VALUE:
837 _fallthrough();
838
840 _fallthrough();
841
842 case ICAL_URI_VALUE:
843 _fallthrough();
844
846 _fallthrough();
847
848 case ICAL_COLOR_VALUE:
849 _fallthrough();
850
851 case ICAL_QUERY_VALUE: {
852 _fallthrough();
853 case ICAL_UID_VALUE:
854 _fallthrough();
856 if (v->data.v_string != 0) {
857 icalmemory_free_buffer((void *)v->data.v_string);
858 v->data.v_string = 0;
859 }
860 break;
861 }
862 case ICAL_RECUR_VALUE: {
863 if (v->data.v_recur != 0) {
864 icalrecurrencetype_unref(v->data.v_recur);
865 v->data.v_recur = NULL;
866 }
867 break;
868 }
869
871 if (v->data.v_requeststatus.debug != 0) {
872 icalmemory_free_buffer((void *)v->data.v_requeststatus.debug);
873 v->data.v_requeststatus.debug = 0;
874 }
875 break;
876 }
877
878 default: {
879 /* Nothing to do */
880 }
881 }
882
883 v->kind = ICAL_NO_VALUE;
884 v->size = 0;
885 v->parent = 0;
886 memset(&(v->data), 0, sizeof(v->data));
887 v->id = ICAL_STRUCTURE_TYPE_VALUE_EMPTY;
889}
890
892{
893 if (value == 0) {
894 return false;
895 }
896
897 return true;
898}
899
900static char *icalvalue_binary_as_ical_string_r(const icalvalue *value)
901{
902 char *str;
903
904 icalerror_check_arg_rz((value != 0), "value");
905
906 str = (char *)icalmemory_new_buffer(60);
907 snprintf(str, 60, "icalvalue_binary_as_ical_string is not implemented yet");
908
909 return str;
910}
911
912static char *icalvalue_boolean_as_ical_string_r(const icalvalue *value)
913{
914 int data;
915 char *str;
916
917 icalerror_check_arg_rz((value != 0), "value");
918 str = (char *)icalmemory_new_buffer(6);
919
920 data = icalvalue_get_integer(value);
921
922 strncpy(str, data ? "TRUE" : "FALSE", 6);
923
924 return str;
925}
926
928#define MAX_INT_DIGITS 12 /* Enough for 2^32 + sign */
930
931static char *icalvalue_int_as_ical_string_r(const icalvalue *value)
932{
933 int data;
934 char *str;
935
936 icalerror_check_arg_rz((value != 0), "value");
938
939 data = icalvalue_get_integer(value);
940
941 snprintf(str, MAX_INT_DIGITS, "%d", data);
942
943 return str;
944}
945
946static char *icalvalue_utcoffset_as_ical_string_r(const icalvalue *value)
947{
948 int data, h, m, s;
949 char sign;
950 char *str;
951
952 icalerror_check_arg_rz((value != 0), "value");
953
954 str = (char *)icalmemory_new_buffer(9);
955 data = icalvalue_get_utcoffset(value);
956
957 if (abs(data) == data) {
958 sign = '+';
959 } else {
960 sign = '-';
961 }
962
963 h = data / 3600;
964 m = (data - (h * 3600)) / 60;
965 s = (data - (h * 3600) - (m * 60));
966
967 h = MIN(abs(h), 23);
968 m = MIN(abs(m), 59);
969 s = MIN(abs(s), 59);
970 if (s != 0) {
971 snprintf(str, 9, "%c%02d%02d%02d", sign, h, m, s);
972 } else {
973 snprintf(str, 9, "%c%02d%02d", sign, h, m);
974 }
975
976 return str;
977}
978
979static char *icalvalue_string_as_ical_string_r(const icalvalue *value)
980{
981 const char *data;
982 char *str = 0;
983
984 icalerror_check_arg_rz((value != 0), "value");
985 data = value->data.v_string;
986
987 const size_t str_len = strlen(data) + 1;
988 str = (char *)icalmemory_new_buffer(str_len);
989
990 strncpy(str, data, str_len);
991 str[str_len - 1] = '\0';
992
993 return str;
994}
995
996static char *icalvalue_recur_as_ical_string_r(const icalvalue *value)
997{
998 struct icalrecurrencetype *recur = value->data.v_recur;
999
1000 return icalrecurrencetype_as_string_r(recur);
1001}
1002
1003static char *icalvalue_text_as_ical_string_r(const icalvalue *value)
1004{
1005 return icalmemory_strdup_and_quote(value, value->data.v_string);
1006}
1007
1008static char *icalvalue_attach_as_ical_string_r(const icalvalue *value)
1009{
1010 icalattach *a;
1011 char *str;
1012
1013 icalerror_check_arg_rz((value != 0), "value");
1014
1015 a = icalvalue_get_attach(value);
1016
1017 if (icalattach_get_is_url(a)) {
1018 const char *url;
1019
1020 url = icalattach_get_url(a);
1021 const size_t len_url = strlen(url) + 1;
1022 str = icalmemory_new_buffer(len_url);
1023 strncpy(str, url, len_url);
1024 str[len_url - 1] = '\0';
1025 return str;
1026 } else {
1027 const char *data = 0;
1028
1029 data = (const char *)icalattach_get_data(a);
1030 const size_t len_data = strlen(data) + 1;
1031 str = icalmemory_new_buffer(len_data);
1032 strncpy(str, data, len_data);
1033 str[len_data - 1] = '\0';
1034 return str;
1035 }
1036}
1037
1038static char *icalvalue_duration_as_ical_string_r(const icalvalue *value)
1039{
1040 struct icaldurationtype data;
1041
1042 icalerror_check_arg_rz((value != 0), "value");
1043 data = icalvalue_get_duration(value);
1044
1046}
1047
1048static void print_time_to_string(char *str, const struct icaltimetype *data)
1049{ /* this function is a candidate for a library-wide external function
1050 except it isn't used any place outside of icalvalue.c.
1051 see print_date_to_string() and print_datetime_to_string in icalvalue.h */
1052#if defined(__GNUC__) && !defined(__clang__)
1053#pragma GCC diagnostic push
1054#pragma GCC diagnostic ignored "-Wstringop-truncation"
1055#endif
1056 char temp[8];
1057
1058 str[0] = '\0';
1059 if (data != 0) {
1060 if (icaltime_is_utc(*data)) {
1061 snprintf(temp, sizeof(temp), "%02d%02d%02dZ", data->hour, data->minute, data->second);
1062 strncat(str, temp, 7);
1063 } else {
1064 snprintf(temp, sizeof(temp), "%02d%02d%02d", data->hour, data->minute, data->second);
1065 strncat(str, temp, 6);
1066 }
1067 }
1068#if defined(__GNUC__) && !defined(__clang__)
1069#pragma GCC diagnostic pop
1070#endif
1071}
1072
1074void print_date_to_string(char *str, const struct icaltimetype *data)
1075{
1076#if defined(__GNUC__) && !defined(__clang__)
1077#pragma GCC diagnostic push
1078#pragma GCC diagnostic ignored "-Wstringop-truncation"
1079#endif
1080 char temp[9];
1081
1082 str[0] = '\0';
1083
1084 if (data != 0) {
1085 snprintf(temp, sizeof(temp), "%04d%02d%02d", data->year, data->month, data->day);
1086 strncat(str, temp, 8);
1087 }
1088#if defined(__GNUC__) && !defined(__clang__)
1089#pragma GCC diagnostic pop
1090#endif
1091}
1093
1094static char *icalvalue_date_as_ical_string_r(const icalvalue *value)
1095{
1096 struct icaltimetype data;
1097 char *str;
1098
1099 icalerror_check_arg_rz((value != 0), "value");
1100 data = icalvalue_get_date(value);
1101
1102 str = (char *)icalmemory_new_buffer(9);
1103
1104 str[0] = '\0';
1105 print_date_to_string(str, &data);
1106
1107 return str;
1108}
1109
1111void print_datetime_to_string(char *str, const struct icaltimetype *data)
1112{
1113#if defined(__GNUC__) && !defined(__clang__)
1114#pragma GCC diagnostic push
1115#pragma GCC diagnostic ignored "-Wstringop-truncation"
1116#endif
1117 char temp[20] = {0};
1118
1119 str[0] = '\0';
1120 if (data != 0) {
1121 print_date_to_string(str, data);
1122 if (!data->is_date) {
1123 strncat(str, "T", 19);
1124 temp[0] = '\0';
1125 print_time_to_string(temp, data);
1126 strncat(str, temp, 19);
1127 }
1128 }
1129#if defined(__GNUC__) && !defined(__clang__)
1130#pragma GCC diagnostic pop
1131#endif
1132}
1134
1135static char *icalvalue_datetime_as_ical_string_r(const icalvalue *value)
1136{
1137 struct icaltimetype data;
1138 char *str;
1140
1141 icalerror_check_arg_rz((value != 0), "value");
1142
1143 if (!(kind == ICAL_DATE_VALUE || kind == ICAL_DATETIME_VALUE)) {
1145 return 0;
1146 }
1147
1148 data = icalvalue_get_datetime(value);
1149
1150 str = (char *)icalmemory_new_buffer(20);
1151
1152 str[0] = 0;
1153 print_datetime_to_string(str, &data);
1154
1155 return str;
1156}
1157
1158static char *icalvalue_float_as_ical_string_r(const icalvalue *value)
1159{
1160 float data;
1161 char *str;
1162 char *old_locale;
1163
1164 icalerror_check_arg_rz((value != 0), "value");
1165 data = icalvalue_get_float(value);
1166
1167 /* bypass current locale in order to make
1168 sure snprintf uses a '.' as a separator
1169 set locate to 'C' and keep old locale */
1170 old_locale = icalmemory_strdup(setlocale(LC_NUMERIC, NULL));
1171 (void)setlocale(LC_NUMERIC, "C");
1172
1173 str = (char *)icalmemory_new_buffer(40);
1174
1175 snprintf(str, 40, "%f", data);
1176
1177 /* restore saved locale */
1178 (void)setlocale(LC_NUMERIC, old_locale);
1179 icalmemory_free_buffer(old_locale);
1180
1181 return str;
1182}
1183
1184static char *icalvalue_geo_as_ical_string_r(const icalvalue *value)
1185{
1186 struct icalgeotype data;
1187 char *str;
1188
1189 icalerror_check_arg_rz((value != 0), "value");
1190
1191 data = icalvalue_get_geo(value);
1192 str = (char *)icalmemory_new_buffer(80);
1193 snprintf(str, 80, "%s;%s", data.lat, data.lon);
1194
1195 return str;
1196}
1197
1198static char *icalvalue_datetimeperiod_as_ical_string_r(const icalvalue *value)
1199{
1201
1202 icalerror_check_arg_rz((value != 0), "value");
1203
1204 if (!icaltime_is_null_time(dtp.time)) {
1205 return icaltime_as_ical_string_r(dtp.time);
1206 } else {
1208 }
1209}
1210
1211static char *icalvalue_period_as_ical_string_r(const icalvalue *value)
1212{
1213 struct icalperiodtype data;
1214
1215 icalerror_check_arg_rz((value != 0), "value");
1216 data = icalvalue_get_period(value);
1217
1219}
1220
1221static char *icalvalue_trigger_as_ical_string_r(const icalvalue *value)
1222{
1223 struct icaltriggertype data;
1224
1225 icalerror_check_arg_rz((value != 0), "value");
1226 data = icalvalue_get_trigger(value);
1227
1228 if (!icaltime_is_null_time(data.time)) {
1229 return icaltime_as_ical_string_r(data.time);
1230 } else {
1231 return icaldurationtype_as_ical_string_r(data.duration);
1232 }
1233}
1234
1235const char *icalvalue_as_ical_string(const icalvalue *value)
1236{
1237 char *buf;
1238
1239 buf = icalvalue_as_ical_string_r(value);
1241 return buf;
1242}
1243
1245{
1246 if (value == 0) {
1247 return 0;
1248 }
1249
1250 switch (value->kind) {
1251 case ICAL_ATTACH_VALUE:
1252 return icalvalue_attach_as_ical_string_r(value);
1253
1254 case ICAL_BINARY_VALUE:
1255 return icalvalue_binary_as_ical_string_r(value);
1256
1257 case ICAL_BOOLEAN_VALUE:
1258 return icalvalue_boolean_as_ical_string_r(value);
1259
1260 case ICAL_INTEGER_VALUE:
1261 return icalvalue_int_as_ical_string_r(value);
1262
1264 return icalvalue_utcoffset_as_ical_string_r(value);
1265
1266 case ICAL_TEXT_VALUE:
1267 case ICAL_UID_VALUE:
1268 return icalvalue_text_as_ical_string_r(value);
1269
1270 case ICAL_QUERY_VALUE:
1271 return icalvalue_string_as_ical_string_r(value);
1272
1273 case ICAL_STRING_VALUE:
1274 case ICAL_COLOR_VALUE:
1275 case ICAL_URI_VALUE:
1278 return icalvalue_string_as_ical_string_r(value);
1279
1280 case ICAL_DATE_VALUE:
1281 return icalvalue_date_as_ical_string_r(value);
1283 return icalvalue_datetime_as_ical_string_r(value);
1285 return icalvalue_duration_as_ical_string_r(value);
1286
1287 case ICAL_PERIOD_VALUE:
1288 return icalvalue_period_as_ical_string_r(value);
1290 return icalvalue_datetimeperiod_as_ical_string_r(value);
1291
1292 case ICAL_FLOAT_VALUE:
1293 return icalvalue_float_as_ical_string_r(value);
1294
1295 case ICAL_GEO_VALUE:
1296 return icalvalue_geo_as_ical_string_r(value);
1297
1298 case ICAL_RECUR_VALUE:
1299 return icalvalue_recur_as_ical_string_r(value);
1300
1301 case ICAL_TRIGGER_VALUE:
1302 return icalvalue_trigger_as_ical_string_r(value);
1303
1305 return icalreqstattype_as_string_r(value->data.v_requeststatus);
1306
1307 case ICAL_ACTION_VALUE:
1308 case ICAL_CMD_VALUE:
1311 case ICAL_METHOD_VALUE:
1312 case ICAL_STATUS_VALUE:
1313 case ICAL_TRANSP_VALUE:
1314 case ICAL_CLASS_VALUE:
1321 if (value->x_value != 0) {
1322 return icalmemory_strdup(value->x_value);
1323 }
1324
1325 return icalproperty_enum_to_string_r(value->data.v_enum);
1326
1327 case ICAL_X_VALUE:
1328 if (value->x_value != 0) {
1329 return icalmemory_strdup_and_quote(value, value->x_value);
1330 }
1331 _fallthrough();
1332
1333 case ICAL_NO_VALUE:
1334 _fallthrough();
1335
1336 default: {
1338 return icalmemory_strdup("");
1339 }
1340 return 0;
1341 }
1342 }
1343}
1344
1346{
1347 if (value == 0) {
1348 return ICAL_NO_VALUE;
1349 }
1350
1351 return value->kind;
1352}
1353
1354bool icalvalue_isa_value(void *value)
1355{
1356 const struct icalvalue_impl *impl = (struct icalvalue_impl *)value;
1357
1358 icalerror_check_arg_rz((value != 0), "value");
1359
1360 return (impl->id == ICAL_STRUCTURE_TYPE_VALUE);
1361}
1362
1363static bool icalvalue_is_time(const icalvalue *a)
1364{
1366
1368 return true;
1369 }
1370
1371 return false;
1372}
1373
1375{
1376 icalerror_check_arg_rx((a != 0), "a", ICAL_XLICCOMPARETYPE_NONE);
1377 icalerror_check_arg_rx((b != 0), "b", ICAL_XLICCOMPARETYPE_NONE);
1378
1379 /* Not the same type; they can only be unequal */
1380 if (!(icalvalue_is_time(a) && icalvalue_is_time(b)) && icalvalue_isa(a) != icalvalue_isa(b)) {
1382 }
1383
1384 switch (icalvalue_isa(a)) {
1385 case ICAL_ATTACH_VALUE: {
1386 if (icalattach_get_is_url(a->data.v_attach) &&
1387 icalattach_get_is_url(b->data.v_attach)) {
1388 if (strcasecmp(icalattach_get_url(a->data.v_attach),
1389 icalattach_get_url(b->data.v_attach)) == 0) {
1391 } else {
1393 }
1394 } else {
1395 if (a->data.v_attach == b->data.v_attach) {
1397 } else {
1399 }
1400 }
1401 }
1402 case ICAL_BINARY_VALUE: {
1403 if (a->data.v_attach == b->data.v_attach) {
1405 } else {
1407 }
1408 }
1409
1410 case ICAL_BOOLEAN_VALUE: {
1413 } else {
1415 }
1416 }
1417
1418 case ICAL_FLOAT_VALUE: {
1419 if (a->data.v_float > b->data.v_float) {
1421 } else if (a->data.v_float < b->data.v_float) {
1423 } else {
1425 }
1426 }
1427
1428 case ICAL_INTEGER_VALUE:
1429 case ICAL_UTCOFFSET_VALUE: {
1430 if (a->data.v_int > b->data.v_int) {
1432 } else if (a->data.v_int < b->data.v_int) {
1434 } else {
1436 }
1437 }
1438
1439 case ICAL_DURATION_VALUE: {
1440 struct icaldurationtype dur_a = a->data.v_duration,
1441 dur_b = b->data.v_duration;
1442 int a_days = (int)(7 * dur_a.weeks + dur_a.days) * (dur_a.is_neg == 1 ? -1 : 1),
1443 b_days = (int)(7 * dur_b.weeks + dur_b.days) * (dur_a.is_neg == 1 ? -1 : 1);
1444 int a_secs = (int)(dur_a.seconds + 60 * (dur_a.minutes + 60 * dur_a.hours)) *
1445 (dur_a.is_neg == 1 ? -1 : 1),
1446 b_secs = (int)(dur_b.seconds + 60 * (dur_b.minutes + 60 * dur_b.hours)) *
1447 (dur_b.is_neg == 1 ? -1 : 1);
1448
1449 if (a_secs == b_secs) {
1450 if (a_days > b_days) {
1452 } else if (a_days < b_days) {
1454 } else {
1456 }
1457 } else if (a_days == b_days) {
1458 if (a_secs > b_secs) {
1460 } else {
1462 }
1463 } else {
1464 /* We can't compare a mix of nominal and accurate durations */
1466 }
1467 }
1468
1469 case ICAL_TEXT_VALUE:
1470 case ICAL_URI_VALUE:
1472 case ICAL_TRIGGER_VALUE:
1473 case ICAL_DATE_VALUE:
1476 case ICAL_QUERY_VALUE:
1477 case ICAL_UID_VALUE:
1479 case ICAL_RECUR_VALUE: {
1480 int r;
1481 char *temp1, *temp2;
1482
1483 temp1 = icalvalue_as_ical_string_r(a);
1484 if (temp1) {
1485 temp2 = icalvalue_as_ical_string_r(b);
1486 if (temp2) {
1487 r = strcmp(temp1, temp2);
1488 } else {
1491 }
1492 } else {
1494 }
1497
1498 if (r > 0) {
1500 } else if (r < 0) {
1502 } else {
1504 }
1505 }
1506
1507 case ICAL_METHOD_VALUE: {
1510 } else {
1512 }
1513 }
1514
1515 case ICAL_STATUS_VALUE: {
1518 } else {
1520 }
1521 }
1522
1523 case ICAL_TRANSP_VALUE: {
1526 } else {
1528 }
1529 }
1530
1531 case ICAL_ACTION_VALUE: {
1534 } else {
1536 }
1537 }
1538
1539 case ICAL_PERIOD_VALUE:
1540 case ICAL_GEO_VALUE:
1541 case ICAL_NO_VALUE:
1542 default: {
1543 icalerror_warn("Comparison not implemented for value type");
1545 }
1546 }
1547}
1548
1550{
1551 if (value &&
1552 (value->kind == ICAL_DATETIME_VALUE || value->kind == ICAL_DATE_VALUE) &&
1553 !icaltime_is_null_time(value->data.v_time)) {
1554 if (icaltime_is_date(value->data.v_time)) {
1555 value->kind = ICAL_DATE_VALUE;
1556 } else {
1557 value->kind = ICAL_DATETIME_VALUE;
1558 }
1559 }
1560}
1561
1562void icalvalue_set_parent(icalvalue *value, icalproperty *property)
1563{
1564 icalerror_check_arg_rv((value != 0), "value");
1565
1566 value->parent = property;
1567}
1568
1569icalproperty *icalvalue_get_parent(const icalvalue *value)
1570{
1571 return value->parent;
1572}
1573
1574bool icalvalue_encode_ical_string(const char *szText, char *szEncText, int maxBufferLen)
1575{
1576 char *ptr;
1577 icalvalue *value = 0;
1578
1579 if ((szText == 0) || (szEncText == 0)) {
1580 return false;
1581 }
1582
1584
1585 if (value == 0) {
1586 return false;
1587 }
1588
1589 ptr = icalvalue_text_as_ical_string_r(value);
1590 if (ptr == 0) {
1591 return false;
1592 }
1593
1594 if ((int)strlen(ptr) >= maxBufferLen) {
1595 icalvalue_free(value);
1597 return false;
1598 }
1599
1600 strcpy(szEncText, ptr); //NOLINT(clang-analyzer-security.insecureAPI.strcp
1602
1603 icalvalue_free((icalvalue *)value);
1604
1605 return true;
1606}
1607
1608bool icalvalue_decode_ical_string(const char *szText, char *szDecText, int maxBufferLen)
1609{
1610 char *str, *str_p;
1611 const char *p;
1612 size_t buf_sz;
1613
1614 if ((szText == 0) || (szDecText == 0) || (maxBufferLen <= 0)) {
1615 return false;
1616 }
1617
1618 buf_sz = strlen(szText) + 1;
1619 str_p = str = (char *)icalmemory_new_buffer(buf_sz);
1620
1621 if (str_p == 0) {
1622 return false;
1623 }
1624
1625 for (p = szText; *p != 0; p++) {
1626 if (*p == '\\') {
1627 icalmemory_append_char(&str, &str_p, &buf_sz, *(p + 1));
1628 p++;
1629 } else {
1630 icalmemory_append_char(&str, &str_p, &buf_sz, *p);
1631 }
1632
1633 if (str_p - str > maxBufferLen) {
1634 break;
1635 }
1636 }
1637
1638 icalmemory_append_char(&str, &str_p, &buf_sz, '\0');
1639
1640 if ((int)strlen(str) >= maxBufferLen) {
1642 return false;
1643 }
1644
1645 strcpy(szDecText, str); //NOLINT(clang-analyzer-security.insecureAPI.strcpy)
1646
1648 return true;
1649}
1650
1651/* The remaining interfaces are 'new', 'set' and 'get' for each of the value
1652 types */
icalattach * icalattach_new_from_data(const char *data, icalattach_free_fn_t free_fn, void *free_fn_data)
Creates new icalattach object from data.
Definition icalattach.c:56
void icalattach_unref(icalattach *attach)
Decrements reference count of the icalattach.
Definition icalattach.c:95
void icalattach_ref(icalattach *attach)
Increments reference count of the icalattach.
Definition icalattach.c:87
unsigned char * icalattach_get_data(icalattach *attach)
Returns the data of the icalattach object.
Definition icalattach.c:130
const char * icalattach_get_url(icalattach *attach)
Returns the URL of the icalattach object.
Definition icalattach.c:122
icalattach * icalattach_new_from_url(const char *url)
Creates new icalattach object from a URL.
Definition icalattach.c:25
bool icalattach_get_is_url(const icalattach *attach)
Determines if attach is an URL.
Definition icalattach.c:115
struct icalattach_impl icalattach
An iCal attach object representing a link to a document object.
Definition icalattach.h:36
struct icalparameter_impl icalparameter
icalparameter_xliccomparetype
@ ICAL_XLICCOMPARETYPE_NOTEQUAL
@ ICAL_XLICCOMPARETYPE_LESS
@ ICAL_XLICCOMPARETYPE_GREATER
@ ICAL_XLICCOMPARETYPE_EQUAL
@ ICAL_XLICCOMPARETYPE_NONE
@ ICAL_XLICERRORTYPE_VALUEPARSEERROR
icalparameter * icalparameter_new_xlicerrortype(icalparameter_xlicerrortype v)
icalproperty * icalproperty_vanew_xlicerror(const char *v,...)
@ ICAL_LOCATIONTYPE_PROPERTY
@ ICAL_CATEGORIES_PROPERTY
@ ICAL_IANA_PROPERTY
@ ICAL_POLLPROPERTIES_PROPERTY
@ ICAL_X_PROPERTY
@ ICAL_RESOURCES_PROPERTY
icalvalue * icalvalue_new_query(const char *v)
struct icaltimetype icalvalue_get_datetime(const icalvalue *value)
enum icalproperty_status icalvalue_get_status(const icalvalue *value)
icalvalue * icalvalue_new_trigger(struct icaltriggertype v)
@ ICAL_CMD_X
struct icaltriggertype icalvalue_get_trigger(const icalvalue *value)
float icalvalue_get_float(const icalvalue *value)
@ ICAL_CARLEVEL_X
icalvalue * icalvalue_new_geo(struct icalgeotype v)
@ ICAL_BUSYTYPE_X
@ ICAL_STATUS_X
icalvalue * icalvalue_new_uid(const char *v)
icalvalue * icalvalue_new_x(const char *v)
icalvalue * icalvalue_new_integer(int v)
@ ICAL_ACTION_X
icalvalue * icalvalue_new_utcoffset(int v)
void icalvalue_set_x(icalvalue *value, const char *v)
@ ICAL_QUERYLEVEL_X
struct icaltimetype icalvalue_get_date(const icalvalue *value)
@ ICAL_METHOD_X
icalvalue * icalvalue_new_uri(const char *v)
@ ICAL_RESOURCETYPE_X
icalvalue * icalvalue_new_xmlreference(const char *v)
int icalvalue_get_integer(const icalvalue *value)
enum icalproperty_action icalvalue_get_action(const icalvalue *value)
icalvalue * icalvalue_new_requeststatus(struct icalreqstattype v)
enum icalproperty_transp icalvalue_get_transp(const icalvalue *value)
icalvalue * icalvalue_new_period(struct icalperiodtype v)
int icalvalue_get_utcoffset(const icalvalue *value)
icalattach * icalvalue_get_attach(const icalvalue *value)
icalvalue * icalvalue_new_color(const char *v)
@ ICAL_CLASS_X
icalvalue * icalvalue_new_boolean(int v)
@ ICAL_PARTICIPANTTYPE_X
icalvalue * icalvalue_new_duration(struct icaldurationtype v)
icalvalue * icalvalue_new_attach(icalattach *attach)
icalvalue_kind
@ ICAL_STATUS_VALUE
@ ICAL_RESOURCETYPE_VALUE
@ ICAL_BOOLEAN_VALUE
@ ICAL_PROXIMITY_VALUE
@ ICAL_URI_VALUE
@ ICAL_CMD_VALUE
@ ICAL_RECUR_VALUE
@ ICAL_INTEGER_VALUE
@ ICAL_ACTION_VALUE
@ ICAL_UTCOFFSET_VALUE
@ ICAL_DATETIME_VALUE
@ ICAL_METHOD_VALUE
@ ICAL_XMLREFERENCE_VALUE
@ ICAL_TRIGGER_VALUE
@ ICAL_TRANSP_VALUE
@ ICAL_BINARY_VALUE
@ ICAL_DATETIMEPERIOD_VALUE
@ ICAL_ATTACH_VALUE
@ ICAL_FLOAT_VALUE
@ ICAL_QUERY_VALUE
@ ICAL_QUERYLEVEL_VALUE
@ ICAL_GEO_VALUE
@ ICAL_PERIOD_VALUE
@ ICAL_DATE_VALUE
@ ICAL_CALADDRESS_VALUE
@ ICAL_COLOR_VALUE
@ ICAL_X_VALUE
@ ICAL_POLLCOMPLETION_VALUE
@ ICAL_POLLMODE_VALUE
@ ICAL_TEXT_VALUE
@ ICAL_NO_VALUE
@ ICAL_DURATION_VALUE
@ ICAL_UID_VALUE
@ ICAL_REQUESTSTATUS_VALUE
@ ICAL_PARTICIPANTTYPE_VALUE
@ ICAL_BUSYTYPE_VALUE
@ ICAL_CLASS_VALUE
@ ICAL_STRING_VALUE
@ ICAL_CARLEVEL_VALUE
icalvalue * icalvalue_new_float(float v)
struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(const icalvalue *value)
icalvalue * icalvalue_new_string(const char *v)
enum icalproperty_method icalvalue_get_method(const icalvalue *value)
@ ICAL_PROXIMITY_X
struct icaldurationtype icalvalue_get_duration(const icalvalue *value)
@ ICAL_POLLMODE_X
icalvalue * icalvalue_new_recur(struct icalrecurrencetype *recur)
icalvalue * icalvalue_new_caladdress(const char *v)
icalvalue * icalvalue_new_datetime(struct icaltimetype v)
struct icalperiodtype icalvalue_get_period(const icalvalue *value)
struct icalgeotype icalvalue_get_geo(const icalvalue *value)
icalvalue * icalvalue_new_text(const char *v)
@ ICAL_TRANSP_X
int icalvalue_get_boolean(const icalvalue *value)
struct icalvalue_impl icalvalue
@ ICAL_POLLCOMPLETION_X
bool icaldurationtype_is_bad_duration(struct icaldurationtype d)
Checks if a duration is a bad duration.
char * icaldurationtype_as_ical_string_r(struct icaldurationtype d)
struct icaldurationtype icaldurationtype_from_string(const char *str)
Creates a new icaldurationtype from a duration given as a string.
enum icalrequeststatus kind
Definition icalenums.c:26
const char * str
Definition icalenums.c:29
@ ICAL_UNKNOWN_STATUS
Definition icalenums.h:80
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition icalerror.c:90
@ ICAL_NEWFAILED_ERROR
Definition icalerror.h:50
@ ICAL_BADARG_ERROR
Definition icalerror.h:47
@ ICAL_PARSE_ERROR
Definition icalerror.h:62
size_t icallimit_get(icallimits_kind kind)
Definition icallimits.c:29
Defines the interface for getting/setting internal library limits.
@ ICAL_LIMIT_VALUE_CHARS
Definition icallimits.h:34
void icalmemory_free_buffer(void *buf)
Releases a buffer.
Definition icalmemory.c:355
char * icalmemory_strdup(const char *s)
Creates a duplicate of a string.
Definition icalmemory.c:242
void icalmemory_append_string(char **buf, char **pos, size_t *buf_size, const char *string)
Appends a string to a buffer.
Definition icalmemory.c:365
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
Definition icalmemory.c:315
void icalmemory_append_char(char **buf, char **pos, size_t *buf_size, char ch)
Appends a character to a buffer.
Definition icalmemory.c:406
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Definition icalmemory.c:158
Common memory management routines.
char * icalperiodtype_as_ical_string_r(struct icalperiodtype p)
Converts an icalperiodtype into an iCal-formatted string.
Definition icalperiod.c:97
bool icalperiodtype_is_null_period(struct icalperiodtype p)
Definition icalperiod.c:138
struct icalperiodtype icalperiodtype_from_string(const char *str)
Constructs a new icalperiodtype from str.
Definition icalperiod.c:25
icalproperty_kind icalproperty_isa(const icalproperty *p)
bool icalproperty_get_allow_empty_properties(void)
char * icalproperty_enum_to_string_r(int e)
bool icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e)
icalproperty_kind icalproperty_value_kind_to_kind(icalvalue_kind kind)
int icalproperty_kind_and_string_to_enum(const int kind, const char *str)
struct icalrecurrencetype * icalrecurrencetype_new_from_string(const char *str)
Definition icalrecur.c:869
struct icalrecurrencetype * icalrecurrencetype_clone(struct icalrecurrencetype *recur)
Definition icalrecur.c:832
void icalrecurrencetype_unref(struct icalrecurrencetype *recur)
Definition icalrecur.c:790
char * icalrecurrencetype_as_string_r(struct icalrecurrencetype *recur)
Definition icalrecur.c:1069
bool icaltime_is_date(const struct icaltimetype t)
Definition icaltime.c:634
struct icaltimetype icaltime_from_string(const char *str)
Definition icaltime.c:379
bool icaltime_is_utc(const struct icaltimetype t)
Definition icaltime.c:639
bool icaltime_is_null_time(const struct icaltimetype t)
Definition icaltime.c:644
char * icaltime_as_ical_string_r(const struct icaltimetype tt)
Definition icaltime.c:346
Defines the data structure for representing date-times.
struct icaltriggertype icaltriggertype_from_string(const char *str)
Definition icaltypes.c:61
bool icaltriggertype_is_bad_trigger(struct icaltriggertype tr)
Definition icaltypes.c:42
struct icalreqstattype icalreqstattype_from_string(const char *str)
Definition icaltypes.c:99
char * icalreqstattype_as_string_r(struct icalreqstattype stat)
Definition icaltypes.c:165
#define ICAL_GEO_LEN
Definition icaltypes.h:35
icalproperty * icalvalue_get_parent(const icalvalue *value)
Definition icalvalue.c:1569
icalvalue_kind icalvalue_isa(const icalvalue *value)
Definition icalvalue.c:1345
bool icalvalue_is_valid(const icalvalue *value)
Definition icalvalue.c:891
bool icalvalue_isa_value(void *value)
Definition icalvalue.c:1354
icalvalue * icalvalue_clone(const icalvalue *old)
Definition icalvalue.c:66
icalvalue * icalvalue_new_from_string(icalvalue_kind kind, const char *str)
Definition icalvalue.c:809
void icalvalue_set_parent(icalvalue *value, icalproperty *property)
Definition icalvalue.c:1562
icalparameter_xliccomparetype icalvalue_compare(const icalvalue *a, const icalvalue *b)
Definition icalvalue.c:1374
icalvalue * icalvalue_new(icalvalue_kind kind)
Definition icalvalue.c:61
bool icalvalue_decode_ical_string(const char *szText, char *szDecText, int maxBufferLen)
Definition icalvalue.c:1608
void icalvalue_reset_kind(icalvalue *value)
Definition icalvalue.c:1549
void icalvalue_free(icalvalue *v)
Definition icalvalue.c:814
char * icalvalue_as_ical_string_r(const icalvalue *value)
Definition icalvalue.c:1244
bool icalvalue_encode_ical_string(const char *szText, char *szEncText, int maxBufferLen)
Definition icalvalue.c:1574
const char * icalvalue_as_ical_string(const icalvalue *value)
Definition icalvalue.c:1235
Defines the data structure representing iCalendar parameter values.
bool icalvalue_kind_is_valid(const icalvalue_kind kind)
const char * icalvalue_kind_to_string(const icalvalue_kind kind)
struct icaltimetype time
Definition icaltypes.h:30
struct icalperiodtype period
Definition icaltypes.h:31
unsigned int weeks
unsigned int hours
unsigned int seconds
unsigned int days
unsigned int minutes
char lat[16]
Definition icaltypes.h:40
char lon[16]
Definition icaltypes.h:41
icalrequeststatus code
Definition icaltypes.h:111
#define MAX_INT_DIGITS
Definition vcardvalue.c:666
#define TMP_BUF_SIZE
Definition vcardvalue.c:30