diff options
Diffstat (limited to 'libical/src/libicalss')
-rw-r--r-- | libical/src/libicalss/Makefile | 49 | ||||
-rw-r--r-- | libical/src/libicalss/Makefile.in | 48 | ||||
-rw-r--r-- | libical/src/libicalss/icalcalendar.c | 263 | ||||
-rw-r--r-- | libical/src/libicalss/icalcalendar.h | 68 | ||||
-rw-r--r-- | libical/src/libicalss/icalcluster.c | 399 | ||||
-rw-r--r-- | libical/src/libicalss/icalcluster.h | 75 | ||||
-rw-r--r-- | libical/src/libicalss/icalcomponent.h | 115 | ||||
-rw-r--r-- | libical/src/libicalss/icalstore.c | 815 | ||||
-rw-r--r-- | libical/src/libicalss/icalstore.h | 78 |
9 files changed, 1910 insertions, 0 deletions
diff --git a/libical/src/libicalss/Makefile b/libical/src/libicalss/Makefile new file mode 100644 index 0000000000..91691b9051 --- /dev/null +++ b/libical/src/libicalss/Makefile @@ -0,0 +1,49 @@ +# Generated automatically from Makefile.in by configure. +SOURCES = icalcluster.c icalstore.c icalcalendar.c +OBJECTS = ${SOURCES:.c=.o} +INCLUDES = -I . -I.. -I../libical +CFLAGS = -Wall -g $(INCLUDES) -DSTDC_HEADERS=1 -DHAVE_MALLOC_H=1 -DHAVE_UNISTD_H=1 -DHAVE_TIME_H=1 -DHAVE_STDIO_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_ASSERT_H=1 -DHAVE_STRDUP=1 -DICAL_ERRORS_ARE_FATAL +LIBS = +CC = gcc +AR = ar cr +RANLIB = ranlib + +prefix = /usr/local +PREFIX = ${prefix} +EXEC_PREFIX = ${prefix} +BIN_DIR = $(EXEC_PREFIX)/bin +LIB_DIR = $(EXEC_PREFIX)/lib +INCLUDE_DIR = $(PREFIX)/include + +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM= ${INSTALL} -m 755 + +all: lib + +lib: $(OBJECTS) + $(AR) libicalss.a $(OBJECTS) + $(RANLIB) libicalss.a + + +clean: + -/bin/rm -f *.o *.a + -/bin/rm -f \#* + -/bin/rm -f *~ Makefile.bak icalitip.tab.h icalitip.tab.c lex.yy.c + -/bin/rm -f icaltest parser core output *.output + +ci: clean + ci -u *.c *.h *.l *.y Makefile.in + +depend: + @makedepend -Y $(INCLUDES) $(SOURCES) + + +install: + $(INSTALL_DATA) libicalss.a $(LIB_DIR)/libicalss.a; + for i in `ls *.h`; \ + do \ + $(INSTALL_DATA) $$i $(INCLUDE_DIR)/$$i; \ + done; + + diff --git a/libical/src/libicalss/Makefile.in b/libical/src/libicalss/Makefile.in new file mode 100644 index 0000000000..fe4de906ad --- /dev/null +++ b/libical/src/libicalss/Makefile.in @@ -0,0 +1,48 @@ +SOURCES = icalcluster.c icalstore.c icalcalendar.c +OBJECTS = ${SOURCES:.c=.o} +INCLUDES = -I . -I.. -I../libical +CFLAGS = -Wall @CFLAGS@ $(INCLUDES) @DEFS@ -DICAL_ERRORS_ARE_FATAL +LIBS = +CC = @CC@ +AR = @AR@ cr +RANLIB = @RANLIB@ + +prefix = @prefix@ +PREFIX = ${prefix} +EXEC_PREFIX = @exec_prefix@ +BIN_DIR = $(EXEC_PREFIX)/bin +LIB_DIR = $(EXEC_PREFIX)/lib +INCLUDE_DIR = $(PREFIX)/include + +INSTALL = @INSTALL@ +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM= ${INSTALL} -m 755 + +all: lib + +lib: $(OBJECTS) + $(AR) libicalss.a $(OBJECTS) + $(RANLIB) libicalss.a + + +clean: + -/bin/rm -f *.o *.a + -/bin/rm -f \#* + -/bin/rm -f *~ Makefile.bak icalitip.tab.h icalitip.tab.c lex.yy.c + -/bin/rm -f icaltest parser core output *.output + +ci: clean + ci -u *.c *.h *.l *.y Makefile.in + +depend: + @makedepend -Y $(INCLUDES) $(SOURCES) + + +install: + $(INSTALL_DATA) libicalss.a $(LIB_DIR)/libicalss.a; + for i in `ls *.h`; \ + do \ + $(INSTALL_DATA) $$i $(INCLUDE_DIR)/$$i; \ + done; + + diff --git a/libical/src/libicalss/icalcalendar.c b/libical/src/libicalss/icalcalendar.c new file mode 100644 index 0000000000..0933df1e31 --- /dev/null +++ b/libical/src/libicalss/icalcalendar.c @@ -0,0 +1,263 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalcalendar.c + CREATOR: eric 23 December 1999 + + $Id$ + $Locker$ + + (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 Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +#include "icalcalendar.h" +#include "icalcluster.h" +#include <limits.h> +#include <sys/stat.h> /* For mkdir, stat */ +#include <sys/types.h> /* For mkdir */ +#include <fcntl.h> /* For mkdir */ +#include <unistd.h> /* For mkdir, stat */ +#include <stdlib.h> /* for malloc */ +#include <string.h> /* for strcat */ +#include <errno.h> + +#define BOOKED_DIR "booked" +#define INCOMING_FILE "incoming.ics" +#define PROP_FILE "properties.ics" +#define FBLIST_FILE "freebusy.ics" + +struct icalcalendar_impl +{ + char* dir; + icalcomponent* freebusy; + icalcomponent* properties; + icalstore* booked; + icalstore* incoming; +}; + +struct icalcalendar_impl* icalcalendar_new_impl() +{ + struct icalcalendar_impl* impl; + + if ( ( impl = (struct icalcalendar_impl*) + malloc(sizeof(struct icalcalendar_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + return impl; +} + + +icalerrorenum icalcalendar_create(struct icalcalendar_impl* impl) +{ + char path[PATH_MAX]; + struct stat sbuf; + int r; + + icalerror_check_arg_re((impl != 0),"impl",ICAL_BADARG_ERROR); + + path[0] = '\0'; + strcpy(path,impl->dir); + strcat(path,"/"); + strcat(path,BOOKED_DIR); + + r = stat(path,&sbuf); + + if( r != 0 && errno == ENOENT){ + + if(mkdir(path,0777)!=0){ + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + } + + return ICAL_NO_ERROR; +} + +icalcalendar* icalcalendar_new(char* dir) +{ + struct icalcalendar_impl* impl; + + icalerror_check_arg_rz((dir != 0),"dir"); + + impl = icalcalendar_new_impl(); + + if (impl == 0){ + return 0; + } + + impl->dir = (char*)strdup(dir); + impl->freebusy = 0; + impl->properties = 0; + impl->booked = 0; + impl->incoming = 0; + + if (icalcalendar_create(impl) != ICAL_NO_ERROR){ + free(impl); + return 0; + } + + return impl; +} + +void icalcalendar_free(icalcalendar* calendar) +{ + + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + + if (impl->dir !=0){ + free(impl->dir); + } + + if (impl->freebusy !=0){ + icalcluster_free(impl->freebusy); + } + + if (impl->properties !=0){ + icalcluster_free(impl->properties); + } + + if (impl->booked !=0){ + icalstore_free(impl->booked); + } + + if (impl->incoming !=0){ + icalstore_free(impl->incoming); + } + + impl->dir = 0; + impl->freebusy = 0; + impl->properties = 0; + impl->booked = 0; + impl->incoming = 0; + + + free(impl); +} + + +int icalcalendar_lock(icalcalendar* calendar) +{ + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + icalerror_check_arg_rz((impl != 0),"impl"); + return 0; +} + +int icalcalendar_unlock(icalcalendar* calendar) +{ + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + icalerror_check_arg_rz((impl != 0),"impl"); + return 0; +} + +int icalcalendar_islocked(icalcalendar* calendar) +{ + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + icalerror_check_arg_rz((impl != 0),"impl"); + return 0; +} + +int icalcalendar_ownlock(icalcalendar* calendar) +{ + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + icalerror_check_arg_rz((impl != 0),"impl"); + return 0; +} + +icalstore* icalcalendar_get_booked(icalcalendar* calendar) +{ + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + char dir[PATH_MAX]; + + icalerror_check_arg_rz((impl != 0),"impl"); + + dir[0] = '\0'; + strcpy(dir,impl->dir); + strcat(dir,"/"); + strcat(dir,BOOKED_DIR); + + if (impl->booked == 0){ + icalerror_clear_errno(); + impl->booked = icalstore_new(dir); + assert(icalerrno == ICAL_NO_ERROR); + } + + return impl->booked; + +} + +icalcluster* icalcalendar_get_incoming(icalcalendar* calendar) +{ + char path[PATH_MAX]; + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + icalerror_check_arg_rz((impl != 0),"impl"); + + path[0] = '\0'; + strcpy(path,impl->dir); + strcat(path,"/"); + strcat(path,INCOMING_FILE); + + if (impl->properties == 0){ + impl->properties = icalcluster_new(path); + } + + return impl->properties; +} + +icalcluster* icalcalendar_get_properties(icalcalendar* calendar) +{ + char path[PATH_MAX]; + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + icalerror_check_arg_rz((impl != 0),"impl"); + + path[0] = '\0'; + strcpy(path,impl->dir); + strcat(path,"/"); + strcat(path,PROP_FILE); + + if (impl->properties == 0){ + impl->properties = icalcluster_new(path); + } + + return impl->properties; +} + +icalcluster* icalcalendar_get_freebusy(icalcalendar* calendar) +{ + char path[PATH_MAX]; + struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar; + icalerror_check_arg_rz((impl != 0),"impl"); + + path[0] = '\0'; + strcpy(path,impl->dir); + strcat(path,"/"); + strcat(path,FBLIST_FILE); + + + if (impl->freebusy == 0){ + impl->freebusy = icalcluster_new(path); + } + + return impl->freebusy; +} + + + + diff --git a/libical/src/libicalss/icalcalendar.h b/libical/src/libicalss/icalcalendar.h new file mode 100644 index 0000000000..90e7b33c22 --- /dev/null +++ b/libical/src/libicalss/icalcalendar.h @@ -0,0 +1,68 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcalendar.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (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 Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALCALENDAR_H +#define ICALCALENDAR_H + +#include "ical.h" +#include "icalstore.h" +#include "icalcluster.h" + +/* icalcalendar + * Routines for storing calendar data in a file system. The calendar + * has two icalstores, one for incoming components and one for booked + * components. It also has interfaces to access the free/busy list + * and a list of calendar properties */ + +typedef void icalcalendar; + +icalcalendar* icalcalendar_new(char* dir); + +void icalcalendar_free(icalcalendar* calendar); + +int icalcalendar_lock(icalcalendar* calendar); + +int icalcalendar_unlock(icalcalendar* calendar); + +int icalcalendar_islocked(icalcalendar* calendar); + +int icalcalendar_ownlock(icalcalendar* calendar); + +icalstore* icalcalendar_get_booked(icalcalendar* calendar); + +icalcluster* icalcalendar_get_incoming(icalcalendar* calendar); + +icalcluster* icalcalendar_get_properties(icalcalendar* calendar); + +icalcluster* icalcalendar_get_freebusy(icalcalendar* calendar); + + +#endif /* !ICALCALENDAR_H */ + + + diff --git a/libical/src/libicalss/icalcluster.c b/libical/src/libicalss/icalcluster.c new file mode 100644 index 0000000000..00e7ef0365 --- /dev/null +++ b/libical/src/libicalss/icalcluster.c @@ -0,0 +1,399 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalcluster.c + CREATOR: eric 23 December 1999 + + $Id$ + $Locker$ + + (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 Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +#include "icalcluster.h" +#include <errno.h> +#include <limits.h> /* For PATH_MAX */ +#include <sys/stat.h> /* for stat */ +#include <unistd.h> /* for stat, getpid */ +#include <stdlib.h> +#include <string.h> + +struct icalcluster_impl { + char *path; + icalcomponent* cluster; + int changed; +}; + +icalcluster* icalcluster_new_impl() +{ + struct icalcluster_impl* comp; + + if ( ( comp = (struct icalcluster_impl*) + malloc(sizeof(struct icalcluster_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + errno = ENOMEM; + return 0; + } + + return comp; +} + +icalerrorenum icalcluster_create_cluster(char *path) +{ + + FILE* f; + int r; + icalcomponent *c; + struct icaltimetype tt; + + icalerror_clear_errno(); + + f = fopen(path,"w"); + + if (f == 0){ + fclose(f); + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + /* Create the root component in the cluster. This component holds + all of the other components and stores a count of + components. */ + + memset(&tt,0,sizeof(struct icaltimetype)); + + c = icalcomponent_vanew( + ICAL_VCALENDAR_COMPONENT, + icalproperty_new_xlicclustercount(0), + icalproperty_new_dtstart(tt), /* dtstart of earliest comp */ + icalproperty_new_dtend(tt), /* dtend of latest comp, excl. recuring */ + 0 + ); + + if (c == 0){ + fclose(f); + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return ICAL_INTERNAL_ERROR; + } + + + /* Write the base component to the file */ + r = fputs(icalcomponent_as_ical_string(c),f); + + fclose(f); + + icalcomponent_free(c); + + if (r == EOF){ + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + return ICAL_NO_ERROR; +} + +FILE* parser_file; /*HACK. Not Thread Safe */ +char* read_from_file(char *s, size_t size) +{ + char *c = fgets(s,size, parser_file); + return c; +} + +icalerrorenum icalcluster_load(icalcluster* cluster, char* path) +{ + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + icalerrorenum error; + errno = 0; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + icalerror_check_arg_rz((path!=0),"path"); + + if(impl->path != 0 && strcmp(impl->path,path) == 0){ + /* Already have the right cluster, so return */ + return ICAL_NO_ERROR; + } + + error = icalcluster_commit(cluster); + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return error; + } + + free(impl->path); + + impl->path= (char*)strdup(path); + + parser_file = fopen(impl->path,"r"); + + /* HACK. Yeah, the following code is horrible....*/ + if (parser_file ==0 || errno != 0){ + + /* Try to create the cluster */ + error = icalcluster_create_cluster(path); + + if (error == ICAL_NO_ERROR){ + /* Try to open the parser again. */ + errno = 0; + parser_file = fopen(impl->path,"r"); + + if (parser_file ==0 || errno != 0){ + impl->cluster = 0; + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + } else { + impl->cluster = 0; + icalerror_set_errno(error); /* Redundant, actually */ + return error; + } + } + + impl->cluster = icalparser_parse(read_from_file); + + fclose(parser_file); + + if (impl->cluster == 0){ + icalerror_set_errno(ICAL_PARSE_ERROR); + return ICAL_PARSE_ERROR; + } + + return ICAL_NO_ERROR; +} + + +icalcluster* icalcluster_new(char* path) +{ + struct icalcluster_impl *impl = icalcluster_new_impl(); + struct stat sbuf; + int createclusterfile = 0; + icalerrorenum error; + + icalerror_clear_errno(); + icalerror_check_arg_rz( (path!=0), "path"); + + if (impl == 0){ + return 0; + } + + /*impl->path = strdup(path); icalcluster_load does this */ + impl->changed = 0; + impl->cluster = 0; + impl->path = 0; + + /* Check if the path already exists and if it is a regular file*/ + if (stat(path,&sbuf) != 0){ + + /* A file by the given name does not exist, or there was + another error */ + + if (errno == ENOENT) { + /* It was because the file does not exist */ + createclusterfile = 1; + } else { + /* It was because of another error */ + icalerror_set_errno(ICAL_FILE_ERROR); + return 0; + } + } else { + /* A file by the given name exists, but is it a regular file */ + + if (!S_ISREG(sbuf.st_mode)){ + /* Nope, not a directory */ + icalerror_set_errno(ICAL_FILE_ERROR); + return 0; + } else { + /* Lets assume that it is a file of the right type */ + createclusterfile = 0; + } + } + + /* if cluster does not already exist, create it */ + + if (createclusterfile == 1) { + error = icalcluster_create_cluster(path); + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return 0; + } + } + + error = icalcluster_load(impl,path); + + if (error != ICAL_NO_ERROR){ + return 0; + } + + return impl; +} + +void icalcluster_free(icalcluster* cluster) +{ + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_rv((cluster!=0),"cluster"); + + if (impl->cluster != 0){ + icalcluster_commit(cluster); + icalcomponent_free(impl->cluster); + impl->cluster=0; + } + + if(impl->path != 0){ + free(impl->path); + impl->path = 0; + } + + free(impl); +} + +icalerrorenum icalcluster_commit(icalcluster* cluster) +{ + int ws; /* Size in char of file written to disk */ + FILE *f; + + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR); + + if (impl->changed != 0 ){ + /* write the cluster to disk */ + + /* Construct a filename and write out the file */ + + if ( (f = fopen(impl->path,"w")) != 0){ + + char* str = icalcomponent_as_ical_string(impl->cluster); + + ws = fwrite(str,sizeof(char),strlen(str),f); + + if ( ws < strlen(str)){ + fclose(f); + return ICAL_FILE_ERROR; + } + + fclose(f); + impl->changed = 0; + return ICAL_NO_ERROR; + } else { + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + } + + return ICAL_NO_ERROR; +} + +void icalcluster_mark(icalcluster* cluster){ + + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_rv((impl!=0),"cluster"); + + impl->changed = 1; + +} + +icalcomponent* icalcluster_get_component(icalcluster* cluster){ + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR); + + return impl->cluster; +} + + +/* manipulate the components in the cluster */ + +icalerrorenum icalcluster_add_component(icalcluster *cluster, + icalcomponent* child) +{ + struct icalcluster_impl* impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_rv((cluster!=0),"cluster"); + icalerror_check_arg_rv((child!=0),"child"); + + icalcomponent_add_component(impl->cluster,child); + + icalcluster_mark(cluster); + + return ICAL_NO_ERROR; + +} + +icalerrorenum icalcluster_remove_component(icalcluster *cluster, + icalcomponent* child) +{ + struct icalcluster_impl* impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_rv((cluster!=0),"cluster"); + icalerror_check_arg_rv((child!=0),"child"); + + icalcomponent_remove_component(impl->cluster,child); + + icalcluster_mark(cluster); + + return ICAL_NO_ERROR; +} + +int icalcluster_count_components(icalcluster *cluster, + icalcomponent_kind kind) +{ + struct icalcluster_impl* impl = (struct icalcluster_impl*)cluster; + + if(cluster == 0){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return -1; + } + + return icalcomponent_count_components(impl->cluster,kind); +} + +/* Iterate through components */ +icalcomponent* icalcluster_get_current_component (icalcluster* cluster) +{ + struct icalcluster_impl* impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return icalcomponent_get_current_component(impl->cluster); +} + +icalcomponent* icalcluster_get_first_component(icalcluster* cluster, + icalcomponent_kind kind) +{ + struct icalcluster_impl* impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return icalcomponent_get_first_component(impl->cluster,kind); +} + +icalcomponent* icalcluster_get_next_component(icalcluster* cluster, + icalcomponent_kind kind) +{ + struct icalcluster_impl* impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return icalcomponent_get_next_component(impl->cluster,kind); +} + diff --git a/libical/src/libicalss/icalcluster.h b/libical/src/libicalss/icalcluster.h new file mode 100644 index 0000000000..05c3a4b144 --- /dev/null +++ b/libical/src/libicalss/icalcluster.h @@ -0,0 +1,75 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcluster.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (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 Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALCLUSTER_H +#define ICALCLUSTER_H + +#include "ical.h" + +typedef void icalcluster; + + +icalcluster* icalcluster_new(char* path); +void icalcluster_free(icalcluster* cluster); + + +/* Load a new file into the cluster */ +icalerrorenum icalcluster_load(icalcluster* cluster, char* path); + +/* Return a reference to the internal component. */ +icalcomponent* icalcluster_get_component(icalcluster* cluster); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed*/ +void icalcluster_mark(icalcluster* cluster); + +/* Write the cluster data back to disk */ +icalerrorenum icalcluster_commit(icalcluster* cluster); + +/* manipulate the components in the cluster */ +icalerrorenum icalcluster_add_component(icalcomponent* parent, + icalcomponent* child); + +icalerrorenum icalcluster_remove_component(icalcomponent* parent, + icalcomponent* child); + +int icalcluster_count_components(icalcomponent* component, + icalcomponent_kind kind); + +/* Iterate through components */ +icalcomponent* icalcluster_get_current_component (icalcomponent* component); + +icalcomponent* icalcluster_get_first_component(icalcomponent* component, + icalcomponent_kind kind); +icalcomponent* icalcluster_get_next_component(icalcomponent* component, + icalcomponent_kind kind); + +#endif /* !ICALCLUSTER_H */ + + + diff --git a/libical/src/libicalss/icalcomponent.h b/libical/src/libicalss/icalcomponent.h new file mode 100644 index 0000000000..9e0e9f5a9f --- /dev/null +++ b/libical/src/libicalss/icalcomponent.h @@ -0,0 +1,115 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalcomponent.h + CREATOR: eric 20 March 1999 + + + (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 + The original code is icalcomponent.h + +======================================================================*/ + +#ifndef ICALCOMPONENT_H +#define ICALCOMPONENT_H + +#include "icalproperty.h" +#include "icalvalue.h" +#include "icalenums.h" /* defines icalcomponent_kind */ + +typedef void icalcomponent; + +icalcomponent* icalcomponent_new(icalcomponent_kind kind); +icalcomponent* icalcomponent_new_clone(icalcomponent* component); +icalcomponent* icalcomponent_new_from_string(char* str); +icalcomponent* icalcomponent_vanew(icalcomponent_kind kind, ...); +void icalcomponent_free(icalcomponent* component); + +char* icalcomponent_as_ical_string(icalcomponent* component); + +int icalcomponent_is_valid(icalcomponent* component); + +icalcomponent_kind icalcomponent_isa(icalcomponent* component); + +int icalcomponent_isa_component (void* component); + +/* + * Working with properties + */ + +void icalcomponent_add_property(icalcomponent* component, + icalproperty* property); + +void icalcomponent_remove_property(icalcomponent* component, + icalproperty* property); + +int icalcomponent_count_properties(icalcomponent* component, + icalproperty_kind kind); + +/* Iterate through the properties */ +icalproperty* icalcomponent_get_current_property(icalcomponent* component); + +icalproperty* icalcomponent_get_first_property(icalcomponent* component, + icalproperty_kind kind); +icalproperty* icalcomponent_get_next_property(icalcomponent* component, + icalproperty_kind kind); + +/* Return a null-terminated array of icalproperties*/ + +icalproperty** icalcomponent_get_properties(icalcomponent* component, + icalproperty_kind kind); + + +/* + * Working with components + */ + + +void icalcomponent_add_component(icalcomponent* parent, + icalcomponent* child); + +void icalcomponent_remove_component(icalcomponent* parent, + icalcomponent* child); + +int icalcomponent_count_components(icalcomponent* component, + icalcomponent_kind kind); + +/* Iterate through components */ +icalcomponent* icalcomponent_get_current_component (icalcomponent* component); + +icalcomponent* icalcomponent_get_first_component(icalcomponent* component, + icalcomponent_kind kind); +icalcomponent* icalcomponent_get_next_component(icalcomponent* component, + icalcomponent_kind kind); + +/* Return a null-terminated array of icalproperties*/ +icalproperty** icalcomponent_get_component(icalcomponent* component, + icalproperty_kind kind); + +/* Working with embedded error properties */ + +int icalcomponent_count_errors(icalcomponent* component); +void icalcomponent_strip_errors(icalcomponent* component); + + +/* Internal operations. You don't see these... */ +icalcomponent* icalcomponent_get_parent(icalcomponent* component); +void icalcomponent_set_parent(icalcomponent* component, + icalcomponent* parent); + +#endif /* !ICALCOMPONENT_H */ + + + diff --git a/libical/src/libicalss/icalstore.c b/libical/src/libicalss/icalstore.c new file mode 100644 index 0000000000..014c9ed19b --- /dev/null +++ b/libical/src/libicalss/icalstore.c @@ -0,0 +1,815 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalstore.c + CREATOR: eric 28 November 1999 + + $Id$ + $Locker$ + + (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 Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +/* + + icalstore manages a database of ical components and offers + interfaces for reading, writting and searching for components. + + icalstore groups components in to clusters based on their DTSTART + time -- all components that start in the same month are grouped + together in a single file. All files in a sotre are kept in a single + directory. ( If a component does not have DTSTART, the store uses + DTSTAMP or CREATE ) + + The primary interfaces are icalstore_first and icalstore_next. These + routine iterate through all of the components in the store, subject + to the current gauge. A gauge is an icalcomponent that is tested + against other componets for a match. If a gauge has been set with + icalstore_select, icalstore_first and icalstore_next will only + return componentes that match the gauge. + + The Store generated UIDs for all objects that are stored if they do + not already have a UID. The UID is the name of the cluster (month & + year as MMYYYY) plus a unique serial number. The serial number is + stored as a property of the cluster. + +*/ + +#include "ical.h" +#include "icalstore.h" +#include "pvl.h" +#include "icalerror.h" +#include "icalparser.h" +#include "icalcluster.h" + +#include "filelock.h" + +#include <limits.h> +#include <dirent.h> /* for opendir() */ +#include <errno.h> +#include <sys/types.h> /* for opendir() */ +#include <sys/stat.h> /* for stat */ +#include <unistd.h> /* for stat, getpid */ +#include <time.h> /* for clock() */ +#include <stdlib.h> /* for rand(), srand() */ +#include <sys/utsname.h> /* for uname */ +#include <string.h> /* for strdup */ + + +struct icalstore_impl +{ + char* dir; + icalcomponent* gauge; + icalcluster* cluster; + int first_component; + pvl_list directory; + pvl_elem directory_iterator; +}; + +struct icalstore_impl* icalstore_new_impl() +{ + struct icalstore_impl* comp; + + if ( ( comp = (struct icalstore_impl*) + malloc(sizeof(struct icalstore_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + return comp; +} + + + +void icalstore_lock_dir(char* dir) +{ +} + + +void icalstore_unlock_dir(char* dir) +{ +} + +/* Load the contents of the store directory into the store's internal directory list*/ +icalerrorenum icalstore_read_directory(struct icalstore_impl* impl) +{ + struct dirent *de; + DIR* dp; + char *str; + + dp = opendir(impl->dir); + + if ( dp == 0) { + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + /* clear contents of directory list */ + while((str = pvl_pop(impl->directory))){ + free(str); + } + + /* load all of the cluster names in the directory list */ + for(de = readdir(dp); + de != 0; + de = readdir(dp)){ + + /* Remove known directory names '.' and '..'*/ + if (strcmp(de->d_name,".") == 0 || + strcmp(de->d_name,"..") == 0 ){ + continue; + } + + pvl_push(impl->directory, (void*)strdup(de->d_name)); + } + + closedir(dp); + + return ICAL_NO_ERROR; +} + +icalstore* icalstore_new(char* dir) +{ + struct icalstore_impl *impl = icalstore_new_impl(); + struct stat sbuf; + + if (impl == 0){ + return 0; + } + + icalerror_check_arg_rz( (dir!=0), "dir"); + + if (stat(dir,&sbuf) != 0){ + icalerror_set_errno(ICAL_FILE_ERROR); + return 0; + } + + /* dir is not the name of a direectory*/ + if (!S_ISDIR(sbuf.st_mode)){ + icalerror_set_errno(ICAL_USAGE_ERROR); + return 0; + } + + icalstore_lock_dir(dir); + + impl = icalstore_new_impl(); + + if (impl ==0){ + icalerror_set_errno(ICAL_ALLOCATION_ERROR); + return 0; + } + + impl->directory = pvl_newlist(); + impl->directory_iterator = 0; + impl->dir = (char*)strdup(dir); + impl->gauge = 0; + impl->first_component = 0; + impl->cluster = 0; + + icalstore_read_directory(impl); + + return (icalstore*) impl; +} + +void icalstore_free(icalstore* s) +{ + struct icalstore_impl *impl = (struct icalstore_impl*)s; + char* str; + + icalstore_unlock_dir(impl->dir); + + if(impl->dir !=0){ + free(impl->dir); + } + + if(impl->gauge !=0){ + icalcomponent_free(impl->gauge); + } + + if(impl->cluster !=0){ + icalcluster_free(impl->cluster); + } + + while( (str=pvl_pop(impl->directory)) != 0){ + free(str); + } + + pvl_free(impl->directory); + + impl->directory = 0; + impl->directory_iterator = 0; + impl->dir = 0; + impl->gauge = 0; + impl->first_component = 0; + + free(impl); + +} + +/* icalstore_next_uid_number updates a serial number in the Store + directory in a file called SEQUENCE */ + +int icalstore_next_uid_number(icalstore* store) +{ + struct icalstore_impl *impl = (struct icalstore_impl*)store; + char sequence = 0; + char temp[128]; + char filename[PATH_MAX]; + char *r; + FILE *f; + struct stat sbuf; + + icalerror_check_arg_rz( (store!=0), "store"); + + sprintf(filename,"%s/%s",impl->dir,"SEQUENCE"); + + /* Create the file if it does not exist.*/ + if (stat(filename,&sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ + + f = fopen(filename,"w"); + if (f != 0){ + fprintf(f,"0"); + fclose(f); + } else { + icalerror_warn("Can't create SEQUENCE file in icalstore_next_uid_number"); + return 0; + } + + } + + if ( (f = fopen(filename,"r+")) != 0){ + + rewind(f); + r = fgets(temp,128,f); + + if (r == 0){ + sequence = 1; + } else { + sequence = atoi(temp)+1; + } + + rewind(f); + + fprintf(f,"%d",sequence); + + fclose(f); + + return sequence; + + } else { + icalerror_warn("Can't create SEQUENCE file in icalstore_next_uid_number"); + return 0; + } + +} + +icalerrorenum icalstore_next_cluster(icalstore* store) +{ + struct icalstore_impl *impl = (struct icalstore_impl*)store; + char path[PATH_MAX]; + + if (impl->directory_iterator == 0){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return ICAL_INTERNAL_ERROR; + } + impl->directory_iterator = pvl_next(impl->directory_iterator); + + if (impl->directory_iterator == 0){ + /* There are no more clusters */ + impl->cluster = 0; + return ICAL_NO_ERROR; + } + + + sprintf(path,"%s/%s",impl->dir,(char*)pvl_data(impl->directory_iterator)); + + return icalcluster_load(impl->cluster,path); +} + +void icalstore_add_uid(icalstore* store, icalstore* comp) +{ + char uidstring[PATH_MAX]; + icalproperty *uid; + struct utsname unamebuf; + + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (comp!=0), "comp"); + + uid = icalcomponent_get_first_property(comp,ICAL_UID_PROPERTY); + + if (uid == 0) { + + uname(&unamebuf); + + sprintf(uidstring,"%d-%s",getpid(),unamebuf.nodename); + + uid = icalproperty_new_uid(uidstring); + icalcomponent_add_property(comp,uid); + } else { + + strcpy(uidstring,icalproperty_get_uid(uid)); + } +} + +icalerrorenum icalstore_add_component(icalstore* store, icalstore* comp) +{ + struct icalstore_impl *impl; + char clustername[PATH_MAX]; + icalproperty *dt, *count, *lm; + icalvalue *v; + struct icaltimetype tm; + icalerrorenum error = ICAL_NO_ERROR; + + impl = (struct icalstore_impl*)store; + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (comp!=0), "comp"); + + errno = 0; + + icalstore_add_uid(store,comp); + + /* Determine which cluster this object belongs in */ + + dt = icalcomponent_get_first_property(comp,ICAL_DTSTART_PROPERTY); + + if (dt == 0){ + dt = icalcomponent_get_first_property(comp,ICAL_DTSTAMP_PROPERTY); + } + + if (dt == 0){ + dt = icalcomponent_get_first_property(comp,ICAL_CREATED_PROPERTY); + } + + if (dt == 0){ + icalerror_warn("The component does not have a DTSTART, DTSTAMP or a CREATED property, so it cannot be added to the store"); + icalerror_set_errno(ICAL_BADARG_ERROR); + return ICAL_BADARG_ERROR; + } + + v = icalproperty_get_value(dt); + + tm = icalvalue_get_datetime(v); + + sprintf(clustername,"%s/%04d%02d",impl->dir,tm.year,tm.month); + + /* Load the cluster and insert the object */ + + if (impl->cluster == 0){ + impl->cluster = icalcluster_new(clustername); + + if (impl->cluster == 0){ + error = icalerrno; + } + } else { + error = icalcluster_load(impl->cluster, + clustername); + + } + + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return error; + } + + /* Update or add the LAST-MODIFIED property */ + + lm = icalcomponent_get_first_property(comp, + ICAL_LASTMODIFIED_PROPERTY); + + if (lm == 0){ + lm = icalproperty_new_lastmodified(icaltimetype_from_timet( time(0),1)); + icalcomponent_add_property(comp,lm); + } else { + icalproperty_set_lastmodified(comp,icaltimetype_from_timet( time(0),1)); + } + + + /* Add the component to the cluster */ + + icalcluster_add_component(impl->cluster,comp); + + + /* Increment the clusters count value */ + count = icalcomponent_get_first_property( + icalcluster_get_component(impl->cluster), + ICAL_XLICCLUSTERCOUNT_PROPERTY); + + if (count == 0){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return ICAL_INTERNAL_ERROR; + } + + icalproperty_set_xlicclustercount(count, + icalproperty_get_xlicclustercount(count)+1); + + + icalcluster_mark(impl->cluster); + + return ICAL_NO_ERROR; +} + +/* Remove a component in the current cluster */ +icalerrorenum icalstore_remove_component(icalstore* store, icalstore* comp) +{ + struct icalstore_impl *impl = (struct icalstore_impl*)store; + icalproperty *count; + + icalerror_check_arg_re((store!=0),"store",ICAL_BADARG_ERROR); + icalerror_check_arg_re((comp!=0),"comp",ICAL_BADARG_ERROR); + icalerror_check_arg_re((impl->cluster!=0),"Cluster pointer",ICAL_USAGE_ERROR); + +/* HACK The following code should be used to ensure that the component +the caller is trying to remove is actually in the cluster, but it +resets the internal iterators, which immediately ends any loops over +the cluster the caller may have in progress + + for(c = icalcluster_get_first_component( + impl->cluster, + ICAL_ANY_COMPONENT); + c != 0; + c = icalcluster_get_next_component( + impl->cluster, + ICAL_ANY_COMPONENT)){ + + if (c == comp){ + found = 1; + } + + } + + if (found != 1){ + icalerror_warn("icalstore_remove_component: component is not part of current cluster"); + icalerror_set_errno(ICAL_USAGE_ERROR); + return ICAL_USAGE_ERROR; + } + +*/ + + icalcluster_remove_component(impl->cluster, + comp); + + icalcluster_mark(impl->cluster); + + /* Decrement the clusters count value */ + count = icalcomponent_get_first_property( + icalcluster_get_component(impl->cluster), + ICAL_XLICCLUSTERCOUNT_PROPERTY); + + if (count == 0){ + icalerror_set_errno(ICAL_INTERNAL_ERROR); + return ICAL_INTERNAL_ERROR; + } + + icalproperty_set_xlicclustercount(count, + icalproperty_get_xlicclustercount(count)-1); + + return ICAL_NO_ERROR; +} + +/* Convert a VQUERY component into a gauge */ +icalcomponent* icalstore_make_gauge(icalcomponent* query); + +/* icalstore_test compares a component against a gauge, and returns + true if the component passes the test + + The gauge is a VCALENDAR component that specifies how to test the + target components. The guage holds a collection of VEVENT, VTODO or + VJOURNAL sub-components. Each of the sub-components has a + collection of properties that are compared to corresponding + properties in the target component, according to the + X-LIC-COMPARETYPE parameters to the gauge's properties. + + When a gauge has several sub-components, the results of testing the + target against each of them is ORed together - the target + component will pass if it matches any of the sub-components in the + gauge. However, the results of matching the proeprties in a + sub-component are ANDed -- the target must match every property in + a gauge sub-component to match the sub-component. + + Here is an example: + + BEGIN:VCOMPONENT + BEGIN:VEVENT + DTSTART;X-LIC-COMPARETYPE=LESS:19981025T020000 + ORGANIZER;X-LIC-COMPARETYPE=EQUAL:mrbig@host.com + END:VEVENT + BEGIN:VEVENT + LOCATION;X-LIC-COMPARETYPE=EQUAL:McNary's Pub + END:VEVENT + END:VCALENDAR + + This gauge has two sub-components; one which will match a VEVENT + based on start time, and organizer, and another that matches based + on LOCATION. A target component will pass the test if it matched + either of the gauge. + + */ + +int icalstore_test(icalcomponent* comp, icalcomponent* gauge) +{ + int pass = 0,localpass = 0; + icalcomponent *c; + icalproperty *p; + icalcomponent *child; + + icalerror_check_arg_rz( (comp!=0), "comp"); + icalerror_check_arg_rz( (gauge!=0), "gauge"); + + for(c = icalcomponent_get_first_component(gauge,ICAL_ANY_COMPONENT); + c != 0; + c = icalcomponent_get_next_component(gauge,ICAL_ANY_COMPONENT)){ + + + /* Test properties. For each property in the gauge, search through + the component for a similar property. If one is found, compare + the two properties value with the comparison specified in the + gauge with the X-LIC-COMPARETYPE parameter */ + + for(p = icalcomponent_get_first_property(c,ICAL_ANY_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(c,ICAL_ANY_PROPERTY)){ + + icalproperty* targetprop; + icalparameter* compareparam; + icalparameter_xliccomparetype compare; + int rel; /* The realtionship between the gauge and target values.*/ + + /* Extract the comparison type from the gauge. If there is no + comparison type, assume that it is "EQUAL" */ + + compareparam = icalproperty_get_first_parameter( + p, + ICAL_XLICCOMPARETYPE_PARAMETER); + + if (compareparam!=0){ + compare = icalparameter_get_xliccomparetype(compareparam); + } else { + compare = ICAL_XLICCOMPARETYPE_EQUAL; + } + + /* Find a property in the component that has the same type as + the gauge property */ + + targetprop = icalcomponent_get_first_property(comp, + icalproperty_isa(p)); + + + if(targetprop == 0){ + continue; + } + + /* Compare the values of the gauge property and the target + property */ + + rel = icalvalue_compare(icalproperty_get_value(p), + icalproperty_get_value(targetprop)); + + /* Now see if the comparison is equavalent to the comparison + specified in the gauge */ + + if (rel == compare){ + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_LESSEQUAL && + ( rel == ICAL_XLICCOMPARETYPE_LESS || + rel == ICAL_XLICCOMPARETYPE_EQUAL)) { + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_GREATEREQUAL && + ( rel == ICAL_XLICCOMPARETYPE_GREATER || + rel == ICAL_XLICCOMPARETYPE_EQUAL)) { + localpass++; + } else if (compare == ICAL_XLICCOMPARETYPE_NOTEQUAL && + ( rel == ICAL_XLICCOMPARETYPE_GREATER || + rel == ICAL_XLICCOMPARETYPE_LESS)) { + pass++; + } else { + localpass = 0; + } + + pass += localpass; + } + + + /* test subcomponents. Look for a child component that has a + counterpart in the gauge. If one is found, recursively call + icalstore_test */ + + for(child = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + child != 0; + child = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){ + + pass += icalstore_test(child,gauge); + + } + } + + return pass>0; + +} + +icalcomponent* icalstore_query(icalstore* store, icalstore* query); + + +icalcomponent* icalstore_fetch(icalstore* store, char* uid) +{ + icalcomponent *gauge; + icalcomponent *old_gauge; + icalcomponent *c; + struct icalstore_impl *impl = (struct icalstore_impl*)store; + + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (uid!=0), "uid"); + + gauge = + icalcomponent_vanew( + ICAL_VCALENDAR_COMPONENT, + icalcomponent_vanew( + ICAL_VEVENT_COMPONENT, + icalproperty_vanew_uid( + uid, + icalparameter_new_xliccomparetype( + ICAL_XLICCOMPARETYPE_EQUAL), + 0), + 0), + 0); + + old_gauge = impl->gauge; + impl->gauge = gauge; + + c= icalstore_get_first_component(store); + + impl->gauge = old_gauge; + + icalcomponent_free(gauge); + + return c; +} + + +int icalstore_has_uid(icalstore* store, char* uid) +{ + icalcomponent *c; + + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (uid!=0), "uid"); + + /* HACK. This is a temporary implementation. _has_uid should use a + database, and _fetch should use _has_uid, not the other way + around */ + c = icalstore_fetch(store,uid); + + return c!=0; + +} + + +icalerrorenum icalstore_select(icalstore* store, icalcomponent* gauge) +{ + struct icalstore_impl *impl = (struct icalstore_impl*)store; + + icalerror_check_arg_re( (store!=0), "store",ICAL_BADARG_ERROR); + icalerror_check_arg_re( (gauge!=0), "gauge",ICAL_BADARG_ERROR); + + if (!icalcomponent_is_valid(gauge)){ + return ICAL_BADARG_ERROR; + } + + impl->gauge = gauge; + + return ICAL_NO_ERROR; +} + + + +icalcomponent* icalstore_get_first_component(icalstore* store) +{ + struct icalstore_impl *impl = (struct icalstore_impl*)store; + icalerrorenum error; + char path[PATH_MAX]; + + error = icalstore_read_directory(impl); + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return 0; + } + + impl->directory_iterator = pvl_head(impl->directory); + + if (impl->directory_iterator == 0){ + icalerror_set_errno(error); + return 0; + } + + sprintf(path,"%s/%s",impl->dir,(char*)pvl_data(impl->directory_iterator)); + + if (impl->cluster == 0){ + impl->cluster = icalcluster_new(path); + + if (impl->cluster == 0){ + error = icalerrno; + } + } else { + error = icalcluster_load(impl->cluster,path); + + } + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return 0; + } + + impl->first_component = 1; + + return icalstore_get_next_component(store); +} + +icalcomponent* icalstore_get_next_component(icalstore* store) +{ + struct icalstore_impl *impl; + icalcomponent *c; + icalerrorenum error; + + icalerror_check_arg_rz( (store!=0), "store"); + + impl = (struct icalstore_impl*)store; + + if(impl->cluster == 0){ + + icalerror_warn("icalstore_get_next_component called with a NULL cluster (Caller must call icalstore_get_first_component first"); + icalerror_set_errno(ICAL_USAGE_ERROR); + return 0; + + } + + /* Set the component iterator for the following for loop */ + if (impl->first_component == 1){ + icalcluster_get_first_component( + impl->cluster, + ICAL_ANY_COMPONENT); + impl->first_component = 0; + } else { + icalcluster_get_next_component( + impl->cluster, + ICAL_ANY_COMPONENT); + } + + + while(1){ + /* Iterate through all of the objects in the cluster*/ + for( c = icalcluster_get_current_component( + impl->cluster); + c != 0; + c = icalcluster_get_next_component( + impl->cluster, + ICAL_ANY_COMPONENT)){ + + /* If there is a gauge defined and the component does not + pass the gauge, skip the rest of the loop */ + if (impl->gauge != 0 && icalstore_test(c,impl->gauge) == 0){ + continue; + } + + /* Either there is no gauge, or the component passed the + gauge, so return it*/ + + return c; + } + + /* Fell through the loop, so the component we want is not + in this cluster. Load a new cluster and try again.*/ + + error = icalstore_next_cluster(store); + + if(impl->cluster == 0 || error != ICAL_NO_ERROR){ + /* No more clusters */ + return 0; + } else { + c = icalcluster_get_first_component( + impl->cluster, + ICAL_ANY_COMPONENT); + } + } +} + + + + + + diff --git a/libical/src/libicalss/icalstore.h b/libical/src/libicalss/icalstore.h new file mode 100644 index 0000000000..13e0a182b5 --- /dev/null +++ b/libical/src/libicalss/icalstore.h @@ -0,0 +1,78 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalstore.h + CREATOR: eric 28 November 1999 + + + $Id$ + $Locker$ + + (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 Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALSTORE_H +#define ICALSTORE_H + +#include "ical.h" +#include "icalerror.h" +typedef void icalstore; + +/* icalstore Routines for storing, fetching, and searching for ical + * objects in a database */ + +icalstore* icalstore_new(char* dir); + +void icalstore_free(icalstore* store); + +/* Add a new component to the store */ +icalerrorenum icalstore_add_component(icalstore* store, icalstore* comp); + +/* Remove a component from the store */ +icalerrorenum icalstore_remove_component(icalstore* store, icalstore* comp); + +/* Restrict the component returned by icalstore_first, _next to those + that pass the gauge */ +icalerrorenum icalstore_select(icalstore* store, icalcomponent* gauge); + +/* Return true if a component passes the gauge */ +int icalstore_test(icalcomponent* comp, icalcomponent* gauge); + +/* Clear the restrictions set by icalstore_select */ +void icalstore_clear(icalstore* store); + +/* Get a single component by uid */ +icalcomponent* icalstore_fetch(icalstore* store, char* uid); + +/* Return true of the store has an object with the given UID */ +int icalstore_has_uid(icalstore* store, char* uid); + +/* Return the first component in the store, or first that passes the gauge.*/ +icalcomponent* icalstore_get_first_component(icalstore* store); + +/* Return the next component in the store, or next that passes the gauge.*/ +icalcomponent* icalstore_get_next_component(icalstore* store); + + +int icalstore_next_uid_number(icalstore* store); + + +#endif /* !ICALSTORE_H */ + + + |