3 /*======================================================================
5 CREATOR: eric 28 April 1999
10 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of either:
15 The LGPL as published by the Free Software Foundation, version
16 2.1, available at: http://www.fsf.org/copyleft/lesser.html
20 The Mozilla Public License Version 1.0. You may obtain a copy of
21 the License at http://www.mozilla.org/MPL/
23 The original code is icalproperty.c
25 ======================================================================*/
26 /*#line 27 "icalproperty.c.in"*/
32 #include "icalproperty.h"
33 #include "icalparameter.h"
34 #include "icalcomponent.h"
36 #include "icalenums.h"
37 #include "icalerror.h"
38 #include "icalmemory.h"
39 #include "icalparser.h"
41 #include <string.h> /* For icalmemory_strdup, rindex */
45 #include <stdio.h> /* for printf */
46 #include <stdarg.h> /* for va_list, va_start, etc. */
48 #define TMP_BUF_SIZE 1024
50 /* Private routines for icalproperty */
51 void icalvalue_set_parent(icalvalue* value,
52 icalproperty* property);
53 icalproperty* icalvalue_get_parent(icalvalue* value);
55 void icalparameter_set_parent(icalparameter* param,
56 icalproperty* property);
57 icalproperty* icalparameter_get_parent(icalparameter* value);
60 void icalproperty_set_x_name(icalproperty* prop, char* name);
62 struct icalproperty_impl
65 icalproperty_kind kind;
68 pvl_elem parameter_iterator;
70 icalcomponent *parent;
73 void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args)
78 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
80 while((vp = va_arg(args, void*)) != 0) {
82 if (icalvalue_isa_value(vp) != 0 ){
83 } else if (icalparameter_isa_parameter(vp) != 0 ){
85 icalproperty_add_parameter((icalproperty*)impl,
97 struct icalproperty_impl*
98 icalproperty_new_impl (icalproperty_kind kind)
100 struct icalproperty_impl* prop;
102 if ( ( prop = (struct icalproperty_impl*)
103 malloc(sizeof(struct icalproperty_impl))) == 0) {
104 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
108 strcpy(prop->id,"prop");
111 prop->parameters = pvl_newlist();
112 prop->parameter_iterator = 0;
122 icalproperty_new (icalproperty_kind kind)
124 if(kind == ICAL_NO_PROPERTY){
128 return (icalproperty*)icalproperty_new_impl(kind);
133 icalproperty_new_clone(icalproperty* prop)
135 struct icalproperty_impl *old = (struct icalproperty_impl*)prop;
136 struct icalproperty_impl *new = icalproperty_new_impl(old->kind);
139 icalerror_check_arg_rz((prop!=0),"Prop");
140 icalerror_check_arg_rz((old!=0),"old");
141 icalerror_check_arg_rz((new!=0),"new");
143 if (old->value !=0) {
144 new->value = icalvalue_new_clone(old->value);
147 if (old->x_name != 0) {
149 new->x_name = icalmemory_strdup(old->x_name);
151 if (new->x_name == 0) {
152 icalproperty_free(new);
153 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
158 for(p=pvl_head(old->parameters);p != 0; p = pvl_next(p)){
159 icalparameter *param = icalparameter_new_clone(pvl_data(p));
162 icalproperty_free(new);
163 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
167 pvl_push(new->parameters,param);
175 icalproperty* icalproperty_new_from_string(char* str)
178 size_t buf_size = 1024;
185 icalerror_check_arg_rz( (str!=0),"str");
187 buf = icalmemory_new_buffer(buf_size);
190 /* Is this a HACK or a crafty reuse of code? */
192 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:VCALENDAR\n");
193 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
194 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "\n");
195 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:VCALENDAR\n");
197 comp = icalparser_parse_string(buf);
200 icalerror_set_errno(ICAL_PARSE_ERROR);
201 icalmemory_free_buffer(buf);
205 errors = icalcomponent_count_errors(comp);
207 prop = icalcomponent_get_first_property(comp,ICAL_ANY_PROPERTY);
209 icalcomponent_remove_property(comp,prop);
211 icalcomponent_free(comp);
212 icalmemory_free_buffer(buf);
215 icalproperty_free(prop);
224 icalproperty_free (icalproperty* prop)
226 struct icalproperty_impl *p;
228 icalparameter* param;
230 icalerror_check_arg_rv((prop!=0),"prop");
232 p = (struct icalproperty_impl*)prop;
234 #ifdef ICAL_FREE_ON_LIST_IS_ERROR
235 icalerror_assert( (p->parent ==0),"Tried to free a property that is still attached to a component. ");
244 icalvalue_set_parent(p->value,0);
245 icalvalue_free(p->value);
248 while( (param = pvl_pop(p->parameters)) != 0){
249 icalparameter_free(param);
252 pvl_free(p->parameters);
254 if (p->x_name != 0) {
258 p->kind = ICAL_NO_PROPERTY;
260 p->parameter_iterator = 0;
271 icalproperty_as_ical_string (icalproperty* prop)
273 icalparameter *param;
275 /* Create new buffer that we can append names, parameters and a
276 value to, and reallocate as needed. Later, this buffer will be
277 copied to a icalmemory_tmp_buffer, which is managed internally
278 by libical, so it can be given to the caller without fear of
279 the caller forgetting to free it */
281 const char* property_name = 0;
282 size_t buf_size = 1024;
288 char newline[] = "\n";
290 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
292 icalerror_check_arg_rz( (prop!=0),"prop");
294 buf = icalmemory_new_buffer(buf_size);
297 /* Append property name */
299 if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
300 property_name = impl->x_name;
302 property_name = icalproperty_kind_to_string(impl->kind);
305 if (property_name == 0 ) {
306 icalerror_warn("Got a property of an unknown kind.");
307 icalmemory_free_buffer(buf);
313 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
314 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
318 /* Determine what VALUE parameter to include. The VALUE parameters
319 are ignored in the normal parameter printing ( the block after
320 this one, so we need to do it here */
322 const char* kind_string = 0;
324 icalparameter *orig_val_param
325 = icalproperty_get_first_parameter(prop,ICAL_VALUE_PARAMETER);
327 icalvalue *value = icalproperty_get_value(impl);
329 icalvalue_kind orig_kind = ICAL_NO_VALUE;
331 icalvalue_kind this_kind = ICAL_NO_VALUE;
333 icalvalue_kind default_kind
334 = icalproperty_kind_to_value_kind(impl->kind);
337 orig_kind = (icalvalue_kind)icalparameter_get_value(orig_val_param);
341 this_kind = icalvalue_isa(value);
345 if(this_kind == default_kind &&
346 orig_kind != ICAL_NO_VALUE){
347 /* The kind is the default, so it does not need to be
348 included, but do it anyway, since it was explicit in
349 the property. But, use the default, not the one
350 specified in the property */
352 kind_string = icalvalue_kind_to_string(default_kind);
354 } else if (this_kind != default_kind && this_kind != ICAL_NO_VALUE){
355 /* Not the default, so it must be specified */
356 kind_string = icalvalue_kind_to_string(this_kind);
358 /* Don'tinclude the VALUE parameter at all */
362 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
363 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "VALUE=");
364 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
365 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
371 /* Append parameters */
372 for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
374 param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) {
376 char* kind_string = icalparameter_as_ical_string(param);
377 icalparameter_kind kind = icalparameter_isa(param);
379 if(kind==ICAL_VALUE_PARAMETER){
383 if (kind_string == 0 ) {
384 char temp[TMP_BUF_SIZE];
385 snprintf(temp, TMP_BUF_SIZE,"Got a parameter of unknown kind in %s property",property_name);
386 icalerror_warn(temp);
390 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
391 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
392 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
398 icalmemory_append_string(&buf, &buf_ptr, &buf_size, " :");
400 value = icalproperty_get_value(prop);
403 const char *str = icalvalue_as_ical_string(value);
404 icalerror_assert((str !=0),"Could not get string representation of a value");
405 icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
407 icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value");
411 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
413 /* Now, copy the buffer to a tmp_buffer, which is safe to give to
414 the caller without worring about de-allocating it. */
417 out_buf = icalmemory_tmp_buffer(strlen(buf)+1);
418 strcpy(out_buf, buf);
420 icalmemory_free_buffer(buf);
428 icalproperty_isa (icalproperty* property)
430 struct icalproperty_impl *p = (struct icalproperty_impl*)property;
436 return ICAL_NO_PROPERTY;
440 icalproperty_isa_property (void* property)
442 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
444 icalerror_check_arg_rz( (property!=0), "property");
446 if (strcmp(impl->id,"prop") == 0) {
455 icalproperty_add_parameter (icalproperty* prop,icalparameter* parameter)
457 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
459 icalerror_check_arg_rv( (prop!=0),"prop");
460 icalerror_check_arg_rv( (parameter!=0),"parameter");
462 pvl_push(p->parameters, parameter);
467 icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter)
469 icalparameter_kind kind;
471 icalerror_check_arg_rv( (prop!=0),"prop");
472 icalerror_check_arg_rv( (parameter!=0),"parameter");
474 kind = icalparameter_isa(parameter);
476 icalproperty_remove_parameter(prop,kind);
478 icalproperty_add_parameter(prop,parameter);
481 void icalproperty_set_parameter_from_string(icalproperty* prop,
482 const char* name, const char* value)
485 icalparameter_kind kind;
486 icalparameter *param;
488 icalerror_check_arg_rv( (prop!=0),"prop");
489 icalerror_check_arg_rv( (name!=0),"name");
490 icalerror_check_arg_rv( (value!=0),"value");
492 kind = icalparameter_string_to_kind(name);
494 if(kind == ICAL_NO_PARAMETER){
495 icalerror_set_errno(ICAL_BADARG_ERROR);
499 param = icalparameter_new_from_value_string(kind,value);
502 icalerror_set_errno(ICAL_BADARG_ERROR);
506 icalproperty_set_parameter(prop,param);
510 const char* icalproperty_get_parameter_as_string(icalproperty* prop,
513 icalparameter_kind kind;
514 icalparameter *param;
518 icalerror_check_arg_rz( (prop!=0),"prop");
519 icalerror_check_arg_rz( (name!=0),"name");
521 kind = icalparameter_string_to_kind(name);
523 if(kind == ICAL_NO_PARAMETER){
524 /* icalenum_string_to_parameter_kind will set icalerrno */
528 param = icalproperty_get_first_parameter(prop,kind);
534 str = icalparameter_as_ical_string(param);
536 pv = strchr(str,'=');
539 icalerror_set_errno(ICAL_INTERNAL_ERROR);
548 icalproperty_remove_parameter (icalproperty* prop, icalparameter_kind kind)
551 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
553 icalerror_check_arg_rv((prop!=0),"prop");
555 for(p=pvl_head(impl->parameters);p != 0; p = pvl_next(p)){
556 icalparameter* param = (icalparameter *)pvl_data (p);
557 if (icalparameter_isa(param) == kind) {
558 pvl_remove (impl->parameters, p);
559 icalparameter_free (param);
567 icalproperty_count_parameters (icalproperty* prop)
569 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
572 return pvl_count(p->parameters);
575 icalerror_set_errno(ICAL_USAGE_ERROR);
581 icalproperty_get_first_parameter (icalproperty* prop, icalparameter_kind kind)
583 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
585 icalerror_check_arg_rz( (prop!=0),"prop");
587 p->parameter_iterator = pvl_head(p->parameters);
589 if (p->parameter_iterator == 0) {
593 for( p->parameter_iterator = pvl_head(p->parameters);
594 p->parameter_iterator !=0;
595 p->parameter_iterator = pvl_next(p->parameter_iterator)){
597 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
599 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
609 icalproperty_get_next_parameter (icalproperty* prop, icalparameter_kind kind)
611 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
613 icalerror_check_arg_rz( (prop!=0),"prop");
615 if (p->parameter_iterator == 0) {
619 for( p->parameter_iterator = pvl_next(p->parameter_iterator);
620 p->parameter_iterator !=0;
621 p->parameter_iterator = pvl_next(p->parameter_iterator)){
623 icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
625 if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
635 icalproperty_set_value (icalproperty* prop, icalvalue* value)
637 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
639 icalerror_check_arg_rv((prop !=0),"prop");
640 icalerror_check_arg_rv((value !=0),"value");
643 icalvalue_set_parent(p->value,0);
644 icalvalue_free(p->value);
650 icalvalue_set_parent(value,prop);
654 void icalproperty_set_value_from_string(icalproperty* prop,const char* str,
657 icalvalue *oval,*nval;
658 icalvalue_kind kind = ICAL_NO_VALUE;
660 icalerror_check_arg_rv( (prop!=0),"prop");
661 icalerror_check_arg_rv( (str!=0),"str");
662 icalerror_check_arg_rv( (type!=0),"type");
664 if(strcmp(type,"NO")==0){
665 /* Get the type from the value the property already has, if it exists */
666 oval = icalproperty_get_value(prop);
668 /* Use the existing value kind */
669 kind = icalvalue_isa(oval);
671 /* Use the default kind for the property */
672 kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop));
675 /* Use the given kind string */
676 kind = icalvalue_string_to_kind(type);
679 if(kind == ICAL_NO_VALUE){
680 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
684 nval = icalvalue_new_from_string(kind, str);
687 /* icalvalue_new_from_string sets errno */
688 assert(icalerrno != ICAL_NO_ERROR);
692 icalproperty_set_value(prop,nval);
698 icalproperty_get_value (icalproperty* prop)
700 struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
702 icalerror_check_arg_rz( (prop!=0),"prop");
707 const char* icalproperty_get_value_as_string(icalproperty* prop)
711 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
713 icalerror_check_arg_rz( (prop!=0),"prop");
717 return icalvalue_as_ical_string(value);
721 void icalproperty_set_x_name(icalproperty* prop, char* name)
723 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
725 icalerror_check_arg_rv( (name!=0),"name");
726 icalerror_check_arg_rv( (prop!=0),"prop");
728 if (impl->x_name != 0) {
732 impl->x_name = icalmemory_strdup(name);
734 if(impl->x_name == 0){
735 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
740 char* icalproperty_get_x_name(icalproperty* prop){
742 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
744 icalerror_check_arg_rz( (prop!=0),"prop");
750 /* From Jonathan Yue <jonathan.yue@cp.net> */
751 char* icalproperty_get_name (icalproperty* prop)
754 const char* property_name = 0;
755 size_t buf_size = 256;
756 char* buf = icalmemory_new_buffer(buf_size);
759 struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
761 icalerror_check_arg_rz( (prop!=0),"prop");
763 if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
764 property_name = impl->x_name;
766 property_name = icalproperty_kind_to_string(impl->kind);
769 if (property_name == 0 ) {
770 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
771 icalmemory_free_buffer(buf);
775 /* _append_string will automatically grow the buffer if
776 property_name is longer than the initial buffer size */
777 icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
780 /* Add the buffer to the temporary buffer ring -- the caller will
781 not have to free the memory. */
782 icalmemory_add_tmp_buffer(buf);
790 void icalproperty_set_parent(icalproperty* property,
791 icalcomponent* component)
793 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
795 icalerror_check_arg_rv( (property!=0),"property");
797 impl->parent = component;
800 icalcomponent* icalproperty_get_parent(icalproperty* property)
802 struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
804 icalerror_check_arg_rz( (property!=0),"property");
815 /* Everything below this line is machine generated. Do not edit. */