diff options
Diffstat (limited to 'libical/src/libicalss')
-rw-r--r-- | libical/src/libicalss/.cvsignore | 6 | ||||
-rw-r--r-- | libical/src/libicalss/Makefile.am | 23 | ||||
-rw-r--r-- | libical/src/libicalss/icalcalendar.c | 268 | ||||
-rw-r--r-- | libical/src/libicalss/icalcalendar.h | 68 | ||||
-rw-r--r-- | libical/src/libicalss/icalcluster.c | 423 | ||||
-rw-r--r-- | libical/src/libicalss/icalcluster.h | 73 | ||||
-rw-r--r-- | libical/src/libicalss/icalcomponent.h | 115 | ||||
-rw-r--r-- | libical/src/libicalss/icalstore.c | 858 | ||||
-rw-r--r-- | libical/src/libicalss/icalstore.h | 78 |
9 files changed, 1912 insertions, 0 deletions
diff --git a/libical/src/libicalss/.cvsignore b/libical/src/libicalss/.cvsignore new file mode 100644 index 0000000000..732c1577b6 --- /dev/null +++ b/libical/src/libicalss/.cvsignore @@ -0,0 +1,6 @@ +Makefile +.deps +Makefile.in +*.lo +*.la +.libs
\ No newline at end of file diff --git a/libical/src/libicalss/Makefile.am b/libical/src/libicalss/Makefile.am new file mode 100644 index 0000000000..ea37380688 --- /dev/null +++ b/libical/src/libicalss/Makefile.am @@ -0,0 +1,23 @@ + + +#noinst_LTLIBRARIES = libicalss.la +lib_LTLIBRARIES = libicalss.la + +libicalss_la_SOURCES =\ + icalcalendar.c \ + icalcalendar.h \ + icalcluster.c \ + icalcluster.h \ + icalstore.c \ + icalstore.h + +include_HEADERS =\ + icalcalendar.h \ + icalcluster.h \ + icalstore.h + + +INCLUDES = \ + -I $(srcdir)/../libical/ \ + -I ../libical + diff --git a/libical/src/libicalss/icalcalendar.c b/libical/src/libicalss/icalcalendar.c new file mode 100644 index 0000000000..0f2231b1d7 --- /dev/null +++ b/libical/src/libicalss/icalcalendar.c @@ -0,0 +1,268 @@ +/* -*- 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 + + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#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..36bdccc743 --- /dev/null +++ b/libical/src/libicalss/icalcluster.c @@ -0,0 +1,423 @@ +/* -*- 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 + + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#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> +#include <fcntl.h> /* for fcntl */ +#include <unistd.h> /* for fcntl */ + +icalerrorenum icalcluster_create_cluster(char *path); + +struct icalcluster_impl { + char *path; + icalcomponent* cluster; + int changed; + FILE* stream; +}; + +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; +} + +char* read_from_file(char *s, size_t size, void *d) +{ + char *c = fgets(s,size, (FILE*)d); + return c; +} + +icalcluster* icalcluster_new(char* path) +{ + struct icalcluster_impl *impl = icalcluster_new_impl(); + struct stat sbuf; + int createclusterfile = 0; + icalerrorenum error = ICAL_NO_ERROR; + icalparser *parser; + struct icaltimetype tt; + off_t cluster_file_size; + + memset(&tt,0,sizeof(struct icaltimetype)); + + 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; + impl->stream = 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 */ + cluster_file_size = 0; + 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 */ + cluster_file_size = sbuf.st_size; + 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; + } + } + + impl->path = (char*)strdup(path); + + errno = 0; + impl->stream = fopen(impl->path,"r"); + + if (impl->stream ==0 || errno != 0){ + impl->cluster = 0; + icalerror_set_errno(ICAL_FILE_ERROR); /* Redundant, actually */ + return 0; + } + + icalcluster_lock(impl); + + if(cluster_file_size > 0){ + parser = icalparser_new(); + icalparser_set_gen_data(parser,impl->stream); + impl->cluster = icalparser_parse(parser,read_from_file); + icalparser_free(parser); + + if (icalcomponent_isa(impl->cluster) != ICAL_XROOT_COMPONENT){ + /* The parser got a single component, so it did not put it in + an XROOT. */ + icalcomponent *cl = impl->cluster; + impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT); + icalcomponent_add_component(impl->cluster,cl); + } + + } else { + + impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT); + } + + if (impl->cluster == 0){ + icalerror_set_errno(ICAL_PARSE_ERROR); + return 0; + } + + 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; + } + + if(impl->stream != 0){ + icalcluster_unlock(impl); + fclose(impl->stream); + impl->stream = 0; + } + + free(impl); +} + +char* icalcluster_path(icalcluster* cluster) +{ + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return impl->path; +} + + +int icalcluster_lock(icalcluster *cluster) +{ + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + struct flock lock; + int fd; + + icalerror_check_arg_rz((impl->stream!=0),"impl->stream"); + + fd = fileno(impl->stream); + + lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */ + lock.l_start = 0; /* byte offset relative to l_whence */ + lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */ + lock.l_len = 0; /* #bytes (0 means to EOF) */ + + return (fcntl(fd, F_SETLKW, &lock)); +} + +int icalcluster_unlock(icalcluster *cluster) +{ + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + int fd; + struct flock lock; + icalerror_check_arg_rz((impl->stream!=0),"impl->stream"); + + fd = fileno(impl->stream); + + lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */ + lock.l_start = 0; /* byte offset relative to l_whence */ + lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */ + lock.l_len = 0; /* #bytes (0 means to EOF) */ + + return (fcntl(fd, F_UNLCK, &lock)); + +} + +icalerrorenum icalcluster_create_cluster(char *path) +{ + + FILE* f; + int r; + icalcomponent *c; + + icalerror_clear_errno(); + + f = fopen(path,"w"); + + if (f == 0){ + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + + /* This used to write data to the file... */ + + + fclose(f); + + return ICAL_NO_ERROR; +} + +icalerrorenum icalcluster_commit(icalcluster* cluster) +{ + FILE *f; + char tmp[PATH_MAX]; /* HACK Buffer overflow potential */ + char *str; + icalparser *parser; + icalcomponent *c; + + struct icalcluster_impl *impl = (struct icalcluster_impl*)cluster; + + icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR); + + if (impl->changed == 0 ){ + return ICAL_NO_ERROR; + } + +#ifdef ICAL_SAFESAVES + snprintf(tmp,PATH_MAX,"%s-tmp",impl->path); +#else + strcpy(tmp,impl->path); +#endif + + if ( (f = fopen(tmp,"w")) < 0 ){ + icalerror_set_errno(ICAL_FILE_ERROR); + return ICAL_FILE_ERROR; + } + + for(c = icalcomponent_get_first_component(impl->cluster,ICAL_ANY_COMPONENT); + c != 0; + c = icalcomponent_get_next_component(impl->cluster,ICAL_ANY_COMPONENT)){ + + str = icalcomponent_as_ical_string(c); + + if ( fwrite(str,sizeof(char),strlen(str),f) < strlen(str)){ + fclose(f); + return ICAL_FILE_ERROR; + } + } + + fclose(f); + impl->changed = 0; + +#ifdef ICAL_SAFESAVES + rename(tmp,impl->path); /* HACK, should check for error here */ +#endif + + 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..39fe542027 --- /dev/null +++ b/libical/src/libicalss/icalcluster.h @@ -0,0 +1,73 @@ +/* -*- 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); + +char* icalcluster_path(icalcluster* cluster); + +/* 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..382464e476 --- /dev/null +++ b/libical/src/libicalss/icalstore.c @@ -0,0 +1,858 @@ +/* -*- 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include "ical.h" +#include "icalstore.h" +#include "pvl.h" +#include "icalerror.h" +#include "icalparser.h" +#include "icalcluster.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(char* dir) +{ +} + + +void icalstore_unlock(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); + + 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(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(impl->directory !=0 && (str=pvl_pop(impl->directory)) != 0){ + free(str); + } + + if(impl->directory != 0){ + 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)); + + icalcluster_free(impl->cluster); + + impl->cluster = icalcluster_new(path); + + return icalerrno; +} + +void icalstore_add_uid(icalstore* store, icalstore* comp) +{ + char uidstring[PATH_MAX]; + icalproperty *uid; + struct utsname unamebuf; + + icalerror_check_arg_rv( (store!=0), "store"); + icalerror_check_arg_rv( (comp!=0), "comp"); + + uid = icalcomponent_get_first_property(comp,ICAL_UID_PROPERTY); + + if (uid == 0) { + + uname(&unamebuf); + + sprintf(uidstring,"%d-%s",(int)getpid(),unamebuf.nodename); + + uid = icalproperty_new_uid(uidstring); + icalcomponent_add_property(comp,uid); + } else { + + strcpy(uidstring,icalproperty_get_uid(uid)); + } +} + + +/* This assumes that the top level component is a VCALENDAR, and there + is an inner component of type VEVENT, VTODO or VJOURNAL. The inner + component must have a DTSTART property */ + +icalerrorenum icalstore_add_component(icalstore* store, icalstore* comp) +{ + struct icalstore_impl *impl; + char clustername[PATH_MAX]; + icalproperty *dt, *count; + icalvalue *v; + struct icaltimetype tm; + icalerrorenum error = ICAL_NO_ERROR; + icalcomponent *inner; + + 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. This is a HACK */ + + for(inner = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + inner != 0; + inner = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)){ + + dt = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY); + + if (dt != 0){ + break; + } + } + + if (dt == 0){ + icalerror_warn("The component does not have a DTSTART 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); + + snprintf(clustername,PATH_MAX,"%s/%04d%02d",impl->dir,tm.year,tm.month); + + /* Load the cluster and insert the object */ + + if(impl->cluster != 0 && + strcmp(clustername,icalcluster_path(impl->cluster)) != 0 ){ + icalcluster_free(impl->cluster); + impl->cluster = 0; + } + + if (impl->cluster == 0){ + impl->cluster = icalcluster_new(clustername); + + if (impl->cluster == 0){ + error = icalerrno; + } + } + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return error; + } + + /* 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:XROOT + 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 + END:XROOT + + 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 sub-components. + + */ + + +int icalstore_test_recurse(icalcomponent* comp, icalcomponent* gauge) +{ + int pass = 1,localpass = 0; + icalproperty *p; + icalcomponent *child,*subgauge; + icalcomponent_kind gaugekind, compkind; + + icalerror_check_arg_rz( (comp!=0), "comp"); + icalerror_check_arg_rz( (gauge!=0), "gauge"); + + gaugekind = icalcomponent_isa(gauge); + compkind = icalcomponent_isa(comp); + + if( ! (gaugekind == compkind || gaugekind == ICAL_ANY_COMPONENT) ){ + return 0; + } + + /* 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(gauge,ICAL_ANY_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(gauge,ICAL_ANY_PROPERTY)){ + + icalproperty* targetprop; + icalparameter* compareparam; + icalparameter_xliccomparetype compare; + int rel; /* The relationship 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. HACK -- multiples of a single + property type in the gauge will match only the first + instance in the component */ + + targetprop = icalcomponent_get_first_property(comp, + icalproperty_isa(p)); + + if(targetprop != 0){ + + /* 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)) { + localpass++; + } else { + localpass = 0; + } + + pass = pass && (localpass>0); + } + } + + /* Test subcomponents. Look for a child component that has a + counterpart in the gauge. If one is found, recursively call + icalstore_test */ + + for(subgauge = icalcomponent_get_first_component(gauge,ICAL_ANY_COMPONENT); + subgauge != 0; + subgauge = icalcomponent_get_next_component(gauge,ICAL_ANY_COMPONENT)){ + + gaugekind = icalcomponent_isa(subgauge); + + if (gaugekind == ICAL_ANY_COMPONENT){ + child = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); + } else { + child = icalcomponent_get_first_component(comp,gaugekind); + } + + if(child !=0){ + localpass = icalstore_test_recurse(child,subgauge); + pass = pass && localpass; + } else { + pass = 0; + } + } + + return pass; +} + +/* guagecontainer is an XROOT component that holds several gauges. The + results of comparing against these gauges are ORed together in this + routine */ +int icalstore_test(icalcomponent* comp, icalcomponent* gaugecontainer) +{ + int pass = 0; + icalcomponent *gauge; + + icalerror_check_arg_rz( (comp!=0), "comp"); + icalerror_check_arg_rz( (gauge!=0), "gauge"); + + for(gauge = icalcomponent_get_first_component(gaugecontainer,ICAL_ANY_COMPONENT); + gauge != 0; + gauge = icalcomponent_get_next_component(gaugecontainer,ICAL_ANY_COMPONENT)){ + + pass += icalstore_test_recurse(comp, 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 the next cluster we need is different than the current cluster, + delete the current one and get a new one */ + + if(impl->cluster != 0 && strcmp(path,icalcluster_path(impl->cluster)) != 0 ){ + icalcluster_free(impl->cluster); + impl->cluster = 0; + } + + if (impl->cluster == 0){ + impl->cluster = icalcluster_new(path); + + if (impl->cluster == 0){ + error = icalerrno; + } + } + + 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 */ + + + |