1 /* -*- Mode: C -*- */
2
3 /*======================================================================
4 FILE: icalproperty.c
5 CREATOR: eric 28 April 1999
6
7 $Id: icalproperty.c,v 1.44 2008-01-30 20:28:42 dothebart Exp $
8
9
10 (C) COPYRIGHT 2000, Eric Busboom <eric@softwarestudio.org>
11 http://www.softwarestudio.org
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of either:
15
16 The LGPL as published by the Free Software Foundation, version
17 2.1, available at: http://www.fsf.org/copyleft/lesser.html
18
19 Or:
20
21 The Mozilla Public License Version 1.0. You may obtain a copy of
22 the License at http://www.mozilla.org/MPL/
23
24 The original code is icalproperty.c
25
26 ======================================================================*/
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "icalproperty.h"
33 #include "icalparameter.h"
34 #include "icalcomponent.h"
35 #include "pvl.h"
36 #include "icalenums.h"
37 #include "icalerror.h"
38 #include "icalmemory.h"
39 #include "icalparser.h"
40
41 #include <string.h> /* For icalmemory_strdup, rindex */
42 #include <assert.h>
43 #include <stdlib.h>
44 #include <errno.h>
45 #include <stdio.h> /* for printf */
46 #include <stdarg.h> /* for va_list, va_start, etc. */
47
48 #ifdef WIN32
49 #if defined(_MSC_VER) && (_MSC_VER < 1900)
50 #define snprintf _snprintf
51 #endif
52 #define strcasecmp stricmp
53 #endif
54
55 /* Private routines for icalproperty */
56 void icalvalue_set_parent(icalvalue* value,
57 icalproperty* property);
58 icalproperty* icalvalue_get_parent(icalvalue* value);
59
60 void icalparameter_set_parent(icalparameter* param,
61 icalproperty* property);
62 icalproperty* icalparameter_get_parent(icalparameter* value);
63
64
65 void icalproperty_set_x_name(icalproperty* prop, const char* name);
66
67 struct icalproperty_impl
68 {
69 char id[5];
70 icalproperty_kind kind;
71 char* x_name;
72 pvl_list parameters;
73 pvl_elem parameter_iterator;
74 icalvalue* value;
75 icalcomponent *parent;
76 };
77
icalproperty_add_parameters(icalproperty * prop,va_list args)78 void icalproperty_add_parameters(icalproperty* prop, va_list args)
79 {
80 void* vp;
81
82 while((vp = va_arg(args, void*)) != 0) {
83
84 if (icalvalue_isa_value(vp) != 0 ){
85 } else if (icalparameter_isa_parameter(vp) != 0 ){
86
87 icalproperty_add_parameter((icalproperty*)prop,
88 (icalparameter*)vp);
89 } else {
90 icalerror_set_errno(ICAL_BADARG_ERROR);
91 }
92
93 }
94 }
95
96
97 icalproperty*
icalproperty_new_impl(icalproperty_kind kind)98 icalproperty_new_impl(icalproperty_kind kind)
99 {
100 icalproperty* prop;
101
102 if (!icalproperty_kind_is_valid(kind))
103 return NULL;
104
105 if ( ( prop = (icalproperty*) malloc(sizeof(icalproperty))) == 0) {
106 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
107 return 0;
108 }
109
110 strcpy(prop->id,"prop");
111
112 prop->kind = kind;
113 prop->parameters = pvl_newlist();
114 prop->parameter_iterator = 0;
115 prop->value = 0;
116 prop->x_name = 0;
117 prop->parent = 0;
118
119 return prop;
120 }
121
122
123 icalproperty*
icalproperty_new(icalproperty_kind kind)124 icalproperty_new (icalproperty_kind kind)
125 {
126 if (kind == ICAL_NO_PROPERTY){
127 return 0;
128 }
129
130 return (icalproperty*)icalproperty_new_impl(kind);
131 }
132
133
134 icalproperty*
icalproperty_new_clone(icalproperty * old)135 icalproperty_new_clone(icalproperty* old)
136 {
137 icalproperty *new;
138 pvl_elem p;
139
140 icalerror_check_arg_rz((old!=0),"old");
141
142 new = icalproperty_new_impl(old->kind);
143 icalerror_check_arg_rz((new!=0),"new");
144
145 if (old->value !=0) {
146 new->value = icalvalue_new_clone(old->value);
147 }
148
149 if (old->x_name != 0) {
150
151 new->x_name = icalmemory_strdup(old->x_name);
152
153 if (new->x_name == 0) {
154 icalproperty_free(new);
155 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
156 return 0;
157 }
158 }
159
160 for(p=pvl_head(old->parameters);p != 0; p = pvl_next(p)){
161 icalparameter *param = icalparameter_new_clone(pvl_data(p));
162
163 if (param == 0){
164 icalproperty_free(new);
165 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
166 return 0;
167 }
168
169 pvl_push(new->parameters,param);
170
171 }
172
173 return new;
174
175 }
176
icalproperty_new_from_string(const char * str)177 icalproperty* icalproperty_new_from_string(const char* str)
178 {
179
180 size_t buf_size = 1024;
181 char* buf;
182 char* buf_ptr;
183 icalproperty *prop;
184 icalcomponent *comp;
185 int errors = 0;
186
187 icalerror_check_arg_rz( (str!=0),"str");
188
189 buf = icalmemory_new_buffer(buf_size);
190 buf_ptr = buf;
191
192 /* Is this a HACK or a crafty reuse of code? */
193
194 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:VCALENDAR\r\n");
195 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
196 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "\r\n");
197 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:VCALENDAR\r\n");
198
199 comp = icalparser_parse_string(buf);
200
201 if(comp == 0){
202 icalerror_set_errno(ICAL_PARSE_ERROR);
203 free(buf);
204 return 0;
205 }
206
207 errors = icalcomponent_count_errors(comp);
208
209 prop = icalcomponent_get_first_property(comp,ICAL_ANY_PROPERTY);
210
211 icalcomponent_remove_property(comp,prop);
212
213 icalcomponent_free(comp);
214 free(buf);
215
216 if(errors > 0){
217 icalproperty_free(prop);
218 return 0;
219 } else {
220 return prop;
221 }
222
223 }
224
225 void
icalproperty_free(icalproperty * p)226 icalproperty_free (icalproperty* p)
227 {
228 icalparameter* param;
229
230 icalerror_check_arg_rv((p!=0),"prop");
231
232 #ifdef ICAL_FREE_ON_LIST_IS_ERROR
233 icalerror_assert( (p->parent ==0),"Tried to free a property that is still attached to a component. ");
234
235 #else
236 if(p->parent !=0){
237 return;
238 }
239 #endif
240
241 if (p->value != 0){
242 icalvalue_set_parent(p->value,0);
243 icalvalue_free(p->value);
244 }
245
246 while( (param = pvl_pop(p->parameters)) != 0){
247 icalparameter_free(param);
248 }
249
250 pvl_free(p->parameters);
251
252 if (p->x_name != 0) {
253 free(p->x_name);
254 }
255
256 p->kind = ICAL_NO_PROPERTY;
257 p->parameters = 0;
258 p->parameter_iterator = 0;
259 p->value = 0;
260 p->x_name = 0;
261 p->id[0] = 'X';
262
263 free(p);
264
265 }
266
267
268 /* This returns where the start of the next line should be. chars_left does
269 not include the trailing '\0'. */
270 #define MAX_LINE_LEN 75
271 /*#define MAX_LINE_LEN 120*/
272
273 static char*
get_next_line_start(char * line_start,int chars_left)274 get_next_line_start (char *line_start, int chars_left)
275 {
276 char *pos;
277
278 /* If we have 74 chars or less left, we can output all of them.
279 we return a pointer to the '\0' at the end of the string. */
280 if (chars_left < MAX_LINE_LEN) {
281 return line_start + chars_left;
282 }
283
284 /* Now try to split on a UTF-8 boundary defined as a 7-bit
285 value or as a byte with the two high-most bits set:
286 11xxxxxx. See http://czyborra.com/utf/ */
287
288 pos = line_start + MAX_LINE_LEN - 1;
289 while (pos > line_start) {
290 /* plain ascii */
291 if ((*pos & 128) == 0)
292 return pos;
293
294 /* utf8 escape byte */
295 if ((*pos & 192) == 192)
296 return pos;
297
298 pos--;
299 }
300
301 /* Give up, just break at 74 chars (the 75th char is the space at
302 the start of the line). */
303
304 return line_start + MAX_LINE_LEN - 1;
305 }
306
307
308 /** This splits the property into lines less than 75 octects long (as
309 * specified in RFC2445). It tries to split after a ';' if it can.
310 * It returns a tmp buffer. NOTE: I'm not sure if it matters if we
311 * split a line in the middle of a UTF-8 character. It probably won't
312 * look nice in a text editor.
313 */
314 static char*
fold_property_line(char * text)315 fold_property_line (char *text)
316 {
317 size_t buf_size;
318 char *buf, *buf_ptr, *line_start, *next_line_start;
319 int len, chars_left, first_line;
320 char ch;
321
322 /* Start with a buffer twice the size of our property line, so we almost
323 certainly won't overflow it. */
324 len = strlen (text);
325 buf_size = len * 2;
326 buf = icalmemory_new_buffer (buf_size);
327 buf_ptr = buf;
328
329 /* Step through the text, finding each line to add to the output. */
330 line_start = text;
331 chars_left = len;
332 first_line = 1;
333 for (;;) {
334 if (chars_left <= 0)
335 break;
336
337 /* This returns the first character for the next line. */
338 next_line_start = get_next_line_start (line_start, chars_left);
339
340 /* If this isn't the first line, we need to output a newline and space
341 first. */
342 if (!first_line) {
343 icalmemory_append_string (&buf, &buf_ptr, &buf_size, "\r\n ");
344 }
345 first_line = 0;
346
347 /* This adds the line to our tmp buffer. We temporarily place a '\0'
348 in text, so we can copy the line in one go. */
349 ch = *next_line_start;
350 *next_line_start = '\0';
351 icalmemory_append_string (&buf, &buf_ptr, &buf_size, line_start);
352 *next_line_start = ch;
353
354 /* Now we move on to the next line. */
355 chars_left -= (next_line_start - line_start);
356 line_start = next_line_start;
357 }
358
359 return buf;
360 }
361
362
363 /* Determine what VALUE parameter to include. The VALUE parameters
364 are ignored in the normal parameter printing ( the block after
365 this one, so we need to do it here */
366 static const char *
icalproperty_get_value_kind(icalproperty * prop)367 icalproperty_get_value_kind(icalproperty *prop)
368 {
369 const char* kind_string = 0;
370
371 icalparameter *orig_val_param
372 = icalproperty_get_first_parameter(prop,ICAL_VALUE_PARAMETER);
373
374 icalvalue *value = icalproperty_get_value(prop);
375
376 icalvalue_kind orig_kind = ICAL_NO_VALUE;
377
378 icalvalue_kind this_kind = ICAL_NO_VALUE;
379
380 icalvalue_kind default_kind
381 = icalproperty_kind_to_value_kind(prop->kind);
382
383 if(orig_val_param){
384 orig_kind = icalparameter_value_to_value_kind( icalparameter_get_value(orig_val_param) );
385 }
386
387 if(value != 0){
388 this_kind = icalvalue_isa(value);
389 }
390
391 if ( orig_kind != ICAL_NO_VALUE ) {
392 kind_string = icalvalue_kind_to_string( orig_kind );
393 } else if(this_kind == default_kind &&
394 orig_kind != ICAL_NO_VALUE){
395 /* The kind is the default, so it does not need to be
396 included, but do it anyway, since it was explicit in
397 the property. But, use the default, not the one
398 specified in the property */
399
400 kind_string = icalvalue_kind_to_string(default_kind);
401
402 } else if (this_kind != default_kind && this_kind != ICAL_NO_VALUE){
403 /* Not the default, so it must be specified */
404 kind_string = icalvalue_kind_to_string(this_kind);
405 } else {
406 /* Don'tinclude the VALUE parameter at all */
407 }
408
409 return kind_string;
410 }
411
412 const char*
icalproperty_as_ical_string(icalproperty * prop)413 icalproperty_as_ical_string (icalproperty* prop)
414 {
415 char *buf;
416 buf = icalproperty_as_ical_string_r(prop);
417 icalmemory_add_tmp_buffer(buf);
418 return buf;
419 }
420
421
422 char*
icalproperty_as_ical_string_r(icalproperty * prop)423 icalproperty_as_ical_string_r(icalproperty* prop)
424 {
425 icalparameter *param;
426
427 /* Create new buffer that we can append names, parameters and a
428 * value to, and reallocate as needed.
429 */
430
431 const char* property_name = 0;
432 size_t buf_size = 1024;
433 char* buf;
434 char* buf_ptr;
435 icalvalue* value;
436 char *out_buf;
437 const char* kind_string = 0;
438 const char newline[] = "\r\n";
439
440
441 icalerror_check_arg_rz( (prop!=0),"prop");
442
443 buf = icalmemory_new_buffer(buf_size);
444 buf_ptr = buf;
445
446 /* Append property name */
447
448 if (prop->kind == ICAL_X_PROPERTY && prop->x_name != 0){
449 property_name = prop->x_name;
450 } else {
451 property_name = icalproperty_kind_to_string(prop->kind);
452 }
453
454 if (property_name == 0 ) {
455 icalerror_warn("Got a property of an unknown kind.");
456 icalmemory_free_buffer(buf);
457 return 0;
458
459 }
460
461 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
462
463 kind_string = icalproperty_get_value_kind(prop);
464 if(kind_string!=0){
465 icalmemory_append_string(&buf, &buf_ptr, &buf_size, ";VALUE=");
466 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
467 }
468
469 /* Append parameters */
470 for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
471 param != 0;
472 param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) {
473
474 icalparameter_kind kind = icalparameter_isa(param);
475 kind_string = icalparameter_as_ical_string_r(param);
476
477 if (kind_string == 0 ) {
478 icalerror_warn("Got a parameter of unknown kind for the following property");
479
480 icalerror_warn((property_name) ? property_name : "(NULL)");
481 continue;
482 }
483
484 if (kind==ICAL_VALUE_PARAMETER) {
485 free ((char *) kind_string);
486 continue;
487 }
488
489 icalmemory_append_string(&buf, &buf_ptr, &buf_size, ";");
490 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
491 free((char *)kind_string);
492 }
493
494 /* Append value */
495
496 icalmemory_append_string(&buf, &buf_ptr, &buf_size, ":");
497
498 value = icalproperty_get_value(prop);
499
500 if (value != 0){
501 char *str = icalvalue_as_ical_string_r(value);
502 if (str != 0)
503 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
504 else
505 icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value");
506 free(str);
507 } else {
508 icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value");
509
510 }
511
512 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
513
514 /* We now use a function to fold the line properly every 75 characters.
515 That function also adds the newline for us. */
516 out_buf = fold_property_line (buf);
517
518 icalmemory_free_buffer(buf);
519
520 return out_buf;
521 }
522
523
524
525 icalproperty_kind
icalproperty_isa(icalproperty * p)526 icalproperty_isa (icalproperty* p)
527 {
528 if(p != 0){
529 return p->kind;
530 }
531
532 return ICAL_NO_PROPERTY;
533 }
534
535 int
icalproperty_isa_property(void * property)536 icalproperty_isa_property (void* property)
537 {
538 icalproperty *impl = (icalproperty *) property;
539
540 icalerror_check_arg_rz( (property!=0), "property");
541 if (strcmp(impl->id,"prop") == 0) {
542 return 1;
543 } else {
544 return 0;
545 }
546 }
547
548
549 void
icalproperty_add_parameter(icalproperty * p,icalparameter * parameter)550 icalproperty_add_parameter (icalproperty* p,icalparameter* parameter)
551 {
552 icalerror_check_arg_rv( (p!=0),"prop");
553 icalerror_check_arg_rv( (parameter!=0),"parameter");
554
555 pvl_push(p->parameters, parameter);
556
557 }
558
559 void
icalproperty_set_parameter(icalproperty * prop,icalparameter * parameter)560 icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter)
561 {
562 icalparameter_kind kind;
563
564 icalerror_check_arg_rv( (prop!=0),"prop");
565 icalerror_check_arg_rv( (parameter!=0),"parameter");
566
567 kind = icalparameter_isa(parameter);
568 if (kind == ICAL_X_PARAMETER) {
569 icalproperty_remove_parameter_by_name(prop,
570 icalparameter_get_xname(parameter));
571 } else if (kind == ICAL_IANA_PARAMETER) {
572 icalproperty_remove_parameter_by_name(prop,
573 icalparameter_get_iana_name(parameter));
574 }
575 else
576 icalproperty_remove_parameter_by_kind(prop,kind);
577
578 icalproperty_add_parameter(prop,parameter);
579 }
580
icalproperty_set_parameter_from_string(icalproperty * prop,const char * name,const char * value)581 void icalproperty_set_parameter_from_string(icalproperty* prop,
582 const char* name, const char* value)
583 {
584
585 icalparameter_kind kind;
586 icalparameter *param;
587
588 icalerror_check_arg_rv( (prop!=0),"prop");
589 icalerror_check_arg_rv( (name!=0),"name");
590 icalerror_check_arg_rv( (value!=0),"value");
591
592 kind = icalparameter_string_to_kind(name);
593
594 if(kind == ICAL_NO_PARAMETER){
595 icalerror_set_errno(ICAL_BADARG_ERROR);
596 return;
597 }
598
599 param = icalparameter_new_from_value_string(kind,value);
600
601 if (param == 0){
602 icalerror_set_errno(ICAL_BADARG_ERROR);
603 return;
604 }
605
606 if (kind == ICAL_X_PARAMETER) {
607 icalparameter_set_xname(param, name);
608 } else if (kind == ICAL_IANA_PARAMETER) {
609 icalparameter_set_iana_name(param, name);
610 }
611
612 icalproperty_set_parameter(prop,param);
613
614 }
615
icalproperty_get_parameter_as_string(icalproperty * prop,const char * name)616 const char* icalproperty_get_parameter_as_string(icalproperty* prop,
617 const char* name)
618 {
619 char *buf;
620 buf = icalproperty_get_parameter_as_string_r(prop, name);
621 icalmemory_add_tmp_buffer(buf);
622 return buf;
623 }
624
625
icalproperty_get_parameter_as_string_r(icalproperty * prop,const char * name)626 char* icalproperty_get_parameter_as_string_r(icalproperty* prop,
627 const char* name)
628 {
629 icalparameter_kind kind;
630 icalparameter *param;
631 char* str;
632 char *pv, *t;
633 char* pvql;
634 char* pvqr;
635
636 icalerror_check_arg_rz( (prop!=0),"prop");
637 icalerror_check_arg_rz( (name!=0),"name");
638
639 kind = icalparameter_string_to_kind(name);
640
641 if(kind == ICAL_NO_PARAMETER){
642 /* icalenum_string_to_parameter_kind will set icalerrno */
643 return 0;
644 }
645
646 for(param = icalproperty_get_first_parameter(prop,kind);
647 param != 0;
648 param = icalproperty_get_next_parameter(prop,kind)) {
649
650 if (kind == ICAL_X_PARAMETER) {
651 if (strcmp(icalparameter_get_xname(param),name)==0) {
652 break;
653 }
654 } else if (kind == ICAL_IANA_PARAMETER) {
655 if (strcmp(icalparameter_get_iana_name(param),name)==0) {
656 break;
657 }
658 } else {
659 break;
660 }
661
662 }
663
664 if (param == 0){
665 return 0;
666 }
667
668
669 str = icalparameter_as_ical_string_r(param);
670
671 t = strchr(str,'=');
672
673 if (t == 0) {
674 icalerror_set_errno(ICAL_INTERNAL_ERROR);
675 free(str);
676 return 0;
677 }
678
679 /* Strip the property name and the equal sign */
680 pv = icalmemory_strdup(t+1);
681 free(str);
682
683 /* Is the string quoted? */
684 pvql = strchr(pv, '"');
685 if (pvql == 0) {
686 return(pv); /* No quotes? Return it immediately. */
687 }
688
689 /* Strip everything up to the first quote */
690 str = icalmemory_strdup(pvql+1);
691 free(pv);
692
693 /* Search for the end quote */
694 pvqr = strrchr(str, '"');
695 if (pvqr == 0) {
696 icalerror_set_errno(ICAL_INTERNAL_ERROR);
697 free(str);
698 return 0;
699 }
700
701 *pvqr = '\0';
702 return str;
703 }
704
705 /** @see icalproperty_remove_parameter_by_kind()
706 *
707 * @deprecated Please use icalproperty_remove_parameter_by_kind()
708 * instead.
709 */
710
711 void
icalproperty_remove_parameter(icalproperty * prop,icalparameter_kind kind)712 icalproperty_remove_parameter(icalproperty* prop, icalparameter_kind kind)
713 {
714 icalproperty_remove_parameter_by_kind(prop, kind);
715 }
716
717
718 /** @brief Remove all parameters with the specified kind.
719 *
720 * @param prop A valid icalproperty.
721 * @param kind The kind to remove (ex. ICAL_TZID_PARAMETER)
722 *
723 * See icalproperty_remove_parameter_by_name() and
724 * icalproperty_remove_parameter_by_ref() for alternate ways of
725 * removing parameters
726 */
727
728 void
icalproperty_remove_parameter_by_kind(icalproperty * prop,icalparameter_kind kind)729 icalproperty_remove_parameter_by_kind(icalproperty* prop, icalparameter_kind kind)
730 {
731 pvl_elem p;
732
733 icalerror_check_arg_rv((prop!=0),"prop");
734
735 for(p=pvl_head(prop->parameters);p != 0; p = pvl_next(p)){
736 icalparameter* param = (icalparameter *)pvl_data (p);
737 if (icalparameter_isa(param) == kind) {
738 pvl_remove (prop->parameters, p);
739 icalparameter_free(param);
740 break;
741 }
742 }
743 }
744
745
746 /** @brief Remove all parameters with the specified name.
747 *
748 * @param prop A valid icalproperty.
749 * @param name The name of the parameter to remove
750 *
751 * This function removes parameters with the given name. The name
752 * corresponds to either a built-in name (TZID, etc.) or the name of
753 * an extended parameter (X-FOO)
754 *
755 * See icalproperty_remove_parameter_by_kind() and
756 * icalproperty_remove_parameter_by_ref() for alternate ways of removing
757 * parameters
758 */
759
760
761 void
icalproperty_remove_parameter_by_name(icalproperty * prop,const char * name)762 icalproperty_remove_parameter_by_name(icalproperty* prop, const char *name)
763 {
764 pvl_elem p;
765
766 icalerror_check_arg_rv((prop!=0),"prop");
767
768 for(p=pvl_head(prop->parameters);p != 0; p = pvl_next(p)){
769 icalparameter* param = (icalparameter *)pvl_data (p);
770 const char * kind_string;
771
772 if (icalparameter_isa(param) == ICAL_X_PARAMETER)
773 kind_string = icalparameter_get_xname(param);
774 else if (icalparameter_isa(param) == ICAL_IANA_PARAMETER)
775 kind_string = icalparameter_get_iana_name(param);
776 else
777 kind_string = icalparameter_kind_to_string(icalparameter_isa(param));
778
779 if (!kind_string)
780 continue;
781
782 if (0 == strcmp(kind_string, name)) {
783 pvl_remove (prop->parameters, p);
784 icalparameter_free(param);
785 break;
786 }
787 }
788 }
789
790
791 /** @brief Remove the specified parameter reference from the property.
792 *
793 * @param prop A valid icalproperty.
794 * @param parameter A reference to a specific icalparameter.
795 *
796 * This function removes the specified parameter reference from the
797 * property.
798 */
799
800 void
icalproperty_remove_parameter_by_ref(icalproperty * prop,icalparameter * parameter)801 icalproperty_remove_parameter_by_ref(icalproperty* prop, icalparameter* parameter)
802 {
803 pvl_elem p;
804
805 icalerror_check_arg_rv((prop!=0),"prop");
806 icalerror_check_arg_rv((parameter!=0),"parameter");
807
808 for (p=pvl_head(prop->parameters);p != 0; p = pvl_next(p)) {
809 icalparameter* p_param = (icalparameter *)pvl_data (p);
810
811 if (icalparameter_has_same_name(parameter, p_param)) {
812 pvl_remove (prop->parameters, p);
813 icalparameter_free(p_param);
814 break;
815 }
816 }
817 }
818
819
820 int
icalproperty_count_parameters(const icalproperty * prop)821 icalproperty_count_parameters (const icalproperty* prop)
822 {
823 if(prop != 0){
824 return pvl_count(prop->parameters);
825 }
826
827 icalerror_set_errno(ICAL_USAGE_ERROR);
828 return -1;
829 }
830
831
832 icalparameter*
icalproperty_get_first_parameter(icalproperty * p,icalparameter_kind kind)833 icalproperty_get_first_parameter(icalproperty* p, icalparameter_kind kind)
834 {
835 icalerror_check_arg_rz( (p!=0),"prop");
836
837 p->parameter_iterator = pvl_head(p->parameters);
838
839 if (p->parameter_iterator == 0) {
840 return 0;
841 }
842
843 for( p->parameter_iterator = pvl_head(p->parameters);
844 p->parameter_iterator !=0;
845 p->parameter_iterator = pvl_next(p->parameter_iterator)){
846
847 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
848
849 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
850 return param;
851 }
852 }
853
854 return 0;
855 }
856
857
858 icalparameter*
icalproperty_get_next_parameter(icalproperty * p,icalparameter_kind kind)859 icalproperty_get_next_parameter (icalproperty* p, icalparameter_kind kind)
860 {
861 icalerror_check_arg_rz( (p!=0),"prop");
862
863 if (p->parameter_iterator == 0) {
864 return 0;
865 }
866
867 for( p->parameter_iterator = pvl_next(p->parameter_iterator);
868 p->parameter_iterator !=0;
869 p->parameter_iterator = pvl_next(p->parameter_iterator)){
870
871 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
872
873 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
874 return param;
875 }
876 }
877
878 return 0;
879
880 }
881
882 void
icalproperty_set_value(icalproperty * p,icalvalue * value)883 icalproperty_set_value (icalproperty* p, icalvalue* value)
884 {
885 icalerror_check_arg_rv((p !=0),"prop");
886 icalerror_check_arg_rv((value !=0),"value");
887
888 if (p->value != 0){
889 icalvalue_set_parent(p->value,0);
890 icalvalue_free(p->value);
891 p->value = 0;
892 }
893
894 p->value = value;
895
896 icalvalue_set_parent(value,p);
897 }
898
899
icalproperty_set_value_from_string(icalproperty * prop,const char * str,const char * type)900 void icalproperty_set_value_from_string(icalproperty* prop,const char* str,
901 const char* type)
902 {
903 icalvalue *oval,*nval;
904 icalvalue_kind kind = ICAL_NO_VALUE;
905
906 icalerror_check_arg_rv( (prop!=0),"prop");
907 icalerror_check_arg_rv( (str!=0),"str");
908 icalerror_check_arg_rv( (type!=0),"type");
909
910 if(strcmp(type,"NO")==0){
911 /* Get the type from the value the property already has, if it exists */
912 oval = icalproperty_get_value(prop);
913 if(oval != 0){
914 /* Use the existing value kind */
915 kind = icalvalue_isa(oval);
916 } else {
917 /* Use the default kind for the property */
918 kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop));
919 }
920 } else {
921 /* Use the given kind string */
922 kind = icalvalue_string_to_kind(type);
923 }
924
925 if(kind == ICAL_NO_VALUE){
926 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
927 return;
928 }
929
930 icalerror_clear_errno();
931 nval = icalvalue_new_from_string(kind, str);
932
933 if(nval == 0){
934 /* icalvalue_new_from_string sets errno */
935 assert(icalerrno != ICAL_NO_ERROR);
936 return;
937 }
938
939 icalproperty_set_value(prop,nval);
940
941
942 }
943
944 icalvalue*
icalproperty_get_value(const icalproperty * prop)945 icalproperty_get_value(const icalproperty* prop)
946 {
947 icalerror_check_arg_rz( (prop!=0),"prop");
948
949 return prop->value;
950 }
951
icalproperty_get_value_as_string(const icalproperty * prop)952 const char* icalproperty_get_value_as_string(const icalproperty* prop)
953 {
954 char *buf;
955 buf = icalproperty_get_value_as_string_r(prop);
956 icalmemory_add_tmp_buffer(buf);
957 return buf;
958 }
959
960
icalproperty_get_value_as_string_r(const icalproperty * prop)961 char* icalproperty_get_value_as_string_r(const icalproperty* prop)
962 {
963 icalvalue *value;
964
965 icalerror_check_arg_rz( (prop!=0),"prop");
966
967 value = prop->value;
968
969 return icalvalue_as_ical_string_r(value);
970 }
971
972
icalproperty_set_x_name(icalproperty * prop,const char * name)973 void icalproperty_set_x_name(icalproperty* prop, const char* name)
974 {
975 icalerror_check_arg_rv( (name!=0),"name");
976 icalerror_check_arg_rv( (prop!=0),"prop");
977
978 if (prop->x_name != 0) {
979 free(prop->x_name);
980 }
981
982 prop->x_name = icalmemory_strdup(name);
983
984 if(prop->x_name == 0){
985 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
986 }
987
988 }
989
icalproperty_get_x_name(icalproperty * prop)990 const char* icalproperty_get_x_name(icalproperty* prop){
991 icalerror_check_arg_rz( (prop!=0),"prop");
992
993 return prop->x_name;
994 }
995
icalproperty_get_property_name(const icalproperty * prop)996 const char* icalproperty_get_property_name(const icalproperty* prop)
997 {
998 char *buf;
999 buf = icalproperty_get_property_name_r(prop);
1000 icalmemory_add_tmp_buffer(buf);
1001 return buf;
1002 }
1003
1004
icalproperty_get_property_name_r(const icalproperty * prop)1005 char* icalproperty_get_property_name_r(const icalproperty* prop)
1006 {
1007
1008 const char* property_name = 0;
1009 size_t buf_size = 256;
1010 char* buf;
1011 char* buf_ptr;
1012
1013 icalerror_check_arg_rz( (prop!=0),"prop");
1014
1015 buf = icalmemory_new_buffer(buf_size);
1016 buf_ptr = buf;
1017
1018 if (prop->kind == ICAL_X_PROPERTY && prop->x_name != 0){
1019 property_name = prop->x_name;
1020 } else {
1021 property_name = icalproperty_kind_to_string(prop->kind);
1022 }
1023
1024 if (property_name == 0 ) {
1025 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1026 icalmemory_free_buffer(buf);
1027 return 0;
1028
1029 } else {
1030 /* _append_string will automatically grow the buffer if
1031 property_name is longer than the initial buffer size */
1032 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
1033 }
1034
1035 return buf;
1036 }
1037
1038
1039
1040
icalproperty_set_parent(icalproperty * property,icalcomponent * component)1041 void icalproperty_set_parent(icalproperty* property,
1042 icalcomponent* component)
1043 {
1044 icalerror_check_arg_rv( (property!=0),"property");
1045
1046 property->parent = component;
1047 }
1048
icalproperty_get_parent(const icalproperty * property)1049 icalcomponent* icalproperty_get_parent(const icalproperty* property)
1050 {
1051 icalerror_check_arg_rz( (property!=0),"property");
1052
1053 return property->parent;
1054 }
1055