aboutsummaryrefslogtreecommitdiffstats
path: root/libical/src/libicalss
diff options
context:
space:
mode:
authorHans Petter <hansp@src.gnome.org>2003-09-12 06:04:44 +0800
committerHans Petter <hansp@src.gnome.org>2003-09-12 06:04:44 +0800
commit697761cc337aa77a47140c8df50ed84bc25e23f6 (patch)
treeb785830f72e9938cceaa016a419c7b6d9892bada /libical/src/libicalss
parent733d77e657516f9a59b5c1a7b62acb87b03ec86f (diff)
downloadgsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar
gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.gz
gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.bz2
gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.lz
gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.xz
gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.zst
gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.zip
Import new libical from mainline HEAD and make appropriate changes to
Evolution. svn path=/trunk/; revision=22538
Diffstat (limited to 'libical/src/libicalss')
-rw-r--r--libical/src/libicalss/.cvsignore6
-rw-r--r--libical/src/libicalss/Makefile.am117
-rw-r--r--libical/src/libicalss/icalbdbset.c1598
-rw-r--r--libical/src/libicalss/icalbdbset.h147
-rw-r--r--libical/src/libicalss/icalbdbset_cxx.h61
-rw-r--r--libical/src/libicalss/icalbdbsetimpl.h41
-rw-r--r--libical/src/libicalss/icalcalendar.c52
-rw-r--r--libical/src/libicalss/icalcalendar.h2
-rw-r--r--libical/src/libicalss/icalcaputil.h58
-rw-r--r--libical/src/libicalss/icalclassify.c174
-rw-r--r--libical/src/libicalss/icalclassify.h36
-rw-r--r--libical/src/libicalss/icalcluster.c245
-rw-r--r--libical/src/libicalss/icalcluster.h61
-rw-r--r--libical/src/libicalss/icalclusterimpl.h45
-rw-r--r--libical/src/libicalss/icaldirset.c518
-rw-r--r--libical/src/libicalss/icaldirset.h54
-rw-r--r--libical/src/libicalss/icaldirsetimpl.h19
-rw-r--r--libical/src/libicalss/icalfileset.c704
-rw-r--r--libical/src/libicalss/icalfileset.h96
-rw-r--r--libical/src/libicalss/icalfilesetimpl.h18
-rw-r--r--libical/src/libicalss/icalgauge.c172
-rw-r--r--libical/src/libicalss/icalgauge.h26
-rw-r--r--libical/src/libicalss/icalgaugeimpl.h12
-rw-r--r--libical/src/libicalss/icalmessage.c16
-rw-r--r--libical/src/libicalss/icalset.c528
-rw-r--r--libical/src/libicalss/icalset.h121
-rw-r--r--libical/src/libicalss/icalspanlist.c386
-rw-r--r--libical/src/libicalss/icalspanlist.h29
-rw-r--r--libical/src/libicalss/icalspanlist_cxx.cpp92
-rw-r--r--libical/src/libicalss/icalspanlist_cxx.h53
-rw-r--r--libical/src/libicalss/icalsslexer.l30
-rw-r--r--libical/src/libicalss/icalssyacc.h45
-rw-r--r--libical/src/libicalss/icalssyacc.y77
33 files changed, 4560 insertions, 1079 deletions
diff --git a/libical/src/libicalss/.cvsignore b/libical/src/libicalss/.cvsignore
index 04a3e1b036..25846dfca6 100644
--- a/libical/src/libicalss/.cvsignore
+++ b/libical/src/libicalss/.cvsignore
@@ -1,10 +1,6 @@
Makefile
.deps
-Makefile.in
+.libs
*.lo
*.la
-.libs
-y.output
-icalsslexer.c
-icalssyacc.c
icalss.h
diff --git a/libical/src/libicalss/Makefile.am b/libical/src/libicalss/Makefile.am
index 9e11bc3fc8..ebb755c95a 100644
--- a/libical/src/libicalss/Makefile.am
+++ b/libical/src/libicalss/Makefile.am
@@ -1,26 +1,89 @@
-lib_LTLIBRARIES = libicalss.la
+#======================================================================
+# FILE: Makefile.am
+# CREATOR: eric
+#
+# $Id: Makefile.am,v 1.19 2003/09/11 22:04:30 hansp Exp $
+#
+#
+# (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of either:
+#
+# The LGPL as published by the Free Software Foundation, version
+# 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+#
+# Or:
+#
+# The Mozilla Public License Version 1.0. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+#
+#
+#======================================================================
-YFLAGS =-d -v -p ss
-LFLAGS = -Pss
+
+AM_YFLAGS =-d -v -p ss
+AM_LFLAGS = -Pss
LEX_OUTPUT_ROOT = lex.ss
all: icalss.h
+# just to get it built
+$(srcdir)/icalgauge.c: icalssyacc.h
+$(srcdir)/icalsslexer.c: icalssyacc.h
+
+
+if WITH_BDB4
+BDB_INCLUDE=-I@BDB_DIR_INCLUDE@ -DWITH_BDB4
+BDB_SOURCEFILES=icalbdbset.c icalbdbset.h icalbdbsetimpl.h
+BDB_HEADERFILES=$(srcdir)/icalbdbset.h
+libicalssinclude_BDBHEADERS=icalbdbset.h icalbdbsetimpl.h
+BDB_LIBFILES=@BDB_DIR_LIB@/@BDB_LIB@
+else
+BDB_INCLUDE=
+BDB_SOURCEFILES=
+BDB_HEADERFILES=
+endif
+
+if WITH_CXX
+cxx_lib=libicalss_cxx.la
+cxx_headers=icalspanlist_cxx.h
+else
+cxx_lib=
+cxx_headers=
+endif
+
+lib_LTLIBRARIES = libicalss.la $(cxx_lib)
+
INCLUDES = \
-I$(top_srcdir)/src \
-I$(top_builddir)/src \
-I$(top_srcdir)/src/libical \
- -I$(top_builddir)/src/libical
+ -I$(top_builddir)/libical \
+ $(BDB_INCLUDE)
libicalss_la_LDFLAGS = -version-info 0:0:0
+libicalss_la_LIBADD = $(BDB_LIBFILES)
+
+if DEV
+libicalss_la_DEVSOURCES = icalsslexer.l icalssyacc.y
+else
+libicalss_la_DEVSOURCES = icalsslexer.c icalssyacc.c
+endif
libicalss_la_SOURCES = \
+ icalcalendar.c \
icalcalendar.h \
icalclassify.c \
icalclassify.h \
+ icalcluster.c \
+ icalcluster.h \
+ icalclusterimpl.h \
icalgauge.c \
icalgauge.h \
icalgaugeimpl.h \
+ icaldirset.c \
icaldirset.h \
icaldirsetimpl.h \
icalfileset.c \
@@ -28,42 +91,58 @@ libicalss_la_SOURCES = \
icalfilesetimpl.h \
icalset.c \
icalset.h \
- icalsslexer.l \
icalssyacc.h \
- icalssyacc.y \
icalspanlist.c \
icalspanlist.h \
icalmessage.c \
icalmessage.h \
- icalcstpclient.c \
- icalcstpclient.h \
- icalcstpserver.c \
- icalcstpserver.h \
- icalcstp.c \
- icalcstp.h
+ $(BDB_SOURCEFILES) \
+ $(libicalss_la_DEVSOURCES)
libicalssincludedir = $(includedir)
COMBINEDHEADERS = \
$(srcdir)/icalgauge.h \
$(srcdir)/icalset.h \
+ $(srcdir)/icalcluster.h \
$(srcdir)/icalfileset.h \
$(srcdir)/icaldirset.h \
+ $(BDB_HEADERFILES) \
$(srcdir)/icalcalendar.h \
$(srcdir)/icalclassify.h \
$(srcdir)/icalspanlist.h \
- $(srcdir)/icalmessage.h \
- $(srcdir)/icalcstp.h \
- $(srcdir)/icalcstpclient.h \
- $(srcdir)/icalcstpserver.h
+ $(srcdir)/icalmessage.h
icalss.h: $(COMBINEDHEADERS)
- cat $(COMBINEDHEADERS) | egrep -v "#include.*\"ical" \
- | egrep -v "#include.*\"pvl\.h\"" > icalss.h
+ echo '#ifdef __cplusplus' > icalss.h
+ echo 'extern "C" {' >> icalss.h
+ echo '#endif' >> icalss.h
+ echo '/*' >> icalss.h
+ echo ' $$''Id''$$' >> icalss.h
+ echo '*/' >> icalss.h
+ cat $(COMBINEDHEADERS) \
+ | egrep -v "#include.*\"ical" \
+ | egrep -v "#include.*\"pvl\.h\"" \
+ | egrep -v '\$$(Id|Locker): .+\$$'>> icalss.h
+ echo '#ifdef __cplusplus' >> icalss.h
+ echo '};' >> icalss.h
+ echo '#endif' >> icalss.h
+
+
+if WITH_CXX
+libicalss_cxx_la_SOURCES = \
+ $(libicalss_la_SOURCES) \
+ icalspanlist_cxx.h \
+ icalspanlist_cxx.cpp
+
+# c++ needs ical.h auto-generated.
+icalspanlist_cxx.lo: icalss.h
+
+endif
-libicalssinclude_HEADERS = icalss.h
+libicalssinclude_HEADERS = icalss.h icalcalendar.h icalclassify.h icalcluster.h icaldirset.h icaldirsetimpl.h icalfileset.h icalfilesetimpl.h icalgauge.h icalgaugeimpl.h icalmessage.h icalset.h icalspanlist.h icalssyacc.h $(libicalssinclude_BDBHEADERS) $(cxx_headers)
CONFIG_CLEAN_FILES = y.output
diff --git a/libical/src/libicalss/icalbdbset.c b/libical/src/libicalss/icalbdbset.c
new file mode 100644
index 0000000000..6b11e46741
--- /dev/null
+++ b/libical/src/libicalss/icalbdbset.c
@@ -0,0 +1,1598 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalbdbset.c
+ ======================================================================*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "icalbdbset.h"
+#include "icalgauge.h"
+#include <errno.h>
+#include <sys/stat.h> /* for stat */
+#include <stdio.h>
+
+#ifndef WIN32
+#include <unistd.h> /* for stat, getpid, unlink */
+#include <fcntl.h> /* for fcntl */
+#include <unistd.h> /* for fcntl */
+#else
+#define S_IRUSR S_IREAD /* R for owner */
+#define S_IWUSR S_IWRITE /* W for owner */
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "icalbdbsetimpl.h"
+
+#define STRBUF_LEN 255
+#define MAX_RETRY 5
+
+extern int errno;
+
+
+
+/* these are just stub functions */
+icalerrorenum icalbdbset_read_database(icalbdbset* bset, char *(*pfunc)(const DBT *dbt));
+icalerrorenum icalbdbset_create_cluster(const char *path);
+int icalbdbset_cget(DBC *dbcp, DBT *key, DBT *data, int access_method);
+
+static int _compare_keys(DB *dbp, const DBT *a, const DBT *b);
+
+
+/** Default options used when NULL is passed to icalset_new() **/
+icalbdbset_options icalbdbset_options_default = {ICALBDB_EVENTS, DB_BTREE, 0644, 0, NULL, NULL};
+
+
+static DB_ENV *ICAL_DB_ENV = 0;
+
+/** Initialize the db environment */
+
+int icalbdbset_init_dbenv(char *db_env_dir, void (*logDbFunc)(const char*, char*)) {
+ int ret;
+ int flags;
+
+ if (db_env_dir) {
+ struct stat env_dir_sb;
+
+ if (stat(db_env_dir, &env_dir_sb)) {
+ fprintf(stderr, "The directory '%s' is missing, please create it.\n", db_env_dir);
+ return EINVAL;
+ }
+ }
+
+ ret = db_env_create(&ICAL_DB_ENV, 0);
+
+ if (ret) {
+ /* some kind of error... */
+ return ret;
+ }
+
+ /* Do deadlock detection internally */
+ if ((ret = ICAL_DB_ENV->set_lk_detect(ICAL_DB_ENV, DB_LOCK_DEFAULT)) != 0) {
+ char * foo = db_strerror(ret);
+ fprintf(stderr, "Could not initialize the database locking environment\n");
+ return ret;
+ }
+
+ flags = DB_INIT_LOCK | DB_INIT_TXN | DB_CREATE | DB_THREAD | \
+ DB_RECOVER | DB_INIT_LOG | DB_INIT_MPOOL;
+ ret = ICAL_DB_ENV->open(ICAL_DB_ENV, db_env_dir, flags, S_IRUSR|S_IWUSR);
+
+ if (ret) {
+ char * foo = db_strerror(ret);
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "dbenv->open");
+ return ret;
+ }
+
+ /* display additional error messages */
+ if (logDbFunc != NULL) {
+ ICAL_DB_ENV->set_errcall(ICAL_DB_ENV, logDbFunc);
+ }
+
+ return ret;
+}
+
+void icalbdbset_checkpoint(void)
+{
+ int ret;
+ char *err;
+
+ switch (ret = ICAL_DB_ENV->txn_checkpoint(ICAL_DB_ENV, 0,0,0)) {
+ case 0:
+ case DB_INCOMPLETE:
+ break;
+ default:
+ err = db_strerror(ret);
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "checkpoint failed");
+ abort();
+ }
+}
+
+void icalbdbset_rmdbLog(void)
+{
+ int ret = 0;
+ char** listp;
+
+ /* remove log files that are archivable (ie. no longer needed) */
+ if (ICAL_DB_ENV->log_archive(ICAL_DB_ENV, &listp, DB_ARCH_ABS) == 0) {
+ if (listp != NULL) {
+ int ii = 0;
+ while (listp[ii] != NULL) {
+ ret = unlink(listp[ii]);
+ ii++;
+ }
+ free(listp);
+ }
+ }
+}
+
+int icalbdbset_cleanup(void)
+{
+ int ret = 0;
+
+ /* one last checkpoint.. */
+ icalbdbset_checkpoint();
+
+ /* remove logs that are not needed anymore */
+ icalbdbset_rmdbLog();
+
+ if (ICAL_DB_ENV)
+ ret = ICAL_DB_ENV->close(ICAL_DB_ENV, 0);
+
+ return ret;
+}
+
+DB_ENV *icalbdbset_get_env(void) {
+ return ICAL_DB_ENV;
+}
+
+
+/** Initialize an icalbdbset. Also attempts to populate from the
+ * database (primary if only dbp is given, secondary if sdbp is
+ * given) and creates an empty object if retrieval is unsuccessful.
+ * pfunc is used to unpack data from the database. If not given, we
+ * assume data is a string.
+ */
+
+icalset* icalbdbset_init(icalset* set, const char* dsn, void* options_in)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalbdbset_options *options = options_in;
+ int ret;
+ DB *cal_db;
+ char *subdb_name;
+
+ if (options == NULL)
+ *options = icalbdbset_options_default;
+
+ switch (options->subdb) {
+ case ICALBDB_CALENDARS:
+ subdb_name = "calendars";
+ break;
+ case ICALBDB_EVENTS:
+ subdb_name = "events";
+ break;
+ case ICALBDB_TODOS:
+ subdb_name = "todos";
+ break;
+ case ICALBDB_REMINDERS:
+ subdb_name = "reminders";
+ break;
+ }
+
+ cal_db = icalbdbset_bdb_open(set->dsn,
+ subdb_name,
+ options->dbtype,
+ options->mode,
+ options->flag);
+ if (cal_db == NULL)
+ return NULL;
+
+ bset->dbp = cal_db;
+ bset->sdbp = NULL;
+ bset->gauge = 0;
+ bset->cluster = 0;
+
+ if ((ret = icalbdbset_read_database(bset, options->pfunc)) != ICAL_NO_ERROR) {
+ return NULL;
+ }
+
+ return (icalset *)bset;
+}
+
+
+/** open a database and return a reference to it. Used only for
+ opening the primary index.
+ flag = set_flag() DUP | DUP_SORT
+ */
+
+icalset* icalbdbset_new(const char* database_filename,
+ icalbdbset_subdb_type subdb_type,
+ int dbtype, int flag)
+{
+ icalbdbset_options options = icalbdbset_options_default;
+
+ options.subdb = subdb_type;
+ options.dbtype = dbtype;
+ options.flag = flag;
+
+ /* this will in turn call icalbdbset_init */
+ return icalset_new(ICAL_BDB_SET, database_filename, &options);
+}
+
+/**
+ * Open a secondary database, used for accessing secondary indices.
+ * The callback function tells icalbdbset how to associate secondary
+ * key information with primary data. See the BerkeleyDB reference
+ * guide for more information.
+ */
+
+DB * icalbdbset_bdb_open_secondary(DB *dbp,
+ const char *database,
+ const char *sub_database,
+ int (*callback) (DB *db,
+ const DBT *dbt1,
+ const DBT *dbt2,
+ DBT *dbt3),
+ int type)
+{
+ int ret;
+ int flags;
+ DB *sdbp = NULL;
+
+ if (!sub_database)
+ return NULL;
+
+ if (!ICAL_DB_ENV)
+ icalbdbset_init_dbenv(NULL, NULL);
+
+ /* Open/create secondary */
+ if((ret = db_create(&sdbp, ICAL_DB_ENV, 0)) != 0) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "secondary index: %s", sub_database);
+ return NULL;
+ }
+
+ if ((ret = sdbp->set_flags(sdbp, DB_DUP | DB_DUPSORT)) != 0) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "set_flags error for secondary index: %s", sub_database);
+ return NULL;
+ }
+
+ flags = DB_CREATE | DB_THREAD;
+ if ((ret = sdbp->open(sdbp, database, sub_database, type, (u_int32_t) flags, 0644)) != 0) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "failed to open secondary index: %s", sub_database);
+ if (ret == DB_RUNRECOVERY)
+ abort();
+ else
+ return NULL;
+ }
+
+ /* Associate the primary index with a secondary */
+ if((ret = dbp->associate(dbp, sdbp, callback, 0)) != 0) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "failed to associate secondary index: %s", sub_database);
+ return NULL;
+ }
+
+ return sdbp;
+}
+
+DB* icalbdbset_bdb_open(const char* path,
+ const char *subdb,
+ int dbtype,
+ mode_t mode,
+ int flag)
+{
+ DB *dbp = NULL;
+ int ret;
+ int flags;
+
+ /* Initialize the correct set of db subsystems (see capdb.c) */
+ flags = DB_CREATE | DB_THREAD;
+
+ /* should just abort here instead of opening an env in the current dir.. */
+ if (!ICAL_DB_ENV)
+ icalbdbset_init_dbenv(NULL, NULL);
+
+ /* Create and initialize database object, open the database. */
+ if ((ret = db_create(&dbp, ICAL_DB_ENV, 0)) != 0) {
+ return (NULL);
+ }
+
+ /* set comparison function, if BTREE */
+ if (dbtype == DB_BTREE)
+ dbp->set_bt_compare(dbp, _compare_keys);
+
+ /* set DUP, DUPSORT */
+ if (flag != 0)
+ dbp->set_flags(dbp, flag);
+
+ if ((ret = dbp->open(dbp, path, subdb, dbtype, flags, mode)) != 0) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "%s (database: %s): open failed.", path, subdb);
+ if (ret == DB_RUNRECOVERY)
+ abort();
+ else
+ return NULL;
+ }
+
+ return (dbp);
+}
+
+
+/* icalbdbset_parse_data -- parses using pfunc to unpack data. */
+char *icalbdbset_parse_data(DBT *dbt, char *(*pfunc)(const DBT *dbt))
+{
+ char *ret;
+
+ if(pfunc) {
+ ret = (char *)pfunc(dbt);
+ } else {
+ ret = (char *) dbt->data;
+ }
+
+ return (ret);
+}
+
+/* This populates a cluster with the entire contents of a database */
+icalerrorenum icalbdbset_read_database(icalbdbset* bset, char *(*pfunc)(const DBT *dbt))
+{
+
+ DB *dbp;
+ DBC *dbcp;
+ DBT key, data;
+ char *str, *szpstr;
+ int ret;
+ char keystore[256];
+ char datastore[1024];
+ char *more_mem = NULL;
+ DB_TXN *tid;
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+
+ if (bset->sdbp) { dbp = bset->sdbp; }
+ else { dbp = bset->dbp; }
+
+ if(!dbp) { goto err1; }
+
+ bset->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
+
+ if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) {
+ char *foo = db_strerror(ret);
+ abort();
+ }
+
+ /* acquire a cursor for the database */
+ if ((ret = dbp->cursor(dbp, tid, &dbcp, 0)) != 0) {
+ dbp->err(dbp, ret, "primary index");
+ goto err1;
+ }
+
+ key.flags = DB_DBT_USERMEM;
+ key.data = keystore;
+ key.ulen = sizeof(keystore);
+
+ data.flags= DB_DBT_USERMEM;
+ data.data = datastore;
+ data.ulen = sizeof(datastore);
+
+
+ /* fetch the key/data pair */
+ while (1) {
+ ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT);
+ if (ret == DB_NOTFOUND) {
+ break;
+ } else if (ret == ENOMEM) {
+ if (more_mem) free (more_mem);
+ more_mem = malloc(data.ulen+1024);
+ data.data = more_mem;
+ data.ulen = data.ulen+1024;
+ } else if (ret == DB_LOCK_DEADLOCK) {
+ char *foo = db_strerror(ret);
+ abort(); /* should retry in case of DB_LOCK_DEADLOCK */
+ } else if (ret) {
+ char *foo = db_strerror(ret);
+ /* some other weird-ass error */
+ dbp->err(dbp, ret, "cursor");
+ abort();
+ } else {
+ icalcomponent *cl;
+
+ /* this prevents an array read bounds error */
+ if((str = (char *)calloc(data.size + 1, sizeof(char)))==NULL)
+ goto err2;
+ memcpy(str, (char *)data.data, data.size);
+
+ cl = icalparser_parse_string(str);
+
+ icalcomponent_add_component(bset->cluster, cl);
+ free(str);
+ }
+ }
+ if(ret != DB_NOTFOUND) {
+ goto err2;
+ }
+
+
+ if (more_mem) {
+ free(more_mem);
+ more_mem = NULL;
+ }
+
+ if ((ret = dbcp->c_close(dbcp)) != 0) {
+ char * foo = db_strerror(ret);
+ abort(); /* should retry in case of DB_LOCK_DEADLOCK */
+ }
+
+ if ((ret = tid->commit(tid, 0)) != 0) {
+ char * foo = db_strerror(ret);
+ abort();
+ }
+
+ return ICAL_NO_ERROR;
+
+ err2:
+ if (more_mem) free(more_mem);
+ dbcp->c_close(dbcp);
+ abort(); /* should retry in case of DB_LOCK_DEADLOCK */
+ return ICAL_INTERNAL_ERROR;
+
+ err1:
+ dbp->err(dbp, ret, "cursor index");
+ abort();
+ return (ICAL_FILE_ERROR);
+}
+
+
+/* XXX add more to this */
+void icalbdbset_free(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ int ret;
+
+ icalerror_check_arg_rv((bset!=0),"bset");
+
+ if (bset->cluster != 0){
+ icalbdbset_commit(set);
+ icalcomponent_free(bset->cluster);
+ bset->cluster=0;
+ }
+
+ if(bset->gauge !=0){
+ icalgauge_free(bset->gauge);
+ }
+
+ if(bset->path != 0){
+ free((char *)bset->path);
+ bset->path = 0;
+ }
+
+ if(bset->sindex != 0) {
+ free((char *)bset->sindex);
+ bset->sindex = 0;
+ }
+
+ if (bset->dbp &&
+ ((ret = bset->dbp->close(bset->dbp, 0)) != 0)) {
+ }
+ bset->dbp = NULL;
+}
+
+/* return cursor is in rdbcp */
+int icalbdbset_acquire_cursor(DB *dbp, DB_TXN *tid, DBC **rdbcp) {
+ int ret=0;
+
+ if((ret = dbp->cursor(dbp, tid, rdbcp, 0)) != 0) {
+ dbp->err(dbp, ret, "couldn't open cursor");
+ goto err1;
+ }
+
+ return ICAL_NO_ERROR;
+
+ err1:
+ return ICAL_FILE_ERROR;
+
+}
+
+/* returns key/data in arguments */
+int icalbdbset_get_first(DBC *dbcp, DBT *key, DBT *data) {
+ return icalbdbset_cget(dbcp, key, data, DB_FIRST);
+}
+
+int icalbdbset_get_next(DBC *dbcp, DBT *key, DBT *data) {
+ return icalbdbset_cget(dbcp, key, data, DB_NEXT);
+}
+
+int icalbdbset_get_last(DBC *dbcp, DBT *key, DBT *data) {
+ return icalbdbset_cget(dbcp, key, data, DB_LAST);
+}
+
+int icalbdbset_get_key(DBC *dbcp, DBT *key, DBT *data) {
+ return icalbdbset_cget(dbcp, key, data, DB_SET);
+}
+
+int icalbdbset_delete(DB *dbp, DBT *key) {
+ DB_TXN *tid;
+ int ret;
+ int done = 0;
+ int retry = 0;
+
+ while ((retry < MAX_RETRY) && !done) {
+
+ if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) {
+ if (ret == DB_LOCK_DEADLOCK) {
+ retry++;
+ continue;
+ }
+ else {
+ char *foo = db_strerror(ret);
+ abort();
+ }
+ }
+
+ if ((ret = dbp->del(dbp, tid, key, 0)) != 0) {
+ if (ret == DB_NOTFOUND) {
+ /* do nothing - not an error condition */
+ }
+ else if (ret == DB_LOCK_DEADLOCK) {
+ tid->abort(tid);
+ retry++;
+ continue;
+ }
+ else {
+ char *strError = db_strerror(ret);
+ icalerror_warn("icalbdbset_delete faild: ");
+ icalerror_warn(strError);
+ tid->abort(tid);
+ return ICAL_FILE_ERROR;
+ }
+ }
+
+ if ((ret = tid->commit(tid, 0)) != 0) {
+ if (ret == DB_LOCK_DEADLOCK) {
+ tid->abort(tid);
+ retry++;
+ continue;
+ }
+ else {
+ char * foo = db_strerror(ret);
+ abort();
+ }
+ }
+
+ done = 1; /* all is well */
+ }
+
+ if (!done) {
+ if (tid != NULL) tid->abort(tid);
+ }
+
+ return ret;
+}
+
+int icalbdbset_cget(DBC *dbcp, DBT *key, DBT *data, int access_method) {
+ int ret=0;
+
+ key->flags |= DB_DBT_MALLOC; /* change these to DB_DBT_USERMEM */
+ data->flags |= DB_DBT_MALLOC;
+
+ /* fetch the key/data pair */
+ if((ret = dbcp->c_get(dbcp, key, data, access_method)) != 0) {
+ goto err1;
+ }
+
+ return ICAL_NO_ERROR;
+
+ err1:
+ return ICAL_FILE_ERROR;
+}
+
+
+int icalbdbset_cput(DBC *dbcp, DBT *key, DBT *data, int access_method) {
+ int ret=0;
+
+ key->flags |= DB_DBT_MALLOC; /* change these to DB_DBT_USERMEM */
+ data->flags |= DB_DBT_MALLOC;
+
+ /* fetch the key/data pair */
+ if((ret = dbcp->c_put(dbcp, key, data, 0)) != 0) {
+ goto err1;
+ }
+
+ return ICAL_NO_ERROR;
+
+ err1:
+ return ICAL_FILE_ERROR;
+}
+
+
+int icalbdbset_put(DB *dbp, DBT *key, DBT *data, int access_method)
+{
+ int ret = 0;
+ DB_TXN *tid = NULL;
+ int retry = 0;
+ int done = 0;
+
+ while ((retry < MAX_RETRY) && !done) {
+
+ if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) {
+ if (ret == DB_LOCK_DEADLOCK) {
+ retry++;
+ continue;
+ }
+ else {
+ char *foo = db_strerror(ret);
+ abort();
+ }
+ }
+
+ if ((ret = dbp->put(dbp, tid, key, data, access_method)) != 0) {
+ if (ret == DB_LOCK_DEADLOCK) {
+ tid->abort(tid);
+ retry++;
+ continue;
+ }
+ else {
+ char *strError = db_strerror(ret);
+ icalerror_warn("icalbdbset_put faild: ");
+ icalerror_warn(strError);
+ tid->abort(tid);
+ return ICAL_FILE_ERROR;
+ }
+ }
+
+ if ((ret = tid->commit(tid, 0)) != 0) {
+ if (ret == DB_LOCK_DEADLOCK) {
+ tid->abort(tid);
+ retry++;
+ continue;
+ }
+ else {
+ char * foo = db_strerror(ret);
+ abort();
+ }
+ }
+
+ done = 1; /* all is well */
+ }
+
+ if (!done) {
+ if (tid != NULL) tid->abort(tid);
+ return ICAL_FILE_ERROR;
+ }
+ else
+ return ICAL_NO_ERROR;
+}
+
+int icalbdbset_get(DB *dbp, DB_TXN *tid, DBT *key, DBT *data, int flags)
+{
+ return (dbp->get(dbp, tid, key, data, flags));
+}
+
+/** Return the path of the database file **/
+
+const char* icalbdbset_path(icalset* set)
+{
+ icalerror_check_arg_rz((set!=0),"set");
+
+ return set->dsn;
+}
+
+const char* icalbdbset_subdb(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ return bset->subdb;
+}
+
+
+/** Write changes out to the database file.
+ */
+
+icalerrorenum icalbdbset_commit(icalset *set) {
+ DB *dbp;
+ DBC *dbcp;
+ DBT key, data;
+ icalcomponent *c;
+ char *str;
+ int ret=0;
+ int reterr = ICAL_NO_ERROR;
+ char keystore[256];
+ char uidbuf[256];
+ char datastore[1024];
+ char *more_mem = NULL;
+ DB_TXN *tid = NULL;
+ icalbdbset *bset = (icalbdbset*)set;
+ int bad_uid_counter = 0;
+ int retry = 0, done = 0, completed = 0, deadlocked = 0;
+
+ icalerror_check_arg_re((bset!=0),"bset",ICAL_BADARG_ERROR);
+
+ dbp = bset->dbp;
+ icalerror_check_arg_re((dbp!=0),"dbp is invalid",ICAL_BADARG_ERROR);
+
+ if (bset->changed == 0)
+ return ICAL_NO_ERROR;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.flags = DB_DBT_USERMEM;
+ key.data = keystore;
+ key.ulen = sizeof(keystore);
+
+ data.flags = DB_DBT_USERMEM;
+ data.data = datastore;
+ data.ulen = sizeof(datastore);
+
+ if (!ICAL_DB_ENV)
+ icalbdbset_init_dbenv(NULL, NULL);
+
+ while ((retry < MAX_RETRY) && !done) {
+
+ if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) {
+ if (ret == DB_LOCK_DEADLOCK) {
+ retry++;
+ continue;
+ }
+ else if (ret == DB_RUNRECOVERY) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit: txn_begin failed");
+ abort();
+ }
+ else {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit");
+ return ICAL_INTERNAL_ERROR;
+ }
+ }
+
+ /* first delete everything in the database, because there could be removed components */
+ if ((ret = dbp->cursor(dbp, tid, &dbcp, DB_DIRTY_READ)) != 0) {
+ tid->abort(tid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ retry++;
+ continue;
+ }
+ else if (ret == DB_RUNRECOVERY) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed");
+ abort();
+ }
+ else {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed");
+ /* leave bset->changed set to true */
+ return ICAL_INTERNAL_ERROR;
+ }
+ }
+
+ /* fetch the key/data pair, then delete it */
+ completed = 0;
+ while (!completed && !deadlocked) {
+ ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT);
+ if (ret == DB_NOTFOUND) {
+ completed = 1;
+ } else if (ret == ENOMEM) {
+ if (more_mem) free(more_mem);
+ more_mem = malloc(data.ulen+1024);
+ data.data = more_mem;
+ data.ulen = data.ulen+1024;
+ } else if (ret == DB_LOCK_DEADLOCK) {
+ deadlocked = 1;
+ } else if (ret == DB_RUNRECOVERY) {
+ tid->abort(tid);
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_get failed.");
+ abort();
+ } else if (ret == 0) {
+ if ((ret = dbcp->c_del(dbcp,0))!=0) {
+ dbp->err(dbp, ret, "cursor");
+ if (ret == DB_KEYEMPTY) {
+ /* never actually created, continue onward.. */
+ /* do nothing - break; */
+ } else if (ret == DB_LOCK_DEADLOCK) {
+ deadlocked = 1;
+ } else {
+ char *foo = db_strerror(ret);
+ abort();
+ }
+ }
+ } else { /* some other non-fatal error */
+ dbcp->c_close(dbcp);
+ tid->abort(tid);
+ if (more_mem) {
+ free(more_mem);
+ more_mem = NULL;
+ }
+ return ICAL_INTERNAL_ERROR;
+ }
+ }
+
+ if (more_mem) {
+ free(more_mem);
+ more_mem = NULL;
+ }
+
+ if (deadlocked) {
+ dbcp->c_close(dbcp);
+ tid->abort(tid);
+ retry++;
+ continue; /* next retry */
+ }
+
+ deadlocked = 0;
+ for (c = icalcomponent_get_first_component(bset->cluster,ICAL_ANY_COMPONENT);
+ c != 0 && !deadlocked;
+ c = icalcomponent_get_next_component(bset->cluster,ICAL_ANY_COMPONENT)) {
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ /* Note that we're always inserting into a primary index. */
+ if (icalcomponent_isa(c) != ICAL_VAGENDA_COMPONENT) {
+ char *uidstr = (char *)icalcomponent_get_uid(c);
+ if (!uidstr) { /* this shouldn't happen */
+ /* no uid string, we need to add one */
+ snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++);
+ key.data = uidbuf;
+ } else {
+ key.data = uidstr;
+ }
+ } else {
+ char *relcalid = NULL;
+ relcalid = (char*)icalcomponent_get_relcalid(c);
+ if (relcalid == NULL) {
+ snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++);
+ key.data = uidbuf;
+ } else {
+ key.data = relcalid;
+ }
+ }
+ key.size = strlen(key.data);
+
+ str = icalcomponent_as_ical_string(c);
+ data.data = str;
+ data.size = strlen(str);
+
+ if ((ret = dbcp->c_put(dbcp, &key, &data, DB_KEYLAST)) != 0) {
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlocked = 1;
+ }
+ else if (ret == DB_RUNRECOVERY) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed.");
+ abort();
+ }
+ else {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed %s.", str);
+ /* continue to try to put as many icalcomponent as possible */
+ reterr = ICAL_INTERNAL_ERROR;
+ }
+ }
+ }
+
+ if (deadlocked) {
+ dbcp->c_close(dbcp);
+ tid->abort(tid);
+ retry++;
+ continue;
+ }
+
+ if ((ret = dbcp->c_close(dbcp)) != 0) {
+ tid->abort(tid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ retry++;
+ continue;
+ }
+ else if (ret == DB_RUNRECOVERY) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed.");
+ abort();
+ }
+ else {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed.");
+ reterr = ICAL_INTERNAL_ERROR;
+ }
+ }
+
+ if ((ret = tid->commit(tid, 0)) != 0) {
+ tid->abort(tid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ retry++;
+ continue;
+ }
+ else if (ret == DB_RUNRECOVERY) {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed.");
+ abort();
+ }
+ else {
+ ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed.");
+ reterr = ICAL_INTERNAL_ERROR;
+ }
+ }
+
+ done = 1;
+ }
+
+ bset->changed = 0;
+ return reterr;
+}
+
+
+void icalbdbset_mark(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rv((bset!=0),"bset");
+
+ bset->changed = 1;
+}
+
+
+icalcomponent* icalbdbset_get_component(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ return bset->cluster;
+}
+
+
+/* manipulate the components in the cluster */
+
+icalerrorenum icalbdbset_add_component(icalset *set,
+ icalcomponent* child)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_re((bset!=0),"bset", ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
+
+ icalcomponent_add_component(bset->cluster,child);
+
+ icalbdbset_mark(set);
+
+ return ICAL_NO_ERROR;
+}
+
+
+icalerrorenum icalbdbset_remove_component(icalset *set,
+ icalcomponent* child)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_re((bset!=0),"bset", ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
+
+ icalcomponent_remove_component(bset->cluster,child);
+
+ icalbdbset_mark(set);
+
+ return ICAL_NO_ERROR;
+}
+
+
+int icalbdbset_count_components(icalset *set,
+ icalcomponent_kind kind)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+
+ if(set == 0){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return -1;
+ }
+
+ return icalcomponent_count_components(bset->cluster,kind);
+}
+
+
+/** Set the gauge **/
+
+icalerrorenum icalbdbset_select(icalset* set, icalgauge* gauge)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_re((bset!=0),"bset", ICAL_BADARG_ERROR);
+ icalerror_check_arg_re(gauge!=0,"gauge",ICAL_BADARG_ERROR);
+
+ bset->gauge = gauge;
+
+ return ICAL_NO_ERROR;
+}
+
+
+/** Clear the gauge **/
+
+void icalbdbset_clear(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rv((bset!=0),"bset");
+
+ bset->gauge = 0;
+}
+
+
+icalcomponent* icalbdbset_fetch(icalset* set, icalcomponent_kind kind, const char* uid)
+{
+ icalcompiter i;
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ for(i = icalcomponent_begin_component(bset->cluster, kind);
+ icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
+
+ icalcomponent *this = icalcompiter_deref(&i);
+ icalproperty *p = NULL;
+ const char *this_uid = NULL;
+
+ if (this != 0){
+ if (kind == ICAL_VAGENDA_COMPONENT) {
+ p = icalcomponent_get_first_property(this,ICAL_RELCALID_PROPERTY);
+ if (p != NULL) this_uid = icalproperty_get_relcalid(p);
+ } else {
+ p = icalcomponent_get_first_property(this,ICAL_UID_PROPERTY);
+ if (p != NULL) this_uid = icalproperty_get_uid(p);
+ }
+
+ if(this_uid==NULL){
+ icalerror_warn("icalbdbset_fetch found a component with no UID");
+ continue;
+ }
+
+ if (strcmp(uid,this_uid)==0){
+ return this;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+int icalbdbset_has_uid(icalset* store,const char* uid)
+{
+ assert(0); /* HACK, not implemented */
+ return 0;
+}
+
+
+/******* support routines for icalbdbset_fetch_match *********/
+
+struct icalbdbset_id {
+ char* uid;
+ char* recurrence_id;
+ int sequence;
+};
+
+void icalbdbset_id_free(struct icalbdbset_id *id)
+{
+ if(id->recurrence_id != 0){
+ free(id->recurrence_id);
+ }
+
+ if(id->uid != 0){
+ free(id->uid);
+ }
+
+}
+
+struct icalbdbset_id icalbdbset_get_id(icalcomponent* comp)
+{
+
+ icalcomponent *inner;
+ struct icalbdbset_id id;
+ icalproperty *p;
+
+ inner = icalcomponent_get_first_real_component(comp);
+
+ p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY);
+
+ assert(p!= 0);
+
+ id.uid = strdup(icalproperty_get_uid(p));
+
+ p = icalcomponent_get_first_property(inner, ICAL_SEQUENCE_PROPERTY);
+
+ if(p == 0) {
+ id.sequence = 0;
+ } else {
+ id.sequence = icalproperty_get_sequence(p);
+ }
+
+ p = icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY);
+
+ if (p == 0){
+ id.recurrence_id = 0;
+ } else {
+ icalvalue *v;
+ v = icalproperty_get_value(p);
+ id.recurrence_id = strdup(icalvalue_as_ical_string(v));
+
+ assert(id.recurrence_id != 0);
+ }
+
+ return id;
+}
+
+/* Find the component that is related to the given
+ component. Currently, it just matches based on UID and
+ RECURRENCE-ID */
+
+icalcomponent* icalbdbset_fetch_match(icalset* set, icalcomponent *comp)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalcompiter i;
+ struct icalbdbset_id comp_id, match_id;
+
+ icalerror_check_arg_rz((bset!=0),"bset");
+ comp_id = icalbdbset_get_id(comp);
+
+ for(i = icalcomponent_begin_component(bset->cluster,ICAL_ANY_COMPONENT);
+ icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
+
+ icalcomponent *match = icalcompiter_deref(&i);
+
+ match_id = icalbdbset_get_id(match);
+
+ if(strcmp(comp_id.uid, match_id.uid) == 0 &&
+ ( comp_id.recurrence_id ==0 ||
+ strcmp(comp_id.recurrence_id, match_id.recurrence_id) ==0 )){
+
+ /* HACK. What to do with SEQUENCE? */
+
+ icalbdbset_id_free(&match_id);
+ icalbdbset_id_free(&comp_id);
+ return match;
+
+ }
+
+ icalbdbset_id_free(&match_id);
+ }
+
+ icalbdbset_id_free(&comp_id);
+ return 0;
+
+}
+
+
+icalerrorenum icalbdbset_modify(icalset* set, icalcomponent *old,
+ icalcomponent *newc)
+{
+ assert(0); /* HACK, not implemented */
+ return ICAL_NO_ERROR;
+}
+
+/* caller is responsible to cal icalbdbset_free_cluster first */
+icalerrorenum icalbdbset_set_cluster(icalset* set, icalcomponent* cluster)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ bset->cluster = cluster;
+}
+
+icalerrorenum icalbdbset_free_cluster(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ if (bset->cluster != NULL) icalcomponent_free(bset->cluster);
+}
+
+icalcomponent* icalbdbset_get_cluster(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ return (bset->cluster);
+}
+
+
+/** Iterate through components. */
+icalcomponent* icalbdbset_get_current_component (icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ return icalcomponent_get_current_component(bset->cluster);
+}
+
+
+icalcomponent* icalbdbset_get_first_component(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalcomponent *c=0;
+
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ do {
+ if (c == 0)
+ c = icalcomponent_get_first_component(bset->cluster,
+ ICAL_ANY_COMPONENT);
+ else
+ c = icalcomponent_get_next_component(bset->cluster,
+ ICAL_ANY_COMPONENT);
+
+ if(c != 0 && (bset->gauge == 0 ||
+ icalgauge_compare(bset->gauge,c) == 1)){
+ return c;
+ }
+
+ } while (c!=0);
+
+ return 0;
+}
+
+
+icalsetiter icalbdbset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge, const char* tzid)
+{
+ icalsetiter itr = icalsetiter_null;
+ icalcomponent* comp = NULL;
+ icalcompiter citr;
+ icalbdbset *bset = (icalbdbset*) set;
+ struct icaltimetype start, next, end;
+ icalproperty *dtstart, *rrule, *prop, *due;
+ struct icalrecurrencetype recur;
+ icaltimezone *u_zone;
+ int g = 0;
+ int orig_time_was_utc = 0;
+
+ icalerror_check_arg_re((set!=0), "set", icalsetiter_null);
+
+ itr.gauge = gauge;
+ itr.tzid = tzid;
+
+ citr = icalcomponent_begin_component(bset->cluster, kind);
+ comp = icalcompiter_deref(&citr);
+
+ if (gauge == 0) {
+ itr.iter = citr;
+ return itr;
+ }
+
+ /* if there is a gauge, the first matched component is returned */
+ while (comp != 0) {
+
+ /* check if it is a recurring component and with guage expand, if so
+ * we need to add recurrence-id property to the given component */
+ rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
+ g = icalgauge_get_expand(gauge);
+
+ if (rrule != 0
+ && g == 1) {
+
+ /* it is a recurring event */
+
+ u_zone = icaltimezone_get_builtin_timezone(itr.tzid);
+
+ /* use UTC, if that's all we have. */
+ if (!u_zone)
+ u_zone = icaltimezone_get_utc_timezone();
+
+
+ recur = icalproperty_get_rrule(rrule);
+
+ if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) {
+ dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
+ if (dtstart)
+ start = icalproperty_get_dtstart(dtstart);
+ } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
+ due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
+ if (due)
+ start = icalproperty_get_due(due);
+ }
+
+ /* Convert to the user's timezone in order to be able to compare
+ * the results from the rrule iterator. */
+ if (icaltime_is_utc(start)) {
+ start = icaltime_convert_to_zone(start, u_zone);
+ orig_time_was_utc = 1;
+ }
+
+ if (itr.last_component == NULL) {
+ itr.ritr = icalrecur_iterator_new(recur, start);
+ next = icalrecur_iterator_next(itr.ritr);
+ itr.last_component = comp;
+ }
+ else {
+ next = icalrecur_iterator_next(itr.ritr);
+ if (icaltime_is_null_time(next)){
+ itr.last_component = NULL;
+ icalrecur_iterator_free(itr.ritr);
+ itr.ritr = NULL;
+ /* no matched occurence */
+ goto getNextComp;
+ } else {
+ itr.last_component = comp;
+ }
+ }
+
+ /* if it is excluded, do next one */
+ if (icalproperty_recurrence_is_excluded(comp, &start, &next)) {
+ icalrecur_iterator_decrement_count(itr.ritr);
+ continue;
+ }
+
+ /* add recurrence-id value to the property if the property already exist;
+ * add the recurrence id property and the value if the property does not exist */
+ prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY);
+ if (prop == 0)
+ icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next));
+ else
+ icalproperty_set_recurrenceid(prop, next);
+
+ /* convert the next recurrence time into the user's timezone */
+ if (orig_time_was_utc)
+ next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone());
+
+ } /* end of a recurring event */
+
+ if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) {
+ /* find a matched and return it */
+ itr.iter = citr;
+ return itr;
+ }
+
+ /* if it is a recurring but no matched occurrence has been found OR
+ * it is not a recurring and no matched component has been found,
+ * read the next component to find out */
+getNextComp:
+ if ((rrule != NULL && itr.last_component == NULL) ||
+ (rrule == NULL)) {
+ comp = icalcompiter_next(&citr);
+ comp = icalcompiter_deref(&citr);
+ }
+ } /* while */
+
+ /* no matched component has found */
+ return icalsetiter_null;
+}
+
+icalcomponent* icalbdbset_form_a_matched_recurrence_component(icalsetiter* itr)
+{
+ icalcomponent* comp = NULL;
+ struct icaltimetype start, next, end;
+ icalproperty *dtstart, *rrule, *prop, *due;
+ struct icalrecurrencetype recur;
+ icaltimezone *u_zone;
+ int g = 0;
+ int orig_time_was_utc = 0;
+
+ comp = itr->last_component;
+
+ if (comp == NULL || itr->gauge == NULL) {
+ return NULL;
+ }
+
+
+ rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
+ /* if there is no RRULE, simply return to the caller */
+ if (rrule == NULL)
+ return NULL;
+
+ u_zone = icaltimezone_get_builtin_timezone(itr->tzid);
+
+ /* use UTC, if that's all we have. */
+ if (!u_zone)
+ u_zone = icaltimezone_get_utc_timezone();
+
+ recur = icalproperty_get_rrule(rrule);
+
+ if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) {
+ dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
+ if (dtstart)
+ start = icalproperty_get_dtstart(dtstart);
+ } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
+ due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
+ if (due)
+ start = icalproperty_get_due(due);
+ }
+
+ /* Convert to the user's timezone in order to be able to compare the results
+ * from the rrule iterator. */
+ if (icaltime_is_utc(start)) {
+ start = icaltime_convert_to_zone(start, u_zone);
+ orig_time_was_utc = 1;
+ }
+
+ if (itr->ritr == NULL) {
+ itr->ritr = icalrecur_iterator_new(recur, start);
+ next = icalrecur_iterator_next(itr->ritr);
+ itr->last_component = comp;
+ } else {
+ next = icalrecur_iterator_next(itr->ritr);
+ if (icaltime_is_null_time(next)){
+ /* no more recurrence, returns */
+ itr->last_component = NULL;
+ icalrecur_iterator_free(itr->ritr);
+ itr->ritr = NULL;
+ /* no more pending matched occurence,
+ * all the pending matched occurences have been returned */
+ return NULL;
+ } else {
+ itr->last_component = comp;
+ }
+ }
+
+ /* if it is excluded, return NULL to the caller */
+ if (icalproperty_recurrence_is_excluded(comp, &start, &next)) {
+ icalrecur_iterator_decrement_count(itr->ritr);
+ return NULL;
+ }
+
+ /* set recurrence-id value to the property if the property already exist;
+ * add the recurrence id property and the value if the property does not exist */
+ prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY);
+ if (prop == 0)
+ icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next));
+ else
+ icalproperty_set_recurrenceid(prop, next);
+
+ if (orig_time_was_utc) {
+ next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone());
+ }
+
+
+ if (itr->gauge == 0 || icalgauge_compare(itr->gauge, comp) == 1) {
+ /* find a matched and return it */
+ return comp;
+ }
+
+ /* not matched */
+ return NULL;
+
+}
+
+icalcomponent* icalbdbsetiter_to_next(icalset *set, icalsetiter* i)
+{
+
+ icalcomponent* comp = NULL;
+ icalbdbset *bset = (icalbdbset*) set;
+ struct icaltimetype start, next, end;
+ icalproperty *dtstart, *rrule, *prop, *due;
+ struct icalrecurrencetype recur;
+ icaltimezone *u_zone;
+ int g = 0;
+ int orig_time_was_utc = 0;
+
+ do {
+
+ /* no pending occurence, read the next component */
+ if (i->last_component == NULL) {
+ comp = icalcompiter_next(&(i->iter));
+ }
+ else {
+ comp = i->last_component;
+ }
+
+ /* no next component, simply return */
+ if (comp == 0) return NULL;
+ if (i->gauge == 0) return comp;
+
+ /* finding the next matched component and return it to the caller */
+
+ rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
+ g = icalgauge_get_expand(i->gauge);
+
+ /* a recurring component with expand query */
+ if (rrule != 0
+ && g == 1) {
+
+ u_zone = icaltimezone_get_builtin_timezone(i->tzid);
+
+ /* use UTC, if that's all we have. */
+ if (!u_zone)
+ u_zone = icaltimezone_get_utc_timezone();
+
+ recur = icalproperty_get_rrule(rrule);
+
+ if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) {
+ dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
+ if (dtstart)
+ start = icalproperty_get_dtstart(dtstart);
+ } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
+ due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
+ if (due)
+ start = icalproperty_get_due(due);
+ }
+
+ /* Convert to the user's timezone in order to be able to compare
+ * the results from the rrule iterator. */
+ if (icaltime_is_utc(start)) {
+ start = icaltime_convert_to_zone(start, u_zone);
+ orig_time_was_utc = 1;
+ }
+
+ if (i->ritr == NULL) {
+ i->ritr = icalrecur_iterator_new(recur, start);
+ next = icalrecur_iterator_next(i->ritr);
+ i->last_component = comp;
+ } else {
+ next = icalrecur_iterator_next(i->ritr);
+ if (icaltime_is_null_time(next)) {
+ i->last_component = NULL;
+ icalrecur_iterator_free(i->ritr);
+ i->ritr = NULL;
+ /* no more occurence, should go to get next component */
+ continue;
+ } else {
+ i->last_component = comp;
+ }
+ }
+
+ /* if it is excluded, do next one */
+ if (icalproperty_recurrence_is_excluded(comp, &start, &next)) {
+ icalrecur_iterator_decrement_count(i->ritr);
+ continue;
+ }
+
+ /* set recurrence-id value to the property if the property already exist;
+ * add the recurrence id property and the value if the property does not exist */
+ prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY);
+ if (prop == 0)
+ icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next));
+ else
+ icalproperty_set_recurrenceid(prop, next);
+
+ if (orig_time_was_utc) {
+ next = icaltime_convert_to_zone(next, icaltimezone_get_utc_timezone());
+ }
+
+ } /* end of recurring event with expand query */
+
+ if(comp != 0 && (i->gauge == 0 ||
+ icalgauge_compare(i->gauge, comp) == 1)){
+ /* found a matched, return it */
+ return comp;
+ }
+ } while (comp != 0);
+
+ return 0;
+
+}
+
+icalcomponent* icalbdbset_get_next_component(icalset* set)
+{
+ icalbdbset *bset = (icalbdbset*)set;
+ icalcomponent *c=0;
+
+ struct icaltimetype start, next;
+ icalproperty *dtstart, *rrule, *prop, *due;
+ struct icalrecurrencetype recur;
+ int g = 0;
+
+ icalerror_check_arg_rz((bset!=0),"bset");
+
+ do {
+ c = icalcomponent_get_next_component(bset->cluster,
+ ICAL_ANY_COMPONENT);
+ if(c != 0 && (bset->gauge == 0 ||
+ icalgauge_compare(bset->gauge,c) == 1)){
+ return c;
+ }
+
+ } while(c != 0);
+
+ return 0;
+}
+
+int icalbdbset_begin_transaction(DB_TXN* parent_tid, DB_TXN** tid)
+{
+ return (ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, parent_tid, tid, 0));
+}
+
+int icalbdbset_commit_transaction(DB_TXN* txnid)
+{
+ return (txnid->commit(txnid, 0));
+}
+
+
+static int _compare_keys(DB *dbp, const DBT *a, const DBT *b)
+{
+/*
+ * Returns:
+ * < 0 if a < b
+ * = 0 if a = b
+ * > 0 if a > b
+ */
+
+ char* ac = (char*)a->data;
+ char* bc = (char*)b->data;
+ return (strncmp(ac, bc, a->size));
+}
+
+
+
diff --git a/libical/src/libicalss/icalbdbset.h b/libical/src/libicalss/icalbdbset.h
new file mode 100644
index 0000000000..c5c835fae3
--- /dev/null
+++ b/libical/src/libicalss/icalbdbset.h
@@ -0,0 +1,147 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalbdbset.h
+ CREATOR: dml 12 December 2001
+ (C) COPYRIGHT 2001, Critical Path
+
+ $Id$
+ $Locker$
+======================================================================*/
+
+#ifndef ICALBDBSET_H
+#define ICALBDBSET_H
+
+#include "ical.h"
+#include "icalset.h"
+#include "icalgauge.h"
+#include <db.h>
+
+typedef struct icalbdbset_impl icalbdbset;
+
+enum icalbdbset_subdb_type {ICALBDB_CALENDARS, ICALBDB_EVENTS, ICALBDB_TODOS, ICALBDB_REMINDERS};
+typedef enum icalbdbset_subdb_type icalbdbset_subdb_type;
+
+/** sets up the db environment, should be done in parent thread.. */
+int icalbdbset_init_dbenv(char *db_env_dir, void (*logDbFunc)(const char*, char*));
+
+icalset* icalbdbset_init(icalset* set, const char *dsn, void *options);
+int icalbdbset_cleanup(void);
+void icalbdbset_checkpoint(void);
+void icalbdbset_rmdbLog(void);
+
+/** Creates a component handle. flags allows caller to
+ specify if database is internally a BTREE or HASH */
+icalset * icalbdbset_new(const char* database_filename,
+ icalbdbset_subdb_type subdb_type,
+ int dbtype, int flag);
+
+DB * icalbdbset_bdb_open_secondary(DB *dbp,
+ const char *subdb,
+ const char *sindex,
+ int (*callback) (DB *db,
+ const DBT *dbt1,
+ const DBT *dbt2,
+ DBT *dbt3),
+ int type);
+
+char *icalbdbset_parse_data(DBT *dbt, char *(*pfunc)(const DBT *dbt)) ;
+
+void icalbdbset_free(icalset* set);
+
+/* cursor operations */
+int icalbdbset_acquire_cursor(DB *dbp, DB_TXN* tid, DBC **rdbcp);
+int icalbdbset_cget(DBC *dbcp, DBT *key, DBT *data, int access_method);
+int icalbdbset_cput(DBC *dbcp, DBT *key, DBT *data, int access_method);
+
+int icalbdbset_get_first(DBC *dbcp, DBT *key, DBT *data);
+int icalbdbset_get_next(DBC *dbcp, DBT *key, DBT *data);
+int icalbdbset_get_last(DBC *dbcp, DBT *key, DBT *data);
+int icalbdbset_get_key(DBC *dbcp, DBT *key, DBT *data);
+int icalbdbset_delete(DB *dbp, DBT *key);
+int icalbdbset_put(DB *dbp, DBT *key, DBT *data, int access_method);
+int icalbdbset_get(DB *dbp, DB_TXN *tid, DBT *key, DBT *data, int flags);
+
+const char* icalbdbset_path(icalset* set);
+const char* icalbdbset_subdb(icalset* set);
+
+/* Mark the set as changed, so it will be written to disk when it
+ is freed. Commit writes to disk immediately. */
+void icalbdbset_mark(icalset* set);
+icalerrorenum icalbdbset_commit(icalset *set);
+
+icalerrorenum icalbdbset_add_component(icalset* set,
+ icalcomponent* child);
+
+icalerrorenum icalbdbset_remove_component(icalset* set,
+ icalcomponent* child);
+
+int icalbdbset_count_components(icalset* set,
+ icalcomponent_kind kind);
+
+/* Restrict the component returned by icalbdbset_first, _next to those
+ that pass the gauge. _clear removes the gauge */
+icalerrorenum icalbdbset_select(icalset* store, icalgauge* gauge);
+void icalbdbset_clear(icalset* store);
+
+/* Get and search for a component by uid */
+icalcomponent* icalbdbset_fetch(icalset* set, icalcomponent_kind kind, const char* uid);
+int icalbdbset_has_uid(icalset* set, const char* uid);
+icalcomponent* icalbdbset_fetch_match(icalset* set, icalcomponent *c);
+
+
+icalerrorenum icalbdbset_modify(icalset* set, icalcomponent *old,
+ icalcomponent *newc);
+
+/* cluster management functions */
+icalerrorenum icalbdbset_set_cluster(icalset* set, icalcomponent* cluster);
+icalerrorenum icalbdbset_free_cluster(icalset* set);
+icalcomponent* icalbdbset_get_cluster(icalset* set);
+
+/* Iterate through components. If a gauge has been defined, these
+ will skip over components that do not pass the gauge */
+
+icalcomponent* icalbdbset_get_current_component (icalset* set);
+icalcomponent* icalbdbset_get_first_component(icalset* set);
+icalcomponent* icalbdbset_get_next_component(icalset* set);
+
+/* External iterator for thread safety */
+icalsetiter icalbdbset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge, const char* tzid);
+
+icalcomponent* icalbdbset_form_a_matched_recurrence_component(icalsetiter* itr);
+
+icalcomponent* icalbdbsetiter_to_next(icalset* set, icalsetiter* i);
+icalcomponent* icalbdbsetiter_to_prior(icalset* set, icalsetiter* i);
+
+/* Return a reference to the internal component. You probably should
+ not be using this. */
+
+icalcomponent* icalbdbset_get_component(icalset* set);
+
+DB_ENV *icalbdbset_get_env(void);
+
+
+int icalbdbset_begin_transaction(DB_TXN* parent_id, DB_TXN** txnid);
+int icalbdbset_commit_transaction(DB_TXN* txnid);
+
+DB* icalbdbset_bdb_open(const char* path,
+ const char *subdb,
+ int type,
+ mode_t mode, int flag);
+
+
+typedef struct icalbdbset_options {
+ icalbdbset_subdb_type subdb; /**< the subdatabase to open */
+ int dbtype; /**< db_open type: DB_HASH | DB_BTREE */
+ mode_t mode; /**< file mode */
+ u_int32_t flag; /**< DB->set_flags(): DB_DUP | DB_DUPSORT */
+ char *(*pfunc)(const DBT *dbt); /**< parsing function */
+ int (*callback) (DB *db, /**< callback for secondary db open */
+ const DBT *dbt1,
+ const DBT *dbt2,
+ DBT *dbt3);
+} icalbdbset_options;
+
+#endif /* !ICALBDBSET_H */
+
+
+
diff --git a/libical/src/libicalss/icalbdbset_cxx.h b/libical/src/libicalss/icalbdbset_cxx.h
new file mode 100644
index 0000000000..678adaa299
--- /dev/null
+++ b/libical/src/libicalss/icalbdbset_cxx.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalbdbset_cxx.h
+ CREATOR: dml 12/12/01
+ (C) COPYRIGHT 2001, Critical Path
+======================================================================*/
+
+#ifndef ICALBDBSET_CXX_H
+#define ICALBDBSET_CXX_H
+
+
+extern "C" {
+#include "ical.h"
+#include "icalgauge.h"
+}
+
+#include "vcomponent.h"
+#include <db_cxx.h>
+
+typedef char* string; // Will use the string library from STL
+
+class ICalBDBSet {
+public:
+
+ ICalBDBSet();
+ ICalBDBSet(const ICalBDBSet&);
+ ICalBDBSet operator=(const ICalBDBSet &);
+ ~ICalBDBSet();
+
+ ICalBDBSet(const string& path, int flags);
+
+public:
+
+ void free();
+ string path();
+
+ icalerrorenum add_component(VComponent* child);
+ icalerrorenum remove_component(VComponent* child);
+ int count_components(icalcomponent_kind kind);
+
+ // Restrict the component returned by icalbdbset_first, _next to those
+ // that pass the gauge. _clear removes the gauge
+ icalerrorenum select(icalgauge *gauge);
+ void clear();
+
+ // Get and search for a component by uid
+ VComponent* fetch(string &uid);
+ VComponent* fetch_match(icalcomponent *c);
+ int has_uid(string &uid);
+
+ // Iterate through components. If a guage has been defined, these
+ // will skip over components that do not pass the gauge
+ VComponent* get_current_component();
+ VComponent* get_first_component();
+ VComponent* get_next_component();
+
+ VComponent* get_component();
+
+};
+
+#endif
diff --git a/libical/src/libicalss/icalbdbsetimpl.h b/libical/src/libicalss/icalbdbsetimpl.h
new file mode 100644
index 0000000000..281a4834d4
--- /dev/null
+++ b/libical/src/libicalss/icalbdbsetimpl.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalbdbsetimpl.h
+ CREATOR: dml 12 December 2001
+ (C) COPYRIGHT 2001, Critical Path
+
+ $Id$
+ $Locker$
+ ======================================================================*/
+
+#ifndef ICALBDBSETIMPL_H
+#define ICALBDBSETIMPL_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "icalgauge.h"
+#include <db.h>
+
+/* 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 icalbdbset_impl {
+ icalset super; /**< parent class */
+ const char *path;
+ const char *subdb;
+ const char *sindex;
+ const char *key;
+ void *data;
+ int datasize;
+ int changed;
+ icalcomponent* cluster;
+ icalgauge* gauge;
+ DB_ENV *dbenv;
+ DB *dbp;
+ DB *sdbp;
+ DBC *dbcp;
+};
+
+#endif
diff --git a/libical/src/libicalss/icalcalendar.c b/libical/src/libicalss/icalcalendar.c
index e63b5330ad..1f24f88db6 100644
--- a/libical/src/libicalss/icalcalendar.c
+++ b/libical/src/libicalss/icalcalendar.c
@@ -34,7 +34,16 @@
#include <sys/stat.h> /* For mkdir, stat */
#include <sys/types.h> /* For mkdir */
#include <fcntl.h> /* For mkdir */
+
+#ifndef WIN32
#include <unistd.h> /* For mkdir, stat */
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 512
+#endif
+
+
#include <stdlib.h> /* for malloc */
#include <string.h> /* for strcat */
#include <errno.h>
@@ -47,13 +56,13 @@
struct icalcalendar_impl
{
char* dir;
- icalcomponent* freebusy;
- icalcomponent* properties;
+ icalset* freebusy;
+ icalset* properties;
icalset* booked;
icalset* incoming;
};
-struct icalcalendar_impl* icalcalendar_new_impl()
+struct icalcalendar_impl* icalcalendar_new_impl(void)
{
struct icalcalendar_impl* impl;
@@ -119,29 +128,26 @@ icalcalendar* icalcalendar_new(char* dir)
return impl;
}
-void icalcalendar_free(icalcalendar* calendar)
+void icalcalendar_free(icalcalendar* impl)
{
-
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
-
if (impl->dir !=0){
free(impl->dir);
}
if (impl->freebusy !=0){
- icalfileset_free(impl->freebusy);
+ icalset_free(impl->booked);
}
if (impl->properties !=0){
- icalfileset_free(impl->properties);
+ icalset_free(impl->properties);
}
if (impl->booked !=0){
- icaldirset_free(impl->booked);
+ icalset_free(impl->booked);
}
if (impl->incoming !=0){
- icaldirset_free(impl->incoming);
+ icalset_free(impl->incoming);
}
impl->dir = 0;
@@ -155,37 +161,32 @@ void icalcalendar_free(icalcalendar* calendar)
}
-int icalcalendar_lock(icalcalendar* calendar)
+int icalcalendar_lock(icalcalendar* impl)
{
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
icalerror_check_arg_rz((impl != 0),"impl");
return 0;
}
-int icalcalendar_unlock(icalcalendar* calendar)
+int icalcalendar_unlock(icalcalendar* impl)
{
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
icalerror_check_arg_rz((impl != 0),"impl");
return 0;
}
-int icalcalendar_islocked(icalcalendar* calendar)
+int icalcalendar_islocked(icalcalendar* impl)
{
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
icalerror_check_arg_rz((impl != 0),"impl");
return 0;
}
-int icalcalendar_ownlock(icalcalendar* calendar)
+int icalcalendar_ownlock(icalcalendar* impl)
{
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
icalerror_check_arg_rz((impl != 0),"impl");
return 0;
}
-icalset* icalcalendar_get_booked(icalcalendar* calendar)
+icalset* icalcalendar_get_booked(icalcalendar* impl)
{
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
char dir[PATH_MAX];
icalerror_check_arg_rz((impl != 0),"impl");
@@ -205,10 +206,9 @@ icalset* icalcalendar_get_booked(icalcalendar* calendar)
}
-icalset* icalcalendar_get_incoming(icalcalendar* calendar)
+icalset* icalcalendar_get_incoming(icalcalendar* impl)
{
char path[PATH_MAX];
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
icalerror_check_arg_rz((impl != 0),"impl");
path[0] = '\0';
@@ -223,10 +223,9 @@ icalset* icalcalendar_get_incoming(icalcalendar* calendar)
return impl->properties;
}
-icalset* icalcalendar_get_properties(icalcalendar* calendar)
+icalset* icalcalendar_get_properties(icalcalendar* impl)
{
char path[PATH_MAX];
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
icalerror_check_arg_rz((impl != 0),"impl");
path[0] = '\0';
@@ -241,10 +240,9 @@ icalset* icalcalendar_get_properties(icalcalendar* calendar)
return impl->properties;
}
-icalset* icalcalendar_get_freebusy(icalcalendar* calendar)
+icalset* icalcalendar_get_freebusy(icalcalendar* impl)
{
char path[PATH_MAX];
- struct icalcalendar_impl *impl = (struct icalcalendar_impl*)calendar;
icalerror_check_arg_rz((impl != 0),"impl");
path[0] = '\0';
diff --git a/libical/src/libicalss/icalcalendar.h b/libical/src/libicalss/icalcalendar.h
index f07457c60d..2a0c15196a 100644
--- a/libical/src/libicalss/icalcalendar.h
+++ b/libical/src/libicalss/icalcalendar.h
@@ -38,7 +38,7 @@
* components. It also has interfaces to access the free/busy list
* and a list of calendar properties */
-typedef void icalcalendar;
+typedef struct icalcalendar_impl icalcalendar;
icalcalendar* icalcalendar_new(char* dir);
diff --git a/libical/src/libicalss/icalcaputil.h b/libical/src/libicalss/icalcaputil.h
new file mode 100644
index 0000000000..4f9bcb31c4
--- /dev/null
+++ b/libical/src/libicalss/icalcaputil.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalutil.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/
+
+
+ =========================================================================*/
+
+
+/* Create new components that have a form suitable for the various
+ iTIP trasactions */
+
+/* Scheduling commands */
+icalcomponent* icalcaputil_new_accept_reply(icalcomponent* comp, char* calid);
+icalcomponent* icalcaputil_new_decline_reply(icalcomponent* comp, char* calid);
+icalcomponent* icalcaputil_new_refresh(icalcomponent* comp, char* calid);
+icalcomponent* icalcaputil_new_cancel(icalcomponent* comp);
+icalcomponent* icalcaputil_new_counter(icalcomponent* comp);
+icalcomponent* icalcaputil_new_declinecounter(icalcomponent* comp);
+
+/* Calendaring commands */
+icalcomponent* icalcaputil_new_create();
+icalcomponent* icalcaputil_new_delete();
+icalcomponent* icalcaputil_new_modify();
+icalerrorenum* icalcaputil_modify_add_old_prop(icalcomponent* c,
+ icalproperty *p);
+icalerrorenum* icalcaputil_modify_add_new_prop(icalcomponent* c,
+ icalproperty *p);
+icalerrorenum* icalcaputil_add_query(icalcomponent* c, char* str);
+
+
+icalcomponent* icalcaputil_new_move();
+icalcomponent* icalcaputil_new_read();
+
+icalerrorenum icalcaputil_add_target(icalcomponent* comp,char* target);
+icalerrorenum icalcaputil_add_to_vcar(icalcomponent* comp,char* target);
+
+
+
+
+
diff --git a/libical/src/libicalss/icalclassify.c b/libical/src/libicalss/icalclassify.c
index ad2d6d6fd8..61ddbd3a76 100644
--- a/libical/src/libicalss/icalclassify.c
+++ b/libical/src/libicalss/icalclassify.c
@@ -29,6 +29,7 @@
#include "ical.h"
#include "icalclassify.h"
#include "icalmemory.h"
+
#include <ctype.h> /* For tolower() */
#include <string.h> /* for index() */
#include <stdlib.h> /* for malloc and free */
@@ -36,15 +37,16 @@
struct icalclassify_parts {
- icalcomponent *c;
- icalproperty_method method;
- char* organizer;
- icalparameter_partstat reply_partstat;
- char* reply_attendee;
- char* uid;
- int sequence;
- struct icaltimetype dtstamp;
- struct icaltimetype recurrence_id;
+ icalcomponent *c;
+ icalcomponent_kind inner_kind;
+ icalproperty_method method;
+ char* organizer;
+ icalparameter_partstat reply_partstat;
+ char* reply_attendee;
+ char* uid;
+ int sequence;
+ struct icaltimetype dtstamp;
+ struct icaltimetype recurrence_id;
};
@@ -121,27 +123,48 @@ icalproperty* icalclassify_find_attendee(icalcomponent *c,
const char* attendee)
{
icalproperty *p;
- char* lattendee = icalclassify_lowercase(attendee);
- char* upn = strchr(lattendee,':');
- icalcomponent *inner = icalcomponent_get_first_real_component(c);
+ icalcomponent* inner;
+ char* lattendee;
+ char* upn;
+
+ if(attendee == 0){
+ return 0;
+ }
+
+ lattendee = icalclassify_lowercase(attendee);
+ upn = strchr(lattendee,':');
+
+ if (upn== 0){
+ upn = lattendee;
+ } else {
+ upn++; /* skip the ";"*/
+ }
+
+ inner = icalcomponent_get_first_real_component(c);
for(p = icalcomponent_get_first_property(inner,ICAL_ATTENDEE_PROPERTY);
p != 0;
p = icalcomponent_get_next_property(inner,ICAL_ATTENDEE_PROPERTY))
{
- const char* this_attendee
+ char* this_attendee
= icalclassify_lowercase(icalproperty_get_attendee(p));
char* this_upn = strchr(this_attendee,':');
if(this_upn == 0){
continue;
- }
+ } else {
+ this_upn++;
+ }
if(strcmp(this_upn,upn)==0){
+ free(lattendee);
+ free(this_attendee);
return p;
}
+ free(this_attendee);
}
+ free(lattendee);
return 0;
@@ -191,6 +214,8 @@ void icalssutil_get_parts(icalcomponent* c,
inner = icalcomponent_get_first_real_component(c);
+ parts->inner_kind = icalcomponent_isa(inner);
+
p = icalcomponent_get_first_property(inner,ICAL_ORGANIZER_PROPERTY);
if(p!=0){
parts->organizer = strdup(icalproperty_get_organizer(p));
@@ -263,7 +288,7 @@ int icalssutil_is_rescheduled(icalcomponent* a,icalcomponent* b)
p1 = icalcomponent_get_first_property(i1,kind_array[i]);
p2 = icalcomponent_get_first_property(i2,kind_array[i]);
- if( (p1!=0)^(p1!=0) ){
+ if( (p1!=0)^(p2!=0) ){
/* Return true if the property exists in one component and not
the other */
return 1;
@@ -293,7 +318,7 @@ int icalclassify_publish_new(struct icalclassify_parts *comp,
icalclassify_pre;
if(comp->method == ICAL_METHOD_PUBLISH &&
- match == 0){
+ match == 0 && comp->inner_kind != ICAL_VFREEBUSY_COMPONENT){
rtrn = 1;
}
@@ -308,7 +333,7 @@ int icalclassify_publish_update(struct icalclassify_parts *comp,
icalclassify_pre;
if(comp->method == ICAL_METHOD_PUBLISH &&
- match !=0 ){
+ match !=0 && comp->inner_kind != ICAL_VFREEBUSY_COMPONENT){
rtrn = 1;
}
@@ -323,7 +348,7 @@ int icalclassify_publish_freebusy(struct icalclassify_parts *comp,
icalclassify_pre;
if(comp->method == ICAL_METHOD_PUBLISH &&
- match == 0){
+ comp->inner_kind == ICAL_VFREEBUSY_COMPONENT){
rtrn = 1;
}
@@ -392,11 +417,19 @@ int icalclassify_request_delegate(
struct icalclassify_parts *match,
const char* user)
{
- icalclassify_pre
+ icalproperty* attendee;
+ icalparameter* param;
+ icalclassify_pre;
- if (match->c != 0 &&
- comp->sequence > match->sequence &&
- icalssutil_is_rescheduled(comp->c,match->c)){
+ attendee = icalclassify_find_attendee(comp->c,user);
+
+ if(attendee == 0){
+ return 0;
+ }
+
+ param = icalproperty_get_first_parameter(attendee,ICAL_DELEGATEDFROM_PARAMETER);
+
+ if (param != 0){
rtrn = 1;
}
@@ -411,7 +444,7 @@ int icalclassify_request_new_organizer(
{
/* Organizer has changed between match and component */
icalclassify_pre
-
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
icalclassify_post
}
@@ -422,6 +455,7 @@ int icalclassify_request_status(
const char* user)
{
icalclassify_pre
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
icalclassify_post
}
@@ -431,6 +465,7 @@ int icalclassify_request_forward(
const char* user)
{
icalclassify_pre
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
icalclassify_post
}
@@ -440,6 +475,7 @@ int icalclassify_request_freebusy(
const char* user)
{
icalclassify_pre
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
icalclassify_post
}
@@ -477,6 +513,22 @@ int icalclassify_reply_decline(
}
icalclassify_post
}
+int icalclassify_reply_delegate(
+ struct icalclassify_parts *comp,
+ struct icalclassify_parts *match,
+ const char* user)
+{
+ icalproperty* attendee;
+ icalclassify_pre;
+
+ attendee = icalclassify_find_attendee(match->c,comp->reply_attendee);
+
+ if( attendee != 0 &&
+ comp->reply_partstat == ICAL_PARTSTAT_DELEGATED){
+ rtrn = 1;
+ }
+ icalclassify_post
+}
int icalclassify_reply_crasher_accept(
struct icalclassify_parts *comp,
struct icalclassify_parts *match,
@@ -498,7 +550,6 @@ int icalclassify_reply_crasher_decline(
struct icalclassify_parts *match,
const char* user)
{
- icalparameter_partstat partstat;
icalproperty* attendee;
icalclassify_pre;
@@ -594,45 +645,47 @@ int icalclassify_delinecounter(
struct icalclassify_map {
icalproperty_method method;
int (*fn)(struct icalclassify_parts *comp,struct icalclassify_parts *match, const char* user);
- ical_class class;
+ icalproperty_xlicclass class;
} icalclassify_map[] =
-{ {ICAL_METHOD_PUBLISH,icalclassify_publish_new,ICAL_PUBLISH_NEW_CLASS},
- {ICAL_METHOD_PUBLISH,icalclassify_publish_update,ICAL_PUBLISH_UPDATE_CLASS},
- {ICAL_METHOD_PUBLISH,icalclassify_publish_freebusy,ICAL_PUBLISH_FREEBUSY_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_new,ICAL_REQUEST_NEW_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_update,ICAL_REQUEST_UPDATE_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_reschedule,ICAL_REQUEST_RESCHEDULE_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_delegate,ICAL_REQUEST_DELEGATE_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_new_organizer,ICAL_REQUEST_NEW_ORGANIZER_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_forward,ICAL_REQUEST_FORWARD_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_status,ICAL_REQUEST_STATUS_CLASS},
- {ICAL_METHOD_REQUEST,icalclassify_request_freebusy,ICAL_REQUEST_FREEBUSY_CLASS},
-
- {ICAL_METHOD_REPLY,icalclassify_reply_accept,ICAL_REPLY_ACCEPT_CLASS},
- {ICAL_METHOD_REPLY,icalclassify_reply_decline,ICAL_REPLY_DECLINE_CLASS},
- {ICAL_METHOD_REPLY,icalclassify_reply_crasher_accept,ICAL_REPLY_CRASHER_ACCEPT_CLASS},
- {ICAL_METHOD_REPLY,icalclassify_reply_crasher_decline,ICAL_REPLY_CRASHER_DECLINE_CLASS},
-
- {ICAL_METHOD_ADD,icalclassify_add_instance,ICAL_ADD_INSTANCE_CLASS},
-
- {ICAL_METHOD_CANCEL,icalclassify_cancel_event,ICAL_CANCEL_EVENT_CLASS},
- {ICAL_METHOD_CANCEL,icalclassify_cancel_instance,ICAL_CANCEL_INSTANCE_CLASS},
- {ICAL_METHOD_CANCEL,icalclassify_cancel_all,ICAL_CANCEL_ALL_CLASS},
-
- {ICAL_METHOD_REFRESH,icalclassify_refesh,ICAL_REFRESH_CLASS},
- {ICAL_METHOD_COUNTER,icalclassify_counter,ICAL_COUNTER_CLASS},
- {ICAL_METHOD_DECLINECOUNTER,icalclassify_delinecounter,ICAL_DECLINECOUNTER_CLASS},
- {ICAL_METHOD_NONE,0,ICAL_NO_CLASS}
+{ {ICAL_METHOD_PUBLISH,icalclassify_publish_new,ICAL_XLICCLASS_PUBLISHNEW},
+ {ICAL_METHOD_PUBLISH,icalclassify_publish_update,ICAL_XLICCLASS_PUBLISHUPDATE},
+ {ICAL_METHOD_PUBLISH,icalclassify_publish_freebusy,ICAL_XLICCLASS_PUBLISHFREEBUSY},
+ {ICAL_METHOD_REQUEST,icalclassify_request_delegate,ICAL_XLICCLASS_REQUESTDELEGATE},
+ {ICAL_METHOD_REQUEST,icalclassify_request_new,ICAL_XLICCLASS_REQUESTNEW},
+ {ICAL_METHOD_REQUEST,icalclassify_request_update,ICAL_XLICCLASS_REQUESTUPDATE},
+ {ICAL_METHOD_REQUEST,icalclassify_request_reschedule,ICAL_XLICCLASS_REQUESTRESCHEDULE},
+
+ {ICAL_METHOD_REQUEST,icalclassify_request_new_organizer,ICAL_XLICCLASS_REQUESTNEWORGANIZER},
+ {ICAL_METHOD_REQUEST,icalclassify_request_forward,ICAL_XLICCLASS_REQUESTFORWARD},
+ {ICAL_METHOD_REQUEST,icalclassify_request_status,ICAL_XLICCLASS_REQUESTSTATUS},
+ {ICAL_METHOD_REQUEST,icalclassify_request_freebusy,ICAL_XLICCLASS_REQUESTFREEBUSY},
+
+ {ICAL_METHOD_REPLY,icalclassify_reply_accept,ICAL_XLICCLASS_REPLYACCEPT},
+ {ICAL_METHOD_REPLY,icalclassify_reply_decline,ICAL_XLICCLASS_REPLYDECLINE},
+ {ICAL_METHOD_REPLY,icalclassify_reply_delegate,ICAL_XLICCLASS_REPLYDELEGATE},
+ {ICAL_METHOD_REPLY,icalclassify_reply_crasher_accept,ICAL_XLICCLASS_REPLYCRASHERACCEPT},
+ {ICAL_METHOD_REPLY,icalclassify_reply_crasher_decline,ICAL_XLICCLASS_REPLYCRASHERDECLINE},
+
+ {ICAL_METHOD_ADD,icalclassify_add_instance,ICAL_XLICCLASS_ADDINSTANCE},
+
+ {ICAL_METHOD_CANCEL,icalclassify_cancel_event,ICAL_XLICCLASS_CANCELEVENT},
+ {ICAL_METHOD_CANCEL,icalclassify_cancel_instance,ICAL_XLICCLASS_CANCELINSTANCE},
+ {ICAL_METHOD_CANCEL,icalclassify_cancel_all,ICAL_XLICCLASS_CANCELALL},
+
+ {ICAL_METHOD_REFRESH,icalclassify_refesh,ICAL_XLICCLASS_REFRESH},
+ {ICAL_METHOD_COUNTER,icalclassify_counter,ICAL_XLICCLASS_COUNTER},
+ {ICAL_METHOD_DECLINECOUNTER,icalclassify_delinecounter,ICAL_XLICCLASS_DECLINECOUNTER},
+ {ICAL_METHOD_NONE,0,ICAL_XLICCLASS_NONE}
};
-ical_class icalclassify(icalcomponent* c,icalcomponent* match,
+icalproperty_xlicclass icalclassify(icalcomponent* c,icalcomponent* match,
const char* user)
{
icalcomponent *inner;
icalproperty *p;
icalproperty_method method;
- ical_class class = ICAL_UNKNOWN_CLASS;
+ icalproperty_xlicclass class = ICAL_XLICCLASS_UNKNOWN;
int i;
@@ -642,7 +695,7 @@ ical_class icalclassify(icalcomponent* c,icalcomponent* match,
inner = icalcomponent_get_first_real_component(c);
if (inner == 0) {
- return ICAL_NO_CLASS;
+ return ICAL_XLICCLASS_NONE;
}
icalssutil_get_parts(c,&comp_parts);
@@ -659,7 +712,8 @@ ical_class icalclassify(icalcomponent* c,icalcomponent* match,
icaltime_compare(comp_parts.dtstamp,match_parts.dtstamp)>0)
{
/* comp has a smaller sequence and a later DTSTAMP */
- return ICAL_MISSEQUENCED_CLASS;
+ class = ICAL_XLICCLASS_MISSEQUENCED;
+ goto CLEANUP;
}
if( (comp_parts.sequence<match_parts.sequence )
@@ -668,14 +722,16 @@ ical_class icalclassify(icalcomponent* c,icalcomponent* match,
( comp_parts.sequence == match_parts.sequence &&
icaltime_compare(comp_parts.dtstamp,match_parts.dtstamp)<=0)){
- return ICAL_OBSOLETE_CLASS;
+ class = ICAL_XLICCLASS_OBSOLETE;
+ goto CLEANUP;
}
}
p = icalcomponent_get_first_property(c,ICAL_METHOD_PROPERTY);
if (p == 0) {
- return ICAL_UNKNOWN_CLASS;
+ class = ICAL_XLICCLASS_UNKNOWN;
+ goto CLEANUP;
}
method = icalproperty_get_method(p);
@@ -688,9 +744,11 @@ ical_class icalclassify(icalcomponent* c,icalcomponent* match,
}
}
+CLEANUP:
icalssutil_free_parts(&comp_parts);
icalssutil_free_parts(&match_parts);
return class;
}
+
diff --git a/libical/src/libicalss/icalclassify.h b/libical/src/libicalss/icalclassify.h
index ae76434378..aceabc0a20 100644
--- a/libical/src/libicalss/icalclassify.h
+++ b/libical/src/libicalss/icalclassify.h
@@ -29,42 +29,14 @@
#include "ical.h"
#include "icalset.h"
-
-typedef enum icalclass {
- ICAL_NO_CLASS,
- ICAL_PUBLISH_NEW_CLASS,
- ICAL_PUBLISH_UPDATE_CLASS,
- ICAL_PUBLISH_FREEBUSY_CLASS,
- ICAL_REQUEST_NEW_CLASS,
- ICAL_REQUEST_UPDATE_CLASS,
- ICAL_REQUEST_RESCHEDULE_CLASS,
- ICAL_REQUEST_DELEGATE_CLASS,
- ICAL_REQUEST_NEW_ORGANIZER_CLASS,
- ICAL_REQUEST_FORWARD_CLASS,
- ICAL_REQUEST_STATUS_CLASS,
- ICAL_REQUEST_FREEBUSY_CLASS,
- ICAL_REPLY_ACCEPT_CLASS,
- ICAL_REPLY_DECLINE_CLASS,
- ICAL_REPLY_CRASHER_ACCEPT_CLASS,
- ICAL_REPLY_CRASHER_DECLINE_CLASS,
- ICAL_ADD_INSTANCE_CLASS,
- ICAL_CANCEL_EVENT_CLASS,
- ICAL_CANCEL_INSTANCE_CLASS,
- ICAL_CANCEL_ALL_CLASS,
- ICAL_REFRESH_CLASS,
- ICAL_COUNTER_CLASS,
- ICAL_DECLINECOUNTER_CLASS,
- ICAL_MALFORMED_CLASS,
- ICAL_OBSOLETE_CLASS, /* 21 */
- ICAL_MISSEQUENCED_CLASS, /* 22 */
- ICAL_UNKNOWN_CLASS /* 23 */
-} ical_class;
-
-ical_class icalclassify(icalcomponent* c,icalcomponent* match,
+icalproperty_xlicclass icalclassify(icalcomponent* c,icalcomponent* match,
const char* user);
icalcomponent* icalclassify_find_overlaps(icalset* set, icalcomponent* comp);
+char* icalclassify_class_to_string(icalproperty_xlicclass c);
+
+
#endif /* ICALCLASSIFY_H*/
diff --git a/libical/src/libicalss/icalcluster.c b/libical/src/libicalss/icalcluster.c
new file mode 100644
index 0000000000..6d11078a72
--- /dev/null
+++ b/libical/src/libicalss/icalcluster.c
@@ -0,0 +1,245 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalcluster.c
+ CREATOR: acampi 13 March 2002
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2002, 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
+
+
+ ======================================================================*/
+
+
+/**
+ *
+ * icalcluster is an utility class design to manage clusters of
+ * icalcomponents on behalf of an implementation of icalset. This is
+ * done in order to split out common behavior different classes might
+ * need.
+ * The definition of what exactly a cluster will contain depends on the
+ * icalset subclass. At the basic level, an icluster is just a tuple,
+ * with anything as key and an icalcomponent as value.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#include <errno.h>
+#include <sys/stat.h> /* for stat */
+#ifndef WIN32
+#include <unistd.h> /* for stat, getpid */
+#else
+#include <io.h>
+#include <share.h>
+#endif
+#include <fcntl.h> /* for fcntl */
+#endif
+
+#include "icalcluster.h"
+#include "icalclusterimpl.h"
+#include "icalgauge.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#endif
+
+
+icalcluster * icalcluster_new_impl(void) {
+
+ struct icalcluster_impl* impl;
+
+ if ((impl = (struct icalcluster_impl*)malloc(
+ sizeof(struct icalcluster_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ memset(impl, 0, sizeof(struct icalcluster_impl));
+ strcpy(impl->id,ICALCLUSTER_ID);
+
+ return impl;
+}
+
+/**
+ * Create a cluster with a key/value pair.
+ *
+ * @todo Always do a deep copy.
+ */
+
+icalcluster * icalcluster_new(const char* key, icalcomponent *data) {
+ struct icalcluster_impl *impl = icalcluster_new_impl();
+ assert(impl->data == 0);
+
+ impl->key = strdup(key);
+ impl->changed = 0;
+ impl->data = 0;
+
+ if (data != NULL) {
+ if (icalcomponent_isa(data) != ICAL_XROOT_COMPONENT) {
+ impl->data = icalcomponent_new(ICAL_XROOT_COMPONENT);
+ icalcomponent_add_component(impl->data, data);
+ } else {
+ impl->data = icalcomponent_new_clone(data);
+ }
+ } else {
+ impl->data = icalcomponent_new(ICAL_XROOT_COMPONENT);
+ }
+
+ return impl;
+}
+
+/**
+ * Deep clone an icalcluster to a new one
+ */
+
+icalcluster *icalcluster_new_clone(const icalcluster *data) {
+ struct icalcluster_impl *old = (struct icalcluster_impl *)data;
+ struct icalcluster_impl *impl = icalcluster_new_impl();
+
+ impl->key = strdup(old->key);
+ impl->data = icalcomponent_new_clone(old->data);
+ impl->changed = 0;
+
+ return impl;
+}
+
+
+void icalcluster_free(icalcluster *impl) {
+ icalerror_check_arg_rv((impl!=0),"cluster");
+
+ if (impl->key != 0){
+ free(impl->key);
+ impl->key = 0;
+ }
+
+ if (impl->data != 0){
+ icalcomponent_free(impl->data);
+ impl->data = 0;
+ }
+
+ free(impl);
+}
+
+
+const char *icalcluster_key(icalcluster *impl) {
+ icalerror_check_arg_rz((impl!=0),"cluster");
+
+ return impl->key;
+}
+
+
+int icalcluster_is_changed(icalcluster *impl) {
+ icalerror_check_arg_rz((impl!=0),"cluster");
+
+ return impl->changed;
+}
+
+
+void icalcluster_mark(icalcluster *impl) {
+ icalerror_check_arg_rv((impl!=0),"cluster");
+
+ impl->changed = 1;
+}
+
+
+void icalcluster_commit(icalcluster *impl) {
+ icalerror_check_arg_rv((impl!=0),"cluster");
+
+ impl->changed = 0;
+}
+
+
+icalcomponent *icalcluster_get_component(icalcluster *impl) {
+
+ icalerror_check_arg_rz((impl!=0),"cluster");
+
+ if (icalcomponent_isa(impl->data) != ICAL_XROOT_COMPONENT) {
+ icalerror_warn("The top component is not an XROOT");
+ fprintf(stderr, "%s\n", icalcomponent_as_ical_string(impl->data));
+ abort();
+ }
+
+ return impl->data;
+}
+
+
+icalerrorenum icalcluster_add_component(icalcluster *impl, icalcomponent* child) {
+
+ icalerror_check_arg_re((impl!=0),"cluster", ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
+
+ icalcomponent_add_component(impl->data, child);
+ icalcluster_mark(impl);
+
+ return ICAL_NO_ERROR;
+}
+
+
+icalerrorenum icalcluster_remove_component(icalcluster *impl, icalcomponent* child) {
+
+ icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
+
+ icalcomponent_remove_component(impl->data,child);
+ icalcluster_mark(impl);
+
+ return ICAL_NO_ERROR;
+}
+
+
+int icalcluster_count_components(icalcluster *impl, icalcomponent_kind kind) {
+
+ icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
+
+ return icalcomponent_count_components(impl->data, kind);
+}
+
+
+/** Iterate through components **/
+icalcomponent *icalcluster_get_current_component(icalcluster* impl) {
+
+ icalerror_check_arg_rz((impl!=0),"cluster");
+
+ return icalcomponent_get_current_component(impl->data);
+}
+
+
+icalcomponent *icalcluster_get_first_component(icalcluster* impl) {
+
+ icalerror_check_arg_rz((impl!=0),"cluster");
+
+ return icalcomponent_get_first_component(impl->data,
+ ICAL_ANY_COMPONENT);
+}
+
+
+icalcomponent *icalcluster_get_next_component(icalcluster* impl) {
+
+ icalerror_check_arg_rz((impl!=0),"cluster");
+
+ return icalcomponent_get_next_component(impl->data,
+ ICAL_ANY_COMPONENT);
+}
diff --git a/libical/src/libicalss/icalcluster.h b/libical/src/libicalss/icalcluster.h
new file mode 100644
index 0000000000..f4eb041b04
--- /dev/null
+++ b/libical/src/libicalss/icalcluster.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalcluster.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 ICALCLUSTER_H
+#define ICALCLUSTER_H
+
+#include "ical.h"
+#include "icalset.h"
+
+typedef struct icalcluster_impl icalcluster;
+
+icalcluster* icalcluster_new(const char *key, icalcomponent *data);
+icalcluster* icalcluster_new_clone(const icalcluster *cluster);
+
+void icalcluster_free(icalcluster *cluster);
+
+const char* icalcluster_key(icalcluster *cluster);
+int icalcluster_is_changed(icalcluster *cluster);
+void icalcluster_mark(icalcluster *cluster);
+void icalcluster_commit(icalcluster *cluster);
+
+icalcomponent* icalcluster_get_component(icalcluster* cluster);
+int icalcluster_count_components(icalcluster *cluster, icalcomponent_kind kind);
+icalerrorenum icalcluster_add_component(icalcluster* cluster,
+ icalcomponent* child);
+icalerrorenum icalcluster_remove_component(icalcluster* cluster,
+ icalcomponent* child);
+
+icalcomponent* icalcluster_get_current_component(icalcluster* cluster);
+icalcomponent* icalcluster_get_first_component(icalcluster* cluster);
+icalcomponent* icalcluster_get_next_component(icalcluster* cluster);
+
+#endif /* !ICALCLUSTER_H */
+
+
+
diff --git a/libical/src/libicalss/icalclusterimpl.h b/libical/src/libicalss/icalclusterimpl.h
new file mode 100644
index 0000000000..ef80e1af81
--- /dev/null
+++ b/libical/src/libicalss/icalclusterimpl.h
@@ -0,0 +1,45 @@
+/* -*- 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*/
+
+#define ICALCLUSTER_ID "clus"
+
+struct icalcluster_impl {
+
+ char id[5]; /* clus */
+
+ char *key;
+ icalcomponent *data;
+ int changed;
+};
diff --git a/libical/src/libicalss/icaldirset.c b/libical/src/libicalss/icaldirset.c
index f5da125459..4a20fe1978 100644
--- a/libical/src/libicalss/icaldirset.c
+++ b/libical/src/libicalss/icaldirset.c
@@ -26,9 +26,10 @@
======================================================================*/
-/*
+/**
+ @file icaldirset.c
- icaldirset manages a database of ical components and offers
+ @brief 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 DTSTAMP
@@ -36,12 +37,13 @@
together in a single file. All files in a sotre are kept in a single
directory.
- 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 primary interfaces are icaldirset__get_first_component and
+ icaldirset_get_next_component. 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 &
@@ -57,64 +59,74 @@
#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 "icalcluster.h"
#include "icalgauge.h"
#include <limits.h> /* For PATH_MAX */
+#ifndef WIN32
+#include <dirent.h> /* for opendir() */
+#include <unistd.h> /* for stat, getpid */
+#include <sys/utsname.h> /* for uname */
+#else
+#include <io.h>
+#include <process.h>
+#endif
#include <errno.h>
#include <sys/types.h> /* for opendir() */
-#include <dirent.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 */
#include "icaldirsetimpl.h"
-struct icaldirset_impl* icaldirset_new_impl()
-{
- struct icaldirset_impl* impl;
+#ifdef WIN32
+#define snprintf _snprintf
+#define strcasecmp stricmp
- if ( ( impl = (struct icaldirset_impl*)
- malloc(sizeof(struct icaldirset_impl))) == 0) {
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- return 0;
- }
+#define _S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
- strcpy(impl->id,ICALDIRSET_ID);
+#define S_ISDIR(mode) _S_ISTYPE((mode), _S_IFDIR)
+#define S_ISREG(mode) _S_ISTYPE((mode), _S_IFREG)
+#endif
- return impl;
-}
+/** Default options used when NULL is passed to icalset_new() **/
+icaldirset_options icaldirset_options_default = {O_RDWR|O_CREAT};
-const char* icaldirset_path(icaldirset* cluster)
-{
- struct icaldirset_impl *impl = icaldirset_new_impl();
- return impl->dir;
+const char* icaldirset_path(icalset* set)
+{
+ icaldirset *dset = (icaldirset*)set;
+ return dset->dir;
}
-void icaldirset_mark(icaldirset* store)
+
+void icaldirset_mark(icalset* set)
{
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
+ icaldirset *dset = (icaldirset*)set;
- icalfileset_mark(impl->cluster);
+ icalcluster_mark(dset->cluster);
}
-icalerrorenum icaldirset_commit(icaldirset* store)
+icalerrorenum icaldirset_commit(icalset* set)
{
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
+ icaldirset *dset = (icaldirset*)set;
+ icalset *fileset;
+ icalfileset_options options = icalfileset_options_default;
- return icalfileset_commit(impl->cluster);
+ options.cluster = dset->cluster;
+ fileset = icalset_new(ICAL_FILE_SET, icalcluster_key(dset->cluster), &options);
+
+ fileset->commit(fileset);
+ fileset->free(fileset);
+
+ return ICAL_NO_ERROR;
}
void icaldirset_lock(const char* dir)
@@ -127,21 +139,22 @@ void icaldirset_unlock(const char* dir)
}
/* Load the contents of the store directory into the store's internal directory list*/
-icalerrorenum icaldirset_read_directory(struct icaldirset_impl* impl)
+icalerrorenum icaldirset_read_directory(icaldirset *dset)
{
+ char *str;
+#ifndef WIN32
struct dirent *de;
DIR* dp;
- char *str;
- dp = opendir(impl->dir);
+ dp = opendir(dset->dir);
- if ( dp == 0) {
+ if (dp == 0) {
icalerror_set_errno(ICAL_FILE_ERROR);
return ICAL_FILE_ERROR;
}
/* clear contents of directory list */
- while((str = pvl_pop(impl->directory))){
+ while((str = pvl_pop(dset->directory))){
free(str);
}
@@ -156,24 +169,52 @@ icalerrorenum icaldirset_read_directory(struct icaldirset_impl* impl)
continue;
}
- pvl_push(impl->directory, (void*)strdup(de->d_name));
+ pvl_push(dset->directory, (void*)strdup(de->d_name));
}
closedir(dp);
+#else
+ struct _finddata_t c_file;
+ long hFile;
+
+ /* Find first .c file in current directory */
+ if( (hFile = _findfirst( "*", &c_file )) == -1L ) {
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ return ICAL_FILE_ERROR;
+ } else {
+ while((str = pvl_pop(dset->directory))){
+ free(str);
+ }
+
+ /* load all of the cluster names in the directory list */
+ do {
+ /* Remove known directory names '.' and '..'*/
+ if (strcmp(c_file.name,".") == 0 ||
+ strcmp(c_file.name,"..") == 0 ){
+ continue;
+ }
+
+ pvl_push(dset->directory, (void*)strdup(c_file.name));
+ }
+ while ( _findnext( hFile, &c_file ) == 0 );
+
+ _findclose( hFile );
+ }
+
+#endif
return ICAL_NO_ERROR;
}
-icaldirset* icaldirset_new(const char* dir)
+
+icalset* icaldirset_init(icalset* set, const char* dir, void* options_in)
{
- struct icaldirset_impl *impl = icaldirset_new_impl();
+ icaldirset *dset = (icaldirset*)set;
+ icaldirset_options *options = options_in;
struct stat sbuf;
- if (impl == 0){
- return 0;
- }
-
icalerror_check_arg_rz( (dir!=0), "dir");
+ icalerror_check_arg_rz( (set!=0), "set");
if (stat(dir,&sbuf) != 0){
icalerror_set_errno(ICAL_FILE_ERROR);
@@ -188,68 +229,83 @@ icaldirset* icaldirset_new(const char* dir)
icaldirset_lock(dir);
- impl = icaldirset_new_impl();
+ dset->dir = (char*)strdup(dir);
+ dset->options = *options;
+ dset->directory = pvl_newlist();
+ dset->directory_iterator = 0;
+ dset->gauge = 0;
+ dset->first_component = 0;
+ dset->cluster = 0;
+
+ return set;
+}
+
+icalset* icaldirset_new(const char* dir)
+{
+ return icalset_new(ICAL_DIR_SET, dir, &icaldirset_options_default);
+}
- if (impl ==0){
- icalerror_set_errno(ICAL_NEWFAILED_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;
+icalset* icaldirset_new_reader(const char* dir)
+{
+ icaldirset_options reader_options = icaldirset_options_default;
+
+ reader_options.flags = O_RDONLY;
+
+ return icalset_new(ICAL_DIR_SET, dir, &reader_options);
+}
+
+
+icalset* icaldirset_new_writer(const char* dir)
+{
+ icaldirset_options writer_options = icaldirset_options_default;
- icaldirset_read_directory(impl);
+ writer_options.flags = O_RDWR|O_CREAT;
- return (icaldirset*) impl;
+ return icalset_new(ICAL_DIR_SET, dir, &writer_options);
}
-void icaldirset_free(icaldirset* s)
+
+void icaldirset_free(icalset* s)
{
- struct icaldirset_impl *impl = (struct icaldirset_impl*)s;
+ icaldirset *dset = (icaldirset*)s;
char* str;
- icaldirset_unlock(impl->dir);
+ icaldirset_unlock(dset->dir);
- if(impl->dir !=0){
- free(impl->dir);
+ if(dset->dir !=0){
+ free(dset->dir);
+ dset->dir = 0;
}
- if(impl->gauge !=0){
- icalcomponent_free(impl->gauge);
+ if(dset->gauge !=0){
+ icalgauge_free(dset->gauge);
+ dset->gauge = 0;
}
- if(impl->cluster !=0){
- icalfileset_free(impl->cluster);
+ if(dset->cluster !=0){
+ icalcluster_free(dset->cluster);
}
- while(impl->directory !=0 && (str=pvl_pop(impl->directory)) != 0){
+ while(dset->directory !=0 && (str=pvl_pop(dset->directory)) != 0){
free(str);
}
- if(impl->directory != 0){
- pvl_free(impl->directory);
+ if(dset->directory != 0){
+ pvl_free(dset->directory);
+ dset->directory = 0;
}
- impl->directory = 0;
- impl->directory_iterator = 0;
- impl->dir = 0;
- impl->gauge = 0;
- impl->first_component = 0;
-
- free(impl);
-
+ dset->directory_iterator = 0;
+ dset->first_component = 0;
}
+
/* icaldirset_next_uid_number updates a serial number in the Store
directory in a file called SEQUENCE */
-int icaldirset_next_uid_number(icaldirset* store)
+int icaldirset_next_uid_number(icaldirset* dset)
{
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
char sequence = 0;
char temp[128];
char filename[ICAL_PATH_MAX];
@@ -257,9 +313,9 @@ int icaldirset_next_uid_number(icaldirset* store)
FILE *f;
struct stat sbuf;
- icalerror_check_arg_rz( (store!=0), "store");
+ icalerror_check_arg_rz( (dset!=0), "dset");
- sprintf(filename,"%s/%s",impl->dir,"SEQUENCE");
+ sprintf(filename,"%s/%s",dset->dir,"SEQUENCE");
/* Create the file if it does not exist.*/
if (stat(filename,&sbuf) == -1 || !S_ISREG(sbuf.st_mode)){
@@ -272,7 +328,6 @@ int icaldirset_next_uid_number(icaldirset* store)
icalerror_warn("Can't create SEQUENCE file in icaldirset_next_uid_number");
return 0;
}
-
}
if ( (f = fopen(filename,"r+")) != 0){
@@ -298,85 +353,85 @@ int icaldirset_next_uid_number(icaldirset* store)
icalerror_warn("Can't create SEQUENCE file in icaldirset_next_uid_number");
return 0;
}
-
}
-icalerrorenum icaldirset_next_cluster(icaldirset* store)
+icalerrorenum icaldirset_next_cluster(icaldirset* dset)
{
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
char path[ICAL_PATH_MAX];
- if (impl->directory_iterator == 0){
+ if (dset->directory_iterator == 0){
icalerror_set_errno(ICAL_INTERNAL_ERROR);
return ICAL_INTERNAL_ERROR;
}
- impl->directory_iterator = pvl_next(impl->directory_iterator);
+ dset->directory_iterator = pvl_next(dset->directory_iterator);
- if (impl->directory_iterator == 0){
+ if (dset->directory_iterator == 0){
/* There are no more clusters */
- if(impl->cluster != 0){
- icalfileset_free(impl->cluster);
- impl->cluster = 0;
+ if(dset->cluster != 0){
+ icalcluster_free(dset->cluster);
+ dset->cluster = 0;
}
return ICAL_NO_ERROR;
}
- sprintf(path,"%s/%s",impl->dir,(char*)pvl_data(impl->directory_iterator));
-
- icalfileset_free(impl->cluster);
+ sprintf(path,"%s/%s", dset->dir,(char*)pvl_data(dset->directory_iterator));
- impl->cluster = icalfileset_new(path);
+ icalcluster_free(dset->cluster);
+ dset->cluster = icalfileset_produce_icalcluster(path);
return icalerrno;
}
-void icaldirset_add_uid(icaldirset* store, icaldirset* comp)
+static void icaldirset_add_uid(icalcomponent* comp)
{
char uidstring[ICAL_PATH_MAX];
icalproperty *uid;
+#ifndef WIN32
struct utsname unamebuf;
+#endif
- 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) {
+#ifndef WIN32
uname(&unamebuf);
sprintf(uidstring,"%d-%s",(int)getpid(),unamebuf.nodename);
+#else
+ sprintf(uidstring,"%d-%s",(int)getpid(),"WINDOWS"); /* FIX: There must be an easy get the system name */
+#endif
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
+/**
+ 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 DTAMP property */
+ component must have a DSTAMP property
+*/
-icalerrorenum icaldirset_add_component(icaldirset* store, icaldirset* comp)
+icalerrorenum icaldirset_add_component(icalset* set, icalcomponent* comp)
{
- struct icaldirset_impl *impl;
char clustername[ICAL_PATH_MAX];
- icalproperty *dt;
+ icalproperty *dt = 0;
icalvalue *v;
struct icaltimetype tm;
icalerrorenum error = ICAL_NO_ERROR;
icalcomponent *inner;
+ icaldirset *dset = (icaldirset*) set;
- impl = (struct icaldirset_impl*)store;
- icalerror_check_arg_rz( (store!=0), "store");
+ icalerror_check_arg_rz( (dset!=0), "dset");
icalerror_check_arg_rz( (comp!=0), "comp");
- errno = 0;
-
- icaldirset_add_uid(store,comp);
+ icaldirset_add_uid(comp);
/* Determine which cluster this object belongs in. This is a HACK */
@@ -386,52 +441,44 @@ icalerrorenum icaldirset_add_component(icaldirset* store, icaldirset* comp)
dt = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY);
- if (dt != 0){
+ if (dt != 0)
break;
}
- }
-
- if (dt == 0){
+ if (dt == 0) {
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){
+ if (dt != 0)
break;
}
}
- }
-
if (dt == 0){
-
-
icalerror_warn("The component does not have a DTSTAMP or 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,ICAL_PATH_MAX,"%s/%04d%02d",impl->dir,tm.year,tm.month);
+ snprintf(clustername,ICAL_PATH_MAX,"%s/%04d%02d",dset->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(dset->cluster != 0 &&
+ strcmp(clustername,icalcluster_key(dset->cluster)) != 0 ){
+ icalcluster_free(dset->cluster);
+ dset->cluster = 0;
}
- if (impl->cluster == 0){
- impl->cluster = icalfileset_new(clustername);
+ if (dset->cluster == 0){
+ dset->cluster = icalfileset_produce_icalcluster(clustername);
- if (impl->cluster == 0){
+ if (dset->cluster == 0){
error = icalerrno;
}
}
@@ -442,33 +489,31 @@ icalerrorenum icaldirset_add_component(icaldirset* store, icaldirset* comp)
}
/* Add the component to the cluster */
-
- icalfileset_add_component(impl->cluster,comp);
+ icalcluster_add_component(dset->cluster,comp);
- icalfileset_mark(impl->cluster);
+ /* icalcluster_mark(impl->cluster); */
return ICAL_NO_ERROR;
}
-/* Remove a component in the current cluster. HACK. This routine is a
+/**
+ 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;
+ no other use.
+ */
- icalcomponent *filecomp = filesetimpl->cluster;
+icalerrorenum icaldirset_remove_component(icalset* set, icalcomponent* comp)
+{
+ icaldirset *dset = (icaldirset*)set;
+ icalcomponent *filecomp = icalcluster_get_component(dset->cluster);
icalcompiter i;
int found = 0;
- icalerror_check_arg_re((store!=0),"store",ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((set!=0),"set",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);
+ icalerror_check_arg_re((dset->cluster!=0),"Cluster pointer",ICAL_USAGE_ERROR);
for(i = icalcomponent_begin_component(filecomp,ICAL_ANY_COMPONENT);
icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
@@ -487,17 +532,16 @@ icalerrorenum icaldirset_remove_component(icaldirset* store, icaldirset* comp)
return ICAL_USAGE_ERROR;
}
- icalfileset_remove_component(impl->cluster,comp);
+ icalcluster_remove_component(dset->cluster,comp);
- icalfileset_mark(impl->cluster);
+ /* icalcluster_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( icalcluster_count_components(dset->cluster,ICAL_ANY_COMPONENT)==0){
+ icalerrorenum error = icaldirset_next_cluster(dset);
- if(impl->cluster != 0 && error == ICAL_NO_ERROR){
- icalfileset_get_first_component(impl->cluster);
+ if(dset->cluster != 0 && error == ICAL_NO_ERROR){
+ icalcluster_get_first_component(dset->cluster);
} else {
/* HACK. Not strictly correct for impl->cluster==0 */
return error;
@@ -511,95 +555,84 @@ icalerrorenum icaldirset_remove_component(icaldirset* store, icaldirset* comp)
-int icaldirset_count_components(icaldirset* store,
+int icaldirset_count_components(icalset* store,
icalcomponent_kind kind)
{
/* HACK, not implemented */
-
assert(0);
return 0;
}
-icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c)
+icalcomponent* icaldirset_fetch_match(icalset* set, icalcomponent *c)
{
fprintf(stderr," icaldirset_fetch_match is not implemented\n");
assert(0);
+ return 0;
}
-icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid)
+icalcomponent* icaldirset_fetch(icalset* set, const char* uid)
{
- icalcomponent *gauge;
- icalcomponent *old_gauge;
+ icaldirset *dset = (icaldirset*)set;
+ icalgauge *gauge;
+ icalgauge *old_gauge;
icalcomponent *c;
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
+ char sql[256];
- icalerror_check_arg_rz( (store!=0), "store");
+ icalerror_check_arg_rz( (set!=0), "set");
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);
+ snprintf(sql, 256, "SELECT * FROM VEVENT WHERE UID = \"%s\"", uid);
+
+ gauge = icalgauge_new_from_sql(sql, 0);
- old_gauge = impl->gauge;
- impl->gauge = gauge;
+ old_gauge = dset->gauge;
+ dset->gauge = gauge;
- c= icaldirset_get_first_component(store);
+ c= icaldirset_get_first_component(set);
- impl->gauge = old_gauge;
+ dset->gauge = old_gauge;
- icalcomponent_free(gauge);
+ icalgauge_free(gauge);
return c;
}
-int icaldirset_has_uid(icaldirset* store, const char* uid)
+int icaldirset_has_uid(icalset* set, const char* uid)
{
icalcomponent *c;
- icalerror_check_arg_rz( (store!=0), "store");
+ icalerror_check_arg_rz( (set!=0), "set");
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);
+ c = icaldirset_fetch(set,uid);
return c!=0;
}
-icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge)
- {
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
+icalerrorenum icaldirset_select(icalset* set, icalgauge* gauge)
+{
+ icaldirset *dset = (icaldirset*)set;
- icalerror_check_arg_re( (store!=0), "store",ICAL_BADARG_ERROR);
+ icalerror_check_arg_re( (set!=0), "set",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;
+ dset->gauge = gauge;
return ICAL_NO_ERROR;
}
-icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *old,
+icalerrorenum icaldirset_modify(icalset* set,
+ icalcomponent *old,
icalcomponent *new)
{
assert(0);
@@ -608,7 +641,7 @@ icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *old,
}
-void icaldirset_clear(icaldirset* store)
+void icaldirset_clear(icalset* set)
{
assert(0);
@@ -616,53 +649,58 @@ void icaldirset_clear(icaldirset* store)
/* HACK, not implemented */
}
-icalcomponent* icaldirset_get_current_component(icaldirset* store)
+icalcomponent* icaldirset_get_current_component(icalset* set)
{
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
+ icaldirset *dset = (icaldirset*)set;
- if(impl->cluster == 0){
- icaldirset_get_first_component(store);
+ if (dset->cluster == 0){
+ icaldirset_get_first_component(set);
+ }
+ if(dset->cluster == 0){
+ return 0;
}
- return icalfileset_get_current_component(impl->cluster);
-
+ return icalcluster_get_current_component(dset->cluster);
}
-icalcomponent* icaldirset_get_first_component(icaldirset* store)
+icalcomponent* icaldirset_get_first_component(icalset* set)
{
- struct icaldirset_impl *impl = (struct icaldirset_impl*)store;
+ icaldirset *dset = (icaldirset*)set;
+
icalerrorenum error;
char path[ICAL_PATH_MAX];
- error = icaldirset_read_directory(impl);
+ error = icaldirset_read_directory(dset);
if (error != ICAL_NO_ERROR){
icalerror_set_errno(error);
return 0;
}
- impl->directory_iterator = pvl_head(impl->directory);
+ dset->directory_iterator = pvl_head(dset->directory);
- if (impl->directory_iterator == 0){
+ if (dset->directory_iterator == 0){
icalerror_set_errno(error);
return 0;
}
- snprintf(path,ICAL_PATH_MAX,"%s/%s",impl->dir,(char*)pvl_data(impl->directory_iterator));
+ snprintf(path,ICAL_PATH_MAX,"%s/%s",
+ dset->dir,
+ (char*)pvl_data(dset->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(dset->cluster != 0 && strcmp(path,icalcluster_key(dset->cluster)) != 0 ){
+ icalcluster_free(dset->cluster);
+ dset->cluster = 0;
}
- if (impl->cluster == 0){
- impl->cluster = icalfileset_new(path);
+ if (dset->cluster == 0){
+ dset->cluster = icalfileset_produce_icalcluster(path);
- if (impl->cluster == 0){
+ if (dset->cluster == 0){
error = icalerrno;
}
}
@@ -672,23 +710,22 @@ icalcomponent* icaldirset_get_first_component(icaldirset* store)
return 0;
}
- impl->first_component = 1;
+ dset->first_component = 1;
- return icaldirset_get_next_component(store);
+ return icaldirset_get_next_component(set);
}
-icalcomponent* icaldirset_get_next_component(icaldirset* store)
+
+icalcomponent* icaldirset_get_next_component(icalset* set)
{
- struct icaldirset_impl *impl;
+ icaldirset *dset = (icaldirset*)set;
icalcomponent *c;
icalerrorenum error;
- icalerror_check_arg_rz( (store!=0), "store");
-
- impl = (struct icaldirset_impl*)store;
+ icalerror_check_arg_rz( (set!=0), "set");
- if(impl->cluster == 0){
+ if(dset->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;
@@ -696,30 +733,26 @@ icalcomponent* icaldirset_get_next_component(icaldirset* store)
}
/* Set the component iterator for the following for loop */
- if (impl->first_component == 1){
- icalfileset_get_first_component(impl->cluster);
- impl->first_component = 0;
+ if (dset->first_component == 1){
+ icalcluster_get_first_component(dset->cluster);
+ dset->first_component = 0;
} else {
- icalfileset_get_next_component(impl->cluster);
+ icalcluster_get_next_component(dset->cluster);
}
-
while(1){
/* Iterate through all of the objects in the cluster*/
- for( c = icalfileset_get_current_component(impl->cluster);
+ for( c = icalcluster_get_current_component(dset->cluster);
c != 0;
- c = icalfileset_get_next_component(impl->cluster)){
+ c = icalcluster_get_next_component(dset->cluster)){
/* If there is a gauge defined and the component does not
pass the gauge, skip the rest of the loop */
-#if 0 /* HACK */
- if (impl->gauge != 0 && icalgauge_test(c,impl->gauge) == 0){
+ if (dset->gauge != 0 && icalgauge_compare(dset->gauge,c) == 0){
continue;
}
-#else
- assert(0); /* icalgauge_test needs to be fixed */
-#endif
+
/* Either there is no gauge, or the component passed the
gauge, so return it*/
@@ -729,13 +762,13 @@ icalcomponent* icaldirset_get_next_component(icaldirset* store)
/* 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);
+ error = icaldirset_next_cluster(dset);
- if(impl->cluster == 0 || error != ICAL_NO_ERROR){
+ if(dset->cluster == 0 || error != ICAL_NO_ERROR){
/* No more clusters */
return 0;
} else {
- c = icalfileset_get_first_component(impl->cluster);
+ c = icalcluster_get_first_component(dset->cluster);
return c;
}
@@ -745,9 +778,28 @@ icalcomponent* icaldirset_get_next_component(icaldirset* store)
return 0; /* Should never get here */
}
-
+icalsetiter icaldirset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge)
+{
+ icalsetiter itr = icalsetiter_null;
+ icaldirset *fset = (icaldirset*) set;
+
+ icalerror_check_arg_re((fset!=0), "set", icalsetiter_null);
+ itr.iter.kind = kind;
+ itr.gauge = gauge;
+ /* TO BE IMPLEMENTED */
+ return icalsetiter_null;
+}
+icalcomponent* icaldirsetiter_to_next(icalset* set, icalsetiter* i)
+{
+ /* TO BE IMPLEMENTED */
+ return NULL;
+}
-
+icalcomponent* icaldirsetiter_to_prior(icalset* set, icalsetiter* i)
+{
+ /* TO BE IMPLEMENTED */
+ return NULL;
+}
diff --git a/libical/src/libicalss/icaldirset.h b/libical/src/libicalss/icaldirset.h
index 7d205ecf0a..a2d577dc34 100644
--- a/libical/src/libicalss/icaldirset.h
+++ b/libical/src/libicalss/icaldirset.h
@@ -30,51 +30,67 @@
#define ICALDIRSET_H
#include "ical.h"
+#include "icalset.h"
+#include "icalcluster.h"
+#include "icalgauge.h"
/* icaldirset Routines for storing, fetching, and searching for ical
* objects in a database */
-typedef void icaldirset;
+typedef struct icaldirset_impl icaldirset;
+icalset* icaldirset_new(const char* path);
-icaldirset* icaldirset_new(const char* path);
+icalset* icaldirset_new_reader(const char* path);
+icalset* icaldirset_new_writer(const char* path);
-void icaldirset_free(icaldirset* store);
-const char* icaldirset_path(icaldirset* store);
+icalset* icaldirset_init(icalset* set, const char *dsn, void *options);
+void icaldirset_free(icalset* set);
+
+const char* icaldirset_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 icaldirset_mark(icaldirset* store);
-icalerrorenum icaldirset_commit(icaldirset* store);
+void icaldirset_mark(icalset* set);
+icalerrorenum icaldirset_commit(icalset* set);
-icalerrorenum icaldirset_add_component(icaldirset* store, icalcomponent* comp);
-icalerrorenum icaldirset_remove_component(icaldirset* store, icalcomponent* comp);
+icalerrorenum icaldirset_add_component(icalset* store, icalcomponent* comp);
+icalerrorenum icaldirset_remove_component(icalset* store, icalcomponent* comp);
-int icaldirset_count_components(icaldirset* store,
+int icaldirset_count_components(icalset* 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);
+icalerrorenum icaldirset_select(icalset* store, icalgauge* gauge);
+void icaldirset_clear(icalset* store);
/* Get a component by uid */
-icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid);
-int icaldirset_has_uid(icaldirset* store, const char* uid);
-icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c);
+icalcomponent* icaldirset_fetch(icalset* store, const char* uid);
+int icaldirset_has_uid(icalset* store, const char* uid);
+icalcomponent* icaldirset_fetch_match(icalset* set, icalcomponent *c);
/* Modify components according to the MODIFY method of CAP. Works on
the currently selected components. */
-icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *oldc,
+icalerrorenum icaldirset_modify(icalset* store, icalcomponent *oldc,
icalcomponent *newc);
-/* Iterate through the components. If a guage has been defined, these
+/* Iterate through the components. If a gauge 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* icaldirset_get_next_component(icaldirset* store);
+icalcomponent* icaldirset_get_current_component(icalset* store);
+icalcomponent* icaldirset_get_first_component(icalset* store);
+icalcomponent* icaldirset_get_next_component(icalset* store);
+
+/* External iterator for thread safety */
+icalsetiter icaldirset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge);
+icalcomponent* icaldirsetiter_to_next(icalset* set, icalsetiter* i);
+icalcomponent* icaldirsetiter_to_prior(icalset* set, icalsetiter* i);
+
+typedef struct icaldirset_options {
+ int flags; /**< flags corresponding to the open() system call O_RDWR, etc. */
+} icaldirset_options;
#endif /* !ICALDIRSET_H */
diff --git a/libical/src/libicalss/icaldirsetimpl.h b/libical/src/libicalss/icaldirsetimpl.h
index 0e69ba2f2e..332a369b02 100644
--- a/libical/src/libicalss/icaldirsetimpl.h
+++ b/libical/src/libicalss/icaldirsetimpl.h
@@ -30,18 +30,19 @@
#include "config.h"
#endif
+#include "icalcluster.h"
+
/* This definition is in its own file so it can be kept out of the
main header file, but used by "friend classes" like icalset*/
-#define ICALDIRSET_ID "dset"
-
struct icaldirset_impl
{
- char id[5]; /* "dset" */
- char* dir;
- icalcomponent* gauge;
- icaldirset* cluster;
- int first_component;
- pvl_list directory;
- pvl_elem directory_iterator;
+ icalset super; /**< parent class */
+ char* dir; /**< directory containing ics files */
+ icaldirset_options options; /**< copy of options passed to icalset_new() */
+ icalcluster* cluster; /**< cluster containing data */
+ icalgauge* gauge; /**< gauge for filtering out data */
+ int first_component; /**< ??? */
+ pvl_list directory; /**< ??? */
+ pvl_elem directory_iterator; /**< ??? */
};
diff --git a/libical/src/libicalss/icalfileset.c b/libical/src/libicalss/icalfileset.c
index b6e3430f7d..389cec7587 100644
--- a/libical/src/libicalss/icalfileset.c
+++ b/libical/src/libicalss/icalfileset.c
@@ -34,98 +34,151 @@
#include "icalgauge.h"
#include <errno.h>
#include <sys/stat.h> /* for stat */
+#ifndef WIN32
#include <unistd.h> /* for stat, getpid */
+#else
+#include <io.h>
+#include <share.h>
+#endif
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> /* for fcntl */
-#include <unistd.h> /* for fcntl */
#include "icalfilesetimpl.h"
+#include "icalclusterimpl.h"
+
+#ifdef WIN32
+#define snprintf _snprintf
+#define strcasecmp stricmp
+
+#define _S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
+
+#define S_ISDIR(mode) _S_ISTYPE((mode), _S_IFDIR)
+#define S_ISREG(mode) _S_ISTYPE((mode), _S_IFREG)
+#endif
extern int errno;
-int icalfileset_lock(icalfileset *cluster);
-int icalfileset_unlock(icalfileset *cluster);
-icalerrorenum icalfileset_read_file(icalfileset* cluster, mode_t mode);
-int icalfileset_filesize(icalfileset* cluster);
+/** Default options used when NULL is passed to icalset_new() **/
+icalfileset_options icalfileset_options_default = {O_RDWR|O_CREAT, 0644, 0};
+
+int icalfileset_lock(icalfileset *set);
+int icalfileset_unlock(icalfileset *set);
+icalerrorenum icalfileset_read_file(icalfileset* set, mode_t mode);
+int icalfileset_filesize(icalfileset* set);
icalerrorenum icalfileset_create_cluster(const char *path);
-icalfileset* icalfileset_new_impl()
+icalset* icalfileset_new(const char* path)
{
- struct icalfileset_impl* impl;
-
- if ( ( impl = (struct icalfileset_impl*)
- malloc(sizeof(struct icalfileset_impl))) == 0) {
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- errno = ENOMEM;
- return 0;
- }
-
- memset(impl,0,sizeof(struct icalfileset_impl));
-
- strcpy(impl->id,ICALFILESET_ID);
-
- return impl;
+ return icalset_new(ICAL_FILE_SET, path, &icalfileset_options_default);
}
-
-icalfileset* icalfileset_new(const char* path)
+icalset* icalfileset_new_reader(const char* path)
{
- return icalfileset_new_open(path, O_RDWR|O_CREAT, 0664);
+ icalfileset_options reader_options = icalfileset_options_default;
+ reader_options.flags = O_RDONLY;
+
+ return icalset_new(ICAL_FILE_SET, path, &reader_options);
}
-icalfileset* icalfileset_new_open(const char* path, int flags, mode_t mode)
+icalset* icalfileset_new_writer(const char* path)
{
- struct icalfileset_impl *impl = icalfileset_new_impl();
- struct icaltimetype tt;
- off_t cluster_file_size;
+ icalfileset_options writer_options = icalfileset_options_default;
+ writer_options.flags = O_RDONLY;
- memset(&tt,0,sizeof(struct icaltimetype));
+ return icalset_new(ICAL_FILE_SET, path, &writer_options);
+}
- icalerror_clear_errno();
- icalerror_check_arg_rz( (path!=0), "path");
+icalset* icalfileset_init(icalset *set, const char* path, void* options_in)
+{
+ icalfileset_options *options = (options_in) ? options_in : &icalfileset_options_default;
+ icalfileset *fset = (icalfileset*) set;
+ int flags;
+ mode_t mode;
+ off_t cluster_file_size;
- if (impl == 0){
- return 0;
- }
+ icalerror_clear_errno();
+ icalerror_check_arg_rz( (path!=0), "path");
+ icalerror_check_arg_rz( (fset!=0), "fset");
- impl->path = strdup(path);
+ fset->path = strdup(path);
+ fset->options = *options;
- cluster_file_size = icalfileset_filesize(impl);
-
- if(cluster_file_size < 0){
- icalfileset_free(impl);
- return 0;
- }
+ flags = options->flags;
+ mode = options->mode;
+
+ cluster_file_size = icalfileset_filesize(fset);
+
+ if(cluster_file_size < 0){
+ icalfileset_free(set);
+ return 0;
+ }
- impl->fd = open(impl->path,flags, mode);
+#ifndef WIN32
+ fset->fd = open(fset->path, flags, mode);
+#else
+ fset->fd = open(fset->path, flags, mode);
+ /* fset->fd = sopen(fset->path,flags, _SH_DENYWR, _S_IREAD | _S_IWRITE); */
+#endif
- if (impl->fd < 0){
- icalerror_set_errno(ICAL_FILE_ERROR);
- icalfileset_free(impl);
- return 0;
- }
+ if (fset->fd < 0){
+ icalerror_set_errno(ICAL_FILE_ERROR);
+ icalfileset_free(set);
+ return 0;
+ }
- icalfileset_lock(impl);
+#ifndef WIN32
+ icalfileset_lock(fset);
+#endif
if(cluster_file_size > 0 ){
icalerrorenum error;
- if((error = icalfileset_read_file(impl,mode))!= ICAL_NO_ERROR){
- icalfileset_free(impl);
- return 0;
+ if((error = icalfileset_read_file(fset,mode))!= ICAL_NO_ERROR){
+ icalfileset_free(set);
+ return 0;
}
}
- if(impl->cluster == 0){
- impl->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
- }
+ if (options->cluster) {
+ fset->cluster = icalcomponent_new_clone(icalcluster_get_component(options->cluster));
+ fset->changed = 1;
+ }
+
+ if (fset->cluster == 0) {
+ fset->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
+ }
+
+ return set;
+}
+
+
+icalcluster* icalfileset_produce_icalcluster(const char *path) {
+ icalset *fileset;
+ icalcluster *ret;
+
+ int errstate = icalerror_errors_are_fatal;
+ icalerror_errors_are_fatal = 0;
- return impl;
+ fileset = icalfileset_new_reader(path);
+
+
+ if (fileset == 0 && icalerrno == ICAL_FILE_ERROR) {
+ /* file does not exist */
+ ret = icalcluster_new(path, NULL);
+ } else {
+ ret = icalcluster_new(path, ((icalfileset*)fileset)->cluster);
+ icalfileset_free(fileset);
+ }
+
+ icalerror_errors_are_fatal = errstate;
+ icalerror_set_errno(ICAL_NO_ERROR);
+ return ret;
}
+
+
char* icalfileset_read_from_file(char *s, size_t size, void *d)
{
-
char* p = s;
int fd = (int)d;
@@ -150,42 +203,38 @@ char* icalfileset_read_from_file(char *s, size_t size, void *d)
}
-icalerrorenum icalfileset_read_file(icalfileset* cluster,mode_t mode)
+icalerrorenum icalfileset_read_file(icalfileset* set,mode_t mode)
{
-
icalparser *parser;
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
-
parser = icalparser_new();
- icalparser_set_gen_data(parser,(void*)impl->fd);
- impl->cluster = icalparser_parse(parser,icalfileset_read_from_file);
+
+ icalparser_set_gen_data(parser,(void*)set->fd);
+ set->cluster = icalparser_parse(parser,icalfileset_read_from_file);
icalparser_free(parser);
- if (impl->cluster == 0 || icalerrno != ICAL_NO_ERROR){
+ if (set->cluster == 0 || icalerrno != ICAL_NO_ERROR){
icalerror_set_errno(ICAL_PARSE_ERROR);
- return ICAL_PARSE_ERROR;
+ /*return ICAL_PARSE_ERROR;*/
}
- if (icalcomponent_isa(impl->cluster) != ICAL_XROOT_COMPONENT){
+ if (icalcomponent_isa(set->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);
+ icalcomponent *cl = set->cluster;
+ set->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
+ icalcomponent_add_component(set->cluster,cl);
}
return ICAL_NO_ERROR;
-
}
-int icalfileset_filesize(icalfileset* cluster)
+int icalfileset_filesize(icalfileset* fset)
{
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
int cluster_file_size;
struct stat sbuf;
-
- if (stat(impl->path,&sbuf) != 0){
+
+ if (stat(fset->path,&sbuf) != 0){
/* A file by the given name does not exist, or there was
another error */
@@ -214,120 +263,110 @@ int icalfileset_filesize(icalfileset* cluster)
/*return -1; not reached*/
}
-void icalfileset_free(icalfileset* cluster)
+void icalfileset_free(icalset* set)
{
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+ icalfileset *fset = (icalfileset*) set;
- icalerror_check_arg_rv((cluster!=0),"cluster");
+ icalerror_check_arg_rv((set!=0),"set");
- if (impl->cluster != 0){
- icalfileset_commit(cluster);
- icalcomponent_free(impl->cluster);
- impl->cluster=0;
+ if (fset->cluster != 0){
+ icalfileset_commit(set);
+ icalcomponent_free(fset->cluster);
+ fset->cluster=0;
}
- if(impl->fd > 0){
- icalfileset_unlock(impl);
- close(impl->fd);
- impl->fd = -1;
+ if (fset->gauge != 0){
+ icalgauge_free(fset->gauge);
+ fset->gauge=0;
}
- if(impl->path != 0){
- free(impl->path);
- impl->path = 0;
+ if(fset->fd > 0){
+ icalfileset_unlock(fset);
+ close(fset->fd);
+ fset->fd = -1;
}
- free(impl);
+ if(fset->path != 0){
+ free(fset->path);
+ fset->path = 0;
+ }
}
-const char* icalfileset_path(icalfileset* cluster)
-{
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
- icalerror_check_arg_rz((cluster!=0),"cluster");
+const char* icalfileset_path(icalset* set) {
+ icalerror_check_arg_rz((set!=0),"set");
- return impl->path;
+ return ((icalfileset*)set)->path;
}
-int icalfileset_lock(icalfileset *cluster)
+int icalfileset_lock(icalfileset *set)
{
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+#ifndef WIN32
struct flock lock;
int rtrn;
- icalerror_check_arg_rz((impl->fd>0),"impl->fd");
+ icalerror_check_arg_rz((set->fd>0),"set->fd");
errno = 0;
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) */
- rtrn = fcntl(impl->fd, F_SETLKW, &lock);
+ rtrn = fcntl(set->fd, F_SETLKW, &lock);
return rtrn;
+#else
+ return 0;
+#endif
}
-int icalfileset_unlock(icalfileset *cluster)
+int icalfileset_unlock(icalfileset *set)
{
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+#ifndef WIN32
struct flock lock;
- icalerror_check_arg_rz((impl->fd>0),"impl->fd");
+ icalerror_check_arg_rz((set->fd>0),"set->fd");
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(impl->fd, F_UNLCK, &lock));
-
-}
-
-#ifdef ICAL_SAFESAVES
-int icalfileset_safe_saves=1;
+ return (fcntl(set->fd, F_UNLCK, &lock));
#else
-int icalfileset_safe_saves=0;
+ return 0;
#endif
+}
-icalerrorenum icalfileset_commit(icalfileset* cluster)
+icalerrorenum icalfileset_commit(icalset* set)
{
char tmp[ICAL_PATH_MAX];
char *str;
icalcomponent *c;
off_t write_size=0;
+ icalfileset *fset = (icalfileset*) set;
+
+ icalerror_check_arg_re((fset!=0),"set",ICAL_BADARG_ERROR);
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
-
- icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
-
- icalerror_check_arg_re((impl->fd>0),"impl->fd is invalid",
+ icalerror_check_arg_re((fset->fd>0),"set->fd is invalid",
ICAL_INTERNAL_ERROR) ;
- if (impl->changed == 0 ){
+ if (fset->changed == 0 ){
return ICAL_NO_ERROR;
}
- if(icalfileset_safe_saves == 1){
- snprintf(tmp,ICAL_PATH_MAX,"cp %s %s.bak",impl->path,impl->path);
-
- if(system(tmp) < 0){
- icalerror_set_errno(ICAL_FILE_ERROR);
- return ICAL_FILE_ERROR;
- }
- }
-
- if(lseek(impl->fd,SEEK_SET,0) < 0){
+ if(lseek(fset->fd, 0, SEEK_SET) < 0){
icalerror_set_errno(ICAL_FILE_ERROR);
return ICAL_FILE_ERROR;
}
- for(c = icalcomponent_get_first_component(impl->cluster,ICAL_ANY_COMPONENT);
+ for(c = icalcomponent_get_first_component(fset->cluster,ICAL_ANY_COMPONENT);
c != 0;
- c = icalcomponent_get_next_component(impl->cluster,ICAL_ANY_COMPONENT)){
+ c = icalcomponent_get_next_component(fset->cluster,ICAL_ANY_COMPONENT)){
int sz;
str = icalcomponent_as_ical_string(c);
- sz=write(impl->fd,str,strlen(str));
+ sz=write(fset->fd,str,strlen(str));
if ( sz != strlen(str)){
perror("write");
@@ -338,132 +377,138 @@ icalerrorenum icalfileset_commit(icalfileset* cluster)
write_size += sz;
}
- impl->changed = 0;
+ fset->changed = 0;
- if(ftruncate(impl->fd,write_size) < 0){
+#ifndef WIN32
+ if(ftruncate(fset->fd,write_size) < 0){
return ICAL_FILE_ERROR;
}
+#else
+ chsize( fset->fd, tell( fset->fd ) );
+#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;
+void icalfileset_mark(icalset* set) {
+ icalerror_check_arg_rv((set!=0),"set");
+ ((icalfileset*)set)->changed = 1;
}
-icalcomponent* icalfileset_get_component(icalfileset* cluster){
- struct icalfileset_impl *impl = (struct icalfileset_impl*)cluster;
+icalcomponent* icalfileset_get_component(icalset* set){
+ icalfileset *fset = (icalfileset*) set;
+ icalerror_check_arg_rz((set!=0),"set");
- icalerror_check_arg_re((impl!=0),"cluster",ICAL_BADARG_ERROR);
-
- return impl->cluster;
+ return fset->cluster;
}
-/* manipulate the components in the cluster */
+/* manipulate the components in the set */
-icalerrorenum icalfileset_add_component(icalfileset *cluster,
+icalerrorenum icalfileset_add_component(icalset *set,
icalcomponent* child)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+ icalfileset *fset = (icalfileset*) set;
- icalerror_check_arg_re((cluster!=0),"cluster", ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((set!=0),"set", ICAL_BADARG_ERROR);
icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
- icalcomponent_add_component(impl->cluster,child);
+ icalcomponent_add_component(fset->cluster,child);
- icalfileset_mark(cluster);
+ icalfileset_mark(set);
return ICAL_NO_ERROR;
-
}
-icalerrorenum icalfileset_remove_component(icalfileset *cluster,
+icalerrorenum icalfileset_remove_component(icalset *set,
icalcomponent* child)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+ icalfileset *fset = (icalfileset*) set;
- icalerror_check_arg_re((cluster!=0),"cluster",ICAL_BADARG_ERROR);
+ icalerror_check_arg_re((set!=0),"set",ICAL_BADARG_ERROR);
icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
- icalcomponent_remove_component(impl->cluster,child);
+ icalcomponent_remove_component(fset->cluster,child);
- icalfileset_mark(cluster);
+ icalfileset_mark(set);
return ICAL_NO_ERROR;
}
-int icalfileset_count_components(icalfileset *cluster,
+int icalfileset_count_components(icalset *set,
icalcomponent_kind kind)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+ icalfileset *fset = (icalfileset*) set;
- if(cluster == 0){
+ if (set == 0){
icalerror_set_errno(ICAL_BADARG_ERROR);
return -1;
}
- return icalcomponent_count_components(impl->cluster,kind);
+ return icalcomponent_count_components(fset->cluster,kind);
}
-icalerrorenum icalfileset_select(icalfileset* set, icalgauge* gauge)
+icalerrorenum icalfileset_select(icalset* set, icalgauge* gauge)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)set;
+ icalfileset *fset = (icalfileset*) set;
- icalerror_check_arg_re(gauge!=0,"guage",ICAL_BADARG_ERROR);
+ icalerror_check_arg_re(gauge!=0,"gauge",ICAL_BADARG_ERROR);
- impl->gauge = gauge;
+ fset->gauge = gauge;
return ICAL_NO_ERROR;
}
-void icalfileset_clear(icalfileset* gauge)
+void icalfileset_clear(icalset* set)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)gauge;
-
- impl->gauge = 0;
+ icalfileset *fset = (icalfileset*) set;
+
+ icalerror_check_arg_rv(set!=0,"set");
+ fset->gauge = 0;
}
-icalcomponent* icalfileset_fetch(icalfileset* store,const char* uid)
+icalcomponent* icalfileset_fetch(icalset* set,const char* uid)
{
+ icalfileset *fset = (icalfileset*) set;
icalcompiter i;
- struct icalfileset_impl* impl = (struct icalfileset_impl*)store;
+
+ icalerror_check_arg_rz(set!=0,"set");
- for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT);
+ for(i = icalcomponent_begin_component(fset->cluster,ICAL_ANY_COMPONENT);
icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
- icalcomponent *this = icalcompiter_deref(&i);
- icalcomponent *inner = icalcomponent_get_first_real_component(this);
- icalcomponent *p;
- const char *this_uid;
-
- if(inner != 0){
- p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY);
- this_uid = icalproperty_get_uid(p);
-
- if(this_uid==0){
- icalerror_warn("icalfileset_fetch found a component with no UID");
- continue;
- }
-
- if (strcmp(uid,this_uid)==0){
- return this;
- }
+ icalcomponent *this = icalcompiter_deref(&i);
+ icalcomponent *inner;
+ icalproperty *p;
+ const char *this_uid;
+
+ for(inner = icalcomponent_get_first_component(this,ICAL_ANY_COMPONENT);
+ inner != 0;
+ inner = icalcomponent_get_next_component(this,ICAL_ANY_COMPONENT)){
+
+ p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY);
+ if ( p )
+ {
+ this_uid = icalproperty_get_uid(p);
+
+ if(this_uid==0){
+ icalerror_warn("icalfileset_fetch found a component with no UID");
+ continue;
+ }
+
+ if (strcmp(uid,this_uid)==0){
+ return this;
+ }
+ }
+ }
}
- }
return 0;
}
-int icalfileset_has_uid(icalfileset* store,const char* uid)
+int icalfileset_has_uid(icalset* set,const char* uid)
{
assert(0); /* HACK, not implemented */
return 0;
@@ -486,12 +531,11 @@ void icalfileset_id_free(struct icalfileset_id *id)
if(id->uid != 0){
free(id->uid);
}
-
}
+
struct icalfileset_id icalfileset_get_id(icalcomponent* comp)
{
-
icalcomponent *inner;
struct icalfileset_id id;
icalproperty *p;
@@ -527,19 +571,20 @@ struct icalfileset_id icalfileset_get_id(icalcomponent* comp)
return id;
}
+
/* Find the component that is related to the given
component. Currently, it just matches based on UID and
RECURRENCE-ID */
-icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *comp)
+icalcomponent* icalfileset_fetch_match(icalset* set, icalcomponent *comp)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)set;
+ icalfileset *fset = (icalfileset*) set;
icalcompiter i;
struct icalfileset_id comp_id, match_id;
comp_id = icalfileset_get_id(comp);
- for(i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT);
+ for(i = icalcomponent_begin_component(fset->cluster,ICAL_ANY_COMPONENT);
icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
icalcomponent *match = icalcompiter_deref(&i);
@@ -567,43 +612,45 @@ icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *comp)
}
-icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *old,
+icalerrorenum icalfileset_modify(icalset* set, icalcomponent *old,
icalcomponent *new)
{
+ icalfileset *fset = (icalfileset*) set;
+
assert(0); /* HACK, not implemented */
return ICAL_NO_ERROR;
}
/* Iterate through components */
-icalcomponent* icalfileset_get_current_component (icalfileset* cluster)
+icalcomponent* icalfileset_get_current_component (icalset* set)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+ icalfileset *fset = (icalfileset*) set;
- icalerror_check_arg_rz((cluster!=0),"cluster");
+ icalerror_check_arg_rz((set!=0),"set");
- return icalcomponent_get_current_component(impl->cluster);
+ return icalcomponent_get_current_component(fset->cluster);
}
-icalcomponent* icalfileset_get_first_component(icalfileset* cluster)
+icalcomponent* icalfileset_get_first_component(icalset* set)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
icalcomponent *c=0;
+ icalfileset *fset = (icalfileset*) set;
- icalerror_check_arg_rz((cluster!=0),"cluster");
+ icalerror_check_arg_rz((set!=0),"set");
do {
if (c == 0){
- c = icalcomponent_get_first_component(impl->cluster,
+ c = icalcomponent_get_first_component(fset->cluster,
ICAL_ANY_COMPONENT);
} else {
- c = icalcomponent_get_next_component(impl->cluster,
+ c = icalcomponent_get_next_component(fset->cluster,
ICAL_ANY_COMPONENT);
}
- if(c != 0 && (impl->gauge == 0 ||
- icalgauge_compare(impl->gauge,c) == 1)){
+ if(c != 0 && (fset->gauge == 0 ||
+ icalgauge_compare(fset->gauge, c) == 1)){
return c;
}
@@ -613,19 +660,19 @@ icalcomponent* icalfileset_get_first_component(icalfileset* cluster)
return 0;
}
-icalcomponent* icalfileset_get_next_component(icalfileset* cluster)
+icalcomponent* icalfileset_get_next_component(icalset* set)
{
- struct icalfileset_impl* impl = (struct icalfileset_impl*)cluster;
+ icalfileset *fset = (icalfileset*) set;
icalcomponent *c;
- icalerror_check_arg_rz((cluster!=0),"cluster");
+ icalerror_check_arg_rz((set!=0),"set");
do {
- c = icalcomponent_get_next_component(impl->cluster,
+ c = icalcomponent_get_next_component(fset->cluster,
ICAL_ANY_COMPONENT);
- if(c != 0 && (impl->gauge == 0 ||
- icalgauge_compare(impl->gauge,c) == 1)){
+ if(c != 0 && (fset->gauge == 0 ||
+ icalgauge_compare(fset->gauge,c) == 1)){
return c;
}
@@ -634,4 +681,241 @@ icalcomponent* icalfileset_get_next_component(icalfileset* cluster)
return 0;
}
+/*
+icalsetiter icalfileset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge)
+{
+ icalsetiter itr = icalsetiter_null;
+ icalcomponent* comp = NULL;
+ icalcompiter citr;
+ icalfileset *fset = (icalfileset*) set;
+
+ icalerror_check_arg_re((set!=0), "set", icalsetiter_null);
+
+ itr.gauge = gauge;
+
+ citr = icalcomponent_begin_component(fset->cluster, kind);
+ comp = icalcompiter_deref(&citr);
+
+ while (comp != 0) {
+ comp = icalcompiter_deref(&citr);
+ if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) {
+ itr.iter = citr;
+ return itr;
+ }
+ comp = icalcompiter_next(&citr);
+ }
+
+ return icalsetiter_null;
+}
+*/
+
+icalsetiter icalfileset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge)
+{
+ icalsetiter itr = icalsetiter_null;
+ icalcomponent* comp = NULL;
+ icalcompiter citr;
+ icalfileset *fset = (icalfileset*) set;
+ struct icaltimetype start, next;
+ icalproperty *dtstart, *rrule, *prop, *due;
+ struct icalrecurrencetype recur;
+ int g = 0;
+ icalerror_check_arg_re((set!=0), "set", icalsetiter_null);
+
+ itr.gauge = gauge;
+
+ citr = icalcomponent_begin_component(fset->cluster, kind);
+ comp = icalcompiter_deref(&citr);
+
+ if (gauge == 0) {
+ itr.iter = citr;
+ return itr;
+ }
+
+ while (comp != 0) {
+
+ /* check if it is a recurring component and with guage expand, if so
+ we need to add recurrence-id property to the given component */
+ rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
+ g = icalgauge_get_expand(gauge);
+
+ if (rrule != 0
+ && g == 1) {
+
+ recur = icalproperty_get_rrule(rrule);
+ if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) {
+ dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
+ if (dtstart)
+ start = icalproperty_get_dtstart(dtstart);
+ } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
+ due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
+ if (due)
+ start = icalproperty_get_due(due);
+ }
+
+ if (itr.last_component == NULL) {
+ itr.ritr = icalrecur_iterator_new(recur, start);
+ next = icalrecur_iterator_next(itr.ritr);
+ itr.last_component = comp;
+ }
+ else {
+ next = icalrecur_iterator_next(itr.ritr);
+ if (icaltime_is_null_time(next)){
+ itr.last_component = NULL;
+ icalrecur_iterator_free(itr.ritr);
+ itr.ritr = NULL;
+ return icalsetiter_null;
+ } else {
+ itr.last_component = comp;
+ }
+ }
+
+ /* add recurrence-id to the component
+ if there is a recurrence-id already, remove it, then add the new one */
+ if (prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY))
+ icalcomponent_remove_property(comp, prop);
+ icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next));
+
+ }
+
+ if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) {
+ /* matches and returns */
+ itr.iter = citr;
+ return itr;
+ }
+
+ /* if there is no previous component pending, then get the next component */
+ if (itr.last_component == NULL)
+ comp = icalcompiter_next(&citr);
+ }
+
+ return icalsetiter_null;
+}
+icalcomponent* icalfileset_form_a_matched_recurrence_component(icalsetiter* itr)
+{
+ icalcomponent* comp = NULL;
+ struct icaltimetype start, next;
+ icalproperty *dtstart, *rrule, *prop, *due;
+ struct icalrecurrencetype recur;
+
+ comp = itr->last_component;
+
+ if (comp == NULL || itr->gauge == NULL) {
+ return NULL;
+ }
+
+ rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
+
+ recur = icalproperty_get_rrule(rrule);
+
+ if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) {
+ dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
+ if (dtstart)
+ start = icalproperty_get_dtstart(dtstart);
+ } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
+ due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
+ if (due)
+ start = icalproperty_get_due(due);
+ }
+
+ if (itr->ritr == NULL) {
+ itr->ritr = icalrecur_iterator_new(recur, start);
+ next = icalrecur_iterator_next(itr->ritr);
+ itr->last_component = comp;
+ } else {
+ next = icalrecur_iterator_next(itr->ritr);
+ if (icaltime_is_null_time(next)){
+ /* no more recurrence, returns */
+ itr->last_component = NULL;
+ icalrecur_iterator_free(itr->ritr);
+ itr->ritr = NULL;
+ return NULL;
+ } else {
+ itr->last_component = comp;
+ }
+ }
+
+ /* add recurrence-id to the component
+ * if there is a recurrence-id already, remove it, then add the new one */
+ if (prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY))
+ icalcomponent_remove_property(comp, prop);
+ icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next));
+
+ if (itr->gauge == 0 || icalgauge_compare(itr->gauge, comp) == 1) {
+ /* matches and returns */
+ return comp;
+ }
+ /* not matched */
+ return NULL;
+
+}
+icalcomponent* icalfilesetiter_to_next(icalset* set, icalsetiter* i)
+{
+
+ icalcomponent* c = NULL;
+ icalfileset *fset = (icalfileset*) set;
+ struct icaltimetype start, next;
+ icalproperty *dtstart, *rrule, *prop, *due;
+ struct icalrecurrencetype recur;
+ int g = 0;
+
+
+ do {
+ c = icalcompiter_next(&(i->iter));
+
+ if (c == 0) continue;
+ if (i->gauge == 0) return c;
+
+
+ rrule = icalcomponent_get_first_property(c, ICAL_RRULE_PROPERTY);
+ g = icalgauge_get_expand(i->gauge);
+
+ /* a recurring component with expand query */
+ if (rrule != 0
+ && g == 1) {
+
+ recur = icalproperty_get_rrule(rrule);
+
+ if (icalcomponent_isa(c) == ICAL_VEVENT_COMPONENT) {
+ dtstart = icalcomponent_get_first_property(c, ICAL_DTSTART_PROPERTY);
+ if (dtstart)
+ start = icalproperty_get_dtstart(dtstart);
+ } else if (icalcomponent_isa(c) == ICAL_VTODO_COMPONENT) {
+ due = icalcomponent_get_first_property(c, ICAL_DUE_PROPERTY);
+ if (due)
+ start = icalproperty_get_due(due);
+ }
+
+ if (i->ritr == NULL) {
+ i->ritr = icalrecur_iterator_new(recur, start);
+ next = icalrecur_iterator_next(i->ritr);
+ i->last_component = c;
+ } else {
+ next = icalrecur_iterator_next(i->ritr);
+ if (icaltime_is_null_time(next)) {
+ /* no more recurrence, returns */
+ i->last_component = NULL;
+ icalrecur_iterator_free(i->ritr);
+ i->ritr = NULL;
+ return NULL;
+ } else {
+ i->last_component = c;
+ }
+ }
+ }
+
+ /* add recurrence-id to the component
+ * if there is a recurrence-id already, remove it, then add the new one */
+ if (prop = icalcomponent_get_first_property(c, ICAL_RECURRENCEID_PROPERTY))
+ icalcomponent_remove_property(c, prop);
+ icalcomponent_add_property(c, icalproperty_new_recurrenceid(next));
+
+ if(c != 0 && (i->gauge == 0 ||
+ icalgauge_compare(i->gauge, c) == 1)){
+ return c;
+ }
+ } while (c != 0);
+
+ return 0;
+
+}
diff --git a/libical/src/libicalss/icalfileset.h b/libical/src/libicalss/icalfileset.h
index c785921463..1a42307525 100644
--- a/libical/src/libicalss/icalfileset.h
+++ b/libical/src/libicalss/icalfileset.h
@@ -31,73 +31,99 @@
#include "ical.h"
#include "icalset.h"
+#include "icalcluster.h"
#include "icalgauge.h"
#include <sys/types.h> /* For open() flags and mode */
#include <sys/stat.h> /* For open() flags and mode */
#include <fcntl.h> /* For open() flags and mode */
-extern int icalfileset_safe_saves;
+#ifdef WIN32
+#define mode_t int
+#endif
-typedef void icalfileset;
+typedef struct icalfileset_impl icalfileset;
+icalset* icalfileset_new(const char* path);
+icalset* icalfileset_new_reader(const char* path);
+icalset* icalfileset_new_writer(const char* path);
-/* icalfileset
- icalfilesetfile
- icalfilesetdir
-*/
+icalset* icalfileset_init(icalset *set, const char *dsn, void* options);
+icalfileset* icalfileset_new_from_cluster(const char* path, icalcluster *cluster);
-icalfileset* icalfileset_new(const char* path);
+icalcluster* icalfileset_produce_icalcluster(const char *path);
-/* Like _new, but takes open() flags for opening the file */
-icalfileset* icalfileset_new_open(const char* path,
- int flags, mode_t mode);
+void icalfileset_free(icalset* cluster);
-void icalfileset_free(icalfileset* cluster);
-
-const char* icalfileset_path(icalfileset* cluster);
+const char* icalfileset_path(icalset* 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);
+void icalfileset_mark(icalset* set);
+icalerrorenum icalfileset_commit(icalset* set);
-icalerrorenum icalfileset_add_component(icalfileset* cluster,
+icalerrorenum icalfileset_add_component(icalset* set,
icalcomponent* child);
-icalerrorenum icalfileset_remove_component(icalfileset* cluster,
+icalerrorenum icalfileset_remove_component(icalset* set,
icalcomponent* child);
-int icalfileset_count_components(icalfileset* cluster,
+int icalfileset_count_components(icalset* set,
icalcomponent_kind kind);
-/* Restrict the component returned by icalfileset_first, _next to those
- that pass the gauge. _clear removes the gauge */
-icalerrorenum icalfileset_select(icalfileset* store, icalgauge* gauge);
-void icalfileset_clear(icalfileset* store);
+/**
+ * Restrict the component returned by icalfileset_first, _next to those
+ * that pass the gauge. _clear removes the gauge
+ */
+icalerrorenum icalfileset_select(icalset* set, icalgauge* gauge);
+
+/** clear the gauge **/
+void icalfileset_clear(icalset* set);
-/* Get and search for a component by uid */
-icalcomponent* icalfileset_fetch(icalfileset* cluster, const char* uid);
-int icalfileset_has_uid(icalfileset* cluster, const char* uid);
-icalcomponent* icalfileset_fetch_match(icalfileset* set, icalcomponent *c);
+/** Get and search for a component by uid **/
+icalcomponent* icalfileset_fetch(icalset* set, const char* uid);
+int icalfileset_has_uid(icalset* set, const char* uid);
+icalcomponent* icalfileset_fetch_match(icalset* set, icalcomponent *c);
-/* Modify components according to the MODIFY method of CAP. Works on
- the currently selected components. */
-icalerrorenum icalfileset_modify(icalfileset* store, icalcomponent *oldcomp,
+/**
+ * Modify components according to the MODIFY method of CAP. Works on the
+ * currently selected components.
+ */
+icalerrorenum icalfileset_modify(icalset* set,
+ icalcomponent *oldcomp,
icalcomponent *newcomp);
-/* Iterate through components. If a guage has been defined, these
+/* Iterate through components. If a gauge has been defined, these
will skip over components that do not pass the gauge */
-icalcomponent* icalfileset_get_current_component (icalfileset* cluster);
-icalcomponent* icalfileset_get_first_component(icalfileset* cluster);
-icalcomponent* icalfileset_get_next_component(icalfileset* cluster);
-/* Return a reference to the internal component. You probably should
+icalcomponent* icalfileset_get_current_component (icalset* cluster);
+icalcomponent* icalfileset_get_first_component(icalset* cluster);
+icalcomponent* icalfileset_get_next_component(icalset* cluster);
+
+/* External iterator for thread safety */
+icalsetiter icalfileset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge);
+icalcomponent * icalfilesetiter_to_next(icalset* set, icalsetiter *iter);
+icalcomponent* icalfileset_form_a_matched_recurrence_component(icalsetiter* itr);
+
+/** Return a reference to the internal component. You probably should
not be using this. */
-icalcomponent* icalfileset_get_component(icalfileset* cluster);
+icalcomponent* icalfileset_get_component(icalset* cluster);
+
+/**
+ * @brief options for opening an icalfileset.
+ *
+ * These options should be passed to the icalset_new() function
+ */
+
+typedef struct icalfileset_options {
+ int flags; /**< flags for open() O_RDONLY, etc */
+ mode_t mode; /**< file mode */
+ icalcluster *cluster; /**< use this cluster to initialize data */
+} icalfileset_options;
+extern icalfileset_options icalfileset_options_default;
#endif /* !ICALFILESET_H */
diff --git a/libical/src/libicalss/icalfilesetimpl.h b/libical/src/libicalss/icalfilesetimpl.h
index fcd3415121..fe39604225 100644
--- a/libical/src/libicalss/icalfilesetimpl.h
+++ b/libical/src/libicalss/icalfilesetimpl.h
@@ -25,6 +25,8 @@
======================================================================*/
+#ifndef ICALFILESETIMPL_H
+#define ICALFILESETIMPL_H
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -38,12 +40,14 @@
#define ICALFILESET_ID "fset"
struct icalfileset_impl {
-
- char id[5]; /*fset*/
- char *path;
- icalcomponent* cluster;
- icalgauge* gauge;
- int changed;
- int fd; /* file descriptor */
+ icalset super; /**< parent class */
+ char *path; /**< pathname of file */
+ icalfileset_options options; /**< copy of options passed to icalset_new() */
+
+ icalcomponent* cluster; /**< cluster containing data */
+ icalgauge* gauge; /**< gauge for filtering out data */
+ int changed; /**< boolean flag, 1 if data has changed */
+ int fd; /**< file descriptor */
};
+#endif
diff --git a/libical/src/libicalss/icalgauge.c b/libical/src/libicalss/icalgauge.c
index b958ecfc9d..f4854c747b 100644
--- a/libical/src/libicalss/icalgauge.c
+++ b/libical/src/libicalss/icalgauge.c
@@ -31,15 +31,17 @@
#include "icalgaugeimpl.h"
#include <stdlib.h>
-extern char* input_buffer;
-extern char* input_buffer_p;
-int ssparse(void);
+#include "icalssyacc.h"
-struct icalgauge_impl *icalss_yy_gauge;
+typedef void* yyscan_t;
-icalgauge* icalgauge_new_from_sql(char* sql)
+int ssparse(yyscan_t );
+
+
+icalgauge* icalgauge_new_from_sql(char* sql, int expand)
{
struct icalgauge_impl *impl;
+ yyscan_t yy_globals = NULL;
int r;
@@ -52,60 +54,82 @@ icalgauge* icalgauge_new_from_sql(char* sql)
impl->select = pvl_newlist();
impl->from = pvl_newlist();
impl->where = pvl_newlist();
+ impl->expand = expand;
+
+ sslex_init(&yy_globals);
+
+ ssset_extra(impl, yy_globals);
- icalss_yy_gauge = impl;
+ ss_scan_string(sql, yy_globals);
- input_buffer_p = input_buffer = sql;
- r = ssparse();
+ r = ssparse(yy_globals);
+ sslex_destroy(yy_globals);
- return impl;
+ if (r == 0) {
+ return impl;
+ }
+ else {
+ icalgauge_free(impl);
+ return NULL;
+ }
}
+int icalgauge_get_expand(icalgauge* gauge)
+{
+return (gauge->expand);
+
+}
void icalgauge_free(icalgauge* gauge)
{
- struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
struct icalgauge_where *w;
- assert(impl->select != 0);
- assert(impl->where != 0);
- assert(impl->from != 0);
+ assert(gauge->select != 0);
+ assert(gauge->where != 0);
+ assert(gauge->from != 0);
- if(impl->select){
- while( (w=pvl_pop(impl->select)) != 0){
+ if(gauge->select){
+ while( (w=pvl_pop(gauge->select)) != 0){
if(w->value != 0){
free(w->value);
}
free(w);
}
- pvl_free(impl->select);
+ pvl_free(gauge->select);
+ gauge->select = 0;
}
- if(impl->where){
- while( (w=pvl_pop(impl->where)) != 0){
+ if(gauge->where){
+ while( (w=pvl_pop(gauge->where)) != 0){
if(w->value != 0){
free(w->value);
}
free(w);
}
- pvl_free(impl->where);
+ pvl_free(gauge->where);
+ gauge->where = 0;
}
- if(impl->from){
- pvl_free(impl->from);
+ if(gauge->from){
+ pvl_free(gauge->from);
+ gauge->from = 0;
}
+
+ free(gauge);
}
-/* Convert a VQUERY component into a gauge */
+
+/** Convert a VQUERY component into a gauge */
icalcomponent* icalgauge_make_gauge(icalcomponent* query);
-/* icaldirset_test compares a component against a gauge, and returns
+/**
+ 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
+ target components. The gauge 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
@@ -252,26 +276,45 @@ int icalgauge_compare_recurse(icalcomponent* comp, icalcomponent* gauge)
int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
{
- struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
icalcomponent *inner;
int local_pass = 0;
int last_clause = 1, this_clause = 1;
pvl_elem e;
+ icalcomponent_kind kind;
+ icalproperty *rrule;
+ int compare_recur = 0;
+
icalerror_check_arg_rz( (comp!=0), "comp");
icalerror_check_arg_rz( (gauge!=0), "gauge");
+ if (gauge == 0 || comp == 0) return 0;
+
inner = icalcomponent_get_first_real_component(comp);
if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
+ /* Wally Yau: our component is not always wrapped with
+ * a <VCALENDAR>. It's not an error.
+ * icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ * return 0; */
+ kind = icalcomponent_isa(comp);
+ if(kind == ICAL_VEVENT_COMPONENT ||
+ kind == ICAL_VTODO_COMPONENT ||
+ kind == ICAL_VJOURNAL_COMPONENT ||
+ kind == ICAL_VQUERY_COMPONENT ||
+ kind == ICAL_VAGENDA_COMPONENT){
+ inner = comp;
+ }
+ else {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+ inner = comp;
}
-
/* Check that this component is one of the FROM types */
local_pass = 0;
- for(e = pvl_head(impl->from);e!=0;e=pvl_next(e)){
+ for(e = pvl_head(gauge->from);e!=0;e=pvl_next(e)){
icalcomponent_kind k = (icalcomponent_kind)pvl_data(e);
if(k == icalcomponent_isa(inner)){
@@ -284,8 +327,8 @@ int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
}
- /* Check each where clause against the component */
- for(e = pvl_head(impl->where);e!=0;e=pvl_next(e)){
+ /**** Check each where clause against the component ****/
+ for(e = pvl_head(gauge->where);e!=0;e=pvl_next(e)){
struct icalgauge_where *w = pvl_data(e);
icalcomponent *sub_comp;
icalvalue *v;
@@ -301,11 +344,14 @@ int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
vk = icalenum_property_kind_to_value_kind(w->prop);
if(vk == ICAL_NO_VALUE){
- icalerror_set_errno(ICAL_INTERNAL_ERROR);
+ icalerror_set_errno(ICAL_INTERNAL_ERROR);
return 0;
}
- v = icalvalue_new_from_string(vk,w->value);
+ if (w->compare == ICALGAUGECOMPARE_ISNULL || w->compare == ICALGAUGECOMPARE_ISNOTNULL)
+ v = icalvalue_new(vk);
+ else
+ v = icalvalue_new_from_string(vk,w->value);
if (v == 0){
/* Keep error set by icalvalue_from-string*/
@@ -324,14 +370,46 @@ int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
}
}
+ /* check if it is a recurring */
+ rrule = icalcomponent_get_first_property(sub_comp,ICAL_RRULE_PROPERTY);
+
+ if (gauge->expand
+ && rrule) {
+
+ if (w->prop == ICAL_DTSTART_PROPERTY ||
+ w->prop == ICAL_DTEND_PROPERTY ||
+ w->prop == ICAL_DUE_PROPERTY){
+ /** needs to use recurrence-id to do comparison */
+ compare_recur = 1;
+ }
+
+ }
+
+
this_clause = 0;
- local_pass = 0;
+ local_pass = (w->compare == ICALGAUGECOMPARE_ISNULL) ? 1 : 0;
+
for(prop = icalcomponent_get_first_property(sub_comp,w->prop);
prop != 0;
prop = icalcomponent_get_next_property(sub_comp,w->prop)){
icalvalue* prop_value;
icalgaugecompare relation;
+ if (w->compare == ICALGAUGECOMPARE_ISNULL) {
+ local_pass = 0;
+ break;
+ }
+
+ if (w->compare == ICALGAUGECOMPARE_ISNOTNULL) {
+ local_pass = 1;
+ break;
+ }
+
+ if (compare_recur) {
+ icalproperty *p = icalcomponent_get_first_property(sub_comp, ICAL_RECURRENCEID_PROPERTY);
+ prop_value = icalproperty_get_value(p);
+ }
+ else /* prop value from this component */
prop_value = icalproperty_get_value(prop);
relation = (icalgaugecompare)icalvalue_compare(prop_value,v);
@@ -355,34 +433,40 @@ int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
}
}
+
this_clause = local_pass > 0 ? 1 : 0;
+
/* Now look at the logic operator for this clause to see how
the value should be merge with the previous clause */
if(w->logic == ICALGAUGELOGIC_AND){
last_clause = this_clause && last_clause;
- } else if(w->logic == ICALGAUGELOGIC_AND) {
+ } else if(w->logic == ICALGAUGELOGIC_OR) {
last_clause = this_clause || last_clause;
} else {
last_clause = this_clause;
}
- }
+
+ icalvalue_free(v);
+
+ }/**** check next one in where clause ****/
return last_clause;
}
+/** @brief Debug
+ * Print gauge information to stdout.
+ */
-void icalgauge_dump(icalcomponent* gauge)
+void icalgauge_dump(icalgauge* gauge)
{
- pvl_elem *p;
- struct icalgauge_impl *impl = (struct icalgauge_impl*)gauge;
-
+ pvl_elem p;
printf("--- Select ---\n");
- for(p = pvl_head(impl->select);p!=0;p=pvl_next(p)){
+ for(p = pvl_head(gauge->select);p!=0;p=pvl_next(p)){
struct icalgauge_where *w = pvl_data(p);
if(w->comp != ICAL_NO_COMPONENT){
@@ -407,14 +491,14 @@ void icalgauge_dump(icalcomponent* gauge)
}
printf("--- From ---\n");
- for(p = pvl_head(impl->from);p!=0;p=pvl_next(p)){
+ for(p = pvl_head(gauge->from);p!=0;p=pvl_next(p)){
icalcomponent_kind k = (icalcomponent_kind)pvl_data(p);
printf("%s\n",icalenum_component_kind_to_string(k));
}
printf("--- Where ---\n");
- for(p = pvl_head(impl->where);p!=0;p=pvl_next(p)){
+ for(p = pvl_head(gauge->where);p!=0;p=pvl_next(p)){
struct icalgauge_where *w = pvl_data(p);
if(w->logic != ICALGAUGELOGIC_NONE){
@@ -441,7 +525,5 @@ void icalgauge_dump(icalcomponent* gauge)
printf("\n");
}
-
-
}
diff --git a/libical/src/libicalss/icalgauge.h b/libical/src/libicalss/icalgauge.h
index 1caf0ac7d1..c35b4f7508 100644
--- a/libical/src/libicalss/icalgauge.h
+++ b/libical/src/libicalss/icalgauge.h
@@ -29,23 +29,33 @@
#ifndef ICALGAUGE_H
#define ICALGAUGE_H
-typedef void icalgauge;
+/** @file icalgauge.h
+ * @brief Routines implementing a filter for ical components
+ */
-icalgauge* icalgauge_new_from_sql(char* sql);
+typedef struct icalgauge_impl icalgauge;
+
+icalgauge* icalgauge_new_from_sql(char* sql, int expand);
+
+int icalgauge_get_expand(icalgauge* gauge);
void icalgauge_free(icalgauge* gauge);
char* icalgauge_as_sql(icalcomponent* gauge);
-void icalgauge_dump(icalcomponent* gauge);
+void icalgauge_dump(icalgauge* gauge);
+
-/* Return true is comp matches the gauge. The component must be in
- cannonical form -- a VCALENDAR with one VEVENT, VTODO or VJOURNAL
- sub component */
+/** @brief Return true if comp matches the gauge.
+ *
+ * The component must be in
+ * cannonical form -- a VCALENDAR with one VEVENT, VTODO or VJOURNAL
+ * sub component
+ */
int icalgauge_compare(icalgauge* g, icalcomponent* comp);
-/* Clone the component, but only return the properties specified in
- the gauge */
+/** Clone the component, but only return the properties
+ * specified in the gauge */
icalcomponent* icalgauge_new_clone(icalgauge* g, icalcomponent* comp);
#endif /* ICALGAUGE_H*/
diff --git a/libical/src/libicalss/icalgaugeimpl.h b/libical/src/libicalss/icalgaugeimpl.h
index 73a2813242..e56b1c01c1 100644
--- a/libical/src/libicalss/icalgaugeimpl.h
+++ b/libical/src/libicalss/icalgaugeimpl.h
@@ -24,8 +24,6 @@
#include "ical.h"
-#include "pvl.h"
-
typedef enum icalgaugecompare {
ICALGAUGECOMPARE_EQUAL=ICAL_XLICCOMPARETYPE_EQUAL,
ICALGAUGECOMPARE_LESS=ICAL_XLICCOMPARETYPE_LESS,
@@ -34,6 +32,8 @@ typedef enum icalgaugecompare {
ICALGAUGECOMPARE_GREATEREQUAL=ICAL_XLICCOMPARETYPE_GREATEREQUAL,
ICALGAUGECOMPARE_NOTEQUAL=ICAL_XLICCOMPARETYPE_NOTEQUAL,
ICALGAUGECOMPARE_REGEX=ICAL_XLICCOMPARETYPE_REGEX,
+ ICALGAUGECOMPARE_ISNULL=ICAL_XLICCOMPARETYPE_ISNULL,
+ ICALGAUGECOMPARE_ISNOTNULL=ICAL_XLICCOMPARETYPE_ISNOTNULL,
ICALGAUGECOMPARE_NONE=0
} icalgaugecompare;
@@ -54,10 +54,10 @@ struct icalgauge_where {
struct icalgauge_impl
{
-
- pvl_list select; /*Of icalgaugecompare, using only prop and comp fields*/
- pvl_list from; /* List of component_kinds, as integers */
- pvl_list where; /* List of icalgaugecompare */
+ pvl_list select; /**< Of icalgaugecompare, using only prop and comp fields*/
+ pvl_list from; /**< List of component_kinds, as integers */
+ pvl_list where; /**< List of icalgaugecompare */
+ int expand;
};
diff --git a/libical/src/libicalss/icalmessage.c b/libical/src/libicalss/icalmessage.c
index e1e8d8015c..731a2c7cfc 100644
--- a/libical/src/libicalss/icalmessage.c
+++ b/libical/src/libicalss/icalmessage.c
@@ -40,7 +40,7 @@ icalcomponent* icalmessage_get_inner(icalcomponent* comp)
}
}
-char* lowercase(const char* str)
+static char* lowercase(const char* str)
{
char* p = 0;
char* n = icalmemory_strdup(str);
@@ -158,8 +158,13 @@ icalcomponent *icalmessage_new_reply_base(icalcomponent* c,
icalcomponent_add_property(reply,icalproperty_new_version("2.0"));
+#ifndef WIN32
sprintf(tmp,
"-//SoftwareStudio//NONSGML %s %s //EN",PACKAGE,VERSION);
+#else
+ sprintf(tmp,
+ "-//SoftwareStudio//NONSGML %s %s //EN",ICAL_PACKAGE,ICAL_VERSION);
+#endif
icalcomponent_add_property(reply,icalproperty_new_prodid(tmp));
return reply;
@@ -230,11 +235,11 @@ icalcomponent* icalmessage_new_counterpropose_reply(icalcomponent* oldc,
icalerror_check_arg_rz(oldc,"oldc");
icalerror_check_arg_rz(newc,"newc");
- reply = icalcomponent_new_clone(newc);
+ reply = icalmessage_new_reply_base(newc,user,msg);
icalcomponent_set_method(reply,ICAL_METHOD_COUNTER);
- return newc;
+ return reply;
}
@@ -353,10 +358,7 @@ icalcomponent* icalmessage_new_error_reply(icalcomponent* c,
rs.debug = debug;
icalcomponent_add_property(inner,
- icalproperty_new_requeststatus(
- icalreqstattype_as_string(rs)
- )
- );
+ icalproperty_new_requeststatus(rs));
} else { /* code == ICAL_UNKNOWN_STATUS */
/* Copy all of the request status properties */
diff --git a/libical/src/libicalss/icalset.c b/libical/src/libicalss/icalset.c
index 2120609928..0ad22696f7 100644
--- a/libical/src/libicalss/icalset.c
+++ b/libical/src/libicalss/icalset.c
@@ -41,33 +41,26 @@
#include "icaldirset.h"
#include "icaldirsetimpl.h"
#include <stdlib.h>
-/*#include "icalheapset.h"*/
-/*#include "icalmysqlset.h"*/
-
-#define ICALSET_ID "set "
-
-struct icalset_fp {
- void (*free)(icalset* set);
- const char* (*path)(icalset* set);
- void (*mark)(icalset* set);
- icalerrorenum (*commit)(icalset* set);
- icalerrorenum (*add_component)(icalset* set, icalcomponent* comp);
- icalerrorenum (*remove_component)(icalset* set, icalcomponent* comp);
- int (*count_components)(icalset* set,
- icalcomponent_kind kind);
- icalerrorenum (*select)(icalset* set, icalcomponent* gauge);
- void (*clear)(icalset* set);
- icalcomponent* (*fetch)(icalset* set, const char* uid);
- icalcomponent* (*fetch_match)(icalset* set, icalcomponent *comp);
- int (*has_uid)(icalset* set, const char* uid);
- icalerrorenum (*modify)(icalset* set, icalcomponent *old,
- icalcomponent *new);
- icalcomponent* (*get_current_component)(icalset* set);
- icalcomponent* (*get_first_component)(icalset* set);
- icalcomponent* (*get_next_component)(icalset* set);
-};
-
-struct icalset_fp icalset_dirset_fp = {
+#include <string.h>
+#include <errno.h>
+
+#ifdef WITH_BDB4
+#include "icalbdbset.h"
+#include "icalbdbsetimpl.h"
+#endif
+
+/* #define _DLOPEN_TEST */
+#ifdef _DLOPEN_TEST
+#include <sys/types.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#endif
+
+static icalset icalset_dirset_init = {
+ ICAL_DIR_SET,
+ sizeof(icaldirset),
+ NULL,
+ icaldirset_init,
icaldirset_free,
icaldirset_path,
icaldirset_mark,
@@ -83,11 +76,18 @@ struct icalset_fp icalset_dirset_fp = {
icaldirset_modify,
icaldirset_get_current_component,
icaldirset_get_first_component,
- icaldirset_get_next_component
+ icaldirset_get_next_component,
+ icaldirset_begin_component,
+ icaldirsetiter_to_next,
+ icaldirsetiter_to_prior
};
-struct icalset_fp icalset_fileset_fp = {
+static icalset icalset_fileset_init = {
+ ICAL_FILE_SET,
+ sizeof(icalfileset),
+ NULL,
+ icalfileset_init,
icalfileset_free,
icalfileset_path,
icalfileset_mark,
@@ -103,265 +103,391 @@ struct icalset_fp icalset_fileset_fp = {
icalfileset_modify,
icalfileset_get_current_component,
icalfileset_get_first_component,
- icalfileset_get_next_component
+ icalfileset_get_next_component,
+ icalfileset_begin_component,
+ icalfilesetiter_to_next,
+ NULL
};
-struct icalset_impl {
+#ifdef WITH_BDB4
+static icalset icalset_bdbset_init = {
+ ICAL_BDB_SET,
+ sizeof(icalbdbset),
+ NULL,
+ icalbdbset_init,
+ icalbdbset_free,
+ icalbdbset_path,
+ icalbdbset_mark,
+ icalbdbset_commit,
+ icalbdbset_add_component,
+ icalbdbset_remove_component,
+ icalbdbset_count_components,
+ icalbdbset_select,
+ icalbdbset_clear,
+ icalbdbset_fetch,
+ icalbdbset_fetch_match,
+ icalbdbset_has_uid,
+ icalbdbset_modify,
+ icalbdbset_get_current_component,
+ icalbdbset_get_first_component,
+ icalbdbset_get_next_component,
+ icalbdbset_begin_component,
+ icalbdbsetiter_to_next,
+ NULL
+};
+#endif
- char id[5]; /* "set " */
+#ifdef _DLOPEN_TEST
+static int icalset_init_done = 0;
+static pvl_list icalset_kinds = 0;
- void *derived_impl;
- struct icalset_fp *fp;
-};
+typedef icalset *(*fptr)(void);
-/* Figure out what was actually passed in as the set. This could be a
- set or and of the derived types such as dirset or fileset. Note
- this routine returns a value, not a reference, to avoid memory
- leaks in the methods */
-struct icalset_impl icalset_get_impl(icalset* set)
-{
- struct icalset_impl impl;
-
- memset(&impl,0,sizeof(impl));
- icalerror_check_arg_re( (set!=0),"set",impl);
-
- if(strcmp((char*)set,ICALSET_ID)==0) {
- /* It is actually a set, so just sent the reference back out. */
- return *(struct icalset_impl*)set;
- } else if(strcmp((char*)set,ICALFILESET_ID)==0) {
- /* Make a new set from the fileset */
- impl.fp = &icalset_fileset_fp;
- impl.derived_impl = set;
- strcpy(impl.id,ICALFILESET_ID);/* HACK. Is this necessary? */
- return impl;
- } else if(strcmp((char*)set,ICALDIRSET_ID)==0) {
- /* Make a new set from the dirset */
- impl.fp = &icalset_dirset_fp;
- impl.derived_impl = set;
- strcpy(impl.id,ICALDIRSET_ID);/* HACK. Is this necessary? */
- return impl;
- } else {
- /* The type of set is unknown, so throw an error */
- icalerror_assert((0),"Unknown set type");
- return impl;
- }
+/**
+ * Try to load the file and register any icalset found within.
+ */
+static int load(const char *file) {
+
+ void *modh;
+ fptr inith;
+ icalset *icalset_init_ptr;
+
+ if ((modh = dlopen(file, RTLD_NOW)) == 0) {
+ perror("dlopen");
+ return 0;
+ }
+
+ if ((inith = (fptr)dlsym(modh, "InitModule")) == 0) {
+ perror("dlsym");
+ return 0;
+ }
+
+ while ((icalset_init_ptr = ((inith)())) != 0) {
+ pvl_push(icalset_kinds, &icalset_init_ptr);
+ }
+
+ return 1;
}
+/**
+ * Look in the given directory for files called mod_*.o and try to
+ * load them.
+ */
+int icalset_loaddir(const char *path) {
+ DIR *d;
+ struct dirent *dp;
+ char buf[PATH_MAX],
+ *bufptr;
+ int tot = 0;
-struct icalset_impl* icalset_new_impl()
-{
-
- struct icalset_impl* impl;
+ strcpy(buf, path);
+ bufptr = buf + strlen(buf);
- if ( ( impl = (struct icalset_impl*)
- malloc(sizeof(struct icalset_impl))) == 0) {
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- return 0;
- }
+ if (*(bufptr-1) != '/')
+ *bufptr++ = '/';
- strcpy(impl->id,ICALSET_ID);
+ if ((d = opendir(path)) == 0) {
+ perror("opendir");
+ return 0;
+ }
- impl->derived_impl = 0;
- impl->fp = 0;
+ while ((dp = readdir(d)) != 0) {
+ if (strncmp(dp->d_name, "mod_", 4)) continue;
- return impl;
-}
+ strcpy(bufptr, dp->d_name);
-struct icalset_impl* icalset_new_file_from_ref(icalfileset *fset)
-{
- struct icalset_impl *impl = icalset_new_impl();
+ load(buf);
+ tot++;
+ }
+ (void)closedir(d);
- icalerror_check_arg_rz( (fset!=0),"fset");
+ return 1;
+}
- if(impl == 0){
- free(impl);
- return 0;
- }
+int icalset_register_class(icalset *set);
- impl->derived_impl = fset;
+static void icalset_init(void) {
+ assert(icalset_kinds == 0);
+ icalset_kinds = pvl_newlist();
- if (impl->derived_impl == 0){
- free(impl);
- return 0;
- }
+ pvl_push(icalset_kinds, &icalset_fileset_init);
+ pvl_push(icalset_kinds, &icalset_dirset_init);
+#ifdef WITH_BDB4
+ pvl_push(icalset_kinds, &icalset_bdb4set_init);
+#endif
- impl->fp = &icalset_fileset_fp;
+#ifdef EXT_PATH
+ icalset_loaddir(EXT_PATH);
+#endif
- return (struct icalset_impl*)impl;
+ icalset_init_done++;
}
-icalset* icalset_new_file(const char* path)
-{
- icalfileset *fset = icalfileset_new(path);
+int icalset_register_class(icalset *set) {
- if(fset == 0){
- return 0;
- }
+ if (!icalset_init_done)
+ icalset_init();
- return (icalset*)icalset_new_file_from_ref(fset);
+ pvl_push(icalset_kinds, set);
+ return 1;
}
-icalset* icalset_new_dir_from_ref(icaldirset *dset)
-{
+#endif
- struct icalset_impl *impl = icalset_new_impl();
+icalset* icalset_new(icalset_kind kind, const char* dsn, void* options) {
+ icalset *data = NULL;
+ icalset *ret = NULL;
- icalerror_check_arg_rz( (dset!=0),"dset");
+#ifdef _DLOPEN_TEST
+ pvl_elem e;
+ icalset *impl;
- if(impl == 0){
- return 0;
+ if (!icalset_init_done)
+ icalset_init();
+
+ for(e = pvl_head(icalset_kinds); e!=0; e = pvl_next(e)) {
+ impl = (icalset*)pvl_data(e);
+ if (impl->kind == kind)
+ break;
+ }
+ if (e == 0) {
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
+ return(NULL);
}
- impl->derived_impl = dset;
+ data = (icalset*)malloc(impl->size);
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
- if (impl->derived_impl == 0){
- free(impl);
+ /* The first member of the derived class must be an icalset. */
+ memset(data,0,impl->size);
+ /* *data = *impl; */
+ memcpy(data, impl, sizeof(icalset));
+
+ data->dsn = strdup(dsn);
+#else
+ switch(kind) {
+ case ICAL_FILE_SET:
+ data = (icalset*) malloc(sizeof(icalfileset));
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(data,0,sizeof(icalfileset));
+ *data = icalset_fileset_init;
+ break;
+ case ICAL_DIR_SET:
+ data = (icalset*) malloc(sizeof(icaldirset));
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(data,0,sizeof(icaldirset));
+ *data = icalset_dirset_init;
+ break;
+#ifdef WITH_BDB4
+ case ICAL_BDB_SET:
+ data = (icalset*) malloc(sizeof(icalbdbset));
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
return 0;
}
+ memset(data,0,sizeof(icalbdbset));
+ *data = icalset_bdbset_init;
+ break;
+#endif
+
+ default:
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
+ /** unimplemented **/
+ return(NULL);
+ }
+
+ if ( data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+ data->kind = kind;
+ data->dsn = strdup(dsn);
+#endif
- impl->fp = &icalset_dirset_fp;
+ /** call the implementation specific initializer **/
+ if ((ret = data->init(data, dsn, options)) == NULL)
+ icalset_free(data);
- return impl;
+ return ret;
}
-icalset* icalset_new_dir(const char* path)
+icalset* icalset_new_file(const char* path)
{
- icaldirset *dset = icaldirset_new(path);
-
- if(dset == 0){
- return 0;
- }
+ return icalset_new(ICAL_FILE_SET, path, NULL);
+}
- return icalset_new_dir_from_ref(dset);
+icalset* icalset_new_file_writer(const char* path)
+{
+ return icalfileset_new_writer(path);
}
-icalset* icalset_new_heap(void)
+icalset* icalset_new_file_reader(const char* path)
{
- struct icalset_impl *impl = icalset_new_impl();
+ return icalfileset_new_reader(path);
+}
- if(impl == 0){
- free(impl);
- return 0;
- }
+icalset* icalset_new_dir(const char* path)
+{
+ return icalset_new(ICAL_DIR_SET, path, NULL);
+}
- return 0;
+icalset* icalset_new_dir_writer(const char* path)
+{
+ return icaldirset_new_writer(path);
}
-icalset* icalset_new_mysql(const char* path)
+icalset* icalset_new_dir_reader(const char* path)
{
- struct icalset_impl *impl = icalset_new_impl();
+ return icaldirset_new_reader(path);
+}
- if(impl == 0){
- free(impl);
- return 0;
- }
- return 0;
-}
+
+/* Functions for built-in methods */
+
+/**
+ * free memory associated with this icalset
+ * automatically calls the implementation specific free routine
+ */
void icalset_free(icalset* set)
{
- struct icalset_impl impl = icalset_get_impl(set);
- (*(impl.fp->free))(impl.derived_impl);
+ if (set->free)
+ set->free(set);
- if(strcmp((char*)set,ICALSET_ID)) {
- free(set);
- }
-}
+ if (set->dsn)
+ free(set->dsn);
-const char* icalset_path(icalset* set)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->path))(impl.derived_impl);
+ free(set);
}
-void icalset_mark(icalset* set)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- (*(impl.fp->mark))(impl.derived_impl);
+
+const char* icalset_path(icalset* set) {
+ return set->path(set);
}
-icalerrorenum icalset_commit(icalset* set)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->commit))(impl.derived_impl);
+void icalset_mark(icalset* set) {
+ set->mark(set);
}
-icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->add_component))(impl.derived_impl,comp);
+icalerrorenum icalset_commit(icalset* set) {
+ return set->commit(set);
}
-icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->remove_component))(impl.derived_impl,comp);
+icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) {
+ return set->add_component(set,comp);
}
-int icalset_count_components(icalset* set,icalcomponent_kind kind)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->count_components))(impl.derived_impl,kind);
+icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) {
+ return set->remove_component(set,comp);
}
-icalerrorenum icalset_select(icalset* set, icalcomponent* gauge)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->select))(impl.derived_impl,gauge);
+int icalset_count_components(icalset* set,icalcomponent_kind kind) {
+ return set->count_components(set,kind);
}
-void icalset_clear(icalset* set)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- (*(impl.fp->clear))(impl.derived_impl);
+icalerrorenum icalset_select(icalset* set, icalgauge* gauge) {
+ return set->select(set, gauge);
}
-icalcomponent* icalset_fetch(icalset* set, const char* uid)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->fetch))(impl.derived_impl,uid);
+void icalset_clear(icalset* set) {
+ set->clear(set);
}
-icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->fetch_match))(impl.derived_impl,comp);
+icalcomponent* icalset_fetch(icalset* set, const char* uid) {
+ return set->fetch(set, uid);
}
+icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) {
+ return set->fetch_match(set, comp);
+}
-int icalset_has_uid(icalset* set, const char* uid)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->has_uid))(impl.derived_impl,uid);
+int icalset_has_uid(icalset* set, const char* uid) {
+ return set->has_uid(set, uid);
}
icalerrorenum icalset_modify(icalset* set, icalcomponent *old,
- icalcomponent *new)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->modify))(impl.derived_impl,old,new);
+ icalcomponent *new) {
+ return set->modify(set, old, new);
}
-icalcomponent* icalset_get_current_component(icalset* set)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->get_current_component))(impl.derived_impl);
+icalcomponent* icalset_get_current_component(icalset* set) {
+ return set->get_current_component(set);
}
-icalcomponent* icalset_get_first_component(icalset* set)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->get_first_component))(impl.derived_impl);
+icalcomponent* icalset_get_first_component(icalset* set) {
+ return set->get_first_component(set);
}
-icalcomponent* icalset_get_next_component(icalset* set)
-{
- struct icalset_impl impl = icalset_get_impl(set);
- return (*(impl.fp->get_next_component))(impl.derived_impl);
+icalcomponent* icalset_get_next_component(icalset* set) {
+ return set->get_next_component(set);
+}
+
+icalsetiter icalsetiter_null = {{ICAL_NO_COMPONENT, 0}, 0};
+
+icalsetiter icalset_begin_component(icalset* set,
+ icalcomponent_kind kind, icalgauge* gauge) {
+ return set->icalset_begin_component(set, kind, gauge);
+}
+
+icalcomponent* icalsetiter_next(icalsetiter* itr) {
+
+ icalcomponent* c = 0;
+ icalerror_check_arg_rz( (itr != NULL), "i");
+
+ do {
+ c = icalcompiter_next(&(itr->iter));
+ if(c != 0 && (itr->gauge == 0 ||
+ icalgauge_compare(itr->gauge, c) == 1)){
+ return c;
+ }
+ } while (c != 0);
+
+ return 0;
}
+icalcomponent* icalsetiter_prior(icalsetiter* i) {
+
+ icalcomponent* c = 0;
+ icalerror_check_arg_rz( (i != NULL), "i" );
+
+ do {
+ c = icalcompiter_prior(&(i->iter));
+ if(c != 0 && (i->gauge == 0 ||
+ icalgauge_compare(i->gauge, c) == 1)){
+ return c;
+ }
+ } while (c != 0);
+
+ return 0;
+}
+icalcomponent* icalsetiter_deref(icalsetiter* i) {
+ icalerror_check_arg_rz( (i != NULL), "i" );
+ return (icalcompiter_deref(&(i->iter)));
+}
+/* for subclasses that use multiple clusters that require specialized cluster traversal */
+icalcomponent* icalsetiter_to_next(icalset* set, icalsetiter* i)
+{
+ return set->icalsetiter_to_next(set, i);
+}
+icalcomponent* icalsetiter_to_prior(icalset* set, icalsetiter* i)
+{
+ return set->icalsetiter_to_prior(set, i);
+}
diff --git a/libical/src/libicalss/icalset.h b/libical/src/libicalss/icalset.h
index 7b083dae24..4008c6216f 100644
--- a/libical/src/libicalss/icalset.h
+++ b/libical/src/libicalss/icalset.h
@@ -1,17 +1,19 @@
/* -*- Mode: C -*- */
-/*======================================================================
- FILE: icalset.h
- CREATOR: eric 28 November 1999
-
+/**
+ @file icalset.h
+ @author 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
+ icalfileset Store components in a single file
icaldirset Store components in multiple files in a directory
+ icalbdbset Store components in a Berkeley DB File
icalheapset Store components on the heap
icalmysqlset Store components in a mysql database.
+**/
+/*
$Id$
$Locker$
@@ -39,7 +41,7 @@
#include <limits.h> /* For PATH_MAX */
#include "ical.h"
-#include "icalerror.h"
+#include "icalgauge.h"
#ifdef PATH_MAX
#define ICAL_PATH_MAX PATH_MAX
@@ -48,33 +50,86 @@
#endif
-
-
-typedef void icalset;
+typedef struct icalset_impl icalset;
typedef enum icalset_kind {
ICAL_FILE_SET,
ICAL_DIR_SET,
- ICAL_HEAP_SET,
- ICAL_MYSQL_SET,
- ICAL_CAP_SET
+ ICAL_BDB_SET
} icalset_kind;
+typedef struct icalsetiter
+{
+ icalcompiter iter; /* icalcomponent_kind, pvl_elem iter */
+ icalgauge* gauge;
+ icalrecur_iterator* ritr; /*the last iterator*/
+ icalcomponent* last_component; /*the pending recurring component to be processed */
+ const char* tzid; /* the calendar's timezone id */
+} icalsetiter;
+
+struct icalset_impl {
+ icalset_kind kind;
+ int size;
+ char *dsn;
+ icalset* (*init)(icalset* set, const char *dsn, void *options);
+ void (*free)(icalset* set);
+ const char* (*path)(icalset* set);
+ void (*mark)(icalset* set);
+ icalerrorenum (*commit)(icalset* set);
+ icalerrorenum (*add_component)(icalset* set, icalcomponent* comp);
+ icalerrorenum (*remove_component)(icalset* set, icalcomponent* comp);
+ int (*count_components)(icalset* set,
+ icalcomponent_kind kind);
+ icalerrorenum (*select)(icalset* set, icalgauge* gauge);
+ void (*clear)(icalset* set);
+ icalcomponent* (*fetch)(icalset* set, const char* uid);
+ icalcomponent* (*fetch_match)(icalset* set, icalcomponent *comp);
+ int (*has_uid)(icalset* set, const char* uid);
+ icalerrorenum (*modify)(icalset* set, icalcomponent *old,
+ icalcomponent *newc);
+ icalcomponent* (*get_current_component)(icalset* set);
+ icalcomponent* (*get_first_component)(icalset* set);
+ icalcomponent* (*get_next_component)(icalset* set);
+ icalsetiter (*icalset_begin_component)(icalset* set,
+ icalcomponent_kind kind, icalgauge* gauge);
+ icalcomponent* (*icalsetiter_to_next)(icalset* set, icalsetiter* i);
+ icalcomponent* (*icalsetiter_to_prior)(icalset* set, icalsetiter* i);
+};
+
+/** @brief Register a new derived class */
+int icalset_register_class(icalset *set);
+
+
+/** @brief Generic icalset constructor
+ *
+ * @param kind The type of icalset to create
+ * @param dsn Data Source Name - usually a pathname or DB handle
+ * @param options Any implementation specific options
+ *
+ * @return A valid icalset reference or NULL if error.
+ *
+ * This creates any of the icalset types available.
+ */
+
+icalset* icalset_new(icalset_kind kind, const char* dsn, void* options);
-/* Create a specific derived type of set */
icalset* icalset_new_file(const char* path);
+icalset* icalset_new_file_reader(const char* path);
+icalset* icalset_new_file_writer(const char* path);
+
icalset* icalset_new_dir(const char* path);
-icalset* icalset_new_heap(void);
-icalset* icalset_new_mysql(const char* path);
-/*icalset* icalset_new_cap(icalcstp* cstp);*/
+icalset* icalset_new_file_reader(const char* path);
+icalset* icalset_new_file_writer(const char* path);
void icalset_free(icalset* set);
const 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*/
+/** Mark the cluster as changed, so it will be written to disk when it
+ is freed. **/
void icalset_mark(icalset* set);
+
+/** Write changes to disk immediately */
icalerrorenum icalset_commit(icalset* set);
icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp);
@@ -83,28 +138,46 @@ 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);
+/** Restrict the component returned by icalset_first, _next to those
+ that pass the gauge. */
+icalerrorenum icalset_select(icalset* set, icalgauge* gauge);
+
+/** Clears the gauge defined by icalset_select() */
void icalset_clear_select(icalset* set);
-/* Get a component by uid */
+/** Get a component by uid */
icalcomponent* icalset_fetch(icalset* set, const char* uid);
+
int icalset_has_uid(icalset* set, const char* uid);
icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *c);
-/* Modify components according to the MODIFY method of CAP. Works on
+/** Modify components according to the MODIFY method of CAP. Works on
the currently selected components. */
icalerrorenum icalset_modify(icalset* set, icalcomponent *oldc,
icalcomponent *newc);
-/* Iterate through the components. If a guage has been defined, these
+/** 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);
+/** External Iterator with gauge - for thread safety */
+extern icalsetiter icalsetiter_null;
+
+icalsetiter icalset_begin_component(icalset* set,
+ icalcomponent_kind kind, icalgauge* gauge);
+
+/** Default _next, _prior, _deref for subclasses that use single cluster */
+icalcomponent* icalsetiter_next(icalsetiter* i);
+icalcomponent* icalsetiter_prior(icalsetiter* i);
+icalcomponent* icalsetiter_deref(icalsetiter* i);
+
+/** for subclasses that use multiple clusters that require specialized cluster traversal */
+icalcomponent* icalsetiter_to_next(icalset* set, icalsetiter* i);
+icalcomponent* icalsetiter_to_prior(icalset* set, icalsetiter* i);
+
#endif /* !ICALSET_H */
diff --git a/libical/src/libicalss/icalspanlist.c b/libical/src/libicalss/icalspanlist.c
index cab6a81c68..f42ff41ed8 100644
--- a/libical/src/libicalss/icalspanlist.c
+++ b/libical/src/libicalss/icalspanlist.c
@@ -28,14 +28,27 @@
#include "ical.h"
#include "icalspanlist.h"
-#include "pvl.h"
+
#include <stdlib.h> /* for free and malloc */
+#include <string.h>
struct icalspanlist_impl {
- pvl_list spans;
+ pvl_list spans; /**< list of icaltime_span data **/
+ struct icaltimetype start; /**< start time of span **/
+ struct icaltimetype end; /**< end time of span **/
};
-int compare_span(void* a, void* b)
+/** @brief Internal comparison function for two spans
+ *
+ * @param a a spanlist.
+ * @param b another spanlist.
+ *
+ * @return -1, 0, 1 depending on the comparison of the start times.
+ *
+ * Used to insert spans into the tree in sorted order.
+ */
+
+static int compare_span(void* a, void* b)
{
struct icaltime_span *span_a = (struct icaltime_span *)a ;
struct icaltime_span *span_b = (struct icaltime_span *)b ;
@@ -49,20 +62,52 @@ int compare_span(void* a, void* b)
}
}
-icalcomponent* icalspanlist_get_inner(icalcomponent* comp)
+
+/** @brief callback function for collecting spanlists of a
+ * series of events.
+ *
+ * @param comp A valid icalcomponent.
+ * @param span The span to insert into data.
+ * @param data The actual spanlist to insert into
+ *
+ * This callback is used by icalcomponent_foreach_recurrence()
+ * to build up a spanlist.
+ */
+
+static void icalspanlist_new_callback(icalcomponent *comp,
+ struct icaltime_span *span,
+ void *data)
{
- if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){
- return icalcomponent_get_first_real_component(comp);
- } else {
- return comp;
- }
+ icaltime_span *s;
+ icalspanlist *sl = (icalspanlist*) data;
+
+ if (span->is_busy == 0)
+ return;
+
+ if ((s=(icaltime_span *) malloc(sizeof(icaltime_span))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return;
+ }
+
+ /** copy span data into allocated memory.. **/
+ *s = *span;
+ pvl_insert_ordered(sl->spans, compare_span, (void*)s);
}
+
-void print_span(int c, struct icaltime_span span );
+/** @brief Make a free list from a set of VEVENT components.
+ *
+ * @param set A valid icalset containing VEVENTS
+ * @param start The free list starts at this date/time
+ * @param end The free list ends at this date/time
+ *
+ * @return A spanlist corresponding to the VEVENTS
+ *
+ * Given a set of components, a start time and an end time
+ * return a spanlist that contains the free/busy times.
+ */
-
-/* Make a free list from a set of component */
icalspanlist* icalspanlist_new(icalset *set,
struct icaltimetype start,
struct icaltimetype end)
@@ -71,7 +116,7 @@ icalspanlist* icalspanlist_new(icalset *set,
pvl_elem itr;
icalcomponent *c,*inner;
icalcomponent_kind kind, inner_kind;
- struct icalspanlist_impl *sl;
+ icalspanlist *sl;
struct icaltime_span *freetime;
if ( ( sl = (struct icalspanlist_impl*)
@@ -81,14 +126,12 @@ icalspanlist* icalspanlist_new(icalset *set,
}
sl->spans = pvl_newlist();
+ sl->start = start;
+ sl->end = end;
range.start = icaltime_as_timet(start);
range.end = icaltime_as_timet(end);
- printf("Range start: %s",ctime(&range.start));
- printf("Range end : %s",ctime(&range.end));
-
-
/* Get a list of spans of busy time from the events in the set
and order the spans based on the start time */
@@ -96,8 +139,6 @@ icalspanlist* icalspanlist_new(icalset *set,
c != 0;
c = icalset_get_next_component(set)){
- struct icaltime_span span;
-
kind = icalcomponent_isa(c);
inner = icalcomponent_get_inner(c);
@@ -113,31 +154,12 @@ icalspanlist* icalspanlist_new(icalset *set,
}
icalerror_clear_errno();
-
- span = icalcomponent_get_span(c);
- span.is_busy = 1;
-
- if(icalerrno != ICAL_NO_ERROR){
- continue;
- }
-
- if ((range.start < span.end && icaltime_is_null_time(end)) ||
- (range.start < span.end && range.end > span.start )){
-
- struct icaltime_span *s;
-
- if ((s=(struct icaltime_span *)
- malloc(sizeof(struct icaltime_span))) == 0){
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- return 0;
- }
-
- memcpy(s,&span,sizeof(span));
-
- pvl_insert_ordered(sl->spans,compare_span,(void*)s);
-
- }
- }
+
+ icalcomponent_foreach_recurrence(c, start, end,
+ icalspanlist_new_callback,
+ (void*)sl);
+
+ }
/* Now Fill in the free time spans. loop through the spans. if the
start of the range is not within the span, create a free entry
@@ -148,7 +170,7 @@ icalspanlist* icalspanlist_new(icalset *set,
itr != 0;
itr = pvl_next(itr))
{
- struct icaltime_span *s = (icalproperty*)pvl_data(itr);
+ struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr);
if ((freetime=(struct icaltime_span *)
malloc(sizeof(struct icaltime_span))) == 0){
@@ -178,7 +200,7 @@ icalspanlist* icalspanlist_new(icalset *set,
if( icaltime_is_null_time(end)){
struct icaltime_span* last_span;
- last_span = pvl_data(pvl_tail(sl->spans));
+ last_span = (struct icaltime_span*)pvl_data(pvl_tail(sl->spans));
if (last_span != 0){
@@ -197,35 +219,46 @@ icalspanlist* icalspanlist_new(icalset *set,
return sl;
-
}
+/** @brief Destructor.
+ * @param s A valid icalspanlist
+ *
+ * Free memory associated with the spanlist
+ */
+
void icalspanlist_free(icalspanlist* s)
{
struct icaltime_span *span;
- struct icalspanlist_impl* impl = (struct icalspanlist_impl*)s;
-
- while( (span=pvl_pop(impl->spans)) != 0){
+
+ if (s == NULL)
+ return;
+
+ while( (span=pvl_pop(s->spans)) != 0){
free(span);
}
- pvl_free(impl->spans);
+ pvl_free(s->spans);
- impl->spans = 0;
+ s->spans = 0;
+
+ free(s);
}
-void icalspanlist_dump(icalspanlist* s){
+/** @brief (Debug) print out spanlist to stdout.
+ * @param sl A valid icalspanlist.
+ */
+void icalspanlist_dump(icalspanlist* sl){
int i = 0;
- struct icalspanlist_impl* sl = (struct icalspanlist_impl*)s;
pvl_elem itr;
for( itr = pvl_head(sl->spans);
itr != 0;
itr = pvl_next(itr))
{
- struct icaltime_span *s = (icalproperty*)pvl_data(itr);
+ struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr);
printf("#%02d %d start: %s",++i,s->is_busy,ctime(&s->start));
printf(" end : %s",ctime(&s->end));
@@ -236,10 +269,19 @@ void icalspanlist_dump(icalspanlist* s){
icalcomponent* icalspanlist_make_free_list(icalspanlist* sl);
icalcomponent* icalspanlist_make_busy_list(icalspanlist* sl);
+
+/** @brief Find next free time span in a spanlist.
+ *
+ * @param sl The spanlist to search.
+ * @param t The time to start looking.
+ *
+ * Given a spanlist and a time, find the next period of time
+ * that is free
+ */
+
struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl,
struct icaltimetype t)
{
- struct icalspanlist_impl* impl = (struct icalspanlist_impl*)sl;
pvl_elem itr;
struct icalperiodtype period;
struct icaltime_span *s;
@@ -249,22 +291,22 @@ struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl,
period.start = icaltime_null_time();
period.end = icaltime_null_time();
- /* Is the reference time before the first span? If so, assume
- that the reference time is free */
- itr = pvl_head(impl->spans);
- s = (icalproperty*)pvl_data(itr);
+ itr = pvl_head(sl->spans);
+ s = (struct icaltime_span *)pvl_data(itr);
if (s == 0){
/* No elements in span */
return period;
}
+ /* Is the reference time before the first span? If so, assume
+ that the reference time is free */
if(rangett <s->start ){
/* End of period is start of first span if span is busy, end
of the span if it is free */
period.start = t;
- if (s->is_busy == 0){
+ if (s->is_busy == 1){
period.end = icaltime_from_timet(s->start,0);
} else {
period.end = icaltime_from_timet(s->end,0);
@@ -275,12 +317,11 @@ struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl,
/* Otherwise, find the first free span that contains the
reference time. */
-
- for( itr = pvl_head(impl->spans);
+ for( itr = pvl_head(sl->spans);
itr != 0;
itr = pvl_next(itr))
{
- s = (icalproperty*)pvl_data(itr);
+ s = (struct icaltime_span *)pvl_data(itr);
if(s->is_busy == 0 && s->start >= rangett &&
( rangett < s->end || s->end == s->start)){
@@ -307,3 +348,220 @@ struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl,
struct icalperiodtype icalspanlist_next_busy_time(icalspanlist* sl,
struct icaltimetype t);
+
+/** @brief Returns an hour-by-hour array of free/busy times over a
+ * given period.
+ *
+ * @param sl A valid icalspanlist
+ * @param delta_t The time slice to divide by, in seconds. Default 3600.
+ *
+ * @return A pointer to an array of integers containing the number of
+ * busy events in each delta_t time period. The final entry
+ * contains the value -1.
+ *
+ * This calculation is somewhat tricky. This is due to the fact that
+ * the time range contains the start time, but does not contain the
+ * end time. To perform a proper calculation we subtract one second
+ * off the end times to get a true containing time.
+ *
+ * Also note that if you supplying a spanlist that does not start or
+ * end on a time boundary divisible by delta_t you may get results
+ * that are not quite what you expect.
+ */
+
+int* icalspanlist_as_freebusy_matrix(icalspanlist* sl, int delta_t) {
+ pvl_elem itr;
+ int spanduration_secs;
+ int *matrix;
+ int matrix_slots;
+ time_t sl_start, sl_end;
+
+ icalerror_check_arg_rz( (sl!=0), "spanlist");
+
+ if (!delta_t)
+ delta_t = 3600;
+
+ /** calculate the start and end time as time_t **/
+ sl_start = icaltime_as_timet_with_zone(sl->start, icaltimezone_get_utc_timezone());
+ sl_end = icaltime_as_timet_with_zone(sl->end, icaltimezone_get_utc_timezone());
+
+
+ /** insure that the time period falls on a time boundary divisable
+ by delta_t */
+
+ sl_start /= delta_t;
+ sl_start *= delta_t;
+
+ sl_end /= delta_t;
+ sl_end *= delta_t;
+
+
+ /** find the duration of this spanlist **/
+ spanduration_secs = sl_end - sl_start;
+
+
+ /** malloc our matrix, add one extra slot for a final -1 **/
+ matrix_slots = spanduration_secs/delta_t + 1;
+
+ matrix = (int*) malloc(sizeof(int) * matrix_slots);
+ if (matrix == NULL) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return NULL;
+ }
+ memset(matrix, 0, sizeof(int) * matrix_slots);
+ matrix[matrix_slots-1] = -1;
+
+ /* loop through each span and mark the slots in the array */
+
+ for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) {
+ struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr);
+
+ if (s->is_busy == 1) {
+ int offset_start = s->start/delta_t - sl_start/delta_t;
+ int offset_end = (s->end - 1) /delta_t - sl_start/delta_t + 1;
+ int i;
+
+ if (offset_end >= matrix_slots)
+ offset_end = matrix_slots - 1;
+
+ i = offset_start;
+ for (i=offset_start; i < offset_end; i++) {
+ matrix[i]++;
+ }
+ }
+ }
+ return matrix;
+}
+
+
+/** @brief Return a VFREEBUSY component for the corresponding spanlist
+ *
+ * @param sl A valid icalspanlist, from icalspanlist_new()
+ * @param organizer The organizer specified as MAILTO:user@domain
+ * @param attendee The attendee specified as MAILTO:user@domain
+ *
+ * @return A valid icalcomponent or NULL.
+ *
+ * This function returns a VFREEBUSY component for the given spanlist.
+ * The start time is mapped to DTSTART, the end time to DTEND.
+ * Each busy span is represented as a separate FREEBUSY entry.
+ * An attendee parameter is required, and organizer parameter is
+ * optional.
+ */
+
+icalcomponent *icalspanlist_as_vfreebusy(icalspanlist* sl,
+ const char* organizer,
+ const char* attendee) {
+ icalcomponent *comp;
+ icalproperty *p;
+ struct icaltimetype atime = icaltime_from_timet( time(0),0);
+ pvl_elem itr;
+ icaltimezone *utc_zone;
+ icalparameter *param;
+
+ if (!attendee) {
+ icalerror_set_errno(ICAL_USAGE_ERROR);
+ return 0;
+ }
+
+ utc_zone = icaltimezone_get_utc_timezone ();
+
+ comp = icalcomponent_new_vfreebusy();
+
+ icalcomponent_add_property(comp, icalproperty_new_dtstart(sl->start));
+ icalcomponent_add_property(comp, icalproperty_new_dtend(sl->end));
+ icalcomponent_add_property(comp, icalproperty_new_dtstamp(atime));
+
+ if (organizer) {
+ icalcomponent_add_property(comp, icalproperty_new_organizer(organizer));
+ }
+ icalcomponent_add_property(comp, icalproperty_new_attendee(attendee));
+
+ /* now add the freebusy sections.. */
+
+ for( itr = pvl_head(sl->spans); itr != 0; itr = pvl_next(itr)) {
+ struct icalperiodtype period;
+ struct icaltime_span *s = (struct icaltime_span*)pvl_data(itr);
+
+ if (s->is_busy == 1) {
+
+ period.start = icaltime_from_timet_with_zone (s->start, 0, utc_zone);
+ period.end = icaltime_from_timet_with_zone (s->end, 0, utc_zone);
+ period.duration = icaldurationtype_null_duration();
+
+
+ p = icalproperty_new_freebusy(period);
+ param = icalparameter_new_fbtype(ICAL_FBTYPE_BUSY);
+ icalproperty_add_parameter(p, param);
+
+ icalcomponent_add_property(comp, p);
+ }
+
+ }
+
+ return comp;
+}
+
+
+/** @brief Return a spanlist corresponding to the VFREEBUSY portion of
+ * an icalcomponent.
+ *
+ * @param c A valid icalcomponent.
+ *
+ * @return A valid icalspanlist or NULL if no VFREEBUSY section.
+ *
+ */
+
+
+icalspanlist *icalspanlist_from_vfreebusy(icalcomponent* comp)
+{
+ icalcomponent *inner;
+ icalproperty *prop;
+ icalspanlist *sl;
+
+ icalerror_check_arg_rz((comp != NULL), "comp");
+
+ inner = icalcomponent_get_inner(comp);
+ if (!inner) return NULL;
+
+ if ( ( sl = (icalspanlist*) malloc(sizeof(icalspanlist))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+ sl->spans = pvl_newlist();
+
+ /* cycle through each FREEBUSY property, adding to the spanlist */
+ for (prop = icalcomponent_get_first_property(inner, ICAL_FREEBUSY_PROPERTY);
+ prop != NULL;
+ prop = icalcomponent_get_next_property(inner, ICAL_FREEBUSY_PROPERTY)) {
+ icaltime_span *s = (icaltime_span *) malloc(sizeof(icaltime_span));
+ icalparameter *param;
+ struct icalperiodtype period;
+ icalparameter_fbtype fbtype;
+
+ if (s == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ param = icalproperty_get_first_parameter(prop, ICAL_FBTYPE_PARAMETER);
+ fbtype = (param) ? icalparameter_get_fbtype(param) : ICAL_FBTYPE_BUSY;
+
+ switch (fbtype) {
+ case ICAL_FBTYPE_FREE:
+ case ICAL_FBTYPE_NONE:
+ case ICAL_FBTYPE_X:
+ s->is_busy = 1;
+ default:
+ s->is_busy = 0;
+ }
+
+ period = icalproperty_get_freebusy(prop);
+ s->start = icaltime_as_timet_with_zone(period.start, icaltimezone_get_utc_timezone());
+ s->end = icaltime_as_timet_with_zone(period.end, icaltimezone_get_utc_timezone());
+;
+ pvl_insert_ordered(sl->spans, compare_span, (void*)s);
+ }
+ /** @todo calculate start/end limits.. fill in holes? **/
+ return sl;
+}
diff --git a/libical/src/libicalss/icalspanlist.h b/libical/src/libicalss/icalspanlist.h
index 83cb1c8a6d..91f0acb8c1 100644
--- a/libical/src/libicalss/icalspanlist.h
+++ b/libical/src/libicalss/icalspanlist.h
@@ -28,26 +28,49 @@
#include "ical.h"
#include "icalset.h"
-typedef void icalspanlist;
+/** @file icalspanlist.h
+ * @brief Code that supports collections of free/busy spans of time
+ */
+
+typedef struct icalspanlist_impl icalspanlist;
+
+
+/** @brief Constructor
+ * Make a free list from a set of component. Start and end should be in UTC
+ */
-/* Make a free list from a set of component. Start and end should be in UTC */
icalspanlist* icalspanlist_new(icalset *set,
struct icaltimetype start,
struct icaltimetype end);
+/** @brief Destructor
+ */
void icalspanlist_free(icalspanlist* spl);
+/* Unimplemented functions */
icalcomponent* icalspanlist_make_free_list(icalspanlist* sl);
icalcomponent* icalspanlist_make_busy_list(icalspanlist* sl);
-/* Get first free or busy time after time t. all times are in UTC */
+/** Get first next free time after time t. all times are in UTC. */
struct icalperiodtype icalspanlist_next_free_time(icalspanlist* sl,
struct icaltimetype t);
+/** Get first next busy time after time t. all times are in UTC. */
struct icalperiodtype icalspanlist_next_busy_time(icalspanlist* sl,
struct icaltimetype t);
void icalspanlist_dump(icalspanlist* s);
+/** @brief Return a valid VFREEBUSY component for this span */
+icalcomponent *icalspanlist_as_vfreebusy(icalspanlist* s_in,
+ const char* organizer,
+ const char* attendee);
+
+/** @brief Return an integer matrix of total events per delta_t timespan */
+int *icalspanlist_as_freebusy_matrix(icalspanlist* span, int delta_t);
+
+/** @brief Construct an icalspanlist from a VFREEBUSY component */
+icalspanlist *icalspanlist_from_vfreebusy(icalcomponent* c);
+
#endif
diff --git a/libical/src/libicalss/icalspanlist_cxx.cpp b/libical/src/libicalss/icalspanlist_cxx.cpp
new file mode 100644
index 0000000000..38761af4c6
--- /dev/null
+++ b/libical/src/libicalss/icalspanlist_cxx.cpp
@@ -0,0 +1,92 @@
+#include "icalspanlist_cxx.h"
+#include <exception>
+
+/** @brief Construct an ICalSpanList from an icalset
+ @param set The icalset containing the VEVENTS
+ @param start Designated start of the spanlist
+ @param end Designated end of the spanlist
+*/
+
+ICalSpanList::ICalSpanList(icalset *set, icaltimetype start, icaltimetype end) throw(icalerrorenum)
+{
+ data = icalspanlist_new(set, start, end);
+ if (!data) throw icalerrno;
+};
+
+
+/** @brief Constructor
+ @param comp A valid icalcomponent with a VFREEBUSY section
+*/
+
+ICalSpanList::ICalSpanList(icalcomponent *comp) throw(icalerrorenum)
+{
+ data = icalspanlist_from_vfreebusy(comp);
+ if (!data) throw icalerrno;
+}
+
+/** @brief Constructor
+ @param comp A valid VComponent with a VFREEBUSY section
+*/
+ICalSpanList::ICalSpanList(VComponent &comp) throw(icalerrorenum)
+{
+ data = icalspanlist_from_vfreebusy((icalcomponent*) comp);
+ if (!data) throw icalerrno;
+}
+
+/** Destructor */
+ICalSpanList::~ICalSpanList() {
+ if (data)
+ icalspanlist_free(data);
+}
+
+
+/**
+ * @brief Returns a VFREEBUSY component for the object.
+ *
+ * @see icalspanlist_as_vfreebusy()
+ */
+
+VComponent*
+ICalSpanList::get_vfreebusy(const char *organizer, const char *attendee) throw(icalerrorenum)
+{
+ icalcomponent *comp;
+ VComponent *vcomp;
+
+ comp = icalspanlist_as_vfreebusy(data, organizer, attendee);
+ if (comp == 0) throw icalerrno;
+
+ vcomp = new VComponent(comp);
+ if (vcomp == 0) throw icalerrno;
+
+ return vcomp;
+}
+
+
+/**
+ * @brief Returns a summary of events over delta_t
+ *
+ * @param delta_t Number of seconds to divide the spanlist time period
+ * into.
+ *
+ * This method calculates the total number of events in each time slot
+ * of delta_t seconds.
+ *
+ * @see icalspanlist_as_freebusy_matrix()
+ */
+
+std::vector<int> ICalSpanList::as_vector(int delta_t) throw(icalerrorenum)
+{
+ int *matrix;
+ int i = 0;
+ std::vector<int> event_vec;
+
+ matrix = icalspanlist_as_freebusy_matrix(data, delta_t);
+
+ if (!matrix) throw ICAL_USAGE_ERROR;
+
+ while (matrix[i] != -1) {
+ event_vec.push_back(matrix[i]); // Add item at end of vector
+ }
+
+ return(event_vec);
+}
diff --git a/libical/src/libicalss/icalspanlist_cxx.h b/libical/src/libicalss/icalspanlist_cxx.h
new file mode 100644
index 0000000000..fce901c3db
--- /dev/null
+++ b/libical/src/libicalss/icalspanlist_cxx.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++ -*- */
+
+/**
+ * @file icalspanlist_cxx.h
+ * @author Critical Path
+ * @brief C++ class wrapping the icalspanlist data structure
+ *
+ * This class wraps the icalspanlist routines in libicalss
+ *
+ * Errors within libicalss are propagated via exceptions of type
+ * icalerrorenum. See icalerror.h for the complete list of exceptions
+ * that might be thrown.
+ */
+
+#ifndef ICALSPANLIST_CXX_H
+#define ICALSPANLIST_CXX_H
+
+#include "ical.h"
+#include "icalss.h"
+#include "vcomponent.h"
+#include <vector> /* For as_matrix.. */
+
+class ICalSpanList {
+ public:
+ /** Construct an ICalSpanList from an icalset */
+ ICalSpanList(icalset *set, icaltimetype start, icaltimetype end) throw(icalerrorenum);
+
+ /** Construct an ICalSpanList from the VFREEBUSY chunk of a icalcomponent */
+ ICalSpanList(icalcomponent *comp) throw(icalerrorenum);
+
+ /** Construct an ICalSpanList from the VFREEBUSY chunk of a vcomponent */
+ ICalSpanList(VComponent &comp) throw(icalerrorenum);
+
+ /** Destructor */
+ ~ICalSpanList();
+
+ /** Return a VFREEBUSY icalcomponent */
+ VComponent* get_vfreebusy(const char *organizer, const char *attendee) throw(icalerrorenum);
+
+ /** Return the base data when casting */
+ operator icalspanlist*() {return data;}
+
+ /** Return a vector of the number of events over delta t */
+ std::vector<int> as_vector(int delta_t) throw(icalerrorenum);
+
+ /** Dump the spanlist to stdout */
+ void dump() {icalspanlist_dump(data);}
+
+ private:
+ icalspanlist *data;
+};
+
+#endif
diff --git a/libical/src/libicalss/icalsslexer.l b/libical/src/libicalss/icalsslexer.l
index 848a9bc74f..6ea9f0ef2a 100644
--- a/libical/src/libicalss/icalsslexer.l
+++ b/libical/src/libicalss/icalsslexer.l
@@ -6,7 +6,7 @@
DESCRIPTION:
- $Id: icalsslexer.l,v 1.1.1.2 2001/01/23 19:20:41 jpr Exp $
+ $Id: icalsslexer.l,v 1.2 2003/09/11 22:04:30 hansp Exp $
$Locker: $
(C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
@@ -33,16 +33,12 @@
#include <string.h> /* For strdup() */
-int icalparser_flex_input(char* buf, int max_size);
-void icalparser_clear_flex_input();
-
-#undef YY_INPUT
-#define YY_INPUT(b,r,ms) ( r= icalparser_flex_input(b,ms))
+#undef YYPURE
+#define YYPURE
#undef SS_FATAL_ERROR
#define SS_FATAL_ERROR(msg) sserror(msg)
-
%}
crlf \x0D?\x0A
@@ -61,6 +57,7 @@ digit [0-9]
%array /* Make yytext an array. Slow, but handy. HACK */
%option caseless
+%option reentrant-bison
%s sql string_value
@@ -77,6 +74,7 @@ FROM { return FROM; }
WHERE { return WHERE; }
, { return COMMA; }
"=" { return EQUALS; }
+"==" { return EQUALS; }
"!=" { return NOTEQUALS; }
"<" { return LESS; }
">" { return GREATER; }
@@ -84,29 +82,35 @@ WHERE { return WHERE; }
">=" { return GREATEREQUALS; }
AND { return AND; }
OR { return OR; }
+IS { return IS; }
+NOT { return NOT; }
+NULL { return SQLNULL; }
\' { return QUOTE; }
[ \t\n\r]+ ;
; { return EOL; }
-\'[\*A-Za-z0-9\-\.]+\' {
- int c = input();
+
+\'[\@\*A-Za-z0-9\-\.\:\ ]+\' {
+ int c = input(yy_globals);
unput(c);
if(c!='\''){
- sslval.v_string= icalmemory_tmp_copy(sstext);
+ yylvalp->v_string= icalmemory_tmp_copy(yytext);
return STRING;
} else {
/*ssmore();*/
}
}
-[\*A-Za-z0-9\-\.]+ { sslval.v_string= icalmemory_tmp_copy(sstext);
- return STRING; }
+[\@\*A-Za-z0-9\-\.]+ {
+ yylval->v_string= icalmemory_tmp_copy(yytext);
+ return STRING;
+}
. { return yytext[0]; }
%%
-int sswrap()
+int yywrap(yyscan_t yy_globals)
{
return 1;
}
diff --git a/libical/src/libicalss/icalssyacc.h b/libical/src/libicalss/icalssyacc.h
index 9a933dc735..6d03a0f5ae 100644
--- a/libical/src/libicalss/icalssyacc.h
+++ b/libical/src/libicalss/icalssyacc.h
@@ -1,22 +1,31 @@
+#ifndef BISON_Y_TAB_H
+# define BISON_Y_TAB_H
+
+#ifndef YYSTYPE
typedef union {
char* v_string;
-} YYSTYPE;
-#define STRING 257
-#define SELECT 258
-#define FROM 259
-#define WHERE 260
-#define COMMA 261
-#define QUOTE 262
-#define EQUALS 263
-#define NOTEQUALS 264
-#define LESS 265
-#define GREATER 266
-#define LESSEQUALS 267
-#define GREATEREQUALS 268
-#define AND 269
-#define OR 270
-#define EOL 271
-#define END 272
+} yystype;
+# define YYSTYPE yystype
+#endif
+# define STRING 257
+# define SELECT 258
+# define FROM 259
+# define WHERE 260
+# define COMMA 261
+# define QUOTE 262
+# define EQUALS 263
+# define NOTEQUALS 264
+# define LESS 265
+# define GREATER 266
+# define LESSEQUALS 267
+# define GREATEREQUALS 268
+# define AND 269
+# define OR 270
+# define EOL 271
+# define END 272
+# define IS 273
+# define NOT 274
+# define SQLNULL 275
-extern YYSTYPE sslval;
+#endif /* not BISON_Y_TAB_H */
diff --git a/libical/src/libicalss/icalssyacc.y b/libical/src/libicalss/icalssyacc.y
index 047b158e93..224841f520 100644
--- a/libical/src/libicalss/icalssyacc.y
+++ b/libical/src/libicalss/icalssyacc.y
@@ -1,3 +1,5 @@
+%pure_parser
+
%{
/* -*- Mode: C -*-
======================================================================
@@ -6,7 +8,7 @@
DESCRIPTION:
- $Id: icalssyacc.y,v 1.1.1.2 2001/01/23 19:20:41 jpr Exp $
+ $Id: icalssyacc.y,v 1.2 2003/09/11 22:04:30 hansp Exp $
$Locker: $
(C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
@@ -26,26 +28,28 @@
Code is Eric Busboom
======================================================================*/
-
+/*#define YYDEBUG 1*/
#include <stdlib.h>
#include <string.h> /* for strdup() */
#include <limits.h> /* for SHRT_MAX*/
#include "ical.h"
-#include "pvl.h"
#include "icalgauge.h"
#include "icalgaugeimpl.h"
-extern struct icalgauge_impl *icalss_yy_gauge;
-
-void ssyacc_add_where(struct icalgauge_impl* impl, char* prop,
- icalgaugecompare compare , char* value);
-void ssyacc_add_select(struct icalgauge_impl* impl, char* str1);
-void ssyacc_add_from(struct icalgauge_impl* impl, char* str1);
-void set_logic(struct icalgauge_impl* impl,icalgaugelogic l);
-void sserror(char *s); /* Don't know why I need this.... */
+#define YYPARSE_PARAM yy_globals
+#define YYLEX_PARAM yy_globals
+#define YY_EXTRA_TYPE icalgauge_impl*
+ /* ick...*/
+#define yyextra ((struct icalgauge_impl*)ssget_extra(yy_globals))
+static void ssyacc_add_where(struct icalgauge_impl* impl, char* prop,
+ icalgaugecompare compare , char* value);
+static void ssyacc_add_select(struct icalgauge_impl* impl, char* str1);
+static void ssyacc_add_from(struct icalgauge_impl* impl, char* str1);
+static void set_logic(struct icalgauge_impl* impl,icalgaugelogic l);
+void sserror(char *s); /* Don't know why I need this.... */
%}
@@ -56,49 +60,51 @@ void sserror(char *s); /* Don't know why I need this.... */
%token <v_string> STRING
%token SELECT FROM WHERE COMMA QUOTE EQUALS NOTEQUALS LESS GREATER LESSEQUALS
-%token GREATEREQUALS AND OR EOL END
+%token GREATEREQUALS AND OR EOL END IS NOT SQLNULL
%%
query_min: SELECT select_list FROM from_list WHERE where_list
+ | SELECT select_list FROM from_list
| error {
- icalparser_clear_flex_input();
yyclearin;
+ YYABORT;
}
;
select_list:
- STRING {ssyacc_add_select(icalss_yy_gauge,$1);}
- | select_list COMMA STRING {ssyacc_add_select(icalss_yy_gauge,$3);}
+ STRING {ssyacc_add_select(yyextra,$1);}
+ | select_list COMMA STRING {ssyacc_add_select(yyextra,$3);}
;
from_list:
- STRING {ssyacc_add_from(icalss_yy_gauge,$1);}
- | from_list COMMA STRING {ssyacc_add_from(icalss_yy_gauge,$3);}
+ STRING {ssyacc_add_from(yyextra,$1);}
+ | from_list COMMA STRING {ssyacc_add_from(yyextra,$3);}
;
where_clause:
/* Empty */
- | STRING EQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_EQUAL,$3); }
-
- | STRING NOTEQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_NOTEQUAL,$3); }
- | STRING LESS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_LESS,$3); }
- | STRING GREATER STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_GREATER,$3); }
- | STRING LESSEQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_LESSEQUAL,$3); }
- | STRING GREATEREQUALS STRING {ssyacc_add_where(icalss_yy_gauge,$1,ICALGAUGECOMPARE_GREATEREQUAL,$3); }
+ | STRING EQUALS STRING {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_EQUAL,$3); }
+ | STRING IS SQLNULL {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_ISNULL,""); }
+ | STRING IS NOT SQLNULL {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_ISNOTNULL,""); }
+ | STRING NOTEQUALS STRING {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_NOTEQUAL,$3); }
+ | STRING LESS STRING {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_LESS,$3); }
+ | STRING GREATER STRING {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_GREATER,$3); }
+ | STRING LESSEQUALS STRING {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_LESSEQUAL,$3); }
+ | STRING GREATEREQUALS STRING {ssyacc_add_where(yyextra,$1,ICALGAUGECOMPARE_GREATEREQUAL,$3); }
;
where_list:
- where_clause {set_logic(icalss_yy_gauge,ICALGAUGELOGIC_NONE);}
- | where_list AND where_clause {set_logic(icalss_yy_gauge,ICALGAUGELOGIC_AND);}
- | where_list OR where_clause {set_logic(icalss_yy_gauge,ICALGAUGELOGIC_OR);}
+ where_clause {set_logic(yyextra,ICALGAUGELOGIC_NONE);}
+ | where_list AND where_clause {set_logic(yyextra,ICALGAUGELOGIC_AND);}
+ | where_list OR where_clause {set_logic(yyextra,ICALGAUGELOGIC_OR);}
;
%%
-void ssyacc_add_where(struct icalgauge_impl* impl, char* str1,
+static void ssyacc_add_where(struct icalgauge_impl* impl, char* str1,
icalgaugecompare compare , char* value_str)
{
@@ -160,7 +166,7 @@ void ssyacc_add_where(struct icalgauge_impl* impl, char* str1,
pvl_push(impl->where,where);
}
-void set_logic(struct icalgauge_impl* impl,icalgaugelogic l)
+static void set_logic(struct icalgauge_impl* impl,icalgaugelogic l)
{
pvl_elem e = pvl_tail(impl->where);
struct icalgauge_where *where = pvl_data(e);
@@ -171,7 +177,7 @@ void set_logic(struct icalgauge_impl* impl,icalgaugelogic l)
-void ssyacc_add_select(struct icalgauge_impl* impl, char* str1)
+static void ssyacc_add_select(struct icalgauge_impl* impl, char* str1)
{
char *c, *compstr, *propstr;
struct icalgauge_where *where;
@@ -217,15 +223,15 @@ void ssyacc_add_select(struct icalgauge_impl* impl, char* str1)
if(where->prop == ICAL_NO_PROPERTY){
- icalgauge_free(where);
- icalerror_set_errno(ICAL_BADARG_ERROR);
- return;
+ free(where);
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return;
}
pvl_push(impl->select,where);
}
-void ssyacc_add_from(struct icalgauge_impl* impl, char* str1)
+static void ssyacc_add_from(struct icalgauge_impl* impl, char* str1)
{
icalcomponent_kind ckind;
@@ -241,5 +247,6 @@ void ssyacc_add_from(struct icalgauge_impl* impl, char* str1)
void sserror(char *s){
- fprintf(stderr,"Parse error \'%s\'\n", s);
+ fprintf(stderr,"Parse error \'%s\'\n", s);
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
}