diff options
author | JP Rosevear <jpr@src.gnome.org> | 2000-08-25 03:31:03 +0800 |
---|---|---|
committer | JP Rosevear <jpr@src.gnome.org> | 2000-08-25 03:31:03 +0800 |
commit | 8357d7b199e26e4d071b267a314447b22f2ddb3c (patch) | |
tree | f6ed518cd2056dacdc9833750137db05bb7fb7cb /libical/src/libicalss | |
parent | 695baf618d363f760ec81d109c6e6185e510b1e7 (diff) | |
download | gsoc2013-evolution-8357d7b199e26e4d071b267a314447b22f2ddb3c.tar gsoc2013-evolution-8357d7b199e26e4d071b267a314447b22f2ddb3c.tar.gz gsoc2013-evolution-8357d7b199e26e4d071b267a314447b22f2ddb3c.tar.bz2 gsoc2013-evolution-8357d7b199e26e4d071b267a314447b22f2ddb3c.tar.lz gsoc2013-evolution-8357d7b199e26e4d071b267a314447b22f2ddb3c.tar.xz gsoc2013-evolution-8357d7b199e26e4d071b267a314447b22f2ddb3c.tar.zst gsoc2013-evolution-8357d7b199e26e4d071b267a314447b22f2ddb3c.zip |
Initial revision
svn path=/trunk/; revision=5011
Diffstat (limited to 'libical/src/libicalss')
-rw-r--r-- | libical/src/libicalss/icaldirset.c | 718 | ||||
-rw-r--r-- | libical/src/libicalss/icaldirset.h | 84 | ||||
-rw-r--r-- | libical/src/libicalss/icalfileset.c | 427 | ||||
-rw-r--r-- | libical/src/libicalss/icalfileset.h | 90 | ||||
-rw-r--r-- | libical/src/libicalss/icalfilesetimpl.h | 42 | ||||
-rw-r--r-- | libical/src/libicalss/icalgauge.c | 208 | ||||
-rw-r--r-- | libical/src/libicalss/icalgauge.h | 37 | ||||
-rw-r--r-- | libical/src/libicalss/icalset.c | 86 | ||||
-rw-r--r-- | libical/src/libicalss/icalset.h | 100 |
9 files changed, 1792 insertions, 0 deletions
diff --git a/libical/src/libicalss/icaldirset.c b/libical/src/libicalss/icaldirset.c new file mode 100644 index 0000000000..ff5357126c --- /dev/null +++ b/libical/src/libicalss/icaldirset.c @@ -0,0 +1,718 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icaldirset.c + CREATOR: eric 28 November 1999 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +/* + + icaldirset manages a database of ical components and offers + interfaces for reading, writting and searching for components. + + icaldirset 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 icaldirset_first and icaldirset_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 + icaldirset_select, icaldirset_first and icaldirset_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 "icaldirset.h" +#include "pvl.h" +#include "icalerror.h" +#include "icalparser.h" +#include "icaldirset.h" +#include "icalfileset.h" +#include "icalfilesetimpl.h" +#include "icalgauge.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 icaldirset_impl +{ + char* dir; + icalcomponent* gauge; + icaldirset* cluster; + int first_component; + pvl_list directory; + pvl_elem directory_iterator; +}; + +struct icaldirset_impl* icaldirset_new_impl() +{ + struct icaldirset_impl* comp; + + if ( ( comp = (struct icaldirset_impl*) + malloc(sizeof(struct icaldirset_impl))) == 0) { + icalerror_set_errno(ICAL_NEWFAILED_ERROR); + return 0; + } + + return comp; +} + +char* icaldirset_path(icaldirset* cluster) +{ + struct icaldirset_impl *impl = icaldirset_new_impl(); + + return impl->dir; + +} + +void icaldirset_mark(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + icalfileset_mark(impl->cluster); +} + + +icalerrorenum icaldirset_commit(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + return icalfileset_commit(impl->cluster); + +} + +void icaldirset_lock(char* dir) +{ +} + + +void icaldirset_unlock(char* dir) +{ +} + +/* Load the contents of the store directory into the store's internal directory list*/ +icalerrorenum icaldirset_read_directory(struct icaldirset_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; +} + +icaldirset* icaldirset_new(char* dir) +{ + struct icaldirset_impl *impl = icaldirset_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; + } + + icaldirset_lock(dir); + + impl = icaldirset_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; + + icaldirset_read_directory(impl); + + return (icaldirset*) impl; +} + +void icaldirset_free(icaldirset* s) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)s; + char* str; + + icaldirset_unlock(impl->dir); + + if(impl->dir !=0){ + free(impl->dir); + } + + if(impl->gauge !=0){ + icalcomponent_free(impl->gauge); + } + + if(impl->cluster !=0){ + icalfileset_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); + +} + +/* icaldirset_next_uid_number updates a serial number in the Store + directory in a file called SEQUENCE */ + +int icaldirset_next_uid_number(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_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 icaldirset_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 icaldirset_next_uid_number"); + return 0; + } + +} + +icalerrorenum icaldirset_next_cluster(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_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 */ + if(impl->cluster != 0){ + icalfileset_free(impl->cluster); + impl->cluster = 0; + } + return ICAL_NO_ERROR; + } + + sprintf(path,"%s/%s",impl->dir,(char*)pvl_data(impl->directory_iterator)); + + icalfileset_free(impl->cluster); + + impl->cluster = icalfileset_new(path); + + return icalerrno; +} + +void icaldirset_add_uid(icaldirset* store, icaldirset* 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 icaldirset_add_component(icaldirset* store, icaldirset* comp) +{ + struct icaldirset_impl *impl; + char clustername[PATH_MAX]; + icalproperty *dt; + icalvalue *v; + struct icaltimetype tm; + icalerrorenum error = ICAL_NO_ERROR; + icalcomponent *inner; + + impl = (struct icaldirset_impl*)store; + icalerror_check_arg_rz( (store!=0), "store"); + icalerror_check_arg_rz( (comp!=0), "comp"); + + errno = 0; + + icaldirset_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,icalfileset_path(impl->cluster)) != 0 ){ + icalfileset_free(impl->cluster); + impl->cluster = 0; + } + + if (impl->cluster == 0){ + impl->cluster = icalfileset_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 */ + + icalfileset_add_component(impl->cluster,comp); + + icalfileset_mark(impl->cluster); + + return ICAL_NO_ERROR; +} + +/* Remove a component in the current cluster. HACK. This routine is a + "friend" of icalfileset, and breaks its encapsulation. It was + either do it this way, or add several layers of interfaces that had + no other use. */ +icalerrorenum icaldirset_remove_component(icaldirset* store, icaldirset* comp) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + struct icalfileset_impl *filesetimpl = + (struct icalfileset_impl*)impl->cluster; + + icalcomponent *filecomp = filesetimpl->cluster; + + icalcompiter i; + int found = 0; + + 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); + + for(i = icalcomponent_begin_component(filecomp,ICAL_ANY_COMPONENT); + icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){ + + icalcomponent *this = icalcompiter_deref(&i); + + if (this == comp){ + found = 1; + break; + } + } + + if (found != 1){ + icalerror_warn("icaldirset_remove_component: component is not part of current cluster"); + icalerror_set_errno(ICAL_USAGE_ERROR); + return ICAL_USAGE_ERROR; + } + + icalfileset_remove_component(impl->cluster,comp); + + icalfileset_mark(impl->cluster); + + /* If the removal emptied the fileset, get the next fileset */ + if( icalfileset_count_components(impl->cluster,ICAL_ANY_COMPONENT)==0){ + + icalerrorenum error = icaldirset_next_cluster(store); + + if(impl->cluster != 0 && error == ICAL_NO_ERROR){ + icalfileset_get_first_component(impl->cluster,ICAL_ANY_COMPONENT); + } else { + /* HACK. Not strictly correct for impl->cluster==0 */ + return error; + } + } else { + /* Do nothing */ + } + + return ICAL_NO_ERROR; +} + + + +int icaldirset_count_components(icaldirset* store, + icalcomponent_kind kind); + + +icalcomponent* icaldirset_fetch(icaldirset* store, char* uid) +{ + icalcomponent *gauge; + icalcomponent *old_gauge; + icalcomponent *c; + struct icaldirset_impl *impl = (struct icaldirset_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= icaldirset_get_first_component(store,ICAL_ANY_COMPONENT); + + impl->gauge = old_gauge; + + icalcomponent_free(gauge); + + return c; +} + + +int icaldirset_has_uid(icaldirset* 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 = icaldirset_fetch(store,uid); + + return c!=0; + +} + + +icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge) +{ + struct icaldirset_impl *impl = (struct icaldirset_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; +} + +void icaldirset_clear(icaldirset* store); +icalcomponent* icaldirset_fetch(icaldirset* store, char* uid); +int icaldirset_has_uid(icaldirset* store, char* uid); + +icalcomponent* icaldirset_get_current_component(icaldirset* store) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + + if(impl->cluster == 0){ + icaldirset_get_first_component(store,ICAL_ANY_COMPONENT); + } + + return icalfileset_get_current_component(impl->cluster); + +} + + +icalcomponent* icaldirset_get_first_component(icaldirset* store, + icalcomponent_kind kind) +{ + struct icaldirset_impl *impl = (struct icaldirset_impl*)store; + icalerrorenum error; + char path[PATH_MAX]; + + error = icaldirset_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; + } + + snprintf(path,PATH_MAX,"%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,icalfileset_path(impl->cluster)) != 0 ){ + icalfileset_free(impl->cluster); + impl->cluster = 0; + } + + if (impl->cluster == 0){ + impl->cluster = icalfileset_new(path); + + if (impl->cluster == 0){ + error = icalerrno; + } + } + + if (error != ICAL_NO_ERROR){ + icalerror_set_errno(error); + return 0; + } + + impl->first_component = 1; + + return icaldirset_get_next_component(store, kind); +} + +icalcomponent* icaldirset_get_next_component(icaldirset* store, + icalcomponent_kind kind) +{ + struct icaldirset_impl *impl; + icalcomponent *c; + icalerrorenum error; + + icalerror_check_arg_rz( (store!=0), "store"); + + impl = (struct icaldirset_impl*)store; + + if(impl->cluster == 0){ + + icalerror_warn("icaldirset_get_next_component called with a NULL cluster (Caller must call icaldirset_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){ + icalfileset_get_first_component(impl->cluster,kind); + impl->first_component = 0; + } else { + icalfileset_get_next_component(impl->cluster,kind); + } + + + while(1){ + /* Iterate through all of the objects in the cluster*/ + for( c = icalfileset_get_current_component(impl->cluster); + c != 0; + c = icalfileset_get_next_component( + impl->cluster, + kind)){ + + /* If there is a gauge defined and the component does not + pass the gauge, skip the rest of the loop */ + if (impl->gauge != 0 && icalgauge_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 = icaldirset_next_cluster(store); + + if(impl->cluster == 0 || error != ICAL_NO_ERROR){ + /* No more clusters */ + return 0; + } else { + c = icalfileset_get_first_component( + impl->cluster, + kind); + + return c; + } + + } + + return 0; /* Should never get here */ +} + + + + + + + diff --git a/libical/src/libicalss/icaldirset.h b/libical/src/libicalss/icaldirset.h new file mode 100644 index 0000000000..e9d6240aeb --- /dev/null +++ b/libical/src/libicalss/icaldirset.h @@ -0,0 +1,84 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icaldirset.h + CREATOR: eric 28 November 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALDIRSET_H +#define ICALDIRSET_H + +#include "ical.h" +#include "icalerror.h" + +/* icaldirset Routines for storing, fetching, and searching for ical + * objects in a database */ + +typedef void icaldirset; + + +icaldirset* icaldirset_new(char* path); + +void icaldirset_free(icaldirset* store); + +char* icaldirset_path(icaldirset* store); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately*/ +void icaldirset_mark(icaldirset* store); +icalerrorenum icaldirset_commit(icaldirset* store); + +icalerrorenum icaldirset_add_component(icaldirset* store, icalcomponent* comp); +icalerrorenum icaldirset_remove_component(icaldirset* store, icalcomponent* comp); + +int icaldirset_count_components(icaldirset* store, + icalcomponent_kind kind); + +/* Restrict the component returned by icaldirset_first, _next to those + that pass the gauge. _clear removes the gauge. */ +icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge); +void icaldirset_clear(icaldirset* store); + +/* Get a component by uid */ +icalcomponent* icaldirset_fetch(icaldirset* store, char* uid); +int icaldirset_has_uid(icaldirset* store, char* uid); + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *old, + icalcomponent *new); + +/* Iterate through the components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icaldirset_get_current_component(icaldirset* store); +icalcomponent* icaldirset_get_first_component(icaldirset* store, + icalcomponent_kind kind); +icalcomponent* icaldirset_get_next_component(icaldirset* store, + icalcomponent_kind kind); + +#endif /* !ICALDIRSET_H */ + + + diff --git a/libical/src/libicalss/icalfileset.c b/libical/src/libicalss/icalfileset.c new file mode 100644 index 0000000000..46c5cd2586 --- /dev/null +++ b/libical/src/libicalss/icalfileset.c @@ -0,0 +1,427 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalfileset.c + CREATOR: eric 23 December 1999 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include "icalfileset.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 */ + +#include "icalfilesetimpl.h" + +int icalfileset_lock(icalfileset *cluster); +int icalfileset_unlock(icalfileset *cluster); + + +icalerrorenum icalfileset_create_cluster(char *path); + +icalfileset* icalfileset_new_impl() +{ + struct icalfileset_impl* comp; + + if ( ( comp = (struct icalfileset_impl*) + malloc(sizeof(struct icalfileset_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; +} + +icalfileset* icalfileset_new(char* path) +{ + struct icalfileset_impl *impl = icalfileset_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); icalfileset_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 = icalfileset_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; + } + + icalfileset_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 icalfileset_free(icalfileset* cluster) +{ + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rv((cluster!=0),"cluster"); + + if (impl->cluster != 0){ + icalfileset_commit(cluster); + icalcomponent_free(impl->cluster); + impl->cluster=0; + } + + if(impl->path != 0){ + free(impl->path); + impl->path = 0; + } + + if(impl->stream != 0){ + icalfileset_unlock(impl); + fclose(impl->stream); + impl->stream = 0; + } + + free(impl); +} + +char* icalfileset_path(icalfileset* cluster) +{ + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return impl->path; +} + + +int icalfileset_lock(icalfileset *cluster) +{ + struct icalfileset_impl *impl = (struct icalfileset_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 icalfileset_unlock(icalfileset *cluster) +{ + struct icalfileset_impl *impl = (struct icalfileset_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 icalfileset_create_cluster(char *path) +{ + + FILE* f; + + 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 icalfileset_commit(icalfileset* cluster) +{ + FILE *f; + char tmp[PATH_MAX]; /* HACK Buffer overflow potential */ + char *str; + icalcomponent *c; + + struct icalfileset_impl *impl = (struct icalfileset_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 icalfileset_mark(icalfileset* cluster){ + + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rv((impl!=0),"cluster"); + + impl->changed = 1; + +} + +icalcomponent* icalfileset_get_component(icalfileset* cluster){ + struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR); + + return impl->cluster; +} + + +/* manipulate the components in the cluster */ + +icalerrorenum icalfileset_add_component(icalfileset *cluster, + icalcomponent* child) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rv((cluster!=0),"cluster"); + icalerror_check_arg_rv((child!=0),"child"); + + icalcomponent_add_component(impl->cluster,child); + + icalfileset_mark(cluster); + + return ICAL_NO_ERROR; + +} + +icalerrorenum icalfileset_remove_component(icalfileset *cluster, + icalcomponent* child) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rv((cluster!=0),"cluster"); + icalerror_check_arg_rv((child!=0),"child"); + + icalcomponent_remove_component(impl->cluster,child); + + icalfileset_mark(cluster); + + return ICAL_NO_ERROR; +} + +int icalfileset_count_components(icalfileset *cluster, + icalcomponent_kind kind) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + if(cluster == 0){ + icalerror_set_errno(ICAL_BADARG_ERROR); + return -1; + } + + return icalcomponent_count_components(impl->cluster,kind); +} + +icalerrorenum icalfileset_select(icalfileset* cluster, icalcomponent* gauge); +void icalfileset_clear(icalfileset* cluster); + +icalcomponent* icalfileset_fetch(icalfileset* store, char* uid); +int icalfileset_has_uid(icalfileset* store, char* uid); + + +/* Iterate through components */ +icalcomponent* icalfileset_get_current_component (icalfileset* cluster) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return icalcomponent_get_current_component(impl->cluster); +} + + +icalcomponent* icalfileset_get_first_component(icalfileset* cluster, + icalcomponent_kind kind) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return icalcomponent_get_first_component(impl->cluster,kind); +} + +icalcomponent* icalfileset_get_next_component(icalfileset* cluster, + icalcomponent_kind kind) +{ + struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster; + + icalerror_check_arg_rz((cluster!=0),"cluster"); + + return icalcomponent_get_next_component(impl->cluster,kind); +} + diff --git a/libical/src/libicalss/icalfileset.h b/libical/src/libicalss/icalfileset.h new file mode 100644 index 0000000000..8ceae632be --- /dev/null +++ b/libical/src/libicalss/icalfileset.h @@ -0,0 +1,90 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalfileset.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALFILESET_H +#define ICALFILESET_H + +#include "ical.h" + +typedef void icalfileset; + + +/* icalfileset + icalfilesetfile + icalfilesetdir +*/ + + +icalfileset* icalfileset_new(char* path); +void icalfileset_free(icalfileset* cluster); + +char* icalfileset_path(icalfileset* cluster); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately. */ +void icalfileset_mark(icalfileset* cluster); +icalerrorenum icalfileset_commit(icalfileset* cluster); + +icalerrorenum icalfileset_add_component(icalfileset* cluster, + icalcomponent* child); + +icalerrorenum icalfileset_remove_component(icalfileset* cluster, + icalcomponent* child); + +int icalfileset_count_components(icalfileset* cluster, + icalcomponent_kind kind); + +/* Restrict the component returned by icalfileset_first, _next to those + that pass the gauge. _clear removes the gauge */ +icalerrorenum icalfileset_select(icalfileset* store, icalcomponent* gauge); +void icalfileset_clear(icalfileset* store); + +/* Get and search for a component by uid */ +icalcomponent* icalfileset_fetch(icalfileset* cluster, char* uid); +int icalfileset_has_uid(icalfileset* cluster, char* uid); + + +/* Iterate through components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icalfileset_get_current_component (icalfileset* cluster); +icalcomponent* icalfileset_get_first_component(icalfileset* cluster, + icalcomponent_kind kind); +icalcomponent* icalfileset_get_next_component(icalfileset* cluster, + icalcomponent_kind kind); + +/* Return a reference to the internal component. You probably should + not be using this. */ + +icalcomponent* icalfileset_get_component(icalfileset* cluster); + + +#endif /* !ICALFILESET_H */ + + + diff --git a/libical/src/libicalss/icalfilesetimpl.h b/libical/src/libicalss/icalfilesetimpl.h new file mode 100644 index 0000000000..de447c64eb --- /dev/null +++ b/libical/src/libicalss/icalfilesetimpl.h @@ -0,0 +1,42 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalfilesetimpl.h + CREATOR: eric 23 December 1999 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + + ======================================================================*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* This definition is in its own file so it can be kept out of the + main header file, but used by "friend classes" like icaldirset*/ + +struct icalfileset_impl { + char *path; + icalcomponent* cluster; + int changed; + FILE* stream; +}; + diff --git a/libical/src/libicalss/icalgauge.c b/libical/src/libicalss/icalgauge.c new file mode 100644 index 0000000000..60ce1587cd --- /dev/null +++ b/libical/src/libicalss/icalgauge.c @@ -0,0 +1,208 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalgauge.c + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#include "ical.h" + +/* Convert a VQUERY component into a gauge */ +icalcomponent* icalgauge_make_gauge(icalcomponent* query); + +/* icaldirset_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 icalgauge_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 + icaldirset_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 = icalgauge_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 icalgauge_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 += icalgauge_test_recurse(comp, gauge); + } + + return pass>0; + +} + + diff --git a/libical/src/libicalss/icalgauge.h b/libical/src/libicalss/icalgauge.h new file mode 100644 index 0000000000..401d9b7347 --- /dev/null +++ b/libical/src/libicalss/icalgauge.h @@ -0,0 +1,37 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalgauge.h + CREATOR: eric 23 December 1999 + + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALGAUGE_H +#define ICALGAUGE_H + +icalcomponent* icalgauge_new_from_vquery(char* vquery); +char* icalgauge_as_vquery(icalcomponent* gauge); +int icalgauge_test(icalcomponent* comp, icalcomponent* gaugecontainer); + + +#endif /* ICALGAUGE_H*/ diff --git a/libical/src/libicalss/icalset.c b/libical/src/libicalss/icalset.c new file mode 100644 index 0000000000..01a36c0129 --- /dev/null +++ b/libical/src/libicalss/icalset.c @@ -0,0 +1,86 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalset.c + CREATOR: eric 17 Jul 2000 + + + Icalset is the "base class" for representations of a collection of + iCal components. Derived classes (actually delegatees) include: + + icalfileset Store componetns in a single file + icaldirset Store components in multiple files in a directory + icalheapset Store components on the heap + icalmysqlset Store components in a mysql database. + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#include "ical.h" +#include "icalset.h" +#include "icalfileset.h" +#include "icaldirset.h" +/*#include "icalheapset.h"*/ +/*#include "icalmysqlset.h"*/ + +icalset* icalset_new_file(char* path); + +icalset* icalset_new_dir(char* path); + +icalset* icalset_new_heap(void); + +icalset* icalset_new_mysql(char* path); + +void icalset_free(icalset* set); + +char* icalset_path(icalset* set); + +void icalset_mark(icalset* set); + +icalerrorenum icalset_commit(icalset* set); + +icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp); + +icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp); + +int icalset_count_components(icalset* set, + icalcomponent_kind kind); + +icalerrorenum icalset_select(icalset* set, icalcomponent* gauge); + +void icalset_clear_select(icalset* set); + +icalcomponent* icalset_fetch(icalset* set, char* uid); + +int icalset_has_uid(icalset* set, char* uid); + +icalerrorenum icalset_modify(icalset* set, icalcomponent *old, + icalcomponent *new); + +icalcomponent* icalset_get_current_component(icalset* set); + +icalcomponent* icalset_get_first_component(icalset* set); + +icalcomponent* icalset_get_next_component(icalset* set); + + + + diff --git a/libical/src/libicalss/icalset.h b/libical/src/libicalss/icalset.h new file mode 100644 index 0000000000..15bb71f72e --- /dev/null +++ b/libical/src/libicalss/icalset.h @@ -0,0 +1,100 @@ +/* -*- Mode: C -*- */ +/*====================================================================== + FILE: icalset.h + CREATOR: eric 28 November 1999 + + + Icalset is the "base class" for representations of a collection of + iCal components. Derived classes (actually delegatees) include: + + icalfileset Store componetns in a single file + icaldirset Store components in multiple files in a directory + icalheapset Store components on the heap + icalmysqlset Store components in a mysql database. + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + The Original Code is eric. The Initial Developer of the Original + Code is Eric Busboom + + +======================================================================*/ + +#ifndef ICALSET_H +#define ICALSET_H + +#include "ical.h" +#include "icalerror.h" + +typedef void icalset; + +typedef enum icalset_kind { + ICAL_FILE_SET, + ICAL_DIR_SET, + ICAL_HEAP_SET, + ICAL_MYSQL_SET, + ICAL_CAP_SET +} icalset_kind; + + +/* Create a specific derived type of set */ +icalset* icalset_new_file(char* path); +icalset* icalset_new_dir(char* path); +icalset* icalset_new_heap(void); +icalset* icalset_new_mysql(char* path); +/*icalset* icalset_new_cap(icalcstp* cstp);*/ + +void icalset_free(icalset* set); + +char* icalset_path(icalset* set); + +/* Mark the cluster as changed, so it will be written to disk when it + is freed. Commit writes to disk immediately*/ +void icalset_mark(icalset* set); +icalerrorenum icalset_commit(icalset* set); + +icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp); +icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp); + +int icalset_count_components(icalset* set, + icalcomponent_kind kind); + +/* Restrict the component returned by icalset_first, _next to those + that pass the gauge. _clear removes the gauge. */ +icalerrorenum icalset_select(icalset* set, icalcomponent* gauge); +void icalset_clear_select(icalset* set); + +/* Get a component by uid */ +icalcomponent* icalset_fetch(icalset* set, char* uid); +int icalset_has_uid(icalset* set, char* uid); + +/* Modify components according to the MODIFY method of CAP. Works on + the currently selected components. */ +icalerrorenum icalset_modify(icalset* set, icalcomponent *old, + icalcomponent *new); + +/* Iterate through the components. If a guage has been defined, these + will skip over components that do not pass the gauge */ + +icalcomponent* icalset_get_current_component(icalset* set); +icalcomponent* icalset_get_first_component(icalset* set); +icalcomponent* icalset_get_next_component(icalset* set); + +#endif /* !ICALSET_H */ + + + |