36static ICAL_GLOBAL_VAR
void *xprop_value_kind_data = NULL;
66#define BUF_INITIALIZER \
70struct vcardparser_state {
74 const char *itemstart;
76 vcardproperty *version;
79 vcardcomponent *xroot;
80 vcardcomponent *vcard;
86struct vcardparser_errorpos {
104static size_t buf_len(
const struct buf *buf)
109static void buf_reset(
struct buf *buf)
114static void buf_free(
struct buf *buf)
121 buf->len = buf->alloc = 0;
124static void _buf_putc(
struct buf *buf,
char c)
126 char *pos = buf->s + buf->len;
131static void buf_putc(
struct buf *buf,
char c)
138static const char *buf_cstring(
struct buf *buf)
140 _buf_putc(buf,
'\0');
145static void buf_trim(
struct buf *buf)
152 const char *s = buf_cstring(buf);
154 for (buf->len = 0; *s; s++) {
155 if (isspace((
int)*s)) {
158 buf->s[buf->len++] = *s;
162#pragma GCC diagnostic push
163#pragma GCC diagnostic ignored "-Wformat-nonliteral"
164static void buf_vprintf(
struct buf *buf,
const char *fmt, va_list args)
172 size = buf->alloc - buf->len;
173 n = (size_t)vsnprintf(buf->s + buf->len, size, fmt, args);
181 n = (size_t)vsnprintf(buf->s + buf->len, size, fmt, ap);
187#pragma GCC diagnostic pop
189#define NOTESTART() state->itemstart = state->p
190#define MAKE(X, Y) X = icalmemory_new_buffer(sizeof(struct Y))
191#define PUTC(C) buf_putc(&state->buf, C)
192#define INC(I) state->p += I
194 ((ch) > 0 && (ch) <= 0x1f && (ch) != '\r' && (ch) != '\n' && (ch) != '\t')
195#define HANDLECTRL(state) \
197 if (IS_CTRL(*(state)->p)) { \
198 while (IS_CTRL(*(state)->p)) \
201 if ((*(state)->p) == 0) \
205static int _parse_param_name(
struct vcardparser_state *state)
216 name = buf_cstring(&state->buf);
224 buf_reset(&state->buf);
238 if (state->p[1] !=
' ' && state->p[1] !=
'\t') {
256static int _parse_param_quoted(
struct vcardparser_state *state,
257 bool is_structured,
bool is_multivalued)
276 if (state->p[1] ==
'\r') {
279 if (state->p[1] ==
'\n') {
280 if (state->p[2] !=
' ' && state->p[2] !=
'\t') {
288 if (state->p[1] ==
'n' || state->p[1] ==
'N') {
290 }
else if (is_structured && strchr(
";,", state->p[1])) {
302 if (state->p[1] ==
'\r') {
305 if (state->p[1] ==
'\n') {
306 if (state->p[2] !=
' ' && state->p[2] !=
'\t') {
311 if (state->p[1] ==
'\'') {
314 }
else if (state->p[1] ==
'n') {
317 }
else if (state->p[1] ==
'^') {
330 if (state->p[1] !=
' ' && state->p[1] !=
'\t') {
337 if (is_multivalued && !is_structured) {
353static int _parse_param_value(
struct vcardparser_state *state)
366 if (state->p[1] ==
'\r') {
369 if (state->p[1] ==
'\n') {
370 if (state->p[2] !=
' ' && state->p[2] !=
'\t') {
378 if (state->p[1] ==
'n' || state->p[1] ==
'N') {
388 if (state->p[1] ==
'\r') {
391 if (state->p[1] ==
'\n') {
392 if (state->p[2] !=
' ' && state->p[2] !=
'\t') {
397 if (state->p[1] ==
'\'') {
400 }
else if (state->p[1] ==
'n') {
403 }
else if (state->p[1] ==
'^') {
414 while ((r = _parse_param_quoted(state,
418 buf_cstring(&state->buf));
420 buf_reset(&state->buf);
431 if (is_multivalued) {
433 buf_cstring(&state->buf));
436 buf_cstring(&state->buf));
443 state->value_kind =
kind;
448 buf_reset(&state->buf);
457 if (state->p[1] !=
' ' && state->p[1] !=
'\t') {
464 if (is_multivalued) {
466 buf_cstring(&state->buf));
467 buf_reset(&state->buf);
484static void _parse_error(
struct vcardparser_state *state,
486 const char *fmt, ...)
491 buf_reset(&state->errbuf);
492 buf_vprintf(&state->errbuf, fmt, ap);
498 state->version = NULL;
505 buf_reset(&state->buf);
508static int _parse_prop_params(
struct vcardparser_state *state)
521 r = _parse_param_name(state);
525 "%s '%s' in %s%s%s property. Removing entire property",
527 group ? group :
"", group ?
"." :
"",
535 r = _parse_param_value(state);
541 "%s for %s in %s%s%s property. Removing entire property",
544 group ? group :
"", group ?
"." :
"",
549 }
while (*state->p ==
';');
554static int _parse_prop_name(
struct vcardparser_state *state)
557 const char *group = NULL;
571 name = buf_cstring(&state->buf);
587 if (state->version) {
614 xprop_value_kind_func ? xprop_value_kind_func(name, xprop_value_kind_data)
623 buf_reset(&state->buf);
630 size_t tmpLen = strlen(group) + buf_len(&state->buf) + 2;
632 snprintf(tmp, tmpLen - 1,
"%s.%s", group, buf_cstring(&state->buf));
638 buf_reset(&state->buf);
646 if (state->p[1] ==
' ' || state->p[1] ==
'\t') {
648 }
else if (!state->buf.len) {
666static int _parse_prop_value(
struct vcardparser_state *state)
680 while (state->p[1] && strchr(
"\r\n", state->p[1])) {
681 if (state->p[1] ==
'\r') {
684 if (state->p[1] ==
'\n') {
685 if (state->p[2] !=
' ' && state->p[2] !=
'\t') {
708 if (state->p[1] ==
' ' || state->p[1] ==
'\t') {
729 buf_trim(&state->buf);
730 state->version = state->prop;
742 buf_cstring(&state->buf));
750 buf_reset(&state->buf);
755static void _parse_eatline(
struct vcardparser_state *state)
763 if (state->p[1] ==
' ' || state->p[1] ==
'\t') {
778static void _parse_prop(
struct vcardparser_state *state)
780 int r = _parse_prop_name(state);
787 "%s '%s.%s'. Removing entire property",
791 _parse_eatline(state);
795 "%s '%s'. Removing entire property",
797 _parse_eatline(state);
801 "%s '%s'. Ignoring property",
807 if (*state->p ==
';') {
808 r = _parse_prop_params(state);
816 r = _parse_prop_value(state);
824 "Error parsing '%s' as %s value in %s%s%s property."
825 " Removing entire property",
826 buf_cstring(&state->buf),
828 group ? group :
"", group ?
"." :
"",
833 "%s in %s%s%s property. Removing entire property",
835 group ? group :
"", group ?
"." :
"",
841static int _parse_vcard(
struct vcardparser_state *state,
int only_one)
843 const char *cardstart = state->p;
848 if (*state->p ==
'\r' || *state->p ==
'\n' ||
849 *state->p ==
' ' || *state->p ==
'\t') {
859 state->itemstart = cardstart;
873 if (!val || strcasecmp(val,
"VCARD") != 0) {
874 state->itemstart = cardstart;
884 }
else if (!state->vcard) {
886 state->itemstart = cardstart;
899 if (!val || strcasecmp(val,
"VCARD") != 0) {
900 state->itemstart = cardstart;
931static int vcardparser_parse(
struct vcardparser_state *state,
int only_one)
935 state->p = state->base;
941 return _parse_vcard(state, only_one);
946static void _free_state(
struct vcardparser_state *state)
948 buf_free(&state->buf);
949 buf_free(&state->errbuf);
955 memset(state, 0,
sizeof(
struct vcardparser_state));
958static void vcardparser_free(
struct vcardparser_state *state)
969 return "EOF after backslash";
971 return "Params on BEGIN field";
973 return "Multiple group levels in property name";
975 return "vCard not completed";
977 return "End of data while parsing parameter key";
979 return "End of line while parsing parameter key";
981 return "Closed a different card name than opened";
983 return "End of data while parsing property name";
985 return "End of line while parsing property name";
987 return "Invalid property name";
989 return "End of data while parsing parameter value";
991 return "End of line while parsing parameter value";
993 return "End of data while parsing quoted value";
995 return "End of line while parsing quoted value";
997 return "End of line while parsing multi or structured value";
999 return "Invalid value for property";
1001 return "Illegal character in vCard";
1004 return "Unknown error";
1010 struct vcardparser_state parser;
1011 vcardcomponent *vcard = NULL;
1014 memset(&parser, 0,
sizeof(
struct vcardparser_state));
1017 r = vcardparser_parse(&parser, 0);
1025 vcard = parser.xroot;
1026 parser.xroot = NULL;
1030 vcardparser_free(&parser);
1037 xprop_value_kind_func = func;
1038 xprop_value_kind_data = data;
enum icalrequeststatus kind
void icalmemory_free_buffer(void *buf)
Releases a buffer.
void * icalmemory_resize_buffer(void *buf, size_t size)
Resizes a buffer created with icalmemory_new_buffer().
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
char * icalmemory_tmp_copy(const char *str)
Creates a copy of the given string, stored on the ring buffer, and returns it.
void icalmemory_append_char(char **buf, char **pos, size_t *buf_size, char ch)
Appends a character to a buffer.
void * icalmemory_tmp_buffer(size_t size)
Creates a new temporary buffer on the ring and returns it.
Common memory management routines.
void vcardcomponent_add_property(vcardcomponent *comp, vcardproperty *property)
void vcardcomponent_remove_component(vcardcomponent *parent, vcardcomponent *child)
vcardcomponent * vcardcomponent_get_first_component(vcardcomponent *c, vcardcomponent_kind kind)
void vcardcomponent_add_component(vcardcomponent *parent, vcardcomponent *child)
void vcardcomponent_free(vcardcomponent *c)
vcardcomponent * vcardcomponent_new(vcardcomponent_kind kind)
Constructor.
int vcardcomponent_count_components(vcardcomponent *component, vcardcomponent_kind kind)
Defines the data structure representing vCard components.
struct vcardparameter_impl vcardparameter
vcardparameter * vcardparameter_new_xlicerrortype(vcardparameter_xlicerrortype v)
vcardparameter_xlicerrortype
@ VCARD_XLICERRORTYPE_PARAMETERNAMEPARSEERROR
@ VCARD_XLICERRORTYPE_PROPERTYPARSEERROR
@ VCARD_XLICERRORTYPE_VALUEPARSEERROR
@ VCARD_XLICERRORTYPE_PARAMETERVALUEPARSEERROR
enum vcardproperty_version vcardproperty_get_version(const vcardproperty *prop)
vcardproperty * vcardproperty_vanew_xlicerror(const char *v,...)
vcardvalue * vcardvalue_new_textlist(vcardstrarray *v)
struct vcardvalue_impl vcardvalue
const char * vcardvalue_get_text(const vcardvalue *value)
bool vcardparameter_is_structured(const vcardparameter *param)
void vcardparameter_set_xname(vcardparameter *param, const char *v)
Sets the X-name of param to v.
bool vcardparameter_is_multivalued(const vcardparameter *param)
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_new(vcardparameter_kind kind)
Creates new vcardparameter object.
Defines the data structure representing vCard parameters.
void vcardparameter_add_value_from_string(vcardparameter *param, const char *val)
const char * vcardparameter_kind_to_string(vcardparameter_kind kind)
Returns a string representing the given vcardparameter_kind.
void vcardparameter_set_value_from_string(vcardparameter *param, const char *val)
vcardparameter_kind vcardparameter_string_to_kind(const char *string)
Returns the vcardparameter_kind for a given string.
#define HANDLECTRL(state)
void buf_init(struct buf *buf, size_t size)
void vcardparser_set_xprop_value_kind(vcard_xprop_value_kind_func func, void *data)
Registers a parser callback to override the default value type of an x-property.
const char * vcardparser_errstr(int err)
vcardcomponent * vcardparser_parse_string(const char *str)
Line-oriented parsing vCard format.
vcardvalue_kind(* vcard_xprop_value_kind_func)(const char *name, void *data)
Callback function pointer to define x-property default value types.
vcardproperty * vcardproperty_new(vcardproperty_kind kind)
void vcardproperty_set_group(vcardproperty *prop, const char *group)
void vcardproperty_set_x_name(vcardproperty *prop, const char *name)
void vcardproperty_free(vcardproperty *p)
void vcardproperty_set_value(vcardproperty *p, vcardvalue *value)
vcardvalue * vcardproperty_get_value(const vcardproperty *prop)
const char * vcardproperty_get_group(const vcardproperty *prop)
void vcardproperty_add_parameter(vcardproperty *p, vcardparameter *parameter)
vcardproperty_kind vcardproperty_isa(const vcardproperty *p)
Defines the data structure representing vCard properties.
vcardproperty_kind vcardproperty_string_to_kind(const char *string)
vcardvalue_kind vcardproperty_kind_to_value_kind(vcardproperty_kind kind)
const char * vcardproperty_kind_to_string(vcardproperty_kind kind)
bool vcardproperty_is_structured(vcardproperty_kind pkind)
icalstrarray vcardstrarray
vcardstrarray * vcardtextlist_new_from_string(const char *str, char sep)
Defines functions for creating vCard text lists.
vcardvalue * vcardvalue_new_from_string(vcardvalue_kind kind, const char *str)
vcardvalue_kind vcardvalue_isa(const vcardvalue *value)
Defines the data structure representing vCard values.
vcardvalue_kind vcardvalue_string_to_kind(const char *str)
const char * vcardvalue_kind_to_string(const vcardvalue_kind kind)