summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalproperty.c
Unidiff
Diffstat (limited to 'libical/src/libical/icalproperty.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libical/icalproperty.c810
1 files changed, 810 insertions, 0 deletions
diff --git a/libical/src/libical/icalproperty.c b/libical/src/libical/icalproperty.c
new file mode 100644
index 0000000..7f2cfa5
--- a/dev/null
+++ b/libical/src/libical/icalproperty.c
@@ -0,0 +1,810 @@
1/* -*- Mode: C -*- */
2
3/*======================================================================
4 FILE: icalproperty.c
5 CREATOR: eric 28 April 1999
6
7 $Id$
8
9
10 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of either:
14
15 The LGPL as published by the Free Software Foundation, version
16 2.1, available at: http://www.fsf.org/copyleft/lesser.html
17
18 Or:
19
20 The Mozilla Public License Version 1.0. You may obtain a copy of
21 the License at http://www.mozilla.org/MPL/
22
23 The original code is icalproperty.c
24
25======================================================================*/
26/*#line 27 "icalproperty.c.in"*/
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
48int snprintf(char *str, size_t n, char const *fmt, ...);
49
50#define TMP_BUF_SIZE 1024
51
52/* Private routines for icalproperty */
53void icalvalue_set_parent(icalvalue* value,
54 icalproperty* property);
55icalproperty* icalvalue_get_parent(icalvalue* value);
56
57void icalparameter_set_parent(icalparameter* param,
58 icalproperty* property);
59icalproperty* icalparameter_get_parent(icalparameter* value);
60
61
62void icalproperty_set_x_name(icalproperty* prop, const char* name);
63
64struct icalproperty_impl
65{
66 char id[5];
67 icalproperty_kind kind;
68 char* x_name;
69 pvl_list parameters;
70 pvl_elem parameter_iterator;
71 icalvalue* value;
72 icalcomponent *parent;
73};
74
75void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args)
76{
77
78 void* vp;
79
80 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
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*)impl,
88 (icalparameter*)vp);
89 } else {
90 assert(0);
91 }
92
93 }
94
95
96}
97
98
99struct icalproperty_impl*
100icalproperty_new_impl (icalproperty_kind kind)
101{
102 struct icalproperty_impl* prop;
103
104 if ( ( prop = (struct icalproperty_impl*)
105 malloc(sizeof(struct icalproperty_impl))) == 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
123icalproperty*
124icalproperty_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
134icalproperty*
135icalproperty_new_clone(icalproperty* prop)
136{
137 struct icalproperty_impl *old = (struct icalproperty_impl*)prop;
138 struct icalproperty_impl *new = icalproperty_new_impl(old->kind);
139 pvl_elem p;
140
141 icalerror_check_arg_rz((prop!=0),"Prop");
142 icalerror_check_arg_rz((old!=0),"old");
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
177icalproperty* icalproperty_new_from_string(const char* str)
178{
179
180 size_t buf_size = 1024;
181 char* buf = icalmemory_new_buffer(buf_size);
182 char* buf_ptr = buf;
183 icalproperty *prop;
184 icalcomponent *comp;
185 int errors = 0;
186
187 icalerror_check_arg_rz( (str!=0),"str");
188
189 /* Is this a HACK or a crafty reuse of code? */
190
191 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:VCALENDAR\n");
192 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
193 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "\n");
194 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:VCALENDAR\n");
195
196 comp = icalparser_parse_string(buf);
197
198 if(comp == 0){
199 icalerror_set_errno(ICAL_PARSE_ERROR);
200 return 0;
201 }
202
203 errors = icalcomponent_count_errors(comp);
204
205 prop = icalcomponent_get_first_property(comp,ICAL_ANY_PROPERTY);
206
207 icalcomponent_remove_property(comp,prop);
208
209 icalcomponent_free(comp);
210 free(buf);
211
212 if(errors > 0){
213 icalproperty_free(prop);
214 return 0;
215 } else {
216 return prop;
217 }
218
219}
220
221void
222icalproperty_free (icalproperty* prop)
223{
224 struct icalproperty_impl *p;
225
226 icalparameter* param;
227
228 icalerror_check_arg_rv((prop!=0),"prop");
229
230 p = (struct icalproperty_impl*)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
268const char*
269icalproperty_as_ical_string (icalproperty* prop)
270{
271 icalparameter *param;
272
273 /* Create new buffer that we can append names, parameters and a
274 value to, and reallocate as needed. Later, this buffer will be
275 copied to a icalmemory_tmp_buffer, which is managed internally
276 by libical, so it can be given to the caller without fear of
277 the caller forgetting to free it */
278
279 const char* property_name = 0;
280 size_t buf_size = 1024;
281 char* buf = icalmemory_new_buffer(buf_size);
282 char* buf_ptr = buf;
283 icalvalue* value;
284 char *out_buf;
285
286 char newline[] = "\n";
287
288 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
289
290 icalerror_check_arg_rz( (prop!=0),"prop");
291
292
293 /* Append property name */
294
295 if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
296 property_name = impl->x_name;
297 } else {
298 property_name = icalproperty_kind_to_string(impl->kind);
299 }
300
301 if (property_name == 0 ) {
302 icalerror_warn("Got a property of an unknown kind.");
303 icalmemory_free_buffer(buf);
304 return 0;
305
306 }
307
308
309 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
310 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
311
312
313
314 /* Determine what VALUE parameter to include. The VALUE parameters
315 are ignored in the normal parameter printing ( the block after
316 this one, so we need to do it here */
317 {
318 const char* kind_string = 0;
319
320 icalparameter *orig_val_param
321 = icalproperty_get_first_parameter(prop,ICAL_VALUE_PARAMETER);
322
323 icalvalue *value = icalproperty_get_value(impl);
324
325 icalvalue_kind orig_kind = ICAL_NO_VALUE;
326
327 icalvalue_kind this_kind = ICAL_NO_VALUE;
328
329 icalvalue_kind default_kind
330 = icalproperty_kind_to_value_kind(impl->kind);
331
332 if(orig_val_param){
333 orig_kind = (icalvalue_kind)icalparameter_get_value(orig_val_param);
334 }
335
336 if(value != 0){
337 this_kind = icalvalue_isa(value);
338 }
339
340
341 if(this_kind == default_kind &&
342 orig_kind != ICAL_NO_VALUE){
343 /* The kind is the default, so it does not need to be
344 included, but do it anyway, since it was explicit in
345 the property. But, use the default, not the one
346 specified in the property */
347
348 kind_string = icalvalue_kind_to_string(default_kind);
349
350 } else if (this_kind != default_kind && this_kind != ICAL_NO_VALUE){
351 /* Not the default, so it must be specified */
352 kind_string = icalvalue_kind_to_string(this_kind);
353 } else {
354 /* Don'tinclude the VALUE parameter at all */
355 }
356
357 if(kind_string!=0){
358 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
359 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "VALUE=");
360 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
361 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
362 }
363
364
365 }
366
367 /* Append parameters */
368 for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
369 param != 0;
370 param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) {
371
372 char* kind_string = icalparameter_as_ical_string(param);
373 icalparameter_kind kind = icalparameter_isa(param);
374
375 if(kind==ICAL_VALUE_PARAMETER){
376 continue;
377 }
378
379 if (kind_string == 0 ) {
380 char temp[TMP_BUF_SIZE];
381 snprintf(temp, TMP_BUF_SIZE,"Got a parameter of unknown kind in %s property",property_name);
382 icalerror_warn(temp);
383 continue;
384 }
385
386 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
387 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
388 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
389
390 }
391
392 /* Append value */
393
394 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " :");
395
396 value = icalproperty_get_value(prop);
397
398 if (value != 0){
399 const char *str = icalvalue_as_ical_string(value);
400 icalerror_assert((str !=0),"Could not get string representation of a value");
401 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
402 } else {
403 icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value");
404
405 }
406
407 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
408
409 /* Now, copy the buffer to a tmp_buffer, which is safe to give to
410 the caller without worring about de-allocating it. */
411
412
413 out_buf = icalmemory_tmp_buffer(strlen(buf)+1);
414 strcpy(out_buf, buf);
415
416 icalmemory_free_buffer(buf);
417
418 return out_buf;
419}
420
421
422
423icalproperty_kind
424icalproperty_isa (icalproperty* property)
425{
426 struct icalproperty_impl *p = (struct icalproperty_impl*)property;
427
428 if(property != 0){
429 return p->kind;
430 }
431
432 return ICAL_NO_PROPERTY;
433}
434
435int
436icalproperty_isa_property (void* property)
437{
438 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
439
440 icalerror_check_arg_rz( (property!=0), "property");
441
442 if (strcmp(impl->id,"prop") == 0) {
443 return 1;
444 } else {
445 return 0;
446 }
447}
448
449
450void
451icalproperty_add_parameter (icalproperty* prop,icalparameter* parameter)
452{
453 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
454
455 icalerror_check_arg_rv( (prop!=0),"prop");
456 icalerror_check_arg_rv( (parameter!=0),"parameter");
457
458 pvl_push(p->parameters, parameter);
459
460}
461
462void
463icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter)
464{
465 icalparameter_kind kind;
466
467 icalerror_check_arg_rv( (prop!=0),"prop");
468 icalerror_check_arg_rv( (parameter!=0),"parameter");
469
470 kind = icalparameter_isa(parameter);
471
472 icalproperty_remove_parameter(prop,kind);
473
474 icalproperty_add_parameter(prop,parameter);
475}
476
477void icalproperty_set_parameter_from_string(icalproperty* prop,
478 const char* name, const char* value)
479{
480
481 icalparameter_kind kind;
482 icalparameter *param;
483
484 icalerror_check_arg_rv( (prop!=0),"prop");
485 icalerror_check_arg_rv( (name!=0),"name");
486 icalerror_check_arg_rv( (value!=0),"value");
487
488 kind = icalparameter_string_to_kind(name);
489
490 if(kind == ICAL_NO_PARAMETER){
491 icalerror_set_errno(ICAL_BADARG_ERROR);
492 return;
493 }
494
495 param = icalparameter_new_from_value_string(kind,value);
496
497 if (param == 0){
498 icalerror_set_errno(ICAL_BADARG_ERROR);
499 return;
500 }
501
502 icalproperty_set_parameter(prop,param);
503
504}
505
506const char* icalproperty_get_parameter_as_string(icalproperty* prop,
507 const char* name)
508{
509 icalparameter_kind kind;
510 icalparameter *param;
511 char* str;
512 char* pv;
513
514 icalerror_check_arg_rz( (prop!=0),"prop");
515 icalerror_check_arg_rz( (name!=0),"name");
516
517 kind = icalparameter_string_to_kind(name);
518
519 if(kind == ICAL_NO_PROPERTY){
520 /* icalenum_string_to_parameter_kind will set icalerrno */
521 return 0;
522 }
523
524 param = icalproperty_get_first_parameter(prop,kind);
525
526 if (param == 0){
527 return 0;
528 }
529
530 str = icalparameter_as_ical_string(param);
531
532 pv = strchr(str,'=');
533
534 if(pv == 0){
535 icalerror_set_errno(ICAL_INTERNAL_ERROR);
536 return 0;
537 }
538
539 return pv+1;
540
541}
542
543void
544icalproperty_remove_parameter (icalproperty* prop, icalparameter_kind kind)
545{
546 pvl_elem p;
547 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
548
549 icalerror_check_arg_rv((prop!=0),"prop");
550
551 for(p=pvl_head(impl->parameters);p != 0; p = pvl_next(p)){
552 icalparameter* param = (icalparameter *)pvl_data (p);
553 if (icalparameter_isa(param) == kind) {
554 pvl_remove (impl->parameters, p);
555 icalparameter_free (param);
556 break;
557 }
558 }
559}
560
561
562int
563icalproperty_count_parameters (icalproperty* prop)
564{
565 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
566
567 if(prop != 0){
568 return pvl_count(p->parameters);
569 }
570
571 icalerror_set_errno(ICAL_USAGE_ERROR);
572 return -1;
573}
574
575
576icalparameter*
577icalproperty_get_first_parameter (icalproperty* prop, icalparameter_kind kind)
578{
579 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
580
581 icalerror_check_arg_rz( (prop!=0),"prop");
582
583 p->parameter_iterator = pvl_head(p->parameters);
584
585 if (p->parameter_iterator == 0) {
586 return 0;
587 }
588
589 for( p->parameter_iterator = pvl_head(p->parameters);
590 p->parameter_iterator !=0;
591 p->parameter_iterator = pvl_next(p->parameter_iterator)){
592
593 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
594
595 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
596 return param;
597 }
598 }
599
600 return 0;
601}
602
603
604icalparameter*
605icalproperty_get_next_parameter (icalproperty* prop, icalparameter_kind kind)
606{
607 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
608
609 icalerror_check_arg_rz( (prop!=0),"prop");
610
611 if (p->parameter_iterator == 0) {
612 return 0;
613 }
614
615 for( p->parameter_iterator = pvl_next(p->parameter_iterator);
616 p->parameter_iterator !=0;
617 p->parameter_iterator = pvl_next(p->parameter_iterator)){
618
619 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
620
621 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
622 return param;
623 }
624 }
625
626 return 0;
627
628}
629
630void
631icalproperty_set_value (icalproperty* prop, icalvalue* value)
632{
633 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
634
635 icalerror_check_arg_rv((prop !=0),"prop");
636 icalerror_check_arg_rv((value !=0),"value");
637
638 if (p->value != 0){
639 icalvalue_set_parent(p->value,0);
640 icalvalue_free(p->value);
641 p->value = 0;
642 }
643
644 p->value = value;
645
646 icalvalue_set_parent(value,prop);
647}
648
649
650void icalproperty_set_value_from_string(icalproperty* prop,const char* str,
651 const char* type)
652{
653 icalvalue *oval,*nval;
654 icalvalue_kind kind = ICAL_NO_VALUE;
655
656 icalerror_check_arg_rv( (prop!=0),"prop");
657 icalerror_check_arg_rv( (str!=0),"str");
658 icalerror_check_arg_rv( (type!=0),"type");
659
660 if(strcmp(type,"NO")==0){
661 /* Get the type from the value the property already has, if it exists */
662 oval = icalproperty_get_value(prop);
663 if(oval != 0){
664 /* Use the existing value kind */
665 kind = icalvalue_isa(oval);
666 } else {
667 /* Use the default kind for the property */
668 kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop));
669 }
670 } else {
671 /* Use the given kind string */
672 kind = icalvalue_string_to_kind(type);
673 }
674
675 if(kind == ICAL_NO_VALUE){
676 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
677 return;
678 }
679
680 nval = icalvalue_new_from_string(kind, str);
681
682 if(nval == 0){
683 /* icalvalue_new_from_string sets errno */
684 assert(icalerrno != ICAL_NO_ERROR);
685 return;
686 }
687
688 icalproperty_set_value(prop,nval);
689
690
691}
692
693icalvalue*
694icalproperty_get_value (icalproperty* prop)
695{
696 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
697
698 icalerror_check_arg_rz( (prop!=0),"prop");
699
700 return p->value;
701}
702
703const char* icalproperty_get_value_as_string(icalproperty* prop)
704{
705 icalvalue *value;
706
707 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
708
709 icalerror_check_arg_rz( (prop!=0),"prop");
710
711 value = impl->value;
712
713 return icalvalue_as_ical_string(value);
714}
715
716
717void icalproperty_set_x_name(icalproperty* prop, const char* name)
718{
719 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
720
721 icalerror_check_arg_rv( (name!=0),"name");
722 icalerror_check_arg_rv( (prop!=0),"prop");
723
724 if (impl->x_name != 0) {
725 free(impl->x_name);
726 }
727
728 impl->x_name = icalmemory_strdup(name);
729
730 if(impl->x_name == 0){
731 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
732 }
733
734}
735
736const char* icalproperty_get_x_name(icalproperty* prop){
737
738 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
739
740 icalerror_check_arg_rz( (prop!=0),"prop");
741
742 return impl->x_name;
743}
744
745
746/* From Jonathan Yue <jonathan.yue@cp.net> */
747const char* icalproperty_get_name (icalproperty* prop)
748{
749
750 const char* property_name = 0;
751 size_t buf_size = 256;
752 char* buf = icalmemory_new_buffer(buf_size);
753 char* buf_ptr = buf;
754
755 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
756
757 icalerror_check_arg_rz( (prop!=0),"prop");
758
759 if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
760 property_name = impl->x_name;
761 } else {
762 property_name = icalproperty_kind_to_string(impl->kind);
763 }
764
765 if (property_name == 0 ) {
766 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
767 return 0;
768
769 } else {
770 /* _append_string will automatically grow the buffer if
771 property_name is longer than the initial buffer size */
772 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
773 }
774
775 /* Add the buffer to the temporary buffer ring -- the caller will
776 not have to free the memory. */
777 icalmemory_add_tmp_buffer(buf);
778
779 return buf;
780}
781
782
783
784
785void icalproperty_set_parent(icalproperty* property,
786 icalcomponent* component)
787{
788 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
789
790 icalerror_check_arg_rv( (property!=0),"property");
791
792 impl->parent = component;
793}
794
795icalcomponent* icalproperty_get_parent(icalproperty* property)
796{
797 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
798
799 icalerror_check_arg_rz( (property!=0),"property");
800
801 return impl->parent;
802}
803
804
805
806
807
808
809
810/* Everything below this line is machine generated. Do not edit. */