diff options
Diffstat (limited to 'libical/src')
32 files changed, 6890 insertions, 0 deletions
diff --git a/libical/src/libical/icalattendee.c b/libical/src/libical/icalattendee.c new file mode 100644 index 0000000000..30cb949c40 --- /dev/null +++ b/libical/src/libical/icalattendee.c @@ -0,0 +1,30 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalattendee.c + CREATOR: eric 08 Mar 01 + + $Id$ + $Locker$ + + + (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 icaltypes.c + + ======================================================================*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "icalattendee.h" diff --git a/libical/src/libical/icalattendee.h b/libical/src/libical/icalattendee.h new file mode 100644 index 0000000000..023b30734c --- /dev/null +++ b/libical/src/libical/icalattendee.h @@ -0,0 +1,68 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalattendee.h + CREATOR: eric 8 Mar 01 + + + (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 icaltypes.h + +======================================================================*/ + +#ifndef ICALATTENDEE_H +#define ICALATTENDEE_H + +#include <time.h> +#include "icalenums.h" +#include "icaltime.h" +#include "icalduration.h" +#include "icalperiod.h" +#include "icalderivedparameter.h" +#include "icalderivedvalue.h" + +struct icalorganizertype { + const char* value; + const char* common_name; + const char* dir; + const char* sentby; + const char* language; + +}; + +/* Create a copy of the given organizer. Libical will not own the + memory for the strings in the copy; the call must free them */ +struct icalorganizertype icalorganizertype_new_clone(struct icalorganizertype a); + + +struct icalattendeetype { + const char* cuid; /* Cal user id, contents of the property value */ + /*icalparameter_cutype cutype;*/ + const char* member; + /*icalparameter_role role;*/ + int rsvp; + const char* delto; + const char* delfrom; + const char* sentby; + const char* cn; + const char* dir; + const char* language; +}; + +/* Create a copy of the given attendee. Libical will not own the + memory for the strings in the copy; the call must free them */ +struct icalattendeetype icalattendeetype_new_clone(struct icalattendeetype a); + + +#endif /* !ICALATTENDEE_H */ diff --git a/libical/src/libical/icalderivedparameter.c.in b/libical/src/libical/icalderivedparameter.c.in new file mode 100644 index 0000000000..4af6e95c0e --- /dev/null +++ b/libical/src/libical/icalderivedparameter.c.in @@ -0,0 +1,211 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalderivedparameters.{c,h} + CREATOR: eric 09 May 1999 + + $Id: icalderivedparameter.c.in,v 1.1 2001/04/17 17:23:17 jpr Exp $ + $Locker: $ + + + (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 icalderivedparameters.{c,h} + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + ======================================================================*/ +/*#line 29 "icalparameter.c.in"*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include "icalparameter.h" +#include "icalparameterimpl.h" + +#include "icalproperty.h" +#include "icalerror.h" +#include "icalmemory.h" + +#include <stdlib.h> /* for malloc() */ +#include <errno.h> +#include <string.h> /* for memset() */ + +icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value); + +struct icalparameter_impl* icalparameter_new_impl(icalparameter_kind kind); + +/* This map associates each of the parameters with the string + representation of the paramter's name */ +struct icalparameter_kind_map { + icalparameter_kind kind; + char *name; + +}; + +extern struct icalparameter_kind_map parameter_map[]; + + +const char* icalparameter_kind_to_string(icalparameter_kind kind) +{ + int i; + + for (i=0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) { + if (parameter_map[i].kind == kind) { + return parameter_map[i].name; + } + } + + return 0; + +} + +icalparameter_kind icalparameter_string_to_kind(const char* string) +{ + int i; + + if (string ==0 ) { + return ICAL_NO_PARAMETER; + } + + for (i=0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) { + + if (strcmp(parameter_map[i].name, string) == 0) { + return parameter_map[i].kind; + } + } + + if(strncmp(string,"X-",2)==0){ + return ICAL_X_PARAMETER; + } + + return ICAL_NO_PARAMETER; +} + +/* This map associates the enumerations for the VALUE parameter with + the kinds of VALUEs. */ + +struct icalparameter_value_kind_map { + icalparameter_value value; + icalvalue_kind kind; +}; + +extern struct icalparameter_value_kind_map value_kind_map[]; + + +icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value) +{ + int i; + + for (i=0; value_kind_map[i].kind != ICAL_NO_VALUE; i++) { + + if (value_kind_map[i].value == value) { + return value_kind_map[i].kind; + } + } + + return ICAL_NO_VALUE; +} + + +/* This map associates the parameter enumerations with a specific parameter and the string representation of the enumeration */ + +struct icalparameter_map { + icalparameter_kind kind; + int enumeration; + const char* str; +}; + + +extern struct icalparameter_map icalparameter_map[]; + + +const char* icalparameter_enum_to_string(int e) +{ + int i; + + icalerror_check_arg_rz(e >= ICALPARAMETER_FIRST_ENUM,"e"); + icalerror_check_arg_rz(e <= ICALPARAMETER_LAST_ENUM,"e"); + + for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){ + if(e == icalparameter_map[i].enumeration){ + return icalparameter_map[i].str; + } + } + + return 0; +} + +int icalparameter_string_to_enum(const char* str) +{ + int i; + + icalerror_check_arg_rz(str != 0,"str"); + + for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){ + if(strcmp(str,icalparameter_map[i].str) == 0) { + return icalparameter_map[i].enumeration; + } + } + + return 0; +} + +icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind,const char* val) +{ + + struct icalparameter_impl* param=0; + int found_kind = 0; + int i; + + icalerror_check_arg_rz((val!=0),"val"); + + /* Search through the parameter map to find a matching kind */ + + param = icalparameter_new_impl(kind); + + for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){ + if(kind == icalparameter_map[i].kind) { + found_kind = 1; + if(strcmp(val,icalparameter_map[i].str) == 0) { + + param->data = (int)icalparameter_map[i].enumeration; + return param; + } + } + } + + if(found_kind == 1){ + /* The kind was in the parameter map, but the string did not + match, so assume that it is an alternate value, like an + X-value.*/ + + icalparameter_set_xvalue(param, val); + + } else { + + /* If the kind was not found, then it must be a string type */ + + ((struct icalparameter_impl*)param)->string = icalmemory_strdup(val); + + } + + return param; +} + + + + +/* Everything below this line is machine generated. Do not edit. */ diff --git a/libical/src/libical/icalderivedparameter.h.in b/libical/src/libical/icalderivedparameter.h.in new file mode 100644 index 0000000000..e9fdd19fa7 --- /dev/null +++ b/libical/src/libical/icalderivedparameter.h.in @@ -0,0 +1,37 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalparam.h + CREATOR: eric 20 March 1999 + + + $Id: icalderivedparameter.h.in,v 1.1 2001/04/17 17:23:17 jpr Exp $ + $Locker: $ + + + + (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 icalparam.h + + ======================================================================*/ + +#ifndef ICALDERIVEDPARAMETER_H +#define ICALDERIVEDPARAMETER_H + + +typedef void icalparameter; + +const char* icalparameter_enum_to_string(int e); +int icalparameter_string_to_enum(const char* str); + diff --git a/libical/src/libical/icalderivedproperty.c.in b/libical/src/libical/icalderivedproperty.c.in new file mode 100644 index 0000000000..ceec0b797d --- /dev/null +++ b/libical/src/libical/icalderivedproperty.c.in @@ -0,0 +1,250 @@ +/* -*- Mode: C -*- */ + +/*====================================================================== + FILE: icalderivedproperty.c + CREATOR: eric 15 Feb 2001 + + $Id: icalderivedproperty.c.in,v 1.1 2001/04/17 17:23:17 jpr Exp $ + + + (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 + +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalproperty.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. */ + +#define TMP_BUF_SIZE 1024 + +struct icalproperty_impl* +icalproperty_new_impl (icalproperty_kind kind); + +/* This map associates the property kinds with the string + representation of the property name and the kind of VALUE that the + property uses as a default */ + +struct icalproperty_map { + icalproperty_kind kind; + const char *name; + icalvalue_kind value; + +}; + +extern struct icalproperty_map property_map[]; + +const char* icalproperty_kind_to_string(icalproperty_kind kind) +{ + int i; + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if (property_map[i].kind == kind) { + return property_map[i].name; + } + } + + return 0; + +} + + +icalproperty_kind icalproperty_string_to_kind(const char* string) +{ + int i; + + if (string ==0 ) { + return ICAL_NO_PROPERTY; + } + + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if (strcmp(property_map[i].name, string) == 0) { + return property_map[i].kind; + } + } + + if(strncmp(string,"X-",2)==0){ + return ICAL_X_PROPERTY; + } + + + return ICAL_NO_PROPERTY; +} + + +icalvalue_kind icalproperty_value_kind_to_kind(icalvalue_kind kind) +{ + int i; + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if ( property_map[i].value == kind ) { + return property_map[i].kind; + } + } + + return ICAL_NO_VALUE; +} + + + +icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind) +{ + int i; + + for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) { + if ( property_map[i].kind == kind ) { + return property_map[i].value; + } + } + + return ICAL_NO_VALUE; +} + + +/* This map associates the property enumerations with the king of + property that they are used in and the string representation of the + enumeration */ + +struct icalproperty_enum_map { + icalproperty_kind prop; + int prop_enum; + const char* str; +}; + +extern struct icalproperty_enum_map enum_map[]; + + +const char* icalproperty_enum_to_string(int e) +{ + icalerror_check_arg_rz(e >= ICALPROPERTY_FIRST_ENUM,"e"); + icalerror_check_arg_rz(e <= ICALPROPERTY_LAST_ENUM,"e"); + + return enum_map[e-ICALPROPERTY_FIRST_ENUM].str; +} + +int icalproperty_string_to_enum(const char* str) +{ + int i; + + icalerror_check_arg_rz(str!=0,"str") + + while(*str == ' '){ + str++; + } + + for (i=ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) { + if ( strcmp(enum_map[i-ICALPROPERTY_FIRST_ENUM].str, str) == 0) { + return enum_map[i-ICALPROPERTY_FIRST_ENUM].prop_enum; + } + } + + return 0; +} + +int icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e) +{ + int i; + + + for (i=ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) { + if(enum_map[i-ICALPROPERTY_FIRST_ENUM].prop_enum == e && + enum_map[i-ICALPROPERTY_FIRST_ENUM].prop == kind ){ + return 1; + } + } + + return 0; +} + + +const char* icalproperty_method_to_string(icalproperty_method method) +{ + icalerror_check_arg_rz(method >= ICAL_METHOD_X,"method"); + icalerror_check_arg_rz(method <= ICAL_METHOD_NONE,"method"); + + return enum_map[method-ICALPROPERTY_FIRST_ENUM].str; +} + +icalproperty_method icalproperty_string_to_method(const char* str) +{ + int i; + + icalerror_check_arg_rx(str!=0,"str",ICAL_METHOD_NONE) + + while(*str == ' '){ + str++; + } + + for (i=ICAL_METHOD_X-ICALPROPERTY_FIRST_ENUM; + i != ICAL_METHOD_NONE-ICALPROPERTY_FIRST_ENUM; + i++) { + if ( strcmp(enum_map[i].str, str) == 0) { + return (icalproperty_method)enum_map[i].prop_enum; + } + } + + return ICAL_METHOD_NONE; +} + + +const char* icalenum_status_to_string(icalproperty_status status) +{ + icalerror_check_arg_rz(status >= ICAL_STATUS_X,"status"); + icalerror_check_arg_rz(status <= ICAL_STATUS_NONE,"status"); + + return enum_map[status-ICALPROPERTY_FIRST_ENUM].str; +} + +icalproperty_status icalenum_string_to_status(const char* str) +{ + int i; + + icalerror_check_arg_rx(str!=0,"str",ICAL_STATUS_NONE) + + while(*str == ' '){ + str++; + } + + for (i=ICAL_STATUS_X-ICALPROPERTY_FIRST_ENUM; + i != ICAL_STATUS_NONE-ICALPROPERTY_FIRST_ENUM; + i++) { + if ( strcmp(enum_map[i].str, str) == 0) { + return (icalproperty_method)enum_map[i].prop_enum; + } + } + + return ICAL_STATUS_NONE; + +} + + + +/* Everything below this line is machine generated. Do not edit. */ diff --git a/libical/src/libical/icalderivedproperty.h.in b/libical/src/libical/icalderivedproperty.h.in new file mode 100644 index 0000000000..6ce34afafb --- /dev/null +++ b/libical/src/libical/icalderivedproperty.h.in @@ -0,0 +1,23 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalderivedproperties.{c,h} + CREATOR: eric 09 May 1999 + + $Id: icalderivedproperty.h.in,v 1.1 2001/04/17 17:23:17 jpr Exp $ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + ======================================================================*/ + + +#ifndef ICALDERIVEDPROPERTY_H +#define ICALDERIVEDPROPERTY_H + +#include <time.h> +#include "icalparameter.h" +#include "icalderivedvalue.h" +#include "icalrecur.h" + +typedef void icalproperty; + + +/* Everything below this line is machine generated. Do not edit. */ diff --git a/libical/src/libical/icalderivedvalue.c.in b/libical/src/libical/icalderivedvalue.c.in new file mode 100644 index 0000000000..420ffb9ef0 --- /dev/null +++ b/libical/src/libical/icalderivedvalue.c.in @@ -0,0 +1,299 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.c + CREATOR: eric 02 May 1999 + + $Id: icalderivedvalue.c.in,v 1.1 2001/04/17 17:23:17 jpr Exp $ + + + (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 icalvalue.c + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalerror.h" +#include "icalmemory.h" +#include "icalparser.h" +#include "icalenums.h" + +#include "icalvalueimpl.h" + +#include <stdlib.h> /* for malloc */ +#include <stdio.h> /* for sprintf */ +#include <string.h> /* For memset, others */ +#include <stddef.h> /* For offsetof() macro */ +#include <errno.h> +#include <time.h> /* for mktime */ +#include <stdlib.h> /* for atoi and atof */ +#include <limits.h> /* for SHRT_MAX */ + + + +#define TMP_BUF_SIZE 1024 + +struct icalvalue_impl* icalvalue_new_impl(icalvalue_kind kind); + +/* This map associates each of the value types with its string + representation */ +struct icalvalue_kind_map { + icalvalue_kind kind; + char name[20]; +}; + +extern struct icalvalue_kind_map value_map[]; + +const char* icalvalue_kind_to_string(icalvalue_kind kind) +{ + int i; + + for (i=0; value_map[i].kind != ICAL_NO_VALUE; i++) { + if (value_map[i].kind == kind) { + return value_map[i].name; + } + } + + return 0; +} + +icalvalue_kind icalvalue_string_to_kind(const char* str) +{ + int i; + + for (i=0; value_map[i].kind != ICAL_NO_VALUE; i++) { + if (strcmp(value_map[i].name,str) == 0) { + return value_map[i].kind; + } + } + + return value_map[i].kind; + +} + +icalvalue* icalvalue_new_x (const char* v){ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_X_VALUE); + icalerror_check_arg_rz( (v!=0),"v"); + + icalvalue_set_x((icalvalue*)impl,v); + return (icalvalue*)impl; +} +void icalvalue_set_x(icalvalue* value, const char* v) { + struct icalvalue_impl* impl; + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_arg_rv( (v!=0),"v"); + + impl = (struct icalvalue_impl*)value; + if(impl->x_value!=0) {free((void*)impl->x_value);} + + impl->x_value = icalmemory_strdup(v); + + if (impl->x_value == 0){ + errno = ENOMEM; + } + + } +const char* icalvalue_get_x(icalvalue* value) { + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_X_VALUE); + return ((struct icalvalue_impl*)value)->x_value; +} + +/* Recur is a special case, so it is not auto generated. */ +icalvalue* +icalvalue_new_recur (struct icalrecurrencetype v) +{ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_RECUR_VALUE); + + icalvalue_set_recur((icalvalue*)impl,v); + + return (icalvalue*)impl; +} + +void +icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v) +{ + struct icalvalue_impl* impl; + + icalerror_check_arg_rv( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_RECUR_VALUE); + + impl = (struct icalvalue_impl*)value; + + if (impl->data.v_recur != 0){ + free(impl->data.v_recur); + impl->data.v_recur = 0; + } + + impl->data.v_recur = malloc(sizeof(struct icalrecurrencetype)); + + if (impl->data.v_recur == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return; + } else { + memcpy(impl->data.v_recur, &v, sizeof(struct icalrecurrencetype)); + } + +} + +struct icalrecurrencetype +icalvalue_get_recur(icalvalue* value) +{ + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_RECUR_VALUE); + + return *(((struct icalvalue_impl*)value)->data.v_recur); +} + + + + +icalvalue* +icalvalue_new_trigger (struct icaltriggertype v) +{ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_TRIGGER_VALUE); + + icalvalue_set_trigger((icalvalue*)impl,v); + + return (icalvalue*)impl; +} + +void +icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v) +{ + struct icalvalue_impl* impl; + + icalerror_check_arg_rv( (value!=0),"value"); + + impl = (struct icalvalue_impl*)value; + + if(!icaltime_is_null_time(v.time)){ + icalvalue_set_datetime((icalvalue*)impl,v.time); + impl->kind = ICAL_DATETIME_VALUE; + } else { + icalvalue_set_duration((icalvalue*)impl,v.duration); + impl->kind = ICAL_DURATION_VALUE; + } + +} + +struct icaltriggertype +icalvalue_get_trigger(icalvalue* value) +{ + struct icalvalue_impl *impl = (struct icalvalue_impl*)value; + struct icaltriggertype tr; + + icalerror_check_arg( (value!=0),"value"); + icalerror_check_arg( (value!=0),"value"); + + if(impl->kind == ICAL_DATETIME_VALUE){ + tr.duration = icaldurationtype_from_int(0); + tr.time = impl->data.v_time; + } else if(impl->kind == ICAL_DURATION_VALUE){ + tr.time = icaltime_null_time(); + tr.duration = impl->data.v_duration; + } else { + tr.duration = icaldurationtype_from_int(0); + tr.time = icaltime_null_time(); + icalerror_set_errno(ICAL_BADARG_ERROR); + } + + return tr; +} + +/* DATE-TIME-PERIOD is a special case, and is not auto generated */ + +icalvalue* +icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v) +{ + struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_DATETIMEPERIOD_VALUE); + + icalvalue_set_datetimeperiod((icalvalue*)impl,v); + + return (icalvalue*)impl; +} + +void +icalvalue_set_datetimeperiod(icalvalue* value, struct icaldatetimeperiodtype v) +{ + struct icalvalue_impl* impl = (struct icalvalue_impl*)value; + + icalerror_check_arg_rv( (value!=0),"value"); + + icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE); + + if(!icaltime_is_null_time(v.time)){ + if(!icaltime_is_valid_time(v.time)){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + impl->kind = ICAL_DATETIME_VALUE; + icalvalue_set_datetime(impl,v.time); + } else if (!icalperiodtype_is_null_period(v.period)) { + if(!icalperiodtype_is_valid_period(v.period)){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return; + } + impl->kind = ICAL_PERIOD_VALUE; + icalvalue_set_period(impl,v.period); + } else { + icalerror_set_errno(ICAL_BADARG_ERROR); + } +} + +struct icaldatetimeperiodtype +icalvalue_get_datetimeperiod(icalvalue* value) +{ + struct icaldatetimeperiodtype dtp; + + struct icalvalue_impl* impl = (struct icalvalue_impl*)value; + icalerror_check_arg( (value!=0),"value"); + icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE); + + if(impl->kind == ICAL_DATETIME_VALUE){ + dtp.period = icalperiodtype_null_period(); + dtp.time = impl->data.v_time; + } else if(impl->kind == ICAL_PERIOD_VALUE) { + dtp.period = impl->data.v_period; + dtp.time = icaltime_null_time(); + } else { + dtp.period = icalperiodtype_null_period(); + dtp.time = icaltime_null_time(); + icalerror_set_errno(ICAL_BADARG_ERROR); + } + + return dtp; +} + + + + + + + + + +/* The remaining interfaces are 'new', 'set' and 'get' for each of the value + types */ + + +/* Everything below this line is machine generated. Do not edit. */ diff --git a/libical/src/libical/icalderivedvalue.h.in b/libical/src/libical/icalderivedvalue.h.in new file mode 100644 index 0000000000..640dd86821 --- /dev/null +++ b/libical/src/libical/icalderivedvalue.h.in @@ -0,0 +1,58 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.h + CREATOR: eric 20 March 1999 + + + $Id: icalderivedvalue.h.in,v 1.1 2001/04/17 17:23:17 jpr Exp $ + $Locker: $ + + + + (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 icalvalue.h + + ======================================================================*/ + +#ifndef ICALDERIVEDVALUE_H +#define ICALDERIVEDVALUE_H + +#include "icaltypes.h" +#include "icalrecur.h" +#include "icaltime.h" +#include "icalduration.h" +#include "icalperiod.h" + +typedef void icalvalue; + + + +void icalvalue_set_x(icalvalue* value, const char* v); +icalvalue* icalvalue_new_x(const char* v); +const char* icalvalue_get_x(icalvalue* value); + +icalvalue* icalvalue_new_recur (struct icalrecurrencetype v); +void icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v); +struct icalrecurrencetype icalvalue_get_recur(icalvalue* value); + +icalvalue* icalvalue_new_trigger (struct icaltriggertype v); +void icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v); +struct icaltriggertype icalvalue_get_trigger(icalvalue* value); + +icalvalue* icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v); +void icalvalue_set_datetimeperiod(icalvalue* value, struct icaldatetimeperiodtype v); +struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(icalvalue* value); + +/* Everything below this line is machine generated. Do not edit. */ diff --git a/libical/src/libical/icalduration.c b/libical/src/libical/icalduration.c new file mode 100644 index 0000000000..18a74396f5 --- /dev/null +++ b/libical/src/libical/icalduration.c @@ -0,0 +1,320 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icaltime.c + CREATOR: eric 02 June 2000 + + $Id$ + $Locker$ + + (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 eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalduration.h" + +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef ICAL_NO_LIBICAL +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#define icalerror_check_arg_re(x,y,z) +#else +#include "icalerror.h" +#include "icalmemory.h" +#endif + + + + +/* From Seth Alves, <alves@hungry.com> */ +struct icaldurationtype icaldurationtype_from_int(int t) +{ + struct icaldurationtype dur; + int used = 0; + + dur = icaldurationtype_null_duration(); + + if(t < 0){ + dur.is_neg = 1; + t = -t; + } + + dur.weeks = (t - used) / (60 * 60 * 24 * 7); + used += dur.weeks * (60 * 60 * 24 * 7); + dur.days = (t - used) / (60 * 60 * 24); + used += dur.days * (60 * 60 * 24); + dur.hours = (t - used) / (60 * 60); + used += dur.hours * (60 * 60); + dur.minutes = (t - used) / (60); + used += dur.minutes * (60); + dur.seconds = (t - used); + + return dur; +} + +#ifndef ICAL_NO_LIBICAL +#include "icalvalue.h" +struct icaldurationtype icaldurationtype_from_string(const char* str) +{ + + int i; + int begin_flag = 0; + int time_flag = 0; + int date_flag = 0; + int week_flag = 0; + int digits=-1; + int scan_size = -1; + int size = strlen(str); + char p; + struct icaldurationtype d; + + memset(&d, 0, sizeof(struct icaldurationtype)); + + for(i=0;i != size;i++){ + p = str[i]; + + switch(p) + { + case '-': { + if(i != 0 || begin_flag == 1) goto error; + + d.is_neg = 1; + break; + } + + case 'P': { + if (i != 0 && i !=1 ) goto error; + begin_flag = 1; + break; + } + + case 'T': { + time_flag = 1; + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + + /* HACK. Skip any more digits if the l;ast one + read has not been assigned */ + if(digits != -1){ + break; + } + + if (begin_flag == 0) goto error; + /* Get all of the digits, not one at a time */ + scan_size = sscanf((char*)(str+i),"%d",&digits); + if(scan_size == 0) goto error; + break; + } + + case 'H': { + if (time_flag == 0||week_flag == 1||d.hours !=0||digits ==-1) + goto error; + d.hours = digits; digits = -1; + break; + } + case 'M': { + if (time_flag == 0||week_flag==1||d.minutes != 0||digits ==-1) + goto error; + d.minutes = digits; digits = -1; + break; + } + case 'S': { + if (time_flag == 0||week_flag==1||d.seconds!=0||digits ==-1) + goto error; + d.seconds = digits; digits = -1; + break; + } + case 'W': { + if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1) + goto error; + week_flag = 1; + d.weeks = digits; digits = -1; + break; + } + case 'D': { + if (time_flag==1||week_flag==1||d.days!=0||digits ==-1) + goto error; + date_flag = 1; + d.days = digits; digits = -1; + break; + } + default: { + goto error; + } + + } + } + + return d; + + + error: + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + memset(&d, 0, sizeof(struct icaldurationtype)); + return d; + +} + +#define TMP_BUF_SIZE 1024 +void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size, + char* sep, unsigned int value) { + + char temp[TMP_BUF_SIZE]; + + sprintf(temp,"%d",value); + + icalmemory_append_string(buf, buf_ptr, buf_size, temp); + icalmemory_append_string(buf, buf_ptr, buf_size, sep); + +} + +char* icaldurationtype_as_ical_string(struct icaldurationtype d) +{ + + char *buf, *output_line; + size_t buf_size = 256; + char* buf_ptr = 0; + int seconds; + + buf = (char*)icalmemory_new_buffer(buf_size); + buf_ptr = buf; + + + seconds = icaldurationtype_as_int(d); + + if(seconds !=0){ + + if(d.is_neg == 1){ + icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-'); + } + + icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P'); + + if (d.weeks != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks); + } + + if (d.days != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days); + } + + if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) { + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T"); + + if (d.hours != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours); + } + if (d.minutes != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "M", + d.minutes); + } + if (d.seconds != 0 ) { + append_duration_segment(&buf, &buf_ptr, &buf_size, "S", + d.seconds); + } + + } + } else { + icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PTS0"); + } + + output_line = icalmemory_tmp_copy(buf); + icalmemory_free_buffer(buf); + + return output_line; + +} + +#endif + + +/* From Russel Steinthal */ +int icaldurationtype_as_int(struct icaldurationtype dur) +{ + return (int)( (dur.seconds + + (60 * dur.minutes) + + (60 * 60 * dur.hours) + + (60 * 60 * 24 * dur.days) + + (60 * 60 * 24 * 7 * dur.weeks)) + * (dur.is_neg==1? -1 : 1) ) ; +} + +struct icaldurationtype icaldurationtype_null_duration() +{ + struct icaldurationtype d; + + memset(&d,0,sizeof(struct icaldurationtype)); + + return d; +} + +int icaldurationtype_is_null_duration(struct icaldurationtype d) +{ + if(icaldurationtype_as_int(d) == 0){ + return 1; + } else { + return 0; + } +} + + + +struct icaltimetype icaltime_add(struct icaltimetype t, + struct icaldurationtype d) +{ + int dt = icaldurationtype_as_int(d); + + t.second += dt; + + t = icaltime_normalize(t); + + return t; +} + +struct icaldurationtype icaltime_subtract(struct icaltimetype t1, + struct icaltimetype t2) +{ + + time_t t1t = icaltime_as_timet(t1); + time_t t2t = icaltime_as_timet(t2); + + return icaldurationtype_from_int(t1t-t2t); + + +} + diff --git a/libical/src/libical/icalduration.h b/libical/src/libical/icalduration.h new file mode 100644 index 0000000000..dd6e311f47 --- /dev/null +++ b/libical/src/libical/icalduration.h @@ -0,0 +1,60 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalduration.h + CREATOR: eric 26 Jan 2001 + + + $Id$ + $Locker$ + + (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 eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALDURATION_H +#define ICALDURATION_H + +#include "icaltime.h" + +struct icaldurationtype +{ + int is_neg; + unsigned int days; + unsigned int weeks; + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +}; + +struct icaldurationtype icaldurationtype_from_int(int t); +struct icaldurationtype icaldurationtype_from_string(const char*); +int icaldurationtype_as_int(struct icaldurationtype duration); +char* icaldurationtype_as_ical_string(struct icaldurationtype d); +struct icaldurationtype icaldurationtype_null_duration(); +int icaldurationtype_is_null_duration(struct icaldurationtype d); + +struct icaltimetype icaltime_add(struct icaltimetype t, + struct icaldurationtype d); + +struct icaldurationtype icaltime_subtract(struct icaltimetype t1, + struct icaltimetype t2); + +#endif /* !ICALDURATION_H */ + + + diff --git a/libical/src/libical/icalparameterimpl.h b/libical/src/libical/icalparameterimpl.h new file mode 100644 index 0000000000..2d0fdd642d --- /dev/null +++ b/libical/src/libical/icalparameterimpl.h @@ -0,0 +1,52 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalparameterimpl.h + CREATOR: eric 09 May 1999 + + $Id$ + $Locker$ + + + (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 icalderivedparameters.{c,h} + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + ======================================================================*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef ICALPARAMETER_IMPL +#define ICALPARAMETER_IMPL + +#include "icalparameter.h" +#include "icalproperty.h" + +struct icalparameter_impl +{ + icalparameter_kind kind; + char id[5]; + int size; + const char* string; + const char* x_name; + icalproperty* parent; + + int data; +}; + + +#endif /*ICALPARAMETER_IMPL*/ diff --git a/libical/src/libical/icalperiod.c b/libical/src/libical/icalperiod.c new file mode 100644 index 0000000000..c74c157eff --- /dev/null +++ b/libical/src/libical/icalperiod.c @@ -0,0 +1,170 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalperiod.c + CREATOR: eric 02 June 2000 + + $Id$ + $Locker$ + + (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 eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icalperiod.h" + +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef ICAL_NO_LIBICAL +#define icalerror_set_errno(x) +#define icalerror_check_arg_rv(x,y) +#define icalerror_check_arg_re(x,y,z) +#else +#include "icalerror.h" +#include "icalmemory.h" +#endif + + + + +struct icalperiodtype icalperiodtype_from_string (const char* str) +{ + + struct icalperiodtype p, null_p; + char *s = icalmemory_strdup(str); + char *start, *end = s; + icalerrorstate es; + + /* Errors are normally generated in the following code, so save + the error state for resoration later */ + + icalerrorenum e = icalerrno; + + p.start = p.end = icaltime_null_time(); + p.duration = icaldurationtype_from_int(0); + + null_p = p; + + if(s == 0) goto error; + + start = s; + end = strchr(s, '/'); + + if(end == 0) goto error; + + *end = 0; + end++; + + p.start = icaltime_from_string(start); + + if (icaltime_is_null_time(p.start)) goto error; + + es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR); + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL); + + p.end = icaltime_from_string(end); + + icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es); + + + if (icaltime_is_null_time(p.end)){ + + p.duration = icaldurationtype_from_string(end); + + if(icaldurationtype_as_int(p.duration) == 0) goto error; + } + + icalerrno = e; + + return p; + + error: + icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); + return null_p; +} + + +const char* icalperiodtype_as_ical_string(struct icalperiodtype p) +{ + + const char* start; + const char* end; + + char *buf; + size_t buf_size = 40; + char* buf_ptr = 0; + + buf = (char*)icalmemory_new_buffer(buf_size); + buf_ptr = buf; + + + start = icaltime_as_ical_string(p.start); + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, start); + + if(!icaltime_is_null_time(p.end)){ + end = icaltime_as_ical_string(p.end); + } else { + end = icaldurationtype_as_ical_string(p.duration); + } + + icalmemory_append_char(&buf, &buf_ptr, &buf_size, '/'); + + icalmemory_append_string(&buf, &buf_ptr, &buf_size, end); + + + return buf; +} + + + +struct icalperiodtype icalperiodtype_null_period() { + struct icalperiodtype p; + p.start = icaltime_null_time(); + p.end = icaltime_null_time(); + p.duration = icaldurationtype_null_duration(); + + return p; +} +int icalperiodtype_is_null_period(struct icalperiodtype p){ + + if(icaltime_is_null_time(p.start) && + icaltime_is_null_time(p.end) && + icaldurationtype_is_null_duration(p.duration)){ + return 1; + } else { + return 0; + } +} + +int icalperiodtype_is_valid_period(struct icalperiodtype p){ + if(icaltime_is_valid_time(p.start) && + (icaltime_is_valid_time(p.end) || icaltime_is_null_time(p.end)) ) + { + return 1; + } + + return 0; +} + diff --git a/libical/src/libical/icalperiod.h b/libical/src/libical/icalperiod.h new file mode 100644 index 0000000000..64d53237ad --- /dev/null +++ b/libical/src/libical/icalperiod.h @@ -0,0 +1,55 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalperiod.h + CREATOR: eric 26 Jan 2001 + + + $Id$ + $Locker$ + + (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 eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALPERIOD_H +#define ICALPERIOD_H + +#include "icaltime.h" +#include "icalduration.h" + +struct icalperiodtype +{ + struct icaltimetype start; + struct icaltimetype end; + struct icaldurationtype duration; +}; + +struct icalperiodtype icalperiodtype_from_string (const char* str); + +const char* icalperiodtype_as_ical_string(struct icalperiodtype p); +struct icalperiodtype icalperiodtype_null_period(); +int icalperiodtype_is_null_period(struct icalperiodtype p); +int icalperiodtype_is_valid_period(struct icalperiodtype p); + + + + +#endif /* !ICALTIME_H */ + + + diff --git a/libical/src/libical/icalvalueimpl.h b/libical/src/libical/icalvalueimpl.h new file mode 100644 index 0000000000..b103c9cb3f --- /dev/null +++ b/libical/src/libical/icalvalueimpl.h @@ -0,0 +1,91 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalvalue.c + CREATOR: eric 02 May 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 icalvalue.c + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + +======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef ICALVALUEIMPL_H +#define ICALVALUEIMPL_H + +#include "icalenums.h" + + +struct icalvalue_impl { + icalvalue_kind kind; /*this is the kind that is visible from the outside*/ + + char id[5]; + int size; + icalproperty* parent; + const char* x_value; + + union data { + struct icalattachtype v_attach; + /* void *v_binary; */ /* use v_attach */ + const char *v_string; + /*char *v_text;*/ + /*char *v_caladdress;*/ + /*char *v_uri;*/ + float v_float; + int v_int; + /*int v_boolean;*/ + /*int v_integer;*/ + struct icaldurationtype v_duration; + /*int v_utcoffset;*/ + + struct icalperiodtype v_period; + /*struct icalperiodtype v_datetimeperiod;*/ + struct icalgeotype v_geo; + /*time_t v_time;*/ + struct icaltimetype v_time; + /*struct icaltimetype v_date;*/ + /*struct icaltimetype v_datetime;*/ + /*struct icaltimetype v_datetimedate;*/ + + /* struct icalrecurrencetype was once included + directly ( not referenced ) in this union, but it + contributes 2000 bytes to every value, so now it is + a reference*/ + + struct icalrecurrencetype *v_recur; + struct icaltriggertype v_trigger; + + int v_enum; + /* v_enum takes care of several enumerated types including: + icalproperty_method v_method; + icalproperty_status v_status; + icalproperty_action v_action; + icalproperty_class v_class; + icalproperty_transp v_transp; + */ + + } data; +}; + +#endif diff --git a/libical/src/libicalss/icalcstpclient.c b/libical/src/libicalss/icalcstpclient.c new file mode 100644 index 0000000000..d53d53f568 --- /dev/null +++ b/libical/src/libicalss/icalcstpclient.c @@ -0,0 +1,343 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalcstps.c + CREATOR: ebusboom 23 Jun 2000 + + $Id$ + $Locker$ + + (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/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ical.h" +#include "icalcstp.h" +#include "icalcstpclient.h" +#include "pvl.h" + +#include <sys/types.h> /* For send(), others */ +#include <sys/socket.h> /* For send(), others. */ +#include <unistd.h> /* For alarm */ +#include <errno.h> +#include <stdlib.h> /* for malloc */ +#include <string.h> + +#define EOL "\n" + + +/* Client state machine */ + +typedef enum icalcstpc_line_type { + ICALCSTPC_RESPONSE_CODE_LINE, + ICALCSTPC_TERMINATOR_LINE, + ICALCSTPC_APPLICATION_DATA_LINE +} icalcstpc_line_type; + +typedef enum icalcstpc_state { + ICALCSTPC_SEND_STATE, + ICALCSTPC_RESPONSE_CODE_STATE, + ICALCSTPC_RESPONSE_DATA_STATE +} icalcstpc_state; + + + +struct icalcstpc_impl { + int timeout; + icalparser *parser; + icalcstp_command command; + icalcstpc_state state; + char* next_output; + char* next_input; +}; + +icalcstpc* icalcstpc_new() +{ + struct icalcstpc_impl *impl; + + impl = malloc(sizeof(struct icalcstpc_impl)); + + if(impl == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + memset(impl,0,sizeof(struct icalcstpc_impl)); + + return impl; +} + +void icalcstpc_free(icalcstpc* cstpc) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstpc; + + if(impl->next_output != 0){ + free(impl->next_output); + } + + if(impl->next_input != 0){ + free(impl->next_input); + } + + + if(impl->parser != 0){ + icalparser_free(impl->parser); + } +} + +/* Get the next string to send to the server */ +char* icalcstpc_next_output(icalcstpc* cstp, char * line) +{ + char* out; + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + if(impl->next_output == 0){ + return 0; + } + + out = impl->next_output; + + impl->next_output = 0; + + icalmemory_add_tmp_buffer(out); + + return out; +} + +/* process the next string sent by the server */ +int icalcstpc_next_input(icalcstpc* cstp, char* line) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + icalcstpc_line_type line_type; + + if(icalcstp_line_is_endofdata(line) || line == 0){ + return 0; + } + + switch (impl->command){ + case ICAL_ABORT_COMMAND:{ + break; + } + case ICAL_AUTHENTICATE_COMMAND:{ + break; + } + case ICAL_CAPABILITY_COMMAND:{ + break; + } + case ICAL_CONTINUE_COMMAND:{ + break; + } + case ICAL_CALIDEXPAND_COMMAND:{ + break; + } + case ICAL_IDENTIFY_COMMAND:{ + break; + } + case ICAL_DISCONNECT_COMMAND:{ + break; + } + case ICAL_SENDDATA_COMMAND:{ + break; + } + case ICAL_STARTTLS_COMMAND:{ + break; + } + case ICAL_UPNEXPAND_COMMAND:{ + break; + } + case ICAL_COMPLETE_COMMAND:{ + break; + } + case ICAL_UNKNOWN_COMMAND:{ + break; + } + default: + break; + } +} + +/* After icalcstpc_next_input returns a 0, there are responses + ready. use these to get them */ +icalcstpc_response icalcstpc_first_response(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + +} + + +icalcstpc_response icalcstpc_next_response(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; +} + + +int icalcstpc_set_timeout(icalcstpc* cstp, int sec) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; +} + +icalerrorenum icalcstpc_abort(icalcstpc* cstp) +{ + struct icalcstpc_impl* impl = (struct icalcstpc_impl*)cstp; + + icalerror_check_arg_re(cstp!=0,"cstp",ICAL_BADARG_ERROR); + + impl->next_output = "ABORT\n"; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpclient_setup_output(icalcstpc* cstp, size_t sz) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + if(impl->next_output != 0){ + icalerror_set_errno(ICAL_USAGE_ERROR); + return ICAL_USAGE_ERROR; + } + + impl->next_output = malloc(sz); + + if(impl->next_output == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return ICAL_NEWFAILED_ERROR; + } + + return ICAL_NO_ERROR; + +} + +icalerrorenum icalcstpc_authenticate(icalcstpc* cstp, char* mechanism, + char* data, char* f(char*)) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + char* command_str; + icalerrorenum error; + size_t sz; + + icalerror_check_arg_re(cstp!=0,"cstp",ICAL_BADARG_ERROR); + icalerror_check_arg_re(mechanism!=0,"mechanism",ICAL_BADARG_ERROR); + icalerror_check_arg_re(data!=0,"data",ICAL_BADARG_ERROR); + icalerror_check_arg_re(f!=0,"f",ICAL_BADARG_ERROR); + + impl->command = ICAL_AUTHENTICATE_COMMAND; + + command_str = icalcstp_command_to_string(impl->command); + + sz = strlen(command_str) + strlen(mechanism) + strlen(data) + 4; + + if((error=icalcstpclient_setup_output(cstp,sz)) != ICAL_NO_ERROR){ + return error; + } + + sprintf(impl->next_output,"%s %s %s%s",command_str,mechanism,data,EOL); + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_capability(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + char* command_str; + icalerrorenum error; + size_t sz; + + icalerror_check_arg_re(cstp!=0,"cstp",ICAL_BADARG_ERROR); + + impl->command = ICAL_CAPABILITY_COMMAND; + + command_str = icalcstp_command_to_string(impl->command); + + sz = strlen(command_str); + + if((error=icalcstpclient_setup_output(cstp,sz)) != ICAL_NO_ERROR){ + return error; + } + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_calidexpand(icalcstpc* cstp,char* calid) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_CALIDEXPAND_COMMAND; + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_continue(icalcstpc* cstp, unsigned int time) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_CONTINUE_COMMAND; + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_disconnect(icalcstpc* cstp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + + impl->command = ICAL_DISCONNECT_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_identify(icalcstpc* cstp, char* id) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + + impl->command = ICAL_IDENTIFY_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_starttls(icalcstpc* cstp, char* command, + char* data, char * f(char*)) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_STARTTLS_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_upnexpand(icalcstpc* cstp,char* calid) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + + impl->command = ICAL_UPNEXPAND_COMMAND; + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcstpc_sendata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp) +{ + struct icalcstpc_impl *impl = (struct icalcstpc_impl *)cstp; + + impl->command = ICAL_SENDDATA_COMMAND; + + return ICAL_NO_ERROR; +} + + + + diff --git a/libical/src/libicalss/icalcstpclient.h b/libical/src/libicalss/icalcstpclient.h new file mode 100644 index 0000000000..8d9d0c904c --- /dev/null +++ b/libical/src/libicalss/icalcstpclient.h @@ -0,0 +1,100 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstpclient.h + CREATOR: eric 4 Feb 01 + + $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 icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTPC_H +#define ICALCSTPC_H + +#include "ical.h" +#include "icalcstp.h" + +/********************** Client (Sender) Interfaces **************************/ + +/* How to use: + + 1) Construct a new icalcstpc + 2) Issue a command by calling one of the command routines. + 3) Repeat until both call icalcstpc_next_output and + icalcstpc_next_input return 0: + 3a) Call icalcstpc_next_output. Send string to server. + 3b) Get string from server, & give to icalcstp_next_input() + 4) Iterate with icalcstpc_first_response & icalcstp_next_response to + get the servers responses + 5) Repeat at #2 +*/ + + +typedef void icalcstpc; + +/* Response code sent by the server. */ +typedef struct icalcstpc_response { + icalrequeststatus code; + char *arg; /* These strings are owned by libical */ + char *debug_text; + char *more_text; + void* result; +} icalcstpc_response; + + +icalcstpc* icalcstpc_new(); + +void icalcstpc_free(icalcstpc* cstpc); + +int icalcstpc_set_timeout(icalcstpc* cstp, int sec); + + +/* Get the next string to send to the server */ +char* icalcstpc_next_output(icalcstpc* cstp, char* line); + +/* process the next string from the server */ +int icalcstpc_next_input(icalcstpc* cstp, char * line); + +/* After icalcstpc_next_input returns a 0, there are responses + ready. use these to get them */ +icalcstpc_response icalcstpc_first_response(icalcstpc* cstp); +icalcstpc_response icalcstpc_next_response(icalcstpc* cstp); + +/* Issue a command */ +icalerrorenum icalcstpc_abort(icalcstpc* cstp); +icalerrorenum icalcstpc_authenticate(icalcstpc* cstp, char* mechanism, + char* init_data, char* f(char*) ); +icalerrorenum icalcstpc_capability(icalcstpc* cstp); +icalerrorenum icalcstpc_calidexpand(icalcstpc* cstp,char* calid); +icalerrorenum icalcstpc_continue(icalcstpc* cstp, unsigned int time); +icalerrorenum icalcstpc_disconnect(icalcstpc* cstp); +icalerrorenum icalcstpc_identify(icalcstpc* cstp, char* id); +icalerrorenum icalcstpc_starttls(icalcstpc* cstp, char* command, + char* init_data, char* f(char*)); +icalerrorenum icalcstpc_senddata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp); +icalerrorenum icalcstpc_upnexpand(icalcstpc* cstp,char* calid); +icalerrorenum icalcstpc_sendata(icalcstpc* cstp, unsigned int time, + icalcomponent *comp); + + +#endif /* !ICALCSTPC_H */ + + + diff --git a/libical/src/libicalss/icalcstpserver.c b/libical/src/libicalss/icalcstpserver.c new file mode 100644 index 0000000000..1a6ed7b976 --- /dev/null +++ b/libical/src/libicalss/icalcstpserver.c @@ -0,0 +1,278 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalcstpserver.c + CREATOR: ebusboom 13 Feb 01 + + $Id$ + $Locker$ + + (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/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ical.h" +#include "icalcstp.h" +#include "icalcstpserver.h" +#include "pvl.h" + +#include <sys/types.h> /* For send(), others */ +#include <sys/socket.h> /* For send(), others. */ +#include <unistd.h> /* For alarm */ +#include <errno.h> +#include <stdlib.h> /* for malloc */ +#include <string.h> + + + +struct icalcstps_impl { + int timeout; + icalparser *parser; + enum cstps_state major_state; + struct icalcstps_commandfp commandfp; +}; + + + + +/* This state machine is a Mealy-type: actions occur on the + transitions, not in the states. + + Here is the state machine diagram from the CAP draft: + + + STARTTLS / + CAPABILITY + +-------+ + | | +---------------+ + | +-----------+ AUTHENTICATE | | + +-->| Connected |-------------->| Authenticated | + +-----------+ | | + | +---------------+ + | | + | | + | | + | | +-----+ STARTTLS / + | V | | CAPABILITY / + | +---------------+ | IDENTIFY + | | |<-+ + | | Identified |<----+ + | +--------| | | + | | +---------------+ | command + | | | | completes + V |DISCONNECT | | + +--------------+ | |SENDDATA | + | Disconnected |<--+ | | + +--------------+ | | ABORT + A | | + | V | + | DISCONNECT +---------------+ | + +--------------------| Receive |--+ + | |<--+ + +---------------+ | + | | CONTINUTE + +----+ + + In this implmenetation, the transition from CONNECTED to IDENTIFIED + is non-standard. The spec specifies that on the ATHENTICATE + command, the machine transitions from CONNECTED to AUTHENTICATED, + and then immediately goes to IDENTIFIED. This makes AUTHENTICATED a + useless state, so I removed it */ + +struct state_table { + enum cstps_state major_state; + enum icalcstp_command command; + void (*action)(); + enum cstps_state next_state; + +} server_state_table[] = +{ + { CONNECTED, ICAL_CAPABILITY_COMMAND , 0, CONNECTED}, + { CONNECTED, ICAL_AUTHENTICATE_COMMAND , 0, IDENTIFIED}, /* Non-standard */ + { IDENTIFIED, ICAL_STARTTLS_COMMAND, 0, IDENTIFIED}, + { IDENTIFIED, ICAL_IDENTIFY_COMMAND, 0, IDENTIFIED}, + { IDENTIFIED, ICAL_CAPABILITY_COMMAND, 0, IDENTIFIED}, + { IDENTIFIED, ICAL_SENDDATA_COMMAND, 0, RECEIVE}, + { IDENTIFIED, ICAL_DISCONNECT_COMMAND, 0, DISCONNECTED}, + { DISCONNECTED, 0, 0, 0}, + { RECEIVE, ICAL_DISCONNECT_COMMAND, 0, DISCONNECTED}, + { RECEIVE, ICAL_CONTINUE_COMMAND, 0, RECEIVE}, + { RECEIVE, ICAL_ABORT_COMMAND , 0, IDENTIFIED}, + { RECEIVE, ICAL_COMPLETE_COMMAND , 0, IDENTIFIED} +}; + + +/**********************************************************************/ + + + +icalcstps* icalcstps_new(struct icalcstps_commandfp cfp) +{ + struct icalcstps_impl* impl; + + if ( ( impl = (struct icalcstps_impl*) + malloc(sizeof(struct icalcstps_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + impl->commandfp = cfp; + impl->timeout = 10; + + return (icalcstps*)impl; + +} + +void icalcstps_free(icalcstps* cstp); + +int icalcstps_set_timeout(icalcstps* cstp, int sec) +{ + struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp; + + icalerror_check_arg_rz( (cstp!=0), "cstp"); + + impl->timeout = sec; + + return sec; +} + +typedef struct icalcstps_response { + icalrequeststatus code; + char caluid[1024]; + void* result; +} icalcstps_response; + + +icalerrorenum prep_abort(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_authenticate(struct icalcstps_impl* impl, char* data) +{ return ICAL_NO_ERROR; +} +icalerrorenum prep_capability(struct icalcstps_impl* impl, char* data) +{ return ICAL_NO_ERROR; +} +icalerrorenum prep_calidexpand(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_continue(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_disconnect(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_identify(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_starttls(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_upnexpand(struct icalcstps_impl* impl, char* data) +{ + return ICAL_NO_ERROR; +} +icalerrorenum prep_sendata(struct icalcstps_impl* impl, char* data) +{ return ICAL_NO_ERROR; +} + +char* icalcstps_process_incoming(icalcstps* cstp, char* input) +{ + struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp; + char *i; + char *cmd_or_resp; + char *data; + char *input_cpy; + icalerrorenum error; + + icalerror_check_arg_rz(cstp !=0,"cstp"); + icalerror_check_arg_rz(input !=0,"input"); + + if ((input_cpy = (char*)strdup(input)) == 0){ + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + i = (char*)strstr(" ",input_cpy); + + cmd_or_resp = input_cpy; + + if (i != 0){ + *i = '\0'; + data = ++i; + } else { + data = 0; + } + + printf("cmd: %s\n",cmd_or_resp); + printf("data: %s\n",data); + + /* extract the command, look up in the state table, and dispatch + to the proper handler */ + + if(strcmp(cmd_or_resp,"ABORT") == 0){ + error = prep_abort(impl,data); + } else if(strcmp(cmd_or_resp,"AUTHENTICATE") == 0){ + error = prep_authenticate(impl,data); + } else if(strcmp(cmd_or_resp,"CAPABILITY") == 0){ + error = prep_capability(impl,data); + } else if(strcmp(cmd_or_resp,"CALIDEXPAND") == 0){ + error = prep_calidexpand(impl,data); + } else if(strcmp(cmd_or_resp,"CONTINUE") == 0){ + error = prep_continue(impl,data); + } else if(strcmp(cmd_or_resp,"DISCONNECT") == 0){ + error = prep_disconnect(impl,data); + } else if(strcmp(cmd_or_resp,"IDENTIFY") == 0){ + error = prep_identify(impl,data); + } else if(strcmp(cmd_or_resp,"STARTTLS") == 0){ + error = prep_starttls(impl,data); + } else if(strcmp(cmd_or_resp,"UPNEXPAND") == 0){ + error = prep_upnexpand(impl,data); + } else if(strcmp(cmd_or_resp,"SENDDATA") == 0){ + error = prep_sendata(impl,data); + } + + return 0; +} + + /* Read data until we get a end of data marker */ + + + +struct icalcstps_server_stubs { + icalerrorenum (*abort)(icalcstps* cstp); + icalerrorenum (*authenticate)(icalcstps* cstp, char* mechanism, + char* data); + icalerrorenum (*calidexpand)(icalcstps* cstp, char* calid); + icalerrorenum (*capability)(icalcstps* cstp); + icalerrorenum (*cont)(icalcstps* cstp, unsigned int time); + icalerrorenum (*identify)(icalcstps* cstp, char* id); + icalerrorenum (*disconnect)(icalcstps* cstp); + icalerrorenum (*sendata)(icalcstps* cstp, unsigned int time, + icalcomponent *comp); + icalerrorenum (*starttls)(icalcstps* cstp, char* command, + char* data); + icalerrorenum (*upnexpand)(icalcstps* cstp, char* upn); + icalerrorenum (*unknown)(icalcstps* cstp, char* command, char* data); +}; + diff --git a/libical/src/libicalss/icalcstpserver.h b/libical/src/libicalss/icalcstpserver.h new file mode 100644 index 0000000000..6fa2254b2e --- /dev/null +++ b/libical/src/libicalss/icalcstpserver.h @@ -0,0 +1,101 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcstpserver.h + CREATOR: eric 13 Feb 01 + + $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 icalcstp.h + +======================================================================*/ + + +#ifndef ICALCSTPS_H +#define ICALCSTPS_H + +#include "ical.h" + + +/********************** Server (Reciever) Interfaces *************************/ + +/* On the server side, the caller will recieve data from the incoming + socket and pass it to icalcstps_next_input. The caller then takes + the return from icalcstps_next_outpu and sends it out through the + socket. This gives the caller a point of control. If the cstp code + connected to the socket itself, it would be hard for the caller to + do anything else after the cstp code was started. + + All of the server and client command routines will generate + response codes. On the server side, these responses will be turned + into text and sent to the client. On the client side, the reponse + is the one sent from the server. + + Since each command can return multiple responses, the responses are + stored in the icalcstps object and are accesses by + icalcstps_first_response() and icalcstps_next_response() + + How to use: + + 1) Construct a new icalcstps, bound to your code via stubs + 2) Repeat forever: + 2a) Get string from client & give to icalcstps_next_input() + 2b) Repeat until icalcstp_next_output returns 0: + 2b1) Call icalcstps_next_output. + 2b2) Send string to client. +*/ + + + +typedef void icalcstps; + +/* Pointers to the rountines that + icalcstps_process_incoming will call when it recognizes a CSTP + command in the data. BTW, the CONTINUE command is named 'cont' + because 'continue' is a C keyword */ + +struct icalcstps_commandfp { + icalerrorenum (*abort)(icalcstps* cstp); + icalerrorenum (*authenticate)(icalcstps* cstp, char* mechanism, + char* data); + icalerrorenum (*calidexpand)(icalcstps* cstp, char* calid); + icalerrorenum (*capability)(icalcstps* cstp); + icalerrorenum (*cont)(icalcstps* cstp, unsigned int time); + icalerrorenum (*identify)(icalcstps* cstp, char* id); + icalerrorenum (*disconnect)(icalcstps* cstp); + icalerrorenum (*sendata)(icalcstps* cstp, unsigned int time, + icalcomponent *comp); + icalerrorenum (*starttls)(icalcstps* cstp, char* command, + char* data); + icalerrorenum (*upnexpand)(icalcstps* cstp, char* upn); + icalerrorenum (*unknown)(icalcstps* cstp, char* command, char* data); +}; + + + +icalcstps* icalcstps_new(struct icalcstps_commandfp stubs); + +void icalcstps_free(icalcstps* cstp); + +int icalcstps_set_timeout(icalcstps* cstp, int sec); + +/* Get the next string to send to the client */ +char* icalcstps_next_output(icalcstps* cstp); + +/* process the next string from the client */ +int icalcstps_next_input(icalcstps* cstp); + +#endif /* ICALCSTPS */ diff --git a/libical/src/libicalvcal/Makefile b/libical/src/libicalvcal/Makefile new file mode 100644 index 0000000000..3a5dfa999a --- /dev/null +++ b/libical/src/libicalvcal/Makefile @@ -0,0 +1,389 @@ +# Generated automatically from Makefile.in by configure. +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = . +top_srcdir = ../.. +prefix = /opt/gnome +exec_prefix = ${prefix} + +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +libexecdir = ${exec_prefix}/libexec +datadir = ${prefix}/share +sysconfdir = ${prefix}/etc +sharedstatedir = ${prefix}/com +localstatedir = ${prefix}/var +libdir = ${exec_prefix}/lib +infodir = ${prefix}/info +mandir = ${prefix}/man +includedir = ${prefix}/include +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/libical +pkglibdir = $(libdir)/libical +pkgincludedir = $(includedir)/libical + +top_builddir = ../.. + +ACLOCAL = aclocal +AUTOCONF = autoconf +AUTOMAKE = automake +AUTOHEADER = autoheader + +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} +transform = s,x,x, + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = i686-pc-linux-gnu +host_triplet = i686-pc-linux-gnu +AR = ar +AS = @AS@ +CC = gcc +DLLTOOL = @DLLTOOL@ +LEX = flex +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LN_S = ln -s +MAINT = # +MAKEINFO = makeinfo +OBJDUMP = @OBJDUMP@ +PACKAGE = libical +PERL = perl +PY_CFLAGS = -I/usr/include/python1.5 +PY_EXTRA_LIBS = -lieee -ldl -lpthread +PY_LIBS = python1.5 +PY_LIB_LOC = -L/usr/lib/python1.5/config +RANLIB = ranlib +VERSION = 0.23a +YACC = bison -y +python_val = true + +lib_LTLIBRARIES = libicalvcal.la + +INCLUDES = -I$(top_builddir) -I$(top_srcdir)/src/libical -I$(top_srcdir)/src/libicalss -I$(srcdir) + + +libicalvcal_la_LDFLAGS = -version-info 0:0:0 + +libicalvcal_la_SOURCES = icalvcal.c vcc.y vobject.c vcaltmp.c + + +libicalvcalincludedir = $(includedir)/libicalvcal + +libicalvcalinclude_HEADERS = icalvcal.h port.h vcc.h vobject.h vcaltmp.h + + +EXTRA_DIST = README.TXT vcaltest.c vctest.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(lib_LTLIBRARIES) + + +DEFS = -DHAVE_CONFIG_H -I. -I$(srcdir) -I../.. +CPPFLAGS = +LDFLAGS = +LIBS = +libicalvcal_la_LIBADD = +libicalvcal_la_OBJECTS = icalvcal.lo vcc.lo vobject.lo vcaltmp.lo +CFLAGS = -g -O2 +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +HEADERS = $(libicalvcalinclude_HEADERS) + +DIST_COMMON = Makefile.am Makefile.in vcc.c + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = gtar +GZIP_ENV = --best +DEP_FILES = .deps/icalvcal.P .deps/vcaltmp.P .deps/vcc.P \ +.deps/vobject.P +SOURCES = $(libicalvcal_la_SOURCES) +OBJECTS = $(libicalvcal_la_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s .y +$(srcdir)/Makefile.in: # Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libicalvcal/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-libLTLIBRARIES: + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + +distclean-libLTLIBRARIES: + +maintainer-clean-libLTLIBRARIES: + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libicalvcal.la: $(libicalvcal_la_OBJECTS) $(libicalvcal_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libicalvcal_la_LDFLAGS) $(libicalvcal_la_OBJECTS) $(libicalvcal_la_LIBADD) $(LIBS) +.y.c: + $(YACC) $(AM_YFLAGS) $(YFLAGS) $< && mv y.tab.c $*.c + if test -f y.tab.h; then \ + if cmp -s y.tab.h $*.h; then rm -f y.tab.h; else mv y.tab.h $*.h; fi; \ + else :; fi +vcc.h: vcc.c + + +install-libicalvcalincludeHEADERS: $(libicalvcalinclude_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libicalvcalincludedir) + @list='$(libicalvcalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \ + echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(libicalvcalincludedir)/$$p"; \ + $(INSTALL_DATA) $$d$$p $(DESTDIR)$(libicalvcalincludedir)/$$p; \ + done + +uninstall-libicalvcalincludeHEADERS: + @$(NORMAL_UNINSTALL) + list='$(libicalvcalinclude_HEADERS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(libicalvcalincludedir)/$$p; \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src/libicalvcal + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/libicalvcal/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-libLTLIBRARIES +install-exec: install-exec-am + +install-data-am: install-libicalvcalincludeHEADERS +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-libLTLIBRARIES \ + uninstall-libicalvcalincludeHEADERS +uninstall: uninstall-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libdir) \ + $(DESTDIR)$(libicalvcalincludedir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + -test -z "vcchvccc" || rm -f vcch vccc +mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-libLTLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-depend \ + distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-libLTLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-depend \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \ +clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \ +uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \ +distclean-compile clean-compile maintainer-clean-compile \ +mostlyclean-libtool distclean-libtool clean-libtool \ +maintainer-clean-libtool uninstall-libicalvcalincludeHEADERS \ +install-libicalvcalincludeHEADERS tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libical/src/python/ChangeLog b/libical/src/python/ChangeLog new file mode 100644 index 0000000000..7b16306ce5 --- /dev/null +++ b/libical/src/python/ChangeLog @@ -0,0 +1,109 @@ +2001-03-13 Eric Busboom <eric@softwarestudio.org> + + * Component.py Added Component.property() + +2001-03-10 Patrick Lewis <plewis@inetarena.com> + + * Added __str__ method to Collection.Collection + + * Component.Component can now be initialized without arguments + + * Made _singular_property and _multiple_properties (in Component) + useful for nearly all the specific component interfaces + + * Changed Property.Attendee and Property.Organizer to allow creation + with no arguments + + * Filled in Todo skeleton + + * Added test function for an Event + + +2001-03-05 Eric Busboom <eric@softwarestudio.org> + + * Property.py Added a lot of exception code to signal failure to + create a Property. + + * DerivedProperties.py Added derived property classes for RDATE + and TRIGGER, two properties that can have one of two value types. + + +2001-03-04 Eric Busboom <eric@softwarestudio.org> + + * Property.pm Added Property.ConstructorFailedError exception + + * Component.pm fixed bug in Collection.__setslice__. "," used + instead of ":" + +2001-03-04 Patrick Lewis <plewis@inetarena.com> + + * Split Libical.py file into Component.py, Property.py, Collection.py, + and Store.py + + * Added test_* functions to test.py + + * Changed component bindings to return a Collection when objects can + have multiple values + + * Changed Component object to allow for creation of an object without + an initial string + + * Added Todo and Journal events + +2001-02-28 Eric Busboom <eric@softwarestudio.org> + + * Property Remove most internal data. The property now work + alsmost entirely off of the icalproperty that it holds a reference + to. Made changes in all derived Properties to accomodate the + change. + + * Property Added __del__ + + * Component Component.properties() now caches properties that it + constructs, so two calls to properties() to that get the same + icalproperty will also get the same Property. + + * Property Added Property.__cmp__ to test equality of properties + based on ical string values + +2001-02-27 Eric Busboom <eric@softwarestudio.org> + + * Property Added Property.ref() to set/get the reference to the + Property's internal icalproperty + + * Property Property._update_value now changes the icalproperty + value if a reference has been set. + + * Component re-instituted Component.properties(). The routine now + adds a 'ref' key to the dict that holds the python pointer + string. The C hex value of the pointer is in the 'pid' key + + +2001-02-27 Patrick Lewis <plewis@inetarena.com> + + * Backed out changes to Component removing comp_p; + Component.comp_p should be restored + +2001-02-26 Eric Busboom <eric@softwarestudio.org> + + * Period Added test routine,test_period() + + * Period implemented methods in period + + * Time Addedd addition and subtraction operators + +2001-02-25 Eric Busboom <eric@softwarestudio.org> + + * Libical.py Added test routine for time, time_test() + + * Libical.py Remove end of line chars ('\r\n" ) from + Property._str__. Caller should add these lines itself + + * Liical.py CHanges Time._update_values to set time VALUE type + based on use of is_date, rather than length of string. + + * Libical.py Removed call to _update_value in TIme::timezone + + + * Libical.py changed update_value to _update_value + diff --git a/libical/src/python/Collection.py b/libical/src/python/Collection.py new file mode 100644 index 0000000000..48092aadaa --- /dev/null +++ b/libical/src/python/Collection.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +#====================================================================== +# FILE: Collection.py +# CREATOR: eric +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2001, Eric Busboom <eric@softwarestudio.org> +# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com> +# +# 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/ +#====================================================================== + +from types import * + +class Collection: + """A group of components that can be modified somewhat like a list. + + Usage: + Collection(componet, propSequence) + + component is a Component object + propSequence is a list or tuple of Property (or subclass of Property) + of objects already in component + """ + + def __init__(self, component, propSequence): + self._properties = list(propSequence[:]) + self._component = component + + def __getslice__(self, beg, end): + return Collection(self._component, self._properties[beg:end]) + + def __setslice__(self, beg, end, sequence): + + if not isinstance(sequence,ListType): + raise TypeError, "must assign list (not instance) to slice" + + oldProps = self._properties[beg:end] + + for p in oldProps: + self._component.remove_property(p) + + self._properties[beg:end] = sequence + for p in sequence: + self._component.add_property(p) + + def __getitem__(self, i): + return self._properties[i] + + def __setitem__(self, i, prop): + self._component.remove_property(self._properties[i]) + self._component.add_property(prop) + self._properties[i]=prop + + def __delitem__(self, i): + self._component.remove_property(self._properties[i]) + del self._properties[i] + + def __len__(self): + return len(self._properties) + + def __str__(self): + s = "[ " + if len(self._properties) > 0: + s = s + str(self._properties[0]) + for p in self._properties[1:]: + s = "%s, %s" % (s, p) + s = s + " ]" + return s + + def append(self, property): + self._properties.append(property) + self._component.add_property(property) + +class ComponentCollection: + + def __init__(self, parent, componentSequence): + self._parent = parent + self._components = list(componentSequence[:]) + + def __getslice__(self, beg, end): + return ComponentCollection(self._parent, self._components[beg:end]) + + def __setslice__(self, beg, end, sequence): + oldComps = self._components[beg:end] + self._components.__setslice__(beg, end, sequence) + for c in sequence: + self._components.addComponent(c) + for c in oldComps: + self._parent.remove_component(c) + + def __getitem__(self, i): + return self._components[i] + + def __setitem__(self, i, prop): + self._parent.remove_component(self._components[i]) + self._parent.add_property(prop) + self._components[i]=prop + + def __delitem__(self, i): + self._parent.remove_componet(self._components[i]) + del self._components[i] + + def __len__(self): + return len(self._components) + + def append(self, property): + self._components.append(property) + self._parent.addComponent(property) diff --git a/libical/src/python/Component.py b/libical/src/python/Component.py new file mode 100644 index 0000000000..f4399f6c20 --- /dev/null +++ b/libical/src/python/Component.py @@ -0,0 +1,670 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +#====================================================================== +# FILE: Component.py +# CREATOR: eric +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2001, Eric Busboom <eric@softwarestudio.org> +# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com> +# +# 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/ +#====================================================================== + +from LibicalWrap import * +from types import * +from Property import * +from Collection import * + +class Component: + + def __init__(self,str=None, component_kind="ANY", ref=None): + + if ref != None: + self._ref = ref + else: + self._ref = None + if str != None: + self._ref = icalparser_parse_string(str) + else: + kind = icalenum_string_to_component_kind(component_kind) + self._ref = icalcomponent_new(kind) + + self.cached_props = {} + + def __del__(self): + if self._ref != None and \ + icalcomponent_get_parent(self._ref) != None: + + for k in self.cached_props.keys(): + del self.cached_props[k] + + icalcomponent_free(self._ref) + self._ref = None + + def _prop_from_ref(self,p): + + d_string = icallangbind_property_eval_string(p,":") + d = eval(d_string) + d['ref'] = p + + if not self.cached_props.has_key(p): + + if d['value_type'] == 'DATE-TIME' or d['value_type'] == 'DATE': + prop = Time(d,) + elif d['value_type'] == 'PERIOD': + prop = Period(d) + elif d['value_type'] == 'DURATION': + prop = Duration(d) + elif d['name'] == 'ATTACH': + prop = Attach(d) + elif d['name'] == 'ATTENDEE': + prop = Attendee(d) + elif d['name'] == 'ORGANIZER': + prop = Organizer(d) + else: + prop=Property(ref=p) + + self.cached_props[p] = prop + + def property(self, type): + + p = icallangbind_get_first_property(self._ref,type) + + if p !='NULL': + self._prop_from_ref(p) + prop = self.cached_props[p] + return prop + else : + return None + + def properties(self,type='ANY'): + """ + Return a list of Property instances, each representing a + property of the type 'type.' + """ + + props = [] + + p = icallangbind_get_first_property(self._ref,type) + + while p !='NULL': + self._prop_from_ref(p) + prop = self.cached_props[p] + props.append(prop) + p = icallangbind_get_next_property(self._ref,type) + + return Collection(self,props) + + def add_property(self, prop): + "Adds the property object to the component." + + if not isinstance(prop,Property): + raise TypeError + + prop_p = prop.ref() + + if not prop_p: + s = str(prop) + prop_p = icalproperty_new_from_string(s) + + if prop_p == 'NULL': + raise "Bad property string: " + s + + prop.ref(prop_p) + + if icalproperty_get_parent(prop_p)=='NULL': + icalcomponent_add_property(self._ref, prop_p) + elif icalproperty_get_parent(prop_p) != self._ref: + raise "Property is already a child of another component" + + + def remove_property(self,prop): + + if prop.ref() and self.cached_props.has_key(prop.ref()): + + del self.cached_props[prop.ref()] + icalcomponent_remove_property(self._ref,prop.ref()) + + def components(self,type='ANY'): + comps = [] + + return comps + + def add_component(self, componentObj): + "Adds a child component." + pass + + + def remove_component(self, component): + "Removes a child component" + pass + + def as_ical_string(self): + return self.__str__() + + def __str__(self): + + return icalcomponent_as_ical_string(self._ref) + + + +def NewComponent(comp): + "Converts a string or C icalcomponent into the right component object." + + wasStr=0 # Were we passed a string or an icalcomponent? + + if isinstance (comp, StringType): + compStr = comp + comp = icalparser_parse_string(comp) + wasStr=1 + else: + compStr = icalcomponent_as_ical_string(comp) + + kind = icalcomponent_isa(comp) + kindStr = icalenum_component_kind_to_string(kind) + # Do I need to free kind? (I think not). + + if kindStr == 'VEVENT': + newComp = Event(compStr) + elif kindStr == 'VTODO': + newComp = Todo(compStr) + elif kindStr == 'VJOURNAL': + newComp = Journal(compstr) + else: + newComp = Component(compStr) + + # I don't think I need to free the component created when passed a string, + # as it wasn't created with a _new function. + + return newComp + + +class GenericComponent(Component): + + def __init__(self): + + # Component.__init__(self, str) # Call from subclasses + self._recurrence_set=None + + def _singular_property(self, name, value_type, value=None, + property_obj=None, enumerated_values=None): + """Sets or gets the value of a method which exists once per Component. + + This is a constructor method for properties without a strictly defined + object.""" + + curr_properties = self.properties(name) + + # Get the value + if value==None: + if len(curr_properties) == 0: + return None + elif len(curr_properties) == 1: + return curr_properties[0].value() + else: + raise ValueError, "too many properties of type %s" % propType + + # Set the value + else: + # Check if value is in enumerated_values + if enumerated_values: + value = upper(value) + if value not in enumerated_values: + raise ValueError, "%s is not one of %s" \ + % (value, enumerated_values) + + # Create the new property + if property_obj: + if not isinstance(value, property_obj): + # Create a special property_obj property + if property_obj == Time: + p = Time(value, name) + ## p.value_type(value_type) + else: + p = property_obj() + ## p.value_type(value_type) + p.value(value) + else: + p = value # value is already a property_obj + else: + # Create a generic property + p = Property(name) + ## p.value_type(value_type) + p.value(value) + + if len(curr_properties) == 1: + self.remove_property(curr_properties[0]) + elif len(curr_properties) > 1: + raise ValueError, "too many properties of type %s" % propType + + self.add_property(p) + + def method(self, v=None): + "Sets or returns the value of the METHOD property." + return self._singular_property("METHOD", "TEXT", v) + + def prodid(self, v=None): + "Sets or returns the value of the PRODID property." + return self._singular_property("PRODID", "TEXT", v) + + def calscale(self, v=None): + "Sets or returns the value of the CALSCALE property." + return self._singular_property("CALSCALE", "TEXT", v) + + def class_prop(self, v=None): # Class is a reserved word + "Sets or returns the value of the CLASS property." + if v!=None: + v = upper(v) + return self._singular_property('CLASS', 'TEXT', v) + + def created(self, v=None): + """Sets or returns the value of the CREATED property. + + Usage: + created(time_obj) # Set the value using a Time object + created('19970101T123000Z') # Set using an iCalendar string + created(982362522) # Set using seconds + created() # Return an iCalendar string + """ + return self._singular_property("CREATED", "DATE-TIME", v, Time) + + def description(self, v=None): + "Sets or returns the value of the DESCRIPTION property." + return self._singular_property("DESCRIPTION", "TEXT", v) + + def dtstamp(self, v=None): + """Sets or returns the value of the DTSTAMP property. + + Usage: + dtstamp(time_obj) # Set the value using a Time object + dtstamp('19970101T123000Z')# Set using an iCalendar string + dtstamp(982362522) # Set using seconds + dtstamp() # Return an iCalendar string + """ + return self._singular_property("DTSTAMP", "DATE-TIME", v, Time) + + def dtstart(self, v=None): + """Sets or returns the value of the DTSTART property. + + Usage: + dtstart(time_obj) # Set the value using a Time object + dtstart('19970101T123000Z') # Set the value as an iCalendar string + dtstart(982362522) # Set the value using seconds (time_t) + dtstart() # Return the time as an iCalendar string + """ + return self._singular_property("DTSTART", "DATE-TIME", v, Time) + + def last_modified(self, v=None): + """Sets or returns the value of the LAST-MODIFIED property. + + Usage: + lastmodified(time_obj) # Set the value using a Time object + lastmodified('19970101T123000Z')# Set using an iCalendar string + lastmodified(982362522) # Set using seconds + lastmodified() # Return an iCalendar string + """ + return self._singular_property("LAST-MODIFIED", "DATE-TIME", v, Time) + + def organizer(self, v=None): + """Sets or gets the value of the ORGANIZER property. + + Usage: + organizer(orgObj) # Set value using an organizer object + organizer('MAILTO:jd@not.com') # Set value using a CAL-ADDRESS string + organizer() # Return a CAL-ADDRESS string + """ + return self._singular_property('ORGANIZER', 'CAL-ADDRESS', v, + Organizer) + + def recurrence_id(self, v=None): + """Sets or gets the value for the RECURRENCE-ID property. + + Usage: + recurrence_id(recIdObj) # Set using a Recurrence_Id object + recurrence_id("19700801T133000") # Set using an iCalendar string + recurrence_id(8349873494) # Set using seconds from epoch + recurrence_id() # Return an iCalendar string + """ + return self._singular_property('RECURRENCE-ID', 'DATE-TIME', v, + Recurrence_Id) + + def sequence(self, v=None): + """Sets or gets the SEQUENCE value of the Event. + + Usage: + sequence(1) # Set the value using an integer + sequence('2') # Set the value using a string containing an integer + sequence() # Return an integer + """ + if isinstance(v, StringType): + v = int(str) + return self._singular_property('SEQUENCE', 'INTEGER', v) + + def summary(self, v=None): + "Sets or gets the SUMMARY value of the Event." + return self._singular_property('SUMMARY', 'TEXT', v) + + def uid(self, v=None): + "Sets or gets the UID of the Event." + return self._singular_property('UID', 'TEXT', v) + + def url(self, v=None): + """Sets or returns the URL property.""" + return self._singular_property('URL', 'URI', v) + + #### + # Not quite sure if this is how we want to handle recurrence rules, but + # this is a start. + + def recurrence_set(self): + "Returns the Events RecurrenceSet object." + if self._recurrence_set == None: # i.e haven't initialized one + self._recurrence_set = RecurrenceSet() + return self._recurrence_set + + ### + # Alarm interface. Returns an ComponentCollection. + + def alarms(self, values=None): + """Sets or returns ALARM components. + + Examples: + alarms((alarm1,)) # Set using Alarm component + alarms() # Returns an ComponentCollection of all Alarms + """ + if values!=None: + for alarm in values: + self.addComponent(alarm) + else: + return ComponentCollection(self, self.components('VALARM')) + + #### + # Methods that deal with Properties that can occur multiple times are + # below. They use the Collection class to return their Properties. + + def _multiple_properties(self, name, value_type, values, + property_obj=None): + "Processes set/get for Properties that can have multiple instances." + + # Set value + if values!=None: + if not isinstance(values, TupleType) \ + and not isinstance(values, ListType): + raise TypeError, "%s is not a tuple or list." + + # Delete old properties + for p in self.properties(name): + self.remove_property(p) + + for v in values: + if property_obj: # Specialized properties + if not isinstance(v, property_obj): # Make new object + new_prop = property_obj() + new_prop.value(v) + else: # Use existing object + new_prop = v + else: # Generic properties + new_prop= Property() + new_prop.name(name) + # new_prop.value_type(value_type) + new_prop.value(v) + + self.add_property(new_prop) + + # Get value + else: + return Collection(self, self.properties(name)) + + def attachments(self, values=None): + """Sets or returns a Collection of Attach properties. + + 'values' can be a sequence containing URLs (strings) and/or file-ish + objects. + """ + return self._multiple_properties("ATTACH", "", value, Attach) + + def attendees(self, value=None): + """Sets attendees or returns a Collection of Attendee objects. + + If setting the attendees, pass a sequence as the argument. + Examples: + # Set using Attendee objects + attendees((attObj1, attObj2)) + # Set using a CAL-ADDRESS string + attendees(['MAILTO:jdoe@somewhere.com']) + # Set using a combination of Attendee objects and strings + attendees(['MAILTO:jdoe@somewhere.com', attObj1]) + # Returns a list of Attendee objects + attendees() + + When setting the attendees, any previous Attendee objects in the Event + are overwritten. If you want to add to the Attendees, one way to do it + is: + + attendees().append(Attendee('MAILTO:jdoe@nothere.com')) + """ + return self._multiple_properties("ATTENDEE", "", value, Attendee) + + def categories(self, value=None): + """Sets categories or returns a Collection of CATEGORIES properties. + + If setting the categories, pass a sequence as the argument. + Examples: + # Set using string[s] + categories(('APPOINTMENT', 'EDUCATION')) + # Returns a list of Category properites + categories() + + When setting the attendees, any previous category Properties in the + Event are overwritten. If you want to add to the categories, one way + to do it is: + + new_cat=Property('CATEGORIES') + new_cat.value_type('TEXT') + new_cat.value('PERSONAL') + categories().append(new_cat) + """ + return self._multiple_properties("CATEGORIES", "TEXT", value) + + def comments(self, value=None): + "Sets or returns a Collection of COMMENT properties." + return self._multiple_properties('COMMENT', 'TEXT', value) + + def contacts(self, value=None): + "Sets or returns a Collection of CONTACT properties." + return self._multiple_properties('CONTACT', 'TEXT', value) + + def related_tos(self, value=None): + "Sets or returns a Collectoin of RELATED-TO properties." + return self._multiple_properties('RELATED-TO', 'TEXT', value) + + +class Event(GenericComponent): + "The iCalendar Event object." + + def __init__(self, str=None): + Component.__init__(self, str, "VEVENT") + GenericComponent.__init__(self) + + def component_type(self): + "Returns the type of component for the object." + return "VEVENT" + + def clone(self): + "Returns a copy of the object." + return Event(self.asIcalString()) + + def dtend(self, v=None): + """Sets or returns the value of the DTEND property. + + Usage: + dtend(time_obj) # Set the value using a Time object + dtend('19970101T123000Z') # Set the value as an iCalendar string + dtend(982362522) # Set the value using seconds (time_t) + dtend() # Return the time as an iCalendar string + + If the dtend value is being set and duration() has a value, the + duration property will be removed. + """ + if v != None: + duration = self.properties('DURATION') + for d in duration: # Clear DURATION properties + self.remove_property(d) + return self._singular_property("DTEND", "DATE-TIME", v, Time) + + def duration(self, v=None): + """Sets or returns the value of the duration property. + + Usage: + duration(dur_obj) # Set the value using a Duration object + duration("P3DT12H") # Set value as an iCalendar string + duration(3600) # Set duration using seconds + duration() # Return duration as an iCalendar string + + If the duration value is being set and dtend() has a value, the dtend + property will be removed. + """ + + if v != None: + dtend = self.properites('DTEND') + for d in dtend: + self.remove_property(d) # Clear DTEND properties + return self._singular_property("DURATION", "DURATION", v, Duration) + + def status(self, v=None): + "Sets or returns the value of the STATUS property." + + # These values are only good for VEVENT components (i.e. don't copy + # & paste into VTODO or VJOURNAL + valid_values=('TENTATIVE', 'CONFIRMED', 'CANCELLED') + return self._singular_property("STATUS", "TEXT", v, + enumerated_values=valid_values) + + def geo(self, v=None): + """Sets or returns the value of the GEO property. + + Usage: + geo(value) or + geo() # Returns the icalendar string + + 'value' is either a icalendar GEO string or a sequence with two 'float' + numbers. + + Examples: + geo('40.232;-115.9531') # Set value using string + geo((40.232, -115.9531)) # Set value using a sequence + geo() # Returns "40.232;-115.9531" + + To get the GEO property represented as a tuple and numbers instead of + the iCalendar string, use geo_get_tuple(). + """ + + if isinstance(v, ListType) or isinstance(v, TupleType): + v = "%s;%s" % (float(v[0]), float(v[1])) + return self._singular_property("GEO", "FLOAT", v) + + def geo_get_tuple(self): + """Returns the GEO property as a tuple.""" + + geo = self.geo() + geo = split(geo, ';') + return float(geo[0]), float(geo[1]) + + def location(self, v=None): + """Sets or returns the LOCATION property.""" + return self._singular_property("LOCATION", "TEXT", v) + + def transp(self, v=None): + """Sets or returns the TRANSP property.""" + ok_values = ('OPAQUE', 'TRANSPARENT') + return self._singular_property('TRANSP', 'TEXT', v, + enumerated_values=ok_values) + + def resources(self, v=None): + pass + +class Todo(GenericComponent): + "The iCalendar TODO component." + + def component_type(self): + "Returns the type of component for the object." + return "VTODO" + + def clone(self): + "Returns a copy of the object." + return Todo(self.asIcalString()) + + def completed(self, value=None): + return self._singular_property('COMPLETED', 'DATE-TIME', value, Time) + + def geo(self, value=None): + if isinstance(v, ListType) or isinstance(v, TupleType): + v = "%s;%s" % (float(v[0]), float(v[1])) + return self._singular_property("GEO", "FLOAT", value) + + def location(self, value=None): + return self._singular_property('LOCATION', 'TEXT', value) + + def percent(self, value=None): + if value!=None: + value = str(int(value)) + return self._singular_property('PERCENT', 'INTEGER', value) + + def status(self, value=None): + if value!=None: + value=upper(value) + ok_values = ('NEEDS-ACTION', 'COMPLETED', 'IN-PROCESS', 'CANCELLED') + return self._singular_property('STATUS', 'TEXT', value, + enumerated_values=ok_values) + + def due(self, value=None): + if value != None: + duration = self.properties('DURATION') + for d in duration: + self.remove_property(d) # Clear DURATION properties + return self._singular_property('DUE', 'DATE-TIME', value, Time) + + def duration(self, value=None): + if value != None: + due = self.properites('DUE') + for d in due: + self.remove_property(d) # Clear DUE properties + return self._singular_property("DURATION", "DURATION", value, Duration) + + def resources(): + pass + + +class Journal(GenericComponent): + "The iCalendar JOURNAL component." + + def component_type(self): + "Returns the type of component for the object." + return "VJOURNAL" + + def clone(self): + "Returns a copy of the object." + return Journal(self.asIcalString()) + + def status(self, v=None): + if v!=None: + v = upper(v) + ok_values=('DRAFT', 'FINAL', 'CANCELLED') + return self._singular_property('STATUS', 'TEXT', v, + enumerated_values=ok_values) + diff --git a/libical/src/python/DerivedProperties.py b/libical/src/python/DerivedProperties.py new file mode 100644 index 0000000000..b557a1f7d7 --- /dev/null +++ b/libical/src/python/DerivedProperties.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +#====================================================================== +# FILE: DerivedProperties.py +# CREATOR: eric +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2001, Eric Busboom <eric@softwarestudio.org> +# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com> +# +# 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/ +#====================================================================== + +from Property import Time, Period, Duration + +def RDate(arg): + + class RDate_Time(Time): + def __init__(self,arg): Time.__init__(self,arg,"RDATE") + + class RDate_Period(Period): + def __init__(self,arg): Period.__init__(self,arg,"RDATE") + + p = None + for c in [RDate_Time, RDate_Period]: + try: return c(arg) + except Property.ConstructorFailedError, d: pass + raise Property.ConstructorFailedError("Failed to construct RDATE from "+str(arg)) + + +def Trigger(arg): + class Trigger_Time(Time): + def __init__(self,arg): Time.__init__(self,arg,"TRIGGER") + + class Trigger_Duration(Duration): + def __init__(self,arg): Duration.__init__(self,arg,"TRIGGER") + + p = None + for c in [Trigger_Duration, Trigger_Time]: + try: return c(arg) + except Property.ConstructorFailedError, d: pass + raise Property.ConstructorFailedError("Failed to construct TRIGGER from "+str(arg)) + + + diff --git a/libical/src/python/Libical.py b/libical/src/python/Libical.py new file mode 100644 index 0000000000..78a0fff8ff --- /dev/null +++ b/libical/src/python/Libical.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +#====================================================================== +# FILE: Libical.py +# CREATOR: eric +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2001, Eric Busboom <eric@softwarestudio.org> +# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com> +# +# 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/ +#====================================================================== + + +import LibicalWrap + +from Component import Component, NewComponent, Event, Todo, Journal + +# Will eventually remove Time for real Property events +from Property import Property, Time, Duration, Period, Attendee, Organizer, \ + Recurrence_Id, Attach, RecurrenceSet + +from DerivedProperties import RDate, Trigger + +from Store import Store, FileStore diff --git a/libical/src/python/LibicalWrap.i b/libical/src/python/LibicalWrap.i new file mode 100644 index 0000000000..c6b6740383 --- /dev/null +++ b/libical/src/python/LibicalWrap.i @@ -0,0 +1,352 @@ +/* -*- Mode: C -*-*/ +/*====================================================================== + FILE: ical.i + + (C) COPYRIGHT 1999 Eric Busboom + http://www.softwarestudio.org + + The contents of this file are subject to the Mozilla Public License + Version 1.0 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and + limitations under the License. + + The original author is Eric Busboom + + Contributions from: + Graham Davison (g.m.davison@computer.org) + + ======================================================================*/ + +%module LibicalWrap + + +%{ +#include "ical.h" +#include "icalss.h" + +#include <sys/types.h> /* for size_t */ +#include <time.h> + +%} + + +#include "fcntl.h" /* For Open flags */ + +typedef void icalcomponent; +typedef void icalproperty; + +icalcomponent* icalparser_parse_string(char* str); + + +icalcomponent* icalcomponent_new(int kind); +icalcomponent* icalcomponent_new_clone(icalcomponent* component); +icalcomponent* icalcomponent_new_from_string(char* str); + +char* icalcomponent_as_ical_string(icalcomponent* component); + +void icalcomponent_free(icalcomponent* component); +int icalcomponent_count_errors(icalcomponent* component); +void icalcomponent_strip_errors(icalcomponent* component); +void icalcomponent_convert_errors(icalcomponent* component); + +icalproperty* icalcomponent_get_current_property(icalcomponent* component); + +icalproperty* icalcomponent_get_first_property(icalcomponent* component, + int kind); +icalproperty* icalcomponent_get_next_property(icalcomponent* component, + int kind); + +icalcomponent* icalcomponent_get_current_component (icalcomponent* component); + +icalcomponent* icalcomponent_get_first_component(icalcomponent* component, + int kind); +icalcomponent* icalcomponent_get_next_component(icalcomponent* component, + int kind); + +void icalcomponent_add_property(icalcomponent* component, + icalproperty* property); + +void icalcomponent_remove_property(icalcomponent* component, + icalproperty* property); + + +icalcomponent* icalcomponent_get_parent(icalcomponent* component); +int icalcomponent_isa(icalcomponent* component); + +int icalrestriction_check(icalcomponent* comp); + + +/* actually takes icalproperty_kind */ +icalproperty* icalproperty_new(int kind); + +icalproperty* icalproperty_new_from_string(char* str); + +char* icalproperty_as_ical_string(icalproperty *prop); + +void icalproperty_set_parameter_from_string(icalproperty* prop, + const char* name, const char* value); +void icalproperty_set_value_from_string(icalproperty* prop,const char* value, const char * kind); + +const char* icalproperty_get_value_as_string(icalproperty* prop); +const char* icalproperty_get_parameter_as_string(icalproperty* prop, + const char* name); + + +icalcomponent* icalproperty_get_parent(icalproperty* property); + +int icalerror_supress(const char* error); +void icalerror_restore(const char* error, int es); +char* icalerror_perror(); +void icalerror_clear_errno(void); + +const char* icalproperty_kind_to_string(int kind); +int icalproperty_string_to_kind(const char* string); +int icalproperty_kind_to_value_kind(int kind); + +const char* icalvalue_kind_to_string(int kind); +int icalvalue_string_to_kind(const char* str); + +const char* icalparameter_kind_to_string(int kind); +int icalparameter_string_to_kind(const char* string); + +const char* icalenum_component_kind_to_string(int kind); +int icalenum_string_to_component_kind(const char* string); + +int* icallangbind_new_array(int size); +void icallangbind_free_array(int* array); +int icallangbind_access_array(int* array, int index); + + + +int icalrecur_expand_recurrence(char* rule, int start, + int count, int* array); + + +/* Iterate through properties and components using strings for the kind */ +icalproperty* icallangbind_get_first_property(icalcomponent *c, + const char* prop); + +icalproperty* icallangbind_get_next_property(icalcomponent *c, + const char* prop); + +icalcomponent* icallangbind_get_first_component(icalcomponent *c, + const char* comp); + +icalcomponent* icallangbind_get_next_component(icalcomponent *c, + const char* comp); + + +/* Return a string that can be evaluated in perl or python to + generated a hash that holds the property's name, value and + parameters. Sep is the hash seperation string, "=>" for perl and + ":" for python */ +const char* icallangbind_property_eval_string(icalproperty* prop, char* sep); + +int icallangbind_string_to_open_flag(const char* str); + +/*********************************************************************** + Time routines +***********************************************************************/ + + +struct icaltimetype +{ + int year; + int month; + int day; + int hour; + int minute; + int second; + + int is_utc; /* 1-> time is in UTC timezone */ + + int is_date; /* 1 -> interpret this as date. */ + + const char* zone; /*Ptr to Olsen placename. Libical does not own mem*/ +}; + + +/* Convert seconds past UNIX epoch to a timetype*/ +struct icaltimetype icaltime_from_timet(int v, int is_date); + +/* Return the time as seconds past the UNIX epoch */ +/* Normally, this returns a time_t, but SWIG tries to turn that type + into a pointer */ +int icaltime_as_timet(struct icaltimetype); + +/* Return a string represention of the time, in RFC2445 format. The + string is owned by libical */ +char* icaltime_as_ical_string(struct icaltimetype tt); + +/* create a time from an ISO format string */ +struct icaltimetype icaltime_from_string(const char* str); + +/* Routines for handling timezones */ +/* Return the offset of the named zone as seconds. tt is a time + indicating the date for which you want the offset */ +int icaltime_utc_offset(struct icaltimetype tt, const char* tzid); + +/* convert tt, of timezone tzid, into a utc time. Does nothing if the + time is already UTC. */ +struct icaltimetype icaltime_as_utc(struct icaltimetype tt, + const char* tzid); + +/* convert tt, a time in UTC, into a time in timezone tzid */ +struct icaltimetype icaltime_as_zone(struct icaltimetype tt, + const char* tzid); + +/* Return a null time, which indicates no time has been set. This time represent the beginning of the epoch */ +struct icaltimetype icaltime_null_time(void); + +/* Return true of the time is null. */ +int icaltime_is_null_time(struct icaltimetype t); + +/* Returns false if the time is clearly invalid, but is not null. This + is usually the result of creating a new time type buy not clearing + it, or setting one of the flags to an illegal value. */ +int icaltime_is_valid_time(struct icaltimetype t); + +/* Reset all of the time components to be in their normal ranges. For + instance, given a time with minutes=70, the minutes will be reduces + to 10, and the hour incremented. This allows the caller to do + arithmetic on times without worrying about overflow or + underflow. */ +struct icaltimetype icaltime_normalize(struct icaltimetype t); + +/* Return the day of the year of the given time */ +short icaltime_day_of_year(struct icaltimetype t); + +/* Create a new time, given a day of year and a year. */ +struct icaltimetype icaltime_from_day_of_year(short doy, short year); + +/* Return the day of the week of the given time. Sunday is 0 */ +short icaltime_day_of_week(struct icaltimetype t); + +/* Return the day of the year for the Sunday of the week that the + given time is within. */ +short icaltime_start_doy_of_week(struct icaltimetype t); + +/* Return a string with the time represented in the same format as ctime(). THe string is owned by libical */ +char* icaltime_as_ctime(struct icaltimetype); + +/* Return the week number for the week the given time is within */ +short icaltime_week_number(struct icaltimetype t); + +/* Return -1, 0, or 1 to indicate that a<b, a==b or a>b */ +int icaltime_compare(struct icaltimetype a,struct icaltimetype b); + +/* like icaltime_compare, but only use the date parts. */ +int icaltime_compare_date_only(struct icaltimetype a, struct icaltimetype b); + +/* Return the number of days in the given month */ +short icaltime_days_in_month(short month,short year); + + +/*********************************************************************** + Duration Routines +***********************************************************************/ + + +struct icaldurationtype +{ + int is_neg; + unsigned int days; + unsigned int weeks; + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +}; + +struct icaldurationtype icaldurationtype_from_int(int t); +struct icaldurationtype icaldurationtype_from_string(const char*); +int icaldurationtype_as_int(struct icaldurationtype duration); +char* icaldurationtype_as_ical_string(struct icaldurationtype d); +struct icaldurationtype icaldurationtype_null_duration(); +int icaldurationtype_is_null_duration(struct icaldurationtype d); + +struct icaltimetype icaltime_add(struct icaltimetype t, + struct icaldurationtype d); + +struct icaldurationtype icaltime_subtract(struct icaltimetype t1, + struct icaltimetype t2); + + +/*********************************************************************** + Period Routines +***********************************************************************/ + + +struct icalperiodtype +{ + struct icaltimetype start; + struct icaltimetype end; + struct icaldurationtype duration; +}; + +struct icalperiodtype icalperiodtype_from_string (const char* str); + +const char* icalperiodtype_as_ical_string(struct icalperiodtype p); +struct icalperiodtype icalperiodtype_null_period(); +int icalperiodtype_is_null_period(struct icalperiodtype p); +int icalperiodtype_is_valid_period(struct icalperiodtype p); + + +/*********************************************************************** + Storage Routines +***********************************************************************/ + +icalfileset* icalfileset_new(const char* path); + +/* Like _new, but takes open() flags for opening the file */ +icalfileset* icalfileset_new_open(const char* path, + int flags, int mode); + +void icalfileset_free(icalfileset* cluster); + +const char* icalfileset_path(icalfileset* cluster); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately. */ +void icalfileset_mark(icalfileset* cluster); +icalerrorenum icalfileset_commit(icalfileset* cluster); + +icalerrorenum icalfileset_add_component(icalfileset* cluster, + icalcomponent* child); + +icalerrorenum icalfileset_remove_component(icalfileset* cluster, + icalcomponent* child); + +int icalfileset_count_components(icalfileset* cluster, + icalcomponent_kind kind); + +/* Restrict the component returned by icalfileset_first, _next to those + that pass the gauge. _clear removes the gauge */ +icalerrorenum icalfileset_select(icalfileset* store, icalgauge* gauge); +void icalfileset_clear(icalfileset* store); + +/* Get and search for a component by uid */ +icalcomponent* icalfileset_fetch(icalfileset* cluster, const char* uid); +int icalfileset_has_uid(icalfileset* cluster, const char* uid); +icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *c); + + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *oldcomp, + icalcomponent *newcomp); + +/* Iterate through components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icalfileset_get_current_component (icalfileset* cluster); +icalcomponent* icalfileset_get_first_component(icalfileset* cluster); +icalcomponent* icalfileset_get_next_component(icalfileset* cluster); +/* Return a reference to the internal component. You probably should + not be using this. */ + +icalcomponent* icalfileset_get_component(icalfileset* cluster); diff --git a/libical/src/python/Makefile b/libical/src/python/Makefile new file mode 100644 index 0000000000..39e3a6ed1e --- /dev/null +++ b/libical/src/python/Makefile @@ -0,0 +1,369 @@ +# Generated automatically from Makefile.in by configure. +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = . +top_srcdir = ../.. +prefix = /opt/gnome +exec_prefix = ${prefix} + +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +libexecdir = ${exec_prefix}/libexec +datadir = ${prefix}/share +sysconfdir = ${prefix}/etc +sharedstatedir = ${prefix}/com +localstatedir = ${prefix}/var +libdir = ${exec_prefix}/lib +infodir = ${prefix}/info +mandir = ${prefix}/man +includedir = ${prefix}/include +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/libical +pkglibdir = $(libdir)/libical +pkgincludedir = $(includedir)/libical + +top_builddir = ../.. + +ACLOCAL = aclocal +AUTOCONF = autoconf +AUTOMAKE = automake +AUTOHEADER = autoheader + +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} +transform = s,x,x, + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = i686-pc-linux-gnu +host_triplet = i686-pc-linux-gnu +AR = ar +AS = @AS@ +CC = gcc +DLLTOOL = @DLLTOOL@ +LEX = flex +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LN_S = ln -s +MAINT = # +MAKEINFO = makeinfo +OBJDUMP = @OBJDUMP@ +PACKAGE = libical +PERL = perl +PY_CFLAGS = -I/usr/include/python1.5 +PY_EXTRA_LIBS = -lieee -ldl -lpthread +PY_LIBS = python1.5 +PY_LIB_LOC = -L/usr/lib/python1.5/config +RANLIB = ranlib +VERSION = 0.23a +YACC = bison -y +python_val = true + +lib_LTLIBRARIES = libLibicalWrap.la + +libLibicalWrap_la_SOURCES = LibicalWrap.c + +INCLUDES = -I$(top_builddir) -I$(top_srcdir)/src -I$(top_builddir)/src -I$(top_srcdir)/src/libical -I$(srcdir)/libical -I$(top_srcdir)/src/libicalss -I$(srcdir)/libicalss $(PY_CFLAGS) + + +LDADD = ../libical/libical.la ../libicalss/libicalss.la + +CLEANFILES = LibicalWrap.c LibicalWrap_wrap.doc Libical.pyc LibicalWrap.so + +EXTRA_DIST = Libical.py LibicalWrap.i python-binding.txt test.py Collection.py Component.py DerivedProperties.py Property.py Store.py ChangeLog + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(lib_LTLIBRARIES) + + +DEFS = -DHAVE_CONFIG_H -I. -I$(srcdir) -I../.. +CPPFLAGS = +LDFLAGS = +LIBS = +libLibicalWrap_la_LDFLAGS = +libLibicalWrap_la_LIBADD = +libLibicalWrap_la_OBJECTS = LibicalWrap.lo +CFLAGS = -g -O2 +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = ChangeLog Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = gtar +GZIP_ENV = --best +DEP_FILES = .deps/LibicalWrap.P +SOURCES = $(libLibicalWrap_la_SOURCES) +OBJECTS = $(libLibicalWrap_la_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s +$(srcdir)/Makefile.in: # Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu src/python/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-libLTLIBRARIES: + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + +distclean-libLTLIBRARIES: + +maintainer-clean-libLTLIBRARIES: + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libLibicalWrap.la: $(libLibicalWrap_la_OBJECTS) $(libLibicalWrap_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libLibicalWrap_la_LDFLAGS) $(libLibicalWrap_la_OBJECTS) $(libLibicalWrap_la_LIBADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src/python + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/python/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-libLTLIBRARIES +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-libLTLIBRARIES +uninstall: uninstall-am +all-am: Makefile $(LTLIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libdir) + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-libLTLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-depend \ + distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-libLTLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-depend \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \ +clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \ +uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \ +distclean-compile clean-compile maintainer-clean-compile \ +mostlyclean-libtool distclean-libtool clean-libtool \ +maintainer-clean-libtool tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +all: LibicalWrap.so + +LibicalWrap.c: LibicalWrap.i + swig -python -o LibicalWrap.c LibicalWrap.i + +# This part should be done with libtool, but I don't know how to do +# it. Libtool needs to generate a shared library in this directory +# regardless of the value of AM_DISABLE_SHARED +LibicalWrap.so: LibicalWrap.c + ld -shared -o LibicalWrap.so LibicalWrap.o ../libical/.libs/libical.a ../libicalss/.libs/libicalss.a + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libical/src/python/Makefile.am b/libical/src/python/Makefile.am new file mode 100644 index 0000000000..8eaf4a74cb --- /dev/null +++ b/libical/src/python/Makefile.am @@ -0,0 +1,42 @@ + +lib_LTLIBRARIES = libLibicalWrap.la + +libLibicalWrap_la_SOURCES = LibicalWrap.c + +INCLUDES = \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src/libical \ + -I$(top_builddir)/src/libical \ + -I$(top_srcdir)/src/libicalss \ + $(PY_CFLAGS) + +LDADD = ../libical/libical.la ../libicalss/libicalss.la + +all: LibicalWrap.so + +LibicalWrap.c: LibicalWrap.i + swig -python -o LibicalWrap.c LibicalWrap.i + +# This part should be done with libtool, but I don't know how to do +# it. Libtool needs to generate a shared library in this directory +# regardless of the value of AM_DISABLE_SHARED +LibicalWrap.so: LibicalWrap.c + ld -shared -o LibicalWrap.so LibicalWrap.o ../libical/.libs/libical.a ../libicalss/.libs/libicalss.a + +CLEANFILES = LibicalWrap.c LibicalWrap_wrap.doc Libical.pyc LibicalWrap.so + +EXTRA_DIST = \ +Libical.py \ +LibicalWrap.i \ +python-binding.txt \ +test.py \ +Collection.py \ +Component.py \ +DerivedProperties.py \ +Property.py \ +Store.py \ +ChangeLog + + diff --git a/libical/src/python/Makefile.in b/libical/src/python/Makefile.in new file mode 100644 index 0000000000..ec74701b19 --- /dev/null +++ b/libical/src/python/Makefile.in @@ -0,0 +1,369 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AR = @AR@ +AS = @AS@ +CC = @CC@ +DLLTOOL = @DLLTOOL@ +LEX = @LEX@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +PERL = @PERL@ +PY_CFLAGS = @PY_CFLAGS@ +PY_EXTRA_LIBS = @PY_EXTRA_LIBS@ +PY_LIBS = @PY_LIBS@ +PY_LIB_LOC = @PY_LIB_LOC@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ +YACC = @YACC@ +python_val = @python_val@ + +lib_LTLIBRARIES = libLibicalWrap.la + +libLibicalWrap_la_SOURCES = LibicalWrap.c + +INCLUDES = -I$(top_builddir) -I$(top_srcdir)/src -I$(top_builddir)/src -I$(top_srcdir)/src/libical -I$(srcdir)/libical -I$(top_srcdir)/src/libicalss -I$(srcdir)/libicalss $(PY_CFLAGS) + + +LDADD = ../libical/libical.la ../libicalss/libicalss.la + +CLEANFILES = LibicalWrap.c LibicalWrap_wrap.doc Libical.pyc LibicalWrap.so + +EXTRA_DIST = Libical.py LibicalWrap.i python-binding.txt test.py Collection.py Component.py DerivedProperties.py Property.py Store.py ChangeLog + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(lib_LTLIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libLibicalWrap_la_LDFLAGS = +libLibicalWrap_la_LIBADD = +libLibicalWrap_la_OBJECTS = LibicalWrap.lo +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = ChangeLog Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = gtar +GZIP_ENV = --best +DEP_FILES = .deps/LibicalWrap.P +SOURCES = $(libLibicalWrap_la_SOURCES) +OBJECTS = $(libLibicalWrap_la_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu src/python/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-libLTLIBRARIES: + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + +distclean-libLTLIBRARIES: + +maintainer-clean-libLTLIBRARIES: + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libLibicalWrap.la: $(libLibicalWrap_la_OBJECTS) $(libLibicalWrap_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libLibicalWrap_la_LDFLAGS) $(libLibicalWrap_la_OBJECTS) $(libLibicalWrap_la_LIBADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src/python + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu src/python/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-libLTLIBRARIES +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-libLTLIBRARIES +uninstall: uninstall-am +all-am: Makefile $(LTLIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libdir) + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-libLTLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-depend \ + distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-libLTLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-depend \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \ +clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \ +uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \ +distclean-compile clean-compile maintainer-clean-compile \ +mostlyclean-libtool distclean-libtool clean-libtool \ +maintainer-clean-libtool tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +all: LibicalWrap.so + +LibicalWrap.c: LibicalWrap.i + swig -python -o LibicalWrap.c LibicalWrap.i + +# This part should be done with libtool, but I don't know how to do +# it. Libtool needs to generate a shared library in this directory +# regardless of the value of AM_DISABLE_SHARED +LibicalWrap.so: LibicalWrap.c + ld -shared -o LibicalWrap.so LibicalWrap.o ../libical/.libs/libical.a ../libicalss/.libs/libicalss.a + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libical/src/python/Property.py b/libical/src/python/Property.py new file mode 100644 index 0000000000..d63b265525 --- /dev/null +++ b/libical/src/python/Property.py @@ -0,0 +1,839 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +#====================================================================== +# FILE: Property.py +# CREATOR: eric +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2001, Eric Busboom <eric@softwarestudio.org> +# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com> +# +# 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/ +#====================================================================== + +from LibicalWrap import * +from types import * +import regsub +import base64 +from string import index, upper + +#def icalerror_supress(arg): +# pass + +#def icalerror_restore(a,b): +# pass + +def error_type(): + error = icalerror_perror() + return error[:index(error,':')] + +class Property: + """ Represent any iCalendar Property. + + Usage: + Property(dict) + + Where: + dict is a dictionary with keys of 'name', 'value_type', and 'value'. + In addition, parameter:parameter value entries may be included. + """ + + class ConstructorFailedError(Exception): + "Failed to construct a property" + + class UpdateFailedError(Exception): + "Failed to update the value of a property" + + + def __init__(self, type = None, ref = None): + + + assert(ref == None or isinstance(ref,StringType)) + assert(type == None or isinstance(type,StringType)) + + self._ref = None + + if ref != None: + self._ref = ref + elif type != None: + kind = icalproperty_string_to_kind(type) + self._ref = icalproperty_new(kind) + + + if self._ref == None or self._ref == 'NULL': + raise Property.ConstructorFailedError("Failed to construct Property") + + self._deleted = 0; + + + # Initialize all of the required keys + + + def __del__(self): + + self._deleted = 1; + + if not self._deleted and \ + self.ref() and \ + icalproperty_get_parent(self.ref()) == 'NULL': + + icalproperty_free(self.ref()) + + def name(self,v=None): + """ Return the name of the property """ + str = icalproperty_as_ical_string(self._ref) + + idx = index(str, '\n') + + return str[:idx] + + def ref(self,v=None): + """ Return the internal reference to the libical icalproperty """ + if(v != None): + + if not self._deleted and self._ref and \ + icalproperty_get_parent(self._ref) == 'NULL': + + icalproperty_free(self._ref) + + self._ref = v + + return self._ref + + + def value(self,v=None, kind = None): + """ Return the RFC2445 representation of the value """ + + if(v != None): + + if kind != None: + # Get the default kind of value for this property + default_kind = icalvalue_kind_to_string(icalproperty_kind_to_value_kind(icalproperty_string_to_kind(self.name()))) + + if(kind != default_kind): + self.__setitem__('VALUE',kind) + vt = kind + elif self.__getitem__('VALUE'): + vt = self.__getitem__('VALUE') + else: + vt = 'NO' # Use the kind of the existing value + + + icalerror_clear_errno() + + #e1=icalerror_supress("MALFORMEDDATA") + icalproperty_set_value_from_string(self._ref,v,vt) + #icalerror_restore("MALFORMEDDATA",e1) + + if error_type() != "NO": + raise Property.UpdateFailedError(error_type()) + + s = icalproperty_get_value_as_string(self._ref) + assert(s == v) + + return icalproperty_get_value_as_string(self._ref) + + def parameters(self): + + d_string = icallangbind_property_eval_string(self._ref,":") + dict = eval(d_string) + + desc_keys = ('name', 'value', 'value_type', 'pid', 'ref', 'deleted' ) + + def foo(k,d=dict): + if d.has_key(k): del d[k] + + map( foo, desc_keys) + + return filter(lambda p, s=self: s[p] != None, dict.keys()) + + + def as_ical_string(self): + + return icalproperty_as_ical_string(self._ref) + + def __getitem__(self,key): + """ Return property values by name """ + key = upper(key) + + str = icalproperty_get_parameter_as_string(self._ref,key) + + if(str == 'NULL'): return None + + return str + + def __setitem__(self,key,value): + """ Set Property Values by Name """ + key = upper(key) + + icalproperty_set_parameter_from_string(self._ref,key,value) + + return self.__getitem__(key) + + def __str__(self): + + str = self.as_ical_string() + return regsub.gsub('\r?\n ?','',str) + + def __cmp__(self, other): + s_str = str(self) + o_str = str(other) + + return cmp(s_str,o_str) + + +class Time(Property): + """ Represent iCalendar DATE, TIME and DATE-TIME """ + def __init__(self, arg, name="DTSTART"): + """ + Create a new Time from a string or number of seconds past the + POSIX epoch + + Time("19970325T123000Z") Construct from an iCalendar string + Time(8349873494) Construct from seconds past POSIX epoch + + """ + e1=icalerror_supress("MALFORMEDDATA") + e2=icalerror_supress("BADARG") + + if isinstance(arg, DictType): + # Dictionary -- used for creating from Component + self.tt = icaltime_from_string(arg['value']) + Property.__init__(self, ref=arg['ref']) + else: + if isinstance(arg, StringType): + # Create from an iCal string + self.tt = icaltime_from_string(arg) + elif isinstance(arg, IntType) or \ + isinstance(arg, FloatType): + # Create from seconds past the POSIX epoch + self.tt = icaltime_from_timet(int(arg),0) + elif isinstance(arg, Time): + # Copy an instance + self.tt = arg.tt + else: + self.tt = icaltime_null_time() + + Property.__init__(self,type=name) + + icalerror_restore("MALFORMEDDATA",e1) + icalerror_restore("BADARG",e2) + + if icaltime_is_null_time(self.tt): + raise Property.ConstructorFailedError("Failed to construct a Time") + + try: + self._update_value() + except Property.UpdateFailedError: + raise Property.ConstructorFailedError("Failed to construct a Time") + + def _update_value(self): + self.tt = icaltime_normalize(self.tt) + self.value(icaltime_as_ical_string(self.tt),"DATE-TIME") + + def valid(self): + " Return true if this is a valid time " + return not icaltime_is_null_time(self.tt) + + def utc_seconds(self,v=None): + """ Return or set time in seconds past POSIX epoch""" + if (v!=None): + self.tt = icaltime_from_timet(v,0) + self._update_value() + + return icaltime_as_timet(self.tt) + + def is_utc(self,v=None): + """ Return or set boolean indicating if time is in UTC """ + if(v != None): + icaltimetype_is_utc_set(self.tt,v) + self._update_value() + return icaltimetype_is_utc_get(self.tt) + + def is_date(self,v=None): + """ Return or set boolean indicating if time is actually a date """ + if(v != None): + icaltimetype_is_date_set(self.tt,v) + self._update_value() + return icaltimetype_is_date_get(self.tt) + + def timezone(self,v=None): + """ Return or set the timezone string for this time """ + + if (v != None): + assert(isinstance(v,StringType) ) + self['TZID'] = v + return self['TZID'] + + def second(self,v=None): + """ Get or set the seconds component of this time """ + if(v != None): + icaltimetype_second_set(self.tt,v) + self._update_value() + return icaltimetype_second_get(self.tt) + + def minute(self,v=None): + """ Get or set the minute component of this time """ + if(v != None): + icaltimetype_minute_set(self.tt,v) + self._update_value() + return icaltimetype_minute_get(self.tt) + + def hour(self,v=None): + """ Get or set the hour component of this time """ + if(v != None): + icaltimetype_hour_set(self.tt,v) + self._update_value() + return icaltimetype_hour_get(self.tt) + + def day(self,v=None): + """ Get or set the month day component of this time """ + if(v != None): + icaltimetype_day_set(self.tt,v) + self._update_value() + return icaltimetype_day_get(self.tt) + + def month(self,v=None): + """ Get or set the month component of this time. January is month 1 """ + if(v != None): + icaltimetype_month_set(self.tt,v) + self._update_value() + return icaltimetype_month_get(self.tt) + + def year(self,v=None): + """ Get or set the year component of this time """ + if(v != None): + icaltimetype_year_set(self.tt,v) + self._update_value() + + return icaltimetype_year_get(self.tt) + + + + def __add__(self,o): + + other = Duration(o,"DURATION") + + if not other.valid(): + return Duration(0,"DURATION") + + seconds = self.utc_seconds() + other.seconds() + + new = Time(seconds,self.name()) + new.timezone(self.timezone()) + new.is_utc(self.is_utc()) + + return new + + def __radd_(self,o): + return self.__add__(o) + + + def __sub__(self,o): + + + if isinstance(o,Time): + # Subtract a time from this time and return a duration + seconds = self.utc_seconds() - other.utc_seconds() + return Duration(seconds) + elif isinstance(o,Duration): + # Subtract a duration from this time and return a time + other = Duration(o) + if(not other.valid()): + return Time() + + seconds = self.utc_seconds() - other.seconds() + return Time(seconds) + else: + raise TypeError, "subtraction with Time reqires Time or Duration" + +class Duration(Property): + """ + Represent a length of time, like 3 minutes, or 6 days, 20 seconds. + + + """ + + def __init__(self, arg, name="DURATION"): + """ + Create a new duration from an RFC2445 string or number of seconds. + Construct the duration from an iCalendar string or a number of seconds. + + Duration("P3DT2H34M45S") Construct from an iCalendar string + Duration(3660) Construct from seconds + """ + + self.dur = None + + e=icalerror_supress("MALFORMEDDATA") + + if isinstance(arg, DictType): + + self.dur = icaldurationtype_from_string(arg['value']) + Property.__init__(self,ref=arg['ref']) + else: + if isinstance(arg, StringType): + self.dur = icaldurationtype_from_string(arg) + elif isinstance(arg, IntType): + self.dur = icaldurationtype_from_int(arg) + elif isinstance(arg,Duration): + self.dur = arg.dur + else: + self.dur = icaldurationtype_null_duration() + + Property.__init__(self,type=name) + + icalerror_restore("MALFORMEDDATA",e) + + if self.dur == None or icaldurationtype_is_null_duration(self.dur): + raise Property.ConstructorFailedError("Failed to construct Duration from " +str(arg)) + + try: + self._update_value() + except Property.UpdateFailedError: + raise Property.ConstructorFailedError("Failed to construct Duration from " + str(arg)) + + def _update_value(self): + + self.value(icaldurationtype_as_ical_string(self.dur),"DURATION") + + def valid(self): + "Return true if this is a valid duration" + + return not icaldurationtype_is_null_duration(self.dur) + + def seconds(self,v=None): + """Return or set duration in seconds""" + if(v != None): + self.dur = icaldurationtype_from_int(v); + self.dict['value'] = icaltimedurationtype_as_ical_string(self.dur) + return icaldurationtype_as_int(self.dur) + + +class Period(Property): + """Represent a span of time""" + def __init__(self,arg,name='FREEBUSY'): + """ """ + + Property.__init__(self, type = name) + + self.pt=None + + #icalerror_clear_errno() + e1=icalerror_supress("MALFORMEDDATA") + e2=icalerror_supress("BADARG") + + if isinstance(arg, DictType): + + + es=icalerror_supress("MALFORMEDDATA") + self.pt = icalperiodtype_from_string(arg['value']) + icalerror_restore("MALFORMEDDATA",es) + + Property.__init__(self, ref=arg['ref']) + else: + if isinstance(arg, StringType): + + self.pt = icalperiodtype_from_string(arg) + + else: + self.pt = icalperiodtype_null_period() + + Property.__init__(self,type=name) + + icalerror_restore("MALFORMEDDATA",e1) + icalerror_restore("BADARG",e2) + + + if self.pt == None or icalperiodtype_is_null_period(self.pt): + raise Property.ConstructorFailedError("Failed to construct Period") + + + try: + self._update_value() + except Property.UpdateFailedError: + raise Property.ConstructorFailedError("Failed to construct Period") + + def _end_is_duration(self): + dur = icalperiodtype_duration_get(self.pt) + if not icaldurationtype_is_null_duration(dur): + return 1 + return 0 + + def _end_is_time(self): + end = icalperiodtype_end_get(self.pt) + if not icaltime_is_null_time(end): + return 1 + return 0 + + def _update_value(self): + + self.value(icalperiodtype_as_ical_string(self.pt),"PERIOD") + + + def valid(self): + "Return true if this is a valid period" + + return not icalperiodtype_is_null_period(self.dur) + + def start(self,v=None): + """ + Return or set start time of the period. The start time may be + expressed as an RFC2445 format string or an instance of Time. + The return value is an instance of Time + """ + + if(v != None): + if isinstance(t,Time): + t = v + elif isinstance(t,StringType) or isinstance(t,IntType): + t = Time(v,"DTSTART") + else: + raise TypeError + + icalperiodtype_start_set(self.pt,t.tt) + + self._update_value() + + + return Time(icaltime_as_timet(icalperiodtype_start_get(self.pt)), + "DTSTART") + + def end(self,v=None): + """ + Return or set end time of the period. The end time may be + expressed as an RFC2445 format string or an instance of Time. + The return value is an instance of Time. + + If the Period has a duration set, but not an end time, this + method will caluculate the end time from the duration. """ + + if(v != None): + + if isinstance(t,Time): + t = v + elif isinstance(t,StringType) or isinstance(t,IntType): + t = Time(v) + else: + raise TypeError + + if(self._end_is_duration()): + start = icaltime_as_timet(icalperiodtype_start_get(self.pt)) + dur = t.utc_seconds()-start; + icalperiodtype_duration_set(self.pt, + icaldurationtype_from_int(dur)) + else: + icalperiodtype_end_set(self.pt,t.tt) + + self._update_value() + + if(self._end_is_time()): + rt = Time(icaltime_as_timet(icalperiodtype_end_get(self.pt)), + 'DTEND') + rt.timezone(self.timezone()) + return rt + elif(self._end_is_duration()): + start = icaltime_as_timet(icalperiodtype_start_get(self.pt)) + dur = icaldurationtype_as_int(icalperiodtype_duration_get(self.pt)) + rt = Time(start+dur,'DTEND') + rt.timezone(self.timezone()) + return rt + else: + return Time({},'DTEND') + + + + def duration(self,v=None): + """ + Return or set the duration of the period. The duration may be + expressed as an RFC2445 format string or an instance of Duration. + The return value is an instance of Duration. + + If the period has an end time set, but not a duration, this + method will calculate the duration from the end time. """ + + if(v != None): + + if isinstance(t,Duration): + d = v + elif isinstance(t,StringType) or isinstance(t,IntType): + d = Duration(v) + else: + raise TypeError + + if(self._end_is_time()): + start = icaltime_as_timet(icalperiodtype_start_get(self.pt)) + end = start + d.seconds() + + icalperiodtype_end_set(self.pt,icaltime_from_timet(end,0)) + else: + icalperiodtype_duration_set(self.pt,d.dur) + + if(self._end_is_time()): + start =icaltime_as_timet(icalperiodtype_start_get(self.pt)) + end = icaltime_as_timet(icalperiodtype_end_get(self.pt)) + + print "End is time " + str(end-start) + + return Duration(end-start,"DURATION") + + elif(self._end_is_duration()): + dur = icaldurationtype_as_int( + icalperiodtype_duration_get(self.pt)) + + return Duration(dur,"DURATION") + else: + + + return Duration(0,"DURATION") + + + def timezone(self,v=None): + """ Return or set the timezone string for this time """ + if (v != None): + self['TZID'] = v + return self['TZID'] + +class Attendee(Property): + """Class for Attendee properties. + + Usage: + Attendee([dict]) + Attendee([address]) + + Where: + dict is an optional dictionary with keys of + 'value': CAL-ADDRESS string and any parameter: parameter_value entries. + 'name' and 'value_type' entries in dict are ignored and automatically set + with the appropriate values. + address is the CAL-ADDRESS (string) of the Attendee + """ + + def __init__(self, arg={}): + + assert(isinstance(arg,DictType)) + + ref = None + + if arg!={}: + ref = arg['ref'] + + Property.__init__(self,type='ATTENDEE',ref=ref) + + def _doParam(self, parameter, v): + if v!=None: + self[parameter]=v + return self[parameter] + + # Methods for accessing enumerated parameters + def cn(self, v=None): self._doParam('CN', v) + def cutype(self, v=None): self._doParam('CUTYPE', v) + def dir(self, v=None): self._doParam('DIR', v) + def delegated_from(self, v=None): self._doParam('DELEGATED-FROM', v) + def delegated_to(self, v=None): self._doParam('DELEGATED-TO', v) + def language(self, v=None): self._doParam('LANGUAGE', v) + def member(self, v=None): self._doParam('MEMBER', v) + def partstat(self, v=None): self._doParam('PARTSTAT', v) + def role(self, v=None): self._doParam('ROLE', v) + def rsvp(self, v=None): self._doParam('RSVP', v) + def sent_by(self, v=None): self._doParam('SENT-BY', v) + + +class Organizer(Property): + """Class for Organizer property. + """ + + def __init__(self, arg={}): + + assert(isinstance(arg, DictType)) + + ref = None + if arg != {}: + ref = arg['ref'] + Property.__init__(self, type='ORGANIZER', ref=ref) + +## param_t = ( 'CN', 'DIR', 'SENT-BY', 'LANGUAGE' ) +## for param in param_t: +## self[param] = None +## if value != None: +## self.value(value) + + + def _doParam(self, parameter, v): + if v!=None: + self[parameter]=v + return self[parameter] + + def name(self): + "Return the name of the property." + return Property.name(self) + + def value_type(self): + "Return the value type of the property." + return self._desc['value_type'] + + # Methods for accessing enumerated parameters + def cn(self, v=None): self._doParam('CN', v) + def dir(self, v=None): self._doParam('DIR', v) + def language(self, v=None): self._doParam('LANGUAGE', v) + def sent_by(self, v=None): self._doParam('SENT-BY', v) + +class Recurrence_Id(Time): + """Class for RECURRENCE-ID property. + + Usage: + Reccurence_Id(dict) # A normal property dictionary + Reccurence_Id("19960401") # An iCalendar string + Reccurence_Id(8349873494) # Seconds from epoch + + If the 'dict' constructor is used, 'name' and 'value_type' + entries in dict are ignored and automatically set with the appropriate + values. + """ + + def __init__(self, dict={}): + Time.__init__(self, dict) + Property.name(self, 'RECURRENCE-ID') + + def name(self): + return Property.name(self) + + def _doParam(self, parameter, v): + if v!=None: + self[parameter]=v + return self[parameter] + + # Enumerated parameters + def value_parameter(self, v=None): + """Sets or gets the VALUE parameter value. + + The value passed should be either "DATE-TIME" or "DATE". Setting this + parameter has no impact on the property's value_type. Doing something + like: + + rid=Recurrence_Id("19960401") # Sets value & makes value_type="DATE" + rid.value_parameter("DATE-TIME") # Sets the parameter VALUE=DATE-TIME + + Would be allowed (even though it is wrong), so pay attention. + Verifying the component will reveal the error. + """ + if v!=None and v!="DATE" and v!="DATE-TIME": + raise ValueError, "%s is an invalid VALUE parameter value" % str(v) + self._doParam("VALUE", v) + + def tzid(self, v=None): + "Sets or gets the TZID parameter value." + self._doParam("TZID", v) + + def range_parameter(self, v=None): # 'range' is a builtin function + "Sets or gets the RANGE parameter value." + if v!=None and v!="THISANDPRIOR" and v!= "THISANDFUTURE": + raise ValueError, "%s is an invalid RANGE parameter value" % str(v) + self._doParam("RANGE", v) + +class Attach(Property): + """A class representing an ATTACH property. + + Usage: + Attach(uriString [, parameter_dict]) + Attach(fileObj [, parameter_dict]) + """ + + def __init__(self, value=None, parameter_dict={}): + Property.__init__(self, parameter_dict) + Property.name(self, 'ATTACH') + self.value(value) + + def value(self, v=None): + "Returns or sets the value of the property." + if v != None: + if isinstance(v, StringType): # Is a URI + self._desc['value']=v + Property.value_type(self, 'URI') + else: + try: + tempStr = v.read() + except: + raise TypeError,"%s must be a URL string or file-ish type"\ + % str(v) + self._desc['value'] = base64.encodestring(tempStr) + Property.value_type(self, 'BINARY') + else: + return self._desc['value'] + + def name(self): + "Returns the name of the property." + return Property.name(self) + + def value_type(self): + return Property.value_type(self) + + def fmttype(self, v=None): + "Gets or sets the FMTYPE parameter." + if v!= None: + self['FMTTYPE']=v + else: + return self['FMTTYPE'] + +class RecurrenceSet: + """ + Represents a set of event occurrences. This + class controls a component's RRULE, EXRULE, RDATE and EXDATE + properties and can produce from them a set of occurrences. + """ + + def __init__(self): + pass + + def include(self, **params): + """ + Include a date or rule to the set. + + Use date= or pass in a + Time instance to include a date. Included dates will add an + RDATE property or will remove an EXDATE property of the same + date. + + Use rule= or pass in a string to include a rule. Included + rules with either add a RRULE property or remove an EXRULE + property. + + """ + pass + + def exclude(self, **params): + """ + Exclude date or rule to the set. + + Use date= or pass in a Time instance to exclude a + date. Excluded dates will add an EXDATE property or will remove + an RDATE property of the same date. + + Use rule= or pass in a string to exclude a rule. Excluded + rules with either add an EXRULE property or remove an RRULE + property. + + """ + pass + + def occurrences(self, count=None): + """ + Return 'count' occurrences as a tuple of Time instances. + """ + pass + + diff --git a/libical/src/python/Store.py b/libical/src/python/Store.py new file mode 100644 index 0000000000..6d13bd5211 --- /dev/null +++ b/libical/src/python/Store.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +#====================================================================== +# FILE: Store.py +# CREATOR: eric +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2001, Eric Busboom <eric@softwarestudio.org> +# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com> +# +# 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/ +#====================================================================== + +from LibicalWrap import * +from Error import LibicalError +from Component import Component + +class Store: + """ + Base class for several component storage methods + """ + + class AddFailedError(LibicalError): + "Failed to add a property to the file store" + + class ConstructorFailedError(LibicalError): + "Failed to create a Store " + + def __init__(self): + pass + + def path(self): + pass + + def mark(self): + pass + + def commit(self): + pass + + def add_component(self, comp): + pass + + def remove_component(self, comp): + pass + + def count_components(self, kind): + pass + + def select(self, gauge): + pass + + def clearSelect(self): + pass + + def fetch(self, uid): + pass + + def fetchMatch(self, comp): + pass + + def modify(self, oldc, newc): + pass + + def current_component(self): + pass + + def first_component(self): + pass + + def next_component(self): + pass + + +class FileStore(Store): + + def __init__(self, file,mode="r",flags=0664): + + _flags = icallangbind_string_to_open_flag(mode) + + + if _flags == -1: + raise Store.ConstructorFailedError("Illegal value for mode: "+mode) + + e1=icalerror_supress("FILE") + self._ref = icalfileset_new_open(file,_flags,flags) + icalerror_restore("FILE",e1) + + print self._ref + + if self._ref == None or self._ref == 'NULL': + raise Store.ConstructorFailedError(file) + + def __del__(self): + icalfileset_free(self._ref) + + def path(self): + return icalfileset_path(self._ref) + + def mark(self): + icalfileset_mark(self._ref) + + def commit(self): + icalfileset_commit(self._ref) + + def add_component(self, comp): + if not isinstance(comp,Component): + raise Store.AddFailedError("Argument is not a component") + + error = icalfileset_add_component(self._ref,comp) + + def remove_component(self, comp): + if not isinstance(comp,Component): + raise Store.AddFailedError("Argument is not a component") + + error = icalfileset_remove_component(self._ref,comp) + + + + def count_components(self, kind): + pass + + def select(self, gauge): + pass + + def clearSelect(self): + pass + + def fetch(self, uid): + pass + + def fetchMatch(self, comp): + pass + + def modify(self, oldc, newc): + pass + + def current_component(self): + comp_ref = icalfileset_get_current_component(self._ref) + + if comp_ref == None: + return None + + return Component(ref=comp_ref) + + def first_component(self): + comp_ref = icalfileset_get_first_component(self._ref) + + if comp_ref == None: + return None + + return Component(ref=comp_ref) + + def next_component(self): + + comp_ref = icalfileset_get_next_component(self._ref) + + if comp_ref == None: + return None + + return Component(ref=comp_ref) + diff --git a/libical/src/python/python-binding.txt b/libical/src/python/python-binding.txt new file mode 100644 index 0000000000..7fc9e066bf --- /dev/null +++ b/libical/src/python/python-binding.txt @@ -0,0 +1,434 @@ + +Classes for python binding to libical +(Indentation indicates inheritance) + + Component + Event + JournalEntry + Todo + FreeBusy + Timezone + Alarm + AudioAlarm + EmailAlarm + ProcedureAlarm + DisplayAlarm + + Property + Attendee + Organizer + Status + Error + + Time + Period + Date + RecurrenceSet + + Timezone + TimezonePhase + + Store + FileStore + DirStore + CAPStore + HeapStore + MySQLStore + + + +Component is the central class in the design. The component can be +though of as a container for child components and properties, or as +representation of a specific kind of iCal object. The first +interface offers general property and component accessors, and the +second treats some types of objects in a special way. + +The general interface offers simple manipulators for child property +and components, and it only works with immediate children. So, given +the Component: + + BEGIN:VCALENDAR + METHOD:PUBLISH + BEGIN:VEVENT + BEGIN:VALARM + COMMENT: An Alarm + END:VALARM + END:VEVENT + END:VCALENDAR + +A caller would have to descend three levels to access the COMMENT +property in the alarm, but only one to access the METHOD property. + +Libical is almost entirely dedicated to the general interface; it +includes all of the *get_first_*, *_next_next_*, *_add_* and *_remove_* +routines. + +The specific interface works with derived classes of Property and +Component. In this interface, the caller could get the COMMENT in the +alarm in the example in two steps. First the caller would ask the +Event object for its alarms, then then the caller would ask the first +Alarm object for its comment. + +The Specific interface is part of the +derived classes of Component. This interface names all of the types of +properties and components that can be accessed from the derived +component type. + +In libical, the specific interface is primarily the "convenience +routines in icalcomponent.h, such as: + + + struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp); + void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v); + + void icalcomponent_set_duration(icalcomponent* comp, + struct icaldurationtype v); + struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp); + +These routines are smarter and do more work than the general +interface. From the general interface, you can set the DTEND +property of a component by creating the property and adding it to a +component. But, if the component already has a DURATION property, then +this is an error -- a component can't have both. + +icalcomponent_set_dtend determines if the component already has a +DURATION. If it does, it substracts the dtstart time from the new +dtend time and sets the duration to that. Otherwise, it creates aor +changes the DTEND. + +Also, icalcomponent_set_duration works the same regardless if the +component is a VCALENDAR or a VEVENT. If it is a VCALENDAR, the +routine descends into the VEVENT before making any changes. If it is +allready a VEVENT ( or VTODO or VJOURNAL ) the routine just makes the +changes. With icalcomponent_add_property, you need to do this check +yourself. + +( There should probably be a class between Component +and Event ,JournalEntry and Todo that names all of the properties and +components. Then Event, JournalEntry and Todo would remove the +accessors that did not apply to them. ) + +Parameters are accessed as dictionaries from Property or as attributes +of a derived class of Property. Both the names and the values of the +parameters are strings. + +The Store hierarchy is a interface to various ways to store iCal +components. Each of these has the same interface as its corresponding +libical module: + + FileStore icalfileset Store iCal components in a single file + DirStore icaldirset Use multiple files, one per month of + DTSTART + CAPStore Access components in a CAP server + HeapStore Components stored in memory + MySQLStore Components stored in a MySQL + database. + +The only iCal value objects that will be implemented as Python classes +are Time, Duration and Period. RecurrenceSet handles recurrence +rules. It replaces the properties RRULE, RDATE, EXRULE and EXDATE. + +(Not all of the libical modules are implemented ) + + +How to Use the library +---------------------- + +The most common usecases will be something like this: + +1)Caller opens a Store object on a file, server or database. The +caller retrieves one or more component. Some of the components will be +booked on the user's calendar. Other components will be messages that +other users have sent, like requests for meetings. + +2) The caller will use the Specific interface ( using methods specific +to each property ) to example the component and decide what to do with +it. + +3) Rarely, the caller will access the general interface to do things +that the specific interface has not implemented or cannot manage +well. + +4) Cller may create a new component, using a combination of the +general and specific interfaces. The caller may send the message to +another user via mail, or may submit it to the user's CAP server with +the CAPStore class. + + +Following are the methods in each of the classes. + +Component + Construct from string + output string in ical form + + Get a Property by type + Get a set of Properties by type + Remove a Property by reference + + Get a Component by type + Get a set of Components by type + Remove a Component by reference + + Validate the component ( insert properties for errors ) + Count error properties + Remove error properties + Convert error properties into REQUEST-STATUS properties + +Event, JournalEntry, Todo + + Construct from string + output string in ical form + + There are get/set accessors for every property. These are + listed in a later section + + +FreeBusy + + Construct from string + Construct from arguments + output string in ical form + + Accessors for the following properties. See below for return + types for these properties: + + method + prodid + attendee + dtstamp + dtstart + freebusy + organizer + uid + comment + contact + request-status + url + duration + sequence + +TimezonePhase + + Construct from string + Construct from arguments + output string in ical form + + Accessors for the following properties. See below for return + types for these properties: + + tzname + offsetto + offsetfrom + rrule + rdate + comment + +TimeZone + + Construct from string + Construct from arguments + output string in ical form + + Accessors for the following properties. See below for return + types for these properties: + + tzid + last-modified + tzurl + standard (returns TimezonePhase) + daylight (returns TimezonePhase) + + +Property + + Construct from string + Construct from arguments + output string in ical form + + Dictionary access to parameters + + Get/set value + +Attendee + + Construct from string + Construct from arguments + output string in ical form + + Access to the following properties and parameters: + cuid + cutype + member + role + rsvp + delto + delfrom + sentby + cn + dir + language + +Organizer + + Access to the following properties: + common_name + dir + sentby + language + + +Time +Date +Period + + Same interfaces as libical modules. + +RecurenceSet + I don't know -- need to think about it more. + +Store + Similar methods to the icalset modules. + + +RFC2445 Properties + +This is a list of all of the RFC2445 properties and their associated +VALUE type. + + +Property Value +---------------------------- +CALSCALE TEXT +METHOD TEXT +PRODID TEXT +VERSION TEXT +CATEGORIES TEXT +CLASS TEXT +COMMENT TEXT +DESCRIPTION TEXT +LOCATION TEXT +PERCENT-COMPLETE INTEGER +PRIORITY INTEGER +RESOURCES TEXT +STATUS STATUS +SUMMARY TEXT +COMPLETED DATE-TIME +FREEBUSY PERIOD +TRANSP TEXT +TZNAME TEXT +TZOFFSETFROM UTC-OFFSET +TZOFFSETTO UTC-OFFSET +TZURL URI +TZID TEXT +ATTENDEE CAL-ADDRESS +CONTACT TEXT +ORGANIZER CAL-ADDRESS +RELATED-TO TEXT +URL URI +UID TEXT +EXRULE RECUR +RRULE RECUR +ACTION TEXT +REPEAT INTEGER +CREATED DATE-TIME +DTSTAMP DATE-TIME +LAST-MODIFIED DATE-TIME +SEQUENCE INTEGER +X TEXT +REQUEST-STATUS STRING +ATTACH URL, BINARY +GEO FLOAT +DTEND DATE-TIME +DUE DATE-TIME +DTSTART DATE-TIME +RECURRENCE-ID DATE-TIME +EXDATE DATE-TIME +RDATE DATE-TIME, PERIOD +TRIGGER DATE-TIME, DURATION +DURATION DURATION + +Some of the properties can appear multiple times in a component, other +can appear only once. For a particular component, the number of times +a property can apper may also change with the METHOD property +associated with the component. This list shows which properties can +appear multiple times for some ( but not all ) combinations of +component type and METHOD value: + +ATTACH +ATTENDEE +CATEGORIES +COMMENT +CONTACT +EXDATE +EXRULE +FREEBUSY +NONE +RDATE +RELATEDTO +REQUESTSTATUS +RESOURCES +RRULE +TZNAME +TZURL +X + + +This is a list of the value types and their associated python return +types. A lowercased return type is a python builtin, and an +uppercase-first-letter is a class in the library: + + +Value Return Type +----------------------------------- +BINARY file +BOOLEAN number +CAL-ADDRESS string +DATE Time +DATE-TIME Time +DURATION Duration +FLOAT number +GEO tuple +INTEGER number +METHOD string +PERIOD Period +RECUR RecurrenceSet +TEXT string +TIME Time +URI string +UTC-OFFSET number +STATUS string +X string + + +I suspect that the Component class should use the three previous +tables to create the property accessor methods on the fly. If the +method generation system is general enough, we could also use it for +other classes, such as Alarm, Timezone, Attendee, Organizer and +Freebusy. + + +Memory Handling +--------------- + +One of the things that made the perl binding to libcal difficult was +that if a Component (in perl) returns a reference to a child Component +(in perl), the child Component (in perl) will contain a reference to a +libical component. When the caller is done with the child component in +perl, the caller just drops it and lets perl reclaim the memory. + +The destructor for Component needs to free the libical component that +it holds a reference to, but the child's libical component is still +being used by libical. So perl frees the libical component and later, +libical tries to reference freed memory. + +The situation is actually a little better than that, because libical +will throw an error when you try to free a component that is still +attached to a parent. + +So, the perl library has to be able to determine when the destructor +should free a libical component or not. The perl library calls +icalcomponent_get_parent(), and if is it non-zero, it does not free +the component. + +It is not hard, just more code, and something to watch out for. + diff --git a/libical/src/python/test.py b/libical/src/python/test.py new file mode 100644 index 0000000000..1fdf515408 --- /dev/null +++ b/libical/src/python/test.py @@ -0,0 +1,373 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +#====================================================================== +# FILE: test.py +# CREATOR: eric +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2001, Eric Busboom <eric@softwarestudio.org> +# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com> +# +# 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/ +#====================================================================== + +from Libical import * + +def error_type(): + error = icalerror_perror() + return error[:index(error,':')] + +comp_str = """ +BEGIN:VEVENT +ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com +COMMENT: When in the course of writting comments and nonsense text\, it + becomes necessary to insert a newline +DTSTART:19972512T120000 +DTSTART:19970101T120000Z +DTSTART:19970101 +DURATION:P3DT4H25M +FREEBUSY:19970101T120000/19970101T120000 +FREEBUSY:19970101T120000/PT3H +FREEBUSY:19970101T120000/PT3H +END:VEVENT""" + + +def test_property(): + + print "--------------------------- Test Property ----------------------" + + liw = LibicalWrap + icalprop = liw.icalproperty_new_from_string("ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com") + + print liw.icalproperty_as_ical_string(icalprop) + + p = Property(ref=icalprop) + + print p.name() + print p.parameters() + print p['ROLE'] + + p['ROLE'] = 'INDIVIDUAL' + + print p['ROLE'] + + print p.value() + p.value("mailto:Bob@bob.com") + print p.value() + + + print p.as_ical_string() + + try: + p = Property() + except Property.ConstructorFailedError: + pass + else: + assert(0) + +def test_time(): + "Test routine" + + print"-------------------Test Time --------------------------------" + + t = Time("19970325T123010Z",'DTSTART') + + assert(t.year() == 1997) + assert(t.month() == 3) + assert(t.day() == 25) + assert(t.hour() == 12) + assert(t.minute() == 30) + assert(t.second() == 10) + assert(t.is_utc()) + assert(not t.is_date()) + + print t + + t.timezone("America/Los_Angeles") + print str(t) + assert(str(t)=='DTSTART;TZID=America/Los_Angeles:19970325T123010Z') + + t.second(t.second()+80) + + print t + + assert(t.minute() == 31) + assert(t.second() == 30) + + d = Duration(3600,"DURATION") + t2 = t + d + + print t2 + assert(t2.hour() == 13) + + t2 = t - d + + print t2 + assert(isinstance(t2,Time)) + assert(t2.hour() == 11) + + +def test_period(): + + print"-------------------Test Period--------------------------------" + + p = Period("19970101T180000Z/19970101T233000Z") + + print p + + + assert(str(p) == 'FREEBUSY:19970101T180000Z/19970101T233000Z') + + print p.start() + assert(str(p.start()) == 'DTSTART:19970101T180000Z') + + print p.end() + assert(str(p.end()) == 'DTEND:19970101T233000Z') + + print p.duration() + assert(str(p.duration()) == 'DURATION:PT5H30M') + p = None + + p = Period("19970101T180000Z/PT5H30M") + print p + + print p.start() + assert(str(p.start()) == 'DTSTART:19970101T180000Z') + + print p.end() + assert(str(p.end()) == 'DTEND:19970101T233000Z') + + print p.duration() + assert(str(p.duration()) == 'DURATION:PT5H30M') + + +def test_duration(): + + print "-------------- Test Duration ----------------" + + # Ical string + + d = Duration("P3DT4H25M") + + print str(d) + + assert(str(d) == "DURATION:P3DT4H25M") + + print d.seconds() + + assert(d.seconds() == 275100) + + # seconds + + d = Duration(-275100) + + print str(d) + + assert(str(d) == "DURATION:-P3DT4H25M") + + print d.seconds() + + assert(d.seconds() == -275100) + + #error + + try: + d = Duration("P10WT7M") + print str(d) + assert(0) + except: pass + + try: + d = Duration("Pgiberish") + print str(d) + assert(0) + except: + pass + + + +def test_attach(): + + file = open('littlefile.txt') + attachProp = Attach(file) + file.close() + attachProp.fmttype('text/ascii') + print "\n" + attachProp.name() + print attachProp.value_type() + print attachProp.fmttype() + attachProp['fmttype']=None + print "Calling value()" + print attachProp.value() + print "Calling asIcalString()" + print attachProp.as_ical_string() + + +def test_component(): + + print "------------------- Test Component ----------------------" + + + c = Component(comp_str); + + props = c.properties() + + for p in props: + print p.as_ical_string() + + dtstart = c.properties('DTSTART')[0] + + print dtstart + + print "\n Orig hour: ", dtstart.hour() + assert(dtstart.hour() == 12) + + dtstart.hour(dtstart.hour() + 5) + + print "\n New hour: ", dtstart.hour() + assert(dtstart.hour() == 17) + + attendee = c.properties('ATTENDEE')[0] + + print attendee + + t = Time("20011111T123030") + t.name('DTEND') + + c.add_property(t) + + + print c + + dtstart1 = c.properties('DTSTART')[0] + dtstart2 = c.properties('DTSTART')[0] + dtstart3 = c.property('DTSTART') + + assert(dtstart1 is dtstart2) + assert(dtstart1 == dtstart2) + + assert(dtstart1 is dtstart3) + assert(dtstart1 == dtstart3) + + + p = Property(type="SUMMARY"); + p.value("This is a summary") + + c.properties().append(p) + + print c.as_ical_string() + + p = c.properties("SUMMARY")[0] + assert(p!=None); + print str(p) + assert(str(p) == "SUMMARY:This is a summary") + + c.properties()[:] = [p] + + print c.as_ical_string() + + +def test_event(): + print "------------ Event Class ----------------------" + event = Event() + event.created("20010313T123000Z") + #print "created =", event.created() + assert (event.created() == "20010313T123000Z") + + event.organizer("MAILTO:j_doe@nowhere.com") + org = event.properties('ORGANIZER')[0] + #print org.cn() + org.cn('Jane Doe') + assert (isinstance(org, Organizer)) + #print "organizer =", event.organizer() + assert (event.organizer() == "MAILTO:j_doe@nowhere.com") + + event.dtstart("20010401T183000Z") + #print "dtstart =", event.dtstart() + assert (event.dtstart()=="20010401T183000Z") + + dtend = Time('20010401T190000Z', 'DTEND') + event.dtend(dtend) + assert (event.dtend()==dtend.value()) + assert (event.dtend() == '20010401T190000Z') + + att = Attendee() + att.value('jsmith@nothere.com') + event.attendees(('ef_hutton@listenup.com', att)) + + event.description("A short description. Longer ones break things.") + event.status('TeNtAtIvE') + + print event.as_ical_string() + + +def test_derivedprop(): + + print "------------ Derived Properties -----------------" + + p = RDate("20011111T123030") + + print str(p) + + + p = RDate("19970101T120000/19970101T123000") + + print str(p) + + try: + p = RDate("P3DT4H25M") + print str(p) + assert(0) + except: pass + + + p = Trigger("P3DT4H25M") + + print str(p) + + p = Trigger("20011111T123030") + + print str(p) + + try: + p = Trigger("19970101T120000/19970101T123000") + print str(p) + assert(0) + except: pass + + +def run_tests(): + test_property() + + test_time() + + test_period() + + test_component() + + test_duration() + + test_derivedprop() + + test_event() + + #test_attach() + + + +if __name__ == "__main__": + run_tests() + |