1 /*======================================================================
2 FILE: icalderivedparameters.{c,h}
3 CREATOR: eric 09 May 1999
4
5 (C) COPYRIGHT 2000, Eric Busboom <eric@civicknowledge.com>
6
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of either:
9
10 The LGPL as published by the Free Software Foundation, version
11 2.1, available at: https://www.gnu.org/licenses/lgpl-2.1.html
12
13 Or:
14
15 The Mozilla Public License Version 2.0. You may obtain a copy of
16 the License at https://www.mozilla.org/MPL/
17
18 The original code is icalderivedparameters.{c,h}
19
20 Contributions from:
21 Graham Davison <g.m.davison@computer.org>
22 ======================================================================*/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include "icalparameter.h"
28 #include "icalparameterimpl.h"
29 #include "icalerror.h"
30 #include "icalmemory.h"
31
32 #include <errno.h>
33 #include <stdlib.h>
34
icalparameter_new_impl(icalparameter_kind kind)35 LIBICAL_ICAL_EXPORT struct icalparameter_impl *icalparameter_new_impl(icalparameter_kind kind)
36 {
37 struct icalparameter_impl *v;
38
39 if ((v = (struct icalparameter_impl *)malloc(sizeof(struct icalparameter_impl))) == 0) {
40 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
41 return 0;
42 }
43
44 memset(v, 0, sizeof(struct icalparameter_impl));
45
46 strcpy(v->id, "para");
47
48 v->kind = kind;
49
50 return v;
51 }
52
icalparameter_new(icalparameter_kind kind)53 icalparameter *icalparameter_new(icalparameter_kind kind)
54 {
55 struct icalparameter_impl *v = icalparameter_new_impl(kind);
56
57 return (icalparameter *) v;
58 }
59
icalparameter_free(icalparameter * param)60 void icalparameter_free(icalparameter *param)
61 {
62 /* Comment out the following as it always triggers, even when parameter is non-zero
63 icalerror_check_arg_rv((parameter==0),"parameter");*/
64
65 if (param->parent != 0) {
66 return;
67 }
68
69 if (param->string != 0) {
70 free((void *)param->string);
71 }
72
73 if (param->x_name != 0) {
74 free((void *)param->x_name);
75 }
76
77 memset(param, 0, sizeof(icalparameter));
78
79 param->parent = 0;
80 param->id[0] = 'X';
81 free(param);
82 }
83
icalparameter_new_clone(icalparameter * old)84 icalparameter *icalparameter_new_clone(icalparameter *old)
85 {
86 struct icalparameter_impl *new;
87
88 icalerror_check_arg_rz((old != 0), "param");
89
90 new = icalparameter_new_impl(old->kind);
91
92 if (new == 0) {
93 return 0;
94 }
95
96 memcpy(new, old, sizeof(struct icalparameter_impl));
97
98 if (old->string != 0) {
99 new->string = icalmemory_strdup(old->string);
100 if (new->string == 0) {
101 new->parent = 0;
102 icalparameter_free(new);
103 return 0;
104 }
105 }
106
107 if (old->x_name != 0) {
108 new->x_name = icalmemory_strdup(old->x_name);
109 if (new->x_name == 0) {
110 new->parent = 0;
111 icalparameter_free(new);
112 return 0;
113 }
114 }
115
116 return new;
117 }
118
icalparameter_new_from_string(const char * str)119 icalparameter *icalparameter_new_from_string(const char *str)
120 {
121 char *eq;
122 char *cpy;
123 icalparameter_kind kind;
124 icalparameter *param;
125
126 icalerror_check_arg_rz(str != 0, "str");
127
128 cpy = icalmemory_strdup(str);
129
130 if (cpy == 0) {
131 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
132 return 0;
133 }
134
135 eq = strchr(cpy, '=');
136
137 if (eq == 0) {
138 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
139 free(cpy);
140 return 0;
141 }
142
143 *eq = '\0';
144
145 eq++;
146
147 kind = icalparameter_string_to_kind(cpy);
148
149 if (kind == ICAL_NO_PARAMETER) {
150 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
151 free(cpy);
152 return 0;
153 }
154
155 param = icalparameter_new_from_value_string(kind, eq);
156
157 if (kind == ICAL_X_PARAMETER) {
158 icalparameter_set_xname(param, cpy);
159 } else if (kind == ICAL_IANA_PARAMETER) {
160 icalparameter_set_iana_name(param, cpy);
161 }
162
163 free(cpy);
164
165 return param;
166 }
167
icalparameter_as_ical_string(icalparameter * param)168 char *icalparameter_as_ical_string(icalparameter *param)
169 {
170 char *buf;
171
172 buf = icalparameter_as_ical_string_r(param);
173 icalmemory_add_tmp_buffer(buf);
174 return buf;
175 }
176
177 /*
178 * checks whether this character is allowed in a (Q)SAFE-CHAR
179 *
180 * QSAFE-CHAR = WSP / %x21 / %x23-7E / NON-US-ASCII
181 * ; any character except CTLs and DQUOTE
182 * SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E / NON-US-ASCII
183 * ; any character except CTLs, DQUOTE. ";", ":", ","
184 * WSP = SPACE / HTAB
185 * NON-US-ASCII = %x80-F8
186 * ; Use restricted by charset parameter
187 * ; on outer MIME object (UTF-8 preferred)
188 */
icalparameter_is_safe_char(unsigned char character,int quoted)189 static int icalparameter_is_safe_char(unsigned char character, int quoted)
190 {
191 if (character == ' ' || character == '\t' || character == '!' ||
192 (character >= 0x80 && character <= 0xF8)) {
193 return 1;
194 }
195
196 if (quoted && character >= 0x23 && character <= 0x7e) {
197 return 1;
198 }
199 else if (!quoted &&
200 ((character >= 0x23 && character <= 0x2b) ||
201 (character >= 0x2d && character <= 0x39) ||
202 (character >= 0x3c && character <= 0x7e))) {
203 return 1;
204 }
205
206 return 0;
207 }
208
209 /**
210 * Appends the parameter value to the buffer, encoding per RFC 6868
211 * and filtering out those characters not permitted by the specifications
212 *
213 * paramtext = *SAFE-CHAR
214 * quoted-string= DQUOTE *QSAFE-CHAR DQUOTE
215 */
icalparameter_append_encoded_value(char ** buf,char ** buf_ptr,size_t * buf_size,const char * value)216 static void icalparameter_append_encoded_value(char **buf, char **buf_ptr,
217 size_t *buf_size, const char *value)
218 {
219 int qm = 0;
220 const char *p;
221
222 /* Encapsulate the property in quotes if necessary */
223 if (strpbrk(value, ";:,") != 0) {
224 icalmemory_append_char(buf, buf_ptr, buf_size, '"');
225 qm = 1;
226 }
227
228 /* Copy the parameter value */
229 for (p = value; *p; p++) {
230 if (icalparameter_is_safe_char((unsigned char)*p, qm)) {
231 icalmemory_append_char(buf, buf_ptr, buf_size, *p);
232 } else {
233 /* Encode unsafe characters per RFC6868, otherwise replace with SP */
234 switch (*p) {
235 case '\n':
236 icalmemory_append_string(buf, buf_ptr, buf_size, "^n");
237 break;
238
239 case '^':
240 icalmemory_append_string(buf, buf_ptr, buf_size, "^^");
241 break;
242
243 case '"':
244 icalmemory_append_string(buf, buf_ptr, buf_size, "^'");
245 break;
246
247 default:
248 icalmemory_append_char(buf, buf_ptr, buf_size, ' ');
249 break;
250 }
251 }
252 }
253
254 if (qm == 1) {
255 icalmemory_append_char(buf, buf_ptr, buf_size, '"');
256 }
257 }
258
259 /**
260 * Return a string representation of the parameter according to RFC5445/RFC6868.
261 *
262 * param = param-name "=" param-value
263 * param-name = iana-token / x-token
264 * param-value = paramtext /quoted-string
265 * paramtext = *SAFE-CHAR
266 * quoted-string= DQUOTE *QSAFE-CHAR DQUOTE
267 * QSAFE-CHAR = any character except CTLs and DQUOTE
268 * SAFE-CHAR = any character except CTLs, DQUOTE. ";", ":", ","
269 */
icalparameter_as_ical_string_r(icalparameter * param)270 char *icalparameter_as_ical_string_r(icalparameter *param)
271 {
272 size_t buf_size = 1024;
273 char *buf;
274 char *buf_ptr;
275 const char *kind_string;
276
277 icalerror_check_arg_rz((param != 0), "parameter");
278
279 /* Create new buffer that we can append names, parameters and a
280 * value to, and reallocate as needed.
281 */
282
283 buf = icalmemory_new_buffer(buf_size);
284 buf_ptr = buf;
285
286 if (param->kind == ICAL_X_PARAMETER) {
287 icalmemory_append_string(&buf, &buf_ptr, &buf_size, icalparameter_get_xname(param));
288 } else if (param->kind == ICAL_IANA_PARAMETER) {
289 icalmemory_append_string(&buf, &buf_ptr, &buf_size, icalparameter_get_iana_name(param));
290 } else {
291
292 kind_string = icalparameter_kind_to_string(param->kind);
293
294 if (param->kind == ICAL_NO_PARAMETER ||
295 param->kind == ICAL_ANY_PARAMETER || kind_string == 0) {
296 icalerror_set_errno(ICAL_BADARG_ERROR);
297 free(buf);
298 return 0;
299 }
300
301 /* Put the parameter name into the string */
302 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
303 }
304
305 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "=");
306
307 if (param->string != 0) {
308 icalparameter_append_encoded_value(&buf, &buf_ptr, &buf_size, param->string);
309 } else if (param->data != 0) {
310 const char *str = icalparameter_enum_to_string(param->data);
311
312 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
313 } else {
314 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
315 free(buf);
316 return 0;
317 }
318
319 return buf;
320 }
321
icalparameter_isa(icalparameter * parameter)322 icalparameter_kind icalparameter_isa(icalparameter *parameter)
323 {
324 if (parameter == 0) {
325 return ICAL_NO_PARAMETER;
326 }
327
328 return parameter->kind;
329 }
330
icalparameter_isa_parameter(void * parameter)331 int icalparameter_isa_parameter(void *parameter)
332 {
333 struct icalparameter_impl *impl = (struct icalparameter_impl *)parameter;
334
335 if (parameter == 0) {
336 return 0;
337 }
338
339 if (strcmp(impl->id, "para") == 0) {
340 return 1;
341 } else {
342 return 0;
343 }
344 }
345
icalparameter_set_xname(icalparameter * param,const char * v)346 void icalparameter_set_xname(icalparameter *param, const char *v)
347 {
348 icalerror_check_arg_rv((param != 0), "param");
349 icalerror_check_arg_rv((v != 0), "v");
350
351 if (param->x_name != 0) {
352 free((void *)param->x_name);
353 }
354
355 param->x_name = icalmemory_strdup(v);
356
357 if (param->x_name == 0) {
358 errno = ENOMEM;
359 }
360 }
361
icalparameter_get_xname(icalparameter * param)362 const char *icalparameter_get_xname(icalparameter *param)
363 {
364 icalerror_check_arg_rz((param != 0), "param");
365
366 return param->x_name;
367 }
368
icalparameter_set_xvalue(icalparameter * param,const char * v)369 void icalparameter_set_xvalue(icalparameter *param, const char *v)
370 {
371 icalerror_check_arg_rv((param != 0), "param");
372 icalerror_check_arg_rv((v != 0), "v");
373
374 if (param->string != 0) {
375 free((void *)param->string);
376 }
377
378 param->string = icalmemory_strdup(v);
379
380 if (param->string == 0) {
381 errno = ENOMEM;
382 }
383 }
384
icalparameter_get_xvalue(icalparameter * param)385 const char *icalparameter_get_xvalue(icalparameter *param)
386 {
387 icalerror_check_arg_rz((param != 0), "param");
388
389 return param->string;
390 }
391
icalparameter_set_iana_value(icalparameter * param,const char * v)392 void icalparameter_set_iana_value(icalparameter *param, const char *v)
393 {
394 icalparameter_set_xvalue(param, v);
395 }
396
icalparameter_get_iana_value(icalparameter * param)397 const char *icalparameter_get_iana_value(icalparameter *param)
398 {
399 return icalparameter_get_xvalue(param);
400 }
401
icalparameter_set_iana_name(icalparameter * param,const char * v)402 void icalparameter_set_iana_name(icalparameter *param, const char *v)
403 {
404 icalparameter_set_xname(param, v);
405 }
406
icalparameter_get_iana_name(icalparameter * param)407 const char *icalparameter_get_iana_name(icalparameter *param)
408 {
409 return icalparameter_get_xname(param);
410 }
411
icalparameter_set_parent(icalparameter * param,icalproperty * property)412 void icalparameter_set_parent(icalparameter *param, icalproperty *property)
413 {
414 icalerror_check_arg_rv((param != 0), "param");
415
416 param->parent = property;
417 }
418
icalparameter_get_parent(icalparameter * param)419 icalproperty *icalparameter_get_parent(icalparameter *param)
420 {
421 icalerror_check_arg_rz((param != 0), "param");
422
423 return param->parent;
424 }
425
426 /* returns 1 if parameters have same name in ICAL, otherwise 0 */
icalparameter_has_same_name(icalparameter * param1,icalparameter * param2)427 int icalparameter_has_same_name(icalparameter *param1, icalparameter *param2)
428 {
429 icalparameter_kind kind1;
430 icalparameter_kind kind2;
431 const char *name1;
432 const char *name2;
433
434 icalerror_check_arg_rz((param1 != 0), "param1");
435 icalerror_check_arg_rz((param2 != 0), "param2");
436
437 kind1 = icalparameter_isa(param1);
438 kind2 = icalparameter_isa(param2);
439
440 if (kind1 != kind2)
441 return 0;
442
443 if (kind1 == ICAL_X_PARAMETER) {
444 name1 = icalparameter_get_xname(param1);
445 name2 = icalparameter_get_xname(param2);
446 if (strcasecmp(name1, name2) != 0) {
447 return 0;
448 }
449 } else if (kind1 == ICAL_IANA_PARAMETER) {
450 name1 = icalparameter_get_iana_name(param1);
451 name2 = icalparameter_get_iana_name(param2);
452 if (strcasecmp(name1, name2) != 0) {
453 return 0;
454 }
455 }
456 return 1;
457 }
458
459 /* Everything below this line is machine generated. Do not edit. */
460 /* ALTREP */
461