18#include "vcardproperty_p.h"
22#include "icalerror_p.h"
29struct vcardproperty_impl {
31 vcardproperty_kind kind;
34 icalpvl_list parameters;
35 icalpvl_elem parameter_iterator;
37 vcardcomponent *parent;
40LIBICAL_VCARD_EXPORT
struct vcardproperty_impl *vcardproperty_new_impl(vcardproperty_kind kind)
53 memset(prop, 0,
sizeof(vcardproperty));
55 strcpy(prop->id,
"prop");
58 prop->parameters = icalpvl_newlist();
63void vcardproperty_add_parameters(vcardproperty *prop, va_list args)
67 while ((vp = va_arg(args,
void *)) != 0) {
68 if (vcardvalue_isa_value(vp) != 0) {
70 vcardproperty_add_parameter((vcardproperty *)prop,
71 (vcardparameter *)vp);
78vcardproperty *vcardproperty_new(vcardproperty_kind kind)
80 if (kind == VCARD_NO_PROPERTY) {
84 return (vcardproperty *)vcardproperty_new_impl(kind);
92 icalerror_check_arg_rz((old != 0),
"old");
93 clone = vcardproperty_new_impl(old->kind);
94 icalerror_check_arg_rz((clone != 0),
"clone");
96 if (old->value != 0) {
97 clone->value = vcardvalue_clone(old->value);
100 if (old->x_name != 0) {
103 if (clone->x_name == 0) {
104 vcardproperty_free(clone);
110 for (p = icalpvl_head(old->parameters); p != 0; p = icalpvl_next(p)) {
114 vcardproperty_free(clone);
119 icalpvl_push(clone->parameters, param);
125vcardproperty *vcardproperty_new_from_string(
const char *str)
127 size_t buf_size = 1024;
131 vcardcomponent *comp;
134 icalerror_check_arg_rz((str != 0),
"str");
146 comp = vcardparser_parse_string(buf);
156 prop = vcardcomponent_get_first_property(comp, VCARD_ANY_PROPERTY);
158 vcardcomponent_remove_property(comp, prop);
160 vcardcomponent_free(comp);
164 vcardproperty_free(prop);
171void vcardproperty_free(vcardproperty *p)
173 vcardparameter *param;
175 icalerror_check_arg_rv((p != 0),
"prop");
177 if (p->parent != 0) {
183 vcardvalue_free(p->value);
186 while ((param = icalpvl_pop(p->parameters)) != 0) {
190 icalpvl_free(p->parameters);
192 if (p->x_name != 0) {
200 p->kind = VCARD_NO_PROPERTY;
202 p->parameter_iterator = 0;
212static const size_t MAX_LINE_LEN = 75;
214static char *get_next_line_start(
char *line_start,
size_t chars_left)
220 if (chars_left < MAX_LINE_LEN) {
221 return line_start + chars_left;
227 pos = line_start + MAX_LINE_LEN - 2;
228 while (pos > line_start) {
229 if (*pos ==
';' || *pos ==
':' || *pos ==
' ') {
238 pos = line_start + MAX_LINE_LEN - 1;
239 while (pos > line_start) {
241 if ((*pos & 128) == 0) {
246 if ((*pos & 192) == 192) {
256 return line_start + MAX_LINE_LEN - 1;
265static char *fold_property_line(
char *text)
267 size_t buf_size, len;
269 char *buf, *buf_ptr, *line_start, *next_line_start;
281 chars_left = (ssize_t)len;
284 if (chars_left <= 0) {
289 next_line_start = get_next_line_start(line_start, (
size_t)chars_left);
300 char ch = *next_line_start;
301 *next_line_start =
'\0';
303 *next_line_start = ch;
306 chars_left -= (next_line_start - line_start);
307 line_start = next_line_start;
316static const char *vcardproperty_get_value_kind(vcardproperty *prop,
317 const vcardvalue *value)
319 const char *kind_string = NULL;
323 vcardvalue_kind kind = VCARD_NO_VALUE;
324 vcardparameter *val_param =
325 vcardproperty_get_first_parameter(prop, VCARD_VALUE_PARAMETER);
326 vcardproperty_version version = vcardcomponent_get_version(prop->parent);
328 if (version == VCARD_VERSION_NONE) {
329 version = VCARD_VERSION_30;
333 kind = vcardparameter_value_to_value_kind(vcardparameter_get_value(val_param));
336 if (kind == VCARD_NO_VALUE && vcardproperty_isa(prop) != VCARD_X_PROPERTY) {
337 kind = vcardvalue_isa(value);
341 switch (vcardproperty_isa(prop)) {
342 case VCARD_GEO_PROPERTY:
346 if (kind != VCARD_X_VALUE) {
347 kind = VCARD_NO_VALUE;
351 case VCARD_KEY_PROPERTY:
352 case VCARD_LOGO_PROPERTY:
353 case VCARD_PHOTO_PROPERTY:
354 case VCARD_SOUND_PROPERTY:
358 if (version == VCARD_VERSION_40 ||
359 vcardproperty_get_first_parameter(prop, VCARD_ENCODING_PARAMETER)) {
360 kind = VCARD_NO_VALUE;
364 case VCARD_ANNIVERSARY_PROPERTY:
365 case VCARD_BDAY_PROPERTY:
366 case VCARD_DEATHDATE_PROPERTY:
370 if (version == VCARD_VERSION_40 &&
371 (kind == VCARD_TIME_VALUE || kind == VCARD_DATEANDORTIME_VALUE)) {
372 kind = VCARD_NO_VALUE;
373 }
else if (kind == VCARD_DATE_VALUE || kind == VCARD_DATETIME_VALUE) {
374 kind = VCARD_NO_VALUE;
378 case VCARD_TZ_PROPERTY:
382 if (version == VCARD_VERSION_40) {
383 if (kind == VCARD_TEXT_VALUE) {
384 kind = VCARD_NO_VALUE;
386 }
else if (kind == VCARD_UTCOFFSET_VALUE) {
387 kind = VCARD_NO_VALUE;
391 case VCARD_UID_PROPERTY:
395 if (version == VCARD_VERSION_40) {
396 if (kind == VCARD_URI_VALUE) {
397 kind = VCARD_NO_VALUE;
400 kind = VCARD_NO_VALUE;
408 if (kind != VCARD_NO_VALUE &&
409 !vcardproperty_value_kind_is_default(prop->kind, kind)) {
411 kind_string = vcardvalue_kind_to_string(kind);
419const char *vcardproperty_as_vcard_string(vcardproperty *prop)
423 buf = vcardproperty_as_vcard_string_r(prop);
428char *vcardproperty_as_vcard_string_r(vcardproperty *prop)
430 vcardparameter *param;
436 const char *property_name = 0;
437 size_t buf_size = 1024;
440 const vcardvalue *value;
442 const char *kind_string = 0;
443 const char newline[] =
"\r\n";
445 icalerror_check_arg_rz((prop != 0),
"prop");
452 if (prop->kind == VCARD_X_PROPERTY && prop->x_name != 0) {
453 property_name = prop->x_name;
455 property_name = vcardproperty_kind_to_string(prop->kind);
458 if (property_name == 0) {
459 icalerror_warn(
"Got a property of an unknown kind.");
464 if (prop->group != 0) {
471 value = vcardproperty_get_value(prop);
472 kind_string = vcardproperty_get_value_kind(prop, value);
473 if (kind_string != 0) {
479 for (param = vcardproperty_get_first_parameter(prop, VCARD_ANY_PARAMETER);
480 param != 0; param = vcardproperty_get_next_parameter(prop, VCARD_ANY_PARAMETER)) {
485 if (kind_string == 0) {
486 icalerror_warn(
"Got a parameter of unknown kind for the following property");
488 icalerror_warn((property_name) ? property_name :
"(NULL)");
492 if (kind == VCARD_VALUE_PARAMETER) {
507 char *str = vcardvalue_as_vcard_string_r(value);
523 out_buf = fold_property_line(buf);
530vcardproperty_kind vcardproperty_isa(
const vcardproperty *p)
536 return VCARD_NO_PROPERTY;
539bool vcardproperty_isa_property(
void *property)
541 const vcardproperty *impl = (vcardproperty *)property;
543 icalerror_check_arg_rz((property != 0),
"property");
544 if (strcmp(impl->id,
"prop") == 0) {
551void vcardproperty_add_parameter(vcardproperty *p, vcardparameter *parameter)
553 icalerror_check_arg_rv((p != 0),
"prop");
554 icalerror_check_arg_rv((parameter != 0),
"parameter");
556 icalpvl_push(p->parameters, parameter);
559void vcardproperty_set_parameter(vcardproperty *prop, vcardparameter *parameter)
561 vcardparameter_kind kind;
563 icalerror_check_arg_rv((prop != 0),
"prop");
564 icalerror_check_arg_rv((parameter != 0),
"parameter");
567 if (kind == VCARD_X_PARAMETER) {
569 }
else if (kind == VCARD_IANA_PARAMETER) {
575 vcardproperty_add_parameter(prop, parameter);
578void vcardproperty_set_parameter_from_string(vcardproperty *prop,
579 const char *name,
const char *value)
581 vcardparameter_kind kind;
582 vcardparameter *param;
584 icalerror_check_arg_rv((prop != 0),
"prop");
585 icalerror_check_arg_rv((name != 0),
"name");
586 icalerror_check_arg_rv((value != 0),
"value");
590 if (kind == VCARD_NO_PARAMETER) {
602 if (kind == VCARD_X_PARAMETER) {
604 }
else if (kind == VCARD_IANA_PARAMETER) {
608 vcardproperty_set_parameter(prop, param);
611const char *vcardproperty_get_parameter_as_string(vcardproperty *prop,
const char *name)
615 buf = vcardproperty_get_parameter_as_string_r(prop, name);
620char *vcardproperty_get_parameter_as_string_r(vcardproperty *prop,
const char *name)
622 vcardparameter_kind kind;
623 vcardparameter *param;
629 icalerror_check_arg_rz((prop != 0),
"prop");
630 icalerror_check_arg_rz((name != 0),
"name");
634 if (kind == VCARD_NO_PARAMETER) {
639 for (param = vcardproperty_get_first_parameter(prop, kind);
640 param != 0; param = vcardproperty_get_next_parameter(prop, kind)) {
641 if (kind == VCARD_X_PARAMETER) {
645 }
else if (kind == VCARD_IANA_PARAMETER) {
660 t = strchr(str,
'=');
673 pvql = strchr(pv,
'"');
683 pvqr = strrchr(str,
'"');
698 icalerror_check_arg_rv((prop != 0),
"prop");
700 for (p = icalpvl_head(prop->parameters); p != 0; p = icalpvl_next(p)) {
701 vcardparameter *param = (vcardparameter *)icalpvl_data(p);
704 (void)icalpvl_remove(prop->parameters, p);
715 icalerror_check_arg_rv((prop != 0),
"prop");
717 for (p = icalpvl_head(prop->parameters); p != 0; p = icalpvl_next(p)) {
718 vcardparameter *param = (vcardparameter *)icalpvl_data(p);
719 const char *kind_string;
733 if (0 == strcmp(kind_string, name)) {
734 (void)icalpvl_remove(prop->parameters, p);
745 icalerror_check_arg_rv((prop != 0),
"prop");
746 icalerror_check_arg_rv((parameter != 0),
"parameter");
748 for (p = icalpvl_head(prop->parameters); p != 0; p = icalpvl_next(p)) {
749 vcardparameter *p_param = (vcardparameter *)icalpvl_data(p);
751 if (parameter == p_param) {
752 (void)icalpvl_remove(prop->parameters, p);
759int vcardproperty_count_parameters(
const vcardproperty *prop)
762 return icalpvl_count(prop->parameters);
769vcardparameter *vcardproperty_get_first_parameter(vcardproperty *p, vcardparameter_kind kind)
771 icalerror_check_arg_rz((p != 0),
"prop");
773 p->parameter_iterator = icalpvl_head(p->parameters);
775 if (p->parameter_iterator == 0) {
779 for (p->parameter_iterator = icalpvl_head(p->parameters);
780 p->parameter_iterator != 0; p->parameter_iterator = icalpvl_next(p->parameter_iterator)) {
781 vcardparameter *param = (vcardparameter *)icalpvl_data(p->parameter_iterator);
791vcardparameter *vcardproperty_get_next_parameter(vcardproperty *p, vcardparameter_kind kind)
793 icalerror_check_arg_rz((p != 0),
"prop");
795 if (p->parameter_iterator == 0) {
799 for (p->parameter_iterator = icalpvl_next(p->parameter_iterator);
800 p->parameter_iterator != 0; p->parameter_iterator = icalpvl_next(p->parameter_iterator)) {
801 vcardparameter *param = (vcardparameter *)icalpvl_data(p->parameter_iterator);
811void vcardproperty_set_value(vcardproperty *p, vcardvalue *value)
813 vcardvalue_kind kind;
815 icalerror_check_arg_rv((p != 0),
"prop");
816 icalerror_check_arg_rv((value != 0),
"value");
820 vcardvalue_free(p->value);
828 kind = vcardvalue_isa(value);
830 if (kind == VCARD_DATE_VALUE || kind == VCARD_DATETIME_VALUE) {
831 vcardparameter *val_param;
833 val_param = vcardproperty_get_first_parameter(p, VCARD_VALUE_PARAMETER);
836 vcardparameter_value_to_value_kind(vcardparameter_get_value(val_param)) != kind) {
842void vcardproperty_set_value_from_string(vcardproperty *prop,
const char *str,
const char *type)
845 vcardvalue_kind kind = VCARD_NO_VALUE;
847 icalerror_check_arg_rv((prop != 0),
"prop");
848 icalerror_check_arg_rv((str != 0),
"str");
849 icalerror_check_arg_rv((type != 0),
"type");
851 if (strcmp(type,
"NO") == 0) {
853 const vcardvalue *oval = vcardproperty_get_value(prop);
856 kind = vcardvalue_isa(oval);
859 kind = vcardproperty_kind_to_value_kind(vcardproperty_isa(prop));
863 kind = vcardvalue_string_to_kind(type);
866 if (kind == VCARD_NO_VALUE) {
872 nval = vcardvalue_new_from_string(kind, str);
880 vcardproperty_set_value(prop, nval);
883vcardvalue *vcardproperty_get_value(
const vcardproperty *prop)
885 icalerror_check_arg_rz((prop != 0),
"prop");
890const char *vcardproperty_get_value_as_string(
const vcardproperty *prop)
894 buf = vcardproperty_get_value_as_string_r(prop);
899char *vcardproperty_get_value_as_string_r(
const vcardproperty *prop)
901 const vcardvalue *value;
903 icalerror_check_arg_rz((prop != 0),
"prop");
907 return vcardvalue_as_vcard_string_r(value);
910void vcardproperty_set_x_name(vcardproperty *prop,
const char *name)
912 icalerror_check_arg_rv((name != 0),
"name");
913 icalerror_check_arg_rv((prop != 0),
"prop");
915 if (prop->x_name != 0) {
921 if (prop->x_name == 0) {
926const char *vcardproperty_get_x_name(
const vcardproperty *prop)
928 icalerror_check_arg_rz((prop != 0),
"prop");
933void vcardproperty_set_group(vcardproperty *prop,
const char *group)
935 icalerror_check_arg_rv((group != 0),
"group");
936 icalerror_check_arg_rv((prop != 0),
"prop");
938 if (prop->group != 0) {
944 if (prop->group == 0) {
949const char *vcardproperty_get_group(
const vcardproperty *prop)
951 icalerror_check_arg_rz((prop != 0),
"prop");
960 buf = vcardproperty_get_property_name_r(prop);
965char *vcardproperty_get_property_name_r(
const vcardproperty *prop)
967 const char *property_name = 0;
968 size_t buf_size = 256;
972 icalerror_check_arg_rz((prop != 0),
"prop");
977 if (prop->kind == VCARD_X_PROPERTY && prop->x_name != 0) {
978 property_name = prop->x_name;
980 property_name = vcardproperty_kind_to_string(prop->kind);
983 if (property_name == 0) {
999 icalerror_check_arg_rv((property != 0),
"property");
1001 property->parent = comp;
1006 icalerror_check_arg_rz((property != 0),
"property");
1008 return property->parent;
1011static int param_compare(
void *a,
void *b)
1019 vcardproperty_kind prop_kind = vcardproperty_isa(prop);
1020 icalpvl_list sorted_params = icalpvl_newlist();
1021 vcardparameter *param;
1024 while ((param = icalpvl_pop(prop->parameters)) != 0) {
1029 case VCARD_VALUE_PARAMETER:
1031 switch (prop_kind) {
1032 case VCARD_TEL_PROPERTY:
1033 case VCARD_TZ_PROPERTY:
1034 case VCARD_BIRTHPLACE_PROPERTY:
1035 case VCARD_DEATHPLACE_PROPERTY:
1036 if (vcardparameter_get_value(param) == VCARD_VALUE_TEXT) {
1041 case VCARD_RELATED_PROPERTY:
1042 case VCARD_UID_PROPERTY:
1043 case VCARD_KEY_PROPERTY:
1044 if (vcardparameter_get_value(param) == VCARD_VALUE_URI) {
1049 case VCARD_BDAY_PROPERTY:
1050 case VCARD_ANNIVERSARY_PROPERTY:
1051 case VCARD_DEATHDATE_PROPERTY:
1052 if (vcardparameter_get_value(param) == VCARD_VALUE_DATEANDORTIME) {
1062 case VCARD_CALSCALE_PARAMETER:
1063 if (vcardparameter_get_calscale(param) == VCARD_CALSCALE_GREGORIAN) {
1068 case VCARD_PREF_PARAMETER:
1069 if (vcardparameter_get_pref(param) >= 100) {
1074 case VCARD_TYPE_PARAMETER:
1075 if (prop_kind == VCARD_TEL_PROPERTY) {
1077 vcardenumarray_element voice = {VCARD_TYPE_VOICE, NULL};
1079 if (vcardenumarray_find(vcardparameter_get_type(param),
1086 vcardenumarray_sort(vcardparameter_get_type(param));
1090 case VCARD_PID_PARAMETER:
1091 vcardstrarray_sort(vcardparameter_get_pid(param));
1094 case VCARD_SORTAS_PARAMETER:
1095 vcardstrarray_sort(vcardparameter_get_sortas(param));
1106 icalpvl_insert_ordered(sorted_params, param_compare, param);
1110 icalpvl_free(prop->parameters);
1111 prop->parameters = sorted_params;
1113 switch (prop_kind) {
1114 case VCARD_CATEGORIES_PROPERTY:
1115 vcardstrarray_sort(vcardproperty_get_categories(prop));
1118 case VCARD_NICKNAME_PROPERTY:
1119 vcardstrarray_sort(vcardproperty_get_nickname(prop));
1127void vcardproperty_add_type_parameter(vcardproperty *prop,
1128 vcardenumarray_element *type)
1130 vcardenumarray *types;
1131 vcardparameter *param =
1132 vcardproperty_get_first_parameter(prop, VCARD_TYPE_PARAMETER);
1135 types = vcardparameter_get_type(param);
1136 vcardenumarray_add(types, type);
1139 types = vcardenumarray_new(0);
1140 vcardenumarray_add(types, type);
1141 vcardparameter_set_type(param, types);
1142 vcardproperty_add_parameter(prop, param);
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
void icalerror_clear_errno(void)
Resets icalerrno to ICAL_NO_ERROR.
@ ICAL_MALFORMEDDATA_ERROR
#define icalerrno
Access the current icalerrno value.
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.
bool icalproperty_get_allow_empty_properties(void)
Defines the data structure representing iCalendar properties.
int vcardcomponent_count_errors(vcardcomponent *comp)
Returns the number of errors encountered parsing the data.
Defines the data structure representing vCard components.
char * vcardparameter_as_vcard_string(vcardparameter *param)
Converts vcardparameter into a string representation.
void vcardparameter_set_xname(vcardparameter *param, const char *v)
Sets the X-name of param to v.
void vcardparameter_free(vcardparameter *param)
Frees an vcardparameter object.
const char * vcardparameter_get_iana_name(const vcardparameter *param)
Returns the IANA name of param.
void vcardparameter_set_parent(vcardparameter *param, vcardproperty *property)
bool vcardparameter_isa_parameter(void *parameter)
vcardparameter_kind vcardparameter_isa(const vcardparameter *parameter)
void vcardparameter_set_iana_name(vcardparameter *param, const char *v)
Sets the IANA name of param to v.
vcardparameter * vcardparameter_clone(const vcardparameter *old)
Creates new vcardparameter as a clone of the given one.
const char * vcardparameter_get_xname(const vcardparameter *param)
Returns the X-name of param.
vcardparameter * vcardparameter_new(vcardparameter_kind kind)
Creates new vcardparameter object.
char * vcardparameter_as_vcard_string_r(vcardparameter *param)
Converts vcardparameter into an string representation according to RFC5445/RFC6868.
const char * vcardparameter_kind_to_string(vcardparameter_kind kind)
Returns a string representing the given vcardparameter_kind.
vcardparameter * vcardparameter_new_from_value_string(vcardparameter_kind kind, const char *value)
Creates new vcardparameter of a given kind with a given value.
vcardparameter_kind vcardparameter_string_to_kind(const char *string)
Returns the vcardparameter_kind for a given string.
Line-oriented parsing vCard format.
const char * vcardproperty_get_property_name(const vcardproperty *prop)
void vcardproperty_normalize(vcardproperty *prop)
void vcardproperty_remove_parameter_by_name(vcardproperty *prop, const char *name)
Removes all parameters with the specified name.
void vcardproperty_remove_parameter_by_ref(vcardproperty *prop, vcardparameter *parameter)
Removes the specified parameter reference from the property.
vcardcomponent * vcardproperty_get_parent(const vcardproperty *property)
Returns the parent vcard for the specified property.
void vcardproperty_set_parent(vcardproperty *property, vcardcomponent *comp)
Sets the parent vcard for the specified vcardproperty property.
vcardproperty * vcardproperty_clone(const vcardproperty *old)
Deeply clones an vcardproperty.
void vcardproperty_remove_parameter_by_kind(vcardproperty *prop, vcardparameter_kind kind)
Removes all parameters with the specified kind.
bool vcardproperty_kind_is_valid(const vcardproperty_kind kind)
void vcardvalue_set_parent(vcardvalue *value, vcardproperty *property)
Defines the data structure representing vCard values.