$darkmode
Libical API Documentation 4.0 STABLE VERSION Visit the v3.0 documentation
vcardparameter.c
Go to the documentation of this file.
1 /*======================================================================
2  FILE: vcardparameter.c
3  CREATOR: Ken Murchison 24 Aug 2022 <murch@fastmailteam.com>
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 
14 #ifdef HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17 
18 #include "vcardparameter.h"
19 #include "vcardparameterimpl.h"
20 #include "icalerror_p.h"
21 #include "icalmemory.h"
22 
23 #include <errno.h>
24 #include <stdlib.h>
25 
26 LIBICAL_VCARD_EXPORT struct vcardparameter_impl *vcardparameter_new_impl(vcardparameter_kind kind)
27 {
28  struct vcardparameter_impl *v;
29 
30  if ((v = (struct vcardparameter_impl *)icalmemory_new_buffer(sizeof(struct vcardparameter_impl))) == 0) {
32  return 0;
33  }
34 
35  memset(v, 0, sizeof(struct vcardparameter_impl));
36 
37  v->id = ICAL_STRUCTURE_TYPE_PARAMETER;
38  v->kind = kind;
39  v->value_kind = vcardparameter_kind_value_kind(kind, &v->is_multivalued);
40 
41  return v;
42 }
43 
44 vcardparameter *vcardparameter_new(vcardparameter_kind kind)
45 {
46  struct vcardparameter_impl *v = vcardparameter_new_impl(kind);
47 
48  return (vcardparameter *)v;
49 }
50 
51 void vcardparameter_free(vcardparameter *param)
52 {
53  if (!param || param->parent != 0) {
54  return;
55  }
56 
57  if (param->string != 0) {
58  icalmemory_free_buffer((void *)param->string);
59  } else if (param->values != 0) {
60  if (param->value_kind == VCARD_TEXT_VALUE) {
61  vcardstrarray_free(param->values);
62  } else {
63  vcardenumarray_free(param->values);
64  }
65  } else if (param->structured != 0) {
66  vcardstructured_unref(param->structured);
67  }
68 
69  if (param->x_name != 0) {
70  icalmemory_free_buffer((void *)param->x_name);
71  }
72 
73  memset(param, 0, sizeof(vcardparameter));
74 
75  param->parent = 0;
76  param->id = ICAL_STRUCTURE_TYPE_PARAMETER_EMPTY;
78 }
79 
80 vcardparameter *vcardparameter_clone(const vcardparameter *old)
81 {
82  struct vcardparameter_impl *clone;
83 
84  icalerror_check_arg_rz((old != 0), "param");
85 
86  clone = vcardparameter_new_impl(old->kind);
87 
88  if (clone == 0) {
89  return 0;
90  }
91 
92  memcpy(clone, old, sizeof(struct vcardparameter_impl));
93 
94  if (old->string != 0) {
95  clone->string = icalmemory_strdup(old->string);
96  if (clone->string == 0) {
97  clone->parent = 0;
98  vcardparameter_free(clone);
99  return 0;
100  }
101  }
102 
103  if (old->x_name != 0) {
104  clone->x_name = icalmemory_strdup(old->x_name);
105  if (clone->x_name == 0) {
106  clone->parent = 0;
107  vcardparameter_free(clone);
108  return 0;
109  }
110  }
111 
112  if (old->values != 0) {
113  clone->values = old->value_kind == VCARD_TEXT_VALUE ? vcardstrarray_clone(old->values) : vcardenumarray_clone(old->values);
114  if (clone->values == 0) {
115  clone->parent = 0;
116  vcardparameter_free(clone);
117  return 0;
118  }
119  }
120 
121  return clone;
122 }
123 
124 vcardparameter *vcardparameter_new_from_string(const char *str)
125 {
126  char *eq;
127  char *cpy;
128  vcardparameter_kind kind;
129  vcardparameter *param;
130 
131  icalerror_check_arg_rz(str != 0, "str");
132 
133  cpy = icalmemory_strdup(str);
134 
135  if (cpy == 0) {
137  return 0;
138  }
139 
140  eq = strchr(cpy, '=');
141 
142  if (eq == 0) {
145  return 0;
146  }
147 
148  *eq = '\0';
149 
150  eq++;
151 
152  kind = vcardparameter_string_to_kind(cpy);
153 
154  if (kind == VCARD_NO_PARAMETER) {
157  return 0;
158  }
159 
160  param = vcardparameter_new_from_value_string(kind, eq);
161 
162  if (kind == VCARD_X_PARAMETER) {
163  vcardparameter_set_xname(param, cpy);
164  } else if (kind == VCARD_IANA_PARAMETER) {
165  vcardparameter_set_iana_name(param, cpy);
166  }
167 
169 
170  return param;
171 }
172 
173 char *vcardparameter_as_vcard_string(vcardparameter *param)
174 {
175  char *buf;
176 
179  return buf;
180 }
181 
182 /*
183  * - param = param-name "=" param-value
184  * - param-name = iana-token / x-token
185  * - param-value = paramtext /quoted-string
186  * - paramtext = *SAFE-CHAR
187  * - quoted-string= DQUOTE *QSAFE-CHAR DQUOTE
188  * - QSAFE-CHAR = any character except CTLs and DQUOTE
189  * - SAFE-CHAR = any character except CTLs, DQUOTE. ";", ":", ","
190  */
191 char *vcardparameter_as_vcard_string_r(vcardparameter *param)
192 {
193  size_t buf_size = 1024;
194  char *buf;
195  char *buf_ptr;
196 
197  icalerror_check_arg_rz((param != 0), "parameter");
198 
199  /* Create new buffer that we can append names, parameters and a
200  * value to, and reallocate as needed.
201  */
202 
203  buf = icalmemory_new_buffer(buf_size);
204  buf_ptr = buf;
205 
206  if (param->kind == VCARD_X_PARAMETER) {
207  icalmemory_append_string(&buf, &buf_ptr,
208  &buf_size, vcardparameter_get_xname(param));
209  } else if (param->kind == VCARD_IANA_PARAMETER) {
210  icalmemory_append_string(&buf, &buf_ptr,
211  &buf_size, vcardparameter_get_iana_name(param));
212  } else {
213  const char *kind_string = vcardparameter_kind_to_string(param->kind);
214 
215  if (param->kind == VCARD_NO_PARAMETER ||
216  param->kind == VCARD_ANY_PARAMETER || kind_string == 0) {
219  return 0;
220  }
221 
222  /* Put the parameter name into the string */
223  icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
224  }
225 
226  icalmemory_append_string(&buf, &buf_ptr, &buf_size, "=");
227 
228  if (param->string != 0) {
229  icalmemory_append_encoded_string(&buf, &buf_ptr,
230  &buf_size, param->string);
231  } else if (param->data != 0) {
232  char *intbuf = NULL;
233  const char *str;
234 
235  if (param->value_kind == VCARD_INTEGER_VALUE) {
236 #define VCARD_INTEGER_LENGTH 21
237  intbuf = icalmemory_tmp_buffer(VCARD_INTEGER_LENGTH);
238  snprintf(intbuf, VCARD_INTEGER_LENGTH - 1, "%d", param->data);
239 
240  str = intbuf;
241  } else {
242  str = vcardparameter_enum_to_string(param->data);
243  }
244 
245  icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
246 
247  } else if (param->values != 0) {
248  size_t i;
249  const char *sep = "";
250 
251  for (i = 0; i < param->values->num_elements; i++) {
252  icalmemory_append_string(&buf, &buf_ptr, &buf_size, sep);
253 
254  if (param->value_kind == VCARD_TEXT_VALUE) {
255  const char *str = vcardstrarray_element_at(param->values, i);
256 
257  icalmemory_append_encoded_string(&buf, &buf_ptr,
258  &buf_size, str);
259  } else {
260  const vcardenumarray_element *elem =
261  vcardenumarray_element_at(param->values, i);
262  if (elem->xvalue != 0) {
263  icalmemory_append_encoded_string(&buf, &buf_ptr,
264  &buf_size, elem->xvalue);
265  } else {
266  const char *str = vcardparameter_enum_to_string(elem->val);
267 
268  icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
269  }
270  }
271  sep = ",";
272  }
273  } else if (vcardparameter_is_structured(param)) {
274  char *str = vcardstructured_as_vcard_string_r(param->structured, 1);
275 
276  icalmemory_append_encoded_string(&buf, &buf_ptr, &buf_size, str);
278  } else if (vcardtime_is_valid_time(param->date)) {
279  const char *str = vcardtime_as_vcard_string(param->date, 0);
280 
281  icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
282 
283  } else {
286  return 0;
287  }
288 
289  return buf;
290 }
291 
292 vcardparameter_kind vcardparameter_isa(const vcardparameter *parameter)
293 {
294  if (parameter == 0) {
295  return VCARD_NO_PARAMETER;
296  }
297 
298  return parameter->kind;
299 }
300 
301 bool vcardparameter_isa_parameter(void *parameter)
302 {
303  const struct vcardparameter_impl *impl = (struct vcardparameter_impl *)parameter;
304 
305  if (parameter == 0) {
306  return false;
307  }
308 
309  return (impl->id == ICAL_STRUCTURE_TYPE_PARAMETER);
310 }
311 
312 void vcardparameter_set_xname(vcardparameter *param, const char *v)
313 {
314  icalerror_check_arg_rv((param != 0), "param");
315  icalerror_check_arg_rv((v != 0), "v");
316 
317  if (param->x_name != 0) {
318  icalmemory_free_buffer((void *)param->x_name);
319  }
320 
321  param->x_name = icalmemory_strdup(v);
322 
323  if (param->x_name == 0) {
324  errno = ENOMEM;
325  }
326 }
327 
328 const char *vcardparameter_get_xname(const vcardparameter *param)
329 {
330  icalerror_check_arg_rz((param != 0), "param");
331 
332  return param->x_name;
333 }
334 
335 void vcardparameter_set_xvalue(vcardparameter *param, const char *v)
336 {
337  icalerror_check_arg_rv((param != 0), "param");
338  icalerror_check_arg_rv((v != 0), "v");
339 
340  if (param->string != 0) {
341  icalmemory_free_buffer((void *)param->string);
342  }
343 
344  param->string = icalmemory_strdup(v);
345 
346  if (param->string == 0) {
347  errno = ENOMEM;
348  }
349 }
350 
351 const char *vcardparameter_get_xvalue(const vcardparameter *param)
352 {
353  icalerror_check_arg_rz((param != 0), "param");
354 
355  return param->string;
356 }
357 
358 void vcardparameter_set_iana_value(vcardparameter *param, const char *v)
359 {
360  vcardparameter_set_xvalue(param, v);
361 }
362 
363 const char *vcardparameter_get_iana_value(const vcardparameter *param)
364 {
365  return vcardparameter_get_xvalue(param);
366 }
367 
368 void vcardparameter_set_iana_name(vcardparameter *param, const char *v)
369 {
370  vcardparameter_set_xname(param, v);
371 }
372 
373 const char *vcardparameter_get_iana_name(const vcardparameter *param)
374 {
375  return vcardparameter_get_xname(param);
376 }
377 
378 void vcardparameter_set_parent(vcardparameter *param, vcardproperty *property)
379 {
380  icalerror_check_arg_rv((param != 0), "param");
381 
382  param->parent = property;
383 }
384 
385 vcardproperty *vcardparameter_get_parent(const vcardparameter *param)
386 {
387  icalerror_check_arg_rz((param != 0), "param");
388 
389  return param->parent;
390 }
391 
392 bool vcardparameter_has_same_name(const vcardparameter *param1, const vcardparameter *param2)
393 {
394  vcardparameter_kind kind1;
395  vcardparameter_kind kind2;
396  const char *name1;
397  const char *name2;
398 
399  icalerror_check_arg_rz((param1 != 0), "param1");
400  icalerror_check_arg_rz((param2 != 0), "param2");
401 
402  kind1 = vcardparameter_isa(param1);
403  kind2 = vcardparameter_isa(param2);
404 
405  if (kind1 != kind2) {
406  return false;
407  }
408 
409  if (kind1 == VCARD_X_PARAMETER) {
410  name1 = vcardparameter_get_xname(param1);
411  name2 = vcardparameter_get_xname(param2);
412  if (strcasecmp(name1, name2) != 0) {
413  return false;
414  }
415  } else if (kind1 == VCARD_IANA_PARAMETER) {
416  name1 = vcardparameter_get_iana_name(param1);
417  name2 = vcardparameter_get_iana_name(param2);
418  if (strcasecmp(name1, name2) != 0) {
419  return false;
420  }
421  }
422  return true;
423 }
424 
425 bool vcardparameter_is_multivalued(const vcardparameter *param)
426 {
427  icalerror_check_arg_rz((param != 0), "param");
428 
429  return param->is_multivalued;
430 }
431 
432 bool vcardparameter_is_structured(const vcardparameter *param)
433 {
434  icalerror_check_arg_rz((param != 0), "param");
435 
436  return (param->value_kind == VCARD_STRUCTURED_VALUE);
437 }
438 
439 /* Everything below this line is machine generated. Do not edit. */
440 /* ALTREP */
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:780
Common memory management routines.
char * vcardparameter_as_vcard_string_r(vcardparameter *param)
Converts vcardparameter into an string representation according to RFC5445/RFC6868.
const char * vcardparameter_get_xvalue(const vcardparameter *param)
Returns the X-value of param.
vcardproperty * vcardparameter_get_parent(const vcardparameter *param)
void * icalmemory_tmp_buffer(size_t size)
Creates a new temporary buffer on the ring and returns it.
Definition: icalmemory.c:182
vcardparameter * vcardparameter_new(vcardparameter_kind kind)
Creates new vcardparameter object.
char * icalmemory_strdup(const char *s)
Creates a duplicate of a string.
Definition: icalmemory.c:242
void icalmemory_free_buffer(void *buf)
Releases a buffer.
Definition: icalmemory.c:355
Defines the data structure representing vCard parameters.
const char * vcardparameter_get_iana_value(const vcardparameter *param)
Returns the IANA value of param.
const char * vcardparameter_kind_to_string(vcardparameter_kind kind)
Returns a string representing the given vcardparameter_kind.
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition: icalerror.c:90
void vcardparameter_set_xname(vcardparameter *param, const char *v)
Sets the X-name of param to v.
void icalmemory_append_encoded_string(char **buf, char **pos, size_t *buf_size, const char *string)
Definition: icalmemory.c:478
bool vcardparameter_has_same_name(const vcardparameter *param1, const vcardparameter *param2)
Determines if two parameters have the same name.
void vcardparameter_set_iana_value(vcardparameter *param, const char *v)
Sets the IANA value of param to v.
const char * vcardparameter_get_iana_name(const vcardparameter *param)
Returns the IANA name of param.
void vcardstructured_unref(vcardstructuredtype *st)
Decrements the reference count of the vcardstructuredtype.
vcardparameter * vcardparameter_clone(const vcardparameter *old)
Creates new vcardparameter as a clone of the given one.
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
Definition: icalmemory.c:315
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 vcardparameter_set_iana_name(vcardparameter *param, const char *v)
Sets the IANA name of param to v.
char * vcardparameter_as_vcard_string(vcardparameter *param)
Converts vcardparameter into a string representation.
bool vcardparameter_isa_parameter(void *parameter)
void vcardparameter_set_xvalue(vcardparameter *param, const char *v)
Sets the X-value of param to v.
vcardparameter_kind vcardparameter_isa(const vcardparameter *parameter)
const char * vcardparameter_get_xname(const vcardparameter *param)
Returns the X-name of param.
void vcardparameter_free(vcardparameter *param)
Frees an vcardparameter object.
vcardparameter * vcardparameter_new_from_value_string(vcardparameter_kind kind, const char *value)
Creates new vcardparameter of a given kind with a given value.
vcardparameter * vcardparameter_new_from_string(const char *str)
Creates new vcardparameter object from string.
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Definition: icalmemory.c:158
void vcardparameter_set_parent(vcardparameter *param, vcardproperty *property)
vcardparameter_kind vcardparameter_string_to_kind(const char *string)
Returns the vcardparameter_kind for a given string.