summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalproperty.c
Side-by-side diff
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 @@
+/* -*- Mode: C -*- */
+
+/*======================================================================
+ FILE: icalproperty.c
+ CREATOR: eric 28 April 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalproperty.c
+
+======================================================================*/
+/*#line 27 "icalproperty.c.in"*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalproperty.h"
+#include "icalparameter.h"
+#include "icalcomponent.h"
+#include "pvl.h"
+#include "icalenums.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "icalparser.h"
+
+#include <string.h> /* For icalmemory_strdup, rindex */
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h> /* for printf */
+#include <stdarg.h> /* for va_list, va_start, etc. */
+
+int snprintf(char *str, size_t n, char const *fmt, ...);
+
+#define TMP_BUF_SIZE 1024
+
+/* Private routines for icalproperty */
+void icalvalue_set_parent(icalvalue* value,
+ icalproperty* property);
+icalproperty* icalvalue_get_parent(icalvalue* value);
+
+void icalparameter_set_parent(icalparameter* param,
+ icalproperty* property);
+icalproperty* icalparameter_get_parent(icalparameter* value);
+
+
+void icalproperty_set_x_name(icalproperty* prop, const char* name);
+
+struct icalproperty_impl
+{
+ char id[5];
+ icalproperty_kind kind;
+ char* x_name;
+ pvl_list parameters;
+ pvl_elem parameter_iterator;
+ icalvalue* value;
+ icalcomponent *parent;
+};
+
+void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args)
+{
+
+ void* vp;
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ while((vp = va_arg(args, void*)) != 0) {
+
+ if (icalvalue_isa_value(vp) != 0 ){
+ } else if (icalparameter_isa_parameter(vp) != 0 ){
+
+ icalproperty_add_parameter((icalproperty*)impl,
+ (icalparameter*)vp);
+ } else {
+ assert(0);
+ }
+
+ }
+
+
+}
+
+
+struct icalproperty_impl*
+icalproperty_new_impl (icalproperty_kind kind)
+{
+ struct icalproperty_impl* prop;
+
+ if ( ( prop = (struct icalproperty_impl*)
+ malloc(sizeof(struct icalproperty_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ strcpy(prop->id,"prop");
+
+ prop->kind = kind;
+ prop->parameters = pvl_newlist();
+ prop->parameter_iterator = 0;
+ prop->value = 0;
+ prop->x_name = 0;
+ prop->parent = 0;
+
+ return prop;
+}
+
+
+icalproperty*
+icalproperty_new (icalproperty_kind kind)
+{
+ if(kind == ICAL_NO_PROPERTY){
+ return 0;
+ }
+
+ return (icalproperty*)icalproperty_new_impl(kind);
+}
+
+
+icalproperty*
+icalproperty_new_clone(icalproperty* prop)
+{
+ struct icalproperty_impl *old = (struct icalproperty_impl*)prop;
+ struct icalproperty_impl *new = icalproperty_new_impl(old->kind);
+ pvl_elem p;
+
+ icalerror_check_arg_rz((prop!=0),"Prop");
+ icalerror_check_arg_rz((old!=0),"old");
+ icalerror_check_arg_rz((new!=0),"new");
+
+ if (old->value !=0) {
+ new->value = icalvalue_new_clone(old->value);
+ }
+
+ if (old->x_name != 0) {
+
+ new->x_name = icalmemory_strdup(old->x_name);
+
+ if (new->x_name == 0) {
+ icalproperty_free(new);
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+ }
+
+ for(p=pvl_head(old->parameters);p != 0; p = pvl_next(p)){
+ icalparameter *param = icalparameter_new_clone(pvl_data(p));
+
+ if (param == 0){
+ icalproperty_free(new);
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ pvl_push(new->parameters,param);
+
+ }
+
+ return new;
+
+}
+
+icalproperty* icalproperty_new_from_string(const char* str)
+{
+
+ size_t buf_size = 1024;
+ char* buf = icalmemory_new_buffer(buf_size);
+ char* buf_ptr = buf;
+ icalproperty *prop;
+ icalcomponent *comp;
+ int errors = 0;
+
+ icalerror_check_arg_rz( (str!=0),"str");
+
+ /* Is this a HACK or a crafty reuse of code? */
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:VCALENDAR\n");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "\n");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:VCALENDAR\n");
+
+ comp = icalparser_parse_string(buf);
+
+ if(comp == 0){
+ icalerror_set_errno(ICAL_PARSE_ERROR);
+ return 0;
+ }
+
+ errors = icalcomponent_count_errors(comp);
+
+ prop = icalcomponent_get_first_property(comp,ICAL_ANY_PROPERTY);
+
+ icalcomponent_remove_property(comp,prop);
+
+ icalcomponent_free(comp);
+ free(buf);
+
+ if(errors > 0){
+ icalproperty_free(prop);
+ return 0;
+ } else {
+ return prop;
+ }
+
+}
+
+void
+icalproperty_free (icalproperty* prop)
+{
+ struct icalproperty_impl *p;
+
+ icalparameter* param;
+
+ icalerror_check_arg_rv((prop!=0),"prop");
+
+ p = (struct icalproperty_impl*)prop;
+
+#ifdef ICAL_FREE_ON_LIST_IS_ERROR
+ icalerror_assert( (p->parent ==0),"Tried to free a property that is still attached to a component. ");
+
+#else
+ if(p->parent !=0){
+ return;
+ }
+#endif
+
+ if (p->value != 0){
+ icalvalue_set_parent(p->value,0);
+ icalvalue_free(p->value);
+ }
+
+ while( (param = pvl_pop(p->parameters)) != 0){
+ icalparameter_free(param);
+ }
+
+ pvl_free(p->parameters);
+
+ if (p->x_name != 0) {
+ free(p->x_name);
+ }
+
+ p->kind = ICAL_NO_PROPERTY;
+ p->parameters = 0;
+ p->parameter_iterator = 0;
+ p->value = 0;
+ p->x_name = 0;
+ p->id[0] = 'X';
+
+ free(p);
+
+}
+
+
+const char*
+icalproperty_as_ical_string (icalproperty* prop)
+{
+ icalparameter *param;
+
+ /* Create new buffer that we can append names, parameters and a
+ value to, and reallocate as needed. Later, this buffer will be
+ copied to a icalmemory_tmp_buffer, which is managed internally
+ by libical, so it can be given to the caller without fear of
+ the caller forgetting to free it */
+
+ const char* property_name = 0;
+ size_t buf_size = 1024;
+ char* buf = icalmemory_new_buffer(buf_size);
+ char* buf_ptr = buf;
+ icalvalue* value;
+ char *out_buf;
+
+ char newline[] = "\n";
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+
+ /* Append property name */
+
+ if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
+ property_name = impl->x_name;
+ } else {
+ property_name = icalproperty_kind_to_string(impl->kind);
+ }
+
+ if (property_name == 0 ) {
+ icalerror_warn("Got a property of an unknown kind.");
+ icalmemory_free_buffer(buf);
+ return 0;
+
+ }
+
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+
+
+ /* Determine what VALUE parameter to include. The VALUE parameters
+ are ignored in the normal parameter printing ( the block after
+ this one, so we need to do it here */
+ {
+ const char* kind_string = 0;
+
+ icalparameter *orig_val_param
+ = icalproperty_get_first_parameter(prop,ICAL_VALUE_PARAMETER);
+
+ icalvalue *value = icalproperty_get_value(impl);
+
+ icalvalue_kind orig_kind = ICAL_NO_VALUE;
+
+ icalvalue_kind this_kind = ICAL_NO_VALUE;
+
+ icalvalue_kind default_kind
+ = icalproperty_kind_to_value_kind(impl->kind);
+
+ if(orig_val_param){
+ orig_kind = (icalvalue_kind)icalparameter_get_value(orig_val_param);
+ }
+
+ if(value != 0){
+ this_kind = icalvalue_isa(value);
+ }
+
+
+ if(this_kind == default_kind &&
+ orig_kind != ICAL_NO_VALUE){
+ /* The kind is the default, so it does not need to be
+ included, but do it anyway, since it was explicit in
+ the property. But, use the default, not the one
+ specified in the property */
+
+ kind_string = icalvalue_kind_to_string(default_kind);
+
+ } else if (this_kind != default_kind && this_kind != ICAL_NO_VALUE){
+ /* Not the default, so it must be specified */
+ kind_string = icalvalue_kind_to_string(this_kind);
+ } else {
+ /* Don'tinclude the VALUE parameter at all */
+ }
+
+ if(kind_string!=0){
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "VALUE=");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+ }
+
+
+ }
+
+ /* Append parameters */
+ for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
+ param != 0;
+ param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) {
+
+ char* kind_string = icalparameter_as_ical_string(param);
+ icalparameter_kind kind = icalparameter_isa(param);
+
+ if(kind==ICAL_VALUE_PARAMETER){
+ continue;
+ }
+
+ if (kind_string == 0 ) {
+ char temp[TMP_BUF_SIZE];
+ snprintf(temp, TMP_BUF_SIZE,"Got a parameter of unknown kind in %s property",property_name);
+ icalerror_warn(temp);
+ continue;
+ }
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+ }
+
+ /* Append value */
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, " :");
+
+ value = icalproperty_get_value(prop);
+
+ if (value != 0){
+ const char *str = icalvalue_as_ical_string(value);
+ icalerror_assert((str !=0),"Could not get string representation of a value");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
+ } else {
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value");
+
+ }
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+ /* Now, copy the buffer to a tmp_buffer, which is safe to give to
+ the caller without worring about de-allocating it. */
+
+
+ out_buf = icalmemory_tmp_buffer(strlen(buf)+1);
+ strcpy(out_buf, buf);
+
+ icalmemory_free_buffer(buf);
+
+ return out_buf;
+}
+
+
+
+icalproperty_kind
+icalproperty_isa (icalproperty* property)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)property;
+
+ if(property != 0){
+ return p->kind;
+ }
+
+ return ICAL_NO_PROPERTY;
+}
+
+int
+icalproperty_isa_property (void* property)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
+
+ icalerror_check_arg_rz( (property!=0), "property");
+
+ if (strcmp(impl->id,"prop") == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+void
+icalproperty_add_parameter (icalproperty* prop,icalparameter* parameter)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (parameter!=0),"parameter");
+
+ pvl_push(p->parameters, parameter);
+
+}
+
+void
+icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter)
+{
+ icalparameter_kind kind;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (parameter!=0),"parameter");
+
+ kind = icalparameter_isa(parameter);
+
+ icalproperty_remove_parameter(prop,kind);
+
+ icalproperty_add_parameter(prop,parameter);
+}
+
+void icalproperty_set_parameter_from_string(icalproperty* prop,
+ const char* name, const char* value)
+{
+
+ icalparameter_kind kind;
+ icalparameter *param;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (name!=0),"name");
+ icalerror_check_arg_rv( (value!=0),"value");
+
+ kind = icalparameter_string_to_kind(name);
+
+ if(kind == ICAL_NO_PARAMETER){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return;
+ }
+
+ param = icalparameter_new_from_value_string(kind,value);
+
+ if (param == 0){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return;
+ }
+
+ icalproperty_set_parameter(prop,param);
+
+}
+
+const char* icalproperty_get_parameter_as_string(icalproperty* prop,
+ const char* name)
+{
+ icalparameter_kind kind;
+ icalparameter *param;
+ char* str;
+ char* pv;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+ icalerror_check_arg_rz( (name!=0),"name");
+
+ kind = icalparameter_string_to_kind(name);
+
+ if(kind == ICAL_NO_PROPERTY){
+ /* icalenum_string_to_parameter_kind will set icalerrno */
+ return 0;
+ }
+
+ param = icalproperty_get_first_parameter(prop,kind);
+
+ if (param == 0){
+ return 0;
+ }
+
+ str = icalparameter_as_ical_string(param);
+
+ pv = strchr(str,'=');
+
+ if(pv == 0){
+ icalerror_set_errno(ICAL_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return pv+1;
+
+}
+
+void
+icalproperty_remove_parameter (icalproperty* prop, icalparameter_kind kind)
+{
+ pvl_elem p;
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv((prop!=0),"prop");
+
+ for(p=pvl_head(impl->parameters);p != 0; p = pvl_next(p)){
+ icalparameter* param = (icalparameter *)pvl_data (p);
+ if (icalparameter_isa(param) == kind) {
+ pvl_remove (impl->parameters, p);
+ icalparameter_free (param);
+ break;
+ }
+ }
+}
+
+
+int
+icalproperty_count_parameters (icalproperty* prop)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ if(prop != 0){
+ return pvl_count(p->parameters);
+ }
+
+ icalerror_set_errno(ICAL_USAGE_ERROR);
+ return -1;
+}
+
+
+icalparameter*
+icalproperty_get_first_parameter (icalproperty* prop, icalparameter_kind kind)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ p->parameter_iterator = pvl_head(p->parameters);
+
+ if (p->parameter_iterator == 0) {
+ return 0;
+ }
+
+ for( p->parameter_iterator = pvl_head(p->parameters);
+ p->parameter_iterator !=0;
+ p->parameter_iterator = pvl_next(p->parameter_iterator)){
+
+ icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
+
+ if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
+ return param;
+ }
+ }
+
+ return 0;
+}
+
+
+icalparameter*
+icalproperty_get_next_parameter (icalproperty* prop, icalparameter_kind kind)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ if (p->parameter_iterator == 0) {
+ return 0;
+ }
+
+ for( p->parameter_iterator = pvl_next(p->parameter_iterator);
+ p->parameter_iterator !=0;
+ p->parameter_iterator = pvl_next(p->parameter_iterator)){
+
+ icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
+
+ if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
+ return param;
+ }
+ }
+
+ return 0;
+
+}
+
+void
+icalproperty_set_value (icalproperty* prop, icalvalue* value)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv((prop !=0),"prop");
+ icalerror_check_arg_rv((value !=0),"value");
+
+ if (p->value != 0){
+ icalvalue_set_parent(p->value,0);
+ icalvalue_free(p->value);
+ p->value = 0;
+ }
+
+ p->value = value;
+
+ icalvalue_set_parent(value,prop);
+}
+
+
+void icalproperty_set_value_from_string(icalproperty* prop,const char* str,
+ const char* type)
+{
+ icalvalue *oval,*nval;
+ icalvalue_kind kind = ICAL_NO_VALUE;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (str!=0),"str");
+ icalerror_check_arg_rv( (type!=0),"type");
+
+ if(strcmp(type,"NO")==0){
+ /* Get the type from the value the property already has, if it exists */
+ oval = icalproperty_get_value(prop);
+ if(oval != 0){
+ /* Use the existing value kind */
+ kind = icalvalue_isa(oval);
+ } else {
+ /* Use the default kind for the property */
+ kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop));
+ }
+ } else {
+ /* Use the given kind string */
+ kind = icalvalue_string_to_kind(type);
+ }
+
+ if(kind == ICAL_NO_VALUE){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return;
+ }
+
+ nval = icalvalue_new_from_string(kind, str);
+
+ if(nval == 0){
+ /* icalvalue_new_from_string sets errno */
+ assert(icalerrno != ICAL_NO_ERROR);
+ return;
+ }
+
+ icalproperty_set_value(prop,nval);
+
+
+}
+
+icalvalue*
+icalproperty_get_value (icalproperty* prop)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ return p->value;
+}
+
+const char* icalproperty_get_value_as_string(icalproperty* prop)
+{
+ icalvalue *value;
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ value = impl->value;
+
+ return icalvalue_as_ical_string(value);
+}
+
+
+void icalproperty_set_x_name(icalproperty* prop, const char* name)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv( (name!=0),"name");
+ icalerror_check_arg_rv( (prop!=0),"prop");
+
+ if (impl->x_name != 0) {
+ free(impl->x_name);
+ }
+
+ impl->x_name = icalmemory_strdup(name);
+
+ if(impl->x_name == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ }
+
+}
+
+const char* icalproperty_get_x_name(icalproperty* prop){
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ return impl->x_name;
+}
+
+
+/* From Jonathan Yue <jonathan.yue@cp.net> */
+const char* icalproperty_get_name (icalproperty* prop)
+{
+
+ const char* property_name = 0;
+ size_t buf_size = 256;
+ char* buf = icalmemory_new_buffer(buf_size);
+ char* buf_ptr = buf;
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
+ property_name = impl->x_name;
+ } else {
+ property_name = icalproperty_kind_to_string(impl->kind);
+ }
+
+ if (property_name == 0 ) {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+
+ } else {
+ /* _append_string will automatically grow the buffer if
+ property_name is longer than the initial buffer size */
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
+ }
+
+ /* Add the buffer to the temporary buffer ring -- the caller will
+ not have to free the memory. */
+ icalmemory_add_tmp_buffer(buf);
+
+ return buf;
+}
+
+
+
+
+void icalproperty_set_parent(icalproperty* property,
+ icalcomponent* component)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
+
+ icalerror_check_arg_rv( (property!=0),"property");
+
+ impl->parent = component;
+}
+
+icalcomponent* icalproperty_get_parent(icalproperty* property)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
+
+ icalerror_check_arg_rz( (property!=0),"property");
+
+ return impl->parent;
+}
+
+
+
+
+
+
+
+/* Everything below this line is machine generated. Do not edit. */