Libical API Documentation 4.0 STABLE VERSION [Visit the v3.0 documentation]
Loading...
Searching...
No Matches
vcardvalue.c
Go to the documentation of this file.
1/*======================================================================
2 FILE: vcardvalue.c
3 CREATOR: Ken Murchison 24 Aug 2022
4
5 SPDX-FileCopyrightText: 2022, Fastmail Pty. Ltd. (https://fastmail.com)
6 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
7 ======================================================================*/
8
13
14#ifdef HAVE_CONFIG_H
15#include <config.h>
16#endif
17
18#include "vcardvalue.h"
19#include "vcardvalueimpl.h"
20#include "vcardcomponent.h"
21#include "vcardproperty.h"
22#include "vcardtextlist.h"
23#include "icalerror_p.h"
24#include "icalmemory.h"
25
26#include <ctype.h>
27#include <locale.h>
28#include <stdlib.h>
29
30#define TMP_BUF_SIZE 1024
31
32LIBICAL_VCARD_EXPORT struct vcardvalue_impl *vcardvalue_new_impl(vcardvalue_kind kind)
33{
34 struct vcardvalue_impl *v;
35
37 return NULL;
38 }
39
40 if ((v = (struct vcardvalue_impl *)icalmemory_new_buffer(sizeof(struct vcardvalue_impl))) == 0) {
42 return 0;
43 }
44
45 v->id = ICAL_STRUCTURE_TYPE_VALUE;
46 v->kind = kind;
47 v->size = 0;
48 v->parent = 0;
49 v->x_value = 0;
50 memset(&(v->data), 0, sizeof(v->data));
51
52 return v;
53}
54
59
61{
62 struct vcardvalue_impl *clone;
63
64 clone = vcardvalue_new_impl(old->kind);
65
66 if (clone == 0) {
67 return 0;
68 }
69
70 clone->id = old->id;
71 clone->kind = old->kind;
72 clone->size = old->size;
73
74 switch (clone->kind) {
76 case VCARD_URI_VALUE:
78 if (old->data.v_string != 0) {
79 clone->data.v_string = icalmemory_strdup(old->data.v_string);
80
81 if (clone->data.v_string == 0) {
82 clone->parent = 0;
83 vcardvalue_free(clone);
84 return 0;
85 }
86 }
87 break;
88 }
89 case VCARD_X_VALUE: {
90 if (old->x_value != 0) {
91 clone->x_value = icalmemory_strdup(old->x_value);
92
93 if (clone->x_value == 0) {
94 clone->parent = 0;
95 vcardvalue_free(clone);
96 return 0;
97 }
98 }
99
100 break;
101 }
102
104 if (old->data.v_structured != 0) {
105 clone->data.v_structured =
106 vcardstructured_clone(old->data.v_structured);
107 }
108 break;
109
110 default: {
111 /* all of the other types are stored as values, not
112 pointers, so we can just copy the whole structure. */
113
114 clone->data = old->data;
115 }
116 }
117
118 return clone;
119}
120
121char *vcardvalue_strdup_and_dequote_text(const char **str, const char *sep)
122{
123 const char *p;
124 char *out = (char *)icalmemory_new_buffer(sizeof(char) * strlen(*str) + 1);
125 char *pout;
126
127 if (out == 0) {
128 return 0;
129 }
130
131 pout = out;
132
133 /* Stop the loop when encountering a terminator/separator in the source string
134 or if a null has been written to the destination. This prevents
135 reading past the end of the source string if the last character
136 is a backslash. */
137 for (p = *str; *p != 0; p++) {
138 if (*p == '\\') {
139 p++;
140 switch (*p) {
141 case 0: {
142 p--; // step back to NUL to stop iteration
143 *pout = '\0';
144 break;
145 }
146 case 'n':
147 case 'N': {
148 *pout = '\n';
149 break;
150 }
151 case 't':
152 case 'T': {
153 *pout = '\t';
154 break;
155 }
156 case 'r':
157 case 'R': {
158 *pout = '\r';
159 break;
160 }
161 case 'b':
162 case 'B': {
163 *pout = '\b';
164 break;
165 }
166 case 'f':
167 case 'F': {
168 *pout = '\f';
169 break;
170 }
171 case ';':
172 case ',':
173 case '"':
174 case '\\': {
175 *pout = *p;
176 break;
177 }
178 default: {
179 *pout = ' ';
180 }
181 }
182 } else if (sep && strchr(sep, *p)) {
183 break;
184 } else {
185 *pout = *p;
186 }
187
188 pout++;
189 }
190
191 *str = p;
192
193 *pout = '\0';
194
195 return out;
196}
197
198/*
199 * Returns a quoted copy of a string
200 * @todo This is not RFC5545 compliant.
201 * RFC 6350 allows:
202 * TEXT-CHAR = "\\" / "\," / "\n" / WSP / NON-ASCII / %x21-2B / %x2D-5B / %x5D-7E
203 * but we use the more restrictive (for ADR and N):
204 * component = "\\" / "\," / "\;" / "\n" / WSP / NON-ASCII /
205 %x21-2B / %x2D-3A / %x3C-5B / %x5D-7E
206 * As such, \b, \f, \r are not allowed, not even escaped
207 */
208static char *vcardmemory_strdup_and_quote(char **str, char **str_p, size_t *buf_sz,
209 const char *unquoted_str, bool is_param)
210{
211 const char *p;
212
213 if (!*str) {
214 *buf_sz = strlen(unquoted_str) + 1;
215
216 *str_p = *str = (char *)icalmemory_new_buffer(*buf_sz);
217 }
218
219 /* cppcheck-suppress uninitvar */
220 if (*str_p == 0) {
221 return 0;
222 }
223
224 for (p = unquoted_str; *p != 0; p++) {
225 switch (*p) {
226 case '\b':
227 case '\f':
228 case '\r':
229 /* ignore */
230 break;
231
232 case '\\':
233 case ',':
234 case ';':
235 /* escape */
236 icalmemory_append_char(str, str_p, buf_sz, '\\');
237 icalmemory_append_char(str, str_p, buf_sz, *p);
238 break;
239
240 case '\n':
241 /* If encoding a parameter value, embed literally
242 (parameter encoding is done elsewhere), otherwise escape */
243 icalmemory_append_string(str, str_p, buf_sz, is_param ? "\n" : "\\n"); //NOLINT
244 break;
245
246 default:
247 icalmemory_append_char(str, str_p, buf_sz, *p);
248 break;
249 }
250 }
251
252 /* Assume the last character is not a '\0' and add one. We could
253 check *str_p != 0, but that would be an uninitialized memory
254 read. */
255
256 icalmemory_append_char(str, str_p, buf_sz, '\0');
257 return *str;
258}
259
260/*
261 * FIXME
262 *
263 * This is a bad API, as it forces callers to specify their own X type.
264 * This function should take care of this by itself.
265 */
266static vcardvalue *vcardvalue_new_enum(vcardvalue_kind kind, int x_type, const char *str)
267{
269 struct vcardvalue_impl *value;
270
272 value = vcardvalue_new_impl(kind);
273 value->data.v_enum = e;
274 } else {
275 /* Make it an X value */
276 value = vcardvalue_new_impl(kind);
277 value->data.v_enum = x_type;
278 vcardvalue_set_x(value, str);
279 }
280
281 return value;
282}
283
290static bool simple_str_to_doublestr(const char *from, char *result, int result_len, char **to)
291{
292 const char *start = NULL;
293 char *end = NULL, *cur = (char *)from;
294
295 struct lconv *loc_data = localeconv();
296 int i = 0, len;
297 double dtest;
298
299 /*sanity checks */
300 if (!from || !result) {
301 return true;
302 }
303
304 /*skip the white spaces at the beginning */
305 while (*cur && isspace((int)*cur)) {
306 cur++;
307 }
308
309 start = cur;
310 /* copy the part that looks like a double into result.
311 * during the copy, we give ourselves a chance to convert the '.'
312 * into the decimal separator of the current locale.
313 */
314 while (*cur && (isdigit((int)*cur) || *cur == '.' || *cur == '+' || *cur == '-')) {
315 ++cur;
316 }
317 end = cur;
318 len = (int)(ptrdiff_t)(end - start);
319 if (len + 1 >= result_len) {
320 /* huh hoh, number is too big. truncate it */
321 len = result_len - 1;
322 }
323
324 /* copy the float number string into result, and take
325 * care to have the (optional) decimal separator be the one
326 * of the current locale.
327 */
328 for (i = 0; i < len; ++i) {
329 if (start[i] == '.' &&
330 loc_data && loc_data->decimal_point && loc_data->decimal_point[0] && loc_data->decimal_point[0] != '.') {
331 /*replace '.' by the digit separator of the current locale */
332 result[i] = loc_data->decimal_point[0];
333 } else {
334 result[i] = start[i];
335 }
336 }
337 if (to) {
338 *to = end;
339 }
340
341 //NOLINTBEGIN(bugprone-unchecked-string-to-number-conversion)
342 /* now try to convert to a floating point number, to check for validity only */
343 if (sscanf(result, "%lf", &dtest) != 1) {
344 return true;
345 }
346 //NOLINTEND(bugprone-unchecked-string-to-number-conversion)
347 return false;
348}
349
350static vcardvalue *vcardvalue_new_from_string_with_error(vcardvalue_kind kind,
351 const char *str,
352 vcardproperty **error)
353{
354 struct vcardvalue_impl *value = 0;
355
356 icalerror_check_arg_rz(str != 0, "str");
357
358 if (error != 0) {
359 *error = 0;
360 }
361
362 switch (kind) {
363 case VCARD_BOOLEAN_VALUE: {
364 if (!strcmp(str, "TRUE")) {
365 value = vcardvalue_new_boolean(1);
366 } else if (!strcmp(str, "FALSE")) {
367 value = vcardvalue_new_boolean(0);
368 } else if (error != 0) {
369 char temp[TMP_BUF_SIZE];
370 vcardparameter *errParam;
371
372 snprintf(temp, sizeof(temp),
373 "Could not parse %s as a %s property",
376 *error = vcardproperty_vanew_xlicerror(temp, errParam, (void *)0);
377 }
378 break;
379 }
380
382 value = vcardvalue_new_enum(kind, (int)VCARD_VERSION_X, str);
383 break;
384
385 case VCARD_KIND_VALUE:
386 value = vcardvalue_new_enum(kind, (int)VCARD_KIND_X, str);
387 break;
388
390 value = vcardvalue_new_enum(kind, (int)VCARD_GRAMGENDER_X, str);
391 break;
392
393 case VCARD_INTEGER_VALUE: {
394 char *s_end;
395 const int v = strtol(str, &s_end, 10);
396 if (str != s_end) {
397 value = vcardvalue_new_integer(v);
398 }
399 break;
400 }
401
402 case VCARD_FLOAT_VALUE: {
403 char *s_end;
404 const float v = strtof(str, &s_end);
405 if (str != s_end) {
406 value = vcardvalue_new_float(v);
407 }
408 break;
409 }
410
412#pragma GCC diagnostic push
413#pragma GCC diagnostic ignored "-Wformat-nonliteral"
414 // NOLINTBEGIN(bugprone-unchecked-string-to-number-conversion)
415 /* "+" / "-" hh [ [":"] mm ] */
416 char sign[2] = "";
417 unsigned hour, min = 0;
418 int nchar = 0, len = (int)strlen(str);
419
420 if (len > 3) {
421 const char *fmt;
422
423 if (str[3] == ':') {
424 fmt = "%1[+-]%02u:%02u%n";
425 } else {
426 fmt = "%1[+-]%02u%02u%n";
427 }
428
429 if (3 != sscanf(str, fmt, sign, &hour, &min, &nchar)) {
430 nchar = 0;
431 }
432 } else if (2 != sscanf(str, "%1[+-]%02u%n", sign, &hour, &nchar)) {
433 nchar = 0;
434 }
435// NOLINTEND(bugprone-unchecked-string-to-number-conversion)
436#pragma GCC diagnostic pop
437
438 if (len && (len == nchar)) {
439 int utcoffset = (int)(hour * 3600 + min * 60);
440
441 if (*sign == '-') {
442 utcoffset = -utcoffset;
443 }
444 value = vcardvalue_new_utcoffset(utcoffset);
445 } else if (error != 0) {
446 char temp[TMP_BUF_SIZE];
447 vcardparameter *errParam;
448
449 snprintf(temp, sizeof(temp),
450 "Could not parse %s as a %s property",
453 *error = vcardproperty_vanew_xlicerror(temp, errParam, (void *)0);
454 }
455 break;
456 }
457
458 case VCARD_TEXT_VALUE: {
459 char *dequoted_str = vcardvalue_strdup_and_dequote_text(&str, NULL);
460
461 value = vcardvalue_new_text(dequoted_str);
462 icalmemory_free_buffer(dequoted_str);
463 break;
464 }
465
468 break;
469 }
470
473 value = vcardvalue_new_structured(st);
475 break;
476 }
477
478 case VCARD_GEO_VALUE: {
479 char *cur = NULL;
480 struct vcardgeotype geo = {0};
481 memset(geo.coords.lat, 0, VCARD_GEO_LEN);
482 memset(geo.coords.lon, 0, VCARD_GEO_LEN);
483
484 if (simple_str_to_doublestr(str, geo.coords.lat, VCARD_GEO_LEN, &cur)) {
485 goto geo_parsing_error;
486 }
487 /* skip white spaces */
488 while (cur && isspace((int)*cur)) {
489 ++cur;
490 }
491
492 /*there is a ';' between the latitude and longitude parts */
493 if (!cur || *cur != ';') {
494 goto geo_parsing_error;
495 }
496
497 ++cur;
498
499 /* skip white spaces */
500 while (cur && isspace((int)*cur)) {
501 ++cur;
502 }
503
504 if (simple_str_to_doublestr(cur, geo.coords.lon, VCARD_GEO_LEN, &cur)) {
505 goto geo_parsing_error;
506 }
507 value = vcardvalue_new_geo(geo);
508 break;
509
510 geo_parsing_error:
511 if (error != 0) {
512 char temp[TMP_BUF_SIZE];
513 snprintf(temp, sizeof(temp),
514 "Could not parse %s as a %s value",
516 vcardparameter *errParam =
518 *error = vcardproperty_vanew_xlicerror(temp, errParam, (void *)0);
519 }
520 } break;
521
522 case VCARD_URI_VALUE:
523 value = vcardvalue_new_uri(str);
524 break;
525
526 case VCARD_DATE_VALUE:
527 case VCARD_TIME_VALUE:
531 struct vcardtimetype tt;
532
535 value = vcardvalue_new_impl(kind);
536 value->data.v_time = tt;
537
539 }
540 break;
541 }
542
545 break;
546
547 case VCARD_X_VALUE: {
548 value = vcardvalue_new_x(str);
549 } break;
550
551 default: {
552 char temp[TMP_BUF_SIZE];
553 if (error != 0) {
554 snprintf(temp, TMP_BUF_SIZE, "Unknown type for \'%s\'", str);
556 *error = vcardproperty_vanew_xlicerror(temp, errParam, (void *)0);
557 }
558
559 snprintf(temp, TMP_BUF_SIZE,
560 "vcardvalue_new_from_string got an unknown value type (%s) for \'%s\'",
562 icalerror_warn(temp);
563 value = 0;
564 }
565 }
566
567 if (error != 0 && *error == 0 && value == 0) {
568 char temp[TMP_BUF_SIZE];
569 vcardparameter *errParam;
570
571 snprintf(temp, TMP_BUF_SIZE, "Failed to parse value: \'%s\'", str);
572
573 /* coverity[resource_leak] */
575 *error = vcardproperty_vanew_xlicerror(temp, errParam, (void *)0);
576 }
577
578 return value;
579}
580
582{
583 return vcardvalue_new_from_string_with_error(kind, str, (vcardproperty **)0);
584}
585
587{
588 icalerror_check_arg_rv((v != 0), "value");
589
590 if (v->parent != 0) {
591 return;
592 }
593
594 if (v->x_value != 0) {
595 icalmemory_free_buffer(v->x_value);
596 }
597
598 switch (v->kind) {
599 case VCARD_TEXT_VALUE:
600 case VCARD_URI_VALUE:
602 if (v->data.v_string != 0) {
603 icalmemory_free_buffer((void *)v->data.v_string);
604 v->data.v_string = 0;
605 }
606 break;
607 }
608
610 if (v->data.v_textlist != 0) {
611 vcardstrarray_free(v->data.v_textlist);
612 }
613 v->data.v_textlist = 0;
614 break;
615 }
616
618 vcardstructured_unref(v->data.v_structured);
619 v->data.v_structured = 0;
620 break;
621 }
622
623 case VCARD_GEO_VALUE: {
624 v->data.v_geo.coords.lat[0] = '\0';
625 v->data.v_geo.coords.lon[0] = '\0';
626 break;
627 }
628
629 default: {
630 /* Nothing to do */
631 }
632 }
633
634 v->kind = VCARD_NO_VALUE;
635 v->size = 0;
636 v->parent = 0;
637 memset(&(v->data), 0, sizeof(v->data));
638 v->id = ICAL_STRUCTURE_TYPE_VALUE_EMPTY;
640}
641
643{
644 if (value == 0) {
645 return false;
646 }
647
648 return true;
649}
650
651static char *vcardvalue_boolean_as_vcard_string_r(const vcardvalue *value)
652{
653 int data;
654 char *str;
655
656 icalerror_check_arg_rz((value != 0), "value");
657 str = (char *)icalmemory_new_buffer(6);
658
659 data = vcardvalue_get_integer(value);
660
661 strncpy(str, data ? "TRUE" : "FALSE", 6);
662
663 return str;
664}
665
666#define MAX_INT_DIGITS 12 /* Enough for 2^32 + sign */
667
668static char *vcardvalue_int_as_vcard_string_r(const vcardvalue *value)
669{
670 int data;
671 char *str;
672
673 icalerror_check_arg_rz((value != 0), "value");
675
676 data = vcardvalue_get_integer(value);
677
678 snprintf(str, MAX_INT_DIGITS, "%d", data);
679
680 return str;
681}
682
683static char *vcardvalue_utcoffset_as_vcard_string_r(const vcardvalue *value,
684 vcardproperty_version version)
685{
686 int data, h, m, s;
687 char sign;
688 char *str;
689 size_t size = 10;
690 const char *fmt;
691
692 icalerror_check_arg_rz((value != 0), "value");
693
694 str = (char *)icalmemory_new_buffer(size);
695 data = vcardvalue_get_utcoffset(value);
696
697 if (abs(data) == data) {
698 sign = '+';
699 } else {
700 sign = '-';
701 }
702
703 h = data / 3600;
704 m = (data - (h * 3600)) / 60;
705 s = (data - (h * 3600) - (m * 60));
706
707 h = MIN(abs(h), 23);
708 m = MIN(abs(m), 59);
709 s = MIN(abs(s), 59);
710#pragma GCC diagnostic push
711#pragma GCC diagnostic ignored "-Wformat-nonliteral"
712 if (s != 0) {
713 if (version == VCARD_VERSION_40) {
714 fmt = "%c%02d%02d%02d";
715 } else {
716 fmt = "%c%02d:%02d:%02d";
717 }
718 } else if (version == VCARD_VERSION_40) {
719 if (m != 0) {
720 fmt = "%c%02d%02d";
721 } else {
722 fmt = "%c%02d";
723 }
724 } else {
725 fmt = "%c%02d:%02d";
726 }
727
728 snprintf(str, size, fmt, sign, h, m, s);
729#pragma GCC diagnostic pop
730 return str;
731}
732
733static char *vcardvalue_text_as_vcard_string_r(const vcardvalue *value)
734{
735 char *str = NULL;
736 char *str_p = NULL;
737 size_t buf_sz;
738
739 return vcardmemory_strdup_and_quote(&str, &str_p, &buf_sz,
740 value->data.v_string, false);
741}
742
743static char *vcardvalue_string_as_vcard_string_r(const vcardvalue *value)
744{
745 const char *data;
746 char *str = 0;
747
748 icalerror_check_arg_rz((value != 0), "value");
749 data = value->data.v_string;
750
751 const size_t len_data = strlen(data) + 1;
752 str = (char *)icalmemory_new_buffer(len_data);
753
754 strncpy(str, data, len_data);
755 str[len_data - 1] = '\0';
756
757 return str;
758}
759
760static void _vcardstrarray_as_vcard_string_r(char **str, char **str_p, size_t *buf_sz,
761 vcardstrarray *array, const char sep,
762 bool is_param)
763{
764 if (!vcardstrarray_size(array)) {
765 (void)vcardmemory_strdup_and_quote(str, str_p, buf_sz, "", is_param);
766 return;
767 }
768
769 size_t i;
770
771 for (i = 0; i < vcardstrarray_size(array); i++) {
772 if (i) {
773 *str_p -= 1; // backup to \0
774 icalmemory_append_char(str, str_p, buf_sz, sep);
775 }
776
777 (void)vcardmemory_strdup_and_quote(str, str_p, buf_sz,
778 vcardstrarray_element_at(array, i), is_param);
779 }
780}
781
782char *vcardstrarray_as_vcard_string_r(const vcardstrarray *array, const char sep)
783{
784 char *buf = NULL;
785 char *buf_ptr = NULL;
786 size_t buf_size;
787
788 _vcardstrarray_as_vcard_string_r(&buf, &buf_ptr, &buf_size,
789 (vcardstrarray *)array, sep, false);
790
791 return buf;
792}
793
795{
796 char *buf;
797 char *buf_ptr;
798 size_t buf_size = 1;
799 size_t i;
800
801 buf_ptr = buf = (char *)icalmemory_new_buffer(buf_size);
802
803 for (i = 0; i < vcardstructured_num_fields(st); i++) {
805
806 if (i) {
807 if (buf_ptr > buf) {
808 buf_ptr -= 1; // backup to \0
809 }
810 icalmemory_append_char(&buf, &buf_ptr, &buf_size, ';');
811 }
812
813 if (array) {
814 _vcardstrarray_as_vcard_string_r(&buf, &buf_ptr, &buf_size,
815 array, ',', is_param);
816 } else {
817 icalmemory_append_char(&buf, &buf_ptr, &buf_size, '\0');
818 }
819 }
820
821 return buf;
822}
823
824static char *vcardvalue_textlist_as_vcard_string_r(const vcardvalue *value,
825 const char sep)
826{
827 icalerror_check_arg_rz((value != 0), "value");
828
829 return vcardstrarray_as_vcard_string_r(value->data.v_textlist, sep);
830}
831
832static char *vcardvalue_structured_as_vcard_string_r(const vcardvalue *value)
833{
834 icalerror_check_arg_rz((value != 0), "value");
835
836 return vcardstructured_as_vcard_string_r(value->data.v_structured, false);
837}
838
839static char *vcardvalue_float_as_vcard_string_r(const vcardvalue *value)
840{
841 float data;
842 char *str;
843 char *old_locale;
844
845 icalerror_check_arg_rz((value != 0), "value");
846 data = vcardvalue_get_float(value);
847
848 /* bypass current locale in order to make
849 sure snprintf uses a '.' as a separator
850 set locate to 'C' and keep old locale */
851 old_locale = icalmemory_strdup(setlocale(LC_NUMERIC, NULL));
852 (void)setlocale(LC_NUMERIC, "C");
853
854 str = (char *)icalmemory_new_buffer(40);
855
856 snprintf(str, 40, "%f", data);
857
858 /* restore saved locale */
859 (void)setlocale(LC_NUMERIC, old_locale);
860 icalmemory_free_buffer(old_locale);
861
862 return str;
863}
864
865static char *vcardvalue_geo_as_vcard_string_r(const vcardvalue *value)
866{
867 icalerror_check_arg_rz((value != 0), "value");
868 size_t max_len = 2 * VCARD_GEO_LEN;
869 char *str = (char *)icalmemory_new_buffer(max_len);
870 snprintf(str, max_len, "%s;%s",
871 value->data.v_geo.coords.lat, value->data.v_geo.coords.lon);
872 str[max_len - 1] = '\0';
873 return str;
874}
875
876const char *vcardvalue_as_vcard_string(const vcardvalue *value)
877{
878 char *buf;
879
880 buf = vcardvalue_as_vcard_string_r(value);
882 return buf;
883}
884
886{
888 bool is_structured;
889 unsigned flags = 0;
890
891 if (value == 0) {
892 return 0;
893 }
894
895 if (value->parent) {
896 vcardcomponent *comp = vcardproperty_get_parent(value->parent);
897 if (comp) {
898 version = vcardcomponent_get_version(comp);
899 }
900 }
901
902 if (version == VCARD_VERSION_NONE) {
903 version = VCARD_VERSION_30;
904 }
905
906 is_structured = vcardproperty_is_structured(vcardproperty_isa(value->parent));
907
908 switch (value->kind) {
910 return vcardvalue_boolean_as_vcard_string_r(value);
911
913 return vcardvalue_int_as_vcard_string_r(value);
914
916 return vcardvalue_utcoffset_as_vcard_string_r(value, version);
917
918 case VCARD_TEXT_VALUE:
919 return vcardvalue_text_as_vcard_string_r(value);
920
922 return vcardvalue_textlist_as_vcard_string_r(value,
923 is_structured ? ';' : ','); //NOLINT
924
926 return vcardvalue_structured_as_vcard_string_r(value);
927
928 case VCARD_GEO_VALUE:
929 return vcardvalue_geo_as_vcard_string_r(value);
930
931 case VCARD_URI_VALUE:
933 return vcardvalue_string_as_vcard_string_r(value);
934
935 case VCARD_TIME_VALUE:
936 flags |= VCARDTIME_BARE_TIME;
937 _fallthrough();
938
939 case VCARD_DATE_VALUE:
940 _fallthrough();
941
943 _fallthrough();
944
946 _fallthrough();
947
949 if (version == VCARD_VERSION_40) {
950 flags |= VCARDTIME_AS_V4;
951 }
952
953 return vcardtime_as_vcard_string_r(value->data.v_time, flags);
954
956 return vcardvalue_float_as_vcard_string_r(value);
957
958 case VCARD_KIND_VALUE:
961 if (value->x_value != 0) {
962 return icalmemory_strdup(value->x_value);
963 }
964
965 return vcardproperty_enum_to_string_r(value->data.v_enum);
966
967 case VCARD_X_VALUE:
968 if (value->x_value != 0) {
969 return icalmemory_strdup(value->x_value);
970 }
971 _fallthrough();
972
973 case VCARD_NO_VALUE:
974 _fallthrough();
975
976 default: {
977 return 0;
978 }
979 }
980}
981
983{
984 if (value == 0) {
985 return VCARD_NO_VALUE;
986 }
987
988 return value->kind;
989}
990
991bool vcardvalue_isa_value(void *value)
992{
993 const struct vcardvalue_impl *impl = (struct vcardvalue_impl *)value;
994
995 icalerror_check_arg_rz((value != 0), "value");
996
997 return (impl->id == ICAL_STRUCTURE_TYPE_VALUE);
998}
999
1003
1005{
1006 if (!value) {
1007 return;
1008 }
1009 switch (value->kind) {
1010 case VCARD_DATE_VALUE:
1011 case VCARD_TIME_VALUE:
1015 if (vcardtime_is_timestamp(value->data.v_time)) {
1016 value->kind = VCARD_TIMESTAMP_VALUE;
1017 } else if (vcardtime_is_time(value->data.v_time)) {
1018 value->kind = VCARD_TIME_VALUE;
1019 } else if (vcardtime_is_date(value->data.v_time)) {
1020 value->kind = VCARD_DATE_VALUE;
1021 } else {
1022 value->kind = VCARD_DATETIME_VALUE;
1023 }
1024 break;
1025
1026 default:
1027 break;
1028 }
1029}
1030
1031void vcardvalue_set_parent(vcardvalue *value, vcardproperty *property)
1032{
1033 icalerror_check_arg_rv((value != 0), "value");
1034
1035 value->parent = property;
1036}
1037
1038vcardproperty *vcardvalue_get_parent(const vcardvalue *value)
1039{
1040 return value->parent;
1041}
1042
1043/* The remaining interfaces are 'new', 'set' and 'get' for each of the value
1044 types */
enum icalrequeststatus kind
Definition icalenums.c:26
const char * str
Definition icalenums.c:29
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition icalerror.c:90
@ ICAL_NEWFAILED_ERROR
Definition icalerror.h:50
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 lon[16]
Definition vcardtypes.h:25
struct vcardgeotype::@162201204342263205067330224176321027032342016274 coords
char lat[16]
Definition vcardtypes.h:24
enum vcardproperty_version vcardcomponent_get_version(vcardcomponent *comp)
Defines the data structure representing vCard components.
vcardcomponent * vcardproperty_get_parent(const vcardproperty *property)
Returns the parent vcard for the specified property.
struct vcardparameter_impl vcardparameter
vcardparameter * vcardparameter_new_xlicerrortype(vcardparameter_xlicerrortype v)
@ VCARD_XLICERRORTYPE_VALUEPARSEERROR
vcardproperty * vcardproperty_vanew_xlicerror(const char *v,...)
vcardvalue * vcardvalue_new_textlist(vcardstrarray *v)
struct vcardvalue_impl vcardvalue
vcardvalue * vcardvalue_new_geo(vcardgeotype v)
int vcardvalue_get_utcoffset(const vcardvalue *value)
vcardvalue * vcardvalue_new_integer(int v)
@ VCARD_KIND_X
vcardvalue * vcardvalue_new_x(const char *v)
vcardvalue * vcardvalue_new_languagetag(const char *v)
int vcardvalue_get_integer(const vcardvalue *value)
void vcardvalue_set_x(vcardvalue *value, const char *v)
vcardvalue * vcardvalue_new_float(float v)
vcardvalue * vcardvalue_new_uri(const char *v)
float vcardvalue_get_float(const vcardvalue *value)
vcardproperty_version
@ VCARD_VERSION_30
@ VCARD_VERSION_40
@ VCARD_VERSION_NONE
@ VCARD_VERSION_X
vcardvalue * vcardvalue_new_structured(vcardstructuredtype *v)
vcardvalue_kind
@ VCARD_INTEGER_VALUE
@ VCARD_TIMESTAMP_VALUE
@ VCARD_URI_VALUE
@ VCARD_VERSION_VALUE
@ VCARD_TEXTLIST_VALUE
@ VCARD_BOOLEAN_VALUE
@ VCARD_KIND_VALUE
@ VCARD_X_VALUE
@ VCARD_DATETIME_VALUE
@ VCARD_GRAMGENDER_VALUE
@ VCARD_GEO_VALUE
@ VCARD_UTCOFFSET_VALUE
@ VCARD_DATE_VALUE
@ VCARD_FLOAT_VALUE
@ VCARD_DATEANDORTIME_VALUE
@ VCARD_STRUCTURED_VALUE
@ VCARD_LANGUAGETAG_VALUE
@ VCARD_NO_VALUE
@ VCARD_TEXT_VALUE
@ VCARD_TIME_VALUE
vcardvalue * vcardvalue_new_text(const char *v)
vcardvalue * vcardvalue_new_utcoffset(int v)
vcardvalue * vcardvalue_new_boolean(int v)
@ VCARD_GRAMGENDER_X
vcardproperty_kind vcardproperty_isa(const vcardproperty *p)
Defines the data structure representing vCard properties.
vcardproperty_kind vcardproperty_value_kind_to_kind(vcardvalue_kind kind)
char * vcardproperty_enum_to_string_r(int e)
int vcardproperty_kind_and_string_to_enum(const int kind, const char *str)
bool vcardproperty_enum_belongs_to_property(vcardproperty_kind kind, int e)
bool vcardproperty_is_structured(vcardproperty_kind pkind)
#define vcardstrarray_size(array)
#define vcardstrarray_free(array)
#define vcardstrarray_element_at(array, position)
icalstrarray vcardstrarray
vcardstrarray * vcardstructured_field_at(const vcardstructuredtype *st, size_t position)
Returns the field at the given position in a vcardstructuredtype.
vcardstructuredtype * vcardstructured_new_from_string(const char *str)
Creates a new instance of vcardstructuredtype from a string.
vcardstructuredtype * vcardstructured_clone(const vcardstructuredtype *st)
Clones a vcardstructuredtype.
void vcardstructured_unref(vcardstructuredtype *st)
Decrements the reference count of the vcardstructuredtype.
size_t vcardstructured_num_fields(const vcardstructuredtype *st)
Returns the number of fields in a vcardstructuredtype.
struct vcardstructuredtype_impl vcardstructuredtype
Represents a decoded, structured text value.
vcardstrarray * vcardtextlist_new_from_string(const char *str, char sep)
Defines functions for creating vCard text lists.
bool vcardtime_is_timestamp(const vcardtimetype t)
Definition vcardtime.c:79
bool vcardtime_is_date(const vcardtimetype t)
Definition vcardtime.c:64
vcardtimetype vcardtime_from_string(const char *str, int is_bare_time)
Definition vcardtime.c:490
bool vcardtime_is_null_datetime(const vcardtimetype t)
Definition vcardtime.c:69
bool vcardtime_is_time(const vcardtimetype t)
Definition vcardtime.c:59
char * vcardtime_as_vcard_string_r(const vcardtimetype t, unsigned flags)
Definition vcardtime.c:266
#define VCARDTIME_BARE_TIME
Definition vcardtime.h:48
#define VCARDTIME_AS_V4
Definition vcardtime.h:49
#define VCARD_GEO_LEN
Definition vcardtypes.h:19
vcardvalue * vcardvalue_new_from_string(vcardvalue_kind kind, const char *str)
Definition vcardvalue.c:581
const char * vcardvalue_as_vcard_string(const vcardvalue *value)
Definition vcardvalue.c:876
bool vcardvalue_isa_value(void *value)
Definition vcardvalue.c:991
#define MAX_INT_DIGITS
Definition vcardvalue.c:666
vcardproperty * vcardvalue_get_parent(const vcardvalue *value)
#define TMP_BUF_SIZE
Definition vcardvalue.c:30
char * vcardvalue_strdup_and_dequote_text(const char **str, const char *sep)
Definition vcardvalue.c:121
struct vcardvalue_impl * vcardvalue_new_impl(vcardvalue_kind kind)
Definition vcardvalue.c:32
vcardvalue_kind vcardvalue_isa(const vcardvalue *value)
Definition vcardvalue.c:982
char * vcardvalue_as_vcard_string_r(const vcardvalue *value)
Definition vcardvalue.c:885
void vcardvalue_set_parent(vcardvalue *value, vcardproperty *property)
vcardvalue * vcardvalue_clone(const vcardvalue *old)
Definition vcardvalue.c:60
void vcardvalue_reset_kind(vcardvalue *value)
bool vcardvalue_is_valid(const vcardvalue *value)
Definition vcardvalue.c:642
char * vcardstrarray_as_vcard_string_r(const vcardstrarray *array, const char sep)
Definition vcardvalue.c:782
vcardvalue * vcardvalue_new(vcardvalue_kind kind)
Definition vcardvalue.c:55
char * vcardstructured_as_vcard_string_r(const vcardstructuredtype *st, bool is_param)
Formats a vcardstructuredtype as a vCard property or parameter value.
Definition vcardvalue.c:794
void vcardvalue_free(vcardvalue *v)
Definition vcardvalue.c:586
Defines the data structure representing vCard values.
const char * vcardvalue_kind_to_string(const vcardvalue_kind kind)
bool vcardvalue_kind_is_valid(const vcardvalue_kind kind)