$darkmode
Libical API Documentation 4.0 STABLE VERSION Visit the v3.0 documentation
icalparameter.c
Go to the documentation of this file.
1 /*======================================================================
2  FILE: icalparameter.c
3  CREATOR: eric 09 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  The original code is icalderivedparameters.{c,h}
9 
10  Contributions from:
11  Graham Davison <g.m.davison@computer.org>
12 ======================================================================*/
13 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 
23 #include "icalparameter.h"
24 #include "icalparameterimpl.h"
25 #include "icalerror_p.h"
26 #include "icalmemory.h"
27 
28 #include <errno.h>
29 #include <stdlib.h>
30 
32 LIBICAL_ICAL_EXPORT struct icalparameter_impl *icalparameter_new_impl(icalparameter_kind kind)
33 {
34  struct icalparameter_impl *v;
35 
36  if ((v = (struct icalparameter_impl *)icalmemory_new_buffer(sizeof(struct icalparameter_impl))) == 0) {
38  return 0;
39  }
40 
41  memset(v, 0, sizeof(struct icalparameter_impl));
42 
43  v->id = ICAL_STRUCTURE_TYPE_PARAMETER;
44  v->kind = kind;
45  v->value_kind = icalparameter_kind_value_kind(kind, &v->is_multivalued);
46 
47  return v;
48 }
50 
51 icalparameter *icalparameter_new(icalparameter_kind kind)
52 {
53  struct icalparameter_impl *v = icalparameter_new_impl(kind);
54 
55  return (icalparameter *)v;
56 }
57 
58 void icalparameter_free(icalparameter *param)
59 {
60  /* Comment out the following as it always triggers, even when parameter is non-zero
61  icalerror_check_arg_rv((parameter==0),"parameter");*/
62 
63  if (param->parent != 0) {
64  return;
65  }
66 
67  if (param->string != 0) {
68  icalmemory_free_buffer((void *)param->string);
69  } else if (param->values != 0) {
70  if (param->value_kind == ICAL_TEXT_VALUE) {
71  icalstrarray_free(param->values);
72  } else {
73  icalenumarray_free(param->values);
74  }
75  }
76 
77  icalmemory_free_buffer((void *)param->x_name);
78 
79  memset(param, 0, sizeof(icalparameter));
80 
81  param->parent = 0;
82  param->id = ICAL_STRUCTURE_TYPE_PARAMETER_EMPTY;
84 }
85 
86 icalparameter *icalparameter_clone(const icalparameter *old)
87 {
88  struct icalparameter_impl *clone;
89 
90  icalerror_check_arg_rz((old != 0), "param");
91 
92  clone = icalparameter_new_impl(old->kind);
93 
94  if (clone == 0) {
95  return 0;
96  }
97 
98  memcpy(clone, old, sizeof(struct icalparameter_impl));
99 
100  if (old->string != 0) {
101  clone->string = icalmemory_strdup(old->string);
102  if (clone->string == 0) {
103  clone->parent = 0;
104  icalparameter_free(clone);
105  return 0;
106  }
107  }
108 
109  if (old->x_name != 0) {
110  clone->x_name = icalmemory_strdup(old->x_name);
111  if (clone->x_name == 0) {
112  clone->parent = 0;
113  icalparameter_free(clone);
114  return 0;
115  }
116  }
117 
118  if (old->values != 0) {
119  clone->values = old->value_kind == ICAL_TEXT_VALUE ? icalstrarray_clone(old->values) : icalenumarray_clone(old->values);
120  if (clone->values == 0) {
121  clone->parent = 0;
122  icalparameter_free(clone);
123  return 0;
124  }
125  }
126 
127  return clone;
128 }
129 
130 icalparameter *icalparameter_new_from_string(const char *str)
131 {
132  char *eq;
133  char *cpy;
134  icalparameter_kind kind;
135  icalparameter *param;
136 
137  icalerror_check_arg_rz(str != 0, "str");
138 
139  cpy = icalmemory_strdup(str);
140 
141  if (cpy == 0) {
143  return 0;
144  }
145 
146  eq = strchr(cpy, '=');
147 
148  if (eq == 0) {
151  return 0;
152  }
153 
154  *eq = '\0';
155 
156  eq++;
157 
158  kind = icalparameter_string_to_kind(cpy);
159 
160  if (kind == ICAL_NO_PARAMETER) {
163  return 0;
164  }
165 
166  param = icalparameter_new_from_value_string(kind, eq);
167 
168  if (kind == ICAL_X_PARAMETER) {
169  icalparameter_set_xname(param, cpy);
170  } else if (kind == ICAL_IANA_PARAMETER) {
171  icalparameter_set_iana_name(param, cpy);
172  }
173 
175 
176  return param;
177 }
178 
179 char *icalparameter_as_ical_string(icalparameter *param)
180 {
181  char *buf;
182 
183  buf = icalparameter_as_ical_string_r(param);
185  return buf;
186 }
187 
188 /*
189  * - param = param-name "=" param-value
190  * - param-name = iana-token / x-token
191  * - param-value = paramtext /quoted-string
192  * - paramtext = *SAFE-CHAR
193  * - quoted-string= DQUOTE *QSAFE-CHAR DQUOTE
194  * - QSAFE-CHAR = any character except CTLs and DQUOTE
195  * - SAFE-CHAR = any character except CTLs, DQUOTE. ";", ":", ","
196  */
197 char *icalparameter_as_ical_string_r(icalparameter *param)
198 {
199  size_t buf_size = 1024;
200  char *buf;
201  char *buf_ptr;
202  const char *kind_string;
203 
204  icalerror_check_arg_rz((param != 0), "parameter");
205 
206  /* Create new buffer that we can append names, parameters and a
207  * value to, and reallocate as needed.
208  */
209 
210  buf = icalmemory_new_buffer(buf_size);
211  buf_ptr = buf;
212 
213  if (param->kind == ICAL_X_PARAMETER) {
214  icalmemory_append_string(&buf, &buf_ptr, &buf_size, icalparameter_get_xname(param));
215  } else if (param->kind == ICAL_IANA_PARAMETER) {
216  icalmemory_append_string(&buf, &buf_ptr, &buf_size, icalparameter_get_iana_name(param));
217  } else {
218  kind_string = icalparameter_kind_to_string(param->kind);
219 
220  if (param->kind == ICAL_NO_PARAMETER ||
221  param->kind == ICAL_ANY_PARAMETER || kind_string == 0) {
224  return 0;
225  }
226 
227  /* Put the parameter name into the string */
228  icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
229  }
230 
231  icalmemory_append_string(&buf, &buf_ptr, &buf_size, "=");
232 
233  if (param->kind == ICAL_GAP_PARAMETER) {
234  char *str = icaldurationtype_as_ical_string_r(param->duration);
235 
236  icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
238  } else if (param->string != 0) {
239  icalmemory_append_encoded_string(&buf, &buf_ptr, &buf_size, param->string);
240  } else if (param->data != 0) {
241  const char *str = icalparameter_enum_to_string(param->data);
242 
243  icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
244  } else if (param->values != 0) {
245  size_t i;
246  const char *sep = "";
247 
248  for (i = 0; i < param->values->num_elements; i++) {
249  icalmemory_append_string(&buf, &buf_ptr, &buf_size, sep);
250 
251  if (param->value_kind == ICAL_TEXT_VALUE) {
252  const char *str = icalstrarray_element_at(param->values, i);
253 
254  icalmemory_append_encoded_string(&buf, &buf_ptr,
255  &buf_size, str);
256  } else {
257  const icalenumarray_element *elem =
258  icalenumarray_element_at(param->values, i);
259  if (elem->xvalue != 0) {
260  icalmemory_append_encoded_string(&buf, &buf_ptr,
261  &buf_size, elem->xvalue);
262  } else {
263  const char *str = icalparameter_enum_to_string(elem->val);
264 
265  icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
266  }
267  }
268  sep = ",";
269  }
270  } else {
273  return 0;
274  }
275 
276  return buf;
277 }
278 
279 icalparameter_kind icalparameter_isa(const icalparameter *parameter)
280 {
281  if (parameter == 0) {
282  return ICAL_NO_PARAMETER;
283  }
284 
285  return parameter->kind;
286 }
287 
288 bool icalparameter_isa_parameter(void *parameter)
289 {
290  const struct icalparameter_impl *impl = (struct icalparameter_impl *)parameter;
291 
292  if (parameter == 0) {
293  return false;
294  }
295 
296  return (impl->id == ICAL_STRUCTURE_TYPE_PARAMETER);
297 }
298 
299 void icalparameter_set_xname(icalparameter *param, const char *v)
300 {
301  icalerror_check_arg_rv((param != 0), "param");
302  icalerror_check_arg_rv((v != 0), "v");
303 
304  icalmemory_free_buffer((void *)param->x_name);
305  param->x_name = icalmemory_strdup(v);
306 
307  if (param->x_name == 0) {
308  errno = ENOMEM;
309  }
310 }
311 
312 const char *icalparameter_get_xname(const icalparameter *param)
313 {
314  icalerror_check_arg_rz((param != 0), "param");
315 
316  return param->x_name;
317 }
318 
319 void icalparameter_set_xvalue(icalparameter *param, const char *v)
320 {
321  icalerror_check_arg_rv((param != 0), "param");
322  icalerror_check_arg_rv((v != 0), "v");
323 
324  icalmemory_free_buffer((void *)param->string);
325  param->string = icalmemory_strdup(v);
326 
327  if (param->string == 0) {
328  errno = ENOMEM;
329  }
330 }
331 
332 const char *icalparameter_get_xvalue(const icalparameter *param)
333 {
334  icalerror_check_arg_rz((param != 0), "param");
335 
336  return param->string;
337 }
338 
339 void icalparameter_set_iana_value(icalparameter *param, const char *v)
340 {
341  icalparameter_set_xvalue(param, v);
342 }
343 
344 const char *icalparameter_get_iana_value(const icalparameter *param)
345 {
346  return icalparameter_get_xvalue(param);
347 }
348 
349 void icalparameter_set_iana_name(icalparameter *param, const char *v)
350 {
351  icalparameter_set_xname(param, v);
352 }
353 
354 const char *icalparameter_get_iana_name(const icalparameter *param)
355 {
356  return icalparameter_get_xname(param);
357 }
358 
359 void icalparameter_set_parent(icalparameter *param, icalproperty *property)
360 {
361  icalerror_check_arg_rv((param != 0), "param");
362 
363  param->parent = property;
364 }
365 
366 icalproperty *icalparameter_get_parent(const icalparameter *param)
367 {
368  icalerror_check_arg_rz((param != 0), "param");
369 
370  return param->parent;
371 }
372 
373 bool icalparameter_has_same_name(const icalparameter *param1, const icalparameter *param2)
374 {
375  icalparameter_kind kind1;
376  icalparameter_kind kind2;
377  const char *name1;
378  const char *name2;
379 
380  icalerror_check_arg_rz((param1 != 0), "param1");
381  icalerror_check_arg_rz((param2 != 0), "param2");
382 
383  kind1 = icalparameter_isa(param1);
384  kind2 = icalparameter_isa(param2);
385 
386  if (kind1 != kind2) {
387  return false;
388  }
389 
390  if (kind1 == ICAL_X_PARAMETER) {
391  name1 = icalparameter_get_xname(param1);
392  name2 = icalparameter_get_xname(param2);
393  if (strcasecmp(name1, name2) != 0) {
394  return false;
395  }
396  } else if (kind1 == ICAL_IANA_PARAMETER) {
397  name1 = icalparameter_get_iana_name(param1);
398  name2 = icalparameter_get_iana_name(param2);
399  if (strcasecmp(name1, name2) != 0) {
400  return false;
401  }
402  }
403  return true;
404 }
405 
406 bool icalparameter_is_multivalued(const icalparameter *param)
407 {
408  icalerror_check_arg_rz((param != 0), "param");
409 
410  return param->is_multivalued;
411 }
412 
413 void icalparameter_decode_value(char *value)
414 {
415  char *in, *out;
416 
417  for (in = out = value; *in; in++, out++) {
418  int found_escaped_char = 0;
419 
420  if (*in == '^') {
421  switch (*(in + 1)) {
422  case 'n':
423  *out = '\n';
424  found_escaped_char = 1;
425  break;
426  case '^':
427  *out = '^';
428  found_escaped_char = 1;
429  break;
430 
431  case '\'':
432  *out = '"';
433  found_escaped_char = 1;
434  break;
435  default:
436  break;
437  }
438  }
439 
440  if (found_escaped_char) {
441  ++in;
442  } else {
443  *out = *in;
444  }
445  }
446 
447  while (*out) {
448  *out++ = '\0';
449  }
450 }
451 
452 /* Everything below this line is machine generated. Do not edit. */
453 /* ALTREP */
void icalparameter_set_parent(icalparameter *param, icalproperty *property)
void icalparameter_decode_value(char *value)
icalparameter_kind icalparameter_isa(const icalparameter *parameter)
void icalparameter_free(icalparameter *param)
Frees an icalparameter object.
Definition: icalparameter.c:58
const char * icalparameter_get_iana_name(const icalparameter *param)
Returns the IANA name of param.
icalparameter * icalparameter_clone(const icalparameter *old)
Creates new icalparameter as a clone of the given one.
Definition: icalparameter.c:86
icalvalue_kind icalparameter_kind_value_kind(const icalparameter_kind kind, int *is_multivalued)
Common memory management routines.
void icalparameter_set_iana_name(icalparameter *param, const char *v)
Sets the IANA name of param to v.
void icalenumarray_free(icalenumarray *array)
Frees this array's memory and all its elements.
icalproperty * icalparameter_get_parent(const icalparameter *param)
const char * icalparameter_kind_to_string(icalparameter_kind kind)
Returns a string representing the given icalparameter_kind.
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
const char * icalstrarray_element_at(icalstrarray *array, size_t position)
Accesses a string stored in the array.
Definition: icalstrarray.c:32
bool icalparameter_isa_parameter(void *parameter)
void icalstrarray_free(icalstrarray *array)
Frees this array's memory and all its elements.
Definition: icalstrarray.c:116
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition: icalerror.c:90
bool icalparameter_has_same_name(const icalparameter *param1, const icalparameter *param2)
Determines if two parameters have the same name.
void icalparameter_set_iana_value(icalparameter *param, const char *v)
Sets the IANA value of param to v.
icalenumarray * icalenumarray_clone(icalenumarray *array)
Clones the array and all its elements.
void icalmemory_append_encoded_string(char **buf, char **pos, size_t *buf_size, const char *string)
Definition: icalmemory.c:478
void icalparameter_set_xvalue(icalparameter *param, const char *v)
Sets the X-value of param to v.
bool icalparameter_is_multivalued(const icalparameter *param)
const char * icalparameter_get_iana_value(const icalparameter *param)
Returns the IANA value of param.
char * icaldurationtype_as_ical_string_r(struct icaldurationtype d)
Definition: icalduration.c:190
char * icalparameter_as_ical_string(icalparameter *param)
Converts icalparameter into a string representation.
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
const char * icalparameter_get_xvalue(const icalparameter *param)
Returns the X-value of param.
char * icalparameter_as_ical_string_r(icalparameter *param)
Converts icalparameter into a string representation according to RFC5445/RFC6868. ...
Defines the data structure representing iCalendar parameters.
void icalparameter_set_xname(icalparameter *param, const char *v)
Sets the X-name of param to v.
icalparameter * icalparameter_new_from_value_string(icalparameter_kind kind, const char *value)
Creates new icalparameter of a given kind with a given value.
icalstrarray * icalstrarray_clone(icalstrarray *array)
Clones the array and all its elements.
Definition: icalstrarray.c:145
icalparameter_kind icalparameter_string_to_kind(const char *string)
Returns the icalparameter_kind for a given string.
const char * icalparameter_get_xname(const icalparameter *param)
Returns the X-name of param.
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Definition: icalmemory.c:158
icalparameter * icalparameter_new(icalparameter_kind kind)
Creates new icalparameter object.
Definition: icalparameter.c:51
const icalenumarray_element * icalenumarray_element_at(icalenumarray *array, size_t position)
Accesses an element stored in the array.
Definition: icalenumarray.c:31
icalparameter * icalparameter_new_from_string(const char *str)
Creates new icalparameter object from string.