commit 9bf8ceff3443878a49a4d8a726fe1299922edad4
parent 476051c361bf0337f9ea993c273e2d50caa09e3c
Author: Colin Leroy <colin@colino.net>
Date: Wed, 13 Feb 2013 20:50:31 +0000
2013-02-13 [colin] 3.9.0cvs65
* src/plugins/address_dup_finder/placeholder.txt
* src/plugins/synce/placeholder.txt
Removed, deprecated plugins
* src/plugins/Makefile.am
* src/plugins/vcalendar/Makefile.am
* src/plugins/vcalendar/Makefile.in
* src/plugins/vcalendar/common-views.c
* src/plugins/vcalendar/common-views.h
* src/plugins/vcalendar/day-view.c
* src/plugins/vcalendar/icaltime_as_local.c
* src/plugins/vcalendar/icaltime_as_local.h
* src/plugins/vcalendar/month-view.c
* src/plugins/vcalendar/placeholder.txt
* src/plugins/vcalendar/plugin.c
* src/plugins/vcalendar/vcal_dbus.c
* src/plugins/vcalendar/vcal_dbus.h
* src/plugins/vcalendar/vcal_folder.c
* src/plugins/vcalendar/vcal_folder.h
* src/plugins/vcalendar/vcal_interface.h
* src/plugins/vcalendar/vcal_manager.c
* src/plugins/vcalendar/vcal_manager.h
* src/plugins/vcalendar/vcal_meeting_gtk.c
* src/plugins/vcalendar/vcal_meeting_gtk.h
* src/plugins/vcalendar/vcal_prefs.c
* src/plugins/vcalendar/vcal_prefs.h
* src/plugins/vcalendar/vcalendar.c
* src/plugins/vcalendar/vcalendar.h
* src/plugins/vcalendar/version.rc
* src/plugins/vcalendar/libical/.cvsignore
* src/plugins/vcalendar/libical/Makefile.am
* src/plugins/vcalendar/libical/Makefile.in
* src/plugins/vcalendar/libical/design-data/.cvsignore
* src/plugins/vcalendar/libical/design-data/Makefile.am
* src/plugins/vcalendar/libical/design-data/Makefile.in
* src/plugins/vcalendar/libical/design-data/parameters.csv
* src/plugins/vcalendar/libical/design-data/properties.csv
* src/plugins/vcalendar/libical/design-data/restrictions.csv
* src/plugins/vcalendar/libical/design-data/status.txt
* src/plugins/vcalendar/libical/design-data/value-types.csv
* src/plugins/vcalendar/libical/libical/.cvsignore
* src/plugins/vcalendar/libical/libical/Makefile.am
* src/plugins/vcalendar/libical/libical/Makefile.in
* src/plugins/vcalendar/libical/libical/icalattendee.c
* src/plugins/vcalendar/libical/libical/icalattendee.h
* src/plugins/vcalendar/libical/libical/icalcomponent.c
* src/plugins/vcalendar/libical/libical/icalcomponent.h
* src/plugins/vcalendar/libical/libical/icalderivedparameter.c.in
* src/plugins/vcalendar/libical/libical/icalderivedparameter.h.in
* src/plugins/vcalendar/libical/libical/icalderivedproperty.c.in
* src/plugins/vcalendar/libical/libical/icalderivedproperty.h.in
* src/plugins/vcalendar/libical/libical/icalderivedvalue.c.in
* src/plugins/vcalendar/libical/libical/icalderivedvalue.h.in
* src/plugins/vcalendar/libical/libical/icalduration.c
* src/plugins/vcalendar/libical/libical/icalduration.h
* src/plugins/vcalendar/libical/libical/icalenums.c
* src/plugins/vcalendar/libical/libical/icalenums.h
* src/plugins/vcalendar/libical/libical/icalerror.c
* src/plugins/vcalendar/libical/libical/icalerror.h
* src/plugins/vcalendar/libical/libical/icallangbind.c
* src/plugins/vcalendar/libical/libical/icallangbind.h
* src/plugins/vcalendar/libical/libical/icallexer.l
* src/plugins/vcalendar/libical/libical/icalmemory.c
* src/plugins/vcalendar/libical/libical/icalmemory.h
* src/plugins/vcalendar/libical/libical/icalmime.c
* src/plugins/vcalendar/libical/libical/icalmime.h
* src/plugins/vcalendar/libical/libical/icalparameter.c
* src/plugins/vcalendar/libical/libical/icalparameter.h
* src/plugins/vcalendar/libical/libical/icalparameterimpl.h
* src/plugins/vcalendar/libical/libical/icalparser.c
* src/plugins/vcalendar/libical/libical/icalparser.h
* src/plugins/vcalendar/libical/libical/icalperiod.c
* src/plugins/vcalendar/libical/libical/icalperiod.h
* src/plugins/vcalendar/libical/libical/icalproperty.c
* src/plugins/vcalendar/libical/libical/icalproperty.h
* src/plugins/vcalendar/libical/libical/icalrecur.c
* src/plugins/vcalendar/libical/libical/icalrecur.h
* src/plugins/vcalendar/libical/libical/icalrestriction.c.in
* src/plugins/vcalendar/libical/libical/icalrestriction.h
* src/plugins/vcalendar/libical/libical/icaltime.c
* src/plugins/vcalendar/libical/libical/icaltime.h
* src/plugins/vcalendar/libical/libical/icaltypes.c
* src/plugins/vcalendar/libical/libical/icaltypes.h
* src/plugins/vcalendar/libical/libical/icalvalue.c
* src/plugins/vcalendar/libical/libical/icalvalue.h
* src/plugins/vcalendar/libical/libical/icalvalueimpl.h
* src/plugins/vcalendar/libical/libical/icalversion.h
* src/plugins/vcalendar/libical/libical/icalversion.h.in
* src/plugins/vcalendar/libical/libical/icalyacc.output
* src/plugins/vcalendar/libical/libical/icalyacc.y
* src/plugins/vcalendar/libical/libical/pvl.c
* src/plugins/vcalendar/libical/libical/pvl.h
* src/plugins/vcalendar/libical/libical/sspm.c
* src/plugins/vcalendar/libical/libical/sspm.h
* src/plugins/vcalendar/libical/libical/vsnprintf.c
* src/plugins/vcalendar/libical/scripts/.cvsignore
* src/plugins/vcalendar/libical/scripts/Makefile.am
* src/plugins/vcalendar/libical/scripts/Makefile.in
* src/plugins/vcalendar/libical/scripts/mkderivedcomponents.pl
* src/plugins/vcalendar/libical/scripts/mkderivedparameters.pl
* src/plugins/vcalendar/libical/scripts/mkderivedproperties.pl
* src/plugins/vcalendar/libical/scripts/mkderivedvalues.pl
* src/plugins/vcalendar/libical/scripts/mkparameterrestrictions.pl
* src/plugins/vcalendar/libical/scripts/mkrestrictionrecords.pl
* src/plugins/vcalendar/libical/scripts/mkrestrictiontable.pl
* src/plugins/vcalendar/libical/scripts/readvaluesfile.pl
Add vcalendar.
Diffstat:
107 files changed, 35757 insertions(+), 10 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,3 +1,112 @@
+2013-02-13 [colin] 3.9.0cvs65
+
+ * src/plugins/address_dup_finder/placeholder.txt
+ * src/plugins/synce/placeholder.txt
+ Removed, deprecated plugins
+ * src/plugins/Makefile.am
+ * src/plugins/vcalendar/Makefile.am
+ * src/plugins/vcalendar/Makefile.in
+ * src/plugins/vcalendar/common-views.c
+ * src/plugins/vcalendar/common-views.h
+ * src/plugins/vcalendar/day-view.c
+ * src/plugins/vcalendar/icaltime_as_local.c
+ * src/plugins/vcalendar/icaltime_as_local.h
+ * src/plugins/vcalendar/month-view.c
+ * src/plugins/vcalendar/placeholder.txt
+ * src/plugins/vcalendar/plugin.c
+ * src/plugins/vcalendar/vcal_dbus.c
+ * src/plugins/vcalendar/vcal_dbus.h
+ * src/plugins/vcalendar/vcal_folder.c
+ * src/plugins/vcalendar/vcal_folder.h
+ * src/plugins/vcalendar/vcal_interface.h
+ * src/plugins/vcalendar/vcal_manager.c
+ * src/plugins/vcalendar/vcal_manager.h
+ * src/plugins/vcalendar/vcal_meeting_gtk.c
+ * src/plugins/vcalendar/vcal_meeting_gtk.h
+ * src/plugins/vcalendar/vcal_prefs.c
+ * src/plugins/vcalendar/vcal_prefs.h
+ * src/plugins/vcalendar/vcalendar.c
+ * src/plugins/vcalendar/vcalendar.h
+ * src/plugins/vcalendar/version.rc
+ * src/plugins/vcalendar/libical/.cvsignore
+ * src/plugins/vcalendar/libical/Makefile.am
+ * src/plugins/vcalendar/libical/Makefile.in
+ * src/plugins/vcalendar/libical/design-data/.cvsignore
+ * src/plugins/vcalendar/libical/design-data/Makefile.am
+ * src/plugins/vcalendar/libical/design-data/Makefile.in
+ * src/plugins/vcalendar/libical/design-data/parameters.csv
+ * src/plugins/vcalendar/libical/design-data/properties.csv
+ * src/plugins/vcalendar/libical/design-data/restrictions.csv
+ * src/plugins/vcalendar/libical/design-data/status.txt
+ * src/plugins/vcalendar/libical/design-data/value-types.csv
+ * src/plugins/vcalendar/libical/libical/.cvsignore
+ * src/plugins/vcalendar/libical/libical/Makefile.am
+ * src/plugins/vcalendar/libical/libical/Makefile.in
+ * src/plugins/vcalendar/libical/libical/icalattendee.c
+ * src/plugins/vcalendar/libical/libical/icalattendee.h
+ * src/plugins/vcalendar/libical/libical/icalcomponent.c
+ * src/plugins/vcalendar/libical/libical/icalcomponent.h
+ * src/plugins/vcalendar/libical/libical/icalderivedparameter.c.in
+ * src/plugins/vcalendar/libical/libical/icalderivedparameter.h.in
+ * src/plugins/vcalendar/libical/libical/icalderivedproperty.c.in
+ * src/plugins/vcalendar/libical/libical/icalderivedproperty.h.in
+ * src/plugins/vcalendar/libical/libical/icalderivedvalue.c.in
+ * src/plugins/vcalendar/libical/libical/icalderivedvalue.h.in
+ * src/plugins/vcalendar/libical/libical/icalduration.c
+ * src/plugins/vcalendar/libical/libical/icalduration.h
+ * src/plugins/vcalendar/libical/libical/icalenums.c
+ * src/plugins/vcalendar/libical/libical/icalenums.h
+ * src/plugins/vcalendar/libical/libical/icalerror.c
+ * src/plugins/vcalendar/libical/libical/icalerror.h
+ * src/plugins/vcalendar/libical/libical/icallangbind.c
+ * src/plugins/vcalendar/libical/libical/icallangbind.h
+ * src/plugins/vcalendar/libical/libical/icallexer.l
+ * src/plugins/vcalendar/libical/libical/icalmemory.c
+ * src/plugins/vcalendar/libical/libical/icalmemory.h
+ * src/plugins/vcalendar/libical/libical/icalmime.c
+ * src/plugins/vcalendar/libical/libical/icalmime.h
+ * src/plugins/vcalendar/libical/libical/icalparameter.c
+ * src/plugins/vcalendar/libical/libical/icalparameter.h
+ * src/plugins/vcalendar/libical/libical/icalparameterimpl.h
+ * src/plugins/vcalendar/libical/libical/icalparser.c
+ * src/plugins/vcalendar/libical/libical/icalparser.h
+ * src/plugins/vcalendar/libical/libical/icalperiod.c
+ * src/plugins/vcalendar/libical/libical/icalperiod.h
+ * src/plugins/vcalendar/libical/libical/icalproperty.c
+ * src/plugins/vcalendar/libical/libical/icalproperty.h
+ * src/plugins/vcalendar/libical/libical/icalrecur.c
+ * src/plugins/vcalendar/libical/libical/icalrecur.h
+ * src/plugins/vcalendar/libical/libical/icalrestriction.c.in
+ * src/plugins/vcalendar/libical/libical/icalrestriction.h
+ * src/plugins/vcalendar/libical/libical/icaltime.c
+ * src/plugins/vcalendar/libical/libical/icaltime.h
+ * src/plugins/vcalendar/libical/libical/icaltypes.c
+ * src/plugins/vcalendar/libical/libical/icaltypes.h
+ * src/plugins/vcalendar/libical/libical/icalvalue.c
+ * src/plugins/vcalendar/libical/libical/icalvalue.h
+ * src/plugins/vcalendar/libical/libical/icalvalueimpl.h
+ * src/plugins/vcalendar/libical/libical/icalversion.h
+ * src/plugins/vcalendar/libical/libical/icalversion.h.in
+ * src/plugins/vcalendar/libical/libical/icalyacc.output
+ * src/plugins/vcalendar/libical/libical/icalyacc.y
+ * src/plugins/vcalendar/libical/libical/pvl.c
+ * src/plugins/vcalendar/libical/libical/pvl.h
+ * src/plugins/vcalendar/libical/libical/sspm.c
+ * src/plugins/vcalendar/libical/libical/sspm.h
+ * src/plugins/vcalendar/libical/libical/vsnprintf.c
+ * src/plugins/vcalendar/libical/scripts/.cvsignore
+ * src/plugins/vcalendar/libical/scripts/Makefile.am
+ * src/plugins/vcalendar/libical/scripts/Makefile.in
+ * src/plugins/vcalendar/libical/scripts/mkderivedcomponents.pl
+ * src/plugins/vcalendar/libical/scripts/mkderivedparameters.pl
+ * src/plugins/vcalendar/libical/scripts/mkderivedproperties.pl
+ * src/plugins/vcalendar/libical/scripts/mkderivedvalues.pl
+ * src/plugins/vcalendar/libical/scripts/mkparameterrestrictions.pl
+ * src/plugins/vcalendar/libical/scripts/mkrestrictionrecords.pl
+ * src/plugins/vcalendar/libical/scripts/mkrestrictiontable.pl
+ * src/plugins/vcalendar/libical/scripts/readvaluesfile.pl
+ Add vcalendar.
+
2013-02-13 [colin] 3.9.0cvs64
* src/plugins/acpi_notifier/placeholder.txt
diff --git a/PATCHSETS b/PATCHSETS
@@ -4562,3 +4562,4 @@
( cvs diff -u -r 1.654.2.4638 -r 1.654.2.4639 configure.ac; cvs diff -u -r 1.53.2.39 -r 1.53.2.40 po/POTFILES.in; cvs diff -u -r 1.8.2.8 -r 1.8.2.9 src/plugins/Makefile.am; diff -u /dev/null src/plugins/fancy/Makefile.am; diff -u /dev/null src/plugins/fancy/fancy_prefs.c; diff -u /dev/null src/plugins/fancy/fancy_prefs.h; diff -u /dev/null src/plugins/fancy/fancy_viewer.c; diff -u /dev/null src/plugins/fancy/fancy_viewer.h; ) > 3.9.0cvs62.patchset
( cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/fancy/Makefile.am; ) > 3.9.0cvs63.patchset
( diff -u /dev/null src/plugins/acpi_notifier/placeholder.txt; diff -u /dev/null src/plugins/address_dup_finder/placeholder.txt; diff -u /dev/null src/plugins/address_keeper/placeholder.txt; diff -u /dev/null src/plugins/archive/placeholder.txt; diff -u /dev/null src/plugins/att_remover/placeholder.txt; diff -u /dev/null src/plugins/attachwarner/placeholder.txt; diff -u /dev/null src/plugins/bsfilter/placeholder.txt; diff -u /dev/null src/plugins/clamd/placeholder.txt; diff -u /dev/null src/plugins/fetchinfo/placeholder.txt; diff -u /dev/null src/plugins/gdata/placeholder.txt; diff -u /dev/null src/plugins/geolocation/placeholder.txt; diff -u /dev/null src/plugins/gtkhtml2_viewer/placeholder.txt; diff -u /dev/null src/plugins/mailmbox/placeholder.txt; diff -u /dev/null src/plugins/newmail/placeholder.txt; diff -u /dev/null src/plugins/notification/placeholder.txt; diff -u /dev/null src/plugins/pdf_viewer/placeholder.txt; diff -u /dev/null src/plugins/perl/placeholder.txt; diff -u /dev/null src/plugins/python/placeholder.txt; diff -u /dev/null src/plugins/rssyl/placeholder.txt; diff -u /dev/null src/plugins/spam_report/placeholder.txt; diff -u /dev/null src/plugins/synce/placeholder.txt; diff -u /dev/null src/plugins/tnef_parse/placeholder.txt; diff -u /dev/null src/plugins/vcalendar/placeholder.txt; ) > 3.9.0cvs64.patchset
+( cvs diff -u -r 1.8.2.9 -r 1.8.2.10 src/plugins/Makefile.am; cvs diff -u -r -1.1.2.1 -r -1.1.2.2 src/plugins/address_dup_finder/placeholder.txt; cvs diff -u -r -1.1.2.1 -r -1.1.2.2 src/plugins/synce/placeholder.txt; diff -u /dev/null src/plugins/vcalendar/Makefile.am; diff -u /dev/null src/plugins/vcalendar/Makefile.in; diff -u /dev/null src/plugins/vcalendar/common-views.c; diff -u /dev/null src/plugins/vcalendar/common-views.h; diff -u /dev/null src/plugins/vcalendar/day-view.c; diff -u /dev/null src/plugins/vcalendar/icaltime_as_local.c; diff -u /dev/null src/plugins/vcalendar/icaltime_as_local.h; diff -u /dev/null src/plugins/vcalendar/month-view.c; cvs diff -u -r -1.1.2.1 -r -1.1.2.2 src/plugins/vcalendar/placeholder.txt; diff -u /dev/null src/plugins/vcalendar/plugin.c; diff -u /dev/null src/plugins/vcalendar/vcal_dbus.c; diff -u /dev/null src/plugins/vcalendar/vcal_dbus.h; diff -u /dev/null src/plugins/vcalendar/vcal_folder.c; diff -u /dev/null src/plugins/vcalendar/vcal_folder.h; diff -u /dev/null src/plugins/vcalendar/vcal_interface.h; diff -u /dev/null src/plugins/vcalendar/vcal_manager.c; diff -u /dev/null src/plugins/vcalendar/vcal_manager.h; diff -u /dev/null src/plugins/vcalendar/vcal_meeting_gtk.c; diff -u /dev/null src/plugins/vcalendar/vcal_meeting_gtk.h; diff -u /dev/null src/plugins/vcalendar/vcal_prefs.c; diff -u /dev/null src/plugins/vcalendar/vcal_prefs.h; diff -u /dev/null src/plugins/vcalendar/vcalendar.c; diff -u /dev/null src/plugins/vcalendar/vcalendar.h; diff -u /dev/null src/plugins/vcalendar/version.rc; diff -u /dev/null src/plugins/vcalendar/libical/.cvsignore; diff -u /dev/null src/plugins/vcalendar/libical/Makefile.am; diff -u /dev/null src/plugins/vcalendar/libical/Makefile.in; diff -u /dev/null src/plugins/vcalendar/libical/design-data/.cvsignore; diff -u /dev/null src/plugins/vcalendar/libical/design-data/Makefile.am; diff -u /dev/null src/plugins/vcalendar/libical/design-data/Makefile.in; diff -u /dev/null src/plugins/vcalendar/libical/design-data/parameters.csv; diff -u /dev/null src/plugins/vcalendar/libical/design-data/properties.csv; diff -u /dev/null src/plugins/vcalendar/libical/design-data/restrictions.csv; diff -u /dev/null src/plugins/vcalendar/libical/design-data/status.txt; diff -u /dev/null src/plugins/vcalendar/libical/design-data/value-types.csv; diff -u /dev/null src/plugins/vcalendar/libical/libical/.cvsignore; diff -u /dev/null src/plugins/vcalendar/libical/libical/Makefile.am; diff -u /dev/null src/plugins/vcalendar/libical/libical/Makefile.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalattendee.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalattendee.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalcomponent.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalcomponent.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalderivedparameter.c.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalderivedparameter.h.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalderivedproperty.c.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalderivedproperty.h.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalderivedvalue.c.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalderivedvalue.h.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalduration.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalduration.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalenums.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalenums.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalerror.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalerror.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icallangbind.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icallangbind.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icallexer.l; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalmemory.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalmemory.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalmime.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalmime.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalparameter.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalparameter.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalparameterimpl.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalparser.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalparser.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalperiod.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalperiod.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalproperty.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalproperty.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalrecur.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalrecur.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalrestriction.c.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalrestriction.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icaltime.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icaltime.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icaltypes.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icaltypes.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalvalue.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalvalue.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalvalueimpl.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalversion.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalversion.h.in; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalyacc.output; diff -u /dev/null src/plugins/vcalendar/libical/libical/icalyacc.y; diff -u /dev/null src/plugins/vcalendar/libical/libical/pvl.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/pvl.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/sspm.c; diff -u /dev/null src/plugins/vcalendar/libical/libical/sspm.h; diff -u /dev/null src/plugins/vcalendar/libical/libical/vsnprintf.c; diff -u /dev/null src/plugins/vcalendar/libical/scripts/.cvsignore; diff -u /dev/null src/plugins/vcalendar/libical/scripts/Makefile.am; diff -u /dev/null src/plugins/vcalendar/libical/scripts/Makefile.in; diff -u /dev/null src/plugins/vcalendar/libical/scripts/mkderivedcomponents.pl; diff -u /dev/null src/plugins/vcalendar/libical/scripts/mkderivedparameters.pl; diff -u /dev/null src/plugins/vcalendar/libical/scripts/mkderivedproperties.pl; diff -u /dev/null src/plugins/vcalendar/libical/scripts/mkderivedvalues.pl; diff -u /dev/null src/plugins/vcalendar/libical/scripts/mkparameterrestrictions.pl; diff -u /dev/null src/plugins/vcalendar/libical/scripts/mkrestrictionrecords.pl; diff -u /dev/null src/plugins/vcalendar/libical/scripts/mkrestrictiontable.pl; diff -u /dev/null src/plugins/vcalendar/libical/scripts/readvaluesfile.pl; ) > 3.9.0cvs65.patchset
diff --git a/configure.ac b/configure.ac
@@ -12,7 +12,7 @@ MINOR_VERSION=9
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=64
+EXTRA_VERSION=65
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
@@ -983,6 +983,11 @@ else
fi
AM_CONDITIONAL(BUILD_DILLO_VIEWER_PLUGIN, test x"$ac_cv_enable_dillo_viewer_plugin" = xyes)
+dnl Find curl-config, used by fancy, vcalendar
+PKG_CHECK_MODULES(CURL, libcurl)
+AC_SUBST(CURL_LIBS)
+AC_SUBST(CURL_CFLAGS)
+
dnl --- Fancy ---
AC_MSG_CHECKING([whether to build Fancy plugin])
@@ -1012,11 +1017,6 @@ if test x"$ac_cv_enable_fancy_plugin" = xyes; then
AC_SUBST(LIBSOUP_GNOME_CFLAGS)
AC_SUBST(LIBSOUP_GNOME_LIBS)
- dnl Find curl-config
- PKG_CHECK_MODULES(CURL, libcurl)
- AC_SUBST(CURL_LIBS)
- AC_SUBST(CURL_CFLAGS)
-
PKG_CHECK_MODULES(GTKPRINTUNIX, gtk+-unix-print-2.0, ac_cv_enable_gtkprint=yes, ac_cv_enable_gtkprint=no)
if test x$ac_cv_enable_gtkprint = xyes; then
AC_DEFINE(USE_PRINTUNIX, 1, Define if you want gtk+-unix-print support)
@@ -1028,6 +1028,17 @@ if test x"$ac_cv_enable_fancy_plugin" = xyes; then
fi
AM_CONDITIONAL(BUILD_FANCY_PLUGIN, test x"$ac_cv_enable_fancy_plugin" = xyes)
+dnl --- Fancy ---
+AC_MSG_CHECKING([whether to build vCalendar plugin])
+AC_ARG_ENABLE(vcalendar-plugin,
+ [ --disable-vcalendar-plugin do not build vcalendar plugin for ical rendering],
+ [ac_cv_enable_vcalendar_plugin=$enableval], [ac_cv_enable_vcalendar_plugin=yes])
+if test x"$ac_cv_enable_vcalendar_plugin" = xyes; then
+ AC_MSG_RESULT(yes)
+ PLUGINS="vcalendar $PLUGINS"
+fi
+AM_CONDITIONAL(BUILD_VCALENDAR_PLUGIN, test x"$ac_cv_enable_vcalendar_plugin" = xyes)
+
dnl --- Demo ---
AC_ARG_ENABLE(demo-plugin,
[ --enable-demo-plugin build demo plugin],
@@ -1125,6 +1136,12 @@ src/plugins/pgpcore/Makefile
src/plugins/pgpmime/Makefile
src/plugins/pgpinline/Makefile
src/plugins/smime/Makefile
+src/plugins/vcalendar/Makefile
+src/plugins/vcalendar/libical/Makefile
+src/plugins/vcalendar/libical/libical/icalversion.h
+src/plugins/vcalendar/libical/libical/Makefile
+src/plugins/vcalendar/libical/design-data/Makefile
+src/plugins/vcalendar/libical/scripts/Makefile
doc/Makefile
doc/man/Makefile
tools/Makefile
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
@@ -18,6 +18,10 @@ if BUILD_FANCY_PLUGIN
fancy_dir = fancy
endif
+if BUILD_VCALENDAR_PLUGIN
+vcalendar_dir = vcalendar
+endif
+
if BUILD_TRAYICON_PLUGIN
trayicon_dir = trayicon
endif
@@ -44,4 +48,5 @@ SUBDIRS = $(demo_dir) \
$(pgpcore_dir) \
$(pgpmime_dir) \
$(pgpinline_dir) \
- $(smime_dir)
+ $(smime_dir) \
+ $(vcalendar_dir)
diff --git a/src/plugins/address_dup_finder/placeholder.txt b/src/plugins/address_dup_finder/placeholder.txt
@@ -1 +0,0 @@
-Placeholder
diff --git a/src/plugins/synce/placeholder.txt b/src/plugins/synce/placeholder.txt
@@ -1 +0,0 @@
-Placeholder
diff --git a/src/plugins/vcalendar/Makefile.am b/src/plugins/vcalendar/Makefile.am
@@ -0,0 +1,90 @@
+SUBDIRS = libical
+EXTRA_DIST = claws.def plugin.def version.rc
+
+if OS_WIN32
+
+LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RC) \
+ `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \
+ sed -e 's/-I/--include-dir /g;s/-D/--define /g'`
+
+%.lo : %.rc
+ $(LTRCCOMPILE) -i $< -o $@
+
+plugin_res = version.lo
+plugin_res_ldflag = -Wl,.libs/version.o
+
+export_symbols = -export-symbols $(srcdir)/plugin.def
+
+plugin_deps = libclaws.a $(plugin_res) plugin.def
+
+libclaws.a: claws.def
+ $(DLLTOOL) --output-lib $@ --def $<
+
+plugin_ldadd = -L. -lclaws
+
+else
+plugin_res =
+plugin_res_ldflag =
+export_symbols =
+plugin_deps =
+plugin_ldadd =
+endif
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+else
+no_undefined =
+endif
+
+if CYGWIN
+cygwin_export_lib = -L$(top_builddir)/src -lclaws-mail
+else
+cygwin_export_lib =
+endif
+
+plugindir = $(pkglibdir)/plugins
+
+plugin_LTLIBRARIES = vcalendar.la
+
+INCLUDES= \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/common \
+ -I$(top_builddir)/src/common \
+ -I$(top_srcdir)/src/gtk \
+ -I$(top_srcdir)/src/plugins/vcalendar/libical/libical
+
+vcalendar_la_SOURCES = \
+ plugin.c \
+ vcalendar.c vcalendar.h \
+ vcal_manager.c vcal_manager.h \
+ vcal_folder.c vcal_folder.h \
+ vcal_meeting_gtk.c vcal_meeting_gtk.h \
+ vcal_prefs.c vcal_prefs.h \
+ vcal_dbus.c vcal_dbus.h \
+ icaltime_as_local.c icaltime_as_local.h \
+ common-views.c common-views.h \
+ day-view.c month-view.c
+
+vcalendarincludedir = $(includedir)/claws-mail/plugins/vcalendar
+vcalendarinclude_HEADERS = \
+ vcal_interface.h
+
+vcalendar_la_LDFLAGS = \
+ $(plugin_res_ldflag) $(no_undefined) $(export_symbols) \
+ -avoid-version -module \
+ $(GTK_LIBS)
+
+vcalendar_la_DEPENDENCIES = $(plugin_deps)
+
+vcalendar_la_LIBADD = $(plugin_ldadd) $(cygwin_export_lib) \
+ $(GTK_LIBS) \
+ $(top_builddir)/src/plugins/vcalendar/libical/libical/libical.la
+
+AM_CPPFLAGS = \
+ $(CLAWS_MAIL_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GTK_CFLAGS) \
+ -DLOCALEDIR=\""$(localedir)"\"
+
+clean-local:
+ rm -f libclaws.a
diff --git a/src/plugins/vcalendar/Makefile.in b/src/plugins/vcalendar/Makefile.in
@@ -0,0 +1,913 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/plugins/vcalendar
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(vcalendarinclude_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/check-type.m4 \
+ $(top_srcdir)/m4/gnupg-check-typedef.m4 \
+ $(top_srcdir)/m4/gnupg.m4 $(top_srcdir)/m4/gpgme.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/spamassassin.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h \
+ $(top_builddir)/claws-features.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)" \
+ "$(DESTDIR)$(vcalendarincludedir)"
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_vcalendar_la_OBJECTS = plugin.lo vcalendar.lo vcal_manager.lo \
+ vcal_folder.lo vcal_meeting_gtk.lo vcal_prefs.lo vcal_dbus.lo \
+ icaltime_as_local.lo common-views.lo day-view.lo month-view.lo
+vcalendar_la_OBJECTS = $(am_vcalendar_la_OBJECTS)
+vcalendar_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(vcalendar_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(vcalendar_la_SOURCES)
+DIST_SOURCES = $(vcalendar_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(vcalendarinclude_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPFACE_LIBS = @COMPFACE_LIBS@
+CONIC_CFLAGS = @CONIC_CFLAGS@
+CONIC_LIBS = @CONIC_LIBS@
+CONTACTS_CFLAGS = @CONTACTS_CFLAGS@
+CONTACTS_LIBS = @CONTACTS_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPT_LIBS = @CRYPT_LIBS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOCBOOK2HTML = @DOCBOOK2HTML@
+DOCBOOK2PDF = @DOCBOOK2PDF@
+DOCBOOK2PS = @DOCBOOK2PS@
+DOCBOOK2TXT = @DOCBOOK2TXT@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCHANT_CFLAGS = @ENCHANT_CFLAGS@
+ENCHANT_LIBS = @ENCHANT_LIBS@
+EXEEXT = @EXEEXT@
+EXTRA_VERSION = @EXTRA_VERSION@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNOME2_CFLAGS = @GNOME2_CFLAGS@
+GNOME2_LIBS = @GNOME2_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GPGME_CFLAGS = @GPGME_CFLAGS@
+GPGME_CONFIG = @GPGME_CONFIG@
+GPGME_LIBS = @GPGME_LIBS@
+GREP = @GREP@
+GTKPRINTUNIX_CFLAGS = @GTKPRINTUNIX_CFLAGS@
+GTKPRINTUNIX_LIBS = @GTKPRINTUNIX_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JPILOT_LIBS = @JPILOT_LIBS@
+LD = @LD@
+LDAP_LIBS = @LDAP_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBETPAN_FLAGS = @LIBETPAN_FLAGS@
+LIBETPAN_LIBS = @LIBETPAN_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBRESOLV = @LIBRESOLV@
+LIBS = @LIBS@
+LIBSOUP_GNOME_CFLAGS = @LIBSOUP_GNOME_CFLAGS@
+LIBSOUP_GNOME_LIBS = @LIBSOUP_GNOME_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAEMO_CFLAGS = @MAEMO_CFLAGS@
+MAEMO_LIBS = @MAEMO_LIBS@
+MAINT = @MAINT@
+MAJOR_VERSION = @MAJOR_VERSION@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MICRO_VERSION = @MICRO_VERSION@
+MINOR_VERSION = @MINOR_VERSION@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETWORKMANAGER_SUPPORT_CFLAGS = @NETWORKMANAGER_SUPPORT_CFLAGS@
+NETWORKMANAGER_SUPPORT_LIBS = @NETWORKMANAGER_SUPPORT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PASSCRYPT_KEY = @PASSCRYPT_KEY@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SM_LIBS = @SM_LIBS@
+STARTUP_NOTIFICATION_CFLAGS = @STARTUP_NOTIFICATION_CFLAGS@
+STARTUP_NOTIFICATION_LIBS = @STARTUP_NOTIFICATION_LIBS@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VERSION = @VERSION@
+WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
+WEBKIT_LIBS = @WEBKIT_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_cv_enable_crash_dialog = @ac_cv_enable_crash_dialog@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gnomedatadir = @gnomedatadir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libetpanconfig = @libetpanconfig@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+manualdir = @manualdir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = libical
+EXTRA_DIST = claws.def plugin.def version.rc
+@OS_WIN32_TRUE@LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RC) \
+@OS_WIN32_TRUE@ `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \
+@OS_WIN32_TRUE@ sed -e 's/-I/--include-dir /g;s/-D/--define /g'`
+
+@OS_WIN32_FALSE@plugin_res =
+@OS_WIN32_TRUE@plugin_res = version.lo
+@OS_WIN32_FALSE@plugin_res_ldflag =
+@OS_WIN32_TRUE@plugin_res_ldflag = -Wl,.libs/version.o
+@OS_WIN32_FALSE@export_symbols =
+@OS_WIN32_TRUE@export_symbols = -export-symbols $(srcdir)/plugin.def
+@OS_WIN32_FALSE@plugin_deps =
+@OS_WIN32_TRUE@plugin_deps = libclaws.a $(plugin_res) plugin.def
+@OS_WIN32_FALSE@plugin_ldadd =
+@OS_WIN32_TRUE@plugin_ldadd = -L. -lclaws
+@PLATFORM_WIN32_FALSE@no_undefined =
+@PLATFORM_WIN32_TRUE@no_undefined = -no-undefined
+@CYGWIN_FALSE@cygwin_export_lib =
+@CYGWIN_TRUE@cygwin_export_lib = -L$(top_builddir)/src -lclaws-mail
+plugindir = $(pkglibdir)/plugins
+plugin_LTLIBRARIES = vcalendar.la
+INCLUDES = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/common \
+ -I$(top_builddir)/src/common \
+ -I$(top_srcdir)/src/gtk \
+ -I$(top_srcdir)/src/plugins/vcalendar/libical/libical
+
+vcalendar_la_SOURCES = \
+ plugin.c \
+ vcalendar.c vcalendar.h \
+ vcal_manager.c vcal_manager.h \
+ vcal_folder.c vcal_folder.h \
+ vcal_meeting_gtk.c vcal_meeting_gtk.h \
+ vcal_prefs.c vcal_prefs.h \
+ vcal_dbus.c vcal_dbus.h \
+ icaltime_as_local.c icaltime_as_local.h \
+ common-views.c common-views.h \
+ day-view.c month-view.c
+
+vcalendarincludedir = $(includedir)/claws-mail/plugins/vcalendar
+vcalendarinclude_HEADERS = \
+ vcal_interface.h
+
+vcalendar_la_LDFLAGS = \
+ $(plugin_res_ldflag) $(no_undefined) $(export_symbols) \
+ -avoid-version -module \
+ $(GTK_LIBS)
+
+vcalendar_la_DEPENDENCIES = $(plugin_deps)
+vcalendar_la_LIBADD = $(plugin_ldadd) $(cygwin_export_lib) \
+ $(GTK_LIBS) \
+ $(top_builddir)/src/plugins/vcalendar/libical/libical/libical.la
+
+AM_CPPFLAGS = \
+ $(CLAWS_MAIL_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GTK_CFLAGS) \
+ -DLOCALEDIR=\""$(localedir)"\"
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/vcalendar/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/vcalendar/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+vcalendar.la: $(vcalendar_la_OBJECTS) $(vcalendar_la_DEPENDENCIES) $(EXTRA_vcalendar_la_DEPENDENCIES)
+ $(vcalendar_la_LINK) -rpath $(plugindir) $(vcalendar_la_OBJECTS) $(vcalendar_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common-views.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/day-view.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icaltime_as_local.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/month-view.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcal_dbus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcal_folder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcal_manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcal_meeting_gtk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcal_prefs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcalendar.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-vcalendarincludeHEADERS: $(vcalendarinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(vcalendarinclude_HEADERS)'; test -n "$(vcalendarincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(vcalendarincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(vcalendarincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(vcalendarincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(vcalendarincludedir)" || exit $$?; \
+ done
+
+uninstall-vcalendarincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(vcalendarinclude_HEADERS)'; test -n "$(vcalendarincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(vcalendarincludedir)'; $(am__uninstall_files_from_dir)
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(vcalendarincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-local \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES \
+ install-vcalendarincludeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES \
+ uninstall-vcalendarincludeHEADERS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ clean-local clean-pluginLTLIBRARIES ctags ctags-recursive \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip install-vcalendarincludeHEADERS installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES uninstall-vcalendarincludeHEADERS
+
+
+@OS_WIN32_TRUE@%.lo : %.rc
+@OS_WIN32_TRUE@ $(LTRCCOMPILE) -i $< -o $@
+
+@OS_WIN32_TRUE@libclaws.a: claws.def
+@OS_WIN32_TRUE@ $(DLLTOOL) --output-lib $@ --def $<
+
+clean-local:
+ rm -f libclaws.a
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/plugins/vcalendar/common-views.c b/src/plugins/vcalendar/common-views.c
@@ -0,0 +1,292 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ *
+ * Copyright (c) 2007-2008 Juha Kautto (juha at xfce.org)
+ * Copyright (c) 2008 Colin Leroy (colin@colino.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "defs.h"
+
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "summaryview.h"
+#include "vcalendar.h"
+#include "vcal_folder.h"
+#include "vcal_prefs.h"
+#include "vcal_manager.h"
+#include "vcal_meeting_gtk.h"
+#include "menu.h"
+
+
+static void view_new_meeting_cb (GtkAction *action,
+ gpointer user_data);
+static void view_edit_meeting_cb (GtkAction *action,
+ gpointer user_data);
+static void view_cancel_meeting_cb (GtkAction *action,
+ gpointer user_data);
+static void view_go_today_cb (GtkAction *action,
+ gpointer user_data);
+
+static GtkActionEntry view_event_popup_entries[] =
+{
+ {"VcalViewEvent", NULL, "VcalViewEvent" },
+ {"VcalViewEvent/EditMeeting", NULL, N_("_Edit this meeting..."), NULL, NULL, G_CALLBACK(view_edit_meeting_cb) },
+ {"VcalViewEvent/CancelMeeting", NULL, N_("_Cancel this meeting..."), NULL, NULL, G_CALLBACK(view_cancel_meeting_cb) },
+ {"VcalViewEvent/---", NULL, "---", NULL, NULL, NULL },
+ {"VcalViewEvent/CreateMeeting", NULL, N_("_Create new meeting..."), NULL, NULL, G_CALLBACK(view_new_meeting_cb) },
+
+ {"VcalViewEvent/GoToday", NULL, N_("_Go to today"), NULL, NULL, G_CALLBACK(view_go_today_cb) },
+};
+
+GtkWidget *build_line(gint start_x, gint start_y
+ , gint width, gint height, GtkWidget *hour_line, GdkColor *line_color)
+{
+ GdkColormap *pic1_cmap;
+ GdkVisual *pic1_vis;
+ GdkPixmap *pic1;
+ GdkGC *pic1_gc;
+ GtkWidget *new_hour_line;
+ gint depth = 16;
+ gboolean first = FALSE;
+
+ /*
+ * GdkPixbuf *scaled;
+ scaled = gdk_pixbuf_scale_simple (pix, w, h, GDK_INTERP_BILINEAR);
+ */
+
+ pic1_cmap = gdk_colormap_get_system();
+ pic1_vis = gdk_colormap_get_visual(pic1_cmap);
+ depth = pic1_vis->depth;
+ if (hour_line == NULL) {
+ pic1 = gdk_pixmap_new(NULL, width, height, depth);
+ gdk_drawable_set_colormap(pic1, pic1_cmap);
+ first = TRUE;
+ }
+ else
+ gtk_image_get_pixmap(GTK_IMAGE(hour_line), &pic1, NULL);
+ pic1_gc = gdk_gc_new(pic1);
+ if (first) {
+ gdk_gc_set_foreground(pic1_gc, line_color);
+ gdk_draw_rectangle(pic1, pic1_gc, TRUE, start_x, start_y, width, height);
+ }
+ else {
+ gdk_draw_rectangle(pic1, pic1_gc, TRUE, start_x, start_y, width, height);
+ }
+
+ new_hour_line = gtk_image_new_from_pixmap(pic1, NULL);
+ g_object_unref(pic1_gc);
+ g_object_unref(pic1);
+ return(new_hour_line);
+}
+
+/* move one day forward or backward */
+void orage_move_day(struct tm *t, int day)
+{
+ guint monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+ t->tm_year += 1900;
+ if (((t->tm_year%4) == 0)
+ && (((t->tm_year%100) != 0) || ((t->tm_year%400) == 0)))
+ ++monthdays[1]; /* leap year, february has 29 days */
+
+ t->tm_mday += day; /* may be negative */
+ if (t->tm_mday == 0) { /* we went to previous month */
+ if (--t->tm_mon == -1) { /* previous year */
+ --t->tm_year;
+ t->tm_mon = 11;
+ }
+ t->tm_mday = monthdays[t->tm_mon];
+ }
+ else if (t->tm_mday > (monthdays[t->tm_mon])) { /* next month */
+ if (++t->tm_mon == 12) {
+ ++t->tm_year;
+ t->tm_mon = 0;
+ }
+ t->tm_mday = 1;
+ }
+ t->tm_year -= 1900;
+ t->tm_wday += day;
+ if (t->tm_wday < 0)
+ t->tm_wday = 6;
+ t->tm_wday %=7;
+}
+
+gint orage_days_between(struct tm *t1, struct tm *t2)
+{
+ GDate *g_t1, *g_t2;
+ gint dd;
+ g_t1 = g_date_new_dmy(t1->tm_mday, t1->tm_mon, t1->tm_year);
+ g_t2 = g_date_new_dmy(t2->tm_mday, t2->tm_mon, t2->tm_year);
+ dd = g_date_days_between(g_t1, g_t2);
+ g_date_free(g_t1);
+ g_date_free(g_t2);
+ return(dd);
+}
+
+gint vcal_view_set_calendar_page(GtkWidget *to_show, GCallback cb, gpointer data)
+{
+ SummaryView *summaryview = NULL;
+ gint selsig = -1;
+ if (mainwindow_get_mainwindow()) {
+ summaryview = mainwindow_get_mainwindow()->summaryview;
+ gtk_container_add(GTK_CONTAINER(summaryview->mainwidget_book),
+ to_show);
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(summaryview->mainwidget_book),
+ gtk_notebook_page_num(GTK_NOTEBOOK(summaryview->mainwidget_book),
+ to_show));
+ main_window_set_menu_sensitive(mainwindow_get_mainwindow());
+ toolbar_main_set_sensitive(mainwindow_get_mainwindow());
+ selsig = g_signal_connect(G_OBJECT(summaryview->ctree), "tree_select_row",
+ G_CALLBACK(cb), data);
+ }
+ return selsig;
+}
+
+void vcal_view_set_summary_page(GtkWidget *to_remove, guint selsig)
+{
+ SummaryView *summaryview = NULL;
+ if (mainwindow_get_mainwindow()) {
+ summaryview = mainwindow_get_mainwindow()->summaryview;
+ if (selsig)
+ g_signal_handler_disconnect(G_OBJECT(summaryview->ctree), selsig);
+ gtk_container_remove(GTK_CONTAINER(summaryview->mainwidget_book),
+ to_remove);
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(summaryview->mainwidget_book),
+ gtk_notebook_page_num(GTK_NOTEBOOK(summaryview->mainwidget_book),
+ summaryview->scrolledwin));
+ main_window_set_menu_sensitive(mainwindow_get_mainwindow());
+ toolbar_main_set_sensitive(mainwindow_get_mainwindow());
+ }
+
+}
+
+void vcal_view_select_event (const gchar *uid, FolderItem *item, gboolean edit,
+ GCallback block_cb, gpointer block_data)
+{
+ if (edit) {
+ VCalEvent *event = NULL;
+ event = vcal_manager_load_event(uid);
+ if (event) {
+ vcal_meeting_create(event);
+ vcal_manager_free_event(event);
+ }
+ } else {
+ SummaryView *summaryview = NULL;
+ if (mainwindow_get_mainwindow()) {
+ MsgInfo *info = folder_item_get_msginfo_by_msgid(item, uid);
+ if (info) {
+ summaryview = mainwindow_get_mainwindow()->summaryview;
+ g_signal_handlers_block_by_func(G_OBJECT(summaryview->ctree),
+ G_CALLBACK(block_cb), block_data);
+ summary_select_by_msgnum(summaryview, info->msgnum);
+ summary_display_msg_selected(summaryview, FALSE);
+ procmsg_msginfo_free(info);
+ g_signal_handlers_unblock_by_func(G_OBJECT(summaryview->ctree),
+ G_CALLBACK(block_cb), block_data);
+ }
+ }
+ }
+}
+
+void vcal_view_create_popup_menus(gpointer data,
+ GtkWidget **view_menu,
+ GtkWidget **event_menu, GtkActionGroup **event_group,
+ GtkUIManager **ui_manager)
+{
+ *ui_manager = gtk_ui_manager_new();
+ *event_group = cm_menu_create_action_group_full(*ui_manager,"VcalViewEvent", view_event_popup_entries,
+ G_N_ELEMENTS(view_event_popup_entries), (gpointer)data);
+
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/", "Menus", "Menus", GTK_UI_MANAGER_MENUBAR)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus", "VcalView", "VcalViewEvent", GTK_UI_MANAGER_MENU)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalView", "CreateMeeting", "VcalViewEvent/CreateMeeting", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalView", "Separator1", "VcalViewEvent/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalView", "GoToday", "VcalViewEvent/GoToday", GTK_UI_MANAGER_MENUITEM)
+
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus", "VcalViewEvent", "VcalViewEvent", GTK_UI_MANAGER_MENU)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalViewEvent", "EditMeeting", "VcalViewEvent/EditMeeting", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalViewEvent", "CancelMeeting", "VcalViewEvent/CancelMeeting", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalViewEvent", "Separator1", "VcalViewEvent/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalViewEvent", "CreateMeeting", "VcalViewEvent/CreateMeeting", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalViewEvent", "Separator2", "VcalViewEvent/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(*ui_manager, "/Menus/VcalViewEvent", "GoToday", "VcalViewEvent/GoToday", GTK_UI_MANAGER_MENUITEM)
+
+ *view_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
+ gtk_ui_manager_get_widget(*ui_manager, "/Menus/VcalView")) );
+ *event_menu= gtk_menu_item_get_submenu(GTK_MENU_ITEM(
+ gtk_ui_manager_get_widget(*ui_manager, "/Menus/VcalViewEvent")) );
+}
+
+static void view_new_meeting_cb (GtkAction *action,
+ gpointer user_data)
+{
+ gpointer data_i = g_object_get_data(G_OBJECT(user_data), "menu_data_i");
+ gpointer data_s = g_object_get_data(G_OBJECT(user_data), "menu_data_s");
+ gpointer win = g_object_get_data(G_OBJECT(user_data), "menu_win");
+ void (*cb)(gpointer win, gpointer data_i, gpointer data_s) =
+ g_object_get_data(G_OBJECT(user_data), "new_meeting_cb");
+ if (cb)
+ cb(win, data_i, data_s);
+}
+static void view_edit_meeting_cb (GtkAction *action,
+ gpointer user_data)
+{
+ gpointer data_i = g_object_get_data(G_OBJECT(user_data), "menu_data_i");
+ gpointer data_s = g_object_get_data(G_OBJECT(user_data), "menu_data_s");
+ gpointer win = g_object_get_data(G_OBJECT(user_data), "menu_win");
+ void (*cb)(gpointer win, gpointer data_i, gpointer data_s) =
+ g_object_get_data(G_OBJECT(user_data), "edit_meeting_cb");
+ if (cb)
+ cb(win, data_i, data_s);
+}
+static void view_cancel_meeting_cb (GtkAction *action,
+ gpointer user_data)
+{
+ gpointer data_i = g_object_get_data(G_OBJECT(user_data), "menu_data_i");
+ gpointer data_s = g_object_get_data(G_OBJECT(user_data), "menu_data_s");
+ gpointer win = g_object_get_data(G_OBJECT(user_data), "menu_win");
+ void (*cb)(gpointer win, gpointer data_i, gpointer data_s) =
+ g_object_get_data(G_OBJECT(user_data), "cancel_meeting_cb");
+ if (cb)
+ cb(win, data_i, data_s);
+}
+static void view_go_today_cb (GtkAction *action,
+ gpointer user_data)
+{
+ gpointer data_i = g_object_get_data(G_OBJECT(user_data), "menu_data_i");
+ gpointer data_s = g_object_get_data(G_OBJECT(user_data), "menu_data_s");
+ gpointer win = g_object_get_data(G_OBJECT(user_data), "menu_win");
+ void (*cb)(gpointer win, gpointer data_i, gpointer data_s) =
+ g_object_get_data(G_OBJECT(user_data), "go_today_cb");
+ if (cb)
+ cb(win, data_i, data_s);
+}
diff --git a/src/plugins/vcalendar/common-views.h b/src/plugins/vcalendar/common-views.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2007-2008 Juha Kautto (juha at xfce.org)
+ * Copyright (c) 2008 Colin Leroy (colin@colino.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __COMMON_VIEWS_H__
+#define __COMMON_VIEWS_H__
+
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "summaryview.h"
+#include "vcalendar.h"
+#include "vcal_folder.h"
+#include "vcal_prefs.h"
+#include "vcal_manager.h"
+#include "vcal_meeting_gtk.h"
+
+GtkWidget *build_line(gint start_x, gint start_y
+ , gint width, gint height, GtkWidget *hour_line, GdkColor *line_color);
+void orage_move_day(struct tm *t, int day);
+gint orage_days_between(struct tm *t1, struct tm *t2);
+gint vcal_view_set_calendar_page(GtkWidget *to_show, GCallback cb, gpointer data);
+void vcal_view_set_summary_page(GtkWidget *to_remove, guint selsig);
+void vcal_view_select_event (const gchar *uid, FolderItem *item, gboolean edit,
+ GCallback block_cb, gpointer block_data);
+void vcal_view_create_popup_menus(gpointer data,
+ GtkWidget **view_menu,
+ GtkWidget **event_menu, GtkActionGroup **event_group,
+ GtkUIManager **ui_manager);
+
+#endif
diff --git a/src/plugins/vcalendar/day-view.c b/src/plugins/vcalendar/day-view.c
@@ -0,0 +1,931 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ *
+ * Copyright (c) 2007-2008 Juha Kautto (juha at xfce.org)
+ * Copyright (c) 2008 Colin Leroy (colin@colino.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "defs.h"
+
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "summaryview.h"
+#include "vcalendar.h"
+#include "vcal_folder.h"
+#include "vcal_prefs.h"
+#include "vcal_manager.h"
+#include "common-views.h"
+#include "vcal_meeting_gtk.h"
+
+#define MAX_DAYS 40
+struct _day_win
+{
+ GtkAccelGroup *accel_group;
+#if !GTK_CHECK_VERSION(2,12,0)
+ GtkTooltips *Tooltips;
+#endif
+ GtkWidget *Window;
+ GtkWidget *Vbox;
+
+ GtkWidget *Menubar;
+ GtkWidget *File_menu;
+ GtkWidget *File_menu_new;
+ GtkWidget *File_menu_close;
+ GtkWidget *View_menu;
+ GtkWidget *View_menu_refresh;
+ GtkWidget *Go_menu;
+ GtkWidget *Go_menu_today;
+ GtkWidget *Go_menu_prev;
+ GtkWidget *Go_menu_next;
+
+ GtkWidget *Toolbar;
+ GtkWidget *Create_toolbutton;
+ GtkWidget *Previous_toolbutton;
+ GtkWidget *Today_toolbutton;
+ GtkWidget *Next_toolbutton;
+ GtkWidget *Refresh_toolbutton;
+ GtkWidget *Close_toolbutton;
+
+ GtkWidget *StartDate_button;
+ GtkRequisition StartDate_button_req;
+ GtkWidget *day_spin;
+
+ GtkWidget *day_view_vbox;
+ GtkWidget *scroll_win_h;
+ GtkWidget *dtable_h; /* header of day table */
+ GtkWidget *scroll_win;
+ GtkWidget *dtable; /* day table */
+ GtkRequisition hour_req;
+
+ GtkWidget *header[MAX_DAYS];
+ GtkWidget *element[24][MAX_DAYS];
+ GtkWidget *line[24][MAX_DAYS];
+
+ guint upd_timer;
+ gdouble scroll_pos; /* remember the scroll position */
+
+ GdkColor bg1, bg2, line_color, bg_today, fg_sunday;
+ GList *apptw_list; /* keep track of appointments being updated */
+ struct tm startdate;
+ FolderItem *item;
+ gulong selsig;
+ GtkWidget *view_menu;
+ GtkWidget *event_menu;
+ GtkActionGroup *event_group;
+ GtkUIManager *ui_manager;
+};
+
+static gchar *get_locale_date(struct tm *tmdate)
+{
+ gchar *d = g_malloc(100);
+ strftime(d, 99, "%x", tmdate);
+ return d;
+}
+
+static void set_scroll_position(day_win *dw)
+{
+ GtkAdjustment *v_adj;
+
+ v_adj = gtk_scrolled_window_get_vadjustment(
+ GTK_SCROLLED_WINDOW(dw->scroll_win));
+ if (dw->scroll_pos > 0) /* we have old value */
+ gtk_adjustment_set_value(v_adj, dw->scroll_pos);
+ else if (dw->scroll_pos < 0)
+ /* default: let's try to start roughly from line 8 = 8 o'clock */
+ gtk_adjustment_set_value(v_adj, v_adj->upper/3);
+ gtk_adjustment_changed(v_adj);
+}
+
+static gboolean scroll_position_timer(gpointer user_data)
+{
+ set_scroll_position((day_win *)user_data);
+ return(FALSE); /* only once */
+}
+
+static void get_scroll_position(day_win *dw)
+{
+ GtkAdjustment *v_adj;
+
+ v_adj = gtk_scrolled_window_get_vadjustment(
+ GTK_SCROLLED_WINDOW(dw->scroll_win));
+ dw->scroll_pos = gtk_adjustment_get_value(v_adj);
+}
+
+void dw_close_window(day_win *dw)
+{
+ vcal_view_set_summary_page(dw->Vbox, dw->selsig);
+
+#if !(GTK_CHECK_VERSION(2,12,0))
+ gtk_object_destroy(G_OBJECT(dw->Tooltips));
+#endif
+ g_free(dw);
+ dw = NULL;
+}
+
+static char *orage_tm_date_to_i18_date(struct tm *tm_date)
+{
+ static char i18_date[32];
+
+ if (strftime(i18_date, 32, "%x", tm_date) == 0)
+ g_error("Orage: orage_tm_date_to_i18_date too long string in strftime");
+ return(i18_date);
+}
+
+static void changeSelectedDate(day_win *dw, gint day)
+{
+ if (day > 0) {
+ do {
+ orage_move_day(&(dw->startdate), 1);
+ } while (--day > 0);
+ } else {
+ do {
+ orage_move_day(&(dw->startdate), -1);
+ } while (++day < 0);
+ }
+}
+
+static gint on_Previous_clicked(GtkWidget *button, GdkEventButton *event,
+ day_win *dw)
+{
+ int days = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dw->day_spin));
+ changeSelectedDate(dw, -days);
+ refresh_day_win(dw);
+ return TRUE;
+}
+
+static gint on_Next_clicked(GtkWidget *button, GdkEventButton *event,
+ day_win *dw)
+{
+ int days = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dw->day_spin));
+ changeSelectedDate(dw, +days);
+ refresh_day_win(dw);
+ return TRUE;
+}
+
+static void dw_summary_selected(GtkCMCTree *ctree, GtkCMCTreeNode *row,
+ gint column, day_win *dw)
+{
+ MsgInfo *msginfo = gtk_cmctree_node_get_row_data(ctree, row);
+ int days = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dw->day_spin));
+
+ if (msginfo && msginfo->msgid) {
+ VCalEvent *event = vcal_manager_load_event(msginfo->msgid);
+ if (event) {
+ time_t t_first = mktime(&dw->startdate);
+ time_t t_start = icaltime_as_timet(icaltime_from_string(event->dtstart));
+ struct tm tm_start;
+ gboolean changed = FALSE;
+ GtkAdjustment *v_adj;
+
+#ifdef G_OS_WIN32
+ if (t_start < 0)
+ t_start = 1;
+#endif
+ localtime_r(&t_start, &tm_start);
+ tm_start.tm_hour = tm_start.tm_min = tm_start.tm_sec = 0;
+ t_start = mktime(&tm_start);
+
+ while (t_start < t_first) {
+ changeSelectedDate(dw, -days);
+ t_first = mktime(&dw->startdate);
+ changed = TRUE;
+ }
+ while (t_start > t_first + (days-1)*24*60*60) {
+ changeSelectedDate(dw, +days);
+ t_first = mktime(&dw->startdate);
+ changed = TRUE;
+ }
+
+ t_start = icaltime_as_timet(icaltime_from_string(event->dtstart));
+#ifdef G_OS_WIN32
+ if (t_start < 0)
+ t_start = 1;
+#endif
+ localtime_r(&t_start, &tm_start);
+ if (changed) {
+ debug_print("changed from %s\n", event->summary);
+ v_adj = gtk_scrolled_window_get_vadjustment(
+ GTK_SCROLLED_WINDOW(dw->scroll_win));
+#ifdef G_OS_WIN32
+ if (t_start < 0)
+ t_start = 1;
+#endif
+ localtime_r(&t_start, &tm_start);
+ if (tm_start.tm_hour > 2)
+ gtk_adjustment_set_value(v_adj,
+ (v_adj->upper-v_adj->page_size)/(24/(tm_start.tm_hour-2)));
+ else
+ gtk_adjustment_set_value(v_adj, 0);
+ gtk_adjustment_changed(v_adj);
+ refresh_day_win(dw);
+ }
+ }
+ vcal_manager_free_event(event);
+ }
+}
+
+static void day_view_new_meeting_cb(day_win *dw, gpointer data_i, gpointer data_s)
+{
+ int offset = GPOINTER_TO_INT(data_i);
+ struct tm tm_date = dw->startdate;
+ int offset_h = offset % 1000;
+ int offset_d = (offset-offset_h) / 1000;
+ guint monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ int mon = tm_date.tm_mon;
+
+ if (((tm_date.tm_year%4) == 0) && (((tm_date.tm_year%100) != 0)
+ || ((tm_date.tm_year%400) == 0)))
+ monthdays[1] = 29;
+
+ if (offset_d > monthdays[mon]) {
+ while (tm_date.tm_mday > 1)
+ orage_move_day(&tm_date, 1);
+ offset_d -= monthdays[mon];
+ }
+
+ while (offset_d > tm_date.tm_mday) {
+ orage_move_day(&tm_date, 1);
+ }
+ while (offset_d < tm_date.tm_mday) {
+ orage_move_day(&tm_date, -1);
+ }
+ tm_date.tm_hour = offset_h;
+ vcal_meeting_create_with_start(NULL, &tm_date);
+}
+
+static void day_view_edit_meeting_cb(day_win *dw, gpointer data_i, gpointer data_s)
+{
+ const gchar *uid = (gchar *)data_s;
+ vcal_view_select_event (uid, dw->item, TRUE,
+ G_CALLBACK(dw_summary_selected), dw);
+}
+
+static void day_view_cancel_meeting_cb(day_win *dw, gpointer data_i, gpointer data_s)
+{
+ const gchar *uid = (gchar *)data_s;
+ vcalendar_cancel_meeting(dw->item, uid);
+}
+
+static void day_view_today_cb(day_win *dw, gpointer data_i, gpointer data_s)
+{
+ time_t now = time(NULL);
+ struct tm tm_today;
+ localtime_r(&now, &tm_today);
+
+ while (tm_today.tm_wday != 1)
+ orage_move_day(&tm_today, -1);
+
+ dw->startdate = tm_today;
+ refresh_day_win(dw);
+}
+
+static void header_button_clicked_cb(GtkWidget *button, day_win *dw)
+{
+ int offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "offset"));
+
+ day_view_new_meeting_cb(dw, GINT_TO_POINTER(offset), NULL);
+}
+
+static void on_button_press_event_cb(GtkWidget *widget
+ , GdkEventButton *event, gpointer *user_data)
+{
+ day_win *dw = (day_win *)user_data;
+ gchar *uid = g_object_get_data(G_OBJECT(widget), "UID");
+ gpointer offset = g_object_get_data(G_OBJECT(widget), "offset");
+
+ if (event->button == 1) {
+ if (uid)
+ vcal_view_select_event (uid, dw->item, (event->type==GDK_2BUTTON_PRESS),
+ G_CALLBACK(dw_summary_selected), dw);
+ }
+ if (event->button == 3) {
+ g_object_set_data(G_OBJECT(dw->Vbox), "menu_win",
+ dw);
+ g_object_set_data(G_OBJECT(dw->Vbox), "menu_data_i",
+ offset);
+ g_object_set_data(G_OBJECT(dw->Vbox), "menu_data_s",
+ uid);
+ g_object_set_data(G_OBJECT(dw->Vbox), "new_meeting_cb",
+ day_view_new_meeting_cb);
+ g_object_set_data(G_OBJECT(dw->Vbox), "edit_meeting_cb",
+ day_view_edit_meeting_cb);
+ g_object_set_data(G_OBJECT(dw->Vbox), "cancel_meeting_cb",
+ day_view_cancel_meeting_cb);
+ g_object_set_data(G_OBJECT(dw->Vbox), "go_today_cb",
+ day_view_today_cb);
+ if (uid)
+ gtk_menu_popup(GTK_MENU(dw->event_menu),
+ NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ else
+ gtk_menu_popup(GTK_MENU(dw->view_menu),
+ NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ }
+}
+
+static void add_row(day_win *dw, VCalEvent *event, gint days)
+{
+ gint row, start_row, end_row;
+ gint col, start_col, end_col, first_col, last_col;
+ gint height, start_height, end_height;
+ gchar *text, *tip, *start_date, *end_date;
+ GtkWidget *ev, *lab, *hb;
+ time_t t_start, t_end;
+ struct tm tm_first, tm_start, tm_end;
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = dw->Tooltips;
+#endif
+
+ /* First clarify timings */
+ t_start = icaltime_as_timet(icaltime_from_string(event->dtstart));
+ if (event->dtend && *event->dtend)
+ t_end = icaltime_as_timet(icaltime_from_string(event->dtend));
+ else
+ t_end = t_start;
+
+#ifdef G_OS_WIN32
+ if (t_start < 0)
+ t_start = 1;
+ if (t_end < 0)
+ t_end = 1;
+#endif
+ localtime_r(&t_start, &tm_start);
+ localtime_r(&t_end, &tm_end);
+ tm_first = dw->startdate;
+
+ tm_first.tm_year += 1900;
+ tm_first.tm_mon += 1;
+ tm_start.tm_year += 1900;
+ tm_start.tm_mon += 1;
+ tm_end.tm_year += 1900;
+ tm_end.tm_mon += 1;
+
+ start_col = orage_days_between(&tm_first, &tm_start)+1;
+ end_col = orage_days_between(&tm_first, &tm_end)+1;
+
+ if (end_col < 1)
+ return;
+ if (start_col > days)
+ return;
+
+ else {
+ col = start_col;
+ row = tm_start.tm_hour;
+ }
+
+ /* then add the appointment */
+ text = g_strdup(event->summary?event->summary : _("Unknown"));
+ ev = gtk_event_box_new();
+ lab = gtk_label_new(text);
+ gtk_misc_set_alignment(GTK_MISC(lab), 0.0, 0.5);
+ gtk_label_set_ellipsize(GTK_LABEL(lab), PANGO_ELLIPSIZE_END);
+ gtk_container_add(GTK_CONTAINER(ev), lab);
+
+ if ((row % 2) == 1)
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &dw->bg1);
+ else
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &dw->bg2);
+ if (dw->element[row][col] == NULL) {
+ hb = gtk_hbox_new(TRUE, 3);
+ dw->element[row][col] = hb;
+ }
+ else {
+ hb = dw->element[row][col];
+ /* FIXME: set some real bar here to make it visible that we
+ * have more than 1 appointment here
+ */
+ }
+ if (orage_days_between(&tm_start, &tm_end) == 0)
+ tip = g_strdup_printf("%s\n%02d:%02d-%02d:%02d\n%s"
+ , text, tm_start.tm_hour, tm_start.tm_min
+ , tm_end.tm_hour, tm_end.tm_min, event->description);
+ else {
+/* we took the date in unnormalized format, so we need to do that now */
+ start_date = g_strdup(orage_tm_date_to_i18_date(&tm_start));
+ end_date = g_strdup(orage_tm_date_to_i18_date(&tm_end));
+ tip = g_strdup_printf("%s\n%s %02d:%02d - %s %02d:%02d\n%s"
+ , text
+ , start_date, tm_start.tm_hour, tm_start.tm_min
+ , end_date, tm_end.tm_hour, tm_end.tm_min
+ , event->description);
+ g_free(start_date);
+ g_free(end_date);
+ }
+ CLAWS_SET_TIP(ev, tip);
+ /*
+ gtk_box_pack_start(GTK_BOX(hb2), ev, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hb), hb2, TRUE, TRUE, 0);
+ */
+ gtk_box_pack_start(GTK_BOX(hb), ev, TRUE, TRUE, 0);
+ g_object_set_data_full(G_OBJECT(ev), "UID", g_strdup(event->uid), g_free);
+ g_object_set_data(G_OBJECT(ev), "offset", GINT_TO_POINTER(tm_start.tm_mday*1000 + tm_start.tm_hour));
+ g_signal_connect((gpointer)ev, "button-press-event"
+ , G_CALLBACK(on_button_press_event_cb), dw);
+ g_free(tip);
+ g_free(text);
+
+ /* and finally draw the line to show how long the appointment is,
+ * but only if it is Busy type event (=availability != 0)
+ * and it is not whole day event */
+ if (TRUE) {
+ height = dw->StartDate_button_req.height;
+ /*
+ * same_date = !strncmp(start_ical_time, end_ical_time, 8);
+ * */
+ if (start_col < 1)
+ first_col = 1;
+ else
+ first_col = start_col;
+ if (end_col > days)
+ last_col = days;
+ else
+ last_col = end_col;
+ for (col = first_col; col <= last_col; col++) {
+ if (col == start_col)
+ start_row = tm_start.tm_hour;
+ else
+ start_row = 0;
+ if (col == end_col)
+ end_row = tm_end.tm_hour;
+ else
+ end_row = 23;
+ for (row = start_row; row <= end_row; row++) {
+ if (row == tm_start.tm_hour && col == start_col)
+ start_height = tm_start.tm_min*height/60;
+ else
+ start_height = 0;
+ if (row == tm_end.tm_hour && col == end_col)
+ end_height = tm_end.tm_min*height/60;
+ else
+ end_height = height;
+ dw->line[row][col] = build_line(1, start_height
+ , 2, end_height-start_height, dw->line[row][col]
+ , &dw->line_color);
+ }
+ }
+ }
+}
+
+static void app_rows(day_win *dw, FolderItem *item)
+{
+ GSList *events = vcal_get_events_list(item);
+ GSList *cur = NULL;
+ int days = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dw->day_spin));
+ for (cur = events; cur ; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *) (cur->data);
+ add_row(dw, event, days);
+ vcal_manager_free_event(event);
+ }
+ g_slist_free(events);
+}
+
+static void app_data(day_win *dw, FolderItem *item)
+{
+ app_rows(dw, item);
+}
+
+
+static void fill_days(day_win *dw, gint days, FolderItem *item, gint first_col_day)
+{
+ gint row, col, height, width;
+ GtkWidget *ev, *hb;
+
+ height = dw->StartDate_button_req.height;
+ width = dw->StartDate_button_req.width;
+
+ /* first clear the structure */
+ for (col = 1; col < days+1; col++) {
+ dw->header[col] = NULL;
+ for (row = 0; row < 24; row++) {
+ dw->element[row][col] = NULL;
+ /* gdk_draw_rectangle(, , , left_x, top_y, width, height); */
+ dw->line[row][col] = build_line(0, 0, 3, height, NULL
+ , &dw->line_color);
+ }
+ }
+
+ app_data(dw, item);
+
+ for (col = 1; col < days+1; col++) {
+ hb = gtk_hbox_new(FALSE, 0);
+ /* check if we have full day events and put them to header */
+ if (dw->header[col]) {
+ gtk_box_pack_start(GTK_BOX(hb), dw->header[col], TRUE, TRUE, 0);
+ gtk_widget_set_size_request(hb, width, -1);
+ }
+ else {
+ ev = gtk_event_box_new();
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &dw->bg2);
+ gtk_box_pack_start(GTK_BOX(hb), ev, TRUE, TRUE, 0);
+ }
+ gtk_table_attach(GTK_TABLE(dw->dtable_h), hb, col, col+1, 1, 2
+ , (GTK_FILL), (0), 0, 0);
+
+ /* check rows */
+ for (row = 0; row < 24; row++) {
+ hb = gtk_hbox_new(FALSE, 0);
+ if (row == 0)
+ gtk_widget_set_size_request(hb, width, -1);
+ if (dw->element[row][col]) {
+ gtk_box_pack_start(GTK_BOX(hb), dw->line[row][col]
+ , FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hb), dw->element[row][col]
+ , TRUE, TRUE, 0);
+ gtk_widget_set_size_request(hb, width, -1);
+ }
+ else {
+ ev = gtk_event_box_new();
+ g_object_set_data(G_OBJECT(ev), "offset", GINT_TO_POINTER(first_col_day*1000 + row));
+ g_signal_connect((gpointer)ev, "button-press-event"
+ , G_CALLBACK(on_button_press_event_cb), dw);
+ /*
+ name = gtk_label_new(" ");
+ gtk_container_add(GTK_CONTAINER(ev), name);
+ */
+ if ((row % 2) == 1)
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &dw->bg1);
+ else
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &dw->bg2);
+ gtk_box_pack_start(GTK_BOX(hb), dw->line[row][col]
+ , FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hb), ev, TRUE, TRUE, 0);
+ }
+ gtk_table_attach(GTK_TABLE(dw->dtable), hb, col, col+1, row, row+1
+ , (GTK_FILL), (0), 0, 0);
+ }
+ first_col_day++;
+ }
+}
+
+static void build_day_view_header(day_win *dw, char *start_date)
+{
+ GtkWidget *hbox, *label, *space_label;
+ SummaryView *summaryview = NULL;
+ int avail_w = 0, avail_d = 0;
+
+ hbox = gtk_hbox_new(FALSE, 0);
+
+ label = gtk_label_new(_("Start"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
+
+ /* start date button */
+ dw->StartDate_button = gtk_button_new();
+ gtk_box_pack_start(GTK_BOX(hbox), dw->StartDate_button, FALSE, FALSE, 0);
+
+ space_label = gtk_label_new(" ");
+ gtk_box_pack_start(GTK_BOX(hbox), space_label, FALSE, FALSE, 0);
+
+ space_label = gtk_label_new(" ");
+ gtk_box_pack_start(GTK_BOX(hbox), space_label, FALSE, FALSE, 0);
+
+ label = gtk_label_new(_("Show"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
+
+ /* show days spin = how many days to show */
+ dw->day_spin = gtk_spin_button_new_with_range(1, MAX_DAYS, 1);
+ gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(dw->day_spin), TRUE);
+ gtk_widget_set_size_request(dw->day_spin, 40, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), dw->day_spin, FALSE, FALSE, 0);
+ label = gtk_label_new(_("days"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+
+ space_label = gtk_label_new(" ");
+ gtk_box_pack_start(GTK_BOX(hbox), space_label, FALSE, FALSE, 0);
+
+ /* sizes */
+ gtk_button_set_label(GTK_BUTTON(dw->StartDate_button)
+ , (const gchar *)start_date);
+ gtk_widget_size_request(dw->StartDate_button, &dw->StartDate_button_req);
+ dw->StartDate_button_req.width += dw->StartDate_button_req.width/10;
+ label = gtk_label_new("00");
+ gtk_widget_size_request(label, &dw->hour_req);
+
+ if (mainwindow_get_mainwindow()) {
+ GtkAllocation allocation;
+ summaryview = mainwindow_get_mainwindow()->summaryview;
+ allocation = summaryview->mainwidget_book->allocation;
+
+ avail_w = allocation.width - 20 - 2*(dw->hour_req.width);
+ avail_d = avail_w / dw->StartDate_button_req.width;
+ }
+ if (avail_d >= 7) {
+ avail_d = 7;
+ gtk_widget_set_size_request(dw->StartDate_button, avail_w / avail_d, -1);
+ gtk_widget_size_request(dw->StartDate_button, &dw->StartDate_button_req);
+ }
+
+ /* initial values */
+ if (avail_d)
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(dw->day_spin), avail_d);
+
+}
+
+static void build_day_view_colours(day_win *dw)
+{
+ GtkStyle *def_style;
+ GdkColormap *pic1_cmap;
+ GtkWidget *ctree = NULL;
+ def_style = gtk_widget_get_default_style();
+ pic1_cmap = gdk_colormap_get_system();
+
+ if (mainwindow_get_mainwindow()) {
+ ctree = mainwindow_get_mainwindow()->summaryview->ctree;
+ }
+ if (ctree) {
+ dw->bg1 = ctree->style->bg[GTK_STATE_NORMAL];
+ dw->bg2 = ctree->style->bg[GTK_STATE_NORMAL];
+ } else {
+ dw->bg1 = def_style->bg[GTK_STATE_NORMAL];
+ dw->bg2 = def_style->bg[GTK_STATE_NORMAL];
+ }
+ dw->bg1.red += (dw->bg1.red < 63000 ? 2000 : -2000);
+ dw->bg1.green += (dw->bg1.green < 63000 ? 2000 : -2000);
+ dw->bg1.blue += (dw->bg1.blue < 63000 ? 2000 : -2000);
+ gdk_colormap_alloc_color(pic1_cmap, &dw->bg1, FALSE, TRUE);
+
+ dw->bg2.red += (dw->bg2.red > 1000 ? -1000 : 1000);
+ dw->bg2.green += (dw->bg2.green > 1000 ? -1000 : 1000);
+ dw->bg2.blue += (dw->bg2.blue > 1000 ? -1000 : 1000);
+ gdk_colormap_alloc_color(pic1_cmap, &dw->bg2, FALSE, TRUE);
+
+ if (!gdk_color_parse("white", &dw->line_color)) {
+ dw->line_color.red = 239 * (65535/255);
+ dw->line_color.green = 235 * (65535/255);
+ dw->line_color.blue = 230 * (65535/255);
+ }
+
+ if (!gdk_color_parse("blue", &dw->fg_sunday)) {
+ g_warning("color parse failed: red\n");
+ dw->fg_sunday.red = 10 * (65535/255);
+ dw->fg_sunday.green = 10 * (65535/255);
+ dw->fg_sunday.blue = 255 * (65535/255);
+ }
+
+ if (!gdk_color_parse("gold", &dw->bg_today)) {
+ g_warning("color parse failed: gold\n");
+ dw->bg_today.red = 255 * (65535/255);
+ dw->bg_today.green = 215 * (65535/255);
+ dw->bg_today.blue = 115 * (65535/255);
+ }
+
+ if (ctree) {
+ dw->fg_sunday.red = (dw->fg_sunday.red + ctree->style->fg[GTK_STATE_SELECTED].red)/2;
+ dw->fg_sunday.green = (dw->fg_sunday.green + ctree->style->fg[GTK_STATE_SELECTED].red)/2;
+ dw->fg_sunday.blue = (3*dw->fg_sunday.blue + ctree->style->fg[GTK_STATE_SELECTED].red)/4;
+ dw->bg_today.red = (3*dw->bg_today.red + ctree->style->bg[GTK_STATE_NORMAL].red)/4;
+ dw->bg_today.green = (3*dw->bg_today.green + ctree->style->bg[GTK_STATE_NORMAL].red)/4;
+ dw->bg_today.blue = (3*dw->bg_today.blue + ctree->style->bg[GTK_STATE_NORMAL].red)/4;
+ }
+
+ gdk_colormap_alloc_color(pic1_cmap, &dw->line_color, FALSE, TRUE);
+ gdk_colormap_alloc_color(pic1_cmap, &dw->fg_sunday, FALSE, TRUE);
+ gdk_colormap_alloc_color(pic1_cmap, &dw->bg_today, FALSE, TRUE);
+}
+
+static void fill_hour(day_win *dw, gint col, gint row, char *text)
+{
+ GtkWidget *name, *ev;
+
+ ev = gtk_event_box_new();
+ name = gtk_label_new(text);
+ gtk_container_add(GTK_CONTAINER(ev), name);
+ if ((row % 2) == 1)
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &dw->bg1);
+ else
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &dw->bg2);
+ gtk_widget_set_size_request(ev, dw->hour_req.width
+ , dw->StartDate_button_req.height);
+ if (text)
+ gtk_table_attach(GTK_TABLE(dw->dtable), ev, col, col+1, row, row+1
+ , (GTK_FILL), (0), 0, 0);
+ else /* special, needed for header table full day events */
+ gtk_table_attach(GTK_TABLE(dw->dtable_h), ev, col, col+1, row, row+1
+ , (GTK_FILL), (0), 0, 0);
+}
+
+static void build_day_view_table(day_win *dw)
+{
+ gint days; /* number of days to show */
+ int year, month, day;
+ gint i = 0;
+ GtkWidget *label, *button;
+ char text[5+1], *date, *today;
+ struct tm tm_date, tm_today;
+ guint monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ GtkWidget *vp;
+ time_t t = time(NULL);
+ GtkWidget *arrow;
+ gchar *tip;
+ gint first_col_day = -1;
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = dw->Tooltips;
+#endif
+
+#ifdef G_OS_WIN32
+ if (t < 0)
+ t = 1;
+#endif
+ localtime_r(&t, &tm_today);
+ days = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dw->day_spin));
+ today = get_locale_date(&tm_today);
+ /****** header of day table = days columns ******/
+ dw->scroll_win_h = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dw->scroll_win_h)
+ , GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
+ gtk_box_pack_start(GTK_BOX(dw->Vbox), dw->scroll_win_h
+ , TRUE, TRUE, 0);
+ dw->day_view_vbox = gtk_vbox_new(FALSE, 0);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(dw->scroll_win_h)
+ , dw->day_view_vbox);
+ /*
+ gtk_container_add(GTK_CONTAINER(dw->scroll_win_h), dw->day_view_vbox);
+ */
+ /* row 1= day header buttons
+ * row 2= full day events after the buttons */
+ dw->dtable_h = gtk_table_new(2 , days+2, FALSE);
+ gtk_box_pack_start(GTK_BOX(dw->day_view_vbox), dw->dtable_h
+ , FALSE, FALSE, 0);
+
+ tm_date = dw->startdate;
+
+ year = tm_date.tm_year + 1900;
+ month = tm_date.tm_mon;
+ day = tm_date.tm_mday;
+ if (((tm_date.tm_year%4) == 0) && (((tm_date.tm_year%100) != 0)
+ || ((tm_date.tm_year%400) == 0)))
+ monthdays[1] = 29;
+
+
+ i=0;
+ dw->Previous_toolbutton = gtk_event_box_new();
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(dw->Previous_toolbutton), FALSE);
+ gtk_container_set_border_width(GTK_CONTAINER(dw->Previous_toolbutton), 0);
+ arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE);
+ gtk_container_add(GTK_CONTAINER(dw->Previous_toolbutton), arrow);
+ gtk_table_attach(GTK_TABLE(dw->dtable_h), dw->Previous_toolbutton, i, i+1, 0, 1
+ , (GTK_FILL), (0), 0, 0);
+ gtk_widget_show_all(dw->Previous_toolbutton);
+ g_signal_connect((gpointer)dw->Previous_toolbutton, "button_release_event"
+ , G_CALLBACK(on_Previous_clicked), dw);
+ tip = g_strdup_printf("Back %d days", days);
+ CLAWS_SET_TIP(dw->Previous_toolbutton, tip);
+ g_free(tip);
+ for (i = 1; i < days+1; i++) {
+ tip = g_malloc(100);
+ strftime(tip, 99, "%A %d %B %Y", &tm_date);
+ if (first_col_day == -1)
+ first_col_day = tm_date.tm_mday;
+ date = get_locale_date(&tm_date);
+ button = gtk_button_new();
+ gtk_button_set_label(GTK_BUTTON(button), date);
+ if (strcmp(today, date) == 0) {
+ gtk_widget_modify_bg(button, GTK_STATE_NORMAL, &dw->bg_today);
+ }
+
+ if (tm_date.tm_wday % 7 == 0) {
+ label = gtk_bin_get_child(GTK_BIN(button));
+ gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &dw->fg_sunday);
+ }
+ CLAWS_SET_TIP(button, tip);
+ g_free(tip);
+ gtk_widget_set_size_request(button, dw->StartDate_button_req.width, -1);
+ g_signal_connect((gpointer)button, "clicked"
+ , G_CALLBACK(header_button_clicked_cb), dw);
+ g_object_set_data(G_OBJECT(button), "offset", GINT_TO_POINTER(tm_date.tm_mday*1000));
+ gtk_table_attach(GTK_TABLE(dw->dtable_h), button, i, i+1, 0, 1
+ , (GTK_FILL), (0), 0, 0);
+
+ if (++tm_date.tm_mday == (monthdays[tm_date.tm_mon]+1)) {
+ if (++tm_date.tm_mon == 12) {
+ ++tm_date.tm_year;
+ tm_date.tm_mon = 0;
+ }
+ tm_date.tm_mday = 1;
+ }
+ ++tm_date.tm_wday; tm_date.tm_wday %=7;
+ g_free(date);
+ }
+
+ dw->Next_toolbutton = gtk_event_box_new();
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(dw->Next_toolbutton), FALSE);
+ gtk_container_set_border_width(GTK_CONTAINER(dw->Next_toolbutton), 0);
+ arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
+ gtk_container_add(GTK_CONTAINER(dw->Next_toolbutton), arrow);
+ gtk_table_attach(GTK_TABLE(dw->dtable_h), dw->Next_toolbutton, i, i+1, 0, 1
+ , (GTK_FILL), (0), 0, 0);
+ gtk_widget_show_all(dw->Next_toolbutton);
+ g_signal_connect((gpointer)dw->Next_toolbutton, "button_release_event"
+ , G_CALLBACK(on_Next_clicked), dw);
+ tip = g_strdup_printf("Forward %d days", days);
+ CLAWS_SET_TIP(dw->Next_toolbutton, tip);
+ g_free(tip);
+ g_free(today);
+
+ /****** body of day table ******/
+ dw->scroll_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(dw->scroll_win)
+ , GTK_SHADOW_NONE);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dw->scroll_win)
+ , GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(dw->scroll_win)
+ , GTK_CORNER_TOP_LEFT);
+ gtk_box_pack_start(GTK_BOX(dw->day_view_vbox), dw->scroll_win
+ , TRUE, TRUE, 0);
+ vp = gtk_viewport_new(NULL, NULL);
+ gtk_viewport_set_shadow_type(GTK_VIEWPORT(vp), GTK_SHADOW_NONE);
+ gtk_container_add(GTK_CONTAINER(dw->scroll_win), vp);
+ dw->dtable = gtk_table_new(24, days+2, FALSE);
+ gtk_container_add(GTK_CONTAINER(vp), dw->dtable);
+
+ gtk_widget_show_all(dw->dtable_h);
+ /* hours column = hour rows */
+ for (i = 0; i < 24; i++) {
+ g_sprintf(text, "%02d", i);
+ /* ev is needed for background colour */
+ fill_hour(dw, 0, i, text);
+ fill_hour(dw, days+1, i, text);
+ }
+ fill_days(dw, days, dw->item, first_col_day);
+}
+
+void refresh_day_win(day_win *dw)
+{
+ get_scroll_position(dw);
+ gtk_widget_destroy(dw->scroll_win_h);
+ build_day_view_table(dw);
+ gtk_widget_show_all(dw->scroll_win_h);
+ /* I was not able to get this work without the timer. Ugly yes, but
+ * it works and does not hurt - much */
+ g_timeout_add(100, (GSourceFunc)scroll_position_timer, (gpointer)dw);
+}
+
+day_win *create_day_win(FolderItem *item, struct tm tmdate)
+{
+ day_win *dw;
+ char *start_date = get_locale_date(&tmdate);
+
+ /* initialisation + main window + base vbox */
+ dw = g_new0(day_win, 1);
+ dw->scroll_pos = -1; /* not set */
+#if !(GTK_CHECK_VERSION(2,12,0))
+ dw->Tooltips = tips;
+#endif
+ dw->accel_group = gtk_accel_group_new();
+
+ while (tmdate.tm_wday != 1)
+ orage_move_day(&tmdate, -1);
+
+ dw->startdate = tmdate;
+ dw->startdate.tm_hour = 0;
+ dw->startdate.tm_min = 0;
+ dw->startdate.tm_sec = 0;
+ dw->Vbox = gtk_vbox_new(FALSE, 0);
+
+ dw->item = item;
+ build_day_view_colours(dw);
+ build_day_view_header(dw, start_date);
+ build_day_view_table(dw);
+ gtk_widget_show_all(dw->Vbox);
+ dw->selsig = vcal_view_set_calendar_page(dw->Vbox,
+ G_CALLBACK(dw_summary_selected), dw);
+ vcal_view_create_popup_menus(dw->Vbox, &dw->view_menu,
+ &dw->event_menu, &dw->event_group,
+ &dw->ui_manager);
+
+ g_timeout_add(100, (GtkFunction)scroll_position_timer, (gpointer)dw);
+
+ return(dw);
+}
diff --git a/src/plugins/vcalendar/icaltime_as_local.c b/src/plugins/vcalendar/icaltime_as_local.c
@@ -0,0 +1,115 @@
+/* Taken as is from http://dev.w3.org/cvsweb/Ical2html/icaltime_as_local.c
+W3C® SOFTWARE NOTICE AND LICENSE
+
+
+Copyright © 1994-2002 World Wide Web Consortium, (Massachusetts
+Institute of Technology, Institut National de Recherche en
+Informatique et en Automatique, Keio University). All Rights
+Reserved. http://www.w3.org/Consortium/Legal/
+
+This W3C work (including software, documents, or other related items)
+is being provided by the copyright holders under the following
+license. By obtaining, using and/or copying this work, you (the
+licensee) agree that you have read, understood, and will comply with
+the following terms and conditions:
+
+Permission to use, copy, modify, and distribute this software and its
+documentation, with or without modification, for any purpose and
+without fee or royalty is hereby granted, provided that you include
+the following on ALL copies of the software and documentation or
+portions thereof, including modifications, that you make:
+
+The full text of this NOTICE in a location viewable to users of the
+redistributed or derivative work. Any pre-existing intellectual
+property disclaimers, notices, or terms and conditions. If none exist,
+a short notice of the following form (hypertext is preferred, text is
+permitted) should be used within the body of any redistributed or
+derivative code: "Copyright © [$date-of-software] World Wide Web
+Consortium, (Massachusetts Institute of Technology, Institut National
+de Recherche en Informatique et en Automatique, Keio University). All
+Rights Reserved. http://www.w3.org/Consortium/Legal/" Notice of any
+changes or modifications to the W3C files, including the date changes
+were made. (We recommend you provide URIs to the location from which
+the code is derived.)
+
+THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT
+HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR
+DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
+TRADEMARKS OR OTHER RIGHTS.
+
+COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
+DOCUMENTATION.
+
+The name and trademarks of copyright holders may NOT be used in
+advertising or publicity pertaining to the software without specific,
+written prior permission. Title to copyright in this software and any
+associated documentation will at all times remain with copyright
+holders.
+
+____________________________________
+
+This formulation of W3C's notice and license became active on August
+14 1998 so as to improve compatibility with GPL. This version ensures
+that W3C software licensing terms are no more restrictive than GPL and
+consequently W3C software may be distributed in GPL packages. See the
+older formulation for the policy prior to this date. Please see our
+Copyright FAQ for common questions about using materials from our
+site, including specific terms and conditions for packages like
+libwww, Amaya, and Jigsaw. Other questions about this notice can be
+directed to site-policy@w3.org.
+*/
+/*
+ * Convert a date/time in UTC to a date/time in the local time zone.
+ * (Seems to be missing from libical v 0.23)
+ *
+ * Author: Bert Bos <bert@w3.org>
+ * Created: 18 Dec 2002
+ * Version: $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include "icaltime_as_local.h"
+
+#if !HAVE_ICALTIME_AS_LOCAL
+
+struct icaltimetype icaltime_as_local(struct icaltimetype tt)
+{
+ time_t t;
+ struct tm *tm;
+ struct icaltimetype h;
+ struct tm buft;
+
+ t = icaltime_as_timet(tt); /* Convert to epoch */
+#ifdef G_OS_WIN32
+ if (t < 0)
+ t = 1;
+#endif
+ tm = localtime_r(&t, &buft); /* Convert to local time */
+ h.year = tm->tm_year + 1900; /* Make an icaltimetype */
+ h.month = tm->tm_mon + 1;
+ h.day = tm->tm_mday;
+ h.hour = tt.is_date ? 0 : tm->tm_hour;
+ h.minute = tt.is_date ? 0 : tm->tm_min;
+ h.second = tt.is_date ? 0 : tm->tm_sec;
+ h.is_utc = 0;
+ h.is_date = tt.is_date;
+ return h;
+}
+
+#endif
+
diff --git a/src/plugins/vcalendar/icaltime_as_local.h b/src/plugins/vcalendar/icaltime_as_local.h
@@ -0,0 +1,18 @@
+#ifndef __ICALTIME_AS_LOCAL_H__
+#define __ICALTIME_AS_LOCAL_H__
+#include <time.h>
+#include <ical.h>
+#undef PACKAGE_BUGREPORT /* Why are they in ical.h? */
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#undef PACKAGE
+#undef VERSION
+
+#if !HAVE_ICALTIME_AS_LOCAL
+
+struct icaltimetype icaltime_as_local(struct icaltimetype tt);
+
+#endif
+#endif
diff --git a/src/plugins/vcalendar/libical/.cvsignore b/src/plugins/vcalendar/libical/.cvsignore
@@ -0,0 +1,6 @@
+.libs
+.deps
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/plugins/vcalendar/libical/Makefile.am b/src/plugins/vcalendar/libical/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = libical design-data scripts
diff --git a/src/plugins/vcalendar/libical/Makefile.in b/src/plugins/vcalendar/libical/Makefile.in
@@ -0,0 +1,681 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/plugins/vcalendar/libical
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/check-type.m4 \
+ $(top_srcdir)/m4/gnupg-check-typedef.m4 \
+ $(top_srcdir)/m4/gnupg.m4 $(top_srcdir)/m4/gpgme.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/spamassassin.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h \
+ $(top_builddir)/claws-features.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPFACE_LIBS = @COMPFACE_LIBS@
+CONIC_CFLAGS = @CONIC_CFLAGS@
+CONIC_LIBS = @CONIC_LIBS@
+CONTACTS_CFLAGS = @CONTACTS_CFLAGS@
+CONTACTS_LIBS = @CONTACTS_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPT_LIBS = @CRYPT_LIBS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOCBOOK2HTML = @DOCBOOK2HTML@
+DOCBOOK2PDF = @DOCBOOK2PDF@
+DOCBOOK2PS = @DOCBOOK2PS@
+DOCBOOK2TXT = @DOCBOOK2TXT@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCHANT_CFLAGS = @ENCHANT_CFLAGS@
+ENCHANT_LIBS = @ENCHANT_LIBS@
+EXEEXT = @EXEEXT@
+EXTRA_VERSION = @EXTRA_VERSION@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNOME2_CFLAGS = @GNOME2_CFLAGS@
+GNOME2_LIBS = @GNOME2_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GPGME_CFLAGS = @GPGME_CFLAGS@
+GPGME_CONFIG = @GPGME_CONFIG@
+GPGME_LIBS = @GPGME_LIBS@
+GREP = @GREP@
+GTKPRINTUNIX_CFLAGS = @GTKPRINTUNIX_CFLAGS@
+GTKPRINTUNIX_LIBS = @GTKPRINTUNIX_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JPILOT_LIBS = @JPILOT_LIBS@
+LD = @LD@
+LDAP_LIBS = @LDAP_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBETPAN_FLAGS = @LIBETPAN_FLAGS@
+LIBETPAN_LIBS = @LIBETPAN_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBRESOLV = @LIBRESOLV@
+LIBS = @LIBS@
+LIBSOUP_GNOME_CFLAGS = @LIBSOUP_GNOME_CFLAGS@
+LIBSOUP_GNOME_LIBS = @LIBSOUP_GNOME_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAEMO_CFLAGS = @MAEMO_CFLAGS@
+MAEMO_LIBS = @MAEMO_LIBS@
+MAINT = @MAINT@
+MAJOR_VERSION = @MAJOR_VERSION@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MICRO_VERSION = @MICRO_VERSION@
+MINOR_VERSION = @MINOR_VERSION@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETWORKMANAGER_SUPPORT_CFLAGS = @NETWORKMANAGER_SUPPORT_CFLAGS@
+NETWORKMANAGER_SUPPORT_LIBS = @NETWORKMANAGER_SUPPORT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PASSCRYPT_KEY = @PASSCRYPT_KEY@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SM_LIBS = @SM_LIBS@
+STARTUP_NOTIFICATION_CFLAGS = @STARTUP_NOTIFICATION_CFLAGS@
+STARTUP_NOTIFICATION_LIBS = @STARTUP_NOTIFICATION_LIBS@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VERSION = @VERSION@
+WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
+WEBKIT_LIBS = @WEBKIT_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_cv_enable_crash_dialog = @ac_cv_enable_crash_dialog@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gnomedatadir = @gnomedatadir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libetpanconfig = @libetpanconfig@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+manualdir = @manualdir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = libical design-data scripts
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/plugins/vcalendar/libical/design-data/.cvsignore b/src/plugins/vcalendar/libical/design-data/.cvsignore
@@ -0,0 +1,6 @@
+.libs
+.deps
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/plugins/vcalendar/libical/design-data/Makefile.am b/src/plugins/vcalendar/libical/design-data/Makefile.am
@@ -0,0 +1,6 @@
+EXTRA_DIST =\
+ properties.csv \
+ parameters.csv \
+ restrictions.csv \
+ status.txt \
+ value-types.csv
diff --git a/src/plugins/vcalendar/libical/design-data/Makefile.in b/src/plugins/vcalendar/libical/design-data/Makefile.in
@@ -0,0 +1,488 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/plugins/vcalendar/libical/design-data
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/check-type.m4 \
+ $(top_srcdir)/m4/gnupg-check-typedef.m4 \
+ $(top_srcdir)/m4/gnupg.m4 $(top_srcdir)/m4/gpgme.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/spamassassin.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h \
+ $(top_builddir)/claws-features.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPFACE_LIBS = @COMPFACE_LIBS@
+CONIC_CFLAGS = @CONIC_CFLAGS@
+CONIC_LIBS = @CONIC_LIBS@
+CONTACTS_CFLAGS = @CONTACTS_CFLAGS@
+CONTACTS_LIBS = @CONTACTS_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPT_LIBS = @CRYPT_LIBS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOCBOOK2HTML = @DOCBOOK2HTML@
+DOCBOOK2PDF = @DOCBOOK2PDF@
+DOCBOOK2PS = @DOCBOOK2PS@
+DOCBOOK2TXT = @DOCBOOK2TXT@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCHANT_CFLAGS = @ENCHANT_CFLAGS@
+ENCHANT_LIBS = @ENCHANT_LIBS@
+EXEEXT = @EXEEXT@
+EXTRA_VERSION = @EXTRA_VERSION@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNOME2_CFLAGS = @GNOME2_CFLAGS@
+GNOME2_LIBS = @GNOME2_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GPGME_CFLAGS = @GPGME_CFLAGS@
+GPGME_CONFIG = @GPGME_CONFIG@
+GPGME_LIBS = @GPGME_LIBS@
+GREP = @GREP@
+GTKPRINTUNIX_CFLAGS = @GTKPRINTUNIX_CFLAGS@
+GTKPRINTUNIX_LIBS = @GTKPRINTUNIX_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JPILOT_LIBS = @JPILOT_LIBS@
+LD = @LD@
+LDAP_LIBS = @LDAP_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBETPAN_FLAGS = @LIBETPAN_FLAGS@
+LIBETPAN_LIBS = @LIBETPAN_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBRESOLV = @LIBRESOLV@
+LIBS = @LIBS@
+LIBSOUP_GNOME_CFLAGS = @LIBSOUP_GNOME_CFLAGS@
+LIBSOUP_GNOME_LIBS = @LIBSOUP_GNOME_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAEMO_CFLAGS = @MAEMO_CFLAGS@
+MAEMO_LIBS = @MAEMO_LIBS@
+MAINT = @MAINT@
+MAJOR_VERSION = @MAJOR_VERSION@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MICRO_VERSION = @MICRO_VERSION@
+MINOR_VERSION = @MINOR_VERSION@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETWORKMANAGER_SUPPORT_CFLAGS = @NETWORKMANAGER_SUPPORT_CFLAGS@
+NETWORKMANAGER_SUPPORT_LIBS = @NETWORKMANAGER_SUPPORT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PASSCRYPT_KEY = @PASSCRYPT_KEY@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SM_LIBS = @SM_LIBS@
+STARTUP_NOTIFICATION_CFLAGS = @STARTUP_NOTIFICATION_CFLAGS@
+STARTUP_NOTIFICATION_LIBS = @STARTUP_NOTIFICATION_LIBS@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VERSION = @VERSION@
+WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
+WEBKIT_LIBS = @WEBKIT_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_cv_enable_crash_dialog = @ac_cv_enable_crash_dialog@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gnomedatadir = @gnomedatadir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libetpanconfig = @libetpanconfig@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+manualdir = @manualdir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ properties.csv \
+ parameters.csv \
+ restrictions.csv \
+ status.txt \
+ value-types.csv
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/design-data/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/design-data/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/plugins/vcalendar/libical/design-data/parameters.csv b/src/plugins/vcalendar/libical/design-data/parameters.csv
@@ -0,0 +1,25 @@
+"#Name ","C Type","Enumeration Values"
+"ALTREP","const char*",
+"CHARSET", "const char *",
+"CN","const char*",
+"CUTYPE","icalparameter_cutype","INDIVIDUAL;GROUP;RESOURCE;ROOM;UNKNOWN"
+"DELEGATED-FROM","const char*",
+"DELEGATED-TO","const char*",
+"DIR","const char*",
+"ENCODING","icalparameter_encoding","8BIT;BASE64"
+"FBTYPE","icalparameter_fbtype","FREE;BUSY;BUSYUNAVAILABLE;BUSYTENTATIVE"
+"FMTTYPE","const char*",
+"LANGUAGE","const char*",
+"MEMBER","const char*",
+"PARTSTAT","icalparameter_partstat","NEEDS-ACTION;ACCEPTED;DECLINED;TENTATIVE;DELEGATED;COMPLETED;INPROCESS"
+"RANGE","icalparameter_range","THISANDPRIOR;THISANDFUTURE"
+"RELATED","icalparameter_related","START;END "
+"RELTYPE","icalparameter_reltype","PARENT;CHILD;SIBLING"
+"ROLE","icalparameter_role","CHAIR;REQ-PARTICIPANT;OPT-PARTICIPANT;NON-PARTICIPANT"
+"RSVP","icalparameter_rsvp","TRUE;FALSE"
+"SENT-BY","const char*",
+"TZID","const char*",
+"VALUE","icalparameter_value","BINARY;BOOLEAN;DATE;DURATION;FLOAT;INTEGER;PERIOD;RECUR;TEXT;TIME;URI;ERROR;DATE-TIME;UTC-OFFSET;CAL-ADDRESS"
+"X","const char*",
+"X-LIC-ERRORTYPE","icalparameter_xlicerrortype","COMPONENT-PARSE-ERROR;PROPERTY-PARSE-ERROR;PARAMETER-NAME-PARSE-ERROR;PARAMETER-VALUE-PARSE-ERROR;VALUE-PARSE-ERROR;INVALID-ITIP;UNKNOWN-VCAL-PROP-ERROR;MIME-PARSE-ERROR"
+"X-LIC-COMPARETYPE","icalparameter_xliccomparetype","EQUAL;NOTEQUAL;LESS;GREATER;LESSEQUAL;GREATEREQUAL;REGEX"
diff --git a/src/plugins/vcalendar/libical/design-data/properties.csv b/src/plugins/vcalendar/libical/design-data/properties.csv
@@ -0,0 +1,66 @@
+,,
+"#Property Name","libical Value type","iCalendar default value"
+"ACTION","ACTION","ACTION"
+"ATTACH","ATTACH","URI"
+"ATTENDEE","CAL-ADDRESS","CAL-ADDRESS"
+"CALSCALE","TEXT","TEXT"
+"CATEGORIES","TEXT","TEXT"
+"CLASS","TEXT","TEXT"
+"COMMENT","TEXT","TEXT"
+"COMPLETED","DATE-TIME","DATE-TIME"
+"CONTACT","TEXT","TEXT"
+"CREATED","DATE-TIME","DATE-TIME"
+"DESCRIPTION","TEXT","TEXT"
+"DTEND","DATE-TIME","DATE-TIME"
+"DTSTAMP","DATE-TIME","DATE-TIME"
+"DTSTART","DATE-TIME","DATE-TIME"
+"DUE","DATE-TIME","DATE-TIME"
+"DURATION","DURATION","DURATION"
+"EXDATE","DATE-TIME","DATE-TIME"
+"EXRULE","RECUR","RECUR"
+"FREEBUSY","PERIOD","PERIOD"
+"GEO","GEO","GEO"
+"LAST-MODIFIED","DATE-TIME","DATE-TIME"
+"LOCATION","TEXT","TEXT"
+"METHOD","METHOD","METHOD"
+"ORGANIZER","CAL-ADDRESS","CAL-ADDRESS"
+"PERCENT-COMPLETE","INTEGER","INTEGER"
+"PRIORITY","INTEGER","INTEGER"
+"PRODID","TEXT","TEXT"
+"RDATE","DATE-TIME-PERIOD","DATE-TIME"
+"RECURRENCE-ID","DATE-TIME","DATE-TIME"
+"RELATED-TO","TEXT","TEXT"
+"REPEAT","INTEGER","INTEGER"
+"REQUEST-STATUS","STRING","STRING"
+"RESOURCES","TEXT","TEXT"
+"RRULE","RECUR","RECUR"
+"SEQUENCE","INTEGER","INTEGER"
+"STATUS","STATUS","STATUS"
+"SUMMARY","TEXT","TEXT"
+"TRANSP","TEXT","TEXT"
+"TRIGGER","TRIGGER","DURATION"
+"TZID","TEXT","TEXT"
+"TZNAME","TEXT","TEXT"
+"TZOFFSETFROM","UTC-OFFSET","UTC-OFFSET"
+"TZOFFSETTO","UTC-OFFSET","UTC-OFFSET"
+"TZURL","URI","URI"
+"UID","TEXT","TEXT"
+"URL","URI","URI"
+"VERSION","TEXT","TEXT"
+"X","TEXT","TEXT"
+"SCOPE","TEXT","TEXT"
+"MAXRESULTS","INTEGER","INTEGER"
+"MAXRESULTSSIZE","INTEGER","INTEGER"
+"QUERY","QUERY","QUERY"
+"QUERYNAME","TEXT","TEXT"
+"TARGET","CAL-ADDRESS","CAL-ADDRESS"
+"X-LIC-ERROR","TEXT","TEXT"
+"X-LIC-CLUSTERCOUNT","STRING","STRING"
+"X-LIC-MIMECONTENTTYPE","STRING","STRING"
+"X-LIC-MIMECHARSET","STRING","STRING"
+"X-LIC-MIMEENCODING","STRING","STRING"
+"X-LIC-MIMEOPTINFO","STRING","STRING"
+"X-LIC-MIMECID","STRING","STRING"
+"X-LIC-MIMEFILENAME","STRING","STRING"
+"ANY","NO","NO"
+"NO","NO","NO"
diff --git a/src/plugins/vcalendar/libical/design-data/restrictions.csv b/src/plugins/vcalendar/libical/design-data/restrictions.csv
@@ -0,0 +1,1348 @@
+# Method, Target component, Property, Sub-component, Restriction
+PUBLISH,VEVENT,NONE,NONE,ONEPLUS
+PUBLISH,VEVENT,DTSTAMP,NONE,ONE
+PUBLISH,VEVENT,DTSTART,NONE,ONE
+PUBLISH,VEVENT,ORGANIZER,NONE,ONE
+PUBLISH,VEVENT,SUMMARY,NONE,ONE
+PUBLISH,VEVENT,UID,NONE,ONE
+PUBLISH,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+PUBLISH,VEVENT,SEQUENCE,NONE,ZEROORONE
+PUBLISH,VEVENT,ATTACH,NONE,ZEROPLUS
+PUBLISH,VEVENT,CATEGORIES,NONE,ZEROPLUS #Non-standard
+PUBLISH,VEVENT,CLASS,NONE,ZEROORONE
+PUBLISH,VEVENT,COMMENT,NONE,ZEROORONE
+PUBLISH,VEVENT,CONTACT,NONE,ZEROPLUS
+PUBLISH,VEVENT,CREATED,NONE,ZEROORONE
+PUBLISH,VEVENT,DESCRIPTION,NONE,ZEROORONE
+PUBLISH,VEVENT,DTEND,NONE,ZEROORONE
+PUBLISH,VEVENT,DURATION,NONE,ZEROORONE
+PUBLISH,VEVENT,EXDATE,NONE,ZEROPLUS
+PUBLISH,VEVENT,EXRULE,NONE,ZEROPLUS
+PUBLISH,VEVENT,GEO,NONE,ZEROORONE
+PUBLISH,VEVENT,LASTMODIFIED,NONE,ZEROORONE
+PUBLISH,VEVENT,LOCATION,NONE,ZEROORONE
+PUBLISH,VEVENT,PRIORITY,NONE,ZEROORONE
+PUBLISH,VEVENT,RDATE,NONE,ZEROPLUS
+PUBLISH,VEVENT,RELATEDTO,NONE,ZEROPLUS
+PUBLISH,VEVENT,RESOURCES,NONE,ZEROORONE
+PUBLISH,VEVENT,RRULE,NONE,ZEROPLUS
+PUBLISH,VEVENT,STATUS,NONE,ZEROORONE,may_be_tent_conf_cancel
+PUBLISH,VEVENT,TRANSP,NONE,ZEROORONE
+PUBLISH,VEVENT,URL,NONE,ZEROORONE
+PUBLISH,VEVENT,X,NONE,ZEROPLUS
+PUBLISH,VEVENT,ATTENDEE,NONE,ZERO
+PUBLISH,VEVENT,REQUESTSTATUS,NONE,ZERO
+PUBLISH,VEVENT,NONE,VALARM,ZEROPLUS
+PUBLISH,VEVENT,NONE,VFREEBUSY,ZERO
+PUBLISH,VEVENT,NONE,VJOURNAL,ZERO
+PUBLISH,VEVENT,NONE,VTODO,ZERO
+PUBLISH,VEVENT,NONE,VTIMEZONE,ZEROPLUS,must_if_tz_ref
+PUBLISH,VEVENT,NONE,X,ZEROPLUS
+REQUEST,VEVENT,NONE,NONE,ONEPLUS
+REQUEST,VEVENT,ATTENDEE,NONE,ONEPLUS
+REQUEST,VEVENT,DTSTAMP,NONE,ONE
+REQUEST,VEVENT,DTSTART,NONE,ONE
+REQUEST,VEVENT,ORGANIZER,NONE,ONE
+REQUEST,VEVENT,SEQUENCE,NONE,ZEROORONE
+REQUEST,VEVENT,SUMMARY,NONE,ONE
+REQUEST,VEVENT,UID,NONE,ONE
+REQUEST,VEVENT,ATTACH,NONE,ZEROPLUS
+REQUEST,VEVENT,CATEGORIES,NONE,ZEROPLUS #Non-standard
+REQUEST,VEVENT,CLASS,NONE,ZEROORONE
+REQUEST,VEVENT,COMMENT,NONE,ZEROORONE
+REQUEST,VEVENT,CONTACT,NONE,ZEROPLUS
+REQUEST,VEVENT,CREATED,NONE,ZEROORONE
+REQUEST,VEVENT,DESCRIPTION,NONE,ZEROORONE
+REQUEST,VEVENT,DTEND,NONE,ONEEXCLUSIVE,no_duration
+REQUEST,VEVENT,DURATION,NONE,ONEEXCLUSIVE,no_dtend
+REQUEST,VEVENT,EXDATE,NONE,ZEROPLUS
+REQUEST,VEVENT,EXRULE,NONE,ZEROPLUS
+REQUEST,VEVENT,GEO,NONE,ZEROORONE
+REQUEST,VEVENT,LASTMODIFIED,NONE,ZEROORONE
+REQUEST,VEVENT,LOCATION,NONE,ZEROORONE
+REQUEST,VEVENT,PRIORITY,NONE,ZEROORONE
+REQUEST,VEVENT,RDATE,NONE,ZEROPLUS
+REQUEST,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+REQUEST,VEVENT,RELATEDTO,NONE,ZEROPLUS
+REQUEST,VEVENT,REQUESTSTATUS,NONE,ZEROPLUS
+REQUEST,VEVENT,RESOURCES,NONE,ZEROORONE
+REQUEST,VEVENT,RRULE,NONE,ZEROPLUS
+REQUEST,VEVENT,STATUS,NONE,ZEROORONE,may_be_tent_conf
+REQUEST,VEVENT,TRANSP,NONE,ZEROORONE
+REQUEST,VEVENT,URL,NONE,ZEROORONE
+REQUEST,VEVENT,X,NONE,ZEROPLUS
+REQUEST,VEVENT,NONE,VALARM,ZEROPLUS
+REQUEST,VEVENT,NONE,VTIMEZONE,ZEROPLUS,must_if_tz_ref
+REQUEST,VEVENT,NONE,X,ZEROPLUS
+REQUEST,VEVENT,NONE,VFREEBUSY,ZERO
+REQUEST,VEVENT,NONE,VJOURNAL,ZERO
+REQUEST,VEVENT,NONE,VTODO,ZERO
+REPLY,VEVENT,NONE,NONE,ONEPLUS
+REPLY,VEVENT,ATTENDEE,NONE,ONE
+REPLY,VEVENT,DTSTAMP,NONE,ONE
+REPLY,VEVENT,ORGANIZER,NONE,ONE
+REPLY,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+REPLY,VEVENT,UID,NONE,ONE
+REPLY,VEVENT,SEQUENCE,NONE,ZEROORONE
+REPLY,VEVENT,ATTACH,NONE,ZEROPLUS
+REPLY,VEVENT,CATEGORIES,NONE,ZEROPLUS #Non-standard
+REPLY,VEVENT,CLASS,NONE,ZEROORONE
+REPLY,VEVENT,COMMENT,NONE,ZEROORONE
+REPLY,VEVENT,CONTACT,NONE,ZEROPLUS
+REPLY,VEVENT,CREATED,NONE,ZEROORONE
+REPLY,VEVENT,DESCRIPTION,NONE,ZEROORONE
+REPLY,VEVENT,DTEND,NONE,ONEEXCLUSIVE,no_duration
+REPLY,VEVENT,DTSTART,NONE,ZEROORONE
+REPLY,VEVENT,DURATION,NONE,ONEEXCLUSIVE,no_dtend
+REPLY,VEVENT,EXDATE,NONE,ZEROPLUS
+REPLY,VEVENT,EXRULE,NONE,ZEROPLUS
+REPLY,VEVENT,GEO,NONE,ZEROORONE
+REPLY,VEVENT,LASTMODIFIED,NONE,ZEROORONE
+REPLY,VEVENT,LOCATION,NONE,ZEROORONE
+REPLY,VEVENT,PRIORITY,NONE,ZEROORONE
+REPLY,VEVENT,RDATE,NONE,ZEROPLUS
+REPLY,VEVENT,RELATEDTO,NONE,ZEROPLUS
+REPLY,VEVENT,RESOURCES,NONE,ZEROORONE
+REPLY,VEVENT,REQUESTSTATUS,NONE,ZEROPLUS
+REPLY,VEVENT,RRULE,NONE,ZEROPLUS
+REPLY,VEVENT,STATUS,NONE,ZEROORONE
+REPLY,VEVENT,SUMMARY,NONE,ZEROORONE
+REPLY,VEVENT,TRANSP,NONE,ZEROORONE
+REPLY,VEVENT,URL,NONE,ZEROORONE
+REPLY,VEVENT,X,NONE,ZEROPLUS
+REPLY,VEVENT,NONE,VTIMEZONE,ZEROORONE,must_if_tz_ref
+REPLY,VEVENT,NONE,X,ZEROPLUS
+REPLY,VEVENT,NONE,VALARM,ZERO
+REPLY,VEVENT,NONE,VFREEBUSY,ZERO
+REPLY,VEVENT,NONE,VJOURNAL,ZERO
+REPLY,VEVENT,NONE,VTODO,ZERO
+ADD,VEVENT,NONE,NONE,ONE
+ADD,VEVENT,DTSTAMP,NONE,ONE
+ADD,VEVENT,DTSTART,NONE,ONE
+ADD,VEVENT,ORGANIZER,NONE,ONE
+ADD,VEVENT,SEQUENCE,NONE,ONE
+ADD,VEVENT,SUMMARY,NONE,ONE
+ADD,VEVENT,UID,NONE,ONE
+ADD,VEVENT,ATTACH,NONE,ZEROPLUS
+ADD,VEVENT,ATTENDEE,NONE,ZEROPLUS
+ADD,VEVENT,CATEGORIES,NONE,ZEROPLUS #Non-standard
+ADD,VEVENT,CLASS,NONE,ZEROORONE
+ADD,VEVENT,COMMENT,NONE,ZEROORONE
+ADD,VEVENT,CONTACT,NONE,ZEROPLUS
+ADD,VEVENT,CREATED,NONE,ZEROORONE
+ADD,VEVENT,DESCRIPTION,NONE,ZEROORONE
+ADD,VEVENT,DTEND,NONE,ONEEXCLUSIVE,no_duration
+ADD,VEVENT,DURATION,NONE,ONEEXCLUSIVE,no_duration
+ADD,VEVENT,EXDATE,NONE,ZEROPLUS
+ADD,VEVENT,EXRULE,NONE,ZEROPLUS
+ADD,VEVENT,GEO,NONE,ZEROORONE
+ADD,VEVENT,LASTMODIFIED,NONE,ZEROORONE
+ADD,VEVENT,LOCATION,NONE,ZEROORONE
+ADD,VEVENT,PRIORITY,NONE,ZEROORONE
+ADD,VEVENT,RDATE,NONE,ZEROPLUS
+ADD,VEVENT,RELATEDTO,NONE,ZEROPLUS
+ADD,VEVENT,RESOURCES,NONE,ZEROORONE
+ADD,VEVENT,RRULE,NONE,ZEROPLUS
+ADD,VEVENT,STATUS,NONE,ZEROORONE,may_be_tent_conf
+ADD,VEVENT,TRANSP,NONE,ZEROORONE
+ADD,VEVENT,URL,NONE,ZEROORONE
+ADD,VEVENT,X,NONE,ZEROPLUS
+ADD,VEVENT,RECURRENCEID,NONE,ZERO,must_be_recurring
+ADD,VEVENT,REQUESTSTATUS,NONE,ZERO
+ADD,VEVENT,NONE,VALARM,ZEROPLUS
+ADD,VEVENT,NONE,VTIMEZONE,ZEROPLUS,must_if_tz_ref
+ADD,VEVENT,NONE,X,ZEROPLUS
+ADD,VEVENT,NONE,VFREEBUSY,ZERO
+ADD,VEVENT,NONE,VTODO,ZERO
+ADD,VEVENT,NONE,VJOURNAL,ZERO
+CANCEL,VEVENT,NONE,NONE,ONEPLUS
+CANCEL,VEVENT,ATTENDEE,NONE,ZEROPLUS
+CANCEL,VEVENT,DTSTAMP,NONE,ONE
+CANCEL,VEVENT,ORGANIZER,NONE,ONE
+CANCEL,VEVENT,SEQUENCE,NONE,ONE
+CANCEL,VEVENT,UID,NONE,ONE
+CANCEL,VEVENT,COMMENT,NONE,ZEROORONE
+CANCEL,VEVENT,ATTACH,NONE,ZEROPLUS
+CANCEL,VEVENT,CATEGORIES,NONE,ZEROPLUS #Non-standard
+CANCEL,VEVENT,CLASS,NONE,ZEROORONE
+CANCEL,VEVENT,CONTACT,NONE,ZEROPLUS
+CANCEL,VEVENT,CREATED,NONE,ZEROORONE
+CANCEL,VEVENT,DESCRIPTION,NONE,ZEROORONE
+CANCEL,VEVENT,DTEND,NONE,ONEEXCLUSIVE ,no_duration
+CANCEL,VEVENT,DTSTART,NONE,ZEROORONE
+CANCEL,VEVENT,DURATION,NONE,ONEEXCLUSIVE,no_duration
+CANCEL,VEVENT,EXDATE,NONE,ZEROPLUS
+CANCEL,VEVENT,EXRULE,NONE,ZEROPLUS
+CANCEL,VEVENT,GEO,NONE,ZEROORONE
+CANCEL,VEVENT,LASTMODIFIED,NONE,ZEROORONE
+CANCEL,VEVENT,LOCATION,NONE,ZEROORONE
+CANCEL,VEVENT,PRIORITY,NONE,ZEROORONE
+CANCEL,VEVENT,RDATE,NONE,ZEROPLUS
+CANCEL,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+CANCEL,VEVENT,RELATEDTO,NONE,ZEROPLUS
+CANCEL,VEVENT,RESOURCES,NONE,ZEROORONE
+CANCEL,VEVENT,RRULE,NONE,ZEROPLUS
+CANCEL,VEVENT,STATUS,NONE,ZEROORONE,must_be_canceled_no_attendee
+CANCEL,VEVENT,SUMMARY,NONE,ZEROORONE
+CANCEL,VEVENT,TRANSP,NONE,ZEROORONE
+CANCEL,VEVENT,URL,NONE,ZEROORONE
+CANCEL,VEVENT,X,NONE,ZEROPLUS
+CANCEL,VEVENT,REQUESTSTATUS,NONE,ZERO
+CANCEL,VEVENT,NONE,VTIMEZONE,ZEROPLUS,must_if_tz_ref
+CANCEL,VEVENT,NONE,X,ZEROPLUS
+CANCEL,VEVENT,NONE,VTODO,ZERO
+CANCEL,VEVENT,NONE,VJOURNAL,ZERO
+CANCEL,VEVENT,NONE,VFREEBUSY,ZERO
+CANCEL,VEVENT,NONE,VALARM,ZERO
+REFRESH,VEVENT,NONE,NONE,ONE
+REFRESH,VEVENT,ATTENDEE,NONE,ONE
+REFRESH,VEVENT,DTSTAMP,NONE,ONE
+REFRESH,VEVENT,ORGANIZER,NONE,ONE
+REFRESH,VEVENT,UID,NONE,ONE
+REFRESH,VEVENT,COMMENT,NONE,ZEROORONE
+REFRESH,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+REFRESH,VEVENT,X,NONE,ZEROPLUS
+REFRESH,VEVENT,ATTACH,NONE,ZERO
+REFRESH,VEVENT,CATEGORIES,NONE,ZERO
+REFRESH,VEVENT,CLASS,NONE,ZERO
+REFRESH,VEVENT,CONTACT,NONE,ZERO
+REFRESH,VEVENT,CREATED,NONE,ZERO
+REFRESH,VEVENT,DESCRIPTION,NONE,ZERO
+REFRESH,VEVENT,DTEND,NONE,ZERO
+REFRESH,VEVENT,DTSTART,NONE,ZERO
+REFRESH,VEVENT,DURATION,NONE,ZERO
+REFRESH,VEVENT,EXDATE,NONE,ZERO
+REFRESH,VEVENT,EXRULE,NONE,ZERO
+REFRESH,VEVENT,GEO,NONE,ZERO
+REFRESH,VEVENT,LASTMODIFIED,NONE,ZERO
+REFRESH,VEVENT,LOCATION,NONE,ZERO
+REFRESH,VEVENT,PRIORITY,NONE,ZERO
+REFRESH,VEVENT,RDATE,NONE,ZERO
+REFRESH,VEVENT,RELATEDTO,NONE,ZERO
+REFRESH,VEVENT,REQUESTSTATUS,NONE,ZERO
+REFRESH,VEVENT,RESOURCES,NONE,ZERO
+REFRESH,VEVENT,RRULE,NONE,ZERO
+REFRESH,VEVENT,SEQUENCE,NONE,ZERO
+REFRESH,VEVENT,STATUS,NONE,ZERO
+REFRESH,VEVENT,SUMMARY,NONE,ZERO
+REFRESH,VEVENT,TRANSP,NONE,ZERO
+REFRESH,VEVENT,URL,NONE,ZERO
+REFRESH,VEVENT,NONE,X,ZEROPLUS
+REFRESH,VEVENT,NONE,VTODO,ZERO
+REFRESH,VEVENT,NONE,VJOURNAL,ZERO
+REFRESH,VEVENT,NONE,VFREEBUSY,ZERO
+REFRESH,VEVENT,NONE,VTIMEZONE,ZERO,must_if_tz_ref
+REFRESH,VEVENT,NONE,VALARM,ZERO
+COUNTER,VEVENT,NONE,NONE,ONE
+COUNTER,VEVENT,DTSTAMP,NONE,ONE
+COUNTER,VEVENT,DTSTART,NONE,ONE
+COUNTER,VEVENT,ORGANIZER,NONE,ONE
+COUNTER,VEVENT,SEQUENCE,NONE,ONE
+COUNTER,VEVENT,SUMMARY,NONE,ONE
+COUNTER,VEVENT,UID,NONE,ONE
+COUNTER,VEVENT,ATTACH,NONE,ZEROPLUS
+COUNTER,VEVENT,ATTENDEE,NONE,ZEROPLUS
+COUNTER,VEVENT,CATEGORIES,NONE,ZEROPLUS #Non-standard
+COUNTER,VEVENT,CLASS,NONE,ZEROORONE
+COUNTER,VEVENT,COMMENT,NONE,ZEROORONE
+COUNTER,VEVENT,CONTACT,NONE,ZEROPLUS
+COUNTER,VEVENT,CREATED,NONE,ZEROORONE
+COUNTER,VEVENT,DESCRIPTION,NONE,ZEROORONE
+COUNTER,VEVENT,DTEND,NONE,ONEEXCLUSIVE,no_duration
+COUNTER,VEVENT,DURATION,NONE,ONEEXCLUSIVE,no_duration
+COUNTER,VEVENT,EXDATE,NONE,ZEROPLUS
+COUNTER,VEVENT,EXRULE,NONE,ZEROPLUS
+COUNTER,VEVENT,GEO,NONE,ZEROORONE
+COUNTER,VEVENT,LASTMODIFIED,NONE,ZEROORONE
+COUNTER,VEVENT,LOCATION,NONE,ZEROORONE
+COUNTER,VEVENT,PRIORITY,NONE,ZEROORONE
+COUNTER,VEVENT,RDATE,NONE,ZEROPLUS
+COUNTER,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+COUNTER,VEVENT,RELATEDTO,NONE,ZEROPLUS
+COUNTER,VEVENT,REQUESTSTATUS,NONE,ZEROPLUS
+COUNTER,VEVENT,RESOURCES,NONE,ZEROORONE
+COUNTER,VEVENT,RRULE,NONE,ZEROPLUS
+COUNTER,VEVENT,STATUS,NONE,ZEROORONE,may_be_tent_conf_cancel
+COUNTER,VEVENT,TRANSP,NONE,ZEROORONE
+COUNTER,VEVENT,URL,NONE,ZEROORONE
+COUNTER,VEVENT,X,NONE,ZEROPLUS
+COUNTER,VEVENT,NONE,VALARM,ZEROPLUS
+COUNTER,VEVENT,NONE,VTIMEZONE,ZEROPLUS,must_if_tz_ref
+COUNTER,VEVENT,NONE,X,ZEROPLUS
+COUNTER,VEVENT,NONE,VTODO,ZERO
+COUNTER,VEVENT,NONE,VJOURNAL,ZERO
+COUNTER,VEVENT,NONE,VFREEBUSY,ZERO
+DECLINECOUNTER,VEVENT,NONE,NONE,ONE
+DECLINECOUNTER,VEVENT,DTSTAMP,NONE,ONE
+DECLINECOUNTER,VEVENT,ORGANIZER,NONE,ONE
+DECLINECOUNTER,VEVENT,UID,NONE,ONE
+DECLINECOUNTER,VEVENT,COMMENT,NONE,ZEROORONE
+DECLINECOUNTER,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+DECLINECOUNTER,VEVENT,REQUESTSTATUS,NONE,ZEROPLUS
+DECLINECOUNTER,VEVENT,SEQUENCE,NONE,ZERO
+DECLINECOUNTER,VEVENT,X,NONE,ZEROPLUS
+DECLINECOUNTER,VEVENT,ATTACH,NONE,ZERO
+DECLINECOUNTER,VEVENT,ATTENDEE,NONE,ZERO
+DECLINECOUNTER,VEVENT,CATEGORIES,NONE,ZERO
+DECLINECOUNTER,VEVENT,CLASS,NONE,ZERO
+DECLINECOUNTER,VEVENT,CONTACT,NONE,ZERO
+DECLINECOUNTER,VEVENT,CREATED,NONE,ZERO
+DECLINECOUNTER,VEVENT,DESCRIPTION,NONE,ZERO
+DECLINECOUNTER,VEVENT,DTEND,NONE,ZERO
+DECLINECOUNTER,VEVENT,DTSTART,NONE,ZERO
+DECLINECOUNTER,VEVENT,DURATION,NONE,ZERO
+DECLINECOUNTER,VEVENT,EXDATE,NONE,ZERO
+DECLINECOUNTER,VEVENT,EXRULE,NONE,ZERO
+DECLINECOUNTER,VEVENT,GEO,NONE,ZERO
+DECLINECOUNTER,VEVENT,LASTMODIFIED,NONE,ZERO
+DECLINECOUNTER,VEVENT,LOCATION,NONE,ZERO
+DECLINECOUNTER,VEVENT,PRIORITY,NONE,ZERO
+DECLINECOUNTER,VEVENT,RDATE,NONE,ZERO
+DECLINECOUNTER,VEVENT,RELATEDTO,NONE,ZERO
+DECLINECOUNTER,VEVENT,RESOURCES,NONE,ZERO
+DECLINECOUNTER,VEVENT,RRULE,NONE,ZERO
+DECLINECOUNTER,VEVENT,STATUS,NONE,ZERO
+DECLINECOUNTER,VEVENT,SUMMARY,NONE,ZERO
+DECLINECOUNTER,VEVENT,TRANSP,NONE,ZERO
+DECLINECOUNTER,VEVENT,URL,NONE,ZERO
+DECLINECOUNTER,VEVENT,NONE,X,ZEROPLUS
+DECLINECOUNTER,VEVENT,NONE,VTODO,ZERO
+DECLINECOUNTER,VEVENT,NONE,VJOURNAL,ZERO
+DECLINECOUNTER,VEVENT,NONE,VFREEBUSY,ZERO
+DECLINECOUNTER,VEVENT,NONE,VTIMEZONE,ZERO,must_if_tz_ref
+DECLINECOUNTER,VEVENT,NONE,VALARM,ZERO
+PUBLISH,VFREEBUSY,NONE,NONE,ONEPLUS
+PUBLISH,VFREEBUSY,DTSTAMP,NONE,ONE
+PUBLISH,VFREEBUSY,DTSTART,NONE,ONE
+PUBLISH,VFREEBUSY,DTEND,NONE,ONE
+PUBLISH,VFREEBUSY,FREEBUSY,NONE,ONEPLUS
+PUBLISH,VFREEBUSY,ORGANIZER,NONE,ONE
+PUBLISH,VFREEBUSY,COMMENT,NONE,ZEROORONE
+PUBLISH,VFREEBUSY,CONTACT,NONE,ZEROPLUS
+PUBLISH,VFREEBUSY,X,NONE,ZEROPLUS
+PUBLISH,VFREEBUSY,URL,NONE,ZEROORONE
+PUBLISH,VFREEBUSY,ATTENDEE,NONE,ZERO
+PUBLISH,VFREEBUSY,DURATION,NONE,ZERO
+PUBLISH,VFREEBUSY,REQUESTSTATUS,NONE,ZERO
+PUBLISH,VFREEBUSY,UID,NONE,ZERO
+PUBLISH,VFREEBUSY,NONE,X,ZEROPLUS
+PUBLISH,VFREEBUSY,NONE,VEVENT,ZERO
+PUBLISH,VFREEBUSY,NONE,VTODO,ZERO
+PUBLISH,VFREEBUSY,NONE,VJOURNAL,ZERO
+PUBLISH,VFREEBUSY,NONE,VTIMEZONE,ZERO,must_if_tz_ref
+PUBLISH,VFREEBUSY,NONE,VALARM,ZERO
+REQUEST,VFREEBUSY,NONE,NONE,ONE
+REQUEST,VFREEBUSY,ATTENDEE,NONE,ONEPLUS
+REQUEST,VFREEBUSY,DTEND,NONE,ONE
+REQUEST,VFREEBUSY,DTSTAMP,NONE,ONE
+REQUEST,VFREEBUSY,DTSTART,NONE,ONE
+REQUEST,VFREEBUSY,ORGANIZER,NONE,ONE
+REQUEST,VFREEBUSY,UID,NONE,ONE
+REQUEST,VFREEBUSY,COMMENT,NONE,ZEROORONE
+REQUEST,VFREEBUSY,CONTACT,NONE,ZEROPLUS
+REQUEST,VFREEBUSY,X,NONE,ZEROPLUS
+REQUEST,VFREEBUSY,FREEBUSY,NONE,ZERO
+REQUEST,VFREEBUSY,DURATION,NONE,ZERO
+REQUEST,VFREEBUSY,REQUESTSTATUS,NONE,ZERO
+REQUEST,VFREEBUSY,URL,NONE,ZERO
+REQUEST,VFREEBUSY,NONE,X,ZEROPLUS
+REQUEST,VFREEBUSY,NONE,VALARM,ZERO
+REQUEST,VFREEBUSY,NONE,VEVENT,ZERO
+REQUEST,VFREEBUSY,NONE,VTODO,ZERO
+REQUEST,VFREEBUSY,NONE,VJOURNAL,ZERO
+REQUEST,VFREEBUSY,NONE,VTIMEZONE,ZERO
+REPLY,VFREEBUSY,NONE,NONE,ONE
+REPLY,VFREEBUSY,ATTENDEE,NONE,ONE
+REPLY,VFREEBUSY,DTSTAMP,NONE,ONE
+REPLY,VFREEBUSY,DTEND,NONE,ONE
+REPLY,VFREEBUSY,DTSTART,NONE,ONE
+REPLY,VFREEBUSY,FREEBUSY,NONE,ONEPLUS
+REPLY,VFREEBUSY,ORGANIZER,NONE,ONE
+REPLY,VFREEBUSY,UID,NONE,ONE
+REPLY,VFREEBUSY,COMMENT,NONE,ZEROORONE
+REPLY,VFREEBUSY,CONTACT,NONE,ZEROPLUS
+REPLY,VFREEBUSY,REQUESTSTATUS,NONE,ZEROPLUS
+REPLY,VFREEBUSY,URL,NONE,ZEROORONE
+REPLY,VFREEBUSY,X,NONE,ZEROPLUS
+REPLY,VFREEBUSY,DURATION,NONE,ZERO
+REPLY,VFREEBUSY,SEQUENCE,NONE,ZERO
+REPLY,VFREEBUSY,NONE,X,ZEROPLUS
+REPLY,VFREEBUSY,NONE,VALARM,ZERO
+REPLY,VFREEBUSY,NONE,VEVENT,ZERO
+REPLY,VFREEBUSY,NONE,VTODO,ZERO
+REPLY,VFREEBUSY,NONE,VJOURNAL,ZERO
+REPLY,VFREEBUSY,NONE,VTIMEZONE,ZERO
+PUBLISH,VTODO,NONE,NONE,ONEPLUS
+PUBLISH,VTODO,DTSTAMP,NONE,ONE
+PUBLISH,VTODO,DTSTART,NONE,ONE
+PUBLISH,VTODO,ORGANIZER,NONE,ONE
+PUBLISH,VTODO,PRIORITY,NONE,ONE
+PUBLISH,VTODO,SEQUENCE,NONE,ZEROORONE
+PUBLISH,VTODO,SUMMARY,NONE,ONE
+PUBLISH,VTODO,UID,NONE,ONE
+PUBLISH,VTODO,ATTACH,NONE,ZEROPLUS
+PUBLISH,VTODO,CATEGORIES,NONE,ZEROPLUS #Non-Standard
+PUBLISH,VTODO,CLASS,NONE,ZEROORONE
+PUBLISH,VTODO,COMMENT,NONE,ZEROORONE
+PUBLISH,VTODO,CONTACT,NONE,ZEROPLUS
+PUBLISH,VTODO,CREATED,NONE,ZEROORONE
+PUBLISH,VTODO,DESCRIPTION,NONE,ZEROORONE
+PUBLISH,VTODO,DUE,NONE,ZEROORONE
+PUBLISH,VTODO,DURATION,NONE,ZEROORONE
+PUBLISH,VTODO,EXDATE,NONE,ZEROPLUS
+PUBLISH,VTODO,EXRULE,NONE,ZEROPLUS
+PUBLISH,VTODO,GEO,NONE,ZEROORONE
+PUBLISH,VTODO,LASTMODIFIED,NONE,ZEROORONE
+PUBLISH,VTODO,LOCATION,NONE,ZEROORONE
+PUBLISH,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+PUBLISH,VTODO,RDATE,NONE,ZEROPLUS
+PUBLISH,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+PUBLISH,VTODO,RELATEDTO,NONE,ZEROPLUS
+PUBLISH,VTODO,RESOURCES,NONE,ZEROORONE
+PUBLISH,VTODO,RRULE,NONE,ZEROPLUS
+PUBLISH,VTODO,STATUS,NONE,ZEROORONE
+PUBLISH,VTODO,URL,NONE,ZEROORONE
+PUBLISH,VTODO,X,NONE,ZEROPLUS
+PUBLISH,VTODO,ATTENDEE,NONE,ZERO
+PUBLISH,VTODO,REQUESTSTATUS,NONE,ZERO
+PUBLISH,VTODO,NONE,VTIMEZONE,ZEROPLUS
+PUBLISH,VTODO,NONE,VALARM,ZEROPLUS
+PUBLISH,VTODO,NONE,X,ZEROPLUS
+PUBLISH,VTODO,NONE,VFREEBUSY,ZERO
+PUBLISH,VTODO,NONE,VEVENT,ZERO
+PUBLISH,VTODO,NONE,VJOURNAL,ZERO
+REQUEST,VTODO,NONE,NONE,ONEPLUS
+REQUEST,VTODO,ATTENDEE,NONE,ONEPLUS
+REQUEST,VTODO,DTSTAMP,NONE,ONE
+REQUEST,VTODO,DTSTART,NONE,ONE
+REQUEST,VTODO,ORGANIZER,NONE,ONE
+REQUEST,VTODO,PRIORITY,NONE,ONE
+REQUEST,VTODO,SEQUENCE,NONE,ZEROORONE
+REQUEST,VTODO,SUMMARY,NONE,ONE
+REQUEST,VTODO,UID,NONE,ONE
+REQUEST,VTODO,ATTACH,NONE,ZEROPLUS
+REQUEST,VTODO,CATEGORIES,NONE,ZEROPLUS #Non-Standard
+REQUEST,VTODO,CLASS,NONE,ZEROORONE
+REQUEST,VTODO,COMMENT,NONE,ZEROORONE
+REQUEST,VTODO,CONTACT,NONE,ZEROPLUS
+REQUEST,VTODO,CREATED,NONE,ZEROORONE
+REQUEST,VTODO,DESCRIPTION,NONE,ZEROORONE
+REQUEST,VTODO,DUE,NONE,ZEROORONE
+REQUEST,VTODO,DURATION,NONE,ZEROORONE
+REQUEST,VTODO,EXDATE,NONE,ZEROPLUS
+REQUEST,VTODO,EXRULE,NONE,ZEROPLUS
+REQUEST,VTODO,GEO,NONE,ZEROORONE
+REQUEST,VTODO,LASTMODIFIED,NONE,ZEROORONE
+REQUEST,VTODO,LOCATION,NONE,ZEROORONE
+REQUEST,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+REQUEST,VTODO,RDATE,NONE,ZEROPLUS
+REQUEST,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+REQUEST,VTODO,RELATEDTO,NONE,ZEROPLUS
+REQUEST,VTODO,RESOURCES,NONE,ZEROORONE
+REQUEST,VTODO,RRULE,NONE,ZEROPLUS
+REQUEST,VTODO,STATUS,NONE,ZEROORONE,may_be_comp_need_process
+REQUEST,VTODO,URL,NONE,ZEROORONE
+REQUEST,VTODO,X,NONE,ZEROPLUS
+REQUEST,VTODO,REQUESTSTATUS,NONE,ZERO
+REQUEST,VTODO,NONE,VALARM,ZEROPLUS
+REQUEST,VTODO,NONE,VTIMEZONE,ZEROPLUS
+REQUEST,VTODO,NONE,X,ZEROPLUS
+REQUEST,VTODO,NONE,VEVENT,ZERO
+REQUEST,VTODO,NONE,VFREEBUSY,ZERO
+REQUEST,VTODO,NONE,VJOURNAL,ZERO
+REPLY,VTODO,NONE,NONE,ONEPLUS
+REPLY,VTODO,ATTENDEE,NONE,ONEPLUS
+REPLY,VTODO,DTSTAMP,NONE,ONE
+REPLY,VTODO,ORGANIZER,NONE,ONE
+REPLY,VTODO,REQUESTSTATUS,NONE,ONEPLUS
+REPLY,VTODO,UID,NONE,ONE
+REPLY,VTODO,ATTACH,NONE,ZEROPLUS
+REPLY,VTODO,CATEGORIES,NONE,ZEROPLUS #Non-Standard
+REPLY,VTODO,CLASS,NONE,ZEROORONE
+REPLY,VTODO,COMMENT,NONE,ZEROORONE
+REPLY,VTODO,CONTACT,NONE,ZEROPLUS
+REPLY,VTODO,CREATED,NONE,ZEROORONE
+REPLY,VTODO,DESCRIPTION,NONE,ZEROORONE
+REPLY,VTODO,DTSTART,NONE,ZEROORONE
+REPLY,VTODO,DUE,NONE,ZEROORONE
+REPLY,VTODO,DURATION,NONE,ZEROORONE
+REPLY,VTODO,EXDATE,NONE,ZEROPLUS
+REPLY,VTODO,EXRULE,NONE,ZEROPLUS
+REPLY,VTODO,GEO,NONE,ZEROORONE
+REPLY,VTODO,LASTMODIFIED,NONE,ZEROORONE
+REPLY,VTODO,LOCATION,NONE,ZEROORONE
+REPLY,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+REPLY,VTODO,PRIORITY,NONE,ZEROORONE
+REPLY,VTODO,RDATE,NONE,ZEROPLUS
+REPLY,VTODO,RELATEDTO,NONE,ZEROPLUS
+REPLY,VTODO,RESOURCES,NONE,ZEROORONE
+REPLY,VTODO,RRULE,NONE,ZEROPLUS
+REPLY,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+REPLY,VTODO,SEQUENCE,NONE,ZEROORONE
+REPLY,VTODO,STATUS,NONE,ZEROORONE
+REPLY,VTODO,SUMMARY,NONE,ZEROORONE
+REPLY,VTODO,URL,NONE,ZEROORONE
+REPLY,VTODO,X,NONE,ZEROPLUS
+REPLY,VTODO,NONE,VTIMEZONE,ZEROORONE
+REPLY,VTODO,NONE,X,ZEROPLUS
+REPLY,VTODO,NONE,VALARM,ZERO
+REPLY,VTODO,NONE,VEVENT,ZERO
+REPLY,VTODO,NONE,VFREEBUSY,ZERO
+ADD,VTODO,NONE,NONE,ONE
+ADD,VTODO,DTSTAMP,NONE,ONE
+ADD,VTODO,ORGANIZER,NONE,ONE
+ADD,VTODO,PRIORITY,NONE,ONE
+ADD,VTODO,SEQUENCE,NONE,ONE
+ADD,VTODO,SUMMARY,NONE,ONE
+ADD,VTODO,UID,NONE,ONE
+ADD,VTODO,ATTACH,NONE,ZEROPLUS
+ADD,VTODO,ATTENDEE,NONE,ZEROPLUS
+ADD,VTODO,CATEGORIES,NONE,ZEROPLUS
+ADD,VTODO,CLASS,NONE,ZEROORONE
+ADD,VTODO,COMMENT,NONE,ZEROORONE
+ADD,VTODO,CONTACT,NONE,ZEROPLUS
+ADD,VTODO,CREATED,NONE,ZEROORONE
+ADD,VTODO,DESCRIPTION,NONE,ZEROORONE
+ADD,VTODO,DTSTART,NONE,ZEROORONE
+ADD,VTODO,DUE,NONE,ZEROORONE
+ADD,VTODO,DURATION,NONE,ZEROORONE
+ADD,VTODO,EXDATE,NONE,ZEROPLUS
+ADD,VTODO,EXRULE,NONE,ZEROPLUS
+ADD,VTODO,GEO,NONE,ZEROORONE
+ADD,VTODO,LASTMODIFIED,NONE,ZEROORONE
+ADD,VTODO,LOCATION,NONE,ZEROORONE
+ADD,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+ADD,VTODO,RDATE,NONE,ZEROPLUS
+ADD,VTODO,RELATEDTO,NONE,ZEROPLUS
+ADD,VTODO,RESOURCES,NONE,ZEROORONE
+ADD,VTODO,RRULE,NONE,ZEROPLUS
+ADD,VTODO,STATUS,NONE,ZEROORONE,may_be_comp_need_process
+ADD,VTODO,URL,NONE,ZEROORONE
+ADD,VTODO,X,NONE,ZEROPLUS
+ADD,VTODO,RECURRENCEID,NONE,ZERO,must_be_recurring
+ADD,VTODO,REQUESTSTATUS,NONE,ZERO
+ADD,VTODO,NONE,VALARM,ZEROPLUS
+ADD,VTODO,NONE,VTIMEZONE,ZEROPLUS
+ADD,VTODO,NONE,X,ZEROPLUS
+ADD,VTODO,NONE,VEVENT,ZERO
+ADD,VTODO,NONE,VJOURNAL,ZERO
+ADD,VTODO,NONE,VFREEBUSY,ZERO
+CANCEL,VTODO,NONE,NONE,ONE
+CANCEL,VTODO,ATTENDEE,NONE,ZEROPLUS
+CANCEL,VTODO,UID,NONE,ONE
+CANCEL,VTODO,DTSTAMP,NONE,ONE
+CANCEL,VTODO,ORGANIZER,NONE,ONE
+CANCEL,VTODO,SEQUENCE,NONE,ONE
+CANCEL,VTODO,ATTACH,NONE,ZEROPLUS
+CANCEL,VTODO,CATEGORIES,NONE,ZEROPLUS #Non-Standard
+CANCEL,VTODO,CLASS,NONE,ZEROORONE
+CANCEL,VTODO,COMMENT,NONE,ZEROORONE
+CANCEL,VTODO,CONTACT,NONE,ZEROPLUS
+CANCEL,VTODO,CREATED,NONE,ZEROORONE
+CANCEL,VTODO,DESCRIPTION,NONE,ZEROORONE
+CANCEL,VTODO,DTSTART,NONE,ZEROORONE
+CANCEL,VTODO,DUE,NONE,ZEROORONE
+CANCEL,VTODO,DURATION,NONE,ZEROORONE
+CANCEL,VTODO,EXDATE,NONE,ZEROPLUS
+CANCEL,VTODO,EXRULE,NONE,ZEROPLUS
+CANCEL,VTODO,GEO,NONE,ZEROORONE
+CANCEL,VTODO,LASTMODIFIED,NONE,ZEROORONE
+CANCEL,VTODO,LOCATION,NONE,ZEROORONE
+CANCEL,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+CANCEL,VTODO,RDATE,NONE,ZEROPLUS
+CANCEL,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+CANCEL,VTODO,RELATEDTO,NONE,ZEROPLUS
+CANCEL,VTODO,RESOURCES,NONE,ZEROORONE
+CANCEL,VTODO,RRULE,NONE,ZEROPLUS
+CANCEL,VTODO,PRIORITY,NONE,ZEROORONE
+CANCEL,VTODO,STATUS,NONE,ZEROORONE,must_be_canceled_no_attendee
+CANCEL,VTODO,URL,NONE,ZEROORONE
+CANCEL,VTODO,X,NONE,ZEROPLUS
+CANCEL,VTODO,REQUESTSTATUS,NONE,ZERO
+CANCEL,VTODO,NONE,VTIMEZONE,ZEROORONE
+CANCEL,VTODO,NONE,X,ZEROPLUS
+CANCEL,VTODO,NONE,VALARM,ZERO
+CANCEL,VTODO,NONE,VEVENT,ZERO
+CANCEL,VTODO,NONE,VFREEBUSY,ZERO
+REFRESH,VTODO,NONE,NONE,ONE
+REFRESH,VTODO,ATTENDEE,NONE,ONE
+REFRESH,VTODO,DTSTAMP,NONE,ONE
+REFRESH,VTODO,UID,NONE,ONE
+REFRESH,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+REFRESH,VTODO,X,NONE,ZEROPLUS
+REFRESH,VTODO,ATTACH,NONE,ZERO
+REFRESH,VTODO,CATEGORIES,NONE,ZERO
+REFRESH,VTODO,CLASS,NONE,ZERO
+REFRESH,VTODO,COMMENT,NONE,ZERO
+REFRESH,VTODO,CONTACT,NONE,ZERO
+REFRESH,VTODO,CREATED,NONE,ZERO
+REFRESH,VTODO,DESCRIPTION,NONE,ZERO
+REFRESH,VTODO,DTSTART,NONE,ZERO
+REFRESH,VTODO,DUE,NONE,ZERO
+REFRESH,VTODO,DURATION,NONE,ZERO
+REFRESH,VTODO,EXDATE,NONE,ZERO
+REFRESH,VTODO,EXRULE,NONE,ZERO
+REFRESH,VTODO,GEO,NONE,ZERO
+REFRESH,VTODO,LASTMODIFIED,NONE,ZERO
+REFRESH,VTODO,LOCATION,NONE,ZERO
+REFRESH,VTODO,ORGANIZER,NONE,ZERO
+REFRESH,VTODO,PERCENTCOMPLETE,NONE,ZERO
+REFRESH,VTODO,PRIORITY,NONE,ZERO
+REFRESH,VTODO,RDATE,NONE,ZERO
+REFRESH,VTODO,RELATEDTO,NONE,ZERO
+REFRESH,VTODO,REQUESTSTATUS,NONE,ZERO
+REFRESH,VTODO,RESOURCES,NONE,ZERO
+REFRESH,VTODO,RRULE,NONE,ZERO
+REFRESH,VTODO,SEQUENCE,NONE,ZERO
+REFRESH,VTODO,STATUS,NONE,ZERO
+REFRESH,VTODO,URL,NONE,ZERO
+REFRESH,VTODO,NONE,X,ZEROPLUS
+REFRESH,VTODO,NONE,VALARM,ZERO
+REFRESH,VTODO,NONE,VEVENT,ZERO
+REFRESH,VTODO,NONE,VFREEBUSY,ZERO
+REFRESH,VTODO,NONE,VTIMEZONE,ZERO
+COUNTER,VTODO,NONE,NONE,ONE
+COUNTER,VTODO,ATTENDEE,NONE,ONEPLUS
+COUNTER,VTODO,DTSTAMP,NONE,ONE
+COUNTER,VTODO,ORGANIZER,NONE,ONE
+COUNTER,VTODO,PRIORITY,NONE,ONE
+COUNTER,VTODO,SUMMARY,NONE,ONE
+COUNTER,VTODO,UID,NONE,ONE
+COUNTER,VTODO,ATTACH,NONE,ZEROPLUS
+COUNTER,VTODO,CATEGORIES,NONE,ZEROPLUS #Non-standard
+COUNTER,VTODO,CLASS,NONE,ZEROORONE
+COUNTER,VTODO,COMMENT,NONE,ZEROORONE
+COUNTER,VTODO,CONTACT,NONE,ZEROPLUS
+COUNTER,VTODO,CREATED,NONE,ZEROORONE
+COUNTER,VTODO,DESCRIPTION,NONE,ZEROORONE
+COUNTER,VTODO,DTSTART,NONE,ZEROORONE
+COUNTER,VTODO,DUE,NONE,ZEROORONE
+COUNTER,VTODO,DURATION,NONE,ZEROORONE
+COUNTER,VTODO,EXDATE,NONE,ZEROPLUS
+COUNTER,VTODO,EXRULE,NONE,ZEROPLUS
+COUNTER,VTODO,GEO,NONE,ZEROORONE
+COUNTER,VTODO,LASTMODIFIED,NONE,ZEROORONE
+COUNTER,VTODO,LOCATION,NONE,ZEROORONE
+COUNTER,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+COUNTER,VTODO,RDATE,NONE,ZEROPLUS
+COUNTER,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+COUNTER,VTODO,RELATEDTO,NONE,ZEROPLUS
+COUNTER,VTODO,REQUESTSTATUS,NONE,ZEROPLUS
+COUNTER,VTODO,RESOURCES,NONE,ZEROORONE
+COUNTER,VTODO,RRULE,NONE,ZEROORONE
+COUNTER,VTODO,SEQUENCE,NONE,ZEROORONE
+COUNTER,VTODO,STATUS,NONE,ZEROORONE,may_be_comp_need_process
+COUNTER,VTODO,URL,NONE,ZEROORONE
+COUNTER,VTODO,X,NONE,ZEROPLUS
+COUNTER,VTODO,NONE,VALARM,ZEROPLUS
+COUNTER,VTODO,NONE,VTIMEZONE,ZEROORONE
+COUNTER,VTODO,NONE,X,ZEROPLUS
+COUNTER,VTODO,NONE,VEVENT,ZERO
+COUNTER,VTODO,NONE,VFREEBUSY,ZERO
+DECLINECOUNTER,VTODO,NONE,NONE,ONE
+DECLINECOUNTER,VTODO,ATTENDEE,NONE,ONEPLUS
+DECLINECOUNTER,VTODO,DTSTAMP,NONE,ONE
+DECLINECOUNTER,VTODO,ORGANIZER,NONE,ONE
+DECLINECOUNTER,VTODO,SEQUENCE,NONE,ONE
+DECLINECOUNTER,VTODO,UID,NONE,ONE
+DECLINECOUNTER,VTODO,ATTACH,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,CATEGORIES,NONE,ZEROPLUS #Non-standard
+DECLINECOUNTER,VTODO,CLASS,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,COMMENT,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,CONTACT,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,CREATED,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,DESCRIPTION,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,DTSTART,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,DUE,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,DURATION,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,EXDATE,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,EXRULE,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,GEO,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,LASTMODIFIED,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,LOCATION,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,PRIORITY,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,RDATE,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+DECLINECOUNTER,VTODO,RELATEDTO,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,REQUESTSTATUS,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,RESOURCES,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,RRULE,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,STATUS,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,URL,NONE,ZEROORONE
+DECLINECOUNTER,VTODO,X,NONE,ZEROPLUS
+DECLINECOUNTER,VTODO,NONE,VTIMEZONE,ZEROPLUS
+DECLINECOUNTER,VTODO,NONE,X,ZEROPLUS
+DECLINECOUNTER,VTODO,NONE,VALARM,ZERO
+DECLINECOUNTER,VTODO,NONE,VEVENT,ZERO
+DECLINECOUNTER,VTODO,NONE,VFREEBUSY,ZERO
+PUBLISH,VJOURNAL,NONE,NONE,ONEPLUS
+PUBLISH,VJOURNAL,DESCRIPTION,NONE,ONE
+PUBLISH,VJOURNAL,DTSTAMP,NONE,ONE
+PUBLISH,VJOURNAL,DTSTART,NONE,ONE
+PUBLISH,VJOURNAL,ORGANIZER,NONE,ONE
+PUBLISH,VJOURNAL,UID,NONE,ONE
+PUBLISH,VJOURNAL,ATTACH,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,CATEGORIES,NONE,ZEROPLUS #Non-standard
+PUBLISH,VJOURNAL,CLASS,NONE,ZEROORONE
+PUBLISH,VJOURNAL,COMMENT,NONE,ZEROORONE
+PUBLISH,VJOURNAL,CONTACT,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,CREATED,NONE,ZEROORONE
+PUBLISH,VJOURNAL,EXDATE,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,EXRULE,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,LASTMODIFIED,NONE,ZEROORONE
+PUBLISH,VJOURNAL,RDATE,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+PUBLISH,VJOURNAL,RELATEDTO,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,RRULE,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,SEQUENCE,NONE,ZEROORONE
+PUBLISH,VJOURNAL,STATUS,NONE,ZEROORONE,may_be_draft_final_canceled
+PUBLISH,VJOURNAL,SUMMARY,NONE,ZEROORONE
+PUBLISH,VJOURNAL,URL,NONE,ZEROORONE
+PUBLISH,VJOURNAL,X,NONE,ZEROPLUS
+PUBLISH,VJOURNAL,ATTENDEE,NONE,ZERO
+PUBLISH,VJOURNAL,NONE,VALARM,ZEROPLUS
+PUBLISH,VJOURNAL,NONE,VTIMEZONE,ZEROPLUS
+PUBLISH,VJOURNAL,NONE,X,ZEROPLUS
+PUBLISH,VJOURNAL,NONE,VEVENT,ZERO
+PUBLISH,VJOURNAL,NONE,VFREEBUSY,ZERO
+PUBLISH,VJOURNAL,NONE,VTODO,ZERO
+ADD,VJOURNAL,NONE,NONE,ONE
+ADD,VJOURNAL,DESCRIPTION,NONE,ONE
+ADD,VJOURNAL,DTSTAMP,NONE,ONE
+ADD,VJOURNAL,DTSTART,NONE,ONE
+ADD,VJOURNAL,ORGANIZER,NONE,ONE
+ADD,VJOURNAL,SEQUENCE,NONE,ONE
+ADD,VJOURNAL,UID,NONE,ONE
+ADD,VJOURNAL,ATTACH,NONE,ZEROPLUS
+ADD,VJOURNAL,CATEGORIES,NONE,ZEROPLUS #Non-standard
+ADD,VJOURNAL,CLASS,NONE,ZEROORONE
+ADD,VJOURNAL,COMMENT,NONE,ZEROORONE
+ADD,VJOURNAL,CONTACT,NONE,ZEROPLUS
+ADD,VJOURNAL,CREATED,NONE,ZEROORONE
+ADD,VJOURNAL,EXDATE,NONE,ZEROPLUS
+ADD,VJOURNAL,EXRULE,NONE,ZEROPLUS
+ADD,VJOURNAL,LASTMODIFIED,NONE,ZEROORONE
+ADD,VJOURNAL,RDATE,NONE,ZEROPLUS
+ADD,VJOURNAL,RELATEDTO,NONE,ZEROPLUS
+ADD,VJOURNAL,RRULE,NONE,ZEROPLUS
+ADD,VJOURNAL,STATUS,NONE,ZEROORONE
+ADD,VJOURNAL,SUMMARY,NONE,ZEROORONE
+ADD,VJOURNAL,URL,NONE,ZEROORONE
+ADD,VJOURNAL,X,NONE,ZEROPLUS
+ADD,VJOURNAL,ATTENDEE,NONE,ZERO
+ADD,VJOURNAL,RECURRENCEID,NONE,ZERO
+ADD,VJOURNAL,NONE,VALARM,ZEROPLUS
+ADD,VJOURNAL,NONE,VTIMEZONE,ZEROORONE
+ADD,VJOURNAL,NONE,X,ZEROPLUS
+ADD,VJOURNAL,NONE,VEVENT,ZERO
+ADD,VJOURNAL,NONE,VFREEBUSY,ZERO
+ADD,VJOURNAL,NONE,VTODO,ZERO
+CANCEL,VJOURNAL,NONE,NONE,ONEPLUS
+CANCEL,VJOURNAL,DTSTAMP,NONE,ONE
+CANCEL,VJOURNAL,ORGANIZER,NONE,ONE
+CANCEL,VJOURNAL,SEQUENCE,NONE,ONE
+CANCEL,VJOURNAL,UID,NONE,ONE
+CANCEL,VJOURNAL,ATTACH,NONE,ZEROPLUS
+CANCEL,VJOURNAL,ATTENDEE,NONE,ZEROPLUS
+CANCEL,VJOURNAL,CATEGORIES,NONE,ZEROPLUS #Non-standard
+CANCEL,VJOURNAL,CLASS,NONE,ZEROORONE
+CANCEL,VJOURNAL,COMMENT,NONE,ZEROORONE
+CANCEL,VJOURNAL,CONTACT,NONE,ZEROPLUS
+CANCEL,VJOURNAL,CREATED,NONE,ZEROORONE
+CANCEL,VJOURNAL,DESCRIPTION,NONE,ZEROORONE
+CANCEL,VJOURNAL,DTSTART,NONE,ZEROORONE
+CANCEL,VJOURNAL,EXDATE,NONE,ZEROPLUS
+CANCEL,VJOURNAL,EXRULE,NONE,ZEROPLUS
+CANCEL,VJOURNAL,LASTMODIFIED,NONE,ZEROORONE
+CANCEL,VJOURNAL,RDATE,NONE,ZEROPLUS
+CANCEL,VJOURNAL,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+CANCEL,VJOURNAL,RELATEDTO,NONE,ZEROPLUS
+CANCEL,VJOURNAL,RRULE,NONE,ZEROPLUS
+CANCEL,VJOURNAL,STATUS,NONE,ZEROORONE,must_be_cancel_if_present
+CANCEL,VJOURNAL,SUMMARY,NONE,ZEROORONE
+CANCEL,VJOURNAL,URL,NONE,ZEROORONE
+CANCEL,VJOURNAL,X,NONE,ZEROPLUS
+CANCEL,VJOURNAL,REQUESTSTATUS,NONE,ZERO
+CANCEL,VJOURNAL,NONE,VTIMEZONE,ZEROPLUS
+CANCEL,VJOURNAL,NONE,X,ZEROPLUS
+CANCEL,VJOURNAL,NONE,VALARM,ZERO
+CANCEL,VJOURNAL,NONE,VEVENT,ZERO
+CANCEL,VJOURNAL,NONE,VFREEBUSY,ZERO
+CANCEL,VJOURNAL,NONE,VTODO,ZERO
+NONE,VCALENDAR,ACTION,NONE,ZERO
+NONE,VCALENDAR,ATTACH,NONE,ZERO
+NONE,VCALENDAR,ATTENDEE,NONE,ZERO
+NONE,VCALENDAR,CALSCALE,NONE,ZEROORONE
+NONE,VCALENDAR,CATEGORIES,NONE,ZERO
+NONE,VCALENDAR,CLASS,NONE,ZERO
+NONE,VCALENDAR,COMMENT,NONE,ZERO
+NONE,VCALENDAR,COMPLETED,NONE,ZERO
+NONE,VCALENDAR,CONTACT,NONE,ZERO
+NONE,VCALENDAR,CREATED,NONE,ZERO
+NONE,VCALENDAR,DESCRIPTION,NONE,ZERO
+NONE,VCALENDAR,DTEND,NONE,ZERO
+NONE,VCALENDAR,DTSTAMP,NONE,ZERO
+NONE,VCALENDAR,DTSTART,NONE,ZERO
+NONE,VCALENDAR,DUE,NONE,ZERO
+NONE,VCALENDAR,DURATION,NONE,ZERO
+NONE,VCALENDAR,EXDATE,NONE,ZERO
+NONE,VCALENDAR,EXRULE,NONE,ZERO
+NONE,VCALENDAR,FREEBUSY,NONE,ZERO
+NONE,VCALENDAR,GEO,NONE,ZERO
+NONE,VCALENDAR,LASTMODIFIED,NONE,ZERO
+NONE,VCALENDAR,LOCATION,NONE,ZERO
+NONE,VCALENDAR,METHOD,NONE,ZEROORONE
+NONE,VCALENDAR,ORGANIZER,NONE,ZERO
+NONE,VCALENDAR,PERCENTCOMPLETE,NONE,ZERO
+NONE,VCALENDAR,PRIORITY,NONE,ZERO
+NONE,VCALENDAR,PRODID,NONE,ONE
+NONE,VCALENDAR,RDATE,NONE,ZERO
+NONE,VCALENDAR,RECURRENCEID,NONE,ZERO
+NONE,VCALENDAR,RELATEDTO,NONE,ZERO
+NONE,VCALENDAR,REPEAT,NONE,ZERO
+NONE,VCALENDAR,REQUESTSTATUS,NONE,ZERO
+NONE,VCALENDAR,RESOURCES,NONE,ZERO
+NONE,VCALENDAR,RRULE,NONE,ZERO
+NONE,VCALENDAR,SEQUENCE,NONE,ZERO
+NONE,VCALENDAR,STATUS,NONE,ZERO
+NONE,VCALENDAR,SUMMARY,NONE,ZERO
+NONE,VCALENDAR,TRANSP,NONE,ZERO
+NONE,VCALENDAR,TRIGGER,NONE,ZERO
+NONE,VCALENDAR,TZID,NONE,ZERO
+NONE,VCALENDAR,TZNAME,NONE,ZERO
+NONE,VCALENDAR,TZOFFSETFROM,NONE,ZERO
+NONE,VCALENDAR,TZOFFSETTO,NONE,ZERO
+NONE,VCALENDAR,TZURL,NONE,ZERO
+NONE,VCALENDAR,UID,NONE,ZERO
+NONE,VCALENDAR,URL,NONE,ZERO
+NONE,VCALENDAR,VERSION,NONE,ONE
+NONE,VCALENDAR,X,NONE,ZEROPLUS
+NONE,VEVENT,ACTION,NONE,ZERO
+NONE,VEVENT,ATTACH,NONE,ZEROPLUS
+NONE,VEVENT,ATTENDEE,NONE,ZEROPLUS
+NONE,VEVENT,CALSCALE,NONE,ZERO
+NONE,VEVENT,CATEGORIES,NONE,ZEROPLUS
+NONE,VEVENT,CLASS,NONE,ZEROORONE
+NONE,VEVENT,COMMENT,NONE,ZEROPLUS
+NONE,VEVENT,COMPLETED,NONE,ZERO
+NONE,VEVENT,CONTACT,NONE,ZEROPLUS
+NONE,VEVENT,CREATED,NONE,ZEROORONE
+NONE,VEVENT,DESCRIPTION,NONE,ZEROORONE
+NONE,VEVENT,DTEND,NONE,ONEEXCLUSIVE,no_duration
+NONE,VEVENT,DTSTAMP,NONE,ZEROORONE
+NONE,VEVENT,DTSTART,NONE,ZEROORONE
+NONE,VEVENT,DUE,NONE,ZERO
+NONE,VEVENT,DURATION,NONE,ONEEXCLUSIVE,no_duration
+NONE,VEVENT,EXDATE,NONE,ZEROPLUS
+NONE,VEVENT,EXRULE,NONE,ZEROPLUS
+NONE,VEVENT,FREEBUSY,NONE,ZERO
+NONE,VEVENT,GEO,NONE,ZEROORONE
+NONE,VEVENT,LASTMODIFIED,NONE,ZEROORONE
+NONE,VEVENT,LOCATION,NONE,ZEROORONE
+NONE,VEVENT,METHOD,NONE,ZERO
+NONE,VEVENT,ORGANIZER,NONE,ZEROORONE
+NONE,VEVENT,PERCENTCOMPLETE,NONE,ZERO
+NONE,VEVENT,PRIORITY,NONE,ZEROORONE
+NONE,VEVENT,PRODID,NONE,ZERO
+NONE,VEVENT,RDATE,NONE,ZEROPLUS
+NONE,VEVENT,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+NONE,VEVENT,RELATEDTO,NONE,ZEROPLUS
+NONE,VEVENT,REPEAT,NONE,ZERO
+NONE,VEVENT,REQUESTSTATUS,NONE,ZEROPLUS
+NONE,VEVENT,RESOURCES,NONE,ZEROPLUS
+NONE,VEVENT,RRULE,NONE,ZEROPLUS
+NONE,VEVENT,SEQUENCE,NONE,ZEROORONE
+NONE,VEVENT,STATUS,NONE,ZEROORONE
+NONE,VEVENT,SUMMARY,NONE,ZEROORONE
+NONE,VEVENT,TRANSP,NONE,ZEROORONE
+NONE,VEVENT,TRIGGER,NONE,ZERO
+NONE,VEVENT,TZID,NONE,ZERO
+NONE,VEVENT,TZNAME,NONE,ZERO
+NONE,VEVENT,TZOFFSETFROM,NONE,ZERO
+NONE,VEVENT,TZOFFSETTO,NONE,ZERO
+NONE,VEVENT,TZURL,NONE,ZERO
+NONE,VEVENT,UID,NONE,ZEROORONE
+NONE,VEVENT,URL,NONE,ZEROORONE
+NONE,VEVENT,VERSION,NONE,ZERO
+NONE,VEVENT,X,NONE,ZEROPLUS
+NONE,VTODO,ACTION,NONE,ZERO
+NONE,VTODO,ATTACH,NONE,ZEROPLUS
+NONE,VTODO,ATTENDEE,NONE,ZEROPLUS
+NONE,VTODO,CALSCALE,NONE,ZERO
+NONE,VTODO,CATEGORIES,NONE,ZEROPLUS
+NONE,VTODO,CLASS,NONE,ZEROORONE
+NONE,VTODO,COMMENT,NONE,ZEROPLUS
+NONE,VTODO,COMPLETED,NONE,ZEROORONE
+NONE,VTODO,CONTACT,NONE,ZEROPLUS
+NONE,VTODO,CREATED,NONE,ZEROORONE
+NONE,VTODO,DESCRIPTION,NONE,ZEROORONE
+NONE,VTODO,DTEND,NONE,ZERO
+NONE,VTODO,DTSTAMP,NONE,ZEROORONE
+NONE,VTODO,DTSTART,NONE,ZEROORONE
+NONE,VTODO,DUE,NONE,ONEEXCLUSIVE
+NONE,VTODO,DURATION,NONE,ONEEXCLUSIVE
+NONE,VTODO,EXDATE,NONE,ZEROPLUS
+NONE,VTODO,EXRULE,NONE,ZEROPLUS
+NONE,VTODO,FREEBUSY,NONE,ZERO
+NONE,VTODO,GEO,NONE,ZEROORONE
+NONE,VTODO,LASTMODIFIED,NONE,ZEROORONE
+NONE,VTODO,LOCATION,NONE,ZEROORONE
+NONE,VTODO,METHOD,NONE,ZERO
+NONE,VTODO,ORGANIZER,NONE,ZEROORONE
+NONE,VTODO,PERCENTCOMPLETE,NONE,ZEROORONE
+NONE,VTODO,PRIORITY,NONE,ZEROORONE
+NONE,VTODO,PRODID,NONE,ZERO
+NONE,VTODO,RDATE,NONE,ZEROPLUS
+NONE,VTODO,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+NONE,VTODO,RELATEDTO,NONE,ZEROPLUS
+NONE,VTODO,REPEAT,NONE,ZERO
+NONE,VTODO,REQUESTSTATUS,NONE,ZEROPLUS
+NONE,VTODO,RESOURCES,NONE,ZEROPLUS
+NONE,VTODO,RRULE,NONE,ZEROPLUS
+NONE,VTODO,SEQUENCE,NONE,ZEROORONE
+NONE,VTODO,STATUS,NONE,ZEROORONE
+NONE,VTODO,SUMMARY,NONE,ZEROORONE
+NONE,VTODO,TRANSP,NONE,ZERO
+NONE,VTODO,TRIGGER,NONE,ZERO
+NONE,VTODO,TZID,NONE,ZERO
+NONE,VTODO,TZNAME,NONE,ZERO
+NONE,VTODO,TZOFFSETFROM,NONE,ZERO
+NONE,VTODO,TZOFFSETTO,NONE,ZERO
+NONE,VTODO,TZURL,NONE,ZERO
+NONE,VTODO,UID,NONE,ZEROORONE
+NONE,VTODO,URL,NONE,ZEROORONE
+NONE,VTODO,VERSION,NONE,ZERO
+NONE,VTODO,X,NONE,ZEROPLUS
+NONE,VJOURNAL,ACTION,NONE,ZERO
+NONE,VJOURNAL,ATTACH,NONE,ZEROPLUS
+NONE,VJOURNAL,ATTENDEE,NONE,ZEROPLUS
+NONE,VJOURNAL,CALSCALE,NONE,ZERO
+NONE,VJOURNAL,CATEGORIES,NONE,ZEROPLUS
+NONE,VJOURNAL,CLASS,NONE,ZEROORONE
+NONE,VJOURNAL,COMMENT,NONE,ZEROPLUS
+NONE,VJOURNAL,COMPLETED,NONE,ZERO
+NONE,VJOURNAL,CONTACT,NONE,ZEROPLUS
+NONE,VJOURNAL,CREATED,NONE,ZEROORONE
+NONE,VJOURNAL,DESCRIPTION,NONE,ZEROORONE
+NONE,VJOURNAL,DTEND,NONE,ZERO
+NONE,VJOURNAL,DTSTAMP,NONE,ZEROORONE
+NONE,VJOURNAL,DTSTART,NONE,ZEROORONE
+NONE,VJOURNAL,DUE,NONE,ONEEXCLUSIVE
+NONE,VJOURNAL,DURATION,NONE,ONEEXCLUSIVE
+NONE,VJOURNAL,EXDATE,NONE,ZEROPLUS
+NONE,VJOURNAL,EXRULE,NONE,ZEROPLUS
+NONE,VJOURNAL,FREEBUSY,NONE,ZERO
+NONE,VJOURNAL,GEO,NONE,ZERO
+NONE,VJOURNAL,LASTMODIFIED,NONE,ZEROORONE
+NONE,VJOURNAL,LOCATION,NONE,ZERO
+NONE,VJOURNAL,METHOD,NONE,ZERO
+NONE,VJOURNAL,ORGANIZER,NONE,ZEROORONE
+NONE,VJOURNAL,PERCENTCOMPLETE,NONE,ZERO
+NONE,VJOURNAL,PRIORITY,NONE,ZERO
+NONE,VJOURNAL,PRODID,NONE,ZERO
+NONE,VJOURNAL,RDATE,NONE,ZEROPLUS
+NONE,VJOURNAL,RECURRENCEID,NONE,ZEROORONE,must_be_recurring
+NONE,VJOURNAL,RELATEDTO,NONE,ZEROPLUS
+NONE,VJOURNAL,REPEAT,NONE,ZERO
+NONE,VJOURNAL,REQUESTSTATUS,NONE,ZEROPLUS
+NONE,VJOURNAL,RESOURCES,NONE,ZERO
+NONE,VJOURNAL,RRULE,NONE,ZEROPLUS
+NONE,VJOURNAL,SEQUENCE,NONE,ZEROORONE
+NONE,VJOURNAL,STATUS,NONE,ZEROORONE
+NONE,VJOURNAL,SUMMARY,NONE,ZEROORONE
+NONE,VJOURNAL,TRANSP,NONE,ZERO
+NONE,VJOURNAL,TRIGGER,NONE,ZERO
+NONE,VJOURNAL,TZID,NONE,ZERO
+NONE,VJOURNAL,TZNAME,NONE,ZERO
+NONE,VJOURNAL,TZOFFSETFROM,NONE,ZERO
+NONE,VJOURNAL,TZOFFSETTO,NONE,ZERO
+NONE,VJOURNAL,TZURL,NONE,ZERO
+NONE,VJOURNAL,UID,NONE,ZEROORONE
+NONE,VJOURNAL,URL,NONE,ZEROORONE
+NONE,VJOURNAL,VERSION,NONE,ZERO
+NONE,VJOURNAL,X,NONE,ZEROPLUS
+NONE,VFREEBUSY,ACTION,NONE,ZERO
+NONE,VFREEBUSY,ATTACH,NONE,ZERO
+NONE,VFREEBUSY,ATTENDEE,NONE,ZEROPLUS
+NONE,VFREEBUSY,CALSCALE,NONE,ZERO
+NONE,VFREEBUSY,CATEGORIES,NONE,ZERO
+NONE,VFREEBUSY,CLASS,NONE,ZERO
+NONE,VFREEBUSY,COMMENT,NONE,ZEROPLUS
+NONE,VFREEBUSY,COMPLETED,NONE,ZERO
+NONE,VFREEBUSY,CONTACT,NONE,ZEROORONE
+NONE,VFREEBUSY,CREATED,NONE,ZERO
+NONE,VFREEBUSY,DESCRIPTION,NONE,ZERO
+NONE,VFREEBUSY,DTEND,NONE,ZEROORONE
+NONE,VFREEBUSY,DTSTAMP,NONE,ZERO
+NONE,VFREEBUSY,DTSTART,NONE,ZEROORONE
+NONE,VFREEBUSY,DUE,NONE,ZERO
+NONE,VFREEBUSY,DURATION,NONE,ZEROORONE
+NONE,VFREEBUSY,EXDATE,NONE,ZERO
+NONE,VFREEBUSY,EXRULE,NONE,ZERO
+NONE,VFREEBUSY,FREEBUSY,NONE,ZEROPLUS
+NONE,VFREEBUSY,GEO,NONE,ZERO
+NONE,VFREEBUSY,LASTMODIFIED,NONE,ZERO
+NONE,VFREEBUSY,LOCATION,NONE,ZERO
+NONE,VFREEBUSY,METHOD,NONE,ZERO
+NONE,VFREEBUSY,ORGANIZER,NONE,ZEROORONE
+NONE,VFREEBUSY,PERCENTCOMPLETE,NONE,ZERO
+NONE,VFREEBUSY,PRIORITY,NONE,ZERO
+NONE,VFREEBUSY,PRODID,NONE,ZERO
+NONE,VFREEBUSY,RDATE,NONE,ZERO
+NONE,VFREEBUSY,RECURRENCEID,NONE,ZERO
+NONE,VFREEBUSY,RELATEDTO,NONE,ZERO
+NONE,VFREEBUSY,REPEAT,NONE,ZERO
+NONE,VFREEBUSY,REQUESTSTATUS,NONE,ZEROPLUS
+NONE,VFREEBUSY,RESOURCES,NONE,ZERO
+NONE,VFREEBUSY,RRULE,NONE,ZERO
+NONE,VFREEBUSY,SEQUENCE,NONE,ZERO
+NONE,VFREEBUSY,STATUS,NONE,ZERO
+NONE,VFREEBUSY,SUMMARY,NONE,ZERO
+NONE,VFREEBUSY,TRANSP,NONE,ZERO
+NONE,VFREEBUSY,TRIGGER,NONE,ZERO
+NONE,VFREEBUSY,TZID,NONE,ZERO
+NONE,VFREEBUSY,TZNAME,NONE,ZERO
+NONE,VFREEBUSY,TZOFFSETFROM,NONE,ZERO
+NONE,VFREEBUSY,TZOFFSETTO,NONE,ZERO
+NONE,VFREEBUSY,TZURL,NONE,ZERO
+NONE,VFREEBUSY,UID,NONE,ZEROORONE
+NONE,VFREEBUSY,URL,NONE,ZEROORONE
+NONE,VFREEBUSY,VERSION,NONE,ZERO
+NONE,VFREEBUSY,X,NONE,ZEROPLUS
+NONE,VTIMEZONE,ACTION,NONE,ZERO
+NONE,VTIMEZONE,ATTACH,NONE,ZERO
+NONE,VTIMEZONE,ATTENDEE,NONE,ZERO
+NONE,VTIMEZONE,CALSCALE,NONE,ZERO
+NONE,VTIMEZONE,CATEGORIES,NONE,ZERO
+NONE,VTIMEZONE,CLASS,NONE,ZERO
+NONE,VTIMEZONE,COMMENT,NONE,ZERO
+NONE,VTIMEZONE,COMPLETED,NONE,ZERO
+NONE,VTIMEZONE,CONTACT,NONE,ZERO
+NONE,VTIMEZONE,CREATED,NONE,ZERO
+NONE,VTIMEZONE,DESCRIPTION,NONE,ZERO
+NONE,VTIMEZONE,DTEND,NONE,ZERO
+NONE,VTIMEZONE,DTSTAMP,NONE,ZERO
+NONE,VTIMEZONE,DTSTART,NONE,ZERO
+NONE,VTIMEZONE,DUE,NONE,ZERO
+NONE,VTIMEZONE,DURATION,NONE,ZERO
+NONE,VTIMEZONE,EXDATE,NONE,ZERO
+NONE,VTIMEZONE,EXRULE,NONE,ZERO
+NONE,VTIMEZONE,FREEBUSY,NONE,ZERO
+NONE,VTIMEZONE,GEO,NONE,ZERO
+NONE,VTIMEZONE,LASTMODIFIED,NONE,ZEROORONE
+NONE,VTIMEZONE,LOCATION,NONE,ZERO
+NONE,VTIMEZONE,METHOD,NONE,ZERO
+NONE,VTIMEZONE,ORGANIZER,NONE,ZERO
+NONE,VTIMEZONE,PERCENTCOMPLETE,NONE,ZERO
+NONE,VTIMEZONE,PRIORITY,NONE,ZERO
+NONE,VTIMEZONE,PRODID,NONE,ZERO
+NONE,VTIMEZONE,RDATE,NONE,ZERO
+NONE,VTIMEZONE,RECURRENCEID,NONE,ZERO
+NONE,VTIMEZONE,RELATEDTO,NONE,ZERO
+NONE,VTIMEZONE,REPEAT,NONE,ZERO
+NONE,VTIMEZONE,REQUESTSTATUS,NONE,ZERO
+NONE,VTIMEZONE,RESOURCES,NONE,ZERO
+NONE,VTIMEZONE,RRULE,NONE,ZERO
+NONE,VTIMEZONE,SEQUENCE,NONE,ZERO
+NONE,VTIMEZONE,STATUS,NONE,ZERO
+NONE,VTIMEZONE,SUMMARY,NONE,ZERO
+NONE,VTIMEZONE,TRANSP,NONE,ZERO
+NONE,VTIMEZONE,TRIGGER,NONE,ZERO
+NONE,VTIMEZONE,TZID,NONE,ONE
+NONE,VTIMEZONE,TZNAME,NONE,ZERO
+NONE,VTIMEZONE,TZOFFSETFROM,NONE,ZERO
+NONE,VTIMEZONE,TZOFFSETTO,NONE,ZERO
+NONE,VTIMEZONE,TZURL,NONE,ZEROPLUS
+NONE,VTIMEZONE,UID,NONE,ZERO
+NONE,VTIMEZONE,URL,NONE,ZERO
+NONE,VTIMEZONE,VERSION,NONE,ZERO
+NONE,VTIMEZONE,X,NONE,ZEROORONE
+NONE,XSTANDARD,ACTION,NONE,ZERO
+NONE,XSTANDARD,ATTACH,NONE,ZERO
+NONE,XSTANDARD,ATTENDEE,NONE,ZERO
+NONE,XSTANDARD,CALSCALE,NONE,ZERO
+NONE,XSTANDARD,CATEGORIES,NONE,ZERO
+NONE,XSTANDARD,CLASS,NONE,ZERO
+NONE,XSTANDARD,COMMENT,NONE,ZEROPLUS
+NONE,XSTANDARD,COMPLETED,NONE,ZERO
+NONE,XSTANDARD,CONTACT,NONE,ZERO
+NONE,XSTANDARD,CREATED,NONE,ZERO
+NONE,XSTANDARD,DESCRIPTION,NONE,ZERO
+NONE,XSTANDARD,DTEND,NONE,ZERO
+NONE,XSTANDARD,DTSTAMP,NONE,ZERO
+NONE,XSTANDARD,DTSTART,NONE,ONE
+NONE,XSTANDARD,DUE,NONE,ZERO
+NONE,XSTANDARD,DURATION,NONE,ZERO
+NONE,XSTANDARD,EXDATE,NONE,ZERO
+NONE,XSTANDARD,EXRULE,NONE,ZERO
+NONE,XSTANDARD,FREEBUSY,NONE,ZERO
+NONE,XSTANDARD,GEO,NONE,ZERO
+NONE,XSTANDARD,LASTMODIFIED,NONE,ZERO
+NONE,XSTANDARD,LOCATION,NONE,ZERO
+NONE,XSTANDARD,METHOD,NONE,ZERO
+NONE,XSTANDARD,ORGANIZER,NONE,ZERO
+NONE,XSTANDARD,PERCENTCOMPLETE,NONE,ZERO
+NONE,XSTANDARD,PRIORITY,NONE,ZERO
+NONE,XSTANDARD,PRODID,NONE,ZERO
+NONE,XSTANDARD,RDATE,NONE,ZEROPLUS
+NONE,XSTANDARD,RECURRENCEID,NONE,ZERO
+NONE,XSTANDARD,RELATEDTO,NONE,ZERO
+NONE,XSTANDARD,REPEAT,NONE,ZERO
+NONE,XSTANDARD,REQUESTSTATUS,NONE,ZERO
+NONE,XSTANDARD,RESOURCES,NONE,ZERO
+NONE,XSTANDARD,RRULE,NONE,ZEROPLUS
+NONE,XSTANDARD,SEQUENCE,NONE,ZERO
+NONE,XSTANDARD,STATUS,NONE,ZERO
+NONE,XSTANDARD,SUMMARY,NONE,ZERO
+NONE,XSTANDARD,TRANSP,NONE,ZERO
+NONE,XSTANDARD,TRIGGER,NONE,ZERO
+NONE,XSTANDARD,TZID,NONE,ZERO
+NONE,XSTANDARD,TZNAME,NONE,ZEROPLUS
+NONE,XSTANDARD,TZOFFSETFROM,NONE,ONE
+NONE,XSTANDARD,TZOFFSETTO,NONE,ONE
+NONE,XSTANDARD,TZURL,NONE,ZERO
+NONE,XSTANDARD,UID,NONE,ZERO
+NONE,XSTANDARD,URL,NONE,ZERO
+NONE,XSTANDARD,VERSION,NONE,ZERO
+NONE,XSTANDARD,X,NONE,ZEROPLUS
+NONE,XDAYLIGHT,ACTION,NONE,ZERO
+NONE,XDAYLIGHT,ATTACH,NONE,ZERO
+NONE,XDAYLIGHT,ATTENDEE,NONE,ZERO
+NONE,XDAYLIGHT,CALSCALE,NONE,ZERO
+NONE,XDAYLIGHT,CATEGORIES,NONE,ZERO
+NONE,XDAYLIGHT,CLASS,NONE,ZERO
+NONE,XDAYLIGHT,COMMENT,NONE,ZEROPLUS
+NONE,XDAYLIGHT,COMPLETED,NONE,ZERO
+NONE,XDAYLIGHT,CONTACT,NONE,ZERO
+NONE,XDAYLIGHT,CREATED,NONE,ZERO
+NONE,XDAYLIGHT,DESCRIPTION,NONE,ZERO
+NONE,XDAYLIGHT,DTEND,NONE,ZERO
+NONE,XDAYLIGHT,DTSTAMP,NONE,ZERO
+NONE,XDAYLIGHT,DTSTART,NONE,ONE
+NONE,XDAYLIGHT,DUE,NONE,ZERO
+NONE,XDAYLIGHT,DURATION,NONE,ZERO
+NONE,XDAYLIGHT,EXDATE,NONE,ZERO
+NONE,XDAYLIGHT,EXRULE,NONE,ZERO
+NONE,XDAYLIGHT,FREEBUSY,NONE,ZERO
+NONE,XDAYLIGHT,GEO,NONE,ZERO
+NONE,XDAYLIGHT,LASTMODIFIED,NONE,ZERO
+NONE,XDAYLIGHT,LOCATION,NONE,ZERO
+NONE,XDAYLIGHT,METHOD,NONE,ZERO
+NONE,XDAYLIGHT,ORGANIZER,NONE,ZERO
+NONE,XDAYLIGHT,PERCENTCOMPLETE,NONE,ZERO
+NONE,XDAYLIGHT,PRIORITY,NONE,ZERO
+NONE,XDAYLIGHT,PRODID,NONE,ZERO
+NONE,XDAYLIGHT,RDATE,NONE,ZEROPLUS
+NONE,XDAYLIGHT,RECURRENCEID,NONE,ZERO
+NONE,XDAYLIGHT,RELATEDTO,NONE,ZERO
+NONE,XDAYLIGHT,REPEAT,NONE,ZERO
+NONE,XDAYLIGHT,REQUESTSTATUS,NONE,ZERO
+NONE,XDAYLIGHT,RESOURCES,NONE,ZERO
+NONE,XDAYLIGHT,RRULE,NONE,ZEROPLUS
+NONE,XDAYLIGHT,SEQUENCE,NONE,ZERO
+NONE,XDAYLIGHT,STATUS,NONE,ZERO
+NONE,XDAYLIGHT,SUMMARY,NONE,ZERO
+NONE,XDAYLIGHT,TRANSP,NONE,ZERO
+NONE,XDAYLIGHT,TRIGGER,NONE,ZERO
+NONE,XDAYLIGHT,TZID,NONE,ZERO
+NONE,XDAYLIGHT,TZNAME,NONE,ZEROPLUS
+NONE,XDAYLIGHT,TZOFFSETFROM,NONE,ONE
+NONE,XDAYLIGHT,TZOFFSETTO,NONE,ONE
+NONE,XDAYLIGHT,TZURL,NONE,ZERO
+NONE,XDAYLIGHT,UID,NONE,ZERO
+NONE,XDAYLIGHT,URL,NONE,ZERO
+NONE,XDAYLIGHT,VERSION,NONE,ZERO
+NONE,XDAYLIGHT,X,NONE,ZEROPLUS
+NONE,XAUDIOALARM,ACTION,NONE,ONE
+NONE,XAUDIOALARM,ATTACH,NONE,ZEROORONE
+NONE,XAUDIOALARM,ATTENDEE,NONE,ZERO
+NONE,XAUDIOALARM,CALSCALE,NONE,ZERO
+NONE,XAUDIOALARM,CATEGORIES,NONE,ZERO
+NONE,XAUDIOALARM,CLASS,NONE,ZERO
+NONE,XAUDIOALARM,COMMENT,NONE,ZERO
+NONE,XAUDIOALARM,COMPLETED,NONE,ZERO
+NONE,XAUDIOALARM,CONTACT,NONE,ZERO
+NONE,XAUDIOALARM,CREATED,NONE,ZERO
+NONE,XAUDIOALARM,DESCRIPTION,NONE,ZERO
+NONE,XAUDIOALARM,DTEND,NONE,ZERO
+NONE,XAUDIOALARM,DTSTAMP,NONE,ZERO
+NONE,XAUDIOALARM,DTSTART,NONE,ZERO
+NONE,XAUDIOALARM,DUE,NONE,ZERO
+NONE,XAUDIOALARM,DURATION,NONE,ONEMUTUAL,must_have_repeat
+NONE,XAUDIOALARM,REPEAT,NONE,ONEMUTUAL,must_have_duration
+NONE,XAUDIOALARM,EXDATE,NONE,ZERO
+NONE,XAUDIOALARM,EXRULE,NONE,ZERO
+NONE,XAUDIOALARM,FREEBUSY,NONE,ZERO
+NONE,XAUDIOALARM,GEO,NONE,ZERO
+NONE,XAUDIOALARM,LASTMODIFIED,NONE,ZERO
+NONE,XAUDIOALARM,LOCATION,NONE,ZERO
+NONE,XAUDIOALARM,METHOD,NONE,ZERO
+NONE,XAUDIOALARM,ORGANIZER,NONE,ZERO
+NONE,XAUDIOALARM,PERCENTCOMPLETE,NONE,ZERO
+NONE,XAUDIOALARM,PRIORITY,NONE,ZERO
+NONE,XAUDIOALARM,PRODID,NONE,ZERO
+NONE,XAUDIOALARM,RDATE,NONE,ZERO
+NONE,XAUDIOALARM,RECURRENCEID,NONE,ZERO
+NONE,XAUDIOALARM,RELATEDTO,NONE,ZERO
+NONE,XAUDIOALARM,REQUESTSTATUS,NONE,ZERO
+NONE,XAUDIOALARM,RESOURCES,NONE,ZERO
+NONE,XAUDIOALARM,RRULE,NONE,ZERO
+NONE,XAUDIOALARM,SEQUENCE,NONE,ZERO
+NONE,XAUDIOALARM,STATUS,NONE,ZERO
+NONE,XAUDIOALARM,SUMMARY,NONE,ZERO
+NONE,XAUDIOALARM,TRANSP,NONE,ZERO
+NONE,XAUDIOALARM,TRIGGER,NONE,ONE
+NONE,XAUDIOALARM,TZID,NONE,ZERO
+NONE,XAUDIOALARM,TZNAME,NONE,ZERO
+NONE,XAUDIOALARM,TZOFFSETFROM,NONE,ZERO
+NONE,XAUDIOALARM,TZOFFSETTO,NONE,ZERO
+NONE,XAUDIOALARM,TZURL,NONE,ZERO
+NONE,XAUDIOALARM,UID,NONE,ZERO
+NONE,XAUDIOALARM,URL,NONE,ZERO
+NONE,XAUDIOALARM,VERSION,NONE,ZERO
+NONE,XAUDIOALARM,X,NONE,ZEROPLUS
+NONE,XDISPLAYALARM,ACTION,NONE,ONE
+NONE,XDISPLAYALARM,ATTACH,NONE,ZERO
+NONE,XDISPLAYALARM,ATTENDEE,NONE,ZERO
+NONE,XDISPLAYALARM,CALSCALE,NONE,ZERO
+NONE,XDISPLAYALARM,CATEGORIES,NONE,ZERO
+NONE,XDISPLAYALARM,CLASS,NONE,ZERO
+NONE,XDISPLAYALARM,COMMENT,NONE,ZERO
+NONE,XDISPLAYALARM,COMPLETED,NONE,ZERO
+NONE,XDISPLAYALARM,CONTACT,NONE,ZERO
+NONE,XDISPLAYALARM,CREATED,NONE,ZERO
+NONE,XDISPLAYALARM,DESCRIPTION,NONE,ONE
+NONE,XDISPLAYALARM,DTEND,NONE,ZERO
+NONE,XDISPLAYALARM,DTSTAMP,NONE,ZERO
+NONE,XDISPLAYALARM,DTSTART,NONE,ZERO
+NONE,XDISPLAYALARM,DUE,NONE,ZERO
+NONE,XDISPLAYALARM,DURATION,NONE,ONEMUTUAL,must_have_repeat
+NONE,XDISPLAYALARM,REPEAT,NONE,ONEMUTUAL,must_have_duration
+NONE,XDISPLAYALARM,EXDATE,NONE,ZERO
+NONE,XDISPLAYALARM,EXRULE,NONE,ZERO
+NONE,XDISPLAYALARM,FREEBUSY,NONE,ZERO
+NONE,XDISPLAYALARM,GEO,NONE,ZERO
+NONE,XDISPLAYALARM,LASTMODIFIED,NONE,ZERO
+NONE,XDISPLAYALARM,LOCATION,NONE,ZERO
+NONE,XDISPLAYALARM,METHOD,NONE,ZERO
+NONE,XDISPLAYALARM,ORGANIZER,NONE,ZERO
+NONE,XDISPLAYALARM,PERCENTCOMPLETE,NONE,ZERO
+NONE,XDISPLAYALARM,PRIORITY,NONE,ZERO
+NONE,XDISPLAYALARM,PRODID,NONE,ZERO
+NONE,XDISPLAYALARM,RDATE,NONE,ZERO
+NONE,XDISPLAYALARM,RECURRENCEID,NONE,ZERO
+NONE,XDISPLAYALARM,RELATEDTO,NONE,ZERO
+NONE,XDISPLAYALARM,REQUESTSTATUS,NONE,ZERO
+NONE,XDISPLAYALARM,RESOURCES,NONE,ZERO
+NONE,XDISPLAYALARM,RRULE,NONE,ZERO
+NONE,XDISPLAYALARM,SEQUENCE,NONE,ZERO
+NONE,XDISPLAYALARM,STATUS,NONE,ZERO
+NONE,XDISPLAYALARM,SUMMARY,NONE,ZERO
+NONE,XDISPLAYALARM,TRANSP,NONE,ZERO
+NONE,XDISPLAYALARM,TRIGGER,NONE,ONE
+NONE,XDISPLAYALARM,TZID,NONE,ZERO
+NONE,XDISPLAYALARM,TZNAME,NONE,ZERO
+NONE,XDISPLAYALARM,TZOFFSETFROM,NONE,ZERO
+NONE,XDISPLAYALARM,TZOFFSETTO,NONE,ZERO
+NONE,XDISPLAYALARM,TZURL,NONE,ZERO
+NONE,XDISPLAYALARM,UID,NONE,ZERO
+NONE,XDISPLAYALARM,URL,NONE,ZERO
+NONE,XDISPLAYALARM,VERSION,NONE,ZERO
+NONE,XDISPLAYALARM,X,NONE,ZEROPLUS
+NONE,XEMAILALARM,ACTION,NONE,ONE
+NONE,XEMAILALARM,ATTACH,NONE,ZEROPLUS
+NONE,XEMAILALARM,ATTENDEE,NONE,ONEPLUS
+NONE,XEMAILALARM,CALSCALE,NONE,ZERO
+NONE,XEMAILALARM,CATEGORIES,NONE,ZERO
+NONE,XEMAILALARM,CLASS,NONE,ZERO
+NONE,XEMAILALARM,COMMENT,NONE,ZERO
+NONE,XEMAILALARM,COMPLETED,NONE,ZERO
+NONE,XEMAILALARM,CONTACT,NONE,ZERO
+NONE,XEMAILALARM,CREATED,NONE,ZERO
+NONE,XEMAILALARM,DESCRIPTION,NONE,ONE
+NONE,XEMAILALARM,DTEND,NONE,ZERO
+NONE,XEMAILALARM,DTSTAMP,NONE,ZERO
+NONE,XEMAILALARM,DTSTART,NONE,ZERO
+NONE,XEMAILALARM,DUE,NONE,ZERO
+NONE,XEMAILALARM,DURATION,NONE,ONEMUTUAL,must_have_repeat
+NONE,XEMAILALARM,REPEAT,NONE,ONEMUTUAL,must_have_duration
+NONE,XEMAILALARM,EXDATE,NONE,ZERO
+NONE,XEMAILALARM,EXRULE,NONE,ZERO
+NONE,XEMAILALARM,FREEBUSY,NONE,ZERO
+NONE,XEMAILALARM,GEO,NONE,ZERO
+NONE,XEMAILALARM,LASTMODIFIED,NONE,ZERO
+NONE,XEMAILALARM,LOCATION,NONE,ZERO
+NONE,XEMAILALARM,METHOD,NONE,ZERO
+NONE,XEMAILALARM,ORGANIZER,NONE,ZERO
+NONE,XEMAILALARM,PERCENTCOMPLETE,NONE,ZERO
+NONE,XEMAILALARM,PRIORITY,NONE,ZERO
+NONE,XEMAILALARM,PRODID,NONE,ZERO
+NONE,XEMAILALARM,RDATE,NONE,ZERO
+NONE,XEMAILALARM,RECURRENCEID,NONE,ZERO
+NONE,XEMAILALARM,RELATEDTO,NONE,ZERO
+NONE,XEMAILALARM,REQUESTSTATUS,NONE,ZERO
+NONE,XEMAILALARM,RESOURCES,NONE,ZERO
+NONE,XEMAILALARM,RRULE,NONE,ZERO
+NONE,XEMAILALARM,SEQUENCE,NONE,ZERO
+NONE,XEMAILALARM,STATUS,NONE,ZERO
+NONE,XEMAILALARM,SUMMARY,NONE,ONE
+NONE,XEMAILALARM,TRANSP,NONE,ZERO
+NONE,XEMAILALARM,TRIGGER,NONE,ONE
+NONE,XEMAILALARM,TZID,NONE,ZERO
+NONE,XEMAILALARM,TZNAME,NONE,ZERO
+NONE,XEMAILALARM,TZOFFSETFROM,NONE,ZERO
+NONE,XEMAILALARM,TZOFFSETTO,NONE,ZERO
+NONE,XEMAILALARM,TZURL,NONE,ZERO
+NONE,XEMAILALARM,UID,NONE,ZERO
+NONE,XEMAILALARM,URL,NONE,ZERO
+NONE,XEMAILALARM,VERSION,NONE,ZERO
+NONE,XEMAILALARM,X,NONE,ZEROPLUS
+NONE,XPROCEDUREALARM,ACTION,NONE,ONE
+NONE,XPROCEDUREALARM,ATTACH,NONE,ZEROORONE
+NONE,XPROCEDUREALARM,ATTENDEE,NONE,ZERO
+NONE,XPROCEDUREALARM,CALSCALE,NONE,ZERO
+NONE,XPROCEDUREALARM,CATEGORIES,NONE,ZERO
+NONE,XPROCEDUREALARM,CLASS,NONE,ZERO
+NONE,XPROCEDUREALARM,COMMENT,NONE,ZERO
+NONE,XPROCEDUREALARM,COMPLETED,NONE,ZERO
+NONE,XPROCEDUREALARM,CONTACT,NONE,ZERO
+NONE,XPROCEDUREALARM,CREATED,NONE,ZERO
+NONE,XPROCEDUREALARM,DESCRIPTION,NONE,ZEROORONE
+NONE,XPROCEDUREALARM,DTEND,NONE,ZERO
+NONE,XPROCEDUREALARM,DTSTAMP,NONE,ZERO
+NONE,XPROCEDUREALARM,DTSTART,NONE,ZERO
+NONE,XPROCEDUREALARM,DUE,NONE,ZERO
+NONE,XPROCEDUREALARM,DURATION,NONE,ONEMUTUAL,must_have_repeat
+NONE,XPROCEDUREALARM,REPEAT,NONE,ONEMUTUAL,must_have_duration
+NONE,XPROCEDUREALARM,EXDATE,NONE,ZERO
+NONE,XPROCEDUREALARM,EXRULE,NONE,ZERO
+NONE,XPROCEDUREALARM,FREEBUSY,NONE,ZERO
+NONE,XPROCEDUREALARM,GEO,NONE,ZERO
+NONE,XPROCEDUREALARM,LASTMODIFIED,NONE,ZERO
+NONE,XPROCEDUREALARM,LOCATION,NONE,ZERO
+NONE,XPROCEDUREALARM,METHOD,NONE,ZERO
+NONE,XPROCEDUREALARM,ORGANIZER,NONE,ZERO
+NONE,XPROCEDUREALARM,PERCENTCOMPLETE,NONE,ZERO
+NONE,XPROCEDUREALARM,PRIORITY,NONE,ZERO
+NONE,XPROCEDUREALARM,PRODID,NONE,ZERO
+NONE,XPROCEDUREALARM,RDATE,NONE,ZERO
+NONE,XPROCEDUREALARM,RECURRENCEID,NONE,ZERO
+NONE,XPROCEDUREALARM,RELATEDTO,NONE,ZERO
+NONE,XPROCEDUREALARM,REQUESTSTATUS,NONE,ZERO
+NONE,XPROCEDUREALARM,RESOURCES,NONE,ZERO
+NONE,XPROCEDUREALARM,RRULE,NONE,ZERO
+NONE,XPROCEDUREALARM,SEQUENCE,NONE,ZERO
+NONE,XPROCEDUREALARM,STATUS,NONE,ZERO
+NONE,XPROCEDUREALARM,SUMMARY,NONE,ZERO
+NONE,XPROCEDUREALARM,TRANSP,NONE,ZERO
+NONE,XPROCEDUREALARM,TRIGGER,NONE,ONE
+NONE,XPROCEDUREALARM,TZID,NONE,ZERO
+NONE,XPROCEDUREALARM,TZNAME,NONE,ZERO
+NONE,XPROCEDUREALARM,TZOFFSETFROM,NONE,ZERO
+NONE,XPROCEDUREALARM,TZOFFSETTO,NONE,ZERO
+NONE,XPROCEDUREALARM,TZURL,NONE,ZERO
+NONE,XPROCEDUREALARM,UID,NONE,ZERO
+NONE,XPROCEDUREALARM,URL,NONE,ZERO
+NONE,XPROCEDUREALARM,VERSION,NONE,ZERO
+NONE,XPROCEDUREALARM,X,NONE,ZEROPLUS
diff --git a/src/plugins/vcalendar/libical/design-data/status.txt b/src/plugins/vcalendar/libical/design-data/status.txt
@@ -0,0 +1,56 @@
+2.0 STATOK Operation was successfully performed.
+2.0.1 STARTSENDATA Start ICAL input; end with <CRLF>.<CRLF>
+2.0.11 OKDATAFOLLOWS The request was processed successfully. Reply data follows on the next line and terminates with <CRLF>.<CRLF>
+2.0.2 REPLYPENDING A timeout has occurred. The server is still working on the reply. Use CONTINUE to continue waiting for the reply or ABORT to terminate the command.
+2.0.3 ABORTED The command currently underway was successsfully aborted.
+2.0.4 WILLATTEMPT The specified Calendar is not here but an attempt will be made to deliver the request or reply to the Calendar anyway.
+2.0.5 TRUSTEDWILLQUEUE The request or reply will be queued and delivered to the target calendar when its iRIP server contacts this server and issues the SWITCH command.
+2.0.6 WILLATTEMPT The specified Calendar is not here but an attempt will be made to deliver the request or reply to the Calendar anyway.
+2.0.7 QUEUED The message has been queued for delivery.
+2.0.8 QUEUEEMPTY There are no more queued messages.
+2.1 FALLBACK Success. Fallback taken on one or more property values.
+2.2 NOCOMMANDINPROGRESS An ABORT or CONTINUE was received when no command was in progress
+2.2 IGPROP Success. Invalid property ignored.
+2.3 IGPARAM Success. invalid property parameter ignored.
+2.4 IGXPROP Success. Unknown non-standard property ignored.
+2.5 IGXPARAM Success. Unknown non standard property value ignored.
+2.6 IGCOMP Success. Invalid calendar component ignored.
+2.7 FORWARD Success. Request forwarded to Calendar User.
+2.8 ONEEVENT Success. Repeating event ignored. Scheduled as a single component.
+2.9 TRUNC Success. Truncated end date time to date boundary.
+2.10 ONETODO Success. Repeating VTODO ignored. Scheduled as a single VTODO.
+2.11 TRUNCRRULE Success. Unbounded RRULE clipped at some finite number of instances
+3.0 INVPROPNAME Invalid property name.
+3.1 INVPROPVAL Invalid property value.
+3.2 INVPARAM Invalid property parameter.
+3.3 INVPARAMVAL Invalid property parameter value.
+3.4 INVCOMP Invalid calendar component sequence.
+3.5 INVTIME Invalid date or time.
+3.6 INVRULE Invalid rule.
+3.7 INVCU Invalid Calendar User.
+3.8 NOAUTH No authority.
+3.9 BADVERSION Unsupported version.
+3.10 TOOBIG Request entity too large.
+3.11 MISSREQCOMP Required component or property missing.
+3.12 UNKCOMP Unknown component or property found.
+3.13 BADCOMP Unsupported component or property found
+3.14 NOCAP Unsupported capability.
+4.0 BUSY Event conflict. Date/time is busy.
+5.0 MAYBE Request MAY supported.
+5.1 UNAVAIL Service unavailable.
+5.2 NOSERVICE Invalid calendar service.
+5.3 NOSCHED No scheduling support for user.
+6.1 AUTHENTICATEFAILURE Unsupported authentication mechanism, credentials rejected
+6.2 AUTHENTICATIONABORTED Sender aborted authentication, authentication exchange cancelled
+8.0 GENERALFAILURE A failure has occurred in the Receiver that prevents the operation from succeeding.
+8.1 SERVERTOOBUSY The iRIP Receiver is too busy.
+8.2 ICALOBJECTTOOBIG Object has exceeded the server's size limit.
+8.3 DATETOOLARGE A DATETIME value was too far in the future to be represented on this Calendar.
+8.4 DATETOOSMALL A DATETIME value was too far in the past to be represented on this Calendar.
+9.0 INVALIDIRIPCOMMAND An unrecongnized command was received.
+9.1 UNEXPECTEDCOMMAND The command is not allowed for the server's current state.
+10.1 REFERRAL Accompanied by an alternate address.
+10.2 SERVERSHUTDOWN The server is shutting down.
+10.3 SERVERSTOPPING FLOOD 2
+10.4 EXCEEDEDQUOTAS The operation would cause a resource to exceed the allocated quota
+10.5 QUEUEDTOOLONG The ITIP message has been queued too long. Delivery has been aborted.
diff --git a/src/plugins/vcalendar/libical/design-data/value-types.csv b/src/plugins/vcalendar/libical/design-data/value-types.csv
@@ -0,0 +1,31 @@
+"#Name","C type& gen flag","Python","Component Values","Enum Values"
+"BINARY","(a)const char*","file","unitary",
+"BOOLEAN","(a)int","integer","unitary",
+"CAL-ADDRESS","(a)const char*","string","unitary",
+"DATE","(a)struct icaltimetype","Time","unitary",
+"DATE-TIME","(a)struct icaltimetype","Time","unitary",
+"DURATION","(a)struct icaldurationtype","Duration","unitary",
+"FLOAT","(a)float","float","unitary",
+"INTEGER","(a)int","integer","unitary",
+"PERIOD","(a)struct icalperiodtype","Period","unitary",
+"RECUR","(m)struct icalrecurrencetype","RecurrenceSet","unitary",
+"TEXT","(a)const char*","string","unitary",
+"TIME","(a)struct icaltimetype","Time","unitary",
+"URI","(a)const char*","string","unitary",
+"UTC-OFFSET","(a)int","integer","unitary",
+"QUERY","(a)const char*","string","unitary",
+"#Non-standard multi-valued types",,,,
+"ATTACH","(a)struct icalattachtype","none","URI;BINARY",
+"DATE-TIME-DATE","(a)struct icaltimetype","none","DATE-TIME;DATE",
+"DATE-TIME-PERIOD","(m)struct icaldatetimeperiodtype","none","DATE-TIME;PERIOD",
+"TRIGGER","(m)struct icaltriggertype","string","DURATION;DATE-TIME",
+"#Non-standard property enumeration types",,,,
+"METHOD","(a)enum icalproperty_method","string","unitary","PUBLISH;REQUEST;REPLY;ADD;CANCEL;REFRESH;COUNTER;DECLINECOUNTER;CREATE;READ;RESPONSE;MOVE;MODIFY;GENERATEUID;DELETE"
+"ACTION","(a)enum icalproperty_action","string","unitary","AUDIO;DISPLAY;EMAIL;PROCEDURE"
+"STATUS","(a)enum icalproperty_status","string","unitary","TENTATIVE;CONFIRMED;COMPLETED;NEEDS-ACTION;CANCELLED;IN-PROCESS;DRAFT;FINAL"
+"TRANSP","(a)enum icalproperty_transp","string","unitary","OPAQUE;TRANSPARENT"
+"CLASS","(a)enum icalproperty_class","string","unitary","PUBLIC;PRIVATE;CONFIDENTIAL"
+"#Other non-standard",,,,
+"GEO","(a)struct icalgeotype","tuple","unitary",
+"STRING","(a)const char*","string","unitary",
+"X","(m)const char*","string","unitary",
diff --git a/src/plugins/vcalendar/libical/libical/.cvsignore b/src/plugins/vcalendar/libical/libical/.cvsignore
@@ -0,0 +1,19 @@
+.libs
+.deps
+Makefile
+Makefile.in
+*.lo
+*.la
+ical.h
+icalderivedparameter.c
+icalderivedparameter.h
+icalderivedproperty.c
+icalderivedproperty.h
+icalderivedvalue.c
+icalderivedvalue.h
+icallexer.c
+icalrestriction.c
+icalversion.h
+icalyacc.c
+icalyacc.h
+icalyacc.output
diff --git a/src/plugins/vcalendar/libical/libical/Makefile.am b/src/plugins/vcalendar/libical/libical/Makefile.am
@@ -0,0 +1,226 @@
+#======================================================================
+# FILE: Makefile.am
+# CREATOR: eric
+#
+# $Id$
+#
+#
+# (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of either:
+#
+# The LGPL as published by the Free Software Foundation, version
+# 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+#
+# Or:
+#
+# The Mozilla Public License Version 1.0. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# The original code is icalcomponent.c
+#
+#======================================================================
+
+
+DESIGNDATA = $(top_srcdir)/src/plugins/vcalendar/libical/design-data
+ICALSCRIPTS = $(top_srcdir)/src/plugins/vcalendar/libical/scripts
+
+noinst_LTLIBRARIES = libical.la
+
+YFLAGS = -d -v -t -pical_yy
+LFLAGS = -Pical_yy
+LEX_OUTPUT_ROOT = lex.ical_yy
+
+INCLUDES = \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(srcdir) \
+ -I$(top_srcdir)/src/plugins/vcalendar/libical \
+ -I$(top_srcdir)/src/plugins/vcalendar/libical/libical
+
+libical_la_LDFLAGS = -version-info 0:0:0
+
+libical_la_SOURCES = \
+ icalattendee.h \
+ icalattendee.c \
+ icalcomponent.c \
+ icalcomponent.h \
+ icalenums.c \
+ icalenums.h \
+ icalerror.c \
+ icalerror.h \
+ icallexer.l \
+ icalmemory.c \
+ icalmemory.h \
+ icalmime.c \
+ icalmime.h \
+ icalparameter.c \
+ icalparameter.h \
+ icalparameterimpl.h \
+ icalderivedparameter.c \
+ icalderivedparameter.h \
+ icalparser.c \
+ icalparser.h \
+ icalderivedproperty.c \
+ icalderivedproperty.h \
+ icalproperty.c \
+ icalproperty.h \
+ icalrecur.c \
+ icalrecur.h \
+ icalrestriction.c \
+ icalrestriction.h \
+ icaltime.c \
+ icaltime.h \
+ icalduration.h \
+ icalduration.c \
+ icalperiod.h \
+ icalperiod.c \
+ icaltypes.c \
+ icaltypes.h \
+ icalvalue.c \
+ icalvalue.h \
+ icalvalueimpl.h \
+ icalderivedvalue.c \
+ icalderivedvalue.h \
+ icalyacc.h \
+ icalyacc.y \
+ pvl.c \
+ pvl.h \
+ sspm.c \
+ sspm.h \
+ vsnprintf.c \
+ icallangbind.h
+
+libicalincludedir = $(includedir)/claws-mail/plugins/@PACKAGE@
+
+libicalinclude_HEADERS = ical.h
+
+# ORDERING OF HEADERS IS SIGNIFICANT. Don't change this ordering. It
+# is required to make the combined header ical.h properly
+COMBINEDHEADERS = \
+ $(top_builddir)/src/plugins/vcalendar/libical/libical/icalversion.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icaltime.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalduration.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalperiod.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalenums.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icaltypes.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalrecur.h \
+ icalderivedvalue.h \
+ icalderivedparameter.h \
+ icalvalue.h \
+ icalparameter.h \
+ icalderivedproperty.h \
+ icalproperty.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalattendee.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/pvl.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalcomponent.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalparser.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalmemory.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalerror.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalrestriction.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/sspm.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalmime.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icallangbind.h
+
+BUILT_SOURCES = \
+ ical.h \
+ icalderivedparameter.c \
+ icalderivedparameter.h \
+ icalderivedproperty.c \
+ icalderivedproperty.h \
+ icalrestriction.c \
+ icalderivedvalue.c \
+ icalderivedvalue.h
+
+ical.h: $(COMBINEDHEADERS)
+ cat $(COMBINEDHEADERS) \
+ | egrep -v "#include.*\"ical" \
+ | egrep -v "#include.*\"pvl\.h\"" > ical.h
+
+icallexer.c : icalyacc.h
+
+
+# parameters
+
+PARAMETERDEPS = \
+ $(ICALSCRIPTS)/mkderivedparameters.pl \
+ $(DESIGNDATA)/parameters.csv \
+ icalderivedparameter.c.in \
+ icalderivedparameter.h.in
+
+icalderivedparameter.h: $(PARAMETERDEPS)
+ $(PERL) -I $(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedparameters.pl -i $(srcdir)/icalderivedparameter.h.in -h $(DESIGNDATA)/parameters.csv > icalderivedparameter.h
+
+icalderivedparameter.c: $(PARAMETERDEPS) icalparameter.h
+ $(PERL) -I $(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedparameters.pl -i $(srcdir)/icalderivedparameter.c.in -c $(DESIGNDATA)/parameters.csv > icalderivedparameter.c
+
+
+# properties
+
+PROPERTYDEPS = \
+ $(ICALSCRIPTS)/mkderivedproperties.pl \
+ $(DESIGNDATA)/properties.csv \
+ $(DESIGNDATA)/value-types.csv \
+ icalderivedproperty.c.in \
+ icalderivedproperty.h.in
+
+
+icalderivedproperty.h: $(PROPERTYDEPS)
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedproperties.pl \
+ -i $(srcdir)/icalderivedproperty.h.in -h $(DESIGNDATA)/properties.csv\
+ ${DESIGNDATA}/value-types.csv > icalderivedproperty.h
+
+icalderivedproperty.c: $(PROPERTYDEPS) icalproperty.h
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedproperties.pl \
+ -i $(srcdir)/icalderivedproperty.c.in -c $(DESIGNDATA)/properties.csv \
+ ${DESIGNDATA}/value-types.csv > icalderivedproperty.c
+
+# restrictions
+
+RESTRICTIONDEPS = \
+ $(ICALSCRIPTS)/mkrestrictiontable.pl \
+ $(DESIGNDATA)/restrictions.csv \
+ icalrestriction.c.in
+
+icalrestriction.c: $(RESTRICTIONDEPS)
+ $(PERL) $(ICALSCRIPTS)/mkrestrictiontable.pl -i $(srcdir)/icalrestriction.c.in \
+ $(DESIGNDATA)/restrictions.csv > icalrestriction.c
+
+# values
+
+VALUEDEPS = \
+ $(ICALSCRIPTS)/mkderivedvalues.pl \
+ $(DESIGNDATA)/value-types.csv \
+ icalderivedvalue.c.in \
+ icalderivedvalue.h.in
+
+icalderivedvalue.h: $(VALUEDEPS)
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedvalues.pl \
+ -i $(srcdir)/icalderivedvalue.h.in -h $(DESIGNDATA)/value-types.csv > icalderivedvalue.h
+
+icalderivedvalue.c: $(VALUEDEPS) icalderivedvalue.h
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedvalues.pl \
+ -i $(srcdir)/icalderivedvalue.c.in -c $(DESIGNDATA)/value-types.csv > icalderivedvalue.c
+
+
+
+# housekeeping
+CONFIG_CLEAN_FILES = y.output
+
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = \
+ icalderivedparameter.c.in \
+ icalderivedparameter.h.in \
+ icalderivedproperty.c.in \
+ icalderivedproperty.h.in \
+ icalrestriction.c.in \
+ icalderivedvalue.c.in \
+ icalderivedvalue.h.in \
+ icalversion.h.in \
+ icallexer.c \
+ icalyacc.c
+
+AM_CPPFLAGS = -DNDEBUG $(GLIB_CFLAGS)
diff --git a/src/plugins/vcalendar/libical/libical/Makefile.in b/src/plugins/vcalendar/libical/libical/Makefile.in
@@ -0,0 +1,923 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#======================================================================
+# FILE: Makefile.am
+# CREATOR: eric
+#
+# $Id$
+#
+#
+# (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of either:
+#
+# The LGPL as published by the Free Software Foundation, version
+# 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+#
+# Or:
+#
+# The Mozilla Public License Version 1.0. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# The original code is icalcomponent.c
+#
+#======================================================================
+
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/plugins/vcalendar/libical/libical
+DIST_COMMON = $(libicalinclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/icalversion.h.in icallexer.c \
+ icalyacc.c icalyacc.h
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/check-type.m4 \
+ $(top_srcdir)/m4/gnupg-check-typedef.m4 \
+ $(top_srcdir)/m4/gnupg.m4 $(top_srcdir)/m4/gpgme.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/spamassassin.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h \
+ $(top_builddir)/claws-features.h
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libical_la_LIBADD =
+am_libical_la_OBJECTS = icalattendee.lo icalcomponent.lo icalenums.lo \
+ icalerror.lo icallexer.lo icalmemory.lo icalmime.lo \
+ icalparameter.lo icalderivedparameter.lo icalparser.lo \
+ icalderivedproperty.lo icalproperty.lo icalrecur.lo \
+ icalrestriction.lo icaltime.lo icalduration.lo icalperiod.lo \
+ icaltypes.lo icalvalue.lo icalderivedvalue.lo icalyacc.lo \
+ pvl.lo sspm.lo vsnprintf.lo
+libical_la_OBJECTS = $(am_libical_la_OBJECTS)
+libical_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libical_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
+LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
+YLWRAP = $(top_srcdir)/config/ylwrap
+@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
+YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
+SOURCES = $(libical_la_SOURCES)
+DIST_SOURCES = $(libical_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libicalincludedir)"
+HEADERS = $(libicalinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPFACE_LIBS = @COMPFACE_LIBS@
+CONIC_CFLAGS = @CONIC_CFLAGS@
+CONIC_LIBS = @CONIC_LIBS@
+CONTACTS_CFLAGS = @CONTACTS_CFLAGS@
+CONTACTS_LIBS = @CONTACTS_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPT_LIBS = @CRYPT_LIBS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOCBOOK2HTML = @DOCBOOK2HTML@
+DOCBOOK2PDF = @DOCBOOK2PDF@
+DOCBOOK2PS = @DOCBOOK2PS@
+DOCBOOK2TXT = @DOCBOOK2TXT@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCHANT_CFLAGS = @ENCHANT_CFLAGS@
+ENCHANT_LIBS = @ENCHANT_LIBS@
+EXEEXT = @EXEEXT@
+EXTRA_VERSION = @EXTRA_VERSION@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNOME2_CFLAGS = @GNOME2_CFLAGS@
+GNOME2_LIBS = @GNOME2_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GPGME_CFLAGS = @GPGME_CFLAGS@
+GPGME_CONFIG = @GPGME_CONFIG@
+GPGME_LIBS = @GPGME_LIBS@
+GREP = @GREP@
+GTKPRINTUNIX_CFLAGS = @GTKPRINTUNIX_CFLAGS@
+GTKPRINTUNIX_LIBS = @GTKPRINTUNIX_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JPILOT_LIBS = @JPILOT_LIBS@
+LD = @LD@
+LDAP_LIBS = @LDAP_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = lex.ical_yy
+LIBETPAN_FLAGS = @LIBETPAN_FLAGS@
+LIBETPAN_LIBS = @LIBETPAN_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBRESOLV = @LIBRESOLV@
+LIBS = @LIBS@
+LIBSOUP_GNOME_CFLAGS = @LIBSOUP_GNOME_CFLAGS@
+LIBSOUP_GNOME_LIBS = @LIBSOUP_GNOME_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAEMO_CFLAGS = @MAEMO_CFLAGS@
+MAEMO_LIBS = @MAEMO_LIBS@
+MAINT = @MAINT@
+MAJOR_VERSION = @MAJOR_VERSION@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MICRO_VERSION = @MICRO_VERSION@
+MINOR_VERSION = @MINOR_VERSION@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETWORKMANAGER_SUPPORT_CFLAGS = @NETWORKMANAGER_SUPPORT_CFLAGS@
+NETWORKMANAGER_SUPPORT_LIBS = @NETWORKMANAGER_SUPPORT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PASSCRYPT_KEY = @PASSCRYPT_KEY@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SM_LIBS = @SM_LIBS@
+STARTUP_NOTIFICATION_CFLAGS = @STARTUP_NOTIFICATION_CFLAGS@
+STARTUP_NOTIFICATION_LIBS = @STARTUP_NOTIFICATION_LIBS@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VERSION = @VERSION@
+WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
+WEBKIT_LIBS = @WEBKIT_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YACC = @YACC@
+YFLAGS = -d -v -t -pical_yy
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_cv_enable_crash_dialog = @ac_cv_enable_crash_dialog@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gnomedatadir = @gnomedatadir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libetpanconfig = @libetpanconfig@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+manualdir = @manualdir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+DESIGNDATA = $(top_srcdir)/src/plugins/vcalendar/libical/design-data
+ICALSCRIPTS = $(top_srcdir)/src/plugins/vcalendar/libical/scripts
+noinst_LTLIBRARIES = libical.la
+LFLAGS = -Pical_yy
+INCLUDES = \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(srcdir) \
+ -I$(top_srcdir)/src/plugins/vcalendar/libical \
+ -I$(top_srcdir)/src/plugins/vcalendar/libical/libical
+
+libical_la_LDFLAGS = -version-info 0:0:0
+libical_la_SOURCES = \
+ icalattendee.h \
+ icalattendee.c \
+ icalcomponent.c \
+ icalcomponent.h \
+ icalenums.c \
+ icalenums.h \
+ icalerror.c \
+ icalerror.h \
+ icallexer.l \
+ icalmemory.c \
+ icalmemory.h \
+ icalmime.c \
+ icalmime.h \
+ icalparameter.c \
+ icalparameter.h \
+ icalparameterimpl.h \
+ icalderivedparameter.c \
+ icalderivedparameter.h \
+ icalparser.c \
+ icalparser.h \
+ icalderivedproperty.c \
+ icalderivedproperty.h \
+ icalproperty.c \
+ icalproperty.h \
+ icalrecur.c \
+ icalrecur.h \
+ icalrestriction.c \
+ icalrestriction.h \
+ icaltime.c \
+ icaltime.h \
+ icalduration.h \
+ icalduration.c \
+ icalperiod.h \
+ icalperiod.c \
+ icaltypes.c \
+ icaltypes.h \
+ icalvalue.c \
+ icalvalue.h \
+ icalvalueimpl.h \
+ icalderivedvalue.c \
+ icalderivedvalue.h \
+ icalyacc.h \
+ icalyacc.y \
+ pvl.c \
+ pvl.h \
+ sspm.c \
+ sspm.h \
+ vsnprintf.c \
+ icallangbind.h
+
+libicalincludedir = $(includedir)/claws-mail/plugins/@PACKAGE@
+libicalinclude_HEADERS = ical.h
+
+# ORDERING OF HEADERS IS SIGNIFICANT. Don't change this ordering. It
+# is required to make the combined header ical.h properly
+COMBINEDHEADERS = \
+ $(top_builddir)/src/plugins/vcalendar/libical/libical/icalversion.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icaltime.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalduration.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalperiod.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalenums.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icaltypes.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalrecur.h \
+ icalderivedvalue.h \
+ icalderivedparameter.h \
+ icalvalue.h \
+ icalparameter.h \
+ icalderivedproperty.h \
+ icalproperty.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalattendee.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/pvl.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalcomponent.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalparser.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalmemory.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalerror.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalrestriction.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/sspm.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icalmime.h \
+ $(top_srcdir)/src/plugins/vcalendar/libical/libical/icallangbind.h
+
+BUILT_SOURCES = \
+ ical.h \
+ icalderivedparameter.c \
+ icalderivedparameter.h \
+ icalderivedproperty.c \
+ icalderivedproperty.h \
+ icalrestriction.c \
+ icalderivedvalue.c \
+ icalderivedvalue.h
+
+
+# parameters
+PARAMETERDEPS = \
+ $(ICALSCRIPTS)/mkderivedparameters.pl \
+ $(DESIGNDATA)/parameters.csv \
+ icalderivedparameter.c.in \
+ icalderivedparameter.h.in
+
+
+# properties
+PROPERTYDEPS = \
+ $(ICALSCRIPTS)/mkderivedproperties.pl \
+ $(DESIGNDATA)/properties.csv \
+ $(DESIGNDATA)/value-types.csv \
+ icalderivedproperty.c.in \
+ icalderivedproperty.h.in
+
+
+# restrictions
+RESTRICTIONDEPS = \
+ $(ICALSCRIPTS)/mkrestrictiontable.pl \
+ $(DESIGNDATA)/restrictions.csv \
+ icalrestriction.c.in
+
+
+# values
+VALUEDEPS = \
+ $(ICALSCRIPTS)/mkderivedvalues.pl \
+ $(DESIGNDATA)/value-types.csv \
+ icalderivedvalue.c.in \
+ icalderivedvalue.h.in
+
+
+# housekeeping
+CONFIG_CLEAN_FILES = y.output
+CLEANFILES = $(BUILT_SOURCES)
+EXTRA_DIST = \
+ icalderivedparameter.c.in \
+ icalderivedparameter.h.in \
+ icalderivedproperty.c.in \
+ icalderivedproperty.h.in \
+ icalrestriction.c.in \
+ icalderivedvalue.c.in \
+ icalderivedvalue.h.in \
+ icalversion.h.in \
+ icallexer.c \
+ icalyacc.c
+
+AM_CPPFLAGS = -DNDEBUG $(GLIB_CFLAGS)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/libical/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/libical/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+icalversion.h: $(top_builddir)/config.status $(srcdir)/icalversion.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+icalyacc.h: icalyacc.c
+ @if test ! -f $@; then rm -f icalyacc.c; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) icalyacc.c; else :; fi
+libical.la: $(libical_la_OBJECTS) $(libical_la_DEPENDENCIES) $(EXTRA_libical_la_DEPENDENCIES)
+ $(libical_la_LINK) $(libical_la_OBJECTS) $(libical_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalattendee.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalcomponent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalderivedparameter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalderivedproperty.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalderivedvalue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalduration.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalenums.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalerror.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icallexer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalmemory.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalmime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalparameter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalparser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalperiod.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalproperty.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalrecur.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalrestriction.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icaltime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icaltypes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalvalue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icalyacc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pvl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sspm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vsnprintf.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+.l.c:
+ $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+ $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-libicalincludeHEADERS: $(libicalinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(libicalinclude_HEADERS)'; test -n "$(libicalincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libicalincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libicalincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libicalincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libicalincludedir)" || exit $$?; \
+ done
+
+uninstall-libicalincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libicalinclude_HEADERS)'; test -n "$(libicalincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libicalincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libicalincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f icallexer.c
+ -rm -f icalyacc.c
+ -rm -f icalyacc.h
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libicalincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libicalincludeHEADERS
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libicalincludeHEADERS install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-libicalincludeHEADERS
+
+
+ical.h: $(COMBINEDHEADERS)
+ cat $(COMBINEDHEADERS) \
+ | egrep -v "#include.*\"ical" \
+ | egrep -v "#include.*\"pvl\.h\"" > ical.h
+
+icallexer.c : icalyacc.h
+
+icalderivedparameter.h: $(PARAMETERDEPS)
+ $(PERL) -I $(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedparameters.pl -i $(srcdir)/icalderivedparameter.h.in -h $(DESIGNDATA)/parameters.csv > icalderivedparameter.h
+
+icalderivedparameter.c: $(PARAMETERDEPS) icalparameter.h
+ $(PERL) -I $(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedparameters.pl -i $(srcdir)/icalderivedparameter.c.in -c $(DESIGNDATA)/parameters.csv > icalderivedparameter.c
+
+icalderivedproperty.h: $(PROPERTYDEPS)
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedproperties.pl \
+ -i $(srcdir)/icalderivedproperty.h.in -h $(DESIGNDATA)/properties.csv\
+ ${DESIGNDATA}/value-types.csv > icalderivedproperty.h
+
+icalderivedproperty.c: $(PROPERTYDEPS) icalproperty.h
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedproperties.pl \
+ -i $(srcdir)/icalderivedproperty.c.in -c $(DESIGNDATA)/properties.csv \
+ ${DESIGNDATA}/value-types.csv > icalderivedproperty.c
+
+icalrestriction.c: $(RESTRICTIONDEPS)
+ $(PERL) $(ICALSCRIPTS)/mkrestrictiontable.pl -i $(srcdir)/icalrestriction.c.in \
+ $(DESIGNDATA)/restrictions.csv > icalrestriction.c
+
+icalderivedvalue.h: $(VALUEDEPS)
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedvalues.pl \
+ -i $(srcdir)/icalderivedvalue.h.in -h $(DESIGNDATA)/value-types.csv > icalderivedvalue.h
+
+icalderivedvalue.c: $(VALUEDEPS) icalderivedvalue.h
+ $(PERL) -I$(ICALSCRIPTS) $(ICALSCRIPTS)/mkderivedvalues.pl \
+ -i $(srcdir)/icalderivedvalue.c.in -c $(DESIGNDATA)/value-types.csv > icalderivedvalue.c
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/plugins/vcalendar/libical/libical/icalattendee.c b/src/plugins/vcalendar/libical/libical/icalattendee.c
@@ -0,0 +1,30 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalattendee.c
+ CREATOR: eric 08 Mar 01
+
+ $Id$
+ $Locker$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icaltypes.c
+
+ ======================================================================*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "icalattendee.h"
diff --git a/src/plugins/vcalendar/libical/libical/icalattendee.h b/src/plugins/vcalendar/libical/libical/icalattendee.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalattendee.h
+ CREATOR: eric 8 Mar 01
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icaltypes.h
+
+======================================================================*/
+
+#ifndef ICALATTENDEE_H
+#define ICALATTENDEE_H
+
+#include <time.h>
+#include "icalenums.h"
+#include "icaltime.h"
+#include "icalduration.h"
+#include "icalperiod.h"
+#include "icalderivedparameter.h"
+#include "icalderivedvalue.h"
+
+struct icalorganizertype {
+ const char* value;
+ const char* common_name;
+ const char* dir;
+ const char* sentby;
+ const char* language;
+
+};
+
+/* Create a copy of the given organizer. Libical will not own the
+ memory for the strings in the copy; the call must free them */
+struct icalorganizertype icalorganizertype_new_clone(struct icalorganizertype a);
+
+
+struct icalattendeetype {
+ const char* cuid; /* Cal user id, contents of the property value */
+ /*icalparameter_cutype cutype;*/
+ const char* member;
+ /*icalparameter_role role;*/
+ int rsvp;
+ const char* delto;
+ const char* delfrom;
+ const char* sentby;
+ const char* cn;
+ const char* dir;
+ const char* language;
+};
+
+/* Create a copy of the given attendee. Libical will not own the
+ memory for the strings in the copy; the call must free them */
+struct icalattendeetype icalattendeetype_new_clone(struct icalattendeetype a);
+
+
+#endif /* !ICALATTENDEE_H */
diff --git a/src/plugins/vcalendar/libical/libical/icalcomponent.c b/src/plugins/vcalendar/libical/libical/icalcomponent.c
@@ -0,0 +1,1500 @@
+/*======================================================================
+ FILE: icalcomponent.c
+ CREATOR: eric 28 April 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalcomponent.c
+
+======================================================================*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "icalcomponent.h"
+#include "pvl.h" /* "Pointer-to-void list" */
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "icalenums.h"
+#include "icaltime.h"
+#include "icalduration.h"
+#include "icalperiod.h"
+#include "icalparser.h"
+
+#include <string.h> /* for strcpy & memset */
+#include <stdlib.h> /* for malloc */
+#include <stdarg.h> /* for va_list, etc */
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h> /* for fprintf */
+
+#define MAX_TMP 1024
+
+struct icalcomponent_impl
+{
+ char id[5];
+ icalcomponent_kind kind;
+ char* x_name;
+ pvl_list properties;
+ pvl_elem property_iterator;
+ pvl_list components;
+ pvl_elem component_iterator;
+ icalcomponent* parent;
+};
+
+/* icalproperty functions that only components get to use */
+void icalproperty_set_parent(icalproperty* property,
+ icalcomponent* component);
+icalcomponent* icalproperty_get_parent(icalproperty* property);
+void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args);
+icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind);
+int icalcomponent_property_sorter(void *a, void *b);
+
+
+void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args)
+{
+ void* vp;
+
+ while((vp = va_arg(args, void*)) != 0) {
+
+ assert (icalcomponent_isa_component(vp) != 0 ||
+ icalproperty_isa_property(vp) != 0 ) ;
+
+ if (icalcomponent_isa_component(vp) != 0 ){
+
+ icalcomponent_add_component((icalcomponent*)impl,
+ (icalcomponent*)vp);
+
+ } else if (icalproperty_isa_property(vp) != 0 ){
+
+ icalcomponent_add_property((icalcomponent*)impl,
+ (icalproperty*)vp);
+ }
+ }
+}
+
+icalcomponent*
+icalcomponent_new_impl (icalcomponent_kind kind)
+{
+ struct icalcomponent_impl* comp;
+
+ if ( ( comp = (struct icalcomponent_impl*)
+ malloc(sizeof(struct icalcomponent_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ strcpy(comp->id,"comp");
+
+ comp->kind = kind;
+ comp->properties = pvl_newlist();
+ comp->property_iterator = 0;
+ comp->components = pvl_newlist();
+ comp->component_iterator = 0;
+ comp->x_name = 0;
+ comp->parent = 0;
+
+ return comp;
+}
+
+icalcomponent*
+icalcomponent_new (icalcomponent_kind kind)
+{
+ return (icalcomponent*)icalcomponent_new_impl(kind);
+}
+
+icalcomponent*
+icalcomponent_vanew (icalcomponent_kind kind, ...)
+{
+ va_list args;
+
+ struct icalcomponent_impl *impl = icalcomponent_new_impl(kind);
+
+ if (impl == 0){
+ return 0;
+ }
+
+ va_start(args,kind);
+ icalcomponent_add_children(impl, args);
+ va_end(args);
+
+ return (icalcomponent*) impl;
+}
+
+icalcomponent* icalcomponent_new_from_string(char* str)
+{
+ return icalparser_parse_string(str);
+}
+
+icalcomponent* icalcomponent_new_clone(icalcomponent* component)
+{
+ struct icalcomponent_impl *old = (struct icalcomponent_impl*)component;
+ struct icalcomponent_impl *new;
+ icalproperty *p;
+ icalcomponent *c;
+ pvl_elem itr;
+
+ icalerror_check_arg_rz( (component!=0), "component");
+
+ new = icalcomponent_new_impl(old->kind);
+
+ if (new == 0){
+ return 0;
+ }
+
+
+ for( itr = pvl_head(old->properties);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ p = (icalproperty*)pvl_data(itr);
+ icalcomponent_add_property(new,icalproperty_new_clone(p));
+ }
+
+
+ for( itr = pvl_head(old->components);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ c = (icalcomponent*)pvl_data(itr);
+ icalcomponent_add_component(new,icalcomponent_new_clone(c));
+ }
+
+ return new;
+
+}
+
+
+void
+icalcomponent_free (icalcomponent* component)
+{
+ icalproperty* prop;
+ icalcomponent* comp;
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+
+ icalerror_check_arg_rv( (component!=0), "component");
+
+#ifdef ICAL_FREE_ON_LIST_IS_ERROR
+ icalerror_assert( (c->parent ==0),"Tried to free a component that is still attached to a parent component");
+#else
+ if(c->parent != 0){
+ return;
+ }
+#endif
+
+ if(component != 0 ){
+
+ while( (prop=pvl_pop(c->properties)) != 0){
+ assert(prop != 0);
+ icalproperty_set_parent(prop,0);
+ icalproperty_free(prop);
+ }
+
+ pvl_free(c->properties);
+
+ while( (comp=pvl_data(pvl_head(c->components))) != 0){
+ assert(comp!=0);
+ icalcomponent_remove_component(component,comp);
+ icalcomponent_free(comp);
+ }
+
+ pvl_free(c->components);
+
+ if (c->x_name != 0) {
+ free(c->x_name);
+ }
+
+ c->kind = ICAL_NO_COMPONENT;
+ c->properties = 0;
+ c->property_iterator = 0;
+ c->components = 0;
+ c->component_iterator = 0;
+ c->x_name = 0;
+ c->id[0] = 'X';
+
+ free(c);
+ }
+}
+
+char*
+icalcomponent_as_ical_string (icalcomponent* component)
+{
+ char* buf, *out_buf;
+ char* tmp_buf;
+ size_t buf_size = 1024;
+ char* buf_ptr = 0;
+ pvl_elem itr;
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
+
+#ifdef ICAL_UNIX_NEWLINE
+ char newline[] = "\n";
+#else
+ char newline[] = "\r\n";
+#endif
+
+ icalcomponent *c;
+ icalproperty *p;
+ icalcomponent_kind kind = icalcomponent_isa(component);
+
+ const char* kind_string;
+
+ buf = icalmemory_new_buffer(buf_size);
+ buf_ptr = buf;
+
+ icalerror_check_arg_rz( (component!=0), "component");
+ icalerror_check_arg_rz( (kind!=ICAL_NO_COMPONENT), "component kind is ICAL_NO_COMPONENT");
+
+ kind_string = icalenum_component_kind_to_string(kind);
+
+ icalerror_check_arg_rz( (kind_string!=0),"Unknown kind of component");
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+
+
+ for( itr = pvl_head(impl->properties);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ p = (icalproperty*)pvl_data(itr);
+
+ icalerror_assert((p!=0),"Got a null property");
+ tmp_buf = icalproperty_as_ical_string(p);
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
+ }
+
+
+ for( itr = pvl_head(impl->components);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ c = (icalcomponent*)pvl_data(itr);
+
+ tmp_buf = icalcomponent_as_ical_string(c);
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
+
+ }
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size,
+ icalenum_component_kind_to_string(kind));
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+ out_buf = icalmemory_tmp_copy(buf);
+ free(buf);
+
+ return out_buf;
+}
+
+
+int
+icalcomponent_is_valid (icalcomponent* component)
+{
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
+
+
+ if ( (strcmp(impl->id,"comp") == 0) &&
+ impl->kind != ICAL_NO_COMPONENT){
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+
+icalcomponent_kind
+icalcomponent_isa (icalcomponent* component)
+{
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
+ icalerror_check_arg_rz( (component!=0), "component");
+
+ if(component != 0)
+ {
+ return impl->kind;
+ }
+
+ return ICAL_NO_COMPONENT;
+}
+
+
+int
+icalcomponent_isa_component (void* component)
+{
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
+
+ icalerror_check_arg_rz( (component!=0), "component");
+
+ if (strcmp(impl->id,"comp") == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+int icalcomponent_property_sorter(void *a, void *b)
+{
+ icalproperty_kind kinda, kindb;
+ const char *ksa, *ksb;
+
+ kinda = icalproperty_isa((icalproperty*)a);
+ kindb = icalproperty_isa((icalproperty*)b);
+
+ ksa = icalenum_property_kind_to_string(kinda);
+ ksb = icalenum_property_kind_to_string(kindb);
+
+ return strcmp(ksa,ksb);
+}
+
+
+void
+icalcomponent_add_property (icalcomponent* component, icalproperty* property)
+{
+ struct icalcomponent_impl *impl;
+
+ icalerror_check_arg_rv( (component!=0), "component");
+ icalerror_check_arg_rv( (property!=0), "property");
+
+ impl = (struct icalcomponent_impl*)component;
+
+ icalerror_assert( (!icalproperty_get_parent(property)),"The property has already been added to a component. Remove the property with icalcomponent_remove_property before calling icalcomponent_add_property");
+
+ icalproperty_set_parent(property,component);
+
+#ifdef ICAL_INSERT_ORDERED
+ pvl_insert_ordered(impl->properties,
+ icalcomponent_property_sorter,property);
+#else
+ pvl_push(impl->properties,property);
+#endif
+
+}
+
+
+void
+icalcomponent_remove_property (icalcomponent* component, icalproperty* property)
+{
+ struct icalcomponent_impl *impl;
+ pvl_elem itr, next_itr;
+ struct icalproperty_impl *pimpl;
+
+ icalerror_check_arg_rv( (component!=0), "component");
+ icalerror_check_arg_rv( (property!=0), "property");
+
+ impl = (struct icalcomponent_impl*)component;
+
+ pimpl = (struct icalproperty_impl*)property;
+
+ icalerror_assert( (icalproperty_get_parent(property)),"The property is not a member of a component");
+
+
+ for( itr = pvl_head(impl->properties);
+ itr != 0;
+ itr = next_itr)
+ {
+ next_itr = pvl_next(itr);
+
+ if( pvl_data(itr) == (void*)property ){
+
+ if (impl->property_iterator == itr){
+ impl->property_iterator = pvl_next(itr);
+ }
+
+ pvl_remove( impl->properties, itr);
+ icalproperty_set_parent(property,0);
+ }
+ }
+}
+
+int
+icalcomponent_count_properties (icalcomponent* component,
+ icalproperty_kind kind)
+{
+ int count=0;
+ pvl_elem itr;
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
+
+ icalerror_check_arg_rz( (component!=0), "component");
+
+ for( itr = pvl_head(impl->properties);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ if(kind == icalproperty_isa((icalproperty*)pvl_data(itr)) ||
+ kind == ICAL_ANY_PROPERTY){
+ count++;
+ }
+ }
+
+
+ return count;
+
+}
+
+icalproperty* icalcomponent_get_current_property (icalcomponent* component)
+{
+
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+ icalerror_check_arg_rz( (component!=0),"component");
+
+ if ((c->property_iterator==0)){
+ return 0;
+ }
+
+ return (icalproperty*) pvl_data(c->property_iterator);
+
+}
+
+icalproperty*
+icalcomponent_get_first_property (icalcomponent* component, icalproperty_kind kind)
+{
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+ icalerror_check_arg_rz( (component!=0),"component");
+
+ for( c->property_iterator = pvl_head(c->properties);
+ c->property_iterator != 0;
+ c->property_iterator = pvl_next(c->property_iterator)) {
+
+ icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
+
+ if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
+
+ return p;
+ }
+ }
+ return 0;
+}
+
+icalproperty*
+icalcomponent_get_next_property (icalcomponent* component, icalproperty_kind kind)
+{
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+ icalerror_check_arg_rz( (component!=0),"component");
+
+ if (c->property_iterator == 0){
+ return 0;
+ }
+
+ for( c->property_iterator = pvl_next(c->property_iterator);
+ c->property_iterator != 0;
+ c->property_iterator = pvl_next(c->property_iterator)) {
+
+ icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
+
+ if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
+
+ return p;
+ }
+ }
+
+ return 0;
+}
+
+
+icalproperty**
+icalcomponent_get_properties (icalcomponent* component, icalproperty_kind kind);
+
+
+void
+icalcomponent_add_component (icalcomponent* parent, icalcomponent* child)
+{
+ struct icalcomponent_impl *impl, *cimpl;
+
+ icalerror_check_arg_rv( (parent!=0), "parent");
+ icalerror_check_arg_rv( (child!=0), "child");
+
+ impl = (struct icalcomponent_impl*)parent;
+ cimpl = (struct icalcomponent_impl*)child;
+
+ icalerror_assert( (cimpl->parent ==0),"The child component has already been added to a parent component. Remove the component with icalcomponent_remove_component before calling icalcomponent_add_component");
+
+ cimpl->parent = parent;
+
+ pvl_push(impl->components,child);
+}
+
+
+void
+icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child)
+{
+ struct icalcomponent_impl *impl,*cimpl;
+ pvl_elem itr, next_itr;
+
+ icalerror_check_arg_rv( (parent!=0), "parent");
+ icalerror_check_arg_rv( (child!=0), "child");
+
+ impl = (struct icalcomponent_impl*)parent;
+ cimpl = (struct icalcomponent_impl*)child;
+
+ for( itr = pvl_head(impl->components);
+ itr != 0;
+ itr = next_itr)
+ {
+ next_itr = pvl_next(itr);
+
+ if( pvl_data(itr) == (void*)child ){
+
+ if (impl->component_iterator == itr){
+ /* Don't let the current iterator become invalid */
+
+ /* HACK. The semantics for this are troubling. */
+ impl->component_iterator =
+ pvl_next(impl->component_iterator);
+
+ }
+ pvl_remove( impl->components, itr);
+ cimpl->parent = 0;
+ break;
+ }
+ }
+}
+
+
+int
+icalcomponent_count_components (icalcomponent* component,
+ icalcomponent_kind kind)
+{
+ int count=0;
+ pvl_elem itr;
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
+
+ icalerror_check_arg_rz( (component!=0), "component");
+
+ for( itr = pvl_head(impl->components);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ if(kind == icalcomponent_isa((icalcomponent*)pvl_data(itr)) ||
+ kind == ICAL_ANY_COMPONENT){
+ count++;
+ }
+ }
+
+ return count;
+}
+
+icalcomponent*
+icalcomponent_get_current_component(icalcomponent* component)
+{
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+
+ icalerror_check_arg_rz( (component!=0),"component");
+
+ if (c->component_iterator == 0){
+ return 0;
+ }
+
+ return (icalcomponent*) pvl_data(c->component_iterator);
+}
+
+icalcomponent*
+icalcomponent_get_first_component (icalcomponent* component,
+ icalcomponent_kind kind)
+{
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+
+ icalerror_check_arg_rz( (component!=0),"component");
+
+ for( c->component_iterator = pvl_head(c->components);
+ c->component_iterator != 0;
+ c->component_iterator = pvl_next(c->component_iterator)) {
+
+ icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
+
+ if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
+
+ return p;
+ }
+ }
+
+ return 0;
+}
+
+
+icalcomponent*
+icalcomponent_get_next_component (icalcomponent* component, icalcomponent_kind kind)
+{
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+
+ icalerror_check_arg_rz( (component!=0),"component");
+
+ if (c->component_iterator == 0){
+ return 0;
+ }
+
+ for( c->component_iterator = pvl_next(c->component_iterator);
+ c->component_iterator != 0;
+ c->component_iterator = pvl_next(c->component_iterator)) {
+
+ icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
+
+ if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
+
+ return p;
+ }
+ }
+
+ return 0;
+}
+
+icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c)
+{
+ icalcomponent *comp;
+
+ for(comp = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT);
+ comp != 0;
+ comp = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){
+
+ icalcomponent_kind kind = icalcomponent_isa(comp);
+
+ if(kind == ICAL_VEVENT_COMPONENT ||
+ kind == ICAL_VTODO_COMPONENT ||
+ kind == ICAL_VJOURNAL_COMPONENT ){
+ return comp;
+ }
+ }
+ return 0;
+}
+
+time_t icalcomponent_convert_time(icalproperty *p)
+{
+ struct icaltimetype sict;
+ time_t convt;
+ icalproperty *tzp;
+
+
+ /* Though it says _dtstart, it will work for dtend too */
+ sict = icalproperty_get_dtstart(p);
+
+ tzp = icalproperty_get_first_parameter(p,ICAL_TZID_PARAMETER);
+
+ if (sict.is_utc == 1 && tzp != 0){
+ icalerror_warn("icalcomponent_get_span: component has a UTC DTSTART with a timezone specified ");
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ if(sict.is_utc == 1){
+#ifdef TEST_CONVERT_TIME
+ gchar buft[512];
+#endif
+ /* _as_timet will use gmtime() to do the conversion */
+ convt = icaltime_as_timet(sict);
+
+#ifdef TEST_CONVERT_TIME
+ printf("convert time: use as_timet:\n %s\n %s",
+ icalproperty_as_ical_string(p), ctime_r(&convt,buft));
+#endif
+
+ } else if (sict.is_utc == 0 && tzp == 0 ) {
+ time_t offset;
+#ifdef TEST_CONVERT_TIME
+ gchar buft[512];
+#endif
+
+ /* _as_timet will use localtime() to do the conversion */
+ convt = icaltime_as_timet(sict);
+ offset = icaltime_utc_offset(sict,0);
+ convt += offset;
+
+#ifdef TEST_CONVERT_TIME
+ printf("convert time: use as_timet and adjust:\n %s\n %s",
+ icalproperty_as_ical_string(p), ctime_r(&convt,buft));
+#endif
+ } else {
+#ifdef TEST_CONVERT_TIME
+ gchar buft[512];
+#endif
+ /* Convert the time to UTC for the named timezone*/
+ const char* timezone = icalparameter_get_tzid(tzp);
+ convt = icaltime_as_timet(icaltime_as_utc(sict,timezone));
+
+#ifdef TEST_CONVERT_TIME
+ printf("convert time: use _as_utc:\n %s\n %s",
+ icalproperty_as_ical_string(p), ctime_r(&convt,buft));
+#endif
+ }
+
+ return convt;
+}
+struct icaltime_span icalcomponent_get_span(icalcomponent* comp)
+{
+ icalcomponent *inner;
+ icalproperty *p, *duration;
+ icalcomponent_kind kind;
+ struct icaltime_span span;
+ struct icaltimetype start;
+#ifdef TEST_CONVERT_TIME
+ gchar buft[512];
+#endif
+
+ span.start = 0;
+ span.end = 0;
+ span.is_busy= 1;
+
+ /* initial Error checking */
+
+/* icalerror_check_arg_rz( (comp!=0),"comp");*/
+
+ kind = icalcomponent_isa(comp);
+
+ if(kind == ICAL_VCALENDAR_COMPONENT){
+ inner = icalcomponent_get_first_real_component(comp);
+
+ /* Maybe there is a VTIMEZONE in there */
+ if (inner == 0){
+ inner = icalcomponent_get_first_component(comp,
+ ICAL_VTIMEZONE_COMPONENT);
+ }
+
+ } else {
+ inner = comp;
+ }
+
+ if (inner == 0){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
+ return span;
+ }
+
+ kind = icalcomponent_isa(inner);
+
+ if( !( kind == ICAL_VEVENT_COMPONENT ||
+ kind == ICAL_VJOURNAL_COMPONENT ||
+ kind == ICAL_VTODO_COMPONENT ||
+ kind == ICAL_VFREEBUSY_COMPONENT )) {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
+ return span;
+
+ }
+
+
+
+ /* Get to work. starting with DTSTART */
+
+ p = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
+
+ if (p ==0 ) {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ /*icalerror_warn("icalcomponent_get_span: component has no DTSTART time");*/
+ return span;
+ }
+
+
+ start = icalproperty_get_dtstart(p);
+
+ icalerror_clear_errno();
+
+ span.start = icalcomponent_convert_time(p);
+
+#ifdef TEST_CONVERT_TIME
+ printf("convert time:\n %s %s",
+ icalproperty_as_ical_string(p), ctime_r(&span.start, buft));
+#endif
+
+ if(icalerrno != ICAL_NO_ERROR){
+ span.start = 0;
+ return span;
+ }
+
+ /* The end time could be specified as either a DTEND or a DURATION */
+ p = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
+ duration = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
+
+ if (p==0 && duration == 0 && start.is_date != 1) {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ /*icalerror_warn("icalcomponent_get_span: component has neither DTEND nor DURATION time");*/
+ span.start = 0;
+ return span;
+ }
+
+ if (p!=0){
+ span.end = icalcomponent_convert_time(p);
+ } else if (start.is_date == 1) {
+ /* Duration is all day */
+ span.end = span.start + 60*60*24;
+ } else {
+ /* Use the duration */
+ struct icaldurationtype dur;
+ time_t durt;
+
+
+ dur = icalproperty_get_duration(duration);
+
+ durt = icaldurationtype_as_int(dur);
+ span.end = span.start+durt;
+ }
+
+ return span;
+
+}
+
+
+int icalcomponent_count_errors(icalcomponent* component)
+{
+ int errors = 0;
+ icalproperty *p;
+ icalcomponent *c;
+ pvl_elem itr;
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
+
+ for( itr = pvl_head(impl->properties);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ p = (icalproperty*)pvl_data(itr);
+
+ if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
+ {
+ errors++;
+ }
+ }
+
+
+ for( itr = pvl_head(impl->components);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ c = (icalcomponent*)pvl_data(itr);
+
+ errors += icalcomponent_count_errors(c);
+
+ }
+
+ return errors;
+}
+
+
+void icalcomponent_strip_errors(icalcomponent* component)
+{
+ icalproperty *p;
+ icalcomponent *c;
+ pvl_elem itr, next_itr;
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
+
+ for( itr = pvl_head(impl->properties);
+ itr != 0;
+ itr = next_itr)
+ {
+ p = (icalproperty*)pvl_data(itr);
+ next_itr = pvl_next(itr);
+
+ if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
+ {
+ icalcomponent_remove_property(component,p);
+ }
+ }
+
+ for( itr = pvl_head(impl->components);
+ itr != 0;
+ itr = pvl_next(itr))
+ {
+ c = (icalcomponent*)pvl_data(itr);
+ icalcomponent_strip_errors(c);
+ }
+}
+
+/* Hack. This will change the state of the iterators */
+void icalcomponent_convert_errors(icalcomponent* component)
+{
+ icalproperty *p, *next_p;
+ icalcomponent *c;
+
+ for(p = icalcomponent_get_first_property(component,ICAL_ANY_PROPERTY);
+ p != 0;
+ p = next_p){
+
+ next_p = icalcomponent_get_next_property(component,ICAL_ANY_PROPERTY);
+
+ if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
+ {
+ struct icalreqstattype rst;
+ icalparameter *param = icalproperty_get_first_parameter
+ (p,ICAL_XLICERRORTYPE_PARAMETER);
+
+ rst.code = ICAL_UNKNOWN_STATUS;
+ rst.desc = 0;
+
+ switch(icalparameter_get_xlicerrortype(param)){
+
+ case ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR: {
+ rst.code = ICAL_3_2_INVPARAM_STATUS;
+ break;
+ }
+ case ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR: {
+ rst.code = ICAL_3_3_INVPARAMVAL_STATUS;
+ break;
+ }
+ case ICAL_XLICERRORTYPE_PROPERTYPARSEERROR: {
+ rst.code = ICAL_3_0_INVPROPNAME_STATUS;
+ break;
+ }
+ case ICAL_XLICERRORTYPE_VALUEPARSEERROR: {
+ rst.code = ICAL_3_1_INVPROPVAL_STATUS;
+ break;
+ }
+ case ICAL_XLICERRORTYPE_COMPONENTPARSEERROR: {
+ rst.code = ICAL_3_4_INVCOMP_STATUS;
+ break;
+ }
+
+ default: {
+ }
+ }
+ if (rst.code != ICAL_UNKNOWN_STATUS){
+
+ rst.debug = icalproperty_get_xlicerror(p);
+ icalcomponent_add_property(component,
+ icalproperty_new_requeststatus(
+ icalreqstattype_as_string(rst)
+ )
+ );
+
+ icalcomponent_remove_property(component,p);
+ }
+ }
+ }
+
+ for(c = icalcomponent_get_first_component(component,ICAL_ANY_COMPONENT);
+ c != 0;
+ c = icalcomponent_get_next_component(component,ICAL_ANY_COMPONENT)){
+
+ icalcomponent_convert_errors(c);
+ }
+}
+
+
+icalcomponent* icalcomponent_get_parent(icalcomponent* component)
+{
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+
+ return c->parent;
+}
+
+void icalcomponent_set_parent(icalcomponent* component, icalcomponent* parent)
+{
+ struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
+
+ c->parent = parent;
+}
+
+icalcompiter icalcompiter_null = {ICAL_NO_COMPONENT,0};
+
+
+struct icalcomponent_kind_map {
+ icalcomponent_kind kind;
+ char name[20];
+};
+
+
+
+static struct icalcomponent_kind_map component_map[] =
+{
+ { ICAL_VEVENT_COMPONENT, "VEVENT" },
+ { ICAL_VTODO_COMPONENT, "VTODO" },
+ { ICAL_VJOURNAL_COMPONENT, "VJOURNAL" },
+ { ICAL_VCALENDAR_COMPONENT, "VCALENDAR" },
+ { ICAL_VFREEBUSY_COMPONENT, "VFREEBUSY" },
+ { ICAL_VTIMEZONE_COMPONENT, "VTIMEZONE" },
+ { ICAL_VALARM_COMPONENT, "VALARM" },
+ { ICAL_XSTANDARD_COMPONENT, "STANDARD" }, /*These are part of RFC2445 */
+ { ICAL_XDAYLIGHT_COMPONENT, "DAYLIGHT" }, /*but are not really components*/
+ { ICAL_X_COMPONENT, "X" },
+ { ICAL_VSCHEDULE_COMPONENT, "SCHEDULE" },
+
+ /* CAP components */
+ { ICAL_VQUERY_COMPONENT, "VQUERY" },
+ { ICAL_VCAR_COMPONENT, "VCAR" },
+ { ICAL_VCOMMAND_COMPONENT, "VCOMMAND" },
+
+ /* libical private components */
+ { ICAL_XLICINVALID_COMPONENT, "X-LIC-UNKNOWN" },
+ { ICAL_XLICMIMEPART_COMPONENT, "X-LIC-MIME-PART" },
+ { ICAL_ANY_COMPONENT, "ANY" },
+ { ICAL_XROOT_COMPONENT, "XROOT" },
+
+ /* End of list */
+ { ICAL_NO_COMPONENT, "" },
+};
+
+
+
+const char* icalcomponent_kind_to_string(icalcomponent_kind kind)
+{
+ int i;
+
+ for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
+ if (component_map[i].kind == kind) {
+ return component_map[i].name;
+ }
+ }
+
+ return 0;
+
+}
+
+icalcomponent_kind icalcomponent_string_to_kind(const char* string)
+{
+ int i;
+
+ if (string ==0 ) {
+ return ICAL_NO_COMPONENT;
+ }
+
+ for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
+ if (strcmp(component_map[i].name, string) == 0) {
+ return component_map[i].kind;
+ }
+ }
+
+ return ICAL_NO_COMPONENT;
+}
+
+
+
+icalcompiter
+icalcomponent_begin_component(icalcomponent* component,icalcomponent_kind kind)
+{
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
+ icalcompiter itr;
+ pvl_elem i;
+
+ itr.kind = kind;
+
+ icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
+
+ for( i = pvl_head(impl->components); i != 0; i = pvl_next(itr.iter)) {
+
+ icalcomponent *c = (icalcomponent*) pvl_data(i);
+
+ if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
+
+ itr.iter = i;
+
+ return itr;
+ }
+ }
+
+ return icalcompiter_null;
+}
+
+icalcompiter
+icalcomponent_end_component(icalcomponent* component,icalcomponent_kind kind)
+{
+ struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
+ icalcompiter itr;
+ pvl_elem i;
+
+ itr.kind = kind;
+
+ icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
+
+ for( i = pvl_tail(impl->components); i != 0; i = pvl_prior(i)) {
+
+ icalcomponent *c = (icalcomponent*) pvl_data(i);
+
+ if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
+
+ itr.iter = pvl_next(i);
+
+ return itr;
+ }
+ }
+
+ return icalcompiter_null;;
+}
+
+
+icalcomponent* icalcompiter_next(icalcompiter* i)
+{
+ if (i->iter == 0){
+ return 0;
+ }
+
+ icalerror_check_arg_rz( (i!=0),"i");
+
+ for( i->iter = pvl_next(i->iter);
+ i->iter != 0;
+ i->iter = pvl_next(i->iter)) {
+
+ icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
+
+ if (icalcomponent_isa(c) == i->kind
+ || i->kind == ICAL_ANY_COMPONENT) {
+
+ return icalcompiter_deref(i);;
+ }
+ }
+
+ return 0;
+
+}
+
+icalcomponent* icalcompiter_prior(icalcompiter* i)
+{
+ if (i->iter == 0){
+ return 0;
+ }
+
+ for( i->iter = pvl_prior(i->iter);
+ i->iter != 0;
+ i->iter = pvl_prior(i->iter)) {
+
+ icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
+
+ if (icalcomponent_isa(c) == i->kind
+ || i->kind == ICAL_ANY_COMPONENT) {
+
+ return icalcompiter_deref(i);;
+ }
+ }
+
+ return 0;
+
+}
+icalcomponent* icalcompiter_deref(icalcompiter* i)
+{
+ if(i->iter ==0){
+ return 0;
+ }
+
+ return pvl_data(i->iter);
+}
+
+icalcomponent* icalcomponent_get_inner(icalcomponent* comp)
+{
+ if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){
+ return icalcomponent_get_first_real_component(comp);
+ } else {
+ return comp;
+ }
+}
+
+
+void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v)
+{
+
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+ icalproperty *prop
+ = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
+
+
+ if (prop == 0){
+ prop = icalproperty_new_dtstart(v);
+ icalcomponent_add_property(inner, prop);
+ }
+
+ icalproperty_set_dtstart(prop,v);
+
+}
+
+
+struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+ icalproperty *prop
+ = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY);
+
+ if (prop == 0){
+ return icaltime_null_time();
+ }
+
+ return icalproperty_get_dtstart(prop);
+}
+
+
+struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+
+ icalproperty *end_prop
+ = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
+
+ icalproperty *dur_prop
+ = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
+
+
+ if( end_prop == 0 && dur_prop == 0){
+ return icaltime_null_time();
+ } else if ( end_prop != 0) {
+ return icalproperty_get_dtend(end_prop);
+ } else if ( dur_prop != 0) {
+
+ struct icaltimetype start =
+ icalcomponent_get_dtstart(inner);
+ struct icaldurationtype duration =
+ icalproperty_get_duration(dur_prop);
+
+ struct icaltimetype end = icaltime_add(start,duration);
+
+ return end;
+
+ } else {
+ /* Error, both duration and dtend have been specified */
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return icaltime_null_time();
+
+ }
+
+}
+
+
+void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+
+ icalproperty *end_prop
+ = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
+
+ icalproperty *dur_prop
+ = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
+
+
+ if( end_prop == 0 && dur_prop == 0){
+ end_prop = icalproperty_new_dtend(v);
+ icalcomponent_add_property(inner,end_prop);
+ } else if ( end_prop != 0) {
+ icalproperty_set_dtend(end_prop,v);
+ } else if ( dur_prop != 0) {
+ struct icaltimetype start =
+ icalcomponent_get_dtstart(inner);
+
+ struct icaltimetype end =
+ icalcomponent_get_dtend(inner);
+
+ struct icaldurationtype dur
+ = icaltime_subtract(end,start);
+
+ icalproperty_set_duration(dur_prop,dur);
+
+ } else {
+ /* Error, both duration and dtend have been specified */
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ }
+}
+
+void icalcomponent_set_duration(icalcomponent* comp,
+ struct icaldurationtype v)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+
+ icalproperty *end_prop
+ = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
+
+ icalproperty *dur_prop
+ = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
+
+
+ if( end_prop == 0 && dur_prop == 0){
+ dur_prop = icalproperty_new_duration(v);
+ icalcomponent_add_property(inner, dur_prop);
+ } else if ( end_prop != 0) {
+ struct icaltimetype start =
+ icalcomponent_get_dtstart(inner);
+
+ struct icaltimetype new_end = icaltime_add(start,v);
+
+ icalproperty_set_dtend(end_prop,new_end);
+
+ } else if ( dur_prop != 0) {
+ icalproperty_set_duration(dur_prop,v);
+ } else {
+ /* Error, both duration and dtend have been specified */
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ }
+}
+
+struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+
+ icalproperty *end_prop
+ = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
+
+ icalproperty *dur_prop
+ = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
+
+ struct icaldurationtype null_duration;
+ memset(&null_duration,0,sizeof(struct icaldurationtype));
+
+
+ if( end_prop == 0 && dur_prop == 0){
+ return null_duration;
+ } else if ( end_prop != 0) {
+ struct icaltimetype start =
+ icalcomponent_get_dtstart(inner);
+ time_t startt = icaltime_as_timet(start);
+
+ struct icaltimetype end =
+ icalcomponent_get_dtend(inner);
+ time_t endt = icaltime_as_timet(end);
+
+ return icaldurationtype_from_int(endt-startt);
+ } else if ( dur_prop != 0) {
+ return icalproperty_get_duration(dur_prop);
+ } else {
+ /* Error, both duration and dtend have been specified */
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return null_duration;
+ }
+}
+
+void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method)
+{
+ icalproperty *prop
+ = icalcomponent_get_first_property(comp, ICAL_METHOD_PROPERTY);
+
+
+ if (prop == 0){
+ prop = icalproperty_new_method(method);
+ icalcomponent_add_property(comp, prop);
+ }
+
+ icalproperty_set_method(prop,method);
+
+}
+
+icalproperty_method icalcomponent_get_method(icalcomponent* comp)
+{
+ icalproperty *prop
+ = icalcomponent_get_first_property(comp,ICAL_METHOD_PROPERTY);
+
+ if (prop == 0){
+ return ICAL_METHOD_NONE;
+ }
+
+ return icalproperty_get_method(prop);
+}
+
+void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v)
+{
+
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+ icalproperty *prop
+ = icalcomponent_get_first_property(inner, ICAL_DTSTAMP_PROPERTY);
+
+
+ if (prop == 0){
+ prop = icalproperty_new_dtstamp(v);
+ icalcomponent_add_property(inner, prop);
+ }
+
+ icalproperty_set_dtstamp(prop,v);
+
+}
+
+
+struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+ icalproperty *prop
+ = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY);
+
+ if (prop == 0){
+ return icaltime_null_time();
+ }
+
+ return icalproperty_get_dtstamp(prop);
+}
+
+
+void icalcomponent_set_summary(icalcomponent* comp, const char* v)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+ icalproperty *prop
+ = icalcomponent_get_first_property(inner, ICAL_SUMMARY_PROPERTY);
+
+ if (prop == 0){
+ prop = icalproperty_new_summary(v);
+ icalcomponent_add_property(inner, prop);
+ }
+
+ icalproperty_set_summary(prop,v);
+}
+
+
+const char* icalcomponent_get_summary(icalcomponent* comp)
+{
+ icalcomponent *inner = icalcomponent_get_inner(comp);
+ icalproperty *prop
+ = icalcomponent_get_first_property(inner,ICAL_SUMMARY_PROPERTY);
+
+ if (prop == 0){
+ return 0;
+ }
+
+ return icalproperty_get_summary(prop);
+
+}
+
+void icalcomponent_set_comment(icalcomponent* comp, const char* v);
+const char* icalcomponent_get_comment(icalcomponent* comp);
+
+void icalcomponent_set_uid(icalcomponent* comp, const char* v);
+const char* icalcomponent_get_uid(icalcomponent* comp);
+
+void icalcomponent_set_recurrenceid(icalcomponent* comp,
+ struct icaltimetype v);
+struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp);
+
+
+
+
+icalcomponent* icalcomponent_new_vcalendar()
+{
+ return icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
+}
+icalcomponent* icalcomponent_new_vevent()
+{
+ return icalcomponent_new(ICAL_VEVENT_COMPONENT);
+}
+icalcomponent* icalcomponent_new_vtodo()
+{
+ return icalcomponent_new(ICAL_VTODO_COMPONENT);
+}
+icalcomponent* icalcomponent_new_vjournal()
+{
+ return icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
+}
+icalcomponent* icalcomponent_new_valarm()
+{
+ return icalcomponent_new(ICAL_VALARM_COMPONENT);
+}
+icalcomponent* icalcomponent_new_vfreebusy()
+{
+ return icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
+}
+icalcomponent* icalcomponent_new_vtimezone()
+{
+ return icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
+}
+icalcomponent* icalcomponent_new_xstandard()
+{
+ return icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
+}
+icalcomponent* icalcomponent_new_xdaylight()
+{
+ return icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
+}
diff --git a/src/plugins/vcalendar/libical/libical/icalcomponent.h b/src/plugins/vcalendar/libical/libical/icalcomponent.h
@@ -0,0 +1,240 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalcomponent.h
+ CREATOR: eric 20 March 1999
+
+
+ (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 icalcomponent.h
+
+======================================================================*/
+
+#ifndef ICALCOMPONENT_H
+#define ICALCOMPONENT_H
+
+#include "icalproperty.h"
+#include "icalvalue.h"
+#include "icalenums.h" /* defines icalcomponent_kind */
+#include "icalattendee.h"
+#include "pvl.h"
+
+typedef void icalcomponent;
+
+/* This is exposed so that callers will not have to allocate and
+ deallocate iterators. Pretend that you can't see it. */
+typedef struct icalcompiter
+{
+ icalcomponent_kind kind;
+ pvl_elem iter;
+
+} icalcompiter;
+
+icalcomponent* icalcomponent_new(icalcomponent_kind kind);
+icalcomponent* icalcomponent_new_clone(icalcomponent* component);
+icalcomponent* icalcomponent_new_from_string(char* str);
+icalcomponent* icalcomponent_vanew(icalcomponent_kind kind, ...);
+void icalcomponent_free(icalcomponent* component);
+
+char* icalcomponent_as_ical_string(icalcomponent* component);
+
+int icalcomponent_is_valid(icalcomponent* component);
+
+icalcomponent_kind icalcomponent_isa(icalcomponent* component);
+
+int icalcomponent_isa_component (void* component);
+
+/*
+ * Working with properties
+ */
+
+void icalcomponent_add_property(icalcomponent* component,
+ icalproperty* property);
+
+void icalcomponent_remove_property(icalcomponent* component,
+ icalproperty* property);
+
+int icalcomponent_count_properties(icalcomponent* component,
+ icalproperty_kind kind);
+
+/* Iterate through the properties */
+icalproperty* icalcomponent_get_current_property(icalcomponent* component);
+
+icalproperty* icalcomponent_get_first_property(icalcomponent* component,
+ icalproperty_kind kind);
+icalproperty* icalcomponent_get_next_property(icalcomponent* component,
+ icalproperty_kind kind);
+
+
+/*
+ * Working with components
+ */
+
+
+/* Return the first VEVENT, VTODO or VJOURNAL sub-component of cop, or
+ comp if it is one of those types */
+
+icalcomponent* icalcomponent_get_inner(icalcomponent* comp);
+
+
+void icalcomponent_add_component(icalcomponent* parent,
+ icalcomponent* child);
+
+void icalcomponent_remove_component(icalcomponent* parent,
+ icalcomponent* child);
+
+int icalcomponent_count_components(icalcomponent* component,
+ icalcomponent_kind kind);
+
+/* Iteration Routines. There are two forms of iterators, internal and
+external. The internal ones came first, and are almost completely
+sufficient, but they fail badly when you want to construct a loop that
+removes components from the container.*/
+
+
+/* Iterate through components */
+icalcomponent* icalcomponent_get_current_component (icalcomponent* component);
+
+icalcomponent* icalcomponent_get_first_component(icalcomponent* component,
+ icalcomponent_kind kind);
+icalcomponent* icalcomponent_get_next_component(icalcomponent* component,
+ icalcomponent_kind kind);
+
+/* Using external iterators */
+icalcompiter icalcomponent_begin_component(icalcomponent* component,
+ icalcomponent_kind kind);
+icalcompiter icalcomponent_end_component(icalcomponent* component,
+ icalcomponent_kind kind);
+icalcomponent* icalcompiter_next(icalcompiter* i);
+icalcomponent* icalcompiter_prior(icalcompiter* i);
+icalcomponent* icalcompiter_deref(icalcompiter* i);
+
+
+
+
+/* Working with embedded error properties */
+
+int icalcomponent_count_errors(icalcomponent* component);
+
+/* Remove all X-LIC-ERROR properties*/
+void icalcomponent_strip_errors(icalcomponent* component);
+
+/* Convert some X-LIC-ERROR properties into RETURN-STATUS properties*/
+void icalcomponent_convert_errors(icalcomponent* component);
+
+/* Internal operations. They are private, and you should not be using them. */
+icalcomponent* icalcomponent_get_parent(icalcomponent* component);
+void icalcomponent_set_parent(icalcomponent* component,
+ icalcomponent* parent);
+
+/* Kind conversion routiens */
+
+icalcomponent_kind icalcomponent_string_to_kind(const char* string);
+
+const char* icalcomponent_kind_to_string(icalcomponent_kind kind);
+
+
+/************* Derived class methods. ****************************
+
+If the code was in an OO language, the remaining routines would be
+members of classes derived from icalcomponent. Don't call them on the
+wrong component subtypes. */
+
+/* For VCOMPONENT: Return a reference to the first VEVENT, VTODO or
+ VJOURNAL */
+icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c);
+
+/* For VEVENT, VTODO, VJOURNAL and VTIMEZONE: report the start and end
+ times of an event in UTC */
+struct icaltime_span icalcomponent_get_span(icalcomponent* comp);
+
+/******************** Convienience routines **********************/
+
+void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v);
+struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp);
+
+/* For the icalcomponent routines only, dtend and duration are tied
+ together. If you call the set routine for one and the other exists,
+ the routine will calculate the change to the other. That is, if
+ there is a DTEND and you call set_duration, the routine will modify
+ DTEND to be the sum of DTSTART and the duration. If you call a get
+ routine for one and the other exists, the routine will calculate
+ the return value. If you call a set routine and neither exists, the
+ routine will create the apcompriate comperty */
+
+
+struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp);
+void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v);
+
+void icalcomponent_set_duration(icalcomponent* comp,
+ struct icaldurationtype v);
+struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp);
+
+void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method);
+icalproperty_method icalcomponent_get_method(icalcomponent* comp);
+
+struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp);
+void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v);
+
+
+void icalcomponent_set_summary(icalcomponent* comp, const char* v);
+const char* icalcomponent_get_summary(icalcomponent* comp);
+
+void icalcomponent_set_comment(icalcomponent* comp, const char* v);
+const char* icalcomponent_get_comment(icalcomponent* comp);
+
+void icalcomponent_set_uid(icalcomponent* comp, const char* v);
+const char* icalcomponent_get_uid(icalcomponent* comp);
+
+void icalcomponent_set_recurrenceid(icalcomponent* comp,
+ struct icaltimetype v);
+struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp);
+
+
+void icalcomponent_set_organizer(icalcomponent* comp,
+ struct icalorganizertype org);
+ struct icalorganizertype icalcomponent_get_organizer(icalcomponent* comp);
+
+
+void icalcomponent_add_attendee(icalcomponent *comp,
+ struct icalattendeetype attendee);
+
+int icalcomponent_remove_attendee(icalcomponent *comp, char* cuid);
+
+/* Get the Nth attendee. Out of range indices return an attendee
+ with cuid == 0 */
+struct icalattendeetype icalcomponent_get_attendee(icalcomponent *comp,
+ int index);
+
+
+
+
+/*************** Type Specific routines ***************/
+
+icalcomponent* icalcomponent_new_vcalendar();
+icalcomponent* icalcomponent_new_vevent();
+icalcomponent* icalcomponent_new_vtodo();
+icalcomponent* icalcomponent_new_vjournal();
+icalcomponent* icalcomponent_new_valarm();
+icalcomponent* icalcomponent_new_vfreebusy();
+icalcomponent* icalcomponent_new_vtimezone();
+icalcomponent* icalcomponent_new_xstandard();
+icalcomponent* icalcomponent_new_xdaylight();
+
+
+
+#endif /* !ICALCOMPONENT_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalderivedparameter.c.in b/src/plugins/vcalendar/libical/libical/icalderivedparameter.c.in
@@ -0,0 +1,211 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalderivedparameters.{c,h}
+ CREATOR: eric 09 May 1999
+
+ $Id$
+ $Locker$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalderivedparameters.{c,h}
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+ ======================================================================*/
+/*#line 29 "icalparameter.c.in"*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "icalparameter.h"
+#include "icalparameterimpl.h"
+
+#include "icalproperty.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+
+#include <stdlib.h> /* for malloc() */
+#include <errno.h>
+#include <string.h> /* for memset() */
+
+icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value);
+
+struct icalparameter_impl* icalparameter_new_impl(icalparameter_kind kind);
+
+/* This map associates each of the parameters with the string
+ representation of the paramter's name */
+struct icalparameter_kind_map {
+ icalparameter_kind kind;
+ char *name;
+
+};
+
+static struct icalparameter_kind_map parameter_map[];
+
+
+const char* icalparameter_kind_to_string(icalparameter_kind kind)
+{
+ int i;
+
+ for (i=0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) {
+ if (parameter_map[i].kind == kind) {
+ return parameter_map[i].name;
+ }
+ }
+
+ return 0;
+
+}
+
+icalparameter_kind icalparameter_string_to_kind(const char* string)
+{
+ int i;
+
+ if (string ==0 ) {
+ return ICAL_NO_PARAMETER;
+ }
+
+ for (i=0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) {
+
+ if (strcmp(parameter_map[i].name, string) == 0) {
+ return parameter_map[i].kind;
+ }
+ }
+
+ if(strncmp(string,"X-",2)==0){
+ return ICAL_X_PARAMETER;
+ }
+
+ return ICAL_NO_PARAMETER;
+}
+
+/* This map associates the enumerations for the VALUE parameter with
+ the kinds of VALUEs. */
+
+struct icalparameter_value_kind_map {
+ icalparameter_value value;
+ icalvalue_kind kind;
+};
+
+static struct icalparameter_value_kind_map value_kind_map[];
+
+
+icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value)
+{
+ int i;
+
+ for (i=0; value_kind_map[i].kind != ICAL_NO_VALUE; i++) {
+
+ if (value_kind_map[i].value == value) {
+ return value_kind_map[i].kind;
+ }
+ }
+
+ return ICAL_NO_VALUE;
+}
+
+
+/* This map associates the parameter enumerations with a specific parameter and the string representation of the enumeration */
+
+struct icalparameter_map {
+ icalparameter_kind kind;
+ int enumeration;
+ const char* str;
+};
+
+
+static struct icalparameter_map icalparameter_map[];
+
+
+const char* icalparameter_enum_to_string(int e)
+{
+ int i;
+
+ icalerror_check_arg_rz(e >= ICALPARAMETER_FIRST_ENUM,"e");
+ icalerror_check_arg_rz(e <= ICALPARAMETER_LAST_ENUM,"e");
+
+ for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){
+ if(e == icalparameter_map[i].enumeration){
+ return icalparameter_map[i].str;
+ }
+ }
+
+ return 0;
+}
+
+int icalparameter_string_to_enum(const char* str)
+{
+ int i;
+
+ icalerror_check_arg_rz(str != 0,"str");
+
+ for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){
+ if(strcmp(str,icalparameter_map[i].str) == 0) {
+ return icalparameter_map[i].enumeration;
+ }
+ }
+
+ return 0;
+}
+
+icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind,const char* val)
+{
+
+ struct icalparameter_impl* param=0;
+ int found_kind = 0;
+ int i;
+
+ icalerror_check_arg_rz((val!=0),"val");
+
+ /* Search through the parameter map to find a matching kind */
+
+ param = icalparameter_new_impl(kind);
+
+ for (i=0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++){
+ if(kind == icalparameter_map[i].kind) {
+ found_kind = 1;
+ if(strcmp(val,icalparameter_map[i].str) == 0) {
+
+ param->data = (int)icalparameter_map[i].enumeration;
+ return param;
+ }
+ }
+ }
+
+ if(found_kind == 1){
+ /* The kind was in the parameter map, but the string did not
+ match, so assume that it is an alternate value, like an
+ X-value.*/
+
+ icalparameter_set_xvalue(param, val);
+
+ } else {
+
+ /* If the kind was not found, then it must be a string type */
+
+ ((struct icalparameter_impl*)param)->string = icalmemory_strdup(val);
+
+ }
+
+ return param;
+}
+
+
+
+
+/* Everything below this line is machine generated. Do not edit. */
diff --git a/src/plugins/vcalendar/libical/libical/icalderivedparameter.h.in b/src/plugins/vcalendar/libical/libical/icalderivedparameter.h.in
@@ -0,0 +1,37 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalparam.h
+ CREATOR: eric 20 March 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 icalparam.h
+
+ ======================================================================*/
+
+#ifndef ICALDERIVEDPARAMETER_H
+#define ICALDERIVEDPARAMETER_H
+
+
+typedef void icalparameter;
+
+const char* icalparameter_enum_to_string(int e);
+int icalparameter_string_to_enum(const char* str);
+
diff --git a/src/plugins/vcalendar/libical/libical/icalderivedproperty.c.in b/src/plugins/vcalendar/libical/libical/icalderivedproperty.c.in
@@ -0,0 +1,250 @@
+/* -*- Mode: C -*- */
+
+/*======================================================================
+ FILE: icalderivedproperty.c
+ CREATOR: eric 15 Feb 2001
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalproperty.c
+
+======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalproperty.h"
+#include "icalcomponent.h"
+#include "pvl.h"
+#include "icalenums.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "icalparser.h"
+
+#include <string.h> /* For icalmemory_strdup, rindex */
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h> /* for printf */
+#include <stdarg.h> /* for va_list, va_start, etc. */
+
+#define TMP_BUF_SIZE 1024
+
+struct icalproperty_impl*
+icalproperty_new_impl (icalproperty_kind kind);
+
+/* This map associates the property kinds with the string
+ representation of the property name and the kind of VALUE that the
+ property uses as a default */
+
+struct icalproperty_map {
+ icalproperty_kind kind;
+ const char *name;
+ icalvalue_kind value;
+
+};
+
+static struct icalproperty_map property_map[];
+
+const char* icalproperty_kind_to_string(icalproperty_kind kind)
+{
+ int i;
+
+ for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) {
+ if (property_map[i].kind == kind) {
+ return property_map[i].name;
+ }
+ }
+
+ return 0;
+
+}
+
+
+icalproperty_kind icalproperty_string_to_kind(const char* string)
+{
+ int i;
+
+ if (string ==0 ) {
+ return ICAL_NO_PROPERTY;
+ }
+
+
+ for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) {
+ if (strcmp(property_map[i].name, string) == 0) {
+ return property_map[i].kind;
+ }
+ }
+
+ if(strncmp(string,"X-",2)==0){
+ return ICAL_X_PROPERTY;
+ }
+
+
+ return ICAL_NO_PROPERTY;
+}
+
+
+icalvalue_kind icalproperty_value_kind_to_kind(icalvalue_kind kind)
+{
+ int i;
+
+ for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) {
+ if ( property_map[i].value == kind ) {
+ return property_map[i].kind;
+ }
+ }
+
+ return ICAL_NO_VALUE;
+}
+
+
+
+icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind)
+{
+ int i;
+
+ for (i=0; property_map[i].kind != ICAL_NO_PROPERTY; i++) {
+ if ( property_map[i].kind == kind ) {
+ return property_map[i].value;
+ }
+ }
+
+ return ICAL_NO_VALUE;
+}
+
+
+/* This map associates the property enumerations with the king of
+ property that they are used in and the string representation of the
+ enumeration */
+
+struct icalproperty_enum_map {
+ icalproperty_kind prop;
+ int prop_enum;
+ const char* str;
+};
+
+static struct icalproperty_enum_map enum_map[];
+
+
+const char* icalproperty_enum_to_string(int e)
+{
+ icalerror_check_arg_rz(e >= ICALPROPERTY_FIRST_ENUM,"e");
+ icalerror_check_arg_rz(e <= ICALPROPERTY_LAST_ENUM,"e");
+
+ return enum_map[e-ICALPROPERTY_FIRST_ENUM].str;
+}
+
+int icalproperty_string_to_enum(const char* str)
+{
+ int i;
+
+ icalerror_check_arg_rz(str!=0,"str")
+
+ while(*str == ' '){
+ str++;
+ }
+
+ for (i=ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) {
+ if ( strcmp(enum_map[i-ICALPROPERTY_FIRST_ENUM].str, str) == 0) {
+ return enum_map[i-ICALPROPERTY_FIRST_ENUM].prop_enum;
+ }
+ }
+
+ return 0;
+}
+
+int icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e)
+{
+ int i;
+
+
+ for (i=ICALPROPERTY_FIRST_ENUM; i != ICALPROPERTY_LAST_ENUM; i++) {
+ if(enum_map[i-ICALPROPERTY_FIRST_ENUM].prop_enum == e &&
+ enum_map[i-ICALPROPERTY_FIRST_ENUM].prop == kind ){
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+const char* icalproperty_method_to_string(icalproperty_method method)
+{
+ icalerror_check_arg_rz(method >= ICAL_METHOD_X,"method");
+ icalerror_check_arg_rz(method <= ICAL_METHOD_NONE,"method");
+
+ return enum_map[method-ICALPROPERTY_FIRST_ENUM].str;
+}
+
+icalproperty_method icalproperty_string_to_method(const char* str)
+{
+ int i;
+
+ icalerror_check_arg_rx(str!=0,"str",ICAL_METHOD_NONE)
+
+ while(*str == ' '){
+ str++;
+ }
+
+ for (i=ICAL_METHOD_X-ICALPROPERTY_FIRST_ENUM;
+ i != ICAL_METHOD_NONE-ICALPROPERTY_FIRST_ENUM;
+ i++) {
+ if ( strcmp(enum_map[i].str, str) == 0) {
+ return (icalproperty_method)enum_map[i].prop_enum;
+ }
+ }
+
+ return ICAL_METHOD_NONE;
+}
+
+
+const char* icalenum_status_to_string(icalproperty_status status)
+{
+ icalerror_check_arg_rz(status >= ICAL_STATUS_X,"status");
+ icalerror_check_arg_rz(status <= ICAL_STATUS_NONE,"status");
+
+ return enum_map[status-ICALPROPERTY_FIRST_ENUM].str;
+}
+
+icalproperty_status icalenum_string_to_status(const char* str)
+{
+ int i;
+
+ icalerror_check_arg_rx(str!=0,"str",ICAL_STATUS_NONE)
+
+ while(*str == ' '){
+ str++;
+ }
+
+ for (i=ICAL_STATUS_X-ICALPROPERTY_FIRST_ENUM;
+ i != ICAL_STATUS_NONE-ICALPROPERTY_FIRST_ENUM;
+ i++) {
+ if ( strcmp(enum_map[i].str, str) == 0) {
+ return (icalproperty_method)enum_map[i].prop_enum;
+ }
+ }
+
+ return ICAL_STATUS_NONE;
+
+}
+
+
+
+/* Everything below this line is machine generated. Do not edit. */
diff --git a/src/plugins/vcalendar/libical/libical/icalderivedproperty.h.in b/src/plugins/vcalendar/libical/libical/icalderivedproperty.h.in
@@ -0,0 +1,23 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalderivedproperties.{c,h}
+ CREATOR: eric 09 May 1999
+
+ $Id$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+ ======================================================================*/
+
+
+#ifndef ICALDERIVEDPROPERTY_H
+#define ICALDERIVEDPROPERTY_H
+
+#include <time.h>
+#include "icalparameter.h"
+#include "icalderivedvalue.h"
+#include "icalrecur.h"
+
+typedef void icalproperty;
+
+
+/* Everything below this line is machine generated. Do not edit. */
diff --git a/src/plugins/vcalendar/libical/libical/icalderivedvalue.c.in b/src/plugins/vcalendar/libical/libical/icalderivedvalue.c.in
@@ -0,0 +1,298 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalvalue.c
+ CREATOR: eric 02 May 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalvalue.c
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+
+======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "icalparser.h"
+#include "icalenums.h"
+
+#include "icalvalueimpl.h"
+
+#include <stdlib.h> /* for malloc */
+#include <stdio.h> /* for sprintf */
+#include <string.h> /* For memset, others */
+#include <stddef.h> /* For offsetof() macro */
+#include <errno.h>
+#include <time.h> /* for mktime */
+#include <stdlib.h> /* for atoi and atof */
+#include <limits.h> /* for SHRT_MAX */
+
+
+
+#define TMP_BUF_SIZE 1024
+
+struct icalvalue_impl* icalvalue_new_impl(icalvalue_kind kind);
+
+/* This map associates each of the value types with its string
+ representation */
+struct icalvalue_kind_map {
+ icalvalue_kind kind;
+ char name[20];
+};
+
+static struct icalvalue_kind_map value_map[];
+
+const char* icalvalue_kind_to_string(icalvalue_kind kind)
+{
+ int i;
+
+ for (i=0; value_map[i].kind != ICAL_NO_VALUE; i++) {
+ if (value_map[i].kind == kind) {
+ return value_map[i].name;
+ }
+ }
+
+ return 0;
+}
+
+icalvalue_kind icalvalue_string_to_kind(const char* str)
+{
+ int i;
+
+ for (i=0; value_map[i].kind != ICAL_NO_VALUE; i++) {
+ if (strcmp(value_map[i].name,str) == 0) {
+ return value_map[i].kind;
+ }
+ }
+
+ return value_map[i].kind;
+
+}
+
+icalvalue* icalvalue_new_x (const char* v){
+ struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_X_VALUE);
+ icalerror_check_arg_rz( (v!=0),"v");
+
+ icalvalue_set_x((icalvalue*)impl,v);
+ return (icalvalue*)impl;
+}
+void icalvalue_set_x(icalvalue* value, const char* v) {
+ struct icalvalue_impl* impl;
+ icalerror_check_arg_rv( (value!=0),"value");
+ icalerror_check_arg_rv( (v!=0),"v");
+
+ impl = (struct icalvalue_impl*)value;
+ if(impl->x_value!=0) {free((void*)impl->x_value);}
+
+ impl->x_value = icalmemory_strdup(v);
+
+ if (impl->x_value == 0){
+ errno = ENOMEM;
+ }
+
+ }
+const char* icalvalue_get_x(icalvalue* value) {
+
+ icalerror_check_arg_rz( (value!=0),"value");
+ icalerror_check_value_type(value, ICAL_X_VALUE);
+ return ((struct icalvalue_impl*)value)->x_value;
+}
+
+/* Recur is a special case, so it is not auto generated. */
+icalvalue*
+icalvalue_new_recur (struct icalrecurrencetype v)
+{
+ struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_RECUR_VALUE);
+
+ icalvalue_set_recur((icalvalue*)impl,v);
+
+ return (icalvalue*)impl;
+}
+
+void
+icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v)
+{
+ struct icalvalue_impl* impl;
+
+ icalerror_check_arg_rv( (value!=0),"value");
+ icalerror_check_value_type(value, ICAL_RECUR_VALUE);
+
+ impl = (struct icalvalue_impl*)value;
+
+ if (impl->data.v_recur != 0){
+ free(impl->data.v_recur);
+ impl->data.v_recur = 0;
+ }
+
+ impl->data.v_recur = malloc(sizeof(struct icalrecurrencetype));
+
+ if (impl->data.v_recur == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return;
+ } else {
+ memcpy(impl->data.v_recur, &v, sizeof(struct icalrecurrencetype));
+ }
+
+}
+
+struct icalrecurrencetype
+icalvalue_get_recur(icalvalue* value)
+{
+ icalerror_check_arg( (value!=0),"value");
+ icalerror_check_value_type(value, ICAL_RECUR_VALUE);
+
+ return *(((struct icalvalue_impl*)value)->data.v_recur);
+}
+
+
+
+
+icalvalue*
+icalvalue_new_trigger (struct icaltriggertype v)
+{
+ struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_TRIGGER_VALUE);
+
+ icalvalue_set_trigger((icalvalue*)impl,v);
+
+ return (icalvalue*)impl;
+}
+
+void
+icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v)
+{
+ struct icalvalue_impl* impl;
+
+ icalerror_check_arg_rv( (value!=0),"value");
+
+ impl = (struct icalvalue_impl*)value;
+
+ if(!icaltime_is_null_time(v.time)){
+ icalvalue_set_datetime((icalvalue*)impl,v.time);
+ impl->kind = ICAL_DATETIME_VALUE;
+ } else {
+ icalvalue_set_duration((icalvalue*)impl,v.duration);
+ impl->kind = ICAL_DURATION_VALUE;
+ }
+
+}
+
+struct icaltriggertype
+icalvalue_get_trigger(icalvalue* value)
+{
+ struct icalvalue_impl *impl = (struct icalvalue_impl*)value;
+ struct icaltriggertype tr;
+
+ icalerror_check_arg( (value!=0),"value");
+
+ if(impl->kind == ICAL_DATETIME_VALUE){
+ tr.duration = icaldurationtype_from_int(0);
+ tr.time = impl->data.v_time;
+ } else if(impl->kind == ICAL_DURATION_VALUE){
+ tr.time = icaltime_null_time();
+ tr.duration = impl->data.v_duration;
+ } else {
+ tr.duration = icaldurationtype_from_int(0);
+ tr.time = icaltime_null_time();
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ }
+
+ return tr;
+}
+
+/* DATE-TIME-PERIOD is a special case, and is not auto generated */
+
+icalvalue*
+icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v)
+{
+ struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_DATETIMEPERIOD_VALUE);
+
+ icalvalue_set_datetimeperiod((icalvalue*)impl,v);
+
+ return (icalvalue*)impl;
+}
+
+void
+icalvalue_set_datetimeperiod(icalvalue* value, struct icaldatetimeperiodtype v)
+{
+ struct icalvalue_impl* impl = (struct icalvalue_impl*)value;
+
+ icalerror_check_arg_rv( (value!=0),"value");
+
+ icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE);
+
+ if(!icaltime_is_null_time(v.time)){
+ if(!icaltime_is_valid_time(v.time)){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return;
+ }
+ impl->kind = ICAL_DATETIME_VALUE;
+ icalvalue_set_datetime(impl,v.time);
+ } else if (!icalperiodtype_is_null_period(v.period)) {
+ if(!icalperiodtype_is_valid_period(v.period)){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return;
+ }
+ impl->kind = ICAL_PERIOD_VALUE;
+ icalvalue_set_period(impl,v.period);
+ } else {
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ }
+}
+
+struct icaldatetimeperiodtype
+icalvalue_get_datetimeperiod(icalvalue* value)
+{
+ struct icaldatetimeperiodtype dtp;
+
+ struct icalvalue_impl* impl = (struct icalvalue_impl*)value;
+ icalerror_check_arg( (value!=0),"value");
+ icalerror_check_value_type(value, ICAL_DATETIMEPERIOD_VALUE);
+
+ if(impl->kind == ICAL_DATETIME_VALUE){
+ dtp.period = icalperiodtype_null_period();
+ dtp.time = impl->data.v_time;
+ } else if(impl->kind == ICAL_PERIOD_VALUE) {
+ dtp.period = impl->data.v_period;
+ dtp.time = icaltime_null_time();
+ } else {
+ dtp.period = icalperiodtype_null_period();
+ dtp.time = icaltime_null_time();
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ }
+
+ return dtp;
+}
+
+
+
+
+
+
+
+
+
+/* The remaining interfaces are 'new', 'set' and 'get' for each of the value
+ types */
+
+
+/* Everything below this line is machine generated. Do not edit. */
diff --git a/src/plugins/vcalendar/libical/libical/icalderivedvalue.h.in b/src/plugins/vcalendar/libical/libical/icalderivedvalue.h.in
@@ -0,0 +1,58 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalvalue.h
+ CREATOR: eric 20 March 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 icalvalue.h
+
+ ======================================================================*/
+
+#ifndef ICALDERIVEDVALUE_H
+#define ICALDERIVEDVALUE_H
+
+#include "icaltypes.h"
+#include "icalrecur.h"
+#include "icaltime.h"
+#include "icalduration.h"
+#include "icalperiod.h"
+
+typedef void icalvalue;
+
+
+
+void icalvalue_set_x(icalvalue* value, const char* v);
+icalvalue* icalvalue_new_x(const char* v);
+const char* icalvalue_get_x(icalvalue* value);
+
+icalvalue* icalvalue_new_recur (struct icalrecurrencetype v);
+void icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v);
+struct icalrecurrencetype icalvalue_get_recur(icalvalue* value);
+
+icalvalue* icalvalue_new_trigger (struct icaltriggertype v);
+void icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v);
+struct icaltriggertype icalvalue_get_trigger(icalvalue* value);
+
+icalvalue* icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v);
+void icalvalue_set_datetimeperiod(icalvalue* value, struct icaldatetimeperiodtype v);
+struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(icalvalue* value);
+
+/* Everything below this line is machine generated. Do not edit. */
diff --git a/src/plugins/vcalendar/libical/libical/icalduration.c b/src/plugins/vcalendar/libical/libical/icalduration.c
@@ -0,0 +1,320 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icaltime.c
+ CREATOR: eric 02 June 2000
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+ ======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalduration.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef ICAL_NO_LIBICAL
+#define icalerror_set_errno(x)
+#define icalerror_check_arg_rv(x,y)
+#define icalerror_check_arg_re(x,y,z)
+#else
+#include "icalerror.h"
+#include "icalmemory.h"
+#endif
+
+
+
+
+/* From Seth Alves, <alves@hungry.com> */
+struct icaldurationtype icaldurationtype_from_int(int t)
+{
+ struct icaldurationtype dur;
+ int used = 0;
+
+ dur = icaldurationtype_null_duration();
+
+ if(t < 0){
+ dur.is_neg = 1;
+ t = -t;
+ }
+
+ dur.weeks = (t - used) / (60 * 60 * 24 * 7);
+ used += dur.weeks * (60 * 60 * 24 * 7);
+ dur.days = (t - used) / (60 * 60 * 24);
+ used += dur.days * (60 * 60 * 24);
+ dur.hours = (t - used) / (60 * 60);
+ used += dur.hours * (60 * 60);
+ dur.minutes = (t - used) / (60);
+ used += dur.minutes * (60);
+ dur.seconds = (t - used);
+
+ return dur;
+}
+
+#ifndef ICAL_NO_LIBICAL
+#include "icalvalue.h"
+struct icaldurationtype icaldurationtype_from_string(const char* str)
+{
+
+ int i;
+ int begin_flag = 0;
+ int time_flag = 0;
+ int date_flag = 0;
+ int week_flag = 0;
+ int digits=-1;
+ int scan_size = -1;
+ int size = strlen(str);
+ char p;
+ struct icaldurationtype d;
+
+ memset(&d, 0, sizeof(struct icaldurationtype));
+
+ for(i=0;i != size;i++){
+ p = str[i];
+
+ switch(p)
+ {
+ case '-': {
+ if(i != 0 || begin_flag == 1) goto error;
+
+ d.is_neg = 1;
+ break;
+ }
+
+ case 'P': {
+ if (i != 0 && i !=1 ) goto error;
+ begin_flag = 1;
+ break;
+ }
+
+ case 'T': {
+ time_flag = 1;
+ break;
+ }
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+
+ /* HACK. Skip any more digits if the l;ast one
+ read has not been assigned */
+ if(digits != -1){
+ break;
+ }
+
+ if (begin_flag == 0) goto error;
+ /* Get all of the digits, not one at a time */
+ scan_size = sscanf((char*)(str+i),"%d",&digits);
+ if(scan_size == 0) goto error;
+ break;
+ }
+
+ case 'H': {
+ if (time_flag == 0||week_flag == 1||d.hours !=0||digits ==-1)
+ goto error;
+ d.hours = digits; digits = -1;
+ break;
+ }
+ case 'M': {
+ if (time_flag == 0||week_flag==1||d.minutes != 0||digits ==-1)
+ goto error;
+ d.minutes = digits; digits = -1;
+ break;
+ }
+ case 'S': {
+ if (time_flag == 0||week_flag==1||d.seconds!=0||digits ==-1)
+ goto error;
+ d.seconds = digits; digits = -1;
+ break;
+ }
+ case 'W': {
+ if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1)
+ goto error;
+ week_flag = 1;
+ d.weeks = digits; digits = -1;
+ break;
+ }
+ case 'D': {
+ if (time_flag==1||week_flag==1||d.days!=0||digits ==-1)
+ goto error;
+ date_flag = 1;
+ d.days = digits; digits = -1;
+ break;
+ }
+ default: {
+ goto error;
+ }
+
+ }
+ }
+
+ return d;
+
+
+ error:
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ memset(&d, 0, sizeof(struct icaldurationtype));
+ return d;
+
+}
+
+#define TMP_BUF_SIZE 1024
+void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size,
+ char* sep, unsigned int value) {
+
+ char temp[TMP_BUF_SIZE];
+
+ sprintf(temp,"%d",value);
+
+ icalmemory_append_string(buf, buf_ptr, buf_size, temp);
+ icalmemory_append_string(buf, buf_ptr, buf_size, sep);
+
+}
+
+char* icaldurationtype_as_ical_string(struct icaldurationtype d)
+{
+
+ char *buf, *output_line;
+ size_t buf_size = 256;
+ char* buf_ptr = 0;
+ int seconds;
+
+ buf = (char*)icalmemory_new_buffer(buf_size);
+ buf_ptr = buf;
+
+
+ seconds = icaldurationtype_as_int(d);
+
+ if(seconds !=0){
+
+ if(d.is_neg == 1){
+ icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-');
+ }
+
+ icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P');
+
+ if (d.weeks != 0 ) {
+ append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks);
+ }
+
+ if (d.days != 0 ) {
+ append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days);
+ }
+
+ if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) {
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T");
+
+ if (d.hours != 0 ) {
+ append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours);
+ }
+ if (d.minutes != 0 ) {
+ append_duration_segment(&buf, &buf_ptr, &buf_size, "M",
+ d.minutes);
+ }
+ if (d.seconds != 0 ) {
+ append_duration_segment(&buf, &buf_ptr, &buf_size, "S",
+ d.seconds);
+ }
+
+ }
+ } else {
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PTS0");
+ }
+
+ output_line = icalmemory_tmp_copy(buf);
+ icalmemory_free_buffer(buf);
+
+ return output_line;
+
+}
+
+#endif
+
+
+/* From Russel Steinthal */
+int icaldurationtype_as_int(struct icaldurationtype dur)
+{
+ return (int)( (dur.seconds +
+ (60 * dur.minutes) +
+ (60 * 60 * dur.hours) +
+ (60 * 60 * 24 * dur.days) +
+ (60 * 60 * 24 * 7 * dur.weeks))
+ * (dur.is_neg==1? -1 : 1) ) ;
+}
+
+struct icaldurationtype icaldurationtype_null_duration()
+{
+ struct icaldurationtype d;
+
+ memset(&d,0,sizeof(struct icaldurationtype));
+
+ return d;
+}
+
+int icaldurationtype_is_null_duration(struct icaldurationtype d)
+{
+ if(icaldurationtype_as_int(d) == 0){
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+struct icaltimetype icaltime_add(struct icaltimetype t,
+ struct icaldurationtype d)
+{
+ int dt = icaldurationtype_as_int(d);
+
+ t.second += dt;
+
+ t = icaltime_normalize(t);
+
+ return t;
+}
+
+struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
+ struct icaltimetype t2)
+{
+
+ time_t t1t = icaltime_as_timet(t1);
+ time_t t2t = icaltime_as_timet(t2);
+
+ return icaldurationtype_from_int(t1t-t2t);
+
+
+}
+
diff --git a/src/plugins/vcalendar/libical/libical/icalduration.h b/src/plugins/vcalendar/libical/libical/icalduration.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalduration.h
+ CREATOR: eric 26 Jan 2001
+
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+======================================================================*/
+
+#ifndef ICALDURATION_H
+#define ICALDURATION_H
+
+#include "icaltime.h"
+
+struct icaldurationtype
+{
+ int is_neg;
+ unsigned int days;
+ unsigned int weeks;
+ unsigned int hours;
+ unsigned int minutes;
+ unsigned int seconds;
+};
+
+struct icaldurationtype icaldurationtype_from_int(int t);
+struct icaldurationtype icaldurationtype_from_string(const char*);
+int icaldurationtype_as_int(struct icaldurationtype duration);
+char* icaldurationtype_as_ical_string(struct icaldurationtype d);
+struct icaldurationtype icaldurationtype_null_duration();
+int icaldurationtype_is_null_duration(struct icaldurationtype d);
+
+struct icaltimetype icaltime_add(struct icaltimetype t,
+ struct icaldurationtype d);
+
+struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
+ struct icaltimetype t2);
+
+#endif /* !ICALDURATION_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalenums.c b/src/plugins/vcalendar/libical/libical/icalenums.c
@@ -0,0 +1,135 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalenum.c
+ CREATOR: eric 29 April 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalenum.c
+
+ ======================================================================*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "icalenums.h"
+
+#include <stdio.h> /* For fprintf */
+#include <stdio.h> /* For stderr */
+#include <string.h> /* For strncmp */
+#include <assert.h>
+
+
+
+struct {
+ enum icalrequeststatus kind;
+ int major;
+ int minor;
+ const char* str;
+} request_status_map[] = {
+ {ICAL_2_0_SUCCESS_STATUS, 2,0,"Success."},
+ {ICAL_2_1_FALLBACK_STATUS, 2,1,"Success but fallback taken on one or more property values."},
+ {ICAL_2_2_IGPROP_STATUS, 2,2,"Success, invalid property ignored."},
+ {ICAL_2_3_IGPARAM_STATUS, 2,3,"Success, invalid property parameter ignored."},
+ {ICAL_2_4_IGXPROP_STATUS, 2,4,"Success, unknown non-standard property ignored."},
+ {ICAL_2_5_IGXPARAM_STATUS, 2,5,"Success, unknown non standard property value ignored."},
+ {ICAL_2_6_IGCOMP_STATUS, 2,6,"Success, invalid calendar component ignored."},
+ {ICAL_2_7_FORWARD_STATUS, 2,7,"Success, request forwarded to Calendar User."},
+ {ICAL_2_8_ONEEVENT_STATUS, 2,8,"Success, repeating event ignored. Scheduled as a single component."},
+ {ICAL_2_9_TRUNC_STATUS, 2,9,"Success, truncated end date time to date boundary."},
+ {ICAL_2_10_ONETODO_STATUS, 2,10,"Success, repeating VTODO ignored. Scheduled as a single VTODO."},
+ {ICAL_2_11_TRUNCRRULE_STATUS, 2,11,"Success, unbounded RRULE clipped at some finite number of instances "},
+ {ICAL_3_0_INVPROPNAME_STATUS, 3,0,"Invalid property name."},
+ {ICAL_3_1_INVPROPVAL_STATUS, 3,1,"Invalid property value."},
+ {ICAL_3_2_INVPARAM_STATUS, 3,2,"Invalid property parameter."},
+ {ICAL_3_3_INVPARAMVAL_STATUS, 3,3,"Invalid property parameter value."},
+ {ICAL_3_4_INVCOMP_STATUS, 3,4,"Invalid calendar component."},
+ {ICAL_3_5_INVTIME_STATUS, 3,5,"Invalid date or time."},
+ {ICAL_3_6_INVRULE_STATUS, 3,6,"Invalid rule."},
+ {ICAL_3_7_INVCU_STATUS, 3,7,"Invalid Calendar User."},
+ {ICAL_3_8_NOAUTH_STATUS, 3,8,"No authority."},
+ {ICAL_3_9_BADVERSION_STATUS, 3,9,"Unsupported version."},
+ {ICAL_3_10_TOOBIG_STATUS, 3,10,"Request entity too large."},
+ {ICAL_3_11_MISSREQCOMP_STATUS, 3,11,"Required component or property missing."},
+ {ICAL_3_12_UNKCOMP_STATUS, 3,12,"Unknown component or property found."},
+ {ICAL_3_13_BADCOMP_STATUS, 3,13,"Unsupported component or property found"},
+ {ICAL_3_14_NOCAP_STATUS, 3,14,"Unsupported capability."},
+ {ICAL_4_0_BUSY_STATUS, 4,0,"Event conflict. Date/time is busy."},
+ {ICAL_5_0_MAYBE_STATUS, 5,0,"Request MAY supported."},
+ {ICAL_5_1_UNAVAIL_STATUS, 5,1,"Service unavailable."},
+ {ICAL_5_2_NOSERVICE_STATUS, 5,2,"Invalid calendar service."},
+ {ICAL_5_3_NOSCHED_STATUS, 5,3,"No scheduling support for user."},
+ {ICAL_UNKNOWN_STATUS, 0,0,"Error: Unknown request status"}
+};
+
+
+const char* icalenum_reqstat_desc(icalrequeststatus stat)
+{
+
+ int i;
+
+ for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) {
+ if ( request_status_map[i].kind == stat) {
+ return request_status_map[i].str;
+ }
+ }
+
+ return 0;
+}
+
+
+short icalenum_reqstat_major(icalrequeststatus stat)
+{
+ int i;
+
+ for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) {
+ if ( request_status_map[i].kind == stat) {
+ return request_status_map[i].major;
+ }
+ }
+ return -1;
+}
+
+short icalenum_reqstat_minor(icalrequeststatus stat)
+{
+ int i;
+
+ for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) {
+ if ( request_status_map[i].kind == stat) {
+ return request_status_map[i].minor;
+ }
+ }
+ return -1;
+}
+
+
+icalrequeststatus icalenum_num_to_reqstat(short major, short minor)
+{
+ int i;
+
+ for (i=0; request_status_map[i].kind != ICAL_UNKNOWN_STATUS; i++) {
+ if ( request_status_map[i].major == major && request_status_map[i].minor == minor) {
+ return request_status_map[i].kind;
+ }
+ }
+ return 0;
+}
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalenums.h b/src/plugins/vcalendar/libical/libical/icalenums.h
@@ -0,0 +1,157 @@
+
+/* -*- Mode: C -*-*/
+/*======================================================================
+ FILE: icalenums.h
+
+
+
+ (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 icalenums.h
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+======================================================================*/
+
+#ifndef ICALENUMS_H
+#define ICALENUMS_H
+
+
+
+/***********************************************************************
+ * Component enumerations
+**********************************************************************/
+
+typedef enum icalcomponent_kind {
+ ICAL_NO_COMPONENT,
+ ICAL_ANY_COMPONENT, /* Used to select all components*/
+ ICAL_XROOT_COMPONENT,
+ ICAL_XATTACH_COMPONENT, /* MIME attached data, returned by parser. */
+ ICAL_VEVENT_COMPONENT,
+ ICAL_VTODO_COMPONENT,
+ ICAL_VJOURNAL_COMPONENT,
+ ICAL_VCALENDAR_COMPONENT,
+ ICAL_VFREEBUSY_COMPONENT,
+ ICAL_VALARM_COMPONENT,
+ ICAL_XAUDIOALARM_COMPONENT,
+ ICAL_XDISPLAYALARM_COMPONENT,
+ ICAL_XEMAILALARM_COMPONENT,
+ ICAL_XPROCEDUREALARM_COMPONENT,
+ ICAL_VTIMEZONE_COMPONENT,
+ ICAL_XSTANDARD_COMPONENT,
+ ICAL_XDAYLIGHT_COMPONENT,
+ ICAL_X_COMPONENT,
+ ICAL_VSCHEDULE_COMPONENT,
+ ICAL_VQUERY_COMPONENT,
+ ICAL_VCAR_COMPONENT,
+ ICAL_VCOMMAND_COMPONENT,
+ ICAL_XLICINVALID_COMPONENT,
+ ICAL_XLICMIMEPART_COMPONENT /* a non-stardard component that mirrors
+ structure of MIME data */
+
+} icalcomponent_kind;
+
+
+
+/***********************************************************************
+ * Request Status codes
+ **********************************************************************/
+
+typedef enum icalrequeststatus {
+ ICAL_UNKNOWN_STATUS,
+ ICAL_2_0_SUCCESS_STATUS,
+ ICAL_2_1_FALLBACK_STATUS,
+ ICAL_2_2_IGPROP_STATUS,
+ ICAL_2_3_IGPARAM_STATUS,
+ ICAL_2_4_IGXPROP_STATUS,
+ ICAL_2_5_IGXPARAM_STATUS,
+ ICAL_2_6_IGCOMP_STATUS,
+ ICAL_2_7_FORWARD_STATUS,
+ ICAL_2_8_ONEEVENT_STATUS,
+ ICAL_2_9_TRUNC_STATUS,
+ ICAL_2_10_ONETODO_STATUS,
+ ICAL_2_11_TRUNCRRULE_STATUS,
+ ICAL_3_0_INVPROPNAME_STATUS,
+ ICAL_3_1_INVPROPVAL_STATUS,
+ ICAL_3_2_INVPARAM_STATUS,
+ ICAL_3_3_INVPARAMVAL_STATUS,
+ ICAL_3_4_INVCOMP_STATUS,
+ ICAL_3_5_INVTIME_STATUS,
+ ICAL_3_6_INVRULE_STATUS,
+ ICAL_3_7_INVCU_STATUS,
+ ICAL_3_8_NOAUTH_STATUS,
+ ICAL_3_9_BADVERSION_STATUS,
+ ICAL_3_10_TOOBIG_STATUS,
+ ICAL_3_11_MISSREQCOMP_STATUS,
+ ICAL_3_12_UNKCOMP_STATUS,
+ ICAL_3_13_BADCOMP_STATUS,
+ ICAL_3_14_NOCAP_STATUS,
+ ICAL_4_0_BUSY_STATUS,
+ ICAL_5_0_MAYBE_STATUS,
+ ICAL_5_1_UNAVAIL_STATUS,
+ ICAL_5_2_NOSERVICE_STATUS,
+ ICAL_5_3_NOSCHED_STATUS
+} icalrequeststatus;
+
+
+const char* icalenum_reqstat_desc(icalrequeststatus stat);
+short icalenum_reqstat_major(icalrequeststatus stat);
+short icalenum_reqstat_minor(icalrequeststatus stat);
+icalrequeststatus icalenum_num_to_reqstat(short major, short minor);
+
+/***********************************************************************
+ * Conversion functions
+**********************************************************************/
+
+
+/* Thse routines used to be in icalenums.c, but were moved into the
+ icalproperty, icalparameter, icalvalue, or icalcomponent modules. */
+
+/* const char* icalproperty_kind_to_string(icalproperty_kind kind);*/
+#define icalenum_property_kind_to_string(x) icalproperty_kind_to_string(x)
+
+/*icalproperty_kind icalproperty_string_to_kind(const char* string)*/
+#define icalenum_string_to_property_kind(x) icalproperty_string_to_kind(x)
+
+/*icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind);*/
+#define icalenum_property_kind_to_value_kind(x) icalproperty_kind_to_value_kind(x)
+
+/*const char* icalenum_method_to_string(icalproperty_method);*/
+#define icalenum_method_to_string(x) icalproperty_method_to_string(x)
+
+/*icalproperty_method icalenum_string_to_method(const char* string);*/
+#define icalenum_string_to_method(x) icalproperty_string_to_method(x)
+
+/*const char* icalenum_status_to_string(icalproperty_status);*/
+#define icalenum_status_to_string(x) icalproperty_status_to_string(x)
+
+/*icalproperty_status icalenum_string_to_status(const char* string);*/
+#define icalenum_string_to_status(x) icalproperty_string_to_status(x)
+
+/*icalvalue_kind icalenum_string_to_value_kind(const char* str);*/
+#define icalenum_string_to_value_kind(x) icalvalue_string_to_kind(x)
+
+/*const char* icalenum_value_kind_to_string(icalvalue_kind kind);*/
+#define icalenum_value_kind_to_string(x) icalvalue_kind_to_string(x)
+
+/*const char* icalenum_component_kind_to_string(icalcomponent_kind kind);*/
+#define icalenum_component_kind_to_string(x) icalcomponent_kind_to_string(x)
+
+/*icalcomponent_kind icalenum_string_to_component_kind(const char* string);*/
+#define icalenum_string_to_component_kind(x) icalcomponent_string_to_kind(x)
+
+
+#endif /* !ICALENUMS_H */
+
diff --git a/src/plugins/vcalendar/libical/libical/icalerror.c b/src/plugins/vcalendar/libical/libical/icalerror.c
@@ -0,0 +1,195 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalerror.c
+ CREATOR: eric 16 May 1999
+
+ $Id$
+ $Locker$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalerror.c
+
+ ======================================================================*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "icalerror.h"
+
+icalerrorenum icalerrno;
+
+int foo;
+void icalerror_stop_here(void)
+{
+ foo++; /* Keep optimizers from removing routine */
+}
+
+void icalerror_crash_here(void)
+{
+ int *p=0;
+ *p = 1;
+
+ assert( *p);
+}
+
+
+void icalerror_clear_errno() {
+
+ icalerrno = ICAL_NO_ERROR;
+}
+
+#ifdef ICAL_ERRORS_ARE_FATAL
+int icalerror_errors_are_fatal = 1;
+#else
+int icalerror_errors_are_fatal = 0;
+#endif
+
+struct icalerror_state {
+ icalerrorenum error;
+ icalerrorstate state;
+};
+
+struct icalerror_state error_state_map[] =
+{
+ { ICAL_BADARG_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_NEWFAILED_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_PARSE_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_INTERNAL_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_FILE_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_USAGE_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_UNIMPLEMENTED_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_UNKNOWN_ERROR,ICAL_ERROR_DEFAULT},
+ { ICAL_NO_ERROR,ICAL_ERROR_DEFAULT}
+
+};
+
+struct icalerror_string_map {
+ const char* str;
+ icalerrorenum error;
+ char name[160];
+};
+
+static struct icalerror_string_map string_map[] =
+{
+ {"BADARG",ICAL_BADARG_ERROR,"BADARG: Bad argument to function"},
+ { "NEWFAILED",ICAL_NEWFAILED_ERROR,"NEWFAILED: Failed to create a new object via a *_new() routine"},
+ {"MALFORMEDDATA",ICAL_MALFORMEDDATA_ERROR,"MALFORMEDDATA: An input string was not correctly formed or a component has missing or extra properties"},
+ { "PARSE",ICAL_PARSE_ERROR,"PARSE: Failed to parse a part of an iCal component"},
+ {"INTERNAL",ICAL_INTERNAL_ERROR,"INTERNAL: Random internal error. This indicates an error in the library code, not an error in use"},
+ { "FILE",ICAL_FILE_ERROR,"FILE: An operation on a file failed. Check errno for more detail."},
+ { "USAGE",ICAL_USAGE_ERROR,"USAGE: Failed to propertyl sequence calls to a set of interfaces"},
+ { "UNIMPLEMENTED",ICAL_UNIMPLEMENTED_ERROR,"UNIMPLEMENTED: This feature has not been implemented"},
+ { "NO",ICAL_NO_ERROR,"NO: No error"},
+ {"UNKNOWN",ICAL_UNKNOWN_ERROR,"UNKNOWN: Unknown error type -- icalerror_strerror() was probably given bad input"}
+};
+
+
+icalerrorenum icalerror_error_from_string(const char* str){
+
+ icalerrorenum e = ICAL_UNKNOWN_ERROR;
+ int i = 0;
+
+ for( i = 0; string_map[i].error != ICAL_NO_ERROR; i++){
+ if (strcmp(string_map[i].str,str) == 0){
+ e = string_map[i].error;
+ }
+ }
+
+ return e;
+}
+
+icalerrorstate icalerror_supress(const char* error){
+
+ icalerrorenum e = icalerror_error_from_string(error);
+ icalerrorstate es;
+
+ if (e == ICAL_NO_ERROR){
+ return ICAL_ERROR_UNKNOWN;
+ }
+
+
+ es = icalerror_get_error_state(e);
+ icalerror_set_error_state(e,ICAL_ERROR_NONFATAL);
+
+ return es;
+}
+
+char* icalerror_perror()
+{
+ return icalerror_strerror(icalerrno);
+}
+
+void icalerror_restore(const char* error, icalerrorstate es){
+
+
+ icalerrorenum e = icalerror_error_from_string(error);
+
+ if (e != ICAL_NO_ERROR){
+ icalerror_set_error_state(e,es);
+ }
+
+}
+
+
+
+void icalerror_set_error_state( icalerrorenum error,
+ icalerrorstate state)
+{
+ int i;
+
+ for(i = ICAL_BADARG_ERROR; error_state_map[i].error!= ICAL_NO_ERROR;i++){
+ if(error_state_map[i].error == error){
+ error_state_map[i].state = state;
+ }
+ }
+}
+
+icalerrorstate icalerror_get_error_state( icalerrorenum error)
+{
+ int i;
+
+ for(i = ICAL_BADARG_ERROR; error_state_map[i].error!= ICAL_NO_ERROR;i++){
+ if(error_state_map[i].error == error){
+ return error_state_map[i].state;
+ }
+ }
+
+ return ICAL_ERROR_UNKNOWN;
+}
+
+
+
+
+char* icalerror_strerror(icalerrorenum e) {
+
+ int i;
+
+ for (i=0; string_map[i].error != ICAL_UNKNOWN_ERROR; i++) {
+ if (string_map[i].error == e) {
+ return string_map[i].name;
+ }
+ }
+
+ return string_map[i].name; /* Return string for ICAL_UNKNOWN_ERROR*/
+
+}
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalerror.h b/src/plugins/vcalendar/libical/libical/icalerror.h
@@ -0,0 +1,153 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalerror.h
+ CREATOR: eric 09 May 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalerror.h
+
+======================================================================*/
+
+
+#ifndef ICALERROR_H
+#define ICALERROR_H
+
+#include <assert.h>
+#include <stdio.h> /* For icalerror_warn() */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+/* This routine is called before any error is triggered. It is called
+ by icalerror_set_errno, so it does not appear in all of the macros
+ below */
+void icalerror_stop_here(void);
+
+void icalerror_crash_here(void);
+
+typedef enum icalerrorenum {
+
+ ICAL_BADARG_ERROR,
+ ICAL_NEWFAILED_ERROR,
+ ICAL_ALLOCATION_ERROR,
+ ICAL_MALFORMEDDATA_ERROR,
+ ICAL_PARSE_ERROR,
+ ICAL_INTERNAL_ERROR, /* Like assert --internal consist. prob */
+ ICAL_FILE_ERROR,
+ ICAL_USAGE_ERROR,
+ ICAL_UNIMPLEMENTED_ERROR,
+ ICAL_UNKNOWN_ERROR, /* Used for problems in input to icalerror_strerror()*/
+ ICAL_NO_ERROR
+
+} icalerrorenum;
+
+/* The libical error enumeration, like errno*/
+extern icalerrorenum icalerrno;
+
+/* If true, libicl aborts after a call to icalerror_set_error*/
+extern int icalerror_errors_are_fatal;
+
+/* Warning messages */
+
+#ifdef __GNUC__ca
+#define icalerror_warn(message) {fprintf(stderr,"%s(), %s:%d: %s\n",__FUNCTION__,__FILE__,__LINE__,message);}
+#else /* __GNU_C__ */
+#define icalerror_warn(message) {fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,message);}
+#endif /* __GNU_C__ */
+
+
+void icalerror_clear_errno(void);
+void _icalerror_set_errno(icalerrorenum);
+
+/* Make an individual error fatal or non-fatal. */
+typedef enum icalerrorstate {
+ ICAL_ERROR_FATAL, /* Not fata */
+ ICAL_ERROR_NONFATAL, /* Fatal */
+ ICAL_ERROR_DEFAULT, /* Use the value of icalerror_errors_are_fatal*/
+ ICAL_ERROR_UNKNOWN /* Asked state for an unknown error type */
+} icalerrorstate ;
+
+char* icalerror_strerror(icalerrorenum e);
+char* icalerror_perror();
+void icalerror_set_error_state( icalerrorenum error, icalerrorstate);
+icalerrorstate icalerror_get_error_state( icalerrorenum error);
+
+
+#define icalerror_set_errno(x) \
+icalerrno = x; \
+if(icalerror_get_error_state(x)==ICAL_ERROR_FATAL || \
+ (icalerror_get_error_state(x)==ICAL_ERROR_DEFAULT && \
+ icalerror_errors_are_fatal == 1 )){ \
+ icalerror_warn(icalerror_strerror(x)); \
+ assert(0); \
+}
+
+
+#ifdef ICAL_ERRORS_ARE_FATAL
+#undef NDEBUG
+#endif
+
+#define icalerror_check_value_type(value,type);
+#define icalerror_check_property_type(value,type);
+#define icalerror_check_parameter_type(value,type);
+#define icalerror_check_component_type(value,type);
+
+/* Assert with a message */
+#ifdef ICAL_ERRORS_ARE_FATAL
+
+#ifdef __GNUC__
+#define icalerror_assert(test,message) if(!(test)){fprintf(stderr,"%s(), %s:%d: %s\n",__FUNCTION__,__FILE__,__LINE__,message);icalerror_stop_here(); abort();}
+#else /*__GNUC__*/
+#define icalerror_assert(test,message) if(!(test)){fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,message);icalerror_stop_here(); abort();}
+#endif /*__GNUC__*/
+
+#else /* ICAL_ERRORS_ARE_FATAL */
+#define icalerror_assert(test,message)
+#endif /* ICAL_ERRORS_ARE_FATAL */
+
+/* Check & abort if check fails */
+#define icalerror_check_arg(test,arg) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); }
+
+/* Check & return void if check fails*/
+#define icalerror_check_arg_rv(test,arg) if(!(test)) {icalerror_set_errno(ICAL_BADARG_ERROR); return; }
+
+/* Check & return 0 if check fails*/
+#define icalerror_check_arg_rz(test,arg) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); return 0;}
+
+/* Check & return an error if check fails*/
+#define icalerror_check_arg_re(test,arg,error) if(!(test)) { icalerror_stop_here(); assert(0); return error;}
+
+/* Check & return something*/
+#define icalerror_check_arg_rx(test,arg,x) if(!(test)) { icalerror_set_errno(ICAL_BADARG_ERROR); return x;}
+
+
+
+/* String interfaces to set an error to NONFATAL and restore it to its
+ original value */
+
+icalerrorstate icalerror_supress(const char* error);
+void icalerror_restore(const char* error, icalerrorstate es);
+
+
+#endif /* !ICALERROR_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icallangbind.c b/src/plugins/vcalendar/libical/libical/icallangbind.c
@@ -0,0 +1,272 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icallangbind.c
+ CREATOR: eric 15 dec 2000
+
+ DESCRIPTION:
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 1999 Eric Busboom
+ http://www.softwarestudio.org
+
+ This package is free software and is provided "as is" without
+ express or implied warranty. It may be used, redistributed and/or
+ modified under the same terms as perl itself. ( Either the Artistic
+ License or the GPL. )
+
+ ======================================================================*/
+
+#include "icalcomponent.h"
+#include "icalproperty.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+#include <malloc.h>
+#include <string.h>
+
+int* icallangbind_new_array(int size){
+ int* p = (int*)malloc(size*sizeof(int));
+ return p; /* Caller handles failures */
+}
+
+void icallangbind_free_array(int* array){
+ free(array);
+}
+
+int icallangbind_access_array(int* array, int index) {
+ return array[index];
+}
+
+
+
+/* LIke icalcomponent_get_first_component, buut takes a string for the
+ kind and can iterate over X properties as if each X name was a
+ seperate kind */
+icalproperty* icallangbind_get_first_property(icalcomponent *c,
+ const char* prop)
+{
+ icalproperty_kind kind = icalproperty_string_to_kind(prop);
+ icalproperty *p;
+
+ if (kind == ICAL_NO_PROPERTY){
+ return 0;
+ }
+
+ if(kind == ICAL_X_PROPERTY){
+ for(p = icalcomponent_get_first_property(c,kind);
+ p !=0;
+ p = icalcomponent_get_next_property(c,kind)){
+
+ if(strcmp(icalproperty_get_x_name(p),prop) == 0){
+ return p;
+ }
+ }
+ } else {
+ p=icalcomponent_get_first_property(c,kind);
+
+ return p;
+ }
+
+ return 0;
+
+}
+
+icalproperty* icallangbind_get_next_property(icalcomponent *c,
+ const char* prop)
+{
+ icalproperty_kind kind = icalenum_string_to_property_kind(prop);
+ icalproperty *p;
+
+ if (kind == ICAL_NO_PROPERTY){
+ return 0;
+ }
+
+ if(kind == ICAL_X_PROPERTY){
+ for(p = icalcomponent_get_next_property(c,kind);
+ p !=0;
+ p = icalcomponent_get_next_property(c,kind)){
+
+ if(strcmp(icalproperty_get_x_name(p),prop) == 0){
+ return p;
+ }
+ }
+ } else {
+ p=icalcomponent_get_next_property(c,kind);
+
+ return p;
+ }
+
+ return 0;
+
+}
+
+
+icalcomponent* icallangbind_get_first_component(icalcomponent *c,
+ const char* comp)
+{
+ icalcomponent_kind kind = icalenum_string_to_component_kind(comp);
+
+ if (kind == ICAL_NO_COMPONENT){
+ return 0;
+ }
+ return icalcomponent_get_first_component(c,kind);
+}
+
+icalcomponent* icallangbind_get_next_component(icalcomponent *c,
+ const char* comp)
+{
+ icalcomponent_kind kind = icalenum_string_to_component_kind(comp);
+
+ if (kind == ICAL_NO_COMPONENT){
+ return 0;
+ }
+ return icalcomponent_get_next_component(c,kind);
+}
+
+
+#define APPENDS(x) icalmemory_append_string(&buf, &buf_ptr, &buf_size, x);
+
+#define APPENDC(x) icalmemory_append_char(&buf, &buf_ptr, &buf_size, x);
+
+const char* icallangbind_property_eval_string(icalproperty* prop, char* sep)
+{
+ char tmp[25];
+ size_t buf_size = 1024;
+ char* buf = icalmemory_new_buffer(buf_size);
+ char* buf_ptr = buf;
+ icalparameter *param;
+
+ icalvalue* value;
+
+ if( prop == 0){
+ return 0;
+ }
+
+ APPENDS("{ ");
+
+ value = icalproperty_get_value(prop);
+
+ APPENDS(" 'name' ");
+ APPENDS(sep);
+ APPENDC('\'');
+ APPENDS(icalenum_property_kind_to_string(icalproperty_isa(prop)));
+ APPENDC('\'');
+
+ if(value){
+ APPENDS(", 'value_type' ");
+ APPENDS(sep);
+ APPENDC('\'');
+ APPENDS(icalenum_value_kind_to_string(icalvalue_isa(value)));
+ APPENDC('\'');
+ }
+
+ APPENDS(", 'pid' ");
+ APPENDS(sep);
+ APPENDC('\'');
+ snprintf(tmp,25,"%p",prop);
+ APPENDS(tmp);
+ APPENDC('\'');
+
+
+ if(value){
+ switch (icalvalue_isa(value)){
+
+ case ICAL_ATTACH_VALUE:
+ case ICAL_BINARY_VALUE:
+ case ICAL_NO_VALUE: {
+ icalerror_set_errno(ICAL_INTERNAL_ERROR);
+ break;
+ }
+
+ default:
+ {
+ const char* str = icalvalue_as_ical_string(value);
+ char* copy = (char*) malloc(strlen(str)+1);
+
+ const char *i;
+ char *j;
+
+ if(copy ==0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ break;
+ }
+ /* Remove any newlines */
+
+ for(j=copy, i = str; *i != 0; j++,i++){
+ if(*i=='\n'){
+ i++;
+ }
+ *j = *i;
+ }
+
+ *j = 0;
+
+ APPENDS(", 'value'");
+ APPENDS(sep);
+ APPENDC('\'');
+ APPENDS(copy);
+ APPENDC('\'');
+
+ free(copy);
+ break;
+
+ }
+ }
+ }
+
+ /* Add Parameters */
+
+ for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
+ param != 0;
+ param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)){
+
+ const char* str = icalparameter_as_ical_string(param);
+ char *copy = icalmemory_tmp_copy(str);
+ char *v;
+
+ if(copy == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ continue;
+ }
+
+ v = strchr(copy,'=');
+
+
+ if(v == 0){
+ continue;
+ }
+
+ *v = 0;
+
+ v++;
+
+ APPENDS(", ");
+ APPENDC('\'');
+ APPENDS(copy);
+ APPENDC('\'');
+ APPENDS(sep);
+ APPENDC('\'');
+ APPENDS(v);
+ APPENDC('\'');
+
+ }
+
+
+ APPENDC('}');
+
+ icalmemory_add_tmp_buffer(buf);
+ return buf;
+
+}
+
+#include "fcntl.h"
+int icallangbind_string_to_open_flag(const char* str)
+{
+ if (strcmp(str,"r") == 0) {return O_RDONLY;}
+ else if (strcmp(str,"r+") == 0) {return O_RDWR;}
+ else if (strcmp(str,"w") == 0) {return O_WRONLY;}
+ else if (strcmp(str,"a") == 0) {return O_WRONLY|O_APPEND;}
+ else return -1;
+}
+
diff --git a/src/plugins/vcalendar/libical/libical/icallangbind.h b/src/plugins/vcalendar/libical/libical/icallangbind.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icallangbind.h
+ CREATOR: eric 25 jan 2001
+
+ DESCRIPTION:
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 1999 Eric Busboom
+ http://www.softwarestudio.org
+
+ This package is free software and is provided "as is" without
+ express or implied warranty. It may be used, redistributed and/or
+ modified under the same terms as perl itself. ( Either the Artistic
+ License or the GPL. )
+
+ ======================================================================*/
+
+#ifndef __ICALLANGBIND_H__
+#define __ICALLANGBIND_H__
+
+int* icallangbind_new_array(int size);
+void icallangbind_free_array(int* array);
+int icallangbind_access_array(int* array, int index);
+icalproperty* icallangbind_get_property(icalcomponent *c, int n, const char* prop);
+const char* icallangbind_get_property_val(icalproperty* p);
+const char* icallangbind_get_parameter(icalproperty *p, const char* parameter);
+icalcomponent* icallangbind_get_component(icalcomponent *c, const char* comp);
+
+icalproperty* icallangbind_get_first_property(icalcomponent *c,
+ const char* prop);
+
+icalproperty* icallangbind_get_next_property(icalcomponent *c,
+ const char* prop);
+
+icalcomponent* icallangbind_get_first_component(icalcomponent *c,
+ const char* comp);
+
+icalcomponent* icallangbind_get_next_component(icalcomponent *c,
+ const char* comp);
+
+
+const char* icallangbind_property_eval_string(icalproperty* prop, char* sep);
+
+
+int icallangbind_string_to_open_flag(const char* str);
+#endif /*__ICALLANGBIND_H__*/
diff --git a/src/plugins/vcalendar/libical/libical/icallexer.l b/src/plugins/vcalendar/libical/libical/icallexer.l
@@ -0,0 +1,168 @@
+%{
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icallexer.l
+ CREATOR: eric 10 June 1999
+
+ DESCRIPTION:
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 1999 Eric Busboom
+ http://www.softwarestudio.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+ The original author is Eric Busboom
+ The original code is icalitip.y
+
+
+
+ ======================================================================*/
+#include "icalparser.h"
+#include "icalenums.h"
+#include "icalmemory.h"
+#include "assert.h"
+#include "icalyacc.h"
+
+#include <string.h> /* For strdup() */
+
+int icalparser_flex_input(char* buf, int max_size);
+void icalparser_clear_flex_input(void);
+
+
+#define ICAL_MAX_STR_CONST 1024
+
+#undef YY_INPUT
+#define YY_INPUT(b,r,ms) ( r= icalparser_flex_input(b,ms))
+#undef yywrap
+
+#undef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) ical_yyerror(msg)
+
+icalvalue_kind value_kind=ICAL_NO_VALUE;
+void set_parser_value_state(icalvalue_kind kind);
+extern int yydebug;
+
+void ical_yyerror(char *s);
+
+void init_str_buf(void);
+
+int last_state;
+
+char *str_buf;
+char *str_buf_p;
+size_t buf_sz; /* = ICAL_MAX_STR_CONST;*/
+
+/* Define routines that were not propertly defined because of the
+renaming hack applied in icalyacc.y */
+YY_BUFFER_STATE ical_yy_scan_buffer ( char *base, yy_size_t size );
+YY_BUFFER_STATE ical_yy_scan_string ( yyconst char *yy_str );
+YY_BUFFER_STATE ical_yy_scan_bytes ( yyconst char *bytes, int len );
+
+%}
+
+crlf \x0D?\x0A
+space [ ]
+qsafechar [^\x00-\x1F\"]
+safechar [^\x00-\x1F\"\:\;\,]
+tsafechar [\x20-\x21\x23-\x2B\x2D-\x39\x3C-\x5B\x5D-\x7E]
+valuechar [^\x00-\x08\x10-\x1F]
+xname X-[a-zA-Z0-9\-]+
+xname2 [a-zA-Z0-9\-\ ]
+paramtext {safechar}+
+value {valuechar}+
+quotedstring \"{qsafechar}+\"
+digit [0-9]
+
+%array /* Make yytext an array. Slow, but handy. HACK */
+
+%option caseless
+
+%s quoted_string
+%s binary_value boolean_value uri_value time_value duration_value number_value period_value recur_value text_value utcoffset_value
+%s enum_param_value string_param_value stringlist_param_value keyword line_start component seperator parameter end_of_value paramtext
+
+
+
+%%
+
+%{
+%}
+
+
+
+<time_value>{
+{digit}+ { ical_yylval.v_string =icalmemory_tmp_copy(yytext) ;
+ return DIGITS; }
+T { return TIME_CHAR; }
+Z { return UTC_CHAR; }
+[\/\+\-PWHMSD] { return yytext[0]; }
+{crlf} { return EOL;}
+
+}
+
+<utcoffset_value>{
+{crlf} { return EOL;}
+\-|\+ { return yytext[0]; }
+{digit}{digit} { ical_yylval.v_int=atoi(yytext); return INTNUMBER; }
+
+}
+
+<enum_param_value>{
+. { return CHARACTER; }
+{crlf} { return EOL;}
+
+}
+
+<seperator>{
+, { BEGIN(last_state); return COMMA; }
+}
+
+
+%%
+
+int yywrap()
+{
+ return 1;
+}
+
+
+void set_parser_value_state(icalvalue_kind kind)
+{
+
+ switch (kind){
+
+ case ICAL_UTCOFFSET_VALUE:
+ {BEGIN(utcoffset_value);break;}
+
+ case ICAL_DATETIMEPERIOD_VALUE:
+ case ICAL_DURATION_VALUE:
+ case ICAL_PERIOD_VALUE:
+ {BEGIN(time_value);break;}
+
+ default:
+ {
+ assert(1==0);
+ }
+ }
+}
+
+void init_str_buf(void)
+{
+ str_buf = icalmemory_tmp_buffer(ICAL_MAX_STR_CONST);
+ str_buf_p = str_buf;
+ buf_sz = ICAL_MAX_STR_CONST;
+
+
+}
+
diff --git a/src/plugins/vcalendar/libical/libical/icalmemory.c b/src/plugins/vcalendar/libical/libical/icalmemory.c
@@ -0,0 +1,287 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalmemory.c
+ CREATOR: eric 30 June 1999
+
+ $Id$
+ $Locker$
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+
+ 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 icalmemory.h
+
+ ======================================================================*/
+
+/* libical often passes strings back to the caller. To make these
+ * interfaces simple, I did not want the caller to have to pass in a
+ * memory buffer, but having libical pass out newly allocated memory
+ * makes it difficult to de-allocate the memory.
+ *
+ * The ring buffer in this scheme makes it possible for libical to pass
+ * out references to memory which the caller does not own, and be able
+ * to de-allocate the memory later. The ring allows libical to have
+ * several buffers active simultaneously, which is handy when creating
+ * string representations of components. */
+
+#define ICALMEMORY_C
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef DMALLOC
+#include "dmalloc.h"
+#endif
+
+#include "icalmemory.h"
+#include "icalerror.h"
+
+#include <stdio.h> /* for printf (debugging) */
+#include <stdlib.h> /* for malloc, realloc */
+#include <string.h> /* for memset(), strdup */
+
+#define BUFFER_RING_SIZE 250
+#define MIN_BUFFER_SIZE 200
+
+void icalmemory_free_tmp_buffer (void* buf);
+
+
+/* HACK. Not threadsafe */
+void* buffer_ring[BUFFER_RING_SIZE];
+int buffer_pos = -1;
+int initialized = 0;
+
+/* Add an existing buffer to the buffer ring */
+void icalmemory_add_tmp_buffer(void* buf)
+{
+ /* I don't think I need this -- I think static arrays are
+ initialized to 0 as a standard part of C, but I am not sure. */
+ if (initialized == 0){
+ int i;
+ for(i=0; i<BUFFER_RING_SIZE; i++){
+ buffer_ring[i] = 0;
+ }
+ initialized = 1;
+ }
+
+ /* Wrap around the ring */
+ if(++buffer_pos == BUFFER_RING_SIZE){
+ buffer_pos = 0;
+ }
+
+ /* Free buffers as their slots are overwritten */
+ if ( buffer_ring[buffer_pos] != 0){
+ free( buffer_ring[buffer_pos]);
+ buffer_ring[buffer_pos] = 0;
+ }
+
+ /* Assign the buffer to a slot */
+ buffer_ring[buffer_pos] = buf;
+}
+
+/* Create a new temporary buffer on the ring. Libical owns these and
+ wil deallocate them. */
+void*
+icalmemory_tmp_buffer (size_t size)
+{
+ char *buf;
+
+ if (size < MIN_BUFFER_SIZE){
+ size = MIN_BUFFER_SIZE;
+ }
+
+ buf = (void*)malloc(size);
+
+ if( buf == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ memset(buf,0,size);
+
+ icalmemory_add_tmp_buffer(buf);
+
+ return buf;
+}
+
+void icalmemory_free_ring()
+{
+
+ int i;
+ for(i=0; i<BUFFER_RING_SIZE; i++){
+ if ( buffer_ring[i] != 0){
+ free( buffer_ring[i]);
+ }
+ buffer_ring[i] = 0;
+ }
+
+ initialized = 1;
+
+}
+
+
+
+/* Like strdup, but the buffer is on the ring. */
+char*
+icalmemory_tmp_copy(const char* str)
+{
+ char* b = icalmemory_tmp_buffer(strlen(str)+1);
+
+ strcpy(b,str);
+
+ return b;
+}
+
+
+char* icalmemory_strdup(const char *s)
+{
+ return strdup(s);
+}
+
+void
+icalmemory_free_tmp_buffer (void* buf)
+{
+ if(buf == 0)
+ {
+ return;
+ }
+
+ free(buf);
+}
+
+
+/* These buffer routines create memory the old fashioned way -- so the
+ caller will have to delocate the new memory */
+
+void* icalmemory_new_buffer(size_t size)
+{
+ void *b = malloc(size);
+
+ if( b == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ memset(b,0,size);
+
+ return b;
+}
+
+void* icalmemory_resize_buffer(void* buf, size_t size)
+{
+ void *b = realloc(buf, size);
+
+ if( b == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ return b;
+}
+
+void icalmemory_free_buffer(void* buf)
+{
+ free(buf);
+}
+
+void
+icalmemory_append_string(char** buf, char** pos, size_t* buf_size,
+ const char* string)
+{
+ char *new_buf;
+ char *new_pos;
+
+ size_t data_length, final_length, string_length;
+
+#ifndef ICAL_NO_INTERNAL_DEBUG
+ icalerror_check_arg_rv( (buf!=0),"buf");
+ icalerror_check_arg_rv( (*buf!=0),"*buf");
+ icalerror_check_arg_rv( (pos!=0),"pos");
+ icalerror_check_arg_rv( (*pos!=0),"*pos");
+ icalerror_check_arg_rv( (buf_size!=0),"buf_size");
+ icalerror_check_arg_rv( (*buf_size!=0),"*buf_size");
+ icalerror_check_arg_rv( (string!=0),"string");
+#endif
+
+ string_length = strlen(string);
+ data_length = (size_t)*pos - (size_t)*buf;
+ final_length = data_length + string_length;
+
+ if ( final_length >= (size_t) *buf_size) {
+
+
+ *buf_size = (*buf_size) * 2 + final_length;
+
+ new_buf = realloc(*buf,*buf_size);
+
+ new_pos = (void*)((size_t)new_buf + data_length);
+
+ *pos = new_pos;
+ *buf = new_buf;
+ }
+
+ strcpy(*pos, string);
+
+ *pos += string_length;
+}
+
+
+void
+icalmemory_append_char(char** buf, char** pos, size_t* buf_size,
+ char ch)
+{
+ char *new_buf;
+ char *new_pos;
+
+ size_t data_length, final_length;
+
+#ifndef ICAL_NO_INTERNAL_DEBUG
+ icalerror_check_arg_rv( (buf!=0),"buf");
+ icalerror_check_arg_rv( (*buf!=0),"*buf");
+ icalerror_check_arg_rv( (pos!=0),"pos");
+ icalerror_check_arg_rv( (*pos!=0),"*pos");
+ icalerror_check_arg_rv( (buf_size!=0),"buf_size");
+ icalerror_check_arg_rv( (*buf_size!=0),"*buf_size");
+#endif
+
+ data_length = (size_t)*pos - (size_t)*buf;
+
+ final_length = data_length + 2;
+
+ if ( final_length > (size_t) *buf_size ) {
+
+
+ *buf_size = (*buf_size) * 2 + final_length +1;
+
+ new_buf = realloc(*buf,*buf_size);
+
+ new_pos = (void*)((size_t)new_buf + data_length);
+
+ *pos = new_pos;
+ *buf = new_buf;
+ }
+
+ **pos = ch;
+ *pos += 1;
+ **pos = 0;
+}
diff --git a/src/plugins/vcalendar/libical/libical/icalmemory.h b/src/plugins/vcalendar/libical/libical/icalmemory.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalmemory.h
+ CREATOR: eric 30 June 1999
+
+
+ $Id$
+ $Locker$
+
+ 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 Initial Developer of the Original Code is Eric Busboom
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+======================================================================*/
+
+#ifndef ICALMEMORY_H
+#define ICALMEMORY_H
+
+#include <sys/types.h> /* for size_t */
+
+
+/* Tmp buffers are managed by ical. References can be returned to the
+ caller, although the caller will not own the memory. */
+
+void* icalmemory_tmp_buffer(size_t size);
+char* icalmemory_tmp_copy(const char* str);
+
+/* Add an externally allocated buffer to the ring. */
+void icalmemory_add_tmp_buffer(void*);
+
+
+/* Free all memory used in the ring */
+void icalmemory_free_ring(void);
+
+/* Non-tmp buffers must be freed. These are mostly wrappers around
+ * malloc, etc, but are used so the caller can change the memory
+ * allocators in a future version of the library */
+
+void* icalmemory_new_buffer(size_t size);
+void* icalmemory_resize_buffer(void* buf, size_t size);
+void icalmemory_free_buffer(void* buf);
+
+/* icalmemory_append_string will copy the string 'string' to the
+ buffer 'buf' starting at position 'pos', reallocing 'buf' if it is
+ too small. 'buf_size' is the size of 'buf' and will be changed if
+ 'buf' is reallocated. 'pos' will point to the last byte of the new
+ string in 'buf', usually a '\0' */
+
+/* THESE ROUTINES CAN NOT BE USED ON TMP BUFFERS. Only use them on
+ normally allocated memory, or on buffers created from
+ icalmemory_new_buffer, never with buffers created by
+ icalmemory_tmp_buffer. If icalmemory_append_string has to resize a
+ buffer on the ring, the ring will loose track of it an you will
+ have memory problems. */
+
+void icalmemory_append_string(char** buf, char** pos, size_t* buf_size,
+ const char* string);
+
+/* icalmemory_append_char is similar, but is appends a character instead of a string */
+void icalmemory_append_char(char** buf, char** pos, size_t* buf_size,
+ char ch);
+
+/* A wrapper around strdup. Partly to trap calls to strdup, partly
+ because in -ansi, gcc on Red Hat claims that strudup is undeclared */
+char* icalmemory_strdup(const char *s);
+
+#endif /* !ICALMEMORY_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalmime.c b/src/plugins/vcalendar/libical/libical/icalmime.c
@@ -0,0 +1,389 @@
+/* -*- Mode: C -*-*/
+/*======================================================================
+ FILE: icalmime.c
+ CREATOR: eric 26 July 2000
+
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+======================================================================*/
+
+#include "icalmime.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "sspm.h"
+#include "stdlib.h"
+#include <string.h> /* For strdup */
+#include <stdio.h> /* for snprintf*/
+
+#ifdef DMALLOC
+#include "dmalloc.h"
+#endif
+
+
+/* These *_part routines are called by the MIME parser via the
+ local_action_map */
+
+struct text_part
+{
+ char* buf;
+ char* buf_pos;
+ size_t buf_size;
+};
+
+void* icalmime_text_new_part()
+{
+
+#define BUF_SIZE 2048
+
+ struct text_part* impl;
+
+ if ( ( impl = (struct text_part*)
+ malloc(sizeof(struct text_part))) == 0) {
+ return 0;
+ }
+
+ impl->buf = icalmemory_new_buffer(BUF_SIZE);
+ impl->buf_pos = impl->buf;
+ impl->buf_size = BUF_SIZE;
+
+ return impl;
+}
+void icalmime_text_add_line(void *part,
+ struct sspm_header *header,
+ char* line, size_t size)
+{
+ struct text_part* impl = (struct text_part*) part;
+
+ icalmemory_append_string(&(impl->buf),&(impl->buf_pos),
+ &(impl->buf_size),line);
+
+}
+
+void* icalmime_textcalendar_end_part(void* part)
+{
+
+ struct text_part* impl = (struct text_part*) part;
+ icalcomponent *c = icalparser_parse_string(impl->buf);
+
+ icalmemory_free_buffer(impl->buf);
+ free(impl);
+
+ return c;
+
+}
+
+void* icalmime_text_end_part(void* part)
+{
+ struct text_part* impl = ( struct text_part*) part;
+ char *buf;
+
+ icalmemory_add_tmp_buffer(impl->buf);
+ buf = impl->buf;
+
+ free(impl);
+
+ return impl->buf;
+}
+
+void icalmime_text_free_part(void *part)
+{
+ part = part;
+}
+
+
+/* Ignore Attachments for now */
+
+void* icalmime_attachment_new_part()
+{
+ return 0;
+}
+void icalmime_attachment_add_line(void *part, struct sspm_header *header,
+ char* line, size_t size)
+{
+ part = part;
+ header = header;
+ line = line;
+ size = size;
+}
+
+void* icalmime_attachment_end_part(void* part)
+{
+ return 0;
+}
+
+void icalmime_attachment_free_part(void *part)
+{
+}
+
+
+
+
+struct sspm_action_map icalmime_local_action_map[] =
+{
+ {SSPM_TEXT_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_textcalendar_end_part,icalmime_text_free_part},
+ {SSPM_TEXT_MAJOR_TYPE,SSPM_ANY_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part},
+ {SSPM_TEXT_MAJOR_TYPE,SSPM_PLAIN_MINOR_TYPE,icalmime_text_new_part,icalmime_text_add_line,icalmime_text_end_part,icalmime_text_free_part},
+ {SSPM_APPLICATION_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
+ {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
+ {SSPM_AUDIO_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
+ {SSPM_IMAGE_MAJOR_TYPE,SSPM_CALENDAR_MINOR_TYPE,icalmime_attachment_new_part,icalmime_attachment_add_line,icalmime_attachment_end_part,icalmime_attachment_free_part},
+ {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,0,0,0,0}
+};
+
+#define NUM_PARTS 100 /* HACK. Hard Limit */
+
+
+
+struct sspm_part* icalmime_make_part(icalcomponent* comp)
+{
+ comp = comp;
+ return 0;
+}
+
+char* icalmime_as_mime_string(char* icalcomponent);
+
+icalcomponent* icalmime_parse(char* (*get_string)(char *s, size_t size,
+ void *d),
+ void *data)
+{
+ struct sspm_part *parts;
+ int i, last_level=0;
+ icalcomponent *root=0, *parent=0, *comp=0, *last = 0;
+
+ if ( (parts = (struct sspm_part *)
+ malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ memset(parts,0,sizeof(parts));
+
+ sspm_parse_mime(parts,
+ NUM_PARTS, /* Max parts */
+ icalmime_local_action_map, /* Actions */
+ get_string,
+ data, /* data for get_string*/
+ 0 /* First header */);
+
+
+
+ for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ; i++){
+
+#define TMPSZ 1024
+ char mimetype[TMPSZ];
+ char* major = sspm_major_type_string(parts[i].header.major);
+ char* minor = sspm_minor_type_string(parts[i].header.minor);
+
+ if(parts[i].header.minor == SSPM_UNKNOWN_MINOR_TYPE ){
+ assert(parts[i].header.minor_text !=0);
+ minor = parts[i].header.minor_text;
+ }
+
+ sprintf(mimetype,"%s/%s",major,minor);
+
+ comp = icalcomponent_new(ICAL_XLICMIMEPART_COMPONENT);
+
+ if(comp == 0){
+ /* HACK Handle Error */
+ assert(0);
+ }
+
+ if(parts[i].header.error!=SSPM_NO_ERROR){
+ char *str = NULL;
+ char* temp[256];
+
+ if(parts[i].header.error==SSPM_UNEXPECTED_BOUNDARY_ERROR){
+ str = "Got an unexpected boundary, possibly due to a MIME header for a MULTIPART part that is missing the Content-Type line";
+ }
+
+ if(parts[i].header.error==SSPM_WRONG_BOUNDARY_ERROR){
+ str = "Got the wrong boundary for the opening of a MULTIPART part.";
+ }
+
+ if(parts[i].header.error==SSPM_NO_BOUNDARY_ERROR){
+ str = "Got a multipart header that did not specify a boundary";
+ }
+
+ if(parts[i].header.error==SSPM_NO_HEADER_ERROR){
+ str = "Did not get a header for the part. Is there a blank\
+line between the header and the previous boundary\?";
+
+ }
+
+ if(parts[i].header.error_text != 0){
+ snprintf((char*)temp,256,
+ "%s: %s",str,parts[i].header.error_text);
+ } else {
+ strcpy((char*)temp,str);
+ }
+
+ icalcomponent_add_property
+ (comp,
+ icalproperty_vanew_xlicerror(
+ (char*)temp,
+ icalparameter_new_xlicerrortype(
+ ICAL_XLICERRORTYPE_MIMEPARSEERROR),
+ 0));
+ }
+
+ if(parts[i].header.major != SSPM_NO_MAJOR_TYPE &&
+ parts[i].header.major != SSPM_UNKNOWN_MAJOR_TYPE){
+
+ icalcomponent_add_property(comp,
+ icalproperty_new_xlicmimecontenttype((char*)
+ icalmemory_strdup(mimetype)));
+
+ }
+
+ if (parts[i].header.encoding != SSPM_NO_ENCODING){
+
+ icalcomponent_add_property(comp,
+ icalproperty_new_xlicmimeencoding(
+ sspm_encoding_string(parts[i].header.encoding)));
+ }
+
+ if (parts[i].header.filename != 0){
+ icalcomponent_add_property(comp,
+ icalproperty_new_xlicmimefilename(parts[i].header.filename));
+ }
+
+ if (parts[i].header.content_id != 0){
+ icalcomponent_add_property(comp,
+ icalproperty_new_xlicmimecid(parts[i].header.content_id));
+ }
+
+ if (parts[i].header.charset != 0){
+ icalcomponent_add_property(comp,
+ icalproperty_new_xlicmimecharset(parts[i].header.charset));
+ }
+
+ /* Add iCal components as children of the component */
+ if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
+ parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE &&
+ parts[i].data != 0){
+
+ icalcomponent_add_component(comp,
+ (icalcomponent*)parts[i].data);
+ parts[i].data = 0;
+
+ } else if(parts[i].header.major == SSPM_TEXT_MAJOR_TYPE &&
+ parts[i].header.minor != SSPM_CALENDAR_MINOR_TYPE &&
+ parts[i].data != 0){
+
+ /* Add other text components as "DESCRIPTION" properties */
+
+ icalcomponent_add_property(comp,
+ icalproperty_new_description(
+ (char*)icalmemory_strdup((char*)parts[i].data)));
+
+ parts[i].data = 0;
+ }
+
+
+ if(root!= 0 && parts[i].level == 0){
+ /* We've already assigned the root, but there is another
+ part at the root level. This is probably a parse
+ error*/
+ icalcomponent_free(comp);
+ continue;
+ }
+
+ if(parts[i].level == last_level && last_level != 0){
+ icalerror_assert(parent!=0,"No parent for adding component");
+
+ icalcomponent_add_component(parent,comp);
+
+ } else if (parts[i].level == last_level && last_level == 0 &&
+ root == 0) {
+
+ root = comp;
+ parent = comp;
+
+ } else if (parts[i].level > last_level){
+
+ parent = last;
+ icalcomponent_add_component(parent,comp);
+
+ last_level = parts[i].level;
+
+ } else if (parts[i].level < last_level){
+
+ parent = icalcomponent_get_parent(parent);
+ icalcomponent_add_component(parent,comp);
+
+ last_level = parts[i].level;
+ } else {
+ assert(0);
+ }
+
+ last = comp;
+ last_level = parts[i].level;
+ assert(parts[i].data == 0);
+ }
+
+ sspm_free_parts(parts,NUM_PARTS);
+ free(parts);
+
+ return root;
+}
+
+
+
+int icalmime_test(char* (*get_string)(char *s, size_t size, void *d),
+ void *data)
+{
+ char *out;
+ struct sspm_part *parts;
+ int i;
+
+ if ( (parts = (struct sspm_part *)
+ malloc(NUM_PARTS*sizeof(struct sspm_part)))==0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ memset(parts,0,sizeof(parts));
+
+ sspm_parse_mime(parts,
+ NUM_PARTS, /* Max parts */
+ icalmime_local_action_map, /* Actions */
+ get_string,
+ data, /* data for get_string*/
+ 0 /* First header */);
+
+ for(i = 0; i <NUM_PARTS && parts[i].header.major != SSPM_NO_MAJOR_TYPE ;
+ i++){
+ if(parts[i].header.minor == SSPM_CALENDAR_MINOR_TYPE){
+ parts[i].data = icalmemory_strdup(
+ icalcomponent_as_ical_string((icalcomponent*)parts[i].data));
+ }
+ }
+
+ sspm_write_mime(parts,NUM_PARTS,&out,"To: bob@bob.org");
+
+ printf("%s\n",out);
+
+ return 0;
+
+}
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalmime.h b/src/plugins/vcalendar/libical/libical/icalmime.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalmime.h
+ CREATOR: eric 26 July 2000
+
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+======================================================================*/
+
+#ifndef ICALMIME_H
+#define ICALMIME_H
+
+#include "icalcomponent.h"
+#include "icalparser.h"
+
+icalcomponent* icalmime_parse( char* (*line_gen_func)(char *s, size_t size,
+ void *d),
+ void *data);
+
+/* The inverse of icalmime_parse, not implemented yet. Use sspm.h directly. */
+char* icalmime_as_mime_string(char* component);
+
+
+
+#endif /* !ICALMIME_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalparameter.c b/src/plugins/vcalendar/libical/libical/icalparameter.c
@@ -0,0 +1,382 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalderivedparameters.{c,h}
+ CREATOR: eric 09 May 1999
+
+ $Id$
+ $Locker$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalderivedparameters.{c,h}
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+ ======================================================================*/
+/*#line 29 "icalparameter.c.in"*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "icalparameter.h"
+#include "icalproperty.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "icalparameterimpl.h"
+
+#include <stdlib.h> /* for malloc() */
+#include <errno.h>
+#include <string.h> /* for memset() */
+
+/* In icalderivedparameter */
+icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind,const char* val);
+
+
+struct icalparameter_impl* icalparameter_new_impl(icalparameter_kind kind)
+{
+ struct icalparameter_impl* v;
+
+ if ( ( v = (struct icalparameter_impl*)
+ malloc(sizeof(struct icalparameter_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ strcpy(v->id,"para");
+
+ v->kind = kind;
+ v->size = 0;
+ v->string = 0;
+ v->x_name = 0;
+ v->parent = 0;
+ v->data = 0;
+
+ return v;
+}
+
+icalparameter*
+icalparameter_new (icalparameter_kind kind)
+{
+ struct icalparameter_impl* v = icalparameter_new_impl(kind);
+
+ return (icalparameter*) v;
+
+}
+
+void
+icalparameter_free (icalparameter* parameter)
+{
+ struct icalparameter_impl * impl;
+
+ impl = (struct icalparameter_impl*)parameter;
+
+/* HACK. This always triggers, even when parameter is non-zero
+ icalerror_check_arg_rv((parameter==0),"parameter");*/
+
+
+#ifdef ICAL_FREE_ON_LIST_IS_ERROR
+ icalerror_assert( (impl->parent ==0),"Tried to free a parameter that is still attached to a component. ");
+
+#else
+ if(impl->parent !=0){
+ return;
+ }
+#endif
+
+
+ if (impl->string != 0){
+ free ((void*)impl->string);
+ }
+
+ if (impl->x_name != 0){
+ free ((void*)impl->x_name);
+ }
+
+ memset(impl,0,sizeof(impl));
+
+ impl->parent = 0;
+ impl->id[0] = 'X';
+ free(impl);
+}
+
+
+
+icalparameter*
+icalparameter_new_clone(icalparameter* param)
+{
+ struct icalparameter_impl *old;
+ struct icalparameter_impl *new;
+
+ old = (struct icalparameter_impl *)param;
+ new = icalparameter_new_impl(old->kind);
+
+ icalerror_check_arg_rz((param!=0),"param");
+
+ if (new == 0){
+ return 0;
+ }
+
+ memcpy(new,old,sizeof(struct icalparameter_impl));
+
+ if (old->string != 0){
+ new->string = icalmemory_strdup(old->string);
+ if (new->string == 0){
+ icalparameter_free(new);
+ return 0;
+ }
+ }
+
+ if (old->x_name != 0){
+ new->x_name = icalmemory_strdup(old->x_name);
+ if (new->x_name == 0){
+ icalparameter_free(new);
+ return 0;
+ }
+ }
+
+ return new;
+}
+
+icalparameter* icalparameter_new_from_string(const char *str)
+{
+ char* eq;
+ char* cpy;
+ icalparameter_kind kind;
+ icalparameter *param;
+
+ icalerror_check_arg_rz(str != 0,"str");
+
+ cpy = icalmemory_strdup(str);
+
+ if (cpy == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ eq = strchr(cpy,'=');
+
+ if(eq == 0){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ *eq = '\0';
+
+ eq++;
+
+ kind = icalparameter_string_to_kind(cpy);
+
+ if(kind == ICAL_NO_PARAMETER){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ param = icalparameter_new_from_value_string(kind,eq);
+
+ if(kind == ICAL_X_PARAMETER){
+ icalparameter_set_xname(param,cpy);
+ }
+
+ free(cpy);
+
+ return param;
+
+}
+
+char*
+icalparameter_as_ical_string (icalparameter* parameter)
+{
+ struct icalparameter_impl* impl;
+ size_t buf_size = 1024;
+ char* buf;
+ char* buf_ptr;
+ char *out_buf;
+ const char *kind_string;
+
+ icalerror_check_arg_rz( (parameter!=0), "parameter");
+
+ /* Create new buffer that we can append names, parameters and a
+ value to, and reallocate as needed. Later, this buffer will be
+ copied to a icalmemory_tmp_buffer, which is managed internally
+ by libical, so it can be given to the caller without fear of
+ the caller forgetting to free it */
+
+ buf = icalmemory_new_buffer(buf_size);
+ buf_ptr = buf;
+ impl = (struct icalparameter_impl*)parameter;
+
+ if(impl->kind == ICAL_X_PARAMETER) {
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size,
+ icalparameter_get_xname(impl));
+
+ } else {
+
+ kind_string = icalparameter_kind_to_string(impl->kind);
+
+ if (impl->kind == ICAL_NO_PARAMETER ||
+ impl->kind == ICAL_ANY_PARAMETER ||
+ kind_string == 0)
+ {
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return 0;
+ }
+
+
+ /* Put the parameter name into the string */
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
+
+ }
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "=");
+
+ if(impl->string !=0){
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, impl->string);
+ } else if (impl->data != 0){
+ const char* str = icalparameter_enum_to_string(impl->data);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
+ } else {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ /* Now, copy the buffer to a tmp_buffer, which is safe to give to
+ the caller without worring about de-allocating it. */
+
+ out_buf = icalmemory_tmp_buffer(strlen(buf));
+ strcpy(out_buf, buf);
+
+ icalmemory_free_buffer(buf);
+
+ return out_buf;
+
+}
+
+
+int
+icalparameter_is_valid (icalparameter* parameter);
+
+
+icalparameter_kind
+icalparameter_isa (icalparameter* parameter)
+{
+ if(parameter == 0){
+ return ICAL_NO_PARAMETER;
+ }
+
+ return ((struct icalparameter_impl *)parameter)->kind;
+}
+
+
+int
+icalparameter_isa_parameter (void* parameter)
+{
+ struct icalparameter_impl *impl = (struct icalparameter_impl *)parameter;
+
+ if (parameter == 0){
+ return 0;
+ }
+
+ if (strcmp(impl->id,"para") == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+void
+icalparameter_set_xname (icalparameter* param, const char* v)
+{
+ struct icalparameter_impl *impl = (struct icalparameter_impl*)param;
+ icalerror_check_arg_rv( (param!=0),"param");
+ icalerror_check_arg_rv( (v!=0),"v");
+
+ if (impl->x_name != 0){
+ free((void*)impl->x_name);
+ }
+
+ impl->x_name = icalmemory_strdup(v);
+
+ if (impl->x_name == 0){
+ errno = ENOMEM;
+ }
+
+}
+
+const char*
+icalparameter_get_xname (icalparameter* param)
+{
+ struct icalparameter_impl *impl = (struct icalparameter_impl*)param;
+ icalerror_check_arg_rz( (param!=0),"param");
+
+ return impl->x_name;
+}
+
+void
+icalparameter_set_xvalue (icalparameter* param, const char* v)
+{
+ struct icalparameter_impl *impl = (struct icalparameter_impl*)param;
+
+ icalerror_check_arg_rv( (param!=0),"param");
+ icalerror_check_arg_rv( (v!=0),"v");
+
+ if (impl->string != 0){
+ free((void*)impl->string);
+ }
+
+ impl->string = icalmemory_strdup(v);
+
+ if (impl->string == 0){
+ errno = ENOMEM;
+ }
+
+}
+
+const char*
+icalparameter_get_xvalue (icalparameter* param)
+{
+ struct icalparameter_impl *impl = (struct icalparameter_impl*)param;
+
+ icalerror_check_arg_rz( (param!=0),"param");
+
+ return impl->string;
+
+}
+
+void icalparameter_set_parent(icalparameter* param,
+ icalproperty* property)
+{
+ struct icalparameter_impl *impl = (struct icalparameter_impl*)param;
+
+ icalerror_check_arg_rv( (param!=0),"param");
+
+ impl->parent = property;
+}
+
+icalproperty* icalparameter_get_parent(icalparameter* param)
+{
+ struct icalparameter_impl *impl = (struct icalparameter_impl*)param;
+
+ icalerror_check_arg_rz( (param!=0),"param");
+
+ return impl->parent;
+}
+
+
+/* Everything below this line is machine generated. Do not edit. */
+/* ALTREP */
diff --git a/src/plugins/vcalendar/libical/libical/icalparameter.h b/src/plugins/vcalendar/libical/libical/icalparameter.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalparam.h
+ CREATOR: eric 20 March 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 icalparam.h
+
+ ======================================================================*/
+
+#ifndef ICALPARAM_H
+#define ICALPARAM_H
+
+#include "icalderivedparameter.h"
+
+/* Declared in icalderivedparameter.h */
+/*typedef void icalparameter;*/
+
+icalparameter* icalparameter_new(icalparameter_kind kind);
+icalparameter* icalparameter_new_clone(icalparameter* p);
+
+/* Create from string of form "PARAMNAME=VALUE" */
+icalparameter* icalparameter_new_from_string(const char* value);
+
+/* Create from just the value, the part after the "=" */
+icalparameter* icalparameter_new_from_value_string(icalparameter_kind kind, const char* value);
+
+void icalparameter_free(icalparameter* parameter);
+
+char* icalparameter_as_ical_string(icalparameter* parameter);
+
+int icalparameter_is_valid(icalparameter* parameter);
+
+icalparameter_kind icalparameter_isa(icalparameter* parameter);
+
+int icalparameter_isa_parameter(void* param);
+
+/* Acess the name of an X parameer */
+void icalparameter_set_xname (icalparameter* param, const char* v);
+const char* icalparameter_get_xname(icalparameter* param);
+void icalparameter_set_xvalue (icalparameter* param, const char* v);
+const char* icalparameter_get_xvalue(icalparameter* param);
+
+/* Convert enumerations */
+
+const char* icalparameter_kind_to_string(icalparameter_kind kind);
+icalparameter_kind icalparameter_string_to_kind(const char* string);
+
+
+
+#endif
diff --git a/src/plugins/vcalendar/libical/libical/icalparameterimpl.h b/src/plugins/vcalendar/libical/libical/icalparameterimpl.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalparameterimpl.h
+ CREATOR: eric 09 May 1999
+
+ $Id$
+ $Locker$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalderivedparameters.{c,h}
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+ ======================================================================*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef ICALPARAMETER_IMPL
+#define ICALPARAMETER_IMPL
+
+#include "icalparameter.h"
+#include "icalproperty.h"
+
+struct icalparameter_impl
+{
+ icalparameter_kind kind;
+ char id[5];
+ int size;
+ const char* string;
+ const char* x_name;
+ icalproperty* parent;
+
+ int data;
+};
+
+
+#endif /*ICALPARAMETER_IMPL*/
diff --git a/src/plugins/vcalendar/libical/libical/icalparser.c b/src/plugins/vcalendar/libical/libical/icalparser.c
@@ -0,0 +1,1109 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalparser.c
+ CREATOR: eric 04 August 1999
+
+ $Id$
+ $Locker$
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+
+ 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 Initial Developer of the Original Code is Eric Busboom
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+ ======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "icalparser.h"
+#include "pvl.h"
+#include "icalmemory.h"
+#include "icalerror.h"
+#include "icalvalue.h"
+#include "icalderivedparameter.h"
+#include "icalparameter.h"
+#include "icalproperty.h"
+#include "icalcomponent.h"
+
+#include <string.h> /* For strncpy & size_t */
+#include <stdio.h> /* For FILE and fgets and sprintf */
+#include <stdlib.h> /* for free */
+
+
+extern icalvalue* icalparser_yy_value;
+void set_parser_value_state(icalvalue_kind kind);
+int ical_yyparse(void);
+
+char* icalparser_get_next_char(char c, char *str);
+char* icalparser_get_next_parameter(char* line,char** end);
+char* icalparser_get_next_value(char* line, char **end, icalvalue_kind kind);
+char* icalparser_get_prop_name(char* line, char** end);
+char* icalparser_get_param_name(char* line, char **end);
+
+#define TMP_BUF_SIZE 80
+
+struct icalparser_impl
+{
+ int buffer_full; /* flag indicates that temp is smaller that
+ data being read into it*/
+ int continuation_line; /* last line read was a continuation line */
+ size_t tmp_buf_size;
+ char temp[TMP_BUF_SIZE];
+ icalcomponent *root_component;
+ int version;
+ int level;
+ int lineno;
+ icalparser_state state;
+ pvl_list components;
+
+ void *line_gen_data;
+
+};
+
+
+icalparser* icalparser_new(void)
+{
+ struct icalparser_impl* impl = 0;
+ if ( ( impl = (struct icalparser_impl*)
+ malloc(sizeof(struct icalparser_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ impl->root_component = 0;
+ impl->components = pvl_newlist();
+ impl->level = 0;
+ impl->state = ICALPARSER_SUCCESS;
+
+ impl->tmp_buf_size = TMP_BUF_SIZE;
+ impl->buffer_full = 0;
+ impl->lineno = 0;
+ impl->continuation_line = 0;
+
+ memset(impl->temp,0, TMP_BUF_SIZE);
+
+ return (icalparser*)impl;
+}
+
+
+void icalparser_free(icalparser* parser)
+{
+ struct icalparser_impl* impl = (struct icalparser_impl*)parser;
+ icalcomponent *c;
+
+ if (impl->root_component != 0){
+ icalcomponent_free(impl->root_component);
+ }
+
+ while( (c=pvl_pop(impl->components)) != 0){
+ icalcomponent_free(c);
+ }
+
+ pvl_free(impl->components);
+
+ free(impl);
+}
+
+void icalparser_set_gen_data(icalparser* parser, void* data)
+{
+ struct icalparser_impl* impl = (struct icalparser_impl*)parser;
+
+ impl->line_gen_data = data;
+}
+
+
+icalvalue* icalvalue_new_From_string_with_error(icalvalue_kind kind,
+ char* str,
+ icalproperty **error);
+
+
+
+char* icalparser_get_next_char(char c, char *str)
+{
+ int quote_mode = 0;
+ char* p;
+
+
+ for(p=str; *p!=0; p++){
+
+ if ( quote_mode == 0 && *p=='"' && *(p-1) != '\\' ){
+ quote_mode =1;
+ continue;
+ }
+
+ if ( quote_mode == 1 && *p=='"' && *(p-1) != '\\' ){
+ quote_mode =0;
+ continue;
+ }
+
+ if (quote_mode == 0 && *p== c && *(p-1) != '\\' ){
+ return p;
+ }
+
+ }
+
+ return 0;
+}
+
+/* make a new tmp buffer out of a substring */
+char* make_segment(char* start, char* end)
+{
+ char *buf;
+ size_t size = (size_t)end - (size_t)start;
+
+ buf = icalmemory_tmp_buffer(size+1);
+
+
+ strncpy(buf,start,size);
+ *(buf+size) = 0;
+
+ return buf;
+
+}
+
+const char* input_buffer;
+const char* input_buffer_p;
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+int icalparser_flex_input(char* buf, int max_size)
+{
+ int n = min(max_size,strlen(input_buffer_p));
+
+ if (n > 0){
+ memcpy(buf, input_buffer_p, n);
+ input_buffer_p += n;
+ return n;
+ } else {
+ return 0;
+ }
+}
+
+void icalparser_clear_flex_input(void)
+{
+ input_buffer_p = input_buffer+strlen(input_buffer);
+}
+
+/* Call the flex/bison parser to parse a complex value */
+
+icalvalue* icalparser_parse_value(icalvalue_kind kind,
+ const char* str, icalproperty** error)
+{
+ int r;
+ input_buffer_p = input_buffer = str;
+
+ set_parser_value_state(kind);
+ icalparser_yy_value = 0;
+
+ r = ical_yyparse();
+
+ /* Error. Parse failed */
+ if( icalparser_yy_value == 0 || r != 0){
+
+ if(icalparser_yy_value !=0){
+ icalvalue_free(icalparser_yy_value);
+ icalparser_yy_value = 0;
+ }
+
+ return 0;
+ }
+
+ if (error != 0){
+ *error = 0;
+ }
+
+ return icalparser_yy_value;
+}
+
+char* icalparser_get_prop_name(char* line, char** end)
+{
+ char* p;
+ char* v;
+ char *str;
+
+ p = icalparser_get_next_char(';',line);
+ v = icalparser_get_next_char(':',line);
+ if (p== 0 && v == 0) {
+ return 0;
+ }
+
+ /* There is no ';' or, it is after the ';' that marks the beginning of
+ the value */
+ if (v!=0 && ( p == 0 || p > v)){
+ str = make_segment(line,v);
+ *end = v+1;
+ } else {
+ str = make_segment(line,p);
+ *end = p+1;
+ }
+
+ return str;
+}
+
+char* icalparser_get_param_name(char* line, char **end)
+{
+
+ char* next;
+ char *str;
+
+ next = icalparser_get_next_char('=',line);
+
+ if (next == 0) {
+ return 0;
+ }
+
+ str = make_segment(line,next);
+ *end = next+1;
+ return str;
+
+}
+
+char* icalparser_get_next_paramvalue(char* line, char **end)
+{
+
+ char* next;
+ char *str;
+
+ next = icalparser_get_next_char(',',line);
+
+ if (next == 0){
+ next = (char*)(size_t)line+(size_t)strlen(line);\
+ }
+
+ if (next == line){
+ return 0;
+ } else {
+ str = make_segment(line,next);
+ *end = next+1;
+ return str;
+ }
+
+}
+
+/* A property may have multiple values, if the values are seperated by
+ commas in the content line. This routine will look for the next
+ comma after line and will set the next place to start searching in
+ end. */
+
+char* icalparser_get_next_value(char* line, char **end, icalvalue_kind kind)
+{
+
+ char* next;
+ char *p;
+ char *str;
+ size_t length = strlen(line);
+
+ p = line;
+ while(1){
+
+ next = icalparser_get_next_char(',',p);
+
+ /* Unforunately, RFC2445 says that for the RECUR value, COMMA
+ can both seperate digits in a list, and it can seperate
+ multiple recurrence specifications. This is not a friendly
+ part of the spec. This weirdness tries to
+ distinguish the two uses. it is probably a HACK*/
+
+ if( kind == ICAL_RECUR_VALUE ) {
+ if ( next != 0 &&
+ (*end+length) > next+5 &&
+ strncmp(next,"FREQ",4) == 0
+ ) {
+ /* The COMMA was followed by 'FREQ', is it a real seperator*/
+ /* Fall through */
+ } else if (next != 0){
+ /* Not real, get the next COMMA */
+ p = next+1;
+ next = 0;
+ continue;
+ }
+ }
+
+ /* If the comma is preceeded by a '\', then it is a literal and
+ not a value seperator*/
+
+ if ( (next!=0 && *(next-1) == '\\') ||
+ (next!=0 && *(next-3) == '\\')
+ )
+ /*second clause for '/' is on prev line. HACK may be out of bounds */
+ {
+ p = next+1;
+ } else {
+ break;
+ }
+
+ }
+
+ if (next == 0){
+ next = (char*)(size_t)line+length;
+ *end = next;
+ } else {
+ *end = next+1;
+ }
+
+ if (next == line){
+ return 0;
+ }
+
+
+ str = make_segment(line,next);
+ return str;
+
+}
+
+char* icalparser_get_next_parameter(char* line,char** end)
+{
+ char *next;
+ char *v;
+ char *str;
+
+ v = icalparser_get_next_char(':',line);
+ next = icalparser_get_next_char(';', line);
+
+ /* There is no ';' or, it is after the ':' that marks the beginning of
+ the value */
+
+ if (next == 0 || next > v) {
+ next = icalparser_get_next_char(':', line);
+ }
+
+ if (next != 0) {
+ str = make_segment(line,next);
+ *end = next+1;
+ return str;
+ } else {
+ *end = line;
+ return 0;
+ }
+}
+
+/* Get a single property line, from the property name through the
+ final new line, and include any continuation lines */
+
+char* icalparser_get_line(icalparser *parser,
+ char* (*line_gen_func)(char *s, size_t size, void *d))
+{
+ char *line;
+ char *line_p;
+ struct icalparser_impl* impl = (struct icalparser_impl*)parser;
+ size_t buf_size = impl->tmp_buf_size;
+
+
+ line_p = line = icalmemory_new_buffer(buf_size);
+ line[0] = '\0';
+
+ /* Read lines by calling line_gen_func and putting the data into
+ impl->temp. If the line is a continuation line ( begins with a
+ space after a newline ) then append the data onto line and read
+ again. Otherwise, exit the loop. */
+
+ while(1) {
+
+ /* The first part of the loop deals with the temp buffer,
+ which was read on he last pass through the loop. The
+ routine is split like this because it has to read lone line
+ ahead to determine if a line is a continuation line. */
+
+
+ /* The tmp buffer is not clear, so transfer the data in it to the
+ output. This may be left over from a previous call */
+ if (impl->temp[0] != '\0' ) {
+
+ /* If the last position in the temp buffer is occupied,
+ mark the buffer as full. The means we will do another
+ read later, because the line is not finished */
+ if (impl->temp[impl->tmp_buf_size-1] == 0 &&
+ impl->temp[impl->tmp_buf_size-2] != '\n'&&
+ impl->temp[impl->tmp_buf_size-2] != 0 ){
+ impl->buffer_full = 1;
+ } else {
+ impl->buffer_full = 0;
+ }
+
+ /* Copy the temp to the output and clear the temp buffer. */
+ if(impl->continuation_line==1){
+ /* back up the pointer to erase the continuation characters */
+ impl->continuation_line = 0;
+ line_p--;
+
+ if ( *(line_p-1) == '\r'){
+ line_p--;
+ }
+
+ /* copy one space up to eliminate the leading space*/
+ icalmemory_append_string(&line,&line_p,&buf_size,
+ impl->temp+1);
+
+ } else {
+ icalmemory_append_string(&line,&line_p,&buf_size,impl->temp);
+ }
+
+ impl->temp[0] = '\0' ;
+ }
+
+ impl->temp[impl->tmp_buf_size-1] = 1; /* Mark end of buffer */
+
+ /****** Here is where the routine gets string data ******************/
+ if ((*line_gen_func)(impl->temp,impl->tmp_buf_size,impl->line_gen_data)
+ ==0){/* Get more data */
+
+ /* If the first position is clear, it means we didn't get
+ any more data from the last call to line_ge_func*/
+ if (impl->temp[0] == '\0'){
+
+ if(line[0] != '\0'){
+ /* There is data in the output, so fall trhough and process it*/
+ break;
+ } else {
+ /* No data in output; return and signal that there
+ is no more input*/
+ free(line);
+ return 0;
+ }
+ }
+ }
+
+
+ /* If the output line ends in a '\n' and the temp buffer
+ begins with a ' ', then the buffer holds a continuation
+ line, so keep reading. */
+
+ if ( line_p > line+1 && *(line_p-1) == '\n' && (impl->temp[0] == ' ' || impl->temp[0] == '\t')) {
+
+ impl->continuation_line = 1;
+
+ } else if ( impl->buffer_full == 1 ) {
+
+ /* The buffer was filled on the last read, so read again */
+
+ } else {
+
+ /* Looks like the end of this content line, so break */
+ break;
+ }
+
+
+ }
+
+ /* Erase the final newline and/or carriage return*/
+ if ( line_p > line+1 && *(line_p-1) == '\n') {
+ *(line_p-1) = '\0';
+ if ( *(line_p-2) == '\r'){
+ *(line_p-2) = '\0';
+ }
+
+ } else {
+ *(line_p) = '\0';
+ }
+
+ return line;
+
+}
+
+void insert_error(icalcomponent* comp, char* text,
+ char* message, icalparameter_xlicerrortype type)
+{
+ char temp[1024];
+
+ if (text == 0){
+ snprintf(temp,1024,"%s:",message);
+ } else {
+ snprintf(temp,1024,"%s: %s",message,text);
+ }
+
+ icalcomponent_add_property
+ (comp,
+ icalproperty_vanew_xlicerror(
+ temp,
+ icalparameter_new_xlicerrortype(type),
+ 0));
+}
+
+int line_is_blank(char* line){
+ int i=0;
+
+ for(i=0; *(line+i)!=0; i++){
+ char c = *(line+i);
+
+ if(c != ' ' && c != '\n' && c != '\t'){
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+icalcomponent* icalparser_parse(icalparser *parser,
+ char* (*line_gen_func)(char *s, size_t size,
+ void* d))
+{
+
+ char* line;
+ icalcomponent *c=0;
+ icalcomponent *root=0;
+ icalerrorstate es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR);
+
+ icalerror_check_arg_rz((parser !=0),"parser");
+
+ icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL);
+
+ do{
+ line = icalparser_get_line(parser, line_gen_func);
+
+ if ((c = icalparser_add_line(parser,line)) != 0){
+
+ if(icalcomponent_get_parent(c) !=0){
+ /* This is bad news... assert? */
+ }
+
+ assert(impl->root_component == 0);
+ assert(pvl_count(impl->components) ==0);
+
+ if (root == 0){
+ /* Just one component */
+ root = c;
+ } else if(icalcomponent_isa(root) != ICAL_XROOT_COMPONENT) {
+ /*Got a second component, so move the two components under
+ an XROOT container */
+ icalcomponent *tempc = icalcomponent_new(ICAL_XROOT_COMPONENT);
+ icalcomponent_add_component(tempc, root);
+ icalcomponent_add_component(tempc, c);
+ root = tempc;
+ } else if(icalcomponent_isa(root) == ICAL_XROOT_COMPONENT) {
+ /* Already have an XROOT container, so add the component
+ to it*/
+ icalcomponent_add_component(root, c);
+
+ } else {
+ /* Badness */
+ assert(0);
+ }
+
+ c = 0;
+
+ }
+ if(line != 0){
+ free(line);
+ }
+ } while ( line != 0);
+
+ icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es);
+
+ return root;
+
+}
+
+
+icalcomponent* icalparser_add_line(icalparser* parser,
+ char* line)
+{
+ char *p;
+ char *str;
+ char *end;
+ int vcount = 0;
+ icalproperty *prop;
+ icalproperty_kind prop_kind;
+ icalvalue *value;
+ icalvalue_kind value_kind = ICAL_NO_VALUE;
+
+
+ struct icalparser_impl *impl = (struct icalparser_impl*)parser;
+ icalerror_check_arg_rz((parser != 0),"parser");
+
+
+ if (line == 0)
+ {
+ impl->state = ICALPARSER_ERROR;
+ return 0;
+ }
+
+ if(line_is_blank(line) == 1){
+ return 0;
+ }
+
+ /* Begin by getting the property name at the start of the line. The
+ property name may end up being "BEGIN" or "END" in which case it
+ is not really a property, but the marker for the start or end of
+ a component */
+
+ end = 0;
+ str = icalparser_get_prop_name(line, &end);
+
+ if (str == 0 || strlen(str) == 0 ){
+ /* Could not get a property name */
+ icalcomponent *tail = pvl_data(pvl_tail(impl->components));
+
+ if (tail){
+ insert_error(tail,line,
+ "Got a data line, but could not find a property name or component begin tag",
+ ICAL_XLICERRORTYPE_COMPONENTPARSEERROR);
+ }
+ tail = 0;
+ impl->state = ICALPARSER_ERROR;
+ return 0;
+ }
+
+ /**********************************************************************
+ * Handle begin and end of components
+ **********************************************************************/
+ /* If the property name is BEGIN or END, we are actually
+ starting or ending a new component */
+
+ if(strcmp(str,"BEGIN") == 0){
+ icalcomponent *c;
+ icalcomponent_kind comp_kind;
+
+ impl->level++;
+ str = icalparser_get_next_value(end,&end, value_kind);
+
+
+ comp_kind = icalenum_string_to_component_kind(str);
+
+ if (comp_kind == ICAL_NO_COMPONENT){
+ c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT);
+ insert_error(c,str,"Parse error in component name",
+ ICAL_XLICERRORTYPE_COMPONENTPARSEERROR);
+ }
+
+ c = icalcomponent_new(comp_kind);
+
+ if (c == 0){
+ c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT);
+ insert_error(c,str,"Parse error in component name",
+ ICAL_XLICERRORTYPE_COMPONENTPARSEERROR);
+ }
+
+ pvl_push(impl->components,c);
+
+ impl->state = ICALPARSER_BEGIN_COMP;
+ return 0;
+
+ } else if (strcmp(str,"END") == 0 ) {
+ icalcomponent* tail;
+
+ impl->level--;
+ str = icalparser_get_next_value(end,&end, value_kind);
+
+ /* Pop last component off of list and add it to the second-to-last*/
+ impl->root_component = pvl_pop(impl->components);
+
+ tail = pvl_data(pvl_tail(impl->components));
+
+ if(tail != 0){
+ icalcomponent_add_component(tail,impl->root_component);
+ }
+
+ tail = 0;
+
+ /* Return the component if we are back to the 0th level */
+ if (impl->level == 0){
+ icalcomponent *rtrn;
+
+ if(pvl_count(impl->components) != 0){
+ /* There are still components on the stack -- this means
+ that one of them did not have a proper "END" */
+ pvl_push(impl->components,impl->root_component);
+ icalparser_clean(parser); /* may reset impl->root_component*/
+ }
+
+ assert(pvl_count(impl->components) == 0);
+
+ impl->state = ICALPARSER_SUCCESS;
+ rtrn = impl->root_component;
+ impl->root_component = 0;
+ return rtrn;
+
+ } else {
+ impl->state = ICALPARSER_END_COMP;
+ return 0;
+ }
+ }
+
+
+ /* There is no point in continuing if we have not seen a
+ component yet */
+
+ if(pvl_data(pvl_tail(impl->components)) == 0){
+ impl->state = ICALPARSER_ERROR;
+ return 0;
+ }
+
+
+ /**********************************************************************
+ * Handle property names
+ **********************************************************************/
+
+ /* At this point, the property name really is a property name,
+ (Not a component name) so make a new property and add it to
+ the component */
+
+
+ prop_kind = icalproperty_string_to_kind(str);
+
+ prop = icalproperty_new(prop_kind);
+
+ if (prop != 0){
+ icalcomponent *tail = pvl_data(pvl_tail(impl->components));
+
+ if(prop_kind==ICAL_X_PROPERTY){
+ icalproperty_set_x_name(prop,str);
+ }
+
+ icalcomponent_add_property(tail, prop);
+
+ /* Set the value kind for the default for this type of
+ property. This may be re-set by a VALUE parameter */
+ value_kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop));
+
+ } else {
+ icalcomponent* tail = pvl_data(pvl_tail(impl->components));
+
+ insert_error(tail,str,"Parse error in property name",
+ ICAL_XLICERRORTYPE_PROPERTYPARSEERROR);
+
+ tail = 0;
+ impl->state = ICALPARSER_ERROR;
+ return 0;
+ }
+
+ /**********************************************************************
+ * Handle parameter values
+ **********************************************************************/
+
+ /* Now, add any parameters to the last property */
+
+ p = 0;
+ while(1) {
+
+ if (*(end-1) == ':'){
+ /* if the last seperator was a ":" and the value is a
+ URL, icalparser_get_next_parameter will find the
+ ':' in the URL, so better break now. */
+ break;
+ }
+
+ str = icalparser_get_next_parameter(end,&end);
+
+ if (str != 0){
+ char* name;
+ char* pvalue;
+
+ icalparameter *param = 0;
+ icalparameter_kind kind;
+ icalcomponent *tail = pvl_data(pvl_tail(impl->components));
+
+ name = icalparser_get_param_name(str,&pvalue);
+
+ if (name == 0){
+ /* 'tail' defined above */
+ insert_error(tail, str, "Cant parse parameter name",
+ ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR);
+ tail = 0;
+ break;
+ }
+
+ kind = icalparameter_string_to_kind(name);
+
+ if(kind == ICAL_X_PARAMETER){
+ param = icalparameter_new(ICAL_X_PARAMETER);
+
+ if(param != 0){
+ icalparameter_set_xname(param,name);
+ icalparameter_set_xvalue(param,pvalue);
+ }
+
+
+ } else if (kind != ICAL_NO_PARAMETER){
+ param = icalparameter_new_from_value_string(kind,pvalue);
+ } else {
+ /* Error. Failed to parse the parameter*/
+ /* 'tail' defined above */
+ insert_error(tail, str, "Cant parse parameter name",
+ ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR);
+ tail = 0;
+ impl->state = ICALPARSER_ERROR;
+ continue;
+ }
+
+ if (param == 0){
+ /* 'tail' defined above */
+ insert_error(tail,str,"Cant parse parameter value",
+ ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR);
+
+ tail = 0;
+ impl->state = ICALPARSER_ERROR;
+ continue;
+ }
+
+ /* If it is a VALUE parameter, set the kind of value*/
+ if (icalparameter_isa(param)==ICAL_VALUE_PARAMETER){
+
+ value_kind = (icalvalue_kind)
+ icalparameter_value_to_value_kind(
+ icalparameter_get_value(param)
+ );
+
+ if (value_kind == ICAL_NO_VALUE){
+
+ /* Ooops, could not parse the value of the
+ parameter ( it was not one of the defined
+ values ), so reset the value_kind */
+
+ insert_error(
+ tail, str,
+ "Got a VALUE parameter with an unknown type",
+ ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR);
+ icalparameter_free(param);
+
+ value_kind =
+ icalproperty_kind_to_value_kind(
+ icalproperty_isa(prop));
+
+ icalparameter_free(param);
+ tail = 0;
+ impl->state = ICALPARSER_ERROR;
+ return 0;
+ }
+ }
+
+ /* Everything is OK, so add the parameter */
+ icalproperty_add_parameter(prop,param);
+ tail = 0;
+
+ } else { /* if ( str != 0) */
+ /* If we did not get a param string, go on to looking
+ for a value */
+ break;
+ } /* if ( str != 0) */
+
+ } /* while(1) */
+
+ /**********************************************************************
+ * Handle values
+ **********************************************************************/
+
+ /* Look for values. If there are ',' characters in the values,
+ then there are multiple values, so clone the current
+ parameter and add one part of the value to each clone */
+
+ vcount=0;
+ while(1) {
+ str = icalparser_get_next_value(end,&end, value_kind);
+
+ if (str != 0){
+
+ if (vcount > 0){
+ /* Actually, only clone after the second value */
+ icalproperty* clone = icalproperty_new_clone(prop);
+ icalcomponent* tail = pvl_data(pvl_tail(impl->components));
+
+ icalcomponent_add_property(tail, clone);
+ prop = clone;
+ tail = 0;
+ }
+
+ value = icalvalue_new_from_string(value_kind, str);
+
+ /* Don't add properties without value */
+ if (value == 0){
+ char temp[200]; /* HACK */
+
+ icalproperty_kind prop_kind = icalproperty_isa(prop);
+ icalcomponent* tail = pvl_data(pvl_tail(impl->components));
+
+ sprintf(temp,"Cant parse as %s value in %s property. Removing entire property",
+ icalvalue_kind_to_string(value_kind),
+ icalproperty_kind_to_string(prop_kind));
+
+ insert_error(tail, str, temp,
+ ICAL_XLICERRORTYPE_VALUEPARSEERROR);
+
+ /* Remove the troublesome property */
+ icalcomponent_remove_property(tail,prop);
+ icalproperty_free(prop);
+ prop = 0;
+ tail = 0;
+ impl->state = ICALPARSER_ERROR;
+ return 0;
+
+ } else {
+ vcount++;
+ icalproperty_set_value(prop, value);
+ }
+
+
+ } else {
+ if (vcount == 0){
+ char temp[200]; /* HACK */
+
+ icalproperty_kind prop_kind = icalproperty_isa(prop);
+ icalcomponent *tail = pvl_data(pvl_tail(impl->components));
+
+ sprintf(temp,"No value for %s property. Removing entire property",
+ icalproperty_kind_to_string(prop_kind));
+
+ insert_error(tail, str, temp,
+ ICAL_XLICERRORTYPE_VALUEPARSEERROR);
+
+ /* Remove the troublesome property */
+ icalcomponent_remove_property(tail,prop);
+ icalproperty_free(prop);
+ prop = 0;
+ tail = 0;
+ impl->state = ICALPARSER_ERROR;
+ return 0;
+ } else {
+
+ break;
+ }
+ }
+ }
+
+ /****************************************************************
+ * End of component parsing.
+ *****************************************************************/
+
+ if (pvl_data(pvl_tail(impl->components)) == 0 &&
+ impl->level == 0){
+ /* HACK. Does this clause ever get executed? */
+ impl->state = ICALPARSER_SUCCESS;
+ assert(0);
+ return impl->root_component;
+ } else {
+ impl->state = ICALPARSER_IN_PROGRESS;
+ return 0;
+ }
+
+}
+
+icalparser_state icalparser_get_state(icalparser* parser)
+{
+ struct icalparser_impl* impl = (struct icalparser_impl*) parser;
+ return impl->state;
+
+}
+
+icalcomponent* icalparser_clean(icalparser* parser)
+{
+ struct icalparser_impl* impl = (struct icalparser_impl*) parser;
+ icalcomponent *tail;
+
+ icalerror_check_arg_rz((parser != 0 ),"parser");
+
+ /* We won't get a clean exit if some components did not have an
+ "END" tag. Clear off any component that may be left in the list */
+
+ while((tail=pvl_data(pvl_tail(impl->components))) != 0){
+
+ insert_error(tail," ",
+ "Missing END tag for this component. Closing component at end of input.",
+ ICAL_XLICERRORTYPE_COMPONENTPARSEERROR);
+
+
+ impl->root_component = pvl_pop(impl->components);
+ tail=pvl_data(pvl_tail(impl->components));
+
+ if(tail != 0){
+ if(icalcomponent_get_parent(impl->root_component)!=0){
+ icalerror_warn("icalparser_clean is trying to attach a component for the second time");
+ } else {
+ icalcomponent_add_component(tail,impl->root_component);
+ }
+ }
+
+ }
+
+ return impl->root_component;
+
+}
+
+struct slg_data {
+ const char* pos;
+ const char* str;
+};
+
+char* string_line_generator(char *out, size_t buf_size, void *d)
+{
+ char *n;
+ size_t size;
+ struct slg_data* data = (struct slg_data*)d;
+
+ if(data->pos==0){
+ data->pos=data->str;
+ }
+
+ /* If the pointer is at the end of the string, we are done */
+ if (*(data->pos)==0){
+ return 0;
+ }
+
+ n = strchr(data->pos,'\n');
+
+ if (n == 0){
+ size = strlen(data->pos);
+ } else {
+ n++; /* include newline in output */
+ size = (n-data->pos);
+ }
+
+ if (size > buf_size-1){
+ size = buf_size-1;
+ }
+
+
+ strncpy(out,data->pos,size);
+
+ *(out+size) = '\0';
+
+ data->pos += size;
+
+ return out;
+}
+
+icalcomponent* icalparser_parse_string(const char* str)
+{
+ icalcomponent *c;
+ struct slg_data d;
+ icalparser *p;
+
+ icalerrorstate es = icalerror_get_error_state(ICAL_PARSE_ERROR);
+
+ d.pos = 0;
+ d.str = str;
+
+ p = icalparser_new();
+ icalparser_set_gen_data(p,&d);
+
+ icalerror_set_error_state(ICAL_PARSE_ERROR,ICAL_ERROR_NONFATAL);
+
+ c = icalparser_parse(p,string_line_generator);
+
+ icalerror_set_error_state(ICAL_PARSE_ERROR,es);
+
+ icalparser_free(p);
+
+ return c;
+
+}
diff --git a/src/plugins/vcalendar/libical/libical/icalparser.h b/src/plugins/vcalendar/libical/libical/icalparser.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalparser.h
+ CREATOR: eric 20 April 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalparser.h
+
+======================================================================*/
+
+
+#ifndef ICALPARSER_H
+#define ICALPARSER_H
+
+#include "icalenums.h"
+#include "icaltypes.h"
+#include"icalcomponent.h"
+
+#include <stdio.h> /* For FILE* */
+
+typedef void* icalparser;
+
+
+/***********************************************************************
+ * Line-oriented parsing.
+ *
+ * Create a new parser via icalparse_new_parser, then add ines one at
+ * a time with icalparse_add_line(). icalparser_add_line() will return
+ * non-zero when it has finished with a component.
+ ***********************************************************************/
+
+typedef enum icalparser_state {
+ ICALPARSER_ERROR,
+ ICALPARSER_SUCCESS,
+ ICALPARSER_BEGIN_COMP,
+ ICALPARSER_END_COMP,
+ ICALPARSER_IN_PROGRESS
+} icalparser_state;
+
+icalparser* icalparser_new(void);
+icalcomponent* icalparser_add_line(icalparser* parser, char* str );
+icalcomponent* icalparser_clean(icalparser* parser);
+icalparser_state icalparser_get_state(icalparser* parser);
+void icalparser_free(icalparser* parser);
+
+
+/***********************************************************************
+ * Message oriented parsing. icalparser_parse takes a string that
+ * holds the text ( in RFC 2445 format ) and returns a pointer to an
+ * icalcomponent. The caller owns the memory. line_gen_func is a
+ * pointer to a function that returns one content line per invocation
+ **********************************************************************/
+
+icalcomponent* icalparser_parse(icalparser *parser,
+ char* (*line_gen_func)(char *s, size_t size, void *d));
+
+/* Set the data that icalparser_parse will give to the line_gen_func
+ as the parameter 'd'*/
+void icalparser_set_gen_data(icalparser* parser, void* data);
+
+
+icalcomponent* icalparser_parse_string(const char* str);
+
+
+/***********************************************************************
+ * Parser support functions
+ ***********************************************************************/
+
+/* Use the flex/bison parser to turn a string into a value type */
+icalvalue* icalparser_parse_value(icalvalue_kind kind,
+ const char* str, icalcomponent** errors);
+
+/* Given a line generator function, return a single iCal content line.*/
+char* icalparser_get_line(icalparser* parser, char* (*line_gen_func)(char *s, size_t size, void *d));
+
+char* string_line_generator(char *out, size_t buf_size, void *d);
+
+#endif /* !ICALPARSE_H */
diff --git a/src/plugins/vcalendar/libical/libical/icalperiod.c b/src/plugins/vcalendar/libical/libical/icalperiod.c
@@ -0,0 +1,172 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalperiod.c
+ CREATOR: eric 02 June 2000
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+ ======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalperiod.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef ICAL_NO_LIBICAL
+#define icalerror_set_errno(x)
+#define icalerror_check_arg_rv(x,y)
+#define icalerror_check_arg_re(x,y,z)
+#else
+#include "icalerror.h"
+#include "icalmemory.h"
+#endif
+
+
+
+
+struct icalperiodtype icalperiodtype_from_string (const char* str)
+{
+
+ struct icalperiodtype p, null_p;
+ char *s = icalmemory_strdup(str);
+ char *start, *end = s;
+ icalerrorstate es;
+
+ /* Errors are normally generated in the following code, so save
+ the error state for resoration later */
+
+ icalerrorenum e = icalerrno;
+
+ p.start = p.end = icaltime_null_time();
+ p.duration = icaldurationtype_from_int(0);
+
+ null_p = p;
+
+ if(s == 0) goto error;
+
+ start = s;
+ end = strchr(s, '/');
+
+ if(end == 0) goto error;
+
+ *end = 0;
+ end++;
+
+ p.start = icaltime_from_string(start);
+
+ if (icaltime_is_null_time(p.start)) goto error;
+
+ es = icalerror_get_error_state(ICAL_MALFORMEDDATA_ERROR);
+ icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,ICAL_ERROR_NONFATAL);
+
+ p.end = icaltime_from_string(end);
+
+ icalerror_set_error_state(ICAL_MALFORMEDDATA_ERROR,es);
+
+
+ if (icaltime_is_null_time(p.end)){
+
+ p.duration = icaldurationtype_from_string(end);
+
+ if(icaldurationtype_as_int(p.duration) == 0) goto error;
+ }
+
+ icalerrno = e;
+ icalmemory_free_buffer(s);
+ return p;
+
+ error:
+ icalmemory_free_buffer(s);
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return null_p;
+}
+
+
+const char* icalperiodtype_as_ical_string(struct icalperiodtype p)
+{
+
+ const char* start;
+ const char* end;
+
+ char *buf;
+ size_t buf_size = 40;
+ char* buf_ptr = 0;
+
+ buf = (char*)icalmemory_new_buffer(buf_size);
+ buf_ptr = buf;
+
+
+ start = icaltime_as_ical_string(p.start);
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, start);
+
+ if(!icaltime_is_null_time(p.end)){
+ end = icaltime_as_ical_string(p.end);
+ } else {
+ end = icaldurationtype_as_ical_string(p.duration);
+ }
+
+ icalmemory_append_char(&buf, &buf_ptr, &buf_size, '/');
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, end);
+
+ icalmemory_add_tmp_buffer(buf);
+
+ return buf;
+}
+
+
+
+struct icalperiodtype icalperiodtype_null_period() {
+ struct icalperiodtype p;
+ p.start = icaltime_null_time();
+ p.end = icaltime_null_time();
+ p.duration = icaldurationtype_null_duration();
+
+ return p;
+}
+int icalperiodtype_is_null_period(struct icalperiodtype p){
+
+ if(icaltime_is_null_time(p.start) &&
+ icaltime_is_null_time(p.end) &&
+ icaldurationtype_is_null_duration(p.duration)){
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int icalperiodtype_is_valid_period(struct icalperiodtype p){
+ if(icaltime_is_valid_time(p.start) &&
+ (icaltime_is_valid_time(p.end) || icaltime_is_null_time(p.end)) )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/src/plugins/vcalendar/libical/libical/icalperiod.h b/src/plugins/vcalendar/libical/libical/icalperiod.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalperiod.h
+ CREATOR: eric 26 Jan 2001
+
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+======================================================================*/
+
+#ifndef ICALPERIOD_H
+#define ICALPERIOD_H
+
+#include "icaltime.h"
+#include "icalduration.h"
+
+struct icalperiodtype
+{
+ struct icaltimetype start;
+ struct icaltimetype end;
+ struct icaldurationtype duration;
+};
+
+struct icalperiodtype icalperiodtype_from_string (const char* str);
+
+const char* icalperiodtype_as_ical_string(struct icalperiodtype p);
+struct icalperiodtype icalperiodtype_null_period();
+int icalperiodtype_is_null_period(struct icalperiodtype p);
+int icalperiodtype_is_valid_period(struct icalperiodtype p);
+
+
+
+
+#endif /* !ICALTIME_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icalproperty.c b/src/plugins/vcalendar/libical/libical/icalproperty.c
@@ -0,0 +1,808 @@
+/* -*- Mode: C -*- */
+
+/*======================================================================
+ FILE: icalproperty.c
+ CREATOR: eric 28 April 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalproperty.c
+
+======================================================================*/
+/*#line 27 "icalproperty.c.in"*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalproperty.h"
+#include "icalparameter.h"
+#include "icalcomponent.h"
+#include "pvl.h"
+#include "icalenums.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "icalparser.h"
+
+#include <string.h> /* For icalmemory_strdup, rindex */
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h> /* for printf */
+#include <stdarg.h> /* for va_list, va_start, etc. */
+
+#define TMP_BUF_SIZE 1024
+
+/* Private routines for icalproperty */
+void icalvalue_set_parent(icalvalue* value,
+ icalproperty* property);
+icalproperty* icalvalue_get_parent(icalvalue* value);
+
+void icalparameter_set_parent(icalparameter* param,
+ icalproperty* property);
+icalproperty* icalparameter_get_parent(icalparameter* value);
+
+
+void icalproperty_set_x_name(icalproperty* prop, char* name);
+
+struct icalproperty_impl
+{
+ char id[5];
+ icalproperty_kind kind;
+ char* x_name;
+ pvl_list parameters;
+ pvl_elem parameter_iterator;
+ icalvalue* value;
+ icalcomponent *parent;
+};
+
+void icalproperty_add_parameters(struct icalproperty_impl *prop,va_list args)
+{
+
+ void* vp;
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ while((vp = va_arg(args, void*)) != 0) {
+
+ if (icalvalue_isa_value(vp) != 0 ){
+ } else if (icalparameter_isa_parameter(vp) != 0 ){
+
+ icalproperty_add_parameter((icalproperty*)impl,
+ (icalparameter*)vp);
+ } else {
+ assert(0);
+ }
+
+ }
+
+
+}
+
+
+struct icalproperty_impl*
+icalproperty_new_impl (icalproperty_kind kind)
+{
+ struct icalproperty_impl* prop;
+
+ if ( ( prop = (struct icalproperty_impl*)
+ malloc(sizeof(struct icalproperty_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ strcpy(prop->id,"prop");
+
+ prop->kind = kind;
+ prop->parameters = pvl_newlist();
+ prop->parameter_iterator = 0;
+ prop->value = 0;
+ prop->x_name = 0;
+ prop->parent = 0;
+
+ return prop;
+}
+
+
+icalproperty*
+icalproperty_new (icalproperty_kind kind)
+{
+ if(kind == ICAL_NO_PROPERTY){
+ return 0;
+ }
+
+ return (icalproperty*)icalproperty_new_impl(kind);
+}
+
+
+icalproperty*
+icalproperty_new_clone(icalproperty* prop)
+{
+ struct icalproperty_impl *old = (struct icalproperty_impl*)prop;
+ struct icalproperty_impl *new = icalproperty_new_impl(old->kind);
+ pvl_elem p;
+
+ icalerror_check_arg_rz((prop!=0),"Prop");
+ icalerror_check_arg_rz((old!=0),"old");
+ icalerror_check_arg_rz((new!=0),"new");
+
+ if (old->value !=0) {
+ new->value = icalvalue_new_clone(old->value);
+ }
+
+ if (old->x_name != 0) {
+
+ new->x_name = icalmemory_strdup(old->x_name);
+
+ if (new->x_name == 0) {
+ icalproperty_free(new);
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+ }
+
+ for(p=pvl_head(old->parameters);p != 0; p = pvl_next(p)){
+ icalparameter *param = icalparameter_new_clone(pvl_data(p));
+
+ if (param == 0){
+ icalproperty_free(new);
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ pvl_push(new->parameters,param);
+
+ }
+
+ return new;
+
+}
+
+icalproperty* icalproperty_new_from_string(char* str)
+{
+
+ size_t buf_size = 1024;
+ char* buf = icalmemory_new_buffer(buf_size);
+ char* buf_ptr = buf;
+ icalproperty *prop;
+ icalcomponent *comp;
+ int errors = 0;
+
+ icalerror_check_arg_rz( (str!=0),"str");
+
+ /* Is this a HACK or a crafty reuse of code? */
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:VCALENDAR\n");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "\n");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:VCALENDAR\n");
+
+ comp = icalparser_parse_string(buf);
+
+ if(comp == 0){
+ icalerror_set_errno(ICAL_PARSE_ERROR);
+ return 0;
+ }
+
+ errors = icalcomponent_count_errors(comp);
+
+ prop = icalcomponent_get_first_property(comp,ICAL_ANY_PROPERTY);
+
+ icalcomponent_remove_property(comp,prop);
+
+ icalcomponent_free(comp);
+ free(buf);
+
+ if(errors > 0){
+ icalproperty_free(prop);
+ return 0;
+ } else {
+ return prop;
+ }
+
+}
+
+void
+icalproperty_free (icalproperty* prop)
+{
+ struct icalproperty_impl *p;
+
+ icalparameter* param;
+
+ icalerror_check_arg_rv((prop!=0),"prop");
+
+ p = (struct icalproperty_impl*)prop;
+
+#ifdef ICAL_FREE_ON_LIST_IS_ERROR
+ icalerror_assert( (p->parent ==0),"Tried to free a property that is still attached to a component. ");
+
+#else
+ if(p->parent !=0){
+ return;
+ }
+#endif
+
+ if (p->value != 0){
+ icalvalue_set_parent(p->value,0);
+ icalvalue_free(p->value);
+ }
+
+ while( (param = pvl_pop(p->parameters)) != 0){
+ icalparameter_free(param);
+ }
+
+ pvl_free(p->parameters);
+
+ if (p->x_name != 0) {
+ free(p->x_name);
+ }
+
+ p->kind = ICAL_NO_PROPERTY;
+ p->parameters = 0;
+ p->parameter_iterator = 0;
+ p->value = 0;
+ p->x_name = 0;
+ p->id[0] = 'X';
+
+ free(p);
+
+}
+
+
+char*
+icalproperty_as_ical_string (icalproperty* prop)
+{
+ icalparameter *param;
+
+ /* Create new buffer that we can append names, parameters and a
+ value to, and reallocate as needed. Later, this buffer will be
+ copied to a icalmemory_tmp_buffer, which is managed internally
+ by libical, so it can be given to the caller without fear of
+ the caller forgetting to free it */
+
+ const char* property_name = 0;
+ size_t buf_size = 1024;
+ char* buf = icalmemory_new_buffer(buf_size);
+ char* buf_ptr = buf;
+ icalvalue* value;
+ char *out_buf;
+
+ char newline[] = "\n";
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+
+ /* Append property name */
+
+ if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
+ property_name = impl->x_name;
+ } else {
+ property_name = icalproperty_kind_to_string(impl->kind);
+ }
+
+ if (property_name == 0 ) {
+ icalerror_warn("Got a property of an unknown kind.");
+ icalmemory_free_buffer(buf);
+ return 0;
+
+ }
+
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+
+
+ /* Determine what VALUE parameter to include. The VALUE parameters
+ are ignored in the normal parameter printing ( the block after
+ this one, so we need to do it here */
+ {
+ const char* kind_string = 0;
+
+ icalparameter *orig_val_param
+ = icalproperty_get_first_parameter(prop,ICAL_VALUE_PARAMETER);
+
+ icalvalue *value = icalproperty_get_value(impl);
+
+ icalvalue_kind orig_kind = ICAL_NO_VALUE;
+
+ icalvalue_kind this_kind = ICAL_NO_VALUE;
+
+ icalvalue_kind default_kind
+ = icalproperty_kind_to_value_kind(impl->kind);
+
+ if(orig_val_param){
+ orig_kind = (icalvalue_kind)icalparameter_get_value(orig_val_param);
+ }
+
+ if(value != 0){
+ this_kind = icalvalue_isa(value);
+ }
+
+
+ if(this_kind == default_kind &&
+ orig_kind != ICAL_NO_VALUE){
+ /* The kind is the default, so it does not need to be
+ included, but do it anyway, since it was explicit in
+ the property. But, use the default, not the one
+ specified in the property */
+
+ kind_string = icalvalue_kind_to_string(default_kind);
+
+ } else if (this_kind != default_kind && this_kind != ICAL_NO_VALUE){
+ /* Not the default, so it must be specified */
+ kind_string = icalvalue_kind_to_string(this_kind);
+ } else {
+ /* Don'tinclude the VALUE parameter at all */
+ }
+
+ if(kind_string!=0){
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, "VALUE=");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+ }
+
+
+ }
+
+ /* Append parameters */
+ for(param = icalproperty_get_first_parameter(prop,ICAL_ANY_PARAMETER);
+ param != 0;
+ param = icalproperty_get_next_parameter(prop,ICAL_ANY_PARAMETER)) {
+
+ char* kind_string = icalparameter_as_ical_string(param);
+ icalparameter_kind kind = icalparameter_isa(param);
+
+ if(kind==ICAL_VALUE_PARAMETER){
+ continue;
+ }
+
+ if (kind_string == 0 ) {
+ char temp[TMP_BUF_SIZE];
+ snprintf(temp, TMP_BUF_SIZE,"Got a parameter of unknown kind in %s property",property_name);
+ icalerror_warn(temp);
+ continue;
+ }
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, " ;");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+ }
+
+ /* Append value */
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, " :");
+
+ value = icalproperty_get_value(prop);
+
+ if (value != 0){
+ const char *str = icalvalue_as_ical_string(value);
+ icalerror_assert((str !=0),"Could not get string representation of a value");
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, str);
+ } else {
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size,"ERROR: No Value");
+
+ }
+
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
+
+ /* Now, copy the buffer to a tmp_buffer, which is safe to give to
+ the caller without worring about de-allocating it. */
+
+
+ out_buf = icalmemory_tmp_buffer(strlen(buf)+1);
+ strcpy(out_buf, buf);
+
+ icalmemory_free_buffer(buf);
+
+ return out_buf;
+}
+
+
+
+icalproperty_kind
+icalproperty_isa (icalproperty* property)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)property;
+
+ if(property != 0){
+ return p->kind;
+ }
+
+ return ICAL_NO_PROPERTY;
+}
+
+int
+icalproperty_isa_property (void* property)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
+
+ icalerror_check_arg_rz( (property!=0), "property");
+
+ if (strcmp(impl->id,"prop") == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+void
+icalproperty_add_parameter (icalproperty* prop,icalparameter* parameter)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (parameter!=0),"parameter");
+
+ pvl_push(p->parameters, parameter);
+
+}
+
+void
+icalproperty_set_parameter (icalproperty* prop,icalparameter* parameter)
+{
+ icalparameter_kind kind;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (parameter!=0),"parameter");
+
+ kind = icalparameter_isa(parameter);
+
+ icalproperty_remove_parameter(prop,kind);
+
+ icalproperty_add_parameter(prop,parameter);
+}
+
+void icalproperty_set_parameter_from_string(icalproperty* prop,
+ const char* name, const char* value)
+{
+
+ icalparameter_kind kind;
+ icalparameter *param;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (name!=0),"name");
+ icalerror_check_arg_rv( (value!=0),"value");
+
+ kind = icalparameter_string_to_kind(name);
+
+ if(kind == ICAL_NO_PARAMETER){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return;
+ }
+
+ param = icalparameter_new_from_value_string(kind,value);
+
+ if (param == 0){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return;
+ }
+
+ icalproperty_set_parameter(prop,param);
+
+}
+
+const char* icalproperty_get_parameter_as_string(icalproperty* prop,
+ const char* name)
+{
+ icalparameter_kind kind;
+ icalparameter *param;
+ char* str;
+ char* pv;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+ icalerror_check_arg_rz( (name!=0),"name");
+
+ kind = icalparameter_string_to_kind(name);
+
+ if(kind == ICAL_NO_PROPERTY){
+ /* icalenum_string_to_parameter_kind will set icalerrno */
+ return 0;
+ }
+
+ param = icalproperty_get_first_parameter(prop,kind);
+
+ if (param == 0){
+ return 0;
+ }
+
+ str = icalparameter_as_ical_string(param);
+
+ pv = strchr(str,'=');
+
+ if(pv == 0){
+ icalerror_set_errno(ICAL_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return pv+1;
+
+}
+
+void
+icalproperty_remove_parameter (icalproperty* prop, icalparameter_kind kind)
+{
+ pvl_elem p;
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv((prop!=0),"prop");
+
+ for(p=pvl_head(impl->parameters);p != 0; p = pvl_next(p)){
+ icalparameter* param = (icalparameter *)pvl_data (p);
+ if (icalparameter_isa(param) == kind) {
+ pvl_remove (impl->parameters, p);
+ icalparameter_free (param);
+ break;
+ }
+ }
+}
+
+
+int
+icalproperty_count_parameters (icalproperty* prop)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ if(prop != 0){
+ return pvl_count(p->parameters);
+ }
+
+ icalerror_set_errno(ICAL_USAGE_ERROR);
+ return -1;
+}
+
+
+icalparameter*
+icalproperty_get_first_parameter (icalproperty* prop, icalparameter_kind kind)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ p->parameter_iterator = pvl_head(p->parameters);
+
+ if (p->parameter_iterator == 0) {
+ return 0;
+ }
+
+ for( p->parameter_iterator = pvl_head(p->parameters);
+ p->parameter_iterator !=0;
+ p->parameter_iterator = pvl_next(p->parameter_iterator)){
+
+ icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
+
+ if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
+ return param;
+ }
+ }
+
+ return 0;
+}
+
+
+icalparameter*
+icalproperty_get_next_parameter (icalproperty* prop, icalparameter_kind kind)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ if (p->parameter_iterator == 0) {
+ return 0;
+ }
+
+ for( p->parameter_iterator = pvl_next(p->parameter_iterator);
+ p->parameter_iterator !=0;
+ p->parameter_iterator = pvl_next(p->parameter_iterator)){
+
+ icalparameter *param = (icalparameter*)pvl_data(p->parameter_iterator);
+
+ if(icalparameter_isa(param) == kind || kind == ICAL_ANY_PARAMETER){
+ return param;
+ }
+ }
+
+ return 0;
+
+}
+
+void
+icalproperty_set_value (icalproperty* prop, icalvalue* value)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv((prop !=0),"prop");
+ icalerror_check_arg_rv((value !=0),"value");
+
+ if (p->value != 0){
+ icalvalue_set_parent(p->value,0);
+ icalvalue_free(p->value);
+ p->value = 0;
+ }
+
+ p->value = value;
+
+ icalvalue_set_parent(value,prop);
+}
+
+
+void icalproperty_set_value_from_string(icalproperty* prop,const char* str,
+ const char* type)
+{
+ icalvalue *oval,*nval;
+ icalvalue_kind kind = ICAL_NO_VALUE;
+
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ icalerror_check_arg_rv( (str!=0),"str");
+ icalerror_check_arg_rv( (type!=0),"type");
+
+ if(strcmp(type,"NO")==0){
+ /* Get the type from the value the property already has, if it exists */
+ oval = icalproperty_get_value(prop);
+ if(oval != 0){
+ /* Use the existing value kind */
+ kind = icalvalue_isa(oval);
+ } else {
+ /* Use the default kind for the property */
+ kind = icalproperty_kind_to_value_kind(icalproperty_isa(prop));
+ }
+ } else {
+ /* Use the given kind string */
+ kind = icalvalue_string_to_kind(type);
+ }
+
+ if(kind == ICAL_NO_VALUE){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return;
+ }
+
+ nval = icalvalue_new_from_string(kind, str);
+
+ if(nval == 0){
+ /* icalvalue_new_from_string sets errno */
+ assert(icalerrno != ICAL_NO_ERROR);
+ return;
+ }
+
+ icalproperty_set_value(prop,nval);
+
+
+}
+
+icalvalue*
+icalproperty_get_value (icalproperty* prop)
+{
+ struct icalproperty_impl *p = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ return p->value;
+}
+
+const char* icalproperty_get_value_as_string(icalproperty* prop)
+{
+ icalvalue *value;
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ value = impl->value;
+
+ return icalvalue_as_ical_string(value);
+}
+
+
+void icalproperty_set_x_name(icalproperty* prop, char* name)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rv( (name!=0),"name");
+ icalerror_check_arg_rv( (prop!=0),"prop");
+
+ if (impl->x_name != 0) {
+ free(impl->x_name);
+ }
+
+ impl->x_name = icalmemory_strdup(name);
+
+ if(impl->x_name == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ }
+
+}
+
+char* icalproperty_get_x_name(icalproperty* prop){
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ return impl->x_name;
+}
+
+
+/* From Jonathan Yue <jonathan.yue@cp.net> */
+char* icalproperty_get_name (icalproperty* prop)
+{
+
+ const char* property_name = 0;
+ size_t buf_size = 256;
+ char* buf = icalmemory_new_buffer(buf_size);
+ char* buf_ptr = buf;
+
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)prop;
+
+ icalerror_check_arg_rz( (prop!=0),"prop");
+
+ if (impl->kind == ICAL_X_PROPERTY && impl->x_name != 0){
+ property_name = impl->x_name;
+ } else {
+ property_name = icalproperty_kind_to_string(impl->kind);
+ }
+
+ if (property_name == 0 ) {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+
+ } else {
+ /* _append_string will automatically grow the buffer if
+ property_name is longer than the initial buffer size */
+ icalmemory_append_string(&buf, &buf_ptr, &buf_size, property_name);
+ }
+
+ /* Add the buffer to the temporary buffer ring -- the caller will
+ not have to free the memory. */
+ icalmemory_add_tmp_buffer(buf);
+
+ return buf;
+}
+
+
+
+
+void icalproperty_set_parent(icalproperty* property,
+ icalcomponent* component)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
+
+ icalerror_check_arg_rv( (property!=0),"property");
+
+ impl->parent = component;
+}
+
+icalcomponent* icalproperty_get_parent(icalproperty* property)
+{
+ struct icalproperty_impl *impl = (struct icalproperty_impl*)property;
+
+ icalerror_check_arg_rz( (property!=0),"property");
+
+ return impl->parent;
+}
+
+
+
+
+
+
+
+/* Everything below this line is machine generated. Do not edit. */
diff --git a/src/plugins/vcalendar/libical/libical/icalproperty.h b/src/plugins/vcalendar/libical/libical/icalproperty.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalproperty.h
+ CREATOR: eric 20 March 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 icalparam.h
+
+ ======================================================================*/
+
+
+#ifndef ICALPROPERTY_H
+#define ICALPROPERTY_H
+
+#include <time.h>
+
+
+#include "icalderivedparameter.h"
+
+#include "icalvalue.h"
+#include "icalrecur.h"
+
+/* Actually in icalderivedproperty.h:
+ typedef void icalproperty; */
+
+#include "icalderivedproperty.h" /* To get icalproperty_kind enumerations */
+
+icalproperty* icalproperty_new(icalproperty_kind kind);
+
+icalproperty* icalproperty_new_clone(icalproperty * prop);
+
+icalproperty* icalproperty_new_from_string(char* str);
+
+char* icalproperty_as_ical_string(icalproperty* prop);
+
+void icalproperty_free(icalproperty* prop);
+
+icalproperty_kind icalproperty_isa(icalproperty* property);
+int icalproperty_isa_property(void* property);
+
+void icalproperty_add_parameter(icalproperty* prop,icalparameter* parameter);
+void icalproperty_set_parameter(icalproperty* prop,icalparameter* parameter);
+void icalproperty_set_parameter_from_string(icalproperty* prop,
+ const char* name, const char* value);
+const char* icalproperty_get_parameter_as_string(icalproperty* prop,
+ const char* name);
+
+void icalproperty_remove_parameter(icalproperty* prop,
+ icalparameter_kind kind);
+
+int icalproperty_count_parameters(icalproperty* prop);
+
+/* Iterate through the parameters */
+icalparameter* icalproperty_get_first_parameter(icalproperty* prop,
+ icalparameter_kind kind);
+icalparameter* icalproperty_get_next_parameter(icalproperty* prop,
+ icalparameter_kind kind);
+/* Access the value of the property */
+void icalproperty_set_value(icalproperty* prop, icalvalue* value);
+void icalproperty_set_value_from_string(icalproperty* prop,const char* value, const char* kind);
+
+icalvalue* icalproperty_get_value(icalproperty* prop);
+const char* icalproperty_get_value_as_string(icalproperty* prop);
+
+/* Deal with X properties */
+
+void icalproperty_set_x_name(icalproperty* prop, char* name);
+char* icalproperty_get_x_name(icalproperty* prop);
+
+/* Return the name of the property -- the type name converted to a
+ string, or the value of _get_x_name if the type is and X property */
+char* icalproperty_get_name (icalproperty* prop);
+
+icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value);
+
+/* Convert kinds to string and get default value type */
+
+icalvalue_kind icalproperty_kind_to_value_kind(icalproperty_kind kind);
+icalvalue_kind icalproperty_value_kind_to_kind(icalvalue_kind kind);
+const char* icalproperty_kind_to_string(icalproperty_kind kind);
+icalproperty_kind icalproperty_string_to_kind(const char* string);
+
+icalproperty_method icalproperty_string_to_method(const char* str);
+const char* icalproperty_method_to_string(icalproperty_method method);
+
+
+const char* icalproperty_enum_to_string(int e);
+int icalproperty_string_to_enum(const char* str);
+
+const char* icalproperty_status_to_string(icalproperty_status);
+icalproperty_status icalproperty_string_to_status(const char* string);
+
+int icalproperty_enum_belongs_to_property(icalproperty_kind kind, int e);
+
+
+
+
+#endif /*ICALPROPERTY_H*/
diff --git a/src/plugins/vcalendar/libical/libical/icalrecur.c b/src/plugins/vcalendar/libical/libical/icalrecur.c
@@ -0,0 +1,2258 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalrecur.c
+ CREATOR: eric 16 May 2000
+
+ $Id$
+ $Locker$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+
+ How this code works:
+
+ Processing starts when the caller generates a new recurrence
+ iterator via icalrecur_iterator_new(). This routine copies the
+ recurrence rule into the iterator and extracts things like start and
+ end dates. Then, it checks if the rule is legal, using some logic
+ from RFC2445 and some logic that probably should be in RFC2445.
+
+ Then, icalrecur_iterator_new() re-writes some of the BY*
+ arrays. This involves ( via a call to setup_defaults() ) :
+
+ 1) For BY rule parts with no data ( ie BYSECOND was not specified )
+ copy the corresponding time part from DTSTART into the BY array. (
+ So impl->by_ptrs[BY_SECOND] will then have one element if is
+ originally had none ) This only happens if the BY* rule part data
+ would expand the number of occurrences in the occurrence set. This
+ lets the code ignore DTSTART later on and still use it to get the
+ time parts that were not specified in any other way.
+
+ 2) For the by rule part that are not the same interval as the
+ frequency -- for HOURLY anything but BYHOUR, for instance -- copy the
+ first data element from the rule part into the first occurrence. For
+ example, for "INTERVAL=MONTHLY and BYHOUR=10,30", initialize the
+ first time to be returned to have an hour of 10.
+
+ Finally, for INTERVAL=YEARLY, the routine expands the rule to get
+ all of the days specified in the rule. The code will do this for
+ each new year, and this is the first expansion. This is a special
+ case for the yearly interval; no other frequency gets expanded this
+ way. The yearly interval is the most complex, so some special
+ processing is required.
+
+ After creating a new iterator, the caller will make successive calls
+ to icalrecur_iterator_next() to get the next time specified by the
+ rule. The main part of this routine is a switch on the frequency of
+ the rule. Each different frequency is handled by a different
+ routine.
+
+ For example, next_hour handles the case of INTERVAL=HOURLY, and it
+ is called by other routines to get the next hour. First, the routine
+ tries to get the next minute part of a time with a call to
+ next_minute(). If next_minute() returns 1, it has reached the end of
+ its data, usually the last element of the BYMINUTE array. Then, if
+ there is data in the BYHOUR array, the routine changes the hour to
+ the next one in the array. If INTERVAL=HOURLY, the routine advances
+ the hour by the interval.
+
+ If the routine used the last hour in the BYHOUR array, and the
+ INTERVAL=HOURLY, then the routine calls increment_monthday() to set
+ the next month day. The increment_* routines may call higher routine
+ to increment the month or year also.
+
+ The code for INTERVAL=DAILY is handled by next_day(). First, the
+ routine tries to get the next hour part of a time with a call to
+ next_hour. If next_hour() returns 1, it has reached the end of its
+ data, usually the last element of the BYHOUR array. This means that
+ next_day() should increment the time to the next day. If FREQUENCY==DAILY,
+ the routine increments the day by the interval; otherwise, it
+ increments the day by 1.
+
+ Next_day() differs from next_hour because it does not use the BYDAY
+ array to select an appropriate day. Instead, it returns every day (
+ incrementing by 1 if the frequency is not DAILY with INTERVAL!=1)
+ Any days that are not specified in an non-empty BYDAY array are
+ filtered out later.
+
+ Generally, the flow of these routine is for a next_* call a next_*
+ routine of a lower interval ( next_day calls next_hour) and then to
+ possibly call an increment_* routine of an equal or higher
+ interval. ( next_day calls increment_monthday() )
+
+ When the call to the original next_* routine returns,
+ icalrecur_iterator_next() will check the returned data against other
+ BYrule parts to determine if is should be excluded by calling
+ check_contracting_rules. Generally, a contracting rule is any with a
+ larger time span than the interval. For instance, if
+ INTERVAL=DAILY, BYMONTH is a contracting rule part.
+
+ Check_contracting_rules() uses icalrecur_check_rulepart() to do its
+ work. icalrecur_check_rulepart() uses expand_map[] to determine if a rule
+ is contracting, and if it is, and if the BY rule part has some data,
+ then the routine checks if the value of a component of the time is
+ part of the byrule part. For instance, for "INTERVAL=DAILY;
+ BYMONTH=6,10", icalrecur_check_rulepart() would check that the time value
+ given to it has a month of either 6 or 10.
+
+ Finally, icalrecur_iterator_next() does a few other checks on the
+ time value, and if it passes, it returns the time.
+
+ A note about the end_of_data flag. The flag indicates that the
+ routine is at the end of its data -- the last BY rule if the routine
+ is using by rules, or the last day of the week/month/year/etc if
+ not.
+
+ This flag is usually set early in a next_* routine and returned in
+ the end. The way it is used allows the next_* routine to set the
+ last time back to the first element in a BYxx rule, and then signal
+ to the higer level routine to increment the next higher level. For
+ instance. WITH FREQ=MONTHLY;BYDAY=TU,FR, After next_weekday_by_month
+ runs though both TU and FR, it sets the week day back to TU and sets
+ end_of_data to 1x. This signals next_month to increment the month.
+
+
+ ======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "icalrecur.h"
+
+#ifdef ICAL_NO_LIBICAL
+#define icalerror_set_errno(x)
+#define icalerror_check_arg_rv(x,y)
+#else
+#include "icalerror.h"
+#include "icalmemory.h"
+#endif
+
+#include <glib.h> /* for malloc */
+#include <stdlib.h> /* for malloc */
+#include <errno.h> /* for errno */
+#include <string.h> /* for strdup and strchr*/
+#include <assert.h>
+#include <stddef.h> /* For offsetof() macro */
+
+#include "pvl.h"
+
+#define TEMP_MAX 1024
+
+
+#define BYDAYIDX impl->by_indices[BY_DAY]
+#define BYDAYPTR impl->by_ptrs[BY_DAY]
+
+#define BYMONIDX impl->by_indices[BY_MONTH]
+#define BYMONPTR impl->by_ptrs[BY_MONTH]
+
+#define BYMDIDX impl->by_indices[BY_MONTH_DAY]
+#define BYMDPTR impl->by_ptrs[BY_MONTH_DAY]
+
+#define BYWEEKIDX impl->by_indices[BY_WEEK_NO]
+#define BYWEEKPTR impl->by_ptrs[BY_WEEK_NO]
+
+const char* icalrecur_freq_to_string(icalrecurrencetype_frequency kind);
+icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str);
+
+const char* icalrecur_weekday_to_string(icalrecurrencetype_weekday kind);
+icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str);
+
+
+
+/*********************** Rule parsing routines ************************/
+
+struct icalrecur_parser {
+ const char* rule;
+ char* copy;
+ char* this_clause;
+ char* next_clause;
+
+ struct icalrecurrencetype rt;
+};
+
+const char* icalrecur_first_clause(struct icalrecur_parser *parser)
+{
+ char *idx;
+ parser->this_clause = parser->copy;
+
+ idx = strchr(parser->this_clause,';');
+
+ if (idx == 0){
+ parser->next_clause = 0;
+ return 0;
+ }
+
+ *idx = 0;
+ idx++;
+ parser->next_clause = idx;
+
+ return parser->this_clause;
+
+}
+
+const char* icalrecur_next_clause(struct icalrecur_parser *parser)
+{
+ char* idx;
+
+ parser->this_clause = parser->next_clause;
+
+ if(parser->this_clause == 0){
+ return 0;
+ }
+
+ idx = strchr(parser->this_clause,';');
+
+ if (idx == 0){
+ parser->next_clause = 0;
+ } else {
+
+ *idx = 0;
+ idx++;
+ parser->next_clause = idx;
+ }
+
+ return parser->this_clause;
+
+}
+
+void icalrecur_clause_name_and_value(struct icalrecur_parser *parser,
+ char** name, char** value)
+{
+ char *idx;
+
+ *name = parser->this_clause;
+
+ idx = strchr(parser->this_clause,'=');
+
+ if (idx == 0){
+ *name = 0;
+ *value = 0;
+ return;
+ }
+
+ *idx = 0;
+ idx++;
+ *value = idx;
+}
+
+void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array,
+ int size, char* vals)
+{
+ char *t, *n;
+ int i=0;
+ int sign = 1;
+ short v;
+
+ n = vals;
+
+ while(n != 0){
+
+ if(i == size){
+ return;
+ }
+
+ t = n;
+
+ n = strchr(t,',');
+
+ if(n != 0){
+ *n = 0;
+ n++;
+ }
+
+ /* Get optional sign. HACK. sign is not allowed for all BYxxx
+ rule parts */
+ if( *t == '-'){
+ sign = -1;
+ t++;
+ } else if (*t == '+'){
+ sign = 1;
+ t++;
+ }
+
+ v = atoi(t) * sign ;
+
+
+ array[i++] = v;
+ array[i] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ }
+
+}
+
+void icalrecur_add_bydayrules(struct icalrecur_parser *parser, const char* vals)
+{
+
+ char *t, *n;
+ int i=0;
+ int sign = 1;
+ int weekno = 0;
+ icalrecurrencetype_weekday wd;
+ short *array = parser->rt.by_day;
+ char* end;
+ char* vals_copy;
+
+ vals_copy = icalmemory_strdup(vals);
+
+ end = (char*)vals_copy+strlen(vals_copy);
+ n = vals_copy;
+
+ while(n != 0){
+
+
+ t = n;
+
+ n = strchr(t,',');
+
+ if(n != 0){
+ *n = 0;
+ n++;
+ }
+
+ /* Get optional sign. */
+ if( *t == '-'){
+ sign = -1;
+ t++;
+ } else if (*t == '+'){
+ sign = 1;
+ t++;
+ } else {
+ sign = 1;
+ }
+
+ weekno = 0;
+ /* Get Optional weekno */
+ if( sscanf(t,"%d",&weekno) != 0){
+ if (n != 0){
+ int weeknolen = (n-t)-3; /* 3 -> one for \0, 2 for day name */
+ /* could use abs(log10(weekno))+1, but that needs libm */
+ t += weeknolen;
+ } else {
+ t = end -2;
+ }
+ }
+
+ wd = icalrecur_string_to_weekday(t);
+
+ array[i++] = sign* ((int)wd + 8*weekno);
+ array[i] = ICAL_RECURRENCE_ARRAY_MAX;
+
+ }
+
+ free(vals_copy);
+
+}
+
+
+struct icalrecurrencetype icalrecurrencetype_from_string(const char* str)
+{
+ struct icalrecur_parser parser;
+
+ memset(&parser,0,sizeof(parser));
+ icalrecurrencetype_clear(&parser.rt);
+
+ icalerror_check_arg_re(str!=0,"str",parser.rt);
+
+
+ /* Set up the parser struct */
+ parser.rule = str;
+ parser.copy = icalmemory_strdup(parser.rule);
+ parser.this_clause = parser.copy;
+
+ if(parser.copy == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return parser.rt;
+ }
+
+ /* Loop through all of the clauses */
+ for(icalrecur_first_clause(&parser);
+ parser.this_clause != 0;
+ icalrecur_next_clause(&parser))
+ {
+ char *name, *value;
+ icalrecur_clause_name_and_value(&parser,&name,&value);
+
+ if(name == 0){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ icalrecurrencetype_clear(&parser.rt);
+ return parser.rt;
+ }
+
+ if (strcmp(name,"FREQ") == 0){
+ parser.rt.freq = icalrecur_string_to_freq(value);
+ } else if (strcmp(name,"COUNT") == 0){
+ parser.rt.count = atoi(value);
+ } else if (strcmp(name,"UNTIL") == 0){
+ parser.rt.until = icaltime_from_string(value);
+ } else if (strcmp(name,"INTERVAL") == 0){
+ parser.rt.interval = atoi(value);
+ } else if (strcmp(name,"WKST") == 0){
+ parser.rt.week_start = icalrecur_string_to_weekday(value);
+ } else if (strcmp(name,"BYSECOND") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_second,
+ ICAL_BY_SECOND_SIZE,value);
+ } else if (strcmp(name,"BYMINUTE") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_minute,
+ ICAL_BY_MINUTE_SIZE,value);
+ } else if (strcmp(name,"BYHOUR") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_hour,
+ ICAL_BY_HOUR_SIZE,value);
+ } else if (strcmp(name,"BYDAY") == 0){
+ icalrecur_add_bydayrules(&parser,value);
+ } else if (strcmp(name,"BYMONTHDAY") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_month_day,
+ ICAL_BY_MONTHDAY_SIZE,value);
+ } else if (strcmp(name,"BYYEARDAY") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_year_day,
+ ICAL_BY_YEARDAY_SIZE,value);
+ } else if (strcmp(name,"BYWEEKNO") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_week_no,
+ ICAL_BY_WEEKNO_SIZE,value);
+ } else if (strcmp(name,"BYMONTH") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_month,
+ ICAL_BY_MONTH_SIZE,value);
+ } else if (strcmp(name,"BYSETPOS") == 0){
+ icalrecur_add_byrules(&parser,parser.rt.by_set_pos,
+ ICAL_BY_SETPOS_SIZE,value);
+ } else {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ icalrecurrencetype_clear(&parser.rt);
+ return parser.rt;
+ }
+
+ }
+
+ free(parser.copy);
+
+ return parser.rt;
+
+}
+
+#ifndef ICAL_NO_LIBICAL
+
+struct { char* str;size_t offset; short limit; } recurmap[] =
+{
+ {";BYSECOND=",offsetof(struct icalrecurrencetype,by_second),60},
+ {";BYMINUTE=",offsetof(struct icalrecurrencetype,by_minute),60},
+ {";BYHOUR=",offsetof(struct icalrecurrencetype,by_hour),24},
+ {";BYDAY=",offsetof(struct icalrecurrencetype,by_day),7},
+ {";BYMONTHDAY=",offsetof(struct icalrecurrencetype,by_month_day),31},
+ {";BYYEARDAY=",offsetof(struct icalrecurrencetype,by_year_day),366},
+ {";BYWEEKNO=",offsetof(struct icalrecurrencetype,by_week_no),52},
+ {";BYMONTH=",offsetof(struct icalrecurrencetype,by_month),12},
+ {";BYSETPOS=",offsetof(struct icalrecurrencetype,by_set_pos),366},
+ {0,0,0},
+};
+
+/* A private routine in icalvalue.c */
+void print_datetime_to_string(char* str, struct icaltimetype *data);
+
+char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur)
+{
+ char* str;
+ char *str_p;
+ size_t buf_sz = 200;
+ char temp[20];
+ int i,j;
+
+ if(recur->freq == ICAL_NO_RECURRENCE){
+ return 0;
+ }
+
+ str = (char*)icalmemory_tmp_buffer(buf_sz);
+ str_p = str;
+
+ icalmemory_append_string(&str,&str_p,&buf_sz,"FREQ=");
+ icalmemory_append_string(&str,&str_p,&buf_sz,
+ icalrecur_freq_to_string(recur->freq));
+
+ if(recur->until.year != 0){
+
+ temp[0] = 0;
+ print_datetime_to_string(temp,&(recur->until));
+
+ icalmemory_append_string(&str,&str_p,&buf_sz,";UNTIL=");
+ icalmemory_append_string(&str,&str_p,&buf_sz, temp);
+ }
+
+ if(recur->count != 0){
+ sprintf(temp,"%d",recur->count);
+ icalmemory_append_string(&str,&str_p,&buf_sz,";COUNT=");
+ icalmemory_append_string(&str,&str_p,&buf_sz, temp);
+ }
+
+ if(recur->interval != 0){
+ sprintf(temp,"%d",recur->interval);
+ icalmemory_append_string(&str,&str_p,&buf_sz,";INTERVAL=");
+ icalmemory_append_string(&str,&str_p,&buf_sz, temp);
+ }
+
+ for(j =0; recurmap[j].str != 0; j++){
+ short* array = (short*)(recurmap[j].offset+ (size_t)recur);
+ short limit = recurmap[j].limit;
+
+ /* Skip unused arrays */
+ if( array[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
+
+ icalmemory_append_string(&str,&str_p,&buf_sz,recurmap[j].str);
+
+ for(i=0;
+ i< limit && array[i] != ICAL_RECURRENCE_ARRAY_MAX;
+ i++){
+ if (j == 3) { /* BYDAY */
+ short dow = icalrecurrencetype_day_day_of_week(array[i]);
+ const char *daystr = icalrecur_weekday_to_string(dow);
+ short pos;
+
+ pos = icalrecurrencetype_day_position(array[i]);
+
+ if (pos == 0)
+ icalmemory_append_string(&str,&str_p,&buf_sz,daystr);
+ else {
+ sprintf(temp,"%d%s",pos,daystr);
+ icalmemory_append_string(&str,&str_p,&buf_sz,temp);
+ }
+
+ } else {
+ sprintf(temp,"%d",array[i]);
+ icalmemory_append_string(&str,&str_p,&buf_sz, temp);
+ }
+
+ if( (i+1)<limit &&array[i+1]
+ != ICAL_RECURRENCE_ARRAY_MAX){
+ icalmemory_append_char(&str,&str_p,&buf_sz,',');
+ }
+ }
+ }
+ }
+
+ return str;
+}
+#endif
+
+
+
+/************************* occurrence iteration routiens ******************/
+
+enum byrule {
+ NO_CONTRACTION = -1,
+ BY_SECOND = 0,
+ BY_MINUTE = 1,
+ BY_HOUR = 2,
+ BY_DAY = 3,
+ BY_MONTH_DAY = 4,
+ BY_YEAR_DAY = 5,
+ BY_WEEK_NO = 6,
+ BY_MONTH = 7,
+ BY_SET_POS
+};
+
+
+
+struct icalrecur_iterator_impl {
+
+ struct icaltimetype dtstart; /* Hack. Make into time_t */
+ struct icaltimetype last; /* last time return from _iterator_next*/
+ int occurrence_no; /* number of step made on t iterator */
+ struct icalrecurrencetype rule;
+
+ short days[366];
+ short days_index;
+
+ enum byrule byrule;
+ short by_indices[9];
+ short orig_data[9]; /* 1 if there was data in the byrule */
+
+
+ short *by_ptrs[9]; /* Pointers into the by_* array elements of the rule */
+
+};
+
+int icalrecur_iterator_sizeof_byarray(short* byarray)
+{
+ int array_itr;
+
+ for(array_itr = 0;
+ byarray[array_itr] != ICAL_RECURRENCE_ARRAY_MAX;
+ array_itr++){
+ }
+
+ return array_itr;
+}
+
+enum expand_table {
+ UNKNOWN = 0,
+ CONTRACT = 1,
+ EXPAND =2,
+ ILLEGAL=3
+};
+
+/* The split map indicates, for a particular interval, wether a BY_*
+ rule part expands the number of instances in the occcurrence set or
+ contracts it. 1=> contract, 2=>expand, and 3 means the pairing is
+ not allowed. */
+struct expand_split_map_struct
+{
+ icalrecurrencetype_frequency frequency;
+
+ /* Elements of the 'map' array correspond to the BYxxx rules:
+ Second,Minute,Hour,Day,Month Day,Year Day,Week No,Month*/
+
+ short map[8];
+};
+
+struct expand_split_map_struct expand_map[] =
+{
+ {ICAL_SECONDLY_RECURRENCE,{1,1,1,1,1,1,1,1}},
+ {ICAL_MINUTELY_RECURRENCE,{2,1,1,1,1,1,1,1}},
+ {ICAL_HOURLY_RECURRENCE, {2,2,1,1,1,1,1,1}},
+ {ICAL_DAILY_RECURRENCE, {2,2,2,1,1,1,1,1}},
+ {ICAL_WEEKLY_RECURRENCE, {2,2,2,2,3,3,1,1}},
+ {ICAL_MONTHLY_RECURRENCE, {2,2,2,2,2,3,3,1}},
+ {ICAL_YEARLY_RECURRENCE, {2,2,2,2,2,2,2,2}},
+ {ICAL_NO_RECURRENCE, {0,0,0,0,0,0,0,0}}
+
+};
+
+
+
+/* Check that the rule has only the two given interday byrule parts. */
+int icalrecur_two_byrule(struct icalrecur_iterator_impl* impl,
+ enum byrule one,enum byrule two)
+{
+ short test_array[9];
+ enum byrule itr;
+ int passes = 0;
+
+ memset(test_array,0,9);
+
+ test_array[one] = 1;
+ test_array[two] = 1;
+
+ for(itr = BY_DAY; itr != BY_SET_POS; itr++){
+
+ if( (test_array[itr] == 0 &&
+ impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX
+ ) ||
+ (test_array[itr] == 1 &&
+ impl->by_ptrs[itr][0] == ICAL_RECURRENCE_ARRAY_MAX
+ )
+ ) {
+ /* test failed */
+ passes = 0;
+ }
+ }
+
+ return passes;
+
+}
+
+/* Check that the rule has only the one given interdat byrule parts. */
+int icalrecur_one_byrule(struct icalrecur_iterator_impl* impl,enum byrule one)
+{
+ int passes = 1;
+ enum byrule itr;
+
+ for(itr = BY_DAY; itr != BY_SET_POS; itr++){
+
+ if ((itr==one && impl->by_ptrs[itr][0] == ICAL_RECURRENCE_ARRAY_MAX) ||
+ (itr!=one && impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX)) {
+ passes = 0;
+ }
+ }
+
+ return passes;
+}
+
+int count_byrules(struct icalrecur_iterator_impl* impl)
+{
+ int count = 0;
+ enum byrule itr;
+
+ for(itr = BY_DAY; itr <= BY_SET_POS; itr++){
+ if(impl->by_ptrs[itr][0] != ICAL_RECURRENCE_ARRAY_MAX){
+ count++;
+ }
+ }
+
+ return count;
+}
+
+
+void setup_defaults(struct icalrecur_iterator_impl* impl,
+ enum byrule byrule, icalrecurrencetype_frequency req,
+ short deftime, int *timepart)
+{
+
+ icalrecurrencetype_frequency freq;
+ freq = impl->rule.freq;
+
+ /* Re-write the BY rule arrays with data from the DTSTART time so
+ we don't have to explicitly deal with DTSTART */
+
+ if(impl->by_ptrs[byrule][0] == ICAL_RECURRENCE_ARRAY_MAX &&
+ expand_map[freq].map[byrule] != CONTRACT){
+ impl->by_ptrs[byrule][0] = deftime;
+ }
+
+ /* Initialize the first occurence */
+ if( freq != req && expand_map[freq].map[byrule] != CONTRACT){
+ *timepart = impl->by_ptrs[byrule][0];
+ }
+
+
+}
+
+int has_by_data(struct icalrecur_iterator_impl* impl, enum byrule byrule){
+
+ return (impl->orig_data[byrule] == 1);
+}
+
+
+int expand_year_days(struct icalrecur_iterator_impl* impl,short year);
+
+
+icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
+ struct icaltimetype dtstart)
+{
+ struct icalrecur_iterator_impl* impl;
+ icalrecurrencetype_frequency freq;
+
+ short days_in_month;
+
+ if ( ( impl = (struct icalrecur_iterator_impl *)
+ malloc(sizeof(struct icalrecur_iterator_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ memset(impl,0,sizeof(struct icalrecur_iterator_impl));
+
+ impl->rule = rule;
+ impl->last = dtstart;
+ impl->dtstart = dtstart;
+ impl->days_index =0;
+ impl->occurrence_no = 0;
+ freq = impl->rule.freq;
+
+ /* Set up convienience pointers to make the code simpler. Allows
+ us to iterate through all of the BY* arrays in the rule. */
+
+ impl->by_ptrs[BY_MONTH]=impl->rule.by_month;
+ impl->by_ptrs[BY_WEEK_NO]=impl->rule.by_week_no;
+ impl->by_ptrs[BY_YEAR_DAY]=impl->rule.by_year_day;
+ impl->by_ptrs[BY_MONTH_DAY]=impl->rule.by_month_day;
+ impl->by_ptrs[BY_DAY]=impl->rule.by_day;
+ impl->by_ptrs[BY_HOUR]=impl->rule.by_hour;
+ impl->by_ptrs[BY_MINUTE]=impl->rule.by_minute;
+ impl->by_ptrs[BY_SECOND]=impl->rule.by_second;
+ impl->by_ptrs[BY_SET_POS]=impl->rule.by_set_pos;
+
+ memset(impl->orig_data,0,9);
+
+ /* Note which by rules had data in them when the iterator was
+ created. We can't use the actuall by_x arrays, because the
+ empty ones will be given default values later in this
+ routine. The orig_data array will be used later in has_by_data */
+
+ impl->orig_data[BY_MONTH]
+ = (impl->rule.by_month[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_WEEK_NO]
+ =(impl->rule.by_week_no[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_YEAR_DAY]
+ =(impl->rule.by_year_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_MONTH_DAY]
+ =(impl->rule.by_month_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_DAY]
+ = (impl->rule.by_day[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_HOUR]
+ = (impl->rule.by_hour[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_MINUTE]
+ = (impl->rule.by_minute[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_SECOND]
+ = (impl->rule.by_second[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ impl->orig_data[BY_SET_POS]
+ = (impl->rule.by_set_pos[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+
+
+ /* Check if the recurrence rule is legal */
+
+ /* If the BYYEARDAY appears, no other date rule part may appear. */
+
+ if(icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_MONTH) ||
+ icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_WEEK_NO) ||
+ icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_MONTH_DAY) ||
+ icalrecur_two_byrule(impl,BY_YEAR_DAY,BY_DAY) ){
+
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+
+ return 0;
+ }
+
+ /* BYWEEKNO and BYMONTH rule parts may not both appear.*/
+
+ if(icalrecur_two_byrule(impl,BY_WEEK_NO,BY_MONTH)){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ /* BYWEEKNO and BYMONTHDAY rule parts may not both appear.*/
+
+ if(icalrecur_two_byrule(impl,BY_WEEK_NO,BY_MONTH_DAY)){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+
+ /*For MONTHLY recurrences (FREQ=MONTHLY) neither BYYEARDAY nor
+ BYWEEKNO may appear. */
+
+ if(freq == ICAL_MONTHLY_RECURRENCE &&
+ icalrecur_one_byrule(impl,BY_WEEK_NO)){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+
+ /*For WEEKLY recurrences (FREQ=WEEKLY) neither BYMONTHDAY nor
+ BYYEARDAY may appear. */
+
+ if(freq == ICAL_WEEKLY_RECURRENCE &&
+ icalrecur_one_byrule(impl,BY_MONTH_DAY )) {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ /* BYYEARDAY may only appear in YEARLY rules */
+ if(freq != ICAL_YEARLY_RECURRENCE &&
+ icalrecur_one_byrule(impl,BY_YEAR_DAY )) {
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ /* Rewrite some of the rules and set up defaults to make later
+ processing easier. Primarily, t involves copying an element
+ from the start time into the coresponding BY_* array when the
+ BY_* array is empty */
+
+
+ setup_defaults(impl,BY_SECOND,ICAL_SECONDLY_RECURRENCE,impl->dtstart.second,
+ &(impl->last.second));
+
+ setup_defaults(impl,BY_MINUTE,ICAL_MINUTELY_RECURRENCE,impl->dtstart.minute,
+ &(impl->last.minute));
+
+ setup_defaults(impl,BY_HOUR,ICAL_HOURLY_RECURRENCE,impl->dtstart.hour,
+ &(impl->last.hour));
+
+ setup_defaults(impl,BY_MONTH_DAY,ICAL_DAILY_RECURRENCE,impl->dtstart.day,
+ &(impl->last.day));
+
+ setup_defaults(impl,BY_MONTH,ICAL_MONTHLY_RECURRENCE,impl->dtstart.month,
+ &(impl->last.month));
+
+
+ if(impl->rule.freq == ICAL_WEEKLY_RECURRENCE ){
+
+ if(impl->by_ptrs[BY_DAY][0] == ICAL_RECURRENCE_ARRAY_MAX){
+
+ /* Weekly recurrences with no BY_DAY data should occur on the
+ same day of the week as the start time . */
+ impl->by_ptrs[BY_DAY][0] = icaltime_day_of_week(impl->dtstart);
+
+ } else {
+ /* If there is BY_DAY data, then we need to move the initial
+ time to the start of the BY_DAY data. That is if the
+ start time is on a Wednesday, and the rule has
+ BYDAY=MO,WE,FR, move the initial time back to
+ monday. Otherwise, jumping to the next week ( jumping 7
+ days ahead ) will skip over some occurrences in the
+ second week. */
+
+ /* This is probably a HACK. There should be some more
+ general way to solve this problem */
+
+ short dow = impl->by_ptrs[BY_DAY][0]-icaltime_day_of_week(impl->last);
+
+ if(dow < 0) {
+ /* initial time is after first day of BY_DAY data */
+
+ impl->last.day += dow;
+ impl->last = icaltime_normalize(impl->last);
+ }
+ }
+
+
+ }
+
+ /* For YEARLY rule, begin by setting up the year days array */
+
+ if(impl->rule.freq == ICAL_YEARLY_RECURRENCE){
+ expand_year_days(impl,impl->last.year);
+ }
+
+
+ /* If this is a monthly interval with by day data, then we need to
+ set the last value to the appropriate day of the month */
+
+ if(impl->rule.freq == ICAL_MONTHLY_RECURRENCE &&
+ has_by_data(impl,BY_DAY)) {
+
+ short dow = icalrecurrencetype_day_day_of_week(
+ impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);
+ short pos = icalrecurrencetype_day_position(
+ impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]);
+
+ short poscount = 0;
+ days_in_month =
+ icaltime_days_in_month(impl->last.month, impl->last.year);
+
+ if(pos >= 0){
+ /* Count up from the first day pf the month to find the
+ pos'th weekday of dow ( like the second monday. ) */
+
+ for(impl->last.day = 1;
+ impl->last.day <= days_in_month;
+ impl->last.day++){
+
+ if(icaltime_day_of_week(impl->last) == dow){
+ if(++poscount == pos || pos == 0){
+ break;
+ }
+ }
+ }
+ } else {
+ /* Count down from the last day pf the month to find the
+ pos'th weekday of dow ( like the second to last monday. ) */
+ pos = -pos;
+ for(impl->last.day = days_in_month;
+ impl->last.day != 0;
+ impl->last.day--){
+
+ if(icaltime_day_of_week(impl->last) == dow){
+ if(++poscount == pos ){
+ break;
+ }
+ }
+ }
+ }
+
+
+ if(impl->last.day > days_in_month || impl->last.day == 0){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return 0;
+ }
+
+ }
+
+
+
+ return impl;
+}
+
+
+void icalrecur_iterator_free(icalrecur_iterator* i)
+{
+
+ struct icalrecur_iterator_impl* impl =
+ (struct icalrecur_iterator_impl*)i;
+
+ icalerror_check_arg_rv((impl!=0),"impl");
+
+ free(impl);
+
+}
+
+
+void increment_year(struct icalrecur_iterator_impl* impl, int inc)
+{
+ impl->last.year+=inc;
+}
+
+/* Increment month is different that the other incement_* routines --
+ it figures out the interval for itself, and uses BYMONTH data if
+ available. */
+void increment_month(struct icalrecur_iterator_impl* impl)
+{
+ int years;
+
+ if(has_by_data(impl,BY_MONTH) ){
+ /* Ignore the frequency and use the byrule data */
+
+ impl->by_indices[BY_MONTH]++;
+
+ if (impl->by_ptrs[BY_MONTH][impl->by_indices[BY_MONTH]]
+ ==ICAL_RECURRENCE_ARRAY_MAX){
+ impl->by_indices[BY_MONTH] = 0;
+
+ increment_year(impl,1);
+
+ }
+
+ impl->last.month =
+ impl->by_ptrs[BY_MONTH][impl->by_indices[BY_MONTH]];
+
+ } else {
+
+ int inc;
+
+ if(impl->rule.freq == ICAL_MONTHLY_RECURRENCE){
+ inc = impl->rule.interval;
+ } else {
+ inc = 1;
+ }
+
+ impl->last.month+=inc;
+
+ /* Months are offset by one */
+ impl->last.month--;
+
+ years = impl->last.month / 12;
+
+ impl->last.month = impl->last.month % 12;
+
+ impl->last.month++;
+
+ if (years != 0){
+ increment_year(impl,years);
+ }
+ }
+}
+
+void increment_monthday(struct icalrecur_iterator_impl* impl, int inc)
+{
+ int i;
+
+ for(i=0; i<inc; i++){
+
+ short days_in_month =
+ icaltime_days_in_month(impl->last.month,impl->last.year);
+
+ impl->last.day++;
+
+ if (impl->last.day > days_in_month){
+ impl->last.day = impl->last.day-days_in_month;
+ increment_month(impl);
+ }
+ }
+}
+
+
+void increment_hour(struct icalrecur_iterator_impl* impl, int inc)
+{
+ short days;
+
+ impl->last.hour+=inc;
+
+ days = impl->last.hour / 24;
+ impl->last.hour = impl->last.hour % 24;
+
+ if (impl->days != 0){
+ increment_monthday(impl,days);
+ }
+}
+
+void increment_minute(struct icalrecur_iterator_impl* impl, int inc)
+{
+ short hours;
+
+ impl->last.minute+=inc;
+
+ hours = impl->last.minute / 60;
+ impl->last.minute = impl->last.minute % 60;
+
+ if (hours != 0){
+ increment_hour(impl,hours);
+ }
+
+}
+
+void increment_second(struct icalrecur_iterator_impl* impl, int inc)
+{
+ short minutes;
+
+ impl->last.second+=inc;
+
+ minutes = impl->last.second / 60;
+ impl->last.second = impl->last.second % 60;
+
+ if (minutes != 0)
+ {
+ increment_minute(impl, minutes);
+ }
+}
+
+#if 0
+#include "ical.h"
+void test_increment()
+{
+ struct icalrecur_iterator_impl impl;
+
+ impl.last = icaltime_from_string("20000101T000000Z");
+
+ printf("Orig: %s\n",icaltime_as_ctime(impl.last));
+
+ increment_second(&impl,5);
+ printf("+ 5 sec : %s\n",icaltime_as_ctime(impl.last));
+
+ increment_second(&impl,355);
+ printf("+ 355 sec : %s\n",icaltime_as_ctime(impl.last));
+
+ increment_minute(&impl,5);
+ printf("+ 5 min : %s\n",icaltime_as_ctime(impl.last));
+
+ increment_minute(&impl,360);
+ printf("+ 360 min : %s\n",icaltime_as_ctime(impl.last));
+ increment_hour(&impl,5);
+ printf("+ 5 hours : %s\n",icaltime_as_ctime(impl.last));
+ increment_hour(&impl,43);
+ printf("+ 43 hours : %s\n",icaltime_as_ctime(impl.last));
+ increment_monthday(&impl,3);
+ printf("+ 3 days : %s\n",icaltime_as_ctime(impl.last));
+ increment_monthday(&impl,600);
+ printf("+ 600 days : %s\n",icaltime_as_ctime(impl.last));
+
+}
+
+#endif
+
+short next_second(struct icalrecur_iterator_impl* impl)
+{
+
+ short has_by_data = (impl->by_ptrs[BY_SECOND][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ short this_frequency = (impl->rule.freq == ICAL_SECONDLY_RECURRENCE);
+
+ short end_of_data = 0;
+
+ assert(has_by_data || this_frequency);
+
+ if( has_by_data ){
+ /* Ignore the frequency and use the byrule data */
+
+ impl->by_indices[BY_SECOND]++;
+
+ if (impl->by_ptrs[BY_SECOND][impl->by_indices[BY_SECOND]]
+ ==ICAL_RECURRENCE_ARRAY_MAX){
+ impl->by_indices[BY_SECOND] = 0;
+
+ end_of_data = 1;
+ }
+
+
+ impl->last.second =
+ impl->by_ptrs[BY_SECOND][impl->by_indices[BY_SECOND]];
+
+
+ } else if( !has_by_data && this_frequency ){
+ /* Compute the next value from the last time and the frequency interval*/
+ increment_second(impl, impl->rule.interval);
+
+ }
+
+ /* If we have gone through all of the seconds on the BY list, then we
+ need to move to the next minute */
+
+ if(has_by_data && end_of_data && this_frequency ){
+ increment_minute(impl,1);
+ }
+
+ return end_of_data;
+
+}
+
+int next_minute(struct icalrecur_iterator_impl* impl)
+{
+
+ short has_by_data = (impl->by_ptrs[BY_MINUTE][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ short this_frequency = (impl->rule.freq == ICAL_MINUTELY_RECURRENCE);
+
+ short end_of_data = 0;
+
+ assert(has_by_data || this_frequency);
+
+
+ if (next_second(impl) == 0){
+ return 0;
+ }
+
+ if( has_by_data ){
+ /* Ignore the frequency and use the byrule data */
+
+ impl->by_indices[BY_MINUTE]++;
+
+ if (impl->by_ptrs[BY_MINUTE][impl->by_indices[BY_MINUTE]]
+ ==ICAL_RECURRENCE_ARRAY_MAX){
+
+ impl->by_indices[BY_MINUTE] = 0;
+
+ end_of_data = 1;
+ }
+
+ impl->last.minute =
+ impl->by_ptrs[BY_MINUTE][impl->by_indices[BY_MINUTE]];
+
+ } else if( !has_by_data && this_frequency ){
+ /* Compute the next value from the last time and the frequency interval*/
+ increment_minute(impl,impl->rule.interval);
+ }
+
+/* If we have gone through all of the minutes on the BY list, then we
+ need to move to the next hour */
+
+ if(has_by_data && end_of_data && this_frequency ){
+ increment_hour(impl,1);
+ }
+
+ return end_of_data;
+}
+
+int next_hour(struct icalrecur_iterator_impl* impl)
+{
+
+ short has_by_data = (impl->by_ptrs[BY_HOUR][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ short this_frequency = (impl->rule.freq == ICAL_HOURLY_RECURRENCE);
+
+ short end_of_data = 0;
+
+ assert(has_by_data || this_frequency);
+
+ if (next_minute(impl) == 0){
+ return 0;
+ }
+
+ if( has_by_data ){
+ /* Ignore the frequency and use the byrule data */
+
+ impl->by_indices[BY_HOUR]++;
+
+ if (impl->by_ptrs[BY_HOUR][impl->by_indices[BY_HOUR]]
+ ==ICAL_RECURRENCE_ARRAY_MAX){
+ impl->by_indices[BY_HOUR] = 0;
+
+ end_of_data = 1;
+ }
+
+ impl->last.hour =
+ impl->by_ptrs[BY_HOUR][impl->by_indices[BY_HOUR]];
+
+ } else if( !has_by_data && this_frequency ){
+ /* Compute the next value from the last time and the frequency interval*/
+ increment_hour(impl,impl->rule.interval);
+
+ }
+
+ /* If we have gone through all of the hours on the BY list, then we
+ need to move to the next day */
+
+ if(has_by_data && end_of_data && this_frequency ){
+ increment_monthday(impl,1);
+ }
+
+ return end_of_data;
+
+}
+
+int next_day(struct icalrecur_iterator_impl* impl)
+{
+
+ short has_by_data = (impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ short this_frequency = (impl->rule.freq == ICAL_DAILY_RECURRENCE);
+
+ assert(has_by_data || this_frequency);
+
+ if (next_hour(impl) == 0){
+ return 0;
+ }
+
+ /* Always increment through the interval, since this routine is not
+ called by any other next_* routine, and the days that are
+ excluded will be taken care of by restriction filtering */
+
+ if(this_frequency){
+ increment_monthday(impl,impl->rule.interval);
+ } else {
+ increment_monthday(impl,1);
+ }
+
+
+ return 0;
+
+}
+
+
+int next_yearday(struct icalrecur_iterator_impl* impl)
+{
+
+ short has_by_data = (impl->by_ptrs[BY_YEAR_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+
+ short end_of_data = 0;
+
+ assert(has_by_data );
+
+ if (next_hour(impl) == 0){
+ return 0;
+ }
+
+ impl->by_indices[BY_YEAR_DAY]++;
+
+ if (impl->by_ptrs[BY_YEAR_DAY][impl->by_indices[BY_YEAR_DAY]]
+ ==ICAL_RECURRENCE_ARRAY_MAX){
+ impl->by_indices[BY_YEAR_DAY] = 0;
+
+ end_of_data = 1;
+ }
+
+ impl->last.day =
+ impl->by_ptrs[BY_YEAR_DAY][impl->by_indices[BY_YEAR_DAY]];
+
+ if(has_by_data && end_of_data){
+ increment_year(impl,1);
+ }
+
+ return end_of_data;
+
+}
+
+/* This routine is only called by next_week. It is certain that BY_DAY
+has data */
+
+int next_weekday_by_week(struct icalrecur_iterator_impl* impl)
+{
+
+ short end_of_data = 0;
+ short start_of_week, dow;
+ struct icaltimetype next;
+
+ if (next_hour(impl) == 0){
+ return 0;
+ }
+
+ assert( impl->by_ptrs[BY_DAY][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+
+ while(1) {
+
+ impl->by_indices[BY_DAY]++; /* Look at next elem in BYDAY array */
+
+ /* Are we at the end of the BYDAY array? */
+ if (impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]]
+ ==ICAL_RECURRENCE_ARRAY_MAX){
+
+ impl->by_indices[BY_DAY] = 0; /* Reset to 0 */
+ end_of_data = 1; /* Signal that we're at the end */
+ }
+
+ /* Add the day of week offset to to the start of this week, and use
+ that to get the next day */
+ dow = impl->by_ptrs[BY_DAY][impl->by_indices[BY_DAY]];
+ start_of_week = icaltime_start_doy_of_week(impl->last);
+
+ dow--; /*Sun is 1, not 0 */
+
+ if(dow+start_of_week <1 && !end_of_data){
+ /* The selected date is in the previous year. */
+ continue;
+ }
+
+ next = icaltime_from_day_of_year(start_of_week + dow,impl->last.year);
+
+ impl->last.day = next.day;
+ impl->last.month = next.month;
+ impl->last.year = next.year;
+
+ return end_of_data;
+ }
+
+}
+
+int nth_weekday(short dow, short pos, struct icaltimetype t){
+
+ short days_in_month = icaltime_days_in_month(t.month,t.year);
+ short end_dow, start_dow;
+ short wd;
+
+ if(pos >= 0){
+ t.day = 1;
+ start_dow = icaltime_day_of_week(t);
+
+ if (pos != 0) {
+ pos--;
+ }
+
+ /* find month day of first occurrence of dow -- such as the
+ month day of the first monday */
+
+ wd = dow-start_dow+1;
+
+ if (wd <= 0){
+ wd = wd + 7;
+ }
+
+ wd = wd + pos * 7;
+
+ } else {
+ t.day = days_in_month;
+ end_dow = icaltime_day_of_week(t);
+
+ pos++;
+
+ /* find month day of last occurrence of dow -- such as the
+ month day of the last monday */
+
+ wd = (end_dow - dow);
+
+ if (wd < 0){
+ wd = wd+ 7;
+ }
+
+ wd = days_in_month - wd;
+
+ wd = wd + pos * 7;
+ }
+
+ return wd;
+}
+
+
+int next_month(struct icalrecur_iterator_impl* impl)
+{
+ int data_valid = 1;
+
+ short this_frequency = (impl->rule.freq == ICAL_MONTHLY_RECURRENCE);
+
+ assert( has_by_data(impl,BY_MONTH) || this_frequency);
+
+ /* Iterate through the occurrences within a day. If we don't get to
+ the end of the intra-day data, don't bother going to the next
+ month */
+
+ if (next_hour(impl) == 0){
+ return data_valid; /* Signal that the data is valid */
+ }
+
+
+ /* Now iterate through the occurrences within a month -- by days,
+ weeks or weekdays. */
+
+ if(has_by_data(impl,BY_DAY) && has_by_data(impl,BY_MONTH_DAY)){
+ /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYMONTHDAY=13 */
+ short day, idx,j;
+ short days_in_month = icaltime_days_in_month(impl->last.month,
+ impl->last.year);
+ /* Iterate through the remaining days in the month and check if
+ each day is listed in the BY_DAY array and in the BY_MONTHDAY
+ array. This seems very inneficient, but I think it is the
+ simplest way to account for both BYDAY=1FR (First friday in
+ month) and BYDAY=FR ( every friday in month ) */
+
+ for(day = impl->last.day+1; day <= days_in_month; day++){
+ for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){
+ for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
+ short dow =
+ icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);
+ short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]);
+ short mday = BYMDPTR[j];
+ short this_dow;
+
+ impl->last.day = day;
+ this_dow = icaltime_day_of_week(impl->last);
+
+ if( (pos == 0 && dow == this_dow && mday == day) ||
+ (nth_weekday(dow,pos,impl->last) == day && mday==day)){
+ goto MDEND;
+ }
+ }
+ }
+ }
+
+ MDEND:
+
+ if ( day > days_in_month){
+ impl->last.day = 1;
+ increment_month(impl);
+ data_valid = 0; /* signal that impl->last is invalid */
+ }
+
+
+ } else if(has_by_data(impl,BY_DAY)){
+ /* Cases like: FREQ=MONTHLY;INTERVAL=1;BYDAY=FR */
+ /* For this case, the weekdays are relative to the
+ month. BYDAY=FR -> First Friday in month, etc. */
+
+ short day, idx;
+ short days_in_month = icaltime_days_in_month(impl->last.month,
+ impl->last.year);
+
+ assert( BYDAYPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+
+ /* Iterate through the remaining days in the month and check if
+ each day is listed in the BY_DAY array. This seems very
+ inneficient, but I think it is the simplest way to account
+ for both BYDAY=1FR (First friday in month) and BYDAY=FR (
+ every friday in month ) */
+
+ for(day = impl->last.day+1; day <= days_in_month; day++){
+ for(idx = 0; BYDAYPTR[idx] != ICAL_RECURRENCE_ARRAY_MAX; idx++){
+ short dow = icalrecurrencetype_day_day_of_week(BYDAYPTR[idx]);
+ short pos = icalrecurrencetype_day_position(BYDAYPTR[idx]);
+ short this_dow;
+
+ impl->last.day = day;
+ this_dow = icaltime_day_of_week(impl->last);
+
+ if( (pos == 0 && dow == this_dow ) ||
+ (nth_weekday(dow,pos,impl->last) == day)){
+ goto DEND;
+ }
+ }
+ }
+
+ DEND:
+
+ if ( day > days_in_month){
+ impl->last.day = 1;
+ increment_month(impl);
+ data_valid = 0; /* signal that impl->last is invalid */
+ }
+
+ } else if (has_by_data(impl,BY_MONTH_DAY)) {
+ /* Cases like: FREQ=MONTHLY;COUNT=10;BYMONTHDAY=-3 */
+ short day;
+
+ assert( BYMDPTR[0]!=ICAL_RECURRENCE_ARRAY_MAX);
+
+ BYMDIDX++;
+
+ /* Are we at the end of the BYDAY array? */
+ if (BYMDPTR[BYMDIDX] ==ICAL_RECURRENCE_ARRAY_MAX){
+
+ BYMDIDX = 0; /* Reset to 0 */
+ increment_month(impl);
+ }
+
+ day = BYMDPTR[BYMDIDX];
+
+ if (day < 0) {
+ day = icaltime_days_in_month(impl->last.month,impl->last.year)+
+ day + 1;
+ }
+
+ impl->last.day = day;
+
+ } else {
+ increment_month(impl);
+ }
+
+ return data_valid; /* Signal that the data is valid */
+
+}
+
+
+int next_week(struct icalrecur_iterator_impl* impl)
+{
+ short has_by_data = (impl->by_ptrs[BY_WEEK_NO][0]!=ICAL_RECURRENCE_ARRAY_MAX);
+ short this_frequency = (impl->rule.freq == ICAL_WEEKLY_RECURRENCE);
+ short end_of_data = 0;
+
+ /* Increment to the next week day */
+ if (next_weekday_by_week(impl) == 0){
+ return 0; /* Have not reached end of week yet */
+ }
+
+ /* If we get here, we have incremented through the entire week, and
+ can increment to the next week */
+
+
+ if( has_by_data){
+ /* Use the Week Number byrule data */
+ int week_no;
+ struct icaltimetype t;
+
+ impl->by_indices[BY_WEEK_NO]++;
+
+ if (impl->by_ptrs[BY_WEEK_NO][impl->by_indices[BY_WEEK_NO]]
+ ==ICAL_RECURRENCE_ARRAY_MAX){
+ impl->by_indices[BY_WEEK_NO] = 0;
+
+ end_of_data = 1;
+ }
+
+ t = impl->last;
+ t.month=1; /* HACK, should be setting to the date of the first week of year*/
+ t.day=1;
+
+ week_no = impl->by_ptrs[BY_WEEK_NO][impl->by_indices[BY_WEEK_NO]];
+
+ impl->last.day += week_no*7;
+
+ impl->last = icaltime_normalize(impl->last);
+
+ } else if( !has_by_data && this_frequency ){
+ /* If there is no BY_WEEK_NO data, just jump forward 7 days. */
+ increment_monthday(impl,7*impl->rule.interval);
+ }
+
+
+ if(has_by_data && end_of_data && this_frequency ){
+ increment_year(impl,1);
+ }
+
+ return end_of_data;
+
+}
+
+
+pvl_list expand_by_day(struct icalrecur_iterator_impl* impl,short year)
+{
+ /* Try to calculate each of the occurrences. */
+ int i;
+ pvl_list days_list = pvl_newlist();
+
+ short start_dow, end_dow, end_year_day, start_doy;
+ struct icaltimetype tmp = impl->last;
+
+ tmp.year= year;
+ tmp.month = 1;
+ tmp.day = 1;
+ tmp.is_date = 1;
+
+ start_dow = icaltime_day_of_week(tmp);
+ start_doy = icaltime_start_doy_of_week(tmp);
+
+ /* Get the last day of the year*/
+ tmp.year++;
+ tmp = icaltime_normalize(tmp);
+ tmp.day--;
+ tmp = icaltime_normalize(tmp);
+
+ end_dow = icaltime_day_of_week(tmp);
+ end_year_day = icaltime_day_of_year(tmp);
+
+ for(i = 0; BYDAYPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
+ short dow =
+ icalrecurrencetype_day_day_of_week(BYDAYPTR[i]);
+ short pos = icalrecurrencetype_day_position(BYDAYPTR[i]);
+
+ if(pos == 0){
+ /* add all of the days of the year with this day-of-week*/
+ int week;
+ for(week = 0; week < 52 ; week ++){
+ short doy = start_doy + (week * 7) + dow-1;
+
+ if(doy > end_year_day){
+ break;
+ } else {
+ pvl_push(days_list, GINT_TO_POINTER((int)doy));
+ }
+ }
+
+ } else if ( pos > 0) {
+ int first;
+ /* First occurrence of dow in year */
+ if( dow >= start_dow) {
+ first = dow - start_dow + 1;
+ } else {
+ first = dow - start_dow + 8;
+ }
+
+ pvl_push(days_list,GINT_TO_POINTER(first+ (pos-1) * 7));
+
+ } else { /* pos < 0 */
+ assert(0);
+ }
+ }
+
+ return days_list;
+}
+
+
+/* For INTERVAL=YEARLY, set up the days[] array in the iterator to
+ list all of the days of the current year that are specified in this
+ rule. */
+
+int expand_year_days(struct icalrecur_iterator_impl* impl,short year)
+{
+ int j,k;
+ int days_index=0;
+ struct icaltimetype t;
+ int flags;
+
+#define HBD(x) has_by_data(impl,x)
+
+ t.is_date = 1; /* Needed to make day_of_year routines work property */
+
+ memset(&t,0,sizeof(t));
+ memset(impl->days,ICAL_RECURRENCE_ARRAY_MAX_BYTE,sizeof(impl->days));
+
+ flags = (HBD(BY_DAY) ? 1<<BY_DAY : 0) +
+ (HBD(BY_WEEK_NO) ? 1<<BY_WEEK_NO : 0) +
+ (HBD(BY_MONTH_DAY) ? 1<<BY_MONTH_DAY : 0) +
+ (HBD(BY_MONTH) ? 1<<BY_MONTH : 0) +
+ (HBD(BY_YEAR_DAY) ? 1<<BY_YEAR_DAY : 0);
+
+
+ switch(flags) {
+
+ case 0: {
+ /* FREQ=YEARLY; */
+
+ break;
+ }
+ case 1<<BY_MONTH: {
+ /* FREQ=YEARLY; BYMONTH=3,11*/
+
+ for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
+ struct icaltimetype t;
+ short month = impl->by_ptrs[BY_MONTH][j];
+ short doy;
+
+ t = impl->dtstart;
+ t.year = year;
+ t.month = month;
+ t.is_date = 1;
+
+ doy = icaltime_day_of_year(t);
+
+ impl->days[days_index++] = doy;
+
+ }
+ break;
+ }
+
+ case 1<<BY_MONTH_DAY: {
+ /* FREQ=YEARLY; BYMONTHDAY=1,15*/
+ assert(0);
+ break;
+ }
+
+ case (1<<BY_MONTH_DAY) + (1<<BY_MONTH): {
+ /* FREQ=YEARLY; BYMONTHDAY=1,15; BYMONTH=10 */
+
+ for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
+ for(k=0;impl->by_ptrs[BY_MONTH_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++)
+ {
+ short month = impl->by_ptrs[BY_MONTH][j];
+ short month_day = impl->by_ptrs[BY_MONTH_DAY][k];
+ short doy;
+
+ t.day = month_day;
+ t.month = month;
+ t.year = year;
+ t.is_date = 1;
+
+ doy = icaltime_day_of_year(t);
+
+ impl->days[days_index++] = doy;
+
+ }
+ }
+
+ break;
+ }
+
+ case 1<<BY_WEEK_NO: {
+ /* FREQ=YEARLY; BYWEEKNO=20,50 */
+
+ struct icaltimetype t;
+ short dow;
+
+ t.day = impl->dtstart.day;
+ t.month = impl->dtstart.month;
+ t.year = year;
+ t.is_date = 1;
+
+ dow = icaltime_day_of_week(t);
+ /* HACK Not finished */
+
+ break;
+ }
+
+ case (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): {
+ /*FREQ=YEARLY; WEEKNO=20,50; BYMONTH= 6,11 */
+ assert(0);
+ break;
+ }
+
+ case 1<<BY_DAY: {
+ /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR*/
+ int days_index = 0;
+ pvl_elem i;
+ pvl_list days = expand_by_day(impl,year);
+
+
+ for(i=pvl_head(days);i!=0;i=pvl_next(i)){
+ short day = (short)GPOINTER_TO_INT(pvl_data(i));
+ impl->days[days_index++] = day;
+ }
+
+ break;
+ }
+
+ case (1<<BY_DAY)+(1<<BY_MONTH): {
+ /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTH = 12*/
+
+
+ for(j=0;impl->by_ptrs[BY_MONTH][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
+ short month = impl->by_ptrs[BY_MONTH][j];
+ short days_in_month = icaltime_days_in_month(month,year);
+
+ struct icaltimetype t;
+ memset(&t,0,sizeof(struct icaltimetype));
+ t.day = 1;
+ t.year = year;
+ t.month = month;
+ t.is_date = 1;
+
+ for(t.day = 1; t.day <=days_in_month; t.day++){
+
+ short current_dow = icaltime_day_of_week(t);
+
+ for(k=0;impl->by_ptrs[BY_DAY][k]!=ICAL_RECURRENCE_ARRAY_MAX;k++){
+
+ enum icalrecurrencetype_weekday dow =
+ icalrecurrencetype_day_day_of_week(impl->by_ptrs[BY_DAY][k]);
+
+ if(current_dow == dow){
+ short doy = icaltime_day_of_year(t);
+ /* HACK, incomplete Nth day of week handling */
+ impl->days[days_index++] = doy;
+
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ case (1<<BY_DAY) + (1<<BY_MONTH_DAY) : {
+ /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=1,15*/
+ assert(0);
+ break;
+ }
+
+ case (1<<BY_DAY) + (1<<BY_MONTH_DAY) + (1<<BY_MONTH): {
+ /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; BYMONTHDAY=10; MYMONTH=6,11*/
+
+ int days_index = 0;
+ pvl_elem itr;
+ pvl_list days = expand_by_day(impl,year);
+
+ for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
+ short day = (short)GPOINTER_TO_INT(pvl_data(itr));
+ struct icaltimetype tt;
+ short i,j;
+
+ tt = icaltime_from_day_of_year(day,year);
+
+ for(i = 0; BYMONPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
+ for(j = 0; BYMDPTR[j]!=ICAL_RECURRENCE_ARRAY_MAX; j++){
+ short mday = BYMDPTR[j];
+ short month = BYMONPTR[i];
+
+ if(tt.month == month && tt.day == mday){
+ impl->days[days_index++] = day;
+ }
+ }
+ }
+
+ }
+
+ break;
+
+ }
+
+ case (1<<BY_DAY) + (1<<BY_WEEK_NO) : {
+ /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; WEEKNO=20,50*/
+
+ int days_index = 0;
+ pvl_elem itr;
+ pvl_list days = expand_by_day(impl,year);
+
+ for(itr=pvl_head(days);itr!=0;itr=pvl_next(itr)){
+ short day = (short)GPOINTER_TO_INT(pvl_data(itr));
+ struct icaltimetype tt;
+ short i;
+
+ tt = icaltime_from_day_of_year(day,year);
+
+ for(i = 0; BYWEEKPTR[i] != ICAL_RECURRENCE_ARRAY_MAX; i++){
+ short weekno = BYWEEKPTR[i];
+
+ if(weekno== icaltime_week_number(tt)){
+ impl->days[days_index++] = day;
+ }
+ }
+
+ }
+ break;
+ }
+
+ case (1<<BY_DAY) + (1<<BY_WEEK_NO) + (1<<BY_MONTH_DAY): {
+ /*FREQ=YEARLY; BYDAY=TH,20MO,-10FR; WEEKNO=20,50; BYMONTHDAY=1,15*/
+ assert(0);
+ break;
+ }
+
+ case 1<<BY_YEAR_DAY: {
+ for(j=0;impl->by_ptrs[BY_YEAR_DAY][j]!=ICAL_RECURRENCE_ARRAY_MAX;j++){
+ short doy = impl->by_ptrs[BY_YEAR_DAY][j];
+ impl->days[days_index++] = doy;
+ }
+ break;
+ }
+
+ default: {
+ assert(0);
+ break;
+ }
+
+ }
+
+ return 0;
+}
+
+
+int next_year(struct icalrecur_iterator_impl* impl)
+{
+ struct icaltimetype next;
+
+ if (next_hour(impl) == 0){
+ return 0;
+ }
+
+ if (impl->days[++impl->days_index] == ICAL_RECURRENCE_ARRAY_MAX){
+ impl->days_index = 0;
+ increment_year(impl,impl->rule.interval);
+ expand_year_days(impl,impl->last.year);
+ }
+
+ next = icaltime_from_day_of_year(impl->days[impl->days_index],impl->last.year);
+
+ impl->last.day = next.day;
+ impl->last.month = next.month;
+
+ return 1;
+}
+
+int icalrecur_check_rulepart(struct icalrecur_iterator_impl* impl,
+ short v, enum byrule byrule)
+{
+ int itr;
+
+ if(impl->by_ptrs[byrule][0]!=ICAL_RECURRENCE_ARRAY_MAX){
+ for(itr=0; impl->by_ptrs[byrule][itr]!=ICAL_RECURRENCE_ARRAY_MAX;itr++){
+ if(impl->by_ptrs[byrule][itr] == v){
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int check_contract_restriction(struct icalrecur_iterator_impl* impl,
+ enum byrule byrule, short v)
+{
+ int pass = 0;
+ int itr;
+ icalrecurrencetype_frequency freq = impl->rule.freq;
+
+ if(impl->by_ptrs[byrule][0]!=ICAL_RECURRENCE_ARRAY_MAX &&
+ expand_map[freq].map[byrule] == CONTRACT){
+ for(itr=0; impl->by_ptrs[byrule][itr]!=ICAL_RECURRENCE_ARRAY_MAX;itr++){
+ if(impl->by_ptrs[byrule][itr] == v){
+ pass=1;
+ break;
+ }
+ }
+
+ return pass;
+ } else {
+ /* This is not a contracting byrule, or it has no data, so the
+ test passes*/
+ return 1;
+ }
+}
+
+
+int check_contracting_rules(struct icalrecur_iterator_impl* impl)
+{
+
+ int day_of_week=0;
+ int week_no=0;
+ int year_day=0;
+
+ if (
+ check_contract_restriction(impl,BY_SECOND,impl->last.second) &&
+ check_contract_restriction(impl,BY_MINUTE,impl->last.minute) &&
+ check_contract_restriction(impl,BY_HOUR,impl->last.hour) &&
+ check_contract_restriction(impl,BY_DAY,day_of_week) &&
+ check_contract_restriction(impl,BY_WEEK_NO,week_no) &&
+ check_contract_restriction(impl,BY_MONTH_DAY,impl->last.day) &&
+ check_contract_restriction(impl,BY_MONTH,impl->last.month) &&
+ check_contract_restriction(impl,BY_YEAR_DAY,year_day) )
+ {
+
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *itr)
+{
+ int valid = 1;
+ struct icalrecur_iterator_impl* impl =
+ (struct icalrecur_iterator_impl*)itr;
+
+ if( (impl->rule.count!=0 &&impl->occurrence_no >= impl->rule.count) ||
+ (!icaltime_is_null_time(impl->rule.until) &&
+ icaltime_compare(impl->last,impl->rule.until) > 0)) {
+ return icaltime_null_time();
+ }
+
+ if(impl->occurrence_no == 0
+ && icaltime_compare(impl->last,impl->dtstart) >= 0){
+
+ impl->occurrence_no++;
+ return impl->last;
+ }
+
+ do {
+ valid = 1;
+ switch(impl->rule.freq){
+
+ case ICAL_SECONDLY_RECURRENCE: {
+ next_second(impl);
+ break;
+ }
+ case ICAL_MINUTELY_RECURRENCE: {
+ next_minute(impl);
+ break;
+ }
+ case ICAL_HOURLY_RECURRENCE: {
+ next_hour(impl);
+ break;
+ }
+ case ICAL_DAILY_RECURRENCE: {
+ next_day(impl);
+ break;
+ }
+ case ICAL_WEEKLY_RECURRENCE: {
+ next_week(impl);
+ break;
+ }
+ case ICAL_MONTHLY_RECURRENCE: {
+ valid = next_month(impl);
+ break;
+ }
+ case ICAL_YEARLY_RECURRENCE:{
+ next_year(impl);
+ break;
+ }
+ default:{
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return icaltime_null_time();
+ }
+ }
+
+ if(impl->last.year >= 2038 ){
+ /* HACK */
+ return icaltime_null_time();
+ }
+
+ } while(!check_contracting_rules(impl)
+ || icaltime_compare(impl->last,impl->dtstart) < 0
+ || valid == 0);
+
+
+/* Ignore null times and times that are after the until time */
+ if( !icaltime_is_null_time(impl->rule.until) &&
+ icaltime_compare(impl->last,impl->rule.until) > 0 ) {
+ return icaltime_null_time();
+ }
+
+ impl->occurrence_no++;
+
+ return impl->last;
+}
+
+
+/************************** Type Routines **********************/
+
+
+void icalrecurrencetype_clear(struct icalrecurrencetype *recur)
+{
+ memset(recur,ICAL_RECURRENCE_ARRAY_MAX_BYTE,
+ sizeof(struct icalrecurrencetype));
+
+ recur->week_start = ICAL_MONDAY_WEEKDAY;
+ recur->freq = ICAL_NO_RECURRENCE;
+ recur->interval = 1;
+ memset(&(recur->until),0,sizeof(struct icaltimetype));
+ recur->count = 0;
+}
+
+/* The 'day' element of icalrecurrencetype_weekday is encoded to allow
+reporesentation of both the day of the week ( Monday, Tueday), but
+also the Nth day of the week ( First tuesday of the month, last
+thursday of the year) These routines decode the day values.
+
+The day's position in the period ( Nth-ness) and the numerical value
+of the day are encoded together as: pos*7 + dow
+
+A position of 0 means 'any' or 'every'
+
+ */
+
+enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day)
+{
+ return abs(day)%8;
+}
+
+short icalrecurrencetype_day_position(short day)
+{
+ short wd, pos;
+
+ wd = icalrecurrencetype_day_day_of_week(day);
+
+ pos = (abs(day)-wd)/8 * ((day<0)?-1:1);
+
+
+ return pos;
+}
+
+
+/****************** Enumeration Routines ******************/
+
+struct {icalrecurrencetype_weekday wd; const char * str; }
+wd_map[] = {
+ {ICAL_SUNDAY_WEEKDAY,"SU"},
+ {ICAL_MONDAY_WEEKDAY,"MO"},
+ {ICAL_TUESDAY_WEEKDAY,"TU"},
+ {ICAL_WEDNESDAY_WEEKDAY,"WE"},
+ {ICAL_THURSDAY_WEEKDAY,"TH"},
+ {ICAL_FRIDAY_WEEKDAY,"FR"},
+ {ICAL_SATURDAY_WEEKDAY,"SA"},
+ {ICAL_NO_WEEKDAY,0}
+};
+
+const char* icalrecur_weekday_to_string(icalrecurrencetype_weekday kind)
+{
+ int i;
+
+ for (i=0; wd_map[i].wd != ICAL_NO_WEEKDAY; i++) {
+ if ( wd_map[i].wd == kind) {
+ return wd_map[i].str;
+ }
+ }
+
+ return 0;
+}
+
+icalrecurrencetype_weekday icalrecur_string_to_weekday(const char* str)
+{
+ int i;
+
+ for (i=0; wd_map[i].wd != ICAL_NO_WEEKDAY; i++) {
+ if ( strcmp(str,wd_map[i].str) == 0){
+ return wd_map[i].wd;
+ }
+ }
+
+ return ICAL_NO_WEEKDAY;
+}
+
+
+
+struct {
+ icalrecurrencetype_frequency kind;
+ const char* str;
+} freq_map[] = {
+ {ICAL_SECONDLY_RECURRENCE,"SECONDLY"},
+ {ICAL_MINUTELY_RECURRENCE,"MINUTELY"},
+ {ICAL_HOURLY_RECURRENCE,"HOURLY"},
+ {ICAL_DAILY_RECURRENCE,"DAILY"},
+ {ICAL_WEEKLY_RECURRENCE,"WEEKLY"},
+ {ICAL_MONTHLY_RECURRENCE,"MONTHLY"},
+ {ICAL_YEARLY_RECURRENCE,"YEARLY"},
+ {ICAL_NO_RECURRENCE,0}
+};
+
+const char* icalrecur_freq_to_string(icalrecurrencetype_frequency kind)
+{
+ int i;
+
+ for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) {
+ if ( freq_map[i].kind == kind ) {
+ return freq_map[i].str;
+ }
+ }
+ return 0;
+}
+
+icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str)
+{
+ int i;
+
+ for (i=0; freq_map[i].kind != ICAL_NO_RECURRENCE ; i++) {
+ if ( strcmp(str,freq_map[i].str) == 0){
+ return freq_map[i].kind;
+ }
+ }
+ return ICAL_NO_RECURRENCE;
+}
+
+/* Fill an array with the 'count' number of occurrences generated by
+ the rrule. Note that the times are returned in UTC, but the times
+ are calculated in local time. YOu will have to convert the results
+ back into local time before using them. */
+
+int icalrecur_expand_recurrence(char* rule, time_t start,
+ int count, time_t* array)
+{
+ struct icalrecurrencetype recur;
+ icalrecur_iterator* ritr;
+ time_t tt;
+ struct icaltimetype icstart, next;
+ int i = 0;
+
+ memset(array, 0, count*sizeof(time_t));
+
+ icstart = icaltime_from_timet(start,0);
+
+ recur = icalrecurrencetype_from_string(rule);
+
+ for(ritr = icalrecur_iterator_new(recur,icstart),
+ next = icalrecur_iterator_next(ritr);
+ !icaltime_is_null_time(next) && i < count;
+ next = icalrecur_iterator_next(ritr)){
+
+ tt = icaltime_as_timet(next);
+
+ if (tt >= start ){
+ array[i++] = tt;
+ }
+
+ }
+
+ icalrecur_iterator_free(ritr);
+
+ return 1;
+}
diff --git a/src/plugins/vcalendar/libical/libical/icalrecur.h b/src/plugins/vcalendar/libical/libical/icalrecur.h
@@ -0,0 +1,189 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalrecur.h
+ CREATOR: eric 20 March 2000
+
+
+ (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/
+
+How to use:
+
+1) Get a rule and a start time from a component
+ icalproperty rrule;
+ struct icalrecurrencetype recur;
+ struct icaltimetype dtstart;
+
+ rrule = icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY);
+ recur = icalproperty_get_rrule(rrule);
+ start = icalproperty_get_dtstart(dtstart);
+
+Or, just make them up:
+ recur = icalrecurrencetype_from_string("FREQ=YEARLY;BYDAY=SU,WE");
+ dtstart = icaltime_from_string("19970101T123000")
+
+2) Create an iterator
+ icalrecur_iterator* ritr;
+ ritr = icalrecur_iterator_new(recur,start);
+
+3) Iterator over the occurrences
+ struct icaltimetype next;
+ while (next = icalrecur_iterator_next(ritr)
+ && !icaltime_is_null_time(next){
+ Do something with next
+ }
+
+Note that that the time returned by icalrecur_iterator_next is in
+whatever timezone that dtstart is in.
+
+======================================================================*/
+
+#ifndef ICALRECUR_H
+#define ICALRECUR_H
+
+#include <time.h>
+#include "icaltime.h"
+
+/***********************************************************************
+ * Recurrance enumerations
+**********************************************************************/
+
+typedef enum icalrecurrencetype_frequency
+{
+ /* These enums are used to index an array, so don't change the
+ order or the integers */
+
+ ICAL_SECONDLY_RECURRENCE=0,
+ ICAL_MINUTELY_RECURRENCE=1,
+ ICAL_HOURLY_RECURRENCE=2,
+ ICAL_DAILY_RECURRENCE=3,
+ ICAL_WEEKLY_RECURRENCE=4,
+ ICAL_MONTHLY_RECURRENCE=5,
+ ICAL_YEARLY_RECURRENCE=6,
+ ICAL_NO_RECURRENCE=7
+
+} icalrecurrencetype_frequency;
+
+typedef enum icalrecurrencetype_weekday
+{
+ ICAL_NO_WEEKDAY,
+ ICAL_SUNDAY_WEEKDAY,
+ ICAL_MONDAY_WEEKDAY,
+ ICAL_TUESDAY_WEEKDAY,
+ ICAL_WEDNESDAY_WEEKDAY,
+ ICAL_THURSDAY_WEEKDAY,
+ ICAL_FRIDAY_WEEKDAY,
+ ICAL_SATURDAY_WEEKDAY
+} icalrecurrencetype_weekday;
+
+enum {
+ ICAL_RECURRENCE_ARRAY_MAX = 0x7f7f,
+ ICAL_RECURRENCE_ARRAY_MAX_BYTE = 0x7f
+};
+
+
+
+/********************** Recurrence type routines **************/
+
+/* See RFC 2445 Section 4.3.10, RECUR Value, for an explaination of
+ the values and fields in struct icalrecurrencetype */
+
+#define ICAL_BY_SECOND_SIZE 61
+#define ICAL_BY_MINUTE_SIZE 61
+#define ICAL_BY_HOUR_SIZE 25
+#define ICAL_BY_DAY_SIZE 364 /* 7 days * 52 weeks */
+#define ICAL_BY_MONTHDAY_SIZE 32
+#define ICAL_BY_YEARDAY_SIZE 367
+#define ICAL_BY_WEEKNO_SIZE 54
+#define ICAL_BY_MONTH_SIZE 13
+#define ICAL_BY_SETPOS_SIZE 367
+
+/* Main struct for holding digested recurrence rules */
+struct icalrecurrencetype
+{
+ icalrecurrencetype_frequency freq;
+
+
+ /* until and count are mutually exclusive. */
+ struct icaltimetype until;
+ int count;
+
+ short interval;
+
+ icalrecurrencetype_weekday week_start;
+
+ /* The BY* parameters can each take a list of values. Here I
+ * assume that the list of values will not be larger than the
+ * range of the value -- that is, the client will not name a
+ * value more than once.
+
+ * Each of the lists is terminated with the value
+ * ICAL_RECURRENCE_ARRAY_MAX unless the the list is full.
+ */
+
+ short by_second[ICAL_BY_SECOND_SIZE];
+ short by_minute[ICAL_BY_MINUTE_SIZE];
+ short by_hour[ICAL_BY_HOUR_SIZE];
+ short by_day[ICAL_BY_DAY_SIZE]; /* Encoded value, see below */
+ short by_month_day[ICAL_BY_MONTHDAY_SIZE];
+ short by_year_day[ ICAL_BY_YEARDAY_SIZE];
+ short by_week_no[ICAL_BY_WEEKNO_SIZE];
+ short by_month[ICAL_BY_MONTH_SIZE];
+ short by_set_pos[ICAL_BY_SETPOS_SIZE];
+};
+
+
+void icalrecurrencetype_clear(struct icalrecurrencetype *r);
+
+/* The 'day' element of the by_day array is encoded to allow
+representation of both the day of the week ( Monday, Tueday), but also
+the Nth day of the week ( First tuesday of the month, last thursday of
+the year) These routines decode the day values */
+
+/* 1 == Monday, etc. */
+enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week(short day);
+
+/* 0 == any of day of week. 1 == first, 2 = second, -2 == second to last, etc */
+short icalrecurrencetype_day_position(short day);
+
+
+/***********************************************************************
+ * Recurrance rule parser
+**********************************************************************/
+
+/* Convert between strings ans recurrencetype structures. */
+struct icalrecurrencetype icalrecurrencetype_from_string(const char* str);
+char* icalrecurrencetype_as_string(struct icalrecurrencetype *recur);
+
+
+/********** recurrence iteration routines ********************/
+
+typedef void icalrecur_iterator;
+
+/* Create a new recurrence rule iterator */
+icalrecur_iterator* icalrecur_iterator_new(struct icalrecurrencetype rule,
+ struct icaltimetype dtstart);
+
+/* Get the next occurrence from an iterator */
+struct icaltimetype icalrecur_iterator_next(icalrecur_iterator*);
+
+/* Free the iterator */
+void icalrecur_iterator_free(icalrecur_iterator*);
+
+/* Fills array up with at most 'count' time_t values, each
+ representing an occurrence time in seconds past the POSIX epoch */
+int icalrecur_expand_recurrence(char* rule, time_t start,
+ int count, time_t* array);
+
+
+#endif
diff --git a/src/plugins/vcalendar/libical/libical/icalrestriction.c.in b/src/plugins/vcalendar/libical/libical/icalrestriction.c.in
@@ -0,0 +1,447 @@
+/* -*- Mode: C -*- */
+/* ======================================================================
+ File: icalrestriction.c
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+ ======================================================================*/
+/*#line 7 "icalrestriction.c.in"*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalrestriction.h"
+#include "icalenums.h"
+#include "icalerror.h"
+
+#include <assert.h>
+#include <stdio.h> /* For snprintf */
+
+#define TMP_BUF_SIZE 1024
+
+
+/* Define the structs for the restrictions. these data are filled out
+in machine generated code below */
+
+struct icalrestriction_property_record;
+
+typedef char* (*restriction_func)(struct icalrestriction_property_record* rec,icalcomponent* comp,icalproperty* prop);
+
+
+typedef struct icalrestriction_property_record {
+ icalproperty_method method;
+ icalcomponent_kind component;
+ icalproperty_kind property;
+ icalrestriction_kind restriction;
+ restriction_func function;
+} icalrestriction_property_record;
+
+
+typedef struct icalrestriction_component_record {
+ icalproperty_method method;
+ icalcomponent_kind component;
+ icalcomponent_kind subcomponent;
+ icalrestriction_kind restriction;
+ restriction_func function;
+} icalrestriction_component_record;
+
+icalrestriction_property_record*
+icalrestriction_get_property_restriction(icalproperty_method method,
+ icalcomponent_kind component,
+ icalproperty_kind property);
+icalrestriction_component_record*
+icalrestriction_get_component_restriction(icalproperty_method method,
+ icalcomponent_kind component,
+ icalcomponent_kind subcomponent);
+
+icalrestriction_component_record icalrestriction_component_records[];
+icalrestriction_property_record icalrestriction_property_records[];
+
+icalrestriction_property_record null_prop_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_RESTRICTION_UNKNOWN,0};
+icalrestriction_component_record null_comp_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_COMPONENT,ICAL_RESTRICTION_UNKNOWN,0};
+
+
+/* The each row gives the result of comparing a restriction against a
+ count. The columns in each row represent 0,1,2+. '-1' indicates
+ 'invalid, 'don't care' or 'needs more analysis' So, for
+ ICAL_RESTRICTION_ONE, if there is 1 of a property with that
+ restriction, it passes, but if there are 0 or 2+, it fails. */
+
+char compare_map[ICAL_RESTRICTION_UNKNOWN+1][3] = {
+ { 1, 1, 1},/*ICAL_RESTRICTION_NONE*/
+ { 1, 0, 0},/*ICAL_RESTRICTION_ZERO*/
+ { 0, 1, 0},/*ICAL_RESTRICTION_ONE*/
+ { 1, 1, 1},/*ICAL_RESTRICTION_ZEROPLUS*/
+ { 0, 1, 1},/*ICAL_RESTRICTION_ONEPLUS*/
+ { 1, 1, 0},/*ICAL_RESTRICTION_ZEROORONE*/
+ { 1, 1, 0},/*ICAL_RESTRICTION_ONEEXCLUSIVE*/
+ { 1, 1, 0},/*ICAL_RESTRICTION_ONEMUTUAL*/
+ { 1, 1, 1} /*ICAL_RESTRICTION_UNKNOWN*/
+};
+
+char restr_string_map[ICAL_RESTRICTION_UNKNOWN+1][60] = {
+ "unknown number",/*ICAL_RESTRICTION_NONE*/
+ "0",/*ICAL_RESTRICTION_ZERO*/
+ "1",/*ICAL_RESTRICTION_ONE*/
+ "zero or more",/*ICAL_RESTRICTION_ZEROPLUS*/
+ "one or more" ,/*ICAL_RESTRICTION_ONEPLUS*/
+ "zero or one",/*ICAL_RESTRICTION_ZEROORONE*/
+ "zero or one, exclusive with another property",/*ICAL_RESTRICTION_ONEEXCLUSIVE*/
+ "zero or one, mutual with another property",/*ICAL_RESTRICTION_ONEMUTUAL*/
+ "unknown number" /*ICAL_RESTRICTION_UNKNOWN*/
+};
+
+
+int
+icalrestriction_compare(icalrestriction_kind restr, int count){
+
+ if ( restr < ICAL_RESTRICTION_NONE || restr > ICAL_RESTRICTION_UNKNOWN
+ || count < 0){
+ return -1;
+ }
+
+ if (count > 2) {
+ count = 2;
+ }
+
+ return compare_map[restr][count];
+
+}
+
+/* Special case routines */
+
+char* icalrestriction_may_be_draft_final_canceled(
+ icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop)
+{
+
+ icalproperty_status stat = icalproperty_get_status(prop);
+
+ if( !( stat == ICAL_STATUS_DRAFT ||
+ stat == ICAL_STATUS_FINAL ||
+ stat == ICAL_STATUS_CANCELLED )){
+
+ return "Failed iTIP restrictions for STATUS property. Value must be one of DRAFT, FINAL, or CANCELED";
+
+ }
+
+ return 0;
+}
+
+char* icalrestriction_may_be_comp_need_process(
+ icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop)
+{
+ icalproperty_status stat = icalproperty_get_status(prop);
+
+ if( !( stat == ICAL_STATUS_COMPLETED ||
+ stat == ICAL_STATUS_NEEDSACTION ||
+ stat == ICAL_STATUS_INPROCESS )){
+
+ return "Failed iTIP restrictions for STATUS property. Value must be one of COMPLETED, NEEDS-ACTION or IN-PROCESS";
+
+ }
+
+ return 0;
+}
+char* icalrestriction_may_be_tent_conf(icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop){
+ icalproperty_status stat = icalproperty_get_status(prop);
+
+ if( !( stat == ICAL_STATUS_TENTATIVE ||
+ stat == ICAL_STATUS_CONFIRMED )){
+
+ return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE or CONFIRMED";
+
+ }
+
+ return 0;
+}
+char* icalrestriction_may_be_tent_conf_cancel(
+ icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop)
+{
+ icalproperty_status stat = icalproperty_get_status(prop);
+
+ if( !( stat == ICAL_STATUS_TENTATIVE ||
+ stat == ICAL_STATUS_CONFIRMED ||
+ stat == ICAL_STATUS_CANCELLED )){
+
+ return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE, CONFIRMED or CANCELED";
+
+ }
+
+ return 0;
+}
+
+char* icalrestriction_must_be_cancel_if_present(
+ icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop)
+{
+ /* This routine will not be called if prop == 0 */
+ icalproperty_status stat = icalproperty_get_status(prop);
+
+ if( stat != ICAL_STATUS_CANCELLED)
+ {
+ return "Failed iTIP restrictions for STATUS property. Value must be CANCELLED";
+
+ }
+
+
+ return 0;
+}
+
+char* icalrestriction_must_be_canceled_no_attendee(
+ icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop)
+{
+
+ /* Hack. see rfc2446, 3.2.5 CANCEL for porperty STATUS. I don't
+ understand the note */
+
+ return 0;
+}
+char* icalrestriction_must_be_recurring(icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop){
+ /* Hack */
+ return 0;
+}
+char* icalrestriction_must_have_duration(icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop){
+
+ if( !icalcomponent_get_first_property(comp,ICAL_DURATION_PROPERTY)){
+
+ return "Failed iTIP restrictions for STATUS property. This component must have a DURATION property";
+
+ }
+
+ return 0;
+}
+char* icalrestriction_must_have_repeat(icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop){
+ if( !icalcomponent_get_first_property(comp,ICAL_REPEAT_PROPERTY)){
+
+ return "Failed iTIP restrictions for STATUS property. This component must have a REPEAT property";
+
+ }
+
+ return 0;
+}
+char* icalrestriction_must_if_tz_ref(icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop){
+
+ /* Hack */
+ return 0;
+}
+char* icalrestriction_no_dtend(icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop){
+
+ if( !icalcomponent_get_first_property(comp,ICAL_DTEND_PROPERTY)){
+
+ return "Failed iTIP restrictions for STATUS property. The component must not have both DURATION and DTEND";
+
+ }
+
+ return 0;
+}
+char* icalrestriction_no_duration(icalrestriction_property_record *rec,
+ icalcomponent* comp,
+ icalproperty* prop){
+
+ /* _no_dtend takes care of this one */
+ return 0;
+}
+
+
+int icalrestriction_check_component(icalproperty_method method,
+ icalcomponent* comp)
+{
+ icalproperty_kind kind;
+ icalcomponent_kind comp_kind;
+ icalrestriction_kind restr;
+ icalrestriction_property_record *prop_record;
+ icalrestriction_component_record *comp_record;
+ char* funcr = 0;
+ icalproperty *prop;
+
+ int count;
+ int compare;
+ int valid = 1;
+
+ comp_kind = icalcomponent_isa(comp);
+
+ /* Check all of the properties in this component */
+
+ for(kind = ICAL_ANY_PROPERTY+1; kind != ICAL_NO_PROPERTY; kind++){
+ count = icalcomponent_count_properties(comp, kind);
+
+ prop_record = icalrestriction_get_property_restriction(method,
+ comp_kind,
+ kind);
+
+ restr = prop_record->restriction;
+
+ if(restr == ICAL_RESTRICTION_ONEEXCLUSIVE ||
+ restr == ICAL_RESTRICTION_ONEMUTUAL) {
+
+ /* First treat is as a 0/1 restriction */
+ restr = ICAL_RESTRICTION_ZEROORONE;
+ compare = icalrestriction_compare(restr,count);
+
+ } else {
+
+ compare = icalrestriction_compare(restr,count);
+ }
+
+ assert(compare != -1);
+
+ if (compare == 0){
+ char temp[TMP_BUF_SIZE];
+
+ snprintf(temp, TMP_BUF_SIZE,"Failed iTIP restrictions for %s property. Expected %s instances of the property and got %d",
+ icalenum_property_kind_to_string(kind),
+ restr_string_map[restr], count);
+
+ icalcomponent_add_property
+ (comp,
+ icalproperty_vanew_xlicerror(
+ temp,
+ icalparameter_new_xlicerrortype(ICAL_XLICERRORTYPE_INVALIDITIP),
+ 0));
+ }
+
+
+ prop = icalcomponent_get_first_property(comp, kind);
+
+ if (prop != 0 && prop_record->function !=0 ){
+ funcr = prop_record->function(prop_record,comp,prop);
+ }
+
+ if(funcr !=0){
+ icalcomponent_add_property
+ (comp,
+ icalproperty_vanew_xlicerror(
+ funcr,
+ icalparameter_new_xlicerrortype(
+ ICAL_XLICERRORTYPE_INVALIDITIP),
+ 0));
+
+ compare = 0;
+ }
+
+ valid = valid && compare;
+ }
+
+
+
+ return valid;
+
+
+}
+
+int icalrestriction_check(icalcomponent* outer_comp)
+{
+ icalcomponent_kind comp_kind;
+ icalproperty_method method;
+ icalcomponent* inner_comp;
+ icalproperty *method_prop;
+ int valid;
+
+ icalerror_check_arg_rz( (outer_comp!=0), "outer comp");
+
+
+ /* Get the Method value from the outer component */
+
+ comp_kind = icalcomponent_isa(outer_comp);
+
+ if (comp_kind != ICAL_VCALENDAR_COMPONENT){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return 0;
+ }
+
+ method_prop = icalcomponent_get_first_property(outer_comp,
+ ICAL_METHOD_PROPERTY);
+
+ if (method_prop == 0){
+ method = ICAL_METHOD_NONE;
+ } else {
+ method = icalproperty_get_method(method_prop);
+ }
+
+
+ /* Check the VCALENDAR wrapper */
+ valid = icalrestriction_check_component(ICAL_METHOD_NONE,outer_comp);
+
+
+ /* Now check the inner components */
+
+ for(inner_comp= icalcomponent_get_first_component(outer_comp,
+ ICAL_ANY_COMPONENT);
+ inner_comp != 0;
+ inner_comp= icalcomponent_get_next_component(outer_comp,
+ ICAL_ANY_COMPONENT)){
+
+ valid = valid && icalrestriction_check_component(method,inner_comp);
+
+ }
+
+
+ return valid;
+
+}
+
+icalrestriction_property_record*
+icalrestriction_get_property_restriction(icalproperty_method method,
+ icalcomponent_kind component,
+ icalproperty_kind property)
+{
+ int i;
+
+ for(i = 0;
+ icalrestriction_property_records[i].restriction != ICAL_RESTRICTION_NONE;
+ i++){
+
+ if (method == icalrestriction_property_records[i].method &&
+ component == icalrestriction_property_records[i].component &&
+ property == icalrestriction_property_records[i].property ){
+ return &icalrestriction_property_records[i];
+ }
+ }
+
+ return &null_prop_record;
+}
+
+
+icalrestriction_component_record*
+icalrestriction_get_component_restriction(icalproperty_method method,
+ icalcomponent_kind component,
+ icalcomponent_kind subcomponent)
+{
+
+ int i;
+
+ for(i = 0;
+ icalrestriction_component_records[i].restriction != ICAL_RESTRICTION_NONE;
+ i++){
+
+ if (method == icalrestriction_component_records[i].method &&
+ component == icalrestriction_component_records[i].component &&
+ subcomponent == icalrestriction_component_records[i].subcomponent ){
+ return &icalrestriction_component_records[i];
+ }
+ }
+
+ return &null_comp_record;
+}
+
diff --git a/src/plugins/vcalendar/libical/libical/icalrestriction.h b/src/plugins/vcalendar/libical/libical/icalrestriction.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalrestriction.h
+ CREATOR: eric 24 April 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalrestriction.h
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+
+======================================================================*/
+
+#include "icalproperty.h"
+#include "icalcomponent.h"
+
+#ifndef ICALRESTRICTION_H
+#define ICALRESTRICTION_H
+
+/* These must stay in this order for icalrestriction_compare to work */
+typedef enum icalrestriction_kind {
+ ICAL_RESTRICTION_NONE=0, /* 0 */
+ ICAL_RESTRICTION_ZERO, /* 1 */
+ ICAL_RESTRICTION_ONE, /* 2 */
+ ICAL_RESTRICTION_ZEROPLUS, /* 3 */
+ ICAL_RESTRICTION_ONEPLUS, /* 4 */
+ ICAL_RESTRICTION_ZEROORONE, /* 5 */
+ ICAL_RESTRICTION_ONEEXCLUSIVE, /* 6 */
+ ICAL_RESTRICTION_ONEMUTUAL, /* 7 */
+ ICAL_RESTRICTION_UNKNOWN /* 8 */
+} icalrestriction_kind;
+
+int
+icalrestriction_compare(icalrestriction_kind restr, int count);
+
+
+int
+icalrestriction_is_parameter_allowed(icalproperty_kind property,
+ icalparameter_kind parameter);
+
+int icalrestriction_check(icalcomponent* comp);
+
+
+#endif /* !ICALRESTRICTION_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icaltime.c b/src/plugins/vcalendar/libical/libical/icaltime.c
@@ -0,0 +1,600 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icaltime.c
+ CREATOR: eric 02 June 2000
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+ ======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if USE_PTHREAD
+#include <pthread.h>
+#endif
+#include <glib.h>
+
+#include "icaltime.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef ICAL_NO_LIBICAL
+#define icalerror_set_errno(x)
+#define icalerror_check_arg_rv(x,y)
+#define icalerror_check_arg_re(x,y,z)
+#else
+#include "icalerror.h"
+#include "icalmemory.h"
+#endif
+
+
+
+
+struct icaltimetype
+icaltime_from_timet(time_t tm, int is_date)
+{
+ struct icaltimetype tt = icaltime_null_time();
+ struct tm t, buft;
+
+ t = *(gmtime_r(&tm, &buft));
+
+ if(is_date == 0){
+ tt.second = t.tm_sec;
+ tt.minute = t.tm_min;
+ tt.hour = t.tm_hour;
+ } else {
+ tt.second = tt.minute =tt.hour = 0 ;
+ }
+
+ tt.day = t.tm_mday;
+ tt.month = t.tm_mon + 1;
+ tt.year = t.tm_year+ 1900;
+
+ tt.is_utc = 1;
+ tt.is_date = is_date;
+
+ return tt;
+}
+
+/* Structure used by set_tz to hold an old value of TZ, and the new
+ value, which is in memory we will have to free in unset_tz */
+struct set_tz_save {char* orig_tzid; char* new_env_str;};
+
+/* Temporarily change the TZ environmental variable. */
+struct set_tz_save set_tz(const char* tzid)
+{
+
+ char *orig_tzid = 0;
+ char *new_env_str;
+ struct set_tz_save savetz;
+ size_t tmp_sz;
+
+ savetz.orig_tzid = 0;
+ savetz.new_env_str = 0;
+
+ if(getenv("TZ") != 0){
+ orig_tzid = (char*)icalmemory_strdup(getenv("TZ"));
+
+ if(orig_tzid == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return savetz;
+ }
+ }
+
+ tmp_sz =strlen(tzid)+4;
+ new_env_str = (char*)malloc(tmp_sz);
+
+ if(new_env_str == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return savetz;
+ }
+
+ /* Copy the TZid into a string with the form that putenv expects. */
+ strcpy(new_env_str,"TZ=");
+ strcpy(new_env_str+3,tzid);
+
+ putenv(new_env_str);
+
+ /* Old value of TZ and the string we will have to free later */
+ savetz.orig_tzid = orig_tzid;
+ savetz.new_env_str = new_env_str;
+
+ tzset();
+
+ return savetz;
+}
+
+void unset_tz(struct set_tz_save savetz)
+{
+ /* restore the original TZ environment */
+
+ char* orig_tzid = savetz.orig_tzid;
+
+ if(orig_tzid!=0){
+ size_t tmp_sz =strlen(orig_tzid)+4;
+ char* orig_env_str = (char*)malloc(tmp_sz);
+
+ if(orig_env_str == 0){
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return;
+ }
+
+ strcpy(orig_env_str,"TZ=");
+ strcpy(orig_env_str+3,orig_tzid);
+
+ putenv(orig_env_str);
+
+ free(orig_tzid);
+ } else {
+ g_unsetenv("TZ"); /* Delete from environment */
+ }
+
+ if(savetz.new_env_str != 0){
+ free(savetz.new_env_str);
+ }
+ tzset();
+}
+
+
+time_t icaltime_as_timet(struct icaltimetype tt)
+{
+ struct tm stm;
+ time_t t;
+
+ memset(&stm,0,sizeof( struct tm));
+
+ if(icaltime_is_null_time(tt)) {
+ return 0;
+ }
+
+ stm.tm_sec = tt.second;
+ stm.tm_min = tt.minute;
+ stm.tm_hour = tt.hour;
+ stm.tm_mday = tt.day;
+ stm.tm_mon = tt.month-1;
+ stm.tm_year = tt.year-1900;
+ stm.tm_isdst = -1;
+
+ if(tt.is_utc == 1 || tt.is_date == 1){
+ struct set_tz_save old_tz = set_tz("UTC");
+ t = mktime(&stm);
+ unset_tz(old_tz);
+ } else {
+ t = mktime(&stm);
+ }
+
+ return t;
+
+}
+
+char* icaltime_as_ical_string(struct icaltimetype tt)
+{
+ size_t size = 17;
+ char* buf = icalmemory_new_buffer(size);
+
+ if(tt.is_date){
+ snprintf(buf, size,"%04d%02d%02d",tt.year,tt.month,tt.day);
+ } else {
+ char* fmt;
+ if(tt.is_utc){
+ fmt = "%04d%02d%02dT%02d%02d%02dZ";
+ } else {
+ fmt = "%04d%02d%02dT%02d%02d%02d";
+ }
+ snprintf(buf, size,fmt,tt.year,tt.month,tt.day,
+ tt.hour,tt.minute,tt.second);
+ }
+
+ icalmemory_add_tmp_buffer(buf);
+
+ return buf;
+
+}
+
+
+/* convert tt, of timezone tzid, into a utc time */
+struct icaltimetype icaltime_as_utc(struct icaltimetype tt,const char* tzid)
+{
+ int tzid_offset;
+
+ if(tt.is_utc == 1 || tt.is_date == 1){
+ return tt;
+ }
+
+ tzid_offset = icaltime_utc_offset(tt,tzid);
+
+ tt.second -= tzid_offset;
+
+ tt.is_utc = 1;
+
+ return icaltime_normalize(tt);
+}
+
+/* convert tt, a time in UTC, into a time in timezone tzid */
+struct icaltimetype icaltime_as_zone(struct icaltimetype tt,const char* tzid)
+{
+ int tzid_offset;
+
+ tzid_offset = icaltime_utc_offset(tt,tzid);
+
+ tt.second += tzid_offset;
+
+ tt.is_utc = 0;
+
+ return icaltime_normalize(tt);
+
+}
+
+
+/* Return the offset of the named zone as seconds. tt is a time
+ indicating the date for which you want the offset */
+int icaltime_utc_offset(struct icaltimetype ictt, const char* tzid)
+{
+
+ time_t tt = icaltime_as_timet(ictt);
+ time_t offset_tt;
+ struct tm gtm, buft1, buft2;
+ struct set_tz_save old_tz;
+
+ if(tzid != 0){
+ old_tz = set_tz(tzid);
+ }
+
+ /* Mis-interpret a UTC broken out time as local time */
+ gtm = *(gmtime_r(&tt, &buft1));
+ gtm.tm_isdst = localtime_r(&tt, &buft2)->tm_isdst;
+ offset_tt = mktime(>m);
+
+ if(tzid != 0){
+ unset_tz(old_tz);
+ }
+
+ return tt-offset_tt;
+}
+
+
+
+/* Normalize by converting from localtime to utc and back to local
+ time. This uses localtime because localtime and mktime are inverses
+ of each other */
+
+struct icaltimetype icaltime_normalize(struct icaltimetype tt)
+{
+ struct tm stm, buft;
+ time_t tut;
+
+ memset(&stm,0,sizeof( struct tm));
+
+ stm.tm_sec = tt.second;
+ stm.tm_min = tt.minute;
+ stm.tm_hour = tt.hour;
+ stm.tm_mday = tt.day;
+ stm.tm_mon = tt.month-1;
+ stm.tm_year = tt.year-1900;
+ stm.tm_isdst = -1; /* prevents mktime from changing hour based on
+ daylight savings */
+
+ tut = mktime(&stm);
+
+ stm = *(localtime_r(&tut, &buft));
+
+ tt.second = stm.tm_sec;
+ tt.minute = stm.tm_min;
+ tt.hour = stm.tm_hour;
+ tt.day = stm.tm_mday;
+ tt.month = stm.tm_mon +1;
+ tt.year = stm.tm_year+1900;
+
+ return tt;
+}
+
+
+#ifndef ICAL_NO_LIBICAL
+#include "icalvalue.h"
+
+struct icaltimetype icaltime_from_string(const char* str)
+{
+ struct icaltimetype tt = icaltime_null_time();
+ int size;
+
+ icalerror_check_arg_re(str!=0,"str",icaltime_null_time());
+
+ size = strlen(str);
+
+ if(size == 15) { /* floating time */
+ tt.is_utc = 0;
+ tt.is_date = 0;
+ } else if (size == 16) { /* UTC time, ends in 'Z'*/
+ tt.is_utc = 1;
+ tt.is_date = 0;
+
+ if(str[15] != 'Z'){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return icaltime_null_time();
+ }
+
+ } else if (size == 8) { /* A DATE */
+ tt.is_utc = 1;
+ tt.is_date = 1;
+ } else if (size == 20) { /* A shitty date by Outlook */
+ char tsep, offset_way;
+ int off_h, off_m;
+ sscanf(str,"%04d%02d%02d%c%02d%02d%02d%c%02d%02d",&tt.year,&tt.month,&tt.day,
+ &tsep,&tt.hour,&tt.minute,&tt.second, &offset_way, &off_h, &off_m);
+
+ if(tsep != 'T'){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return icaltime_null_time();
+ }
+ if (offset_way != '-' && offset_way != '+'){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return icaltime_null_time();
+ }
+
+ /* substract offset to get utc */
+ if (offset_way == '-')
+ tt.second += 3600*off_h;
+ else
+ tt.second -= 3600*off_h;
+ tt.is_utc = 1;
+ tt.is_date = 0;
+ return icaltime_normalize(tt);
+ } else { /* error */
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return icaltime_null_time();
+ }
+
+ if(tt.is_date == 1){
+ sscanf(str,"%04d%02d%02d",&tt.year,&tt.month,&tt.day);
+ } else {
+ char tsep;
+ sscanf(str,"%04d%02d%02d%c%02d%02d%02d",&tt.year,&tt.month,&tt.day,
+ &tsep,&tt.hour,&tt.minute,&tt.second);
+
+ if(tsep != 'T'){
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return icaltime_null_time();
+ }
+
+ }
+
+ return tt;
+}
+#endif
+
+char ctime_str[20];
+char* icaltime_as_ctime(struct icaltimetype t)
+{
+ time_t tt;
+ char buft[512];
+ tt = icaltime_as_timet(t);
+ sprintf(ctime_str,"%s",ctime_r(&tt, buft));
+
+ ctime_str[strlen(ctime_str)-1] = 0;
+
+ return ctime_str;
+}
+
+
+short days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
+
+short icaltime_days_in_month(short month,short year)
+{
+
+ int is_leap =0;
+ int days = days_in_month[month];
+
+ assert(month > 0);
+ assert(month <= 12);
+
+ if( (year % 4 == 0 && year % 100 != 0) ||
+ year % 400 == 0){
+ is_leap =1;
+ }
+
+ if( month == 2){
+ days += is_leap;
+ }
+
+ return days;
+}
+
+/* 1-> Sunday, 7->Saturday */
+short icaltime_day_of_week(struct icaltimetype t){
+
+ time_t tt = icaltime_as_timet(t);
+ struct tm *tm, buft;
+
+ if(t.is_utc == 1){
+ tm = gmtime_r(&tt, &buft);
+ } else {
+ tm = localtime_r(&tt, &buft);
+ }
+
+ return tm->tm_wday+1;
+}
+
+/* Day of the year that the first day of the week (Sunday) is on */
+short icaltime_start_doy_of_week(struct icaltimetype t){
+ time_t tt = icaltime_as_timet(t);
+ time_t start_tt;
+ struct tm *stm, buft1, buft2;
+ int syear;
+
+ stm = gmtime_r(&tt, &buft1);
+ syear = stm->tm_year;
+
+ start_tt = tt - stm->tm_wday*(60*60*24);
+
+ stm = gmtime_r(&start_tt, &buft2);
+
+ if(syear == stm->tm_year){
+ return stm->tm_yday+1;
+ } else {
+ /* return negative to indicate that start of week is in
+ previous year. */
+ int is_leap = 0;
+ int year = stm->tm_year;
+
+ if( (year % 4 == 0 && year % 100 != 0) ||
+ year % 400 == 0){
+ is_leap =1;
+ }
+
+ return (stm->tm_yday+1)-(365+is_leap);
+ }
+
+}
+
+short icaltime_week_number(struct icaltimetype ictt)
+{
+ char str[5];
+ time_t t = icaltime_as_timet(ictt);
+ int week_no;
+ struct tm buft;
+
+ strftime(str,5,"%V", gmtime_r(&t, &buft));
+
+ week_no = atoi(str);
+
+ return week_no;
+
+}
+
+
+short icaltime_day_of_year(struct icaltimetype t){
+ time_t tt = icaltime_as_timet(t);
+ struct tm *stm, buft;
+
+ if(t.is_utc==1){
+ stm = gmtime_r(&tt, &buft);
+ } else {
+ stm = localtime_r(&tt, &buft);
+ }
+
+ return stm->tm_yday+1;
+
+}
+
+/* Jan 1 is day #1, not 0 */
+struct icaltimetype icaltime_from_day_of_year(short doy, short year)
+{
+ struct tm stm;
+ time_t tt;
+ struct set_tz_save old_tz = set_tz("UTC");
+
+ /* Get the time of january 1 of this year*/
+ memset(&stm,0,sizeof(struct tm));
+ stm.tm_year = year-1900;
+ stm.tm_mday = 1;
+
+ tt = mktime(&stm);
+ unset_tz(old_tz);
+
+
+ /* Now add in the days */
+
+ doy--;
+ tt += doy *60*60*24;
+
+ return icaltime_from_timet(tt, 1);
+}
+
+struct icaltimetype icaltime_null_time()
+{
+ struct icaltimetype t;
+ memset(&t,0,sizeof(struct icaltimetype));
+
+ return t;
+}
+
+
+int icaltime_is_valid_time(struct icaltimetype t){
+ if(t.is_utc > 1 || t.is_utc < 0 ||
+ t.year < 0 || t.year > 3000 ||
+ t.is_date > 1 || t.is_date < 0){
+ return 0;
+ } else {
+ return 1;
+ }
+
+}
+
+int icaltime_is_null_time(struct icaltimetype t)
+{
+ if (t.second +t.minute+t.hour+t.day+t.month+t.year == 0){
+ return 1;
+ }
+
+ return 0;
+
+}
+
+int icaltime_compare(struct icaltimetype a,struct icaltimetype b)
+{
+ time_t t1 = icaltime_as_timet(a);
+ time_t t2 = icaltime_as_timet(b);
+
+ if (t1 > t2) {
+ return 1;
+ } else if (t1 < t2) {
+ return -1;
+ } else {
+ return 0;
+ }
+
+}
+
+int
+icaltime_compare_date_only (struct icaltimetype a, struct icaltimetype b)
+{
+ time_t t1;
+ time_t t2;
+
+ if (a.year == b.year && a.month == b.month && a.day == b.day)
+ return 0;
+
+ t1 = icaltime_as_timet (a);
+ t2 = icaltime_as_timet (b);
+
+ if (t1 > t2)
+ return 1;
+ else if (t1 < t2)
+ return -1;
+ else {
+ /* not reached */
+ assert (0);
+ return 0;
+ }
+}
+
+
+/* These are defined in icalduration.c:
+struct icaltimetype icaltime_add(struct icaltimetype t,
+ struct icaldurationtype d)
+struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
+ struct icaltimetype t2)
+*/
+
diff --git a/src/plugins/vcalendar/libical/libical/icaltime.h b/src/plugins/vcalendar/libical/libical/icaltime.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icaltime.h
+ CREATOR: eric 02 June 2000
+
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+======================================================================*/
+
+#ifndef ICALTIME_H
+#define ICALTIME_H
+
+#include <time.h>
+
+/* icaltime_span is returned by icalcomponent_get_span() */
+struct icaltime_span {
+ time_t start; /* in UTC */
+ time_t end; /* in UTC */
+ int is_busy; /* 1->busy time, 0-> free time */
+};
+
+
+struct icaltimetype
+{
+ int year;
+ int month;
+ int day;
+ int hour;
+ int minute;
+ int second;
+
+ int is_utc; /* 1-> time is in UTC timezone */
+
+ int is_date; /* 1 -> interpret this as date. */
+
+ const char* zone; /*Ptr to Olsen placename. Libical does not own mem*/
+};
+
+/* Convert seconds past UNIX epoch to a timetype*/
+struct icaltimetype icaltime_from_timet(time_t v, int is_date);
+
+/* Return the time as seconds past the UNIX epoch */
+time_t icaltime_as_timet(struct icaltimetype);
+
+/* Return a string represention of the time, in RFC2445 format. The
+ string is owned by libical */
+char* icaltime_as_ical_string(struct icaltimetype tt);
+
+/* Like icaltime_from_timet(), except that the input may be in seconds
+ past the epoch in floating time. This routine is deprecated */
+struct icaltimetype icaltime_from_int(int v, int is_date, int is_utc);
+
+/* Like icaltime_as_timet, but in a floating epoch. This routine is deprecated */
+int icaltime_as_int(struct icaltimetype);
+
+/* create a time from an ISO format string */
+struct icaltimetype icaltime_from_string(const char* str);
+
+/* Routines for handling timezones */
+/* Return the offset of the named zone as seconds. tt is a time
+ indicating the date for which you want the offset */
+int icaltime_utc_offset(struct icaltimetype tt, const char* tzid);
+
+/* convert tt, of timezone tzid, into a utc time. Does nothing if the
+ time is already UTC. */
+struct icaltimetype icaltime_as_utc(struct icaltimetype tt,
+ const char* tzid);
+
+/* convert tt, a time in UTC, into a time in timezone tzid */
+struct icaltimetype icaltime_as_zone(struct icaltimetype tt,
+ const char* tzid);
+
+/* Return a null time, which indicates no time has been set. This time represent the beginning of the epoch */
+struct icaltimetype icaltime_null_time(void);
+
+/* Return true of the time is null. */
+int icaltime_is_null_time(struct icaltimetype t);
+
+/* Returns false if the time is clearly invalid, but is not null. This
+ is usually the result of creating a new time type buy not clearing
+ it, or setting one of the flags to an illegal value. */
+int icaltime_is_valid_time(struct icaltimetype t);
+
+/* Reset all of the time components to be in their normal ranges. For
+ instance, given a time with minutes=70, the minutes will be reduces
+ to 10, and the hour incremented. This allows the caller to do
+ arithmetic on times without worrying about overflow or
+ underflow. */
+struct icaltimetype icaltime_normalize(struct icaltimetype t);
+
+/* Return the day of the year of the given time */
+short icaltime_day_of_year(struct icaltimetype t);
+
+/* Create a new time, given a day of year and a year. */
+struct icaltimetype icaltime_from_day_of_year(short doy, short year);
+
+/* Return the day of the week of the given time. Sunday is 1 */
+short icaltime_day_of_week(struct icaltimetype t);
+
+/* Return the day of the year for the Sunday of the week that the
+ given time is within. */
+short icaltime_start_doy_of_week(struct icaltimetype t);
+
+/* Return a string with the time represented in the same format as ctime(). THe string is owned by libical */
+char* icaltime_as_ctime(struct icaltimetype);
+
+/* Return the week number for the week the given time is within */
+short icaltime_week_number(struct icaltimetype t);
+
+/* Create a new time from a weeknumber and a year. */
+struct icaltimetype icaltime_from_week_number(short week_number, short year);
+
+/* Return -1, 0, or 1 to indicate that a<b, a==b or a>b */
+int icaltime_compare(struct icaltimetype a,struct icaltimetype b);
+
+/* like icaltime_compare, but only use the date parts. */
+int icaltime_compare_date_only(struct icaltimetype a, struct icaltimetype b);
+
+/* Return the number of days in the given month */
+short icaltime_days_in_month(short month,short year);
+
+
+#endif /* !ICALTIME_H */
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/icaltypes.c b/src/plugins/vcalendar/libical/libical/icaltypes.c
@@ -0,0 +1,263 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icaltypes.c
+ CREATOR: eric 16 May 1999
+
+ $Id$
+ $Locker$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icaltypes.c
+
+ ======================================================================*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "icaltypes.h"
+#include "icalerror.h"
+#include "icalmemory.h"
+#include <stdlib.h> /* for malloc and abs() */
+#include <errno.h> /* for errno */
+#include <string.h> /* for icalmemory_strdup */
+#include <assert.h>
+
+#define TEMP_MAX 1024
+
+void*
+icalattachtype_get_data (struct icalattachtype* type);
+
+struct icalattachtype*
+icalattachtype_new()
+{
+ struct icalattachtype* v;
+
+ if ( ( v = (struct icalattachtype*)
+ malloc(sizeof(struct icalattachtype))) == 0) {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ v->refcount = 1;
+
+ v->binary = 0;
+ v->owns_binary = 0;
+
+ v->base64 = 0;
+ v->owns_base64 = 0;
+
+ v->url = 0;
+
+ return v;
+}
+
+
+void
+icalattachtype_free(struct icalattachtype* v)
+{
+ icalerror_check_arg( (v!=0),"v");
+
+ v->refcount--;
+
+ if (v->refcount <= 0){
+
+ if (v->base64 != 0 && v->owns_base64 != 0){
+ free(v->base64);
+ }
+
+ if (v->binary != 0 && v->owns_binary != 0){
+ free(v->binary);
+ }
+
+ if (v->url != 0){
+ free(v->url);
+ }
+
+ free(v);
+ }
+}
+
+void icalattachtype_add_reference(struct icalattachtype* v)
+{
+ icalerror_check_arg( (v!=0),"v");
+ v->refcount++;
+}
+
+void icalattachtype_set_url(struct icalattachtype* v, char* url)
+{
+ icalerror_check_arg( (v!=0),"v");
+
+ if (v->url != 0){
+ free (v->url);
+ }
+
+ v->url = icalmemory_strdup(url);
+
+ /* HACK This routine should do something if icalmemory_strdup returns NULL */
+
+}
+
+char* icalattachtype_get_url(struct icalattachtype* v)
+{
+ icalerror_check_arg( (v!=0),"v");
+ return v->url;
+}
+
+void icalattachtype_set_base64(struct icalattachtype* v, char* base64,
+ int owns)
+{
+ icalerror_check_arg( (v!=0),"v");
+
+ v->base64 = base64;
+ v->owns_base64 = !(owns != 0 );
+
+}
+
+char* icalattachtype_get_base64(struct icalattachtype* v)
+{
+ icalerror_check_arg( (v!=0),"v");
+ return v->base64;
+}
+
+void icalattachtype_set_binary(struct icalattachtype* v, char* binary,
+ int owns)
+{
+ icalerror_check_arg( (v!=0),"v");
+
+ v->binary = binary;
+ v->owns_binary = !(owns != 0 );
+
+}
+
+void* icalattachtype_get_binary(struct icalattachtype* v)
+{
+ icalerror_check_arg( (v!=0),"v");
+ return v->binary;
+}
+
+
+struct icaltriggertype icaltriggertype_from_string(const char* str)
+{
+
+
+ struct icaltriggertype tr, null_tr;
+ int old_ieaf = icalerror_errors_are_fatal;
+
+ tr.time= icaltime_null_time();
+ tr.duration = icaldurationtype_from_int(0);
+
+ null_tr = tr;
+
+ if(str == 0) goto error;
+
+
+ icalerror_errors_are_fatal = 0;
+
+ tr.time = icaltime_from_string(str);
+
+ icalerror_errors_are_fatal = old_ieaf;
+
+ if (icaltime_is_null_time(tr.time)){
+
+ tr.duration = icaldurationtype_from_string(str);
+
+ if(icaldurationtype_as_int(tr.duration) == 0) goto error;
+ }
+
+ return tr;
+
+ error:
+ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
+ return null_tr;
+
+}
+
+
+struct icalreqstattype icalreqstattype_from_string(char* str)
+{
+ char *p1,*p2;
+ struct icalreqstattype stat;
+ int major, minor;
+
+ icalerror_check_arg((str != 0),"str");
+
+ stat.code = ICAL_UNKNOWN_STATUS;
+ stat.debug = 0;
+ stat.desc = 0;
+
+ /* Get the status numbers */
+
+ sscanf(str, "%d.%d",&major, &minor);
+
+ if (major <= 0 || minor < 0){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return stat;
+ }
+
+ stat.code = icalenum_num_to_reqstat(major, minor);
+
+ if (stat.code == ICAL_UNKNOWN_STATUS){
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return stat;
+ }
+
+
+ p1 = strchr(str,';');
+
+ if (p1 == 0){
+/* icalerror_set_errno(ICAL_BADARG_ERROR);*/
+ return stat;
+ }
+
+ /* Just ignore the second clause; it will be taken from inside the library
+ */
+
+
+
+ p2 = strchr(p1+1,';');
+ if (p2 != 0 && *p2 != 0){
+ stat.debug = p2+1;
+ }
+
+ return stat;
+
+}
+
+char* icalreqstattype_as_string(struct icalreqstattype stat)
+{
+ char *temp;
+
+ temp = (char*)icalmemory_tmp_buffer(TEMP_MAX);
+
+ icalerror_check_arg_rz((stat.code != ICAL_UNKNOWN_STATUS),"Status");
+
+ if (stat.desc == 0){
+ stat.desc = icalenum_reqstat_desc(stat.code);
+ }
+
+ if(stat.debug != 0){
+ snprintf(temp,TEMP_MAX,"%d.%d;%s;%s", icalenum_reqstat_major(stat.code),
+ icalenum_reqstat_minor(stat.code),
+ stat.desc, stat.debug);
+
+ } else {
+ snprintf(temp,TEMP_MAX,"%d.%d;%s", icalenum_reqstat_major(stat.code),
+ icalenum_reqstat_minor(stat.code),
+ stat.desc);
+ }
+
+ return temp;
+}
diff --git a/src/plugins/vcalendar/libical/libical/icaltypes.h b/src/plugins/vcalendar/libical/libical/icaltypes.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icaltypes.h
+ CREATOR: eric 20 March 1999
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icaltypes.h
+
+======================================================================*/
+
+#ifndef ICALTYPES_H
+#define ICALTYPES_H
+
+#include <time.h>
+#include "icalenums.h"
+#include "icaltime.h"
+#include "icalduration.h"
+#include "icalperiod.h"
+
+
+/* This type type should probably be an opaque type... */
+struct icalattachtype
+{
+ void* binary;
+ int owns_binary;
+
+ char* base64;
+ int owns_base64;
+
+ char* url;
+
+ int refcount;
+
+};
+
+/* converts base64 to binary, fetches url and stores as binary, or
+ just returns data */
+
+struct icalattachtype* icalattachtype_new(void);
+void icalattachtype_add_reference(struct icalattachtype* v);
+void icalattachtype_free(struct icalattachtype* v);
+
+void icalattachtype_set_url(struct icalattachtype* v, char* url);
+char* icalattachtype_get_url(struct icalattachtype* v);
+
+void icalattachtype_set_base64(struct icalattachtype* v, char* base64,
+ int owns);
+char* icalattachtype_get_base64(struct icalattachtype* v);
+
+void icalattachtype_set_binary(struct icalattachtype* v, char* binary,
+ int owns);
+void* icalattachtype_get_binary(struct icalattachtype* v);
+
+struct icalgeotype
+{
+ float lat;
+ float lon;
+};
+
+
+struct icaldatetimeperiodtype
+{
+ struct icaltimetype time;
+ struct icalperiodtype period;
+};
+
+
+struct icaltriggertype
+{
+ struct icaltimetype time;
+ struct icaldurationtype duration;
+};
+
+struct icaltriggertype icaltriggertype_from_string(const char* str);
+
+/* struct icalreqstattype. This struct contains two string pointers,
+but don't try to free either of them. The "desc" string is a pointer
+to a static table inside the library. Don't try to free it. The
+"debug" string is a pointer into the string that the called passed
+into to icalreqstattype_from_string. Don't try to free it either, and
+don't use it after the original string has been freed.
+
+BTW, you would get that original string from
+*icalproperty_get_requeststatus() or icalvalue_get_text(), when
+operating on a the value of a request_status property. */
+
+struct icalreqstattype {
+
+ icalrequeststatus code;
+ const char* desc;
+ const char* debug;
+};
+
+struct icalreqstattype icalreqstattype_from_string(char* str);
+char* icalreqstattype_as_string(struct icalreqstattype);
+
+
+
+struct icaltimezonephase {
+ const char* tzname;
+ int is_stdandard; /* 1 = standard tme, 0 = daylight savings time */
+ struct icaltimetype dtstart;
+ int offsetto;
+ int tzoffsetfrom;
+ const char* comment;
+ struct icaldatetimeperiodtype rdate;
+ const char* rrule;
+};
+
+
+struct icaltimezonetype {
+ const char* tzid;
+ struct icaltimetype last_mod;
+ const char* tzurl;
+
+ /* Array of phases. The end of the array is a phase with tzname == 0 */
+ struct icaltimezonephase *phases;
+};
+
+void icaltimezonetype_free(struct icaltimezonetype tzt);
+
+
+#endif /* !ICALTYPES_H */
diff --git a/src/plugins/vcalendar/libical/libical/icalvalue.c b/src/plugins/vcalendar/libical/libical/icalvalue.c
@@ -0,0 +1,1197 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalvalue.c
+ CREATOR: eric 02 May 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalvalue.c
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+
+======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icalerror.h"
+#include "icalmemory.h"
+#include "icalparser.h"
+#include "icalenums.h"
+#include "icalvalueimpl.h"
+
+#include <stdlib.h> /* for malloc */
+#include <stdio.h> /* for sprintf */
+#include <string.h> /* For memset, others */
+#include <stddef.h> /* For offsetof() macro */
+#include <errno.h>
+#include <time.h> /* for mktime */
+#include <stdlib.h> /* for atoi and atof */
+#include <limits.h> /* for SHRT_MAX */
+
+#if _MAC_OS_
+#include "icalmemory_strdup.h"
+#endif
+
+#define TMP_BUF_SIZE 1024
+
+void print_datetime_to_string(char* str, struct icaltimetype *data);
+void print_date_to_string(char* str, struct icaltimetype *data);
+void print_time_to_string(char* str, struct icaltimetype *data);
+void print_recur_to_string(char* str, struct icaltimetype *data);
+
+
+struct icalvalue_impl* icalvalue_new_impl(icalvalue_kind kind){
+
+ struct icalvalue_impl* v;
+
+ if ( ( v = (struct icalvalue_impl*)
+ malloc(sizeof(struct icalvalue_impl))) == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ return 0;
+ }
+
+ strcpy(v->id,"val");
+
+ v->kind = kind;
+ v->size = 0;
+ v->parent = 0;
+ v->x_value = 0;
+ memset(&(v->data),0,sizeof(v->data));
+
+ return v;
+
+}
+
+
+
+icalvalue*
+icalvalue_new (icalvalue_kind kind)
+{
+ return (icalvalue*)icalvalue_new_impl(kind);
+}
+
+icalvalue* icalvalue_new_clone(icalvalue* value){
+
+ struct icalvalue_impl* new;
+ struct icalvalue_impl* old = (struct icalvalue_impl*)value;
+
+ new = icalvalue_new_impl(old->kind);
+
+ if (new == 0){
+ return 0;
+ }
+
+
+ strcpy(new->id, old->id);
+ new->kind = old->kind;
+ new->size = old->size;
+
+ switch (new->kind){
+
+ /* The contents of the attach value may or may not be owned by the
+ * library. */
+ case ICAL_ATTACH_VALUE:
+ case ICAL_BINARY_VALUE:
+ {
+ /* HACK ugh. I don't feel like impleenting this */
+ }
+
+ case ICAL_STRING_VALUE:
+ case ICAL_TEXT_VALUE:
+ case ICAL_CALADDRESS_VALUE:
+ case ICAL_URI_VALUE:
+ {
+ if (old->data.v_string != 0) {
+ new->data.v_string=icalmemory_strdup(old->data.v_string);
+
+ if ( new->data.v_string == 0 ) {
+ return 0;
+ }
+
+ }
+ break;
+ }
+ case ICAL_RECUR_VALUE:
+ {
+ if(old->data.v_recur != 0){
+ new->data.v_recur = malloc(sizeof(struct icalrecurrencetype));
+
+ if(new->data.v_recur == 0){
+ return 0;
+ }
+
+ memcpy( new->data.v_recur, old->data.v_recur,
+ sizeof(struct icalrecurrencetype));
+ }
+ break;
+ }
+
+ default:
+ {
+ /* all of the other types are stored as values, not
+ pointers, so we can just copy the whole structure. */
+
+ new->data = old->data;
+ }
+ }
+
+ return new;
+}
+
+char* icalmemory_strdup_and_dequote(const char* str)
+{
+ const char* p;
+ char* out = (char*)malloc(sizeof(char) * strlen(str) +1);
+ char* pout;
+
+ if (out == 0){
+ return 0;
+ }
+
+ pout = out;
+
+ for (p = str; *p!=0; p++){
+
+ if( *p == '\\')
+ {
+ p++;
+ switch(*p){
+ case 0:
+ {
+ *pout = '\0';
+ break;
+
+ }
+ case 'n':
+ {
+ *pout = '\n';
+ break;
+ }
+ case 'N':
+ {
+ *pout = '\n';
+ break;
+ }
+ case '\\':
+ case ',':
+ case ';':
+ {
+ *pout = *p;
+ break;
+ }
+ default:
+ {
+ *pout = ' ';
+ }
+ }
+ } else {
+ *pout = *p;
+ }
+
+ pout++;
+
+ }
+
+ *pout = '\0';
+
+ return out;
+}
+
+icalvalue* icalvalue_new_enum(icalvalue_kind kind, int x_type, const char* str)
+{
+ int e = icalproperty_string_to_enum(str);
+ struct icalvalue_impl *value;
+
+ if(e != 0 && icalproperty_enum_belongs_to_property(
+ icalproperty_value_kind_to_kind(kind),e)) {
+
+ value = icalvalue_new_impl(kind);
+ value->data.v_enum = e;
+ } else {
+ /* Make it an X value */
+ value = icalvalue_new_impl(kind);
+ value->data.v_enum = x_type;
+ icalvalue_set_x(value,str);
+ }
+
+ return value;
+}
+
+
+icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind,const char* str,icalproperty** error)
+{
+
+ struct icalvalue_impl *value = 0;
+
+ icalerror_check_arg_rz(str!=0,"str");
+
+ if (error != 0){
+ *error = 0;
+ }
+
+ switch (kind){
+
+ case ICAL_ATTACH_VALUE:
+ case ICAL_BINARY_VALUE:
+ case ICAL_BOOLEAN_VALUE:
+ {
+ /* HACK */
+ value = 0;
+
+ if (error != 0){
+ char temp[TMP_BUF_SIZE];
+ sprintf(temp,"%s Values are not implemented",
+ icalparameter_kind_to_string(kind));
+ *error = icalproperty_vanew_xlicerror(
+ temp,
+ icalparameter_new_xlicerrortype(
+ ICAL_XLICERRORTYPE_VALUEPARSEERROR),
+ 0);
+ }
+ break;
+ }
+
+
+ case ICAL_TRANSP_VALUE:
+ value = icalvalue_new_enum(kind, ICAL_TRANSP_X,str);
+ break;
+ case ICAL_METHOD_VALUE:
+ value = icalvalue_new_enum(kind, ICAL_METHOD_X,str);
+ break;
+ case ICAL_STATUS_VALUE:
+ value = icalvalue_new_enum(kind, ICAL_STATUS_X,str);
+ break;
+ case ICAL_ACTION_VALUE:
+ value = icalvalue_new_enum(kind, ICAL_ACTION_X,str);
+ break;
+ case ICAL_CLASS_VALUE:
+ value = icalvalue_new_enum(kind, ICAL_CLASS_X,str);
+ break;
+
+
+ case ICAL_INTEGER_VALUE:
+ {
+ value = icalvalue_new_integer(atoi(str));
+ break;
+ }
+
+ case ICAL_FLOAT_VALUE:
+ {
+ value = icalvalue_new_float(atof(str));
+ break;
+ }
+
+ case ICAL_UTCOFFSET_VALUE:
+ {
+ value = icalparser_parse_value(kind,str,(icalcomponent*)0);
+ break;
+ }
+
+ case ICAL_TEXT_VALUE:
+ {
+ char* dequoted_str = icalmemory_strdup_and_dequote(str);
+ value = icalvalue_new_text(dequoted_str);
+ free(dequoted_str);
+ break;
+ }
+
+
+ case ICAL_STRING_VALUE:
+ {
+ value = icalvalue_new_string(str);
+ break;
+ }
+
+ case ICAL_CALADDRESS_VALUE:
+ {
+ value = icalvalue_new_caladdress(str);
+ break;
+ }
+
+ case ICAL_URI_VALUE:
+ {
+ value = icalvalue_new_uri(str);
+ break;
+ }
+
+
+ case ICAL_GEO_VALUE:
+ {
+ value = 0;
+ /* HACK */
+
+ if (error != 0){
+ char temp[TMP_BUF_SIZE];
+ sprintf(temp,"GEO Values are not implemented");
+ *error = icalproperty_vanew_xlicerror(
+ temp,
+ icalparameter_new_xlicerrortype(
+ ICAL_XLICERRORTYPE_VALUEPARSEERROR),
+ 0);
+ }
+
+ /*icalerror_warn("Parsing GEO properties is unimplmeneted");*/
+
+ break;
+ }
+
+ case ICAL_RECUR_VALUE:
+ {
+ struct icalrecurrencetype rt;
+ rt = icalrecurrencetype_from_string(str);
+ value = icalvalue_new_recur(rt);
+ break;
+ }
+
+ case ICAL_TIME_VALUE:
+ case ICAL_DATE_VALUE:
+ case ICAL_DATETIME_VALUE:
+ case ICAL_DATETIMEDATE_VALUE:
+ {
+ struct icaltimetype tt;
+ tt = icaltime_from_string(str);
+ if(!icaltime_is_null_time(tt)){
+ value = icalvalue_new_impl(kind);
+ value->data.v_time = tt;
+ }
+ break;
+ }
+
+ case ICAL_DATETIMEPERIOD_VALUE:
+ {
+ struct icaltimetype tt;
+ struct icalperiodtype p;
+ tt = icaltime_from_string(str);
+ p = icalperiodtype_from_string(str);
+
+ if(!icaltime_is_null_time(tt)){
+ value = icalvalue_new_datetime(tt);
+ } else if (!icalperiodtype_is_null_period(p)){
+ value = icalvalue_new_period(p);
+ }
+
+ break;
+ }
+
+ case ICAL_DURATION_VALUE:
+ {
+ struct icaldurationtype dur = icaldurationtype_from_string(str);
+
+ if(icaldurationtype_is_null_duration(dur)){
+ value = 0;
+ } else {
+ value = icalvalue_new_duration(dur);
+ }
+
+ break;
+ }
+
+ case ICAL_PERIOD_VALUE:
+ {
+ struct icalperiodtype p;
+ p = icalperiodtype_from_string(str);
+
+ if(!icalperiodtype_is_null_period(p)){
+ value = icalvalue_new_period(p);
+ }
+ break;
+ }
+
+ case ICAL_TRIGGER_VALUE:
+ {
+ struct icaltriggertype tr = icaltriggertype_from_string(str);
+ value = icalvalue_new_trigger(tr);
+ break;
+ }
+
+ default:
+ {
+
+ if (error != 0 ){
+ char temp[TMP_BUF_SIZE];
+
+ snprintf(temp,TMP_BUF_SIZE,"Unknown type for \'%s\'",str);
+
+ *error = icalproperty_vanew_xlicerror(
+ temp,
+ icalparameter_new_xlicerrortype(
+ ICAL_XLICERRORTYPE_VALUEPARSEERROR),
+ 0);
+ }
+
+ icalerror_warn("icalvalue_new_from_string got an unknown value type");
+ value=0;
+ }
+ }
+
+
+ if (error != 0 && *error == 0 && value == 0){
+ char temp[TMP_BUF_SIZE];
+
+ snprintf(temp,TMP_BUF_SIZE,"Failed to parse value: \'%s\'",str);
+
+ *error = icalproperty_vanew_xlicerror(
+ temp,
+ icalparameter_new_xlicerrortype(
+ ICAL_XLICERRORTYPE_VALUEPARSEERROR),
+ 0);
+ }
+
+
+ return value;
+
+}
+
+icalvalue* icalvalue_new_from_string(icalvalue_kind kind,const char* str)
+{
+ return icalvalue_new_from_string_with_error(kind,str,(icalproperty*)0);
+}
+
+
+
+void
+icalvalue_free (icalvalue* value)
+{
+ struct icalvalue_impl* v = (struct icalvalue_impl*)value;
+
+ icalerror_check_arg_rv((value != 0),"value");
+
+#ifdef ICAL_FREE_ON_LIST_IS_ERROR
+ icalerror_assert( (v->parent ==0),"This value is still attached to a property");
+
+#else
+ if(v->parent !=0){
+ return;
+ }
+#endif
+
+ if(v->x_value != 0){
+ free((char *)v->x_value);
+ }
+
+ switch (v->kind){
+ case ICAL_BINARY_VALUE:
+ case ICAL_ATTACH_VALUE: {
+ /* HACK ugh. This will be tough to implement */
+ }
+ case ICAL_TEXT_VALUE:
+ case ICAL_CALADDRESS_VALUE:
+ case ICAL_URI_VALUE:
+ {
+ if (v->data.v_string != 0) {
+ free((void*)v->data.v_string);
+ v->data.v_string = 0;
+ }
+ break;
+ }
+ case ICAL_RECUR_VALUE:
+ {
+ if(v->data.v_recur != 0){
+ free((void*)v->data.v_recur);
+ v->data.v_recur = 0;
+ }
+ break;
+ }
+
+ default:
+ {
+ /* Nothing to do */
+ }
+ }
+
+ v->kind = ICAL_NO_VALUE;
+ v->size = 0;
+ v->parent = 0;
+ memset(&(v->data),0,sizeof(v->data));
+ v->id[0] = 'X';
+ free(v);
+}
+
+int
+icalvalue_is_valid (icalvalue* value)
+{
+ /*struct icalvalue_impl* v = (struct icalvalue_impl*)value;*/
+
+ if(value == 0){
+ return 0;
+ }
+
+ return 1;
+}
+
+char* icalvalue_binary_as_ical_string(icalvalue* value) {
+
+ const char* data;
+ char* str;
+ icalerror_check_arg_rz( (value!=0),"value");
+
+ data = icalvalue_get_binary(value);
+
+ str = (char*)icalmemory_tmp_buffer(60);
+ sprintf(str,"icalvalue_binary_as_ical_string is not implemented yet");
+
+ return str;
+}
+
+
+#define MAX_INT_DIGITS 12 /* Enough for 2^32 + sign*/
+char* icalvalue_int_as_ical_string(icalvalue* value) {
+
+ int data;
+ char* str = (char*)icalmemory_tmp_buffer(MAX_INT_DIGITS);
+
+ icalerror_check_arg_rz( (value!=0),"value");
+
+ data = icalvalue_get_integer(value);
+
+ snprintf(str,MAX_INT_DIGITS,"%d",data);
+
+ return str;
+}
+
+char* icalvalue_utcoffset_as_ical_string(icalvalue* value)
+{
+ int data,h,m,s;
+ char sign;
+ char* str = (char*)icalmemory_tmp_buffer(9);
+
+ icalerror_check_arg_rz( (value!=0),"value");
+
+ data = icalvalue_get_utcoffset(value);
+
+ if (abs(data) == data){
+ sign = '+';
+ } else {
+ sign = '-';
+ }
+
+ h = data/3600;
+ m = (data - (h*3600))/ 60;
+ s = (data - (h*3600) - (m*60));
+
+ sprintf(str,"%c%02d%02d%02d",sign,abs(h),abs(m),abs(s));
+
+ return str;
+}
+
+char* icalvalue_string_as_ical_string(icalvalue* value) {
+
+ const char* data;
+ char* str = 0;
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = ((struct icalvalue_impl*)value)->data.v_string;
+
+ str = (char*)icalmemory_tmp_buffer(strlen(data)+1);
+
+ strcpy(str,data);
+
+ return str;
+}
+
+
+char* icalvalue_recur_as_ical_string(icalvalue* value)
+{
+ struct icalvalue_impl *impl = (struct icalvalue_impl*)value;
+ struct icalrecurrencetype *recur = impl->data.v_recur;
+
+ return icalrecurrencetype_as_string(recur);
+}
+
+char* icalvalue_text_as_ical_string(icalvalue* value) {
+
+ char *str;
+ char *str_p;
+ char *rtrn;
+ const char *p;
+ size_t buf_sz;
+ int line_length;
+
+ line_length = 0;
+
+ buf_sz = strlen(((struct icalvalue_impl*)value)->data.v_string)+1;
+
+ str_p = str = (char*)icalmemory_new_buffer(buf_sz);
+
+ if (str_p == 0){
+ return 0;
+ }
+
+ for(p=((struct icalvalue_impl*)value)->data.v_string; *p!=0; p++){
+
+ switch(*p){
+ case '\n': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\n");
+ line_length+=3;
+ break;
+ }
+
+ case '\t': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\t");
+ line_length+=3;
+ break;
+ }
+ case '\r': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\r");
+ line_length+=3;
+ break;
+ }
+ case '\b': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\b");
+ line_length+=3;
+ break;
+ }
+ case '\f': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\f");
+ line_length+=3;
+ break;
+ }
+
+ case ';':
+ case ',':{
+ icalmemory_append_char(&str,&str_p,&buf_sz,'\\');
+ icalmemory_append_char(&str,&str_p,&buf_sz,*p);
+ line_length+=3;
+ break;
+ }
+
+ case '"':{
+ icalmemory_append_char(&str,&str_p,&buf_sz,'\\');
+ icalmemory_append_char(&str,&str_p,&buf_sz,*p);
+ line_length+=3;
+ break;
+ }
+
+ default: {
+ icalmemory_append_char(&str,&str_p,&buf_sz,*p);
+ line_length++;
+ }
+ }
+
+ if (line_length > 65 && *p == ' '){
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\n ");
+ line_length=0;
+ }
+
+
+ if (line_length > 75){
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\n ");
+ line_length=0;
+ }
+
+ }
+
+ /* Assume the last character is not a '\0' and add one. We could
+ check *str_p != 0, but that would be an uninitialized memory
+ read. */
+
+
+ icalmemory_append_char(&str,&str_p,&buf_sz,'\0');
+
+ rtrn = icalmemory_tmp_copy(str);
+
+ icalmemory_free_buffer(str);
+
+ return rtrn;
+}
+
+
+char* icalvalue_attach_as_ical_string(icalvalue* value) {
+
+ struct icalattachtype a;
+ char * str;
+
+ icalerror_check_arg_rz( (value!=0),"value");
+
+ a = icalvalue_get_attach(value);
+
+ if (a.binary != 0) {
+ return icalvalue_binary_as_ical_string(value);
+ } else if (a.base64 != 0) {
+ str = (char*)icalmemory_tmp_buffer(strlen(a.base64)+1);
+ strcpy(str,a.base64);
+ return str;
+ } else if (a.url != 0){
+ return icalvalue_string_as_ical_string(value);
+ } else {
+ icalerrno = ICAL_MALFORMEDDATA_ERROR;
+ return 0;
+ }
+}
+
+
+char* icalvalue_duration_as_ical_string(icalvalue* value) {
+
+ struct icaldurationtype data;
+
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = icalvalue_get_duration(value);
+
+ return icaldurationtype_as_ical_string(data);
+}
+
+void print_time_to_string(char* str, struct icaltimetype *data)
+{
+ char temp[20];
+
+ if (data->is_utc == 1){
+ sprintf(temp,"%02d%02d%02dZ",data->hour,data->minute,data->second);
+ } else {
+ sprintf(temp,"%02d%02d%02d",data->hour,data->minute,data->second);
+ }
+
+ strcat(str,temp);
+}
+
+
+char* icalvalue_time_as_ical_string(icalvalue* value) {
+
+ struct icaltimetype data;
+ char* str;
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = icalvalue_get_time(value);
+
+ str = (char*)icalmemory_tmp_buffer(8);
+
+ str[0] = 0;
+ print_time_to_string(str,&data);
+
+ return str;
+}
+
+void print_date_to_string(char* str, struct icaltimetype *data)
+{
+ char temp[20];
+
+ sprintf(temp,"%04d%02d%02d",data->year,data->month,data->day);
+
+ strcat(str,temp);
+}
+
+char* icalvalue_date_as_ical_string(icalvalue* value) {
+
+ struct icaltimetype data;
+ char* str;
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = icalvalue_get_date(value);
+
+ str = (char*)icalmemory_tmp_buffer(9);
+
+ str[0] = 0;
+ print_date_to_string(str,&data);
+
+ return str;
+}
+
+void print_datetime_to_string(char* str, struct icaltimetype *data)
+{
+ print_date_to_string(str,data);
+ strcat(str,"T");
+ print_time_to_string(str,data);
+
+}
+
+const char* icalvalue_datetime_as_ical_string(icalvalue* value) {
+
+ struct icaltimetype data;
+ char* str;
+ icalvalue_kind kind = icalvalue_isa(value);
+
+ icalerror_check_arg_rz( (value!=0),"value");
+
+
+ if( !(kind == ICAL_DATETIMEDATE_VALUE ||
+ kind == ICAL_DATE_VALUE ||
+ kind == ICAL_DATETIME_VALUE ||
+ kind == ICAL_TIME_VALUE))
+ {
+ icalerror_set_errno(ICAL_BADARG_ERROR);
+ return 0;
+ }
+
+ data = icalvalue_get_datetime(value);
+
+ str = (char*)icalmemory_tmp_buffer(20);
+
+ str[0] = 0;
+
+ print_datetime_to_string(str,&data);
+
+ return str;
+
+}
+
+
+const char* icalvalue_datetimedate_as_ical_string(icalvalue* value) {
+
+ struct icaltimetype data;
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = icalvalue_get_datetime(value);
+
+ if (data.is_date == 1){
+ return icalvalue_date_as_ical_string(value);
+ } else {
+ return icalvalue_datetime_as_ical_string(value);
+ }
+}
+
+
+char* icalvalue_float_as_ical_string(icalvalue* value) {
+
+ float data;
+ char* str;
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = icalvalue_get_float(value);
+
+ str = (char*)icalmemory_tmp_buffer(15);
+
+ sprintf(str,"%f",data);
+
+ return str;
+}
+
+char* icalvalue_geo_as_ical_string(icalvalue* value) {
+
+ struct icalgeotype data;
+ char* str;
+ icalerror_check_arg_rz( (value!=0),"value");
+
+ data = icalvalue_get_geo(value);
+
+ str = (char*)icalmemory_tmp_buffer(25);
+
+ sprintf(str,"%f;%f",data.lat,data.lon);
+
+ return str;
+}
+
+const char* icalvalue_datetimeperiod_as_ical_string(icalvalue* value) {
+ struct icaldatetimeperiodtype dtp = icalvalue_get_datetimeperiod(value);
+
+ icalerror_check_arg_rz( (value!=0),"value");
+
+ if(!icaltime_is_null_time(dtp.time)){
+ return icaltime_as_ical_string(dtp.time);
+ } else {
+ return icalperiodtype_as_ical_string(dtp.period);
+ }
+}
+
+const char* icalvalue_period_as_ical_string(icalvalue* value) {
+ struct icalperiodtype data;
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = icalvalue_get_period(value);
+
+ return icalperiodtype_as_ical_string(data);
+
+}
+
+char* icalvalue_trigger_as_ical_string(icalvalue* value) {
+
+ struct icaltriggertype data;
+
+ icalerror_check_arg_rz( (value!=0),"value");
+ data = icalvalue_get_trigger(value);
+
+ if(!icaltime_is_null_time(data.time)){
+ return icaltime_as_ical_string(data.time);
+ } else {
+ return icaldurationtype_as_ical_string(data.duration);
+ }
+
+}
+
+const char*
+icalvalue_as_ical_string (icalvalue* value)
+{
+ struct icalvalue_impl* v = (struct icalvalue_impl*)value;
+
+ v=v;
+
+ if(value == 0){
+ return 0;
+ }
+
+ switch (v->kind){
+
+ case ICAL_ATTACH_VALUE:
+ return icalvalue_attach_as_ical_string(value);
+
+ case ICAL_BINARY_VALUE:
+ return icalvalue_binary_as_ical_string(value);
+
+ case ICAL_BOOLEAN_VALUE:
+ case ICAL_INTEGER_VALUE:
+ return icalvalue_int_as_ical_string(value);
+
+ case ICAL_UTCOFFSET_VALUE:
+ return icalvalue_utcoffset_as_ical_string(value);
+
+ case ICAL_TEXT_VALUE:
+ return icalvalue_text_as_ical_string(value);
+
+ case ICAL_STRING_VALUE:
+ case ICAL_URI_VALUE:
+ case ICAL_CALADDRESS_VALUE:
+ return icalvalue_string_as_ical_string(value);
+
+ case ICAL_DATE_VALUE:
+ return icalvalue_date_as_ical_string(value);
+ case ICAL_DATETIME_VALUE:
+ return icalvalue_datetime_as_ical_string(value);
+ case ICAL_DATETIMEDATE_VALUE:
+ return icalvalue_datetimedate_as_ical_string(value);
+ case ICAL_DURATION_VALUE:
+ return icalvalue_duration_as_ical_string(value);
+ case ICAL_TIME_VALUE:
+ return icalvalue_time_as_ical_string(value);
+
+ case ICAL_PERIOD_VALUE:
+ return icalvalue_period_as_ical_string(value);
+ case ICAL_DATETIMEPERIOD_VALUE:
+ return icalvalue_datetimeperiod_as_ical_string(value);
+
+ case ICAL_FLOAT_VALUE:
+ return icalvalue_float_as_ical_string(value);
+
+ case ICAL_GEO_VALUE:
+ return icalvalue_geo_as_ical_string(value);
+
+ case ICAL_RECUR_VALUE:
+ return icalvalue_recur_as_ical_string(value);
+
+ case ICAL_TRIGGER_VALUE:
+ return icalvalue_trigger_as_ical_string(value);
+
+ case ICAL_ACTION_VALUE:
+ case ICAL_METHOD_VALUE:
+ case ICAL_STATUS_VALUE:
+ case ICAL_TRANSP_VALUE:
+ case ICAL_CLASS_VALUE:
+ if(v->x_value !=0){
+ return icalmemory_tmp_copy(v->x_value);
+ }
+
+ return icalproperty_enum_to_string(v->data.v_enum);
+
+ case ICAL_X_VALUE:
+ return icalmemory_tmp_copy(v->x_value);
+
+ case ICAL_NO_VALUE:
+ default:
+ {
+ return 0;
+ }
+ }
+}
+
+
+icalvalue_kind
+icalvalue_isa (icalvalue* value)
+{
+ struct icalvalue_impl* v = (struct icalvalue_impl*)value;
+
+ if(value == 0){
+ return ICAL_NO_VALUE;
+ }
+
+ return v->kind;
+}
+
+
+int
+icalvalue_isa_value (void* value)
+{
+ struct icalvalue_impl *impl = (struct icalvalue_impl *)value;
+
+ icalerror_check_arg_rz( (value!=0), "value");
+
+ if (strcmp(impl->id,"val") == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+int icalvalue_is_time(icalvalue* a) {
+ icalvalue_kind kind = icalvalue_isa(a);
+
+ if(kind == ICAL_DATETIMEDATE_VALUE ||
+ kind == ICAL_DATETIME_VALUE ||
+ kind == ICAL_DATE_VALUE ||
+ kind == ICAL_TIME_VALUE ){
+ return 1;
+ }
+
+ return 0;
+
+}
+
+icalparameter_xliccomparetype
+icalvalue_compare(icalvalue* a, icalvalue *b)
+{
+ struct icalvalue_impl *impla = (struct icalvalue_impl *)a;
+ struct icalvalue_impl *implb = (struct icalvalue_impl *)b;
+
+ icalerror_check_arg_rz( (a!=0), "a");
+ icalerror_check_arg_rz( (b!=0), "b");
+
+ /* Not the same type; they can only be unequal */
+ if( ! (icalvalue_is_time(a) && icalvalue_is_time(b)) &&
+ icalvalue_isa(a) != icalvalue_isa(b)){
+ return ICAL_XLICCOMPARETYPE_NOTEQUAL;
+ }
+
+ switch (icalvalue_isa(a)){
+
+ case ICAL_ATTACH_VALUE:
+ case ICAL_BINARY_VALUE:
+
+ case ICAL_BOOLEAN_VALUE:
+ {
+ if (icalvalue_get_boolean(a) == icalvalue_get_boolean(b)){
+ return ICAL_XLICCOMPARETYPE_EQUAL;
+ } else {
+ return ICAL_XLICCOMPARETYPE_NOTEQUAL;
+ }
+ }
+
+ case ICAL_FLOAT_VALUE:
+ {
+ if (impla->data.v_float > implb->data.v_float){
+ return ICAL_XLICCOMPARETYPE_GREATER;
+ } else if (impla->data.v_float < implb->data.v_float){
+ return ICAL_XLICCOMPARETYPE_LESS;
+ } else {
+ return ICAL_XLICCOMPARETYPE_EQUAL;
+ }
+ }
+
+ case ICAL_INTEGER_VALUE:
+ case ICAL_UTCOFFSET_VALUE:
+ {
+ if (impla->data.v_int > implb->data.v_int){
+ return ICAL_XLICCOMPARETYPE_GREATER;
+ } else if (impla->data.v_int < implb->data.v_int){
+ return ICAL_XLICCOMPARETYPE_LESS;
+ } else {
+ return ICAL_XLICCOMPARETYPE_EQUAL;
+ }
+ }
+
+ case ICAL_DURATION_VALUE:
+ {
+ int a = icaldurationtype_as_int(impla->data.v_duration);
+ int b = icaldurationtype_as_int(implb->data.v_duration);
+
+ if (a > b){
+ return ICAL_XLICCOMPARETYPE_GREATER;
+ } else if (a < b){
+ return ICAL_XLICCOMPARETYPE_LESS;
+ } else {
+ return ICAL_XLICCOMPARETYPE_EQUAL;
+ }
+ }
+
+
+ case ICAL_TEXT_VALUE:
+ case ICAL_URI_VALUE:
+ case ICAL_CALADDRESS_VALUE:
+ case ICAL_TRIGGER_VALUE:
+ case ICAL_DATE_VALUE:
+ case ICAL_DATETIME_VALUE:
+ case ICAL_DATETIMEDATE_VALUE:
+ case ICAL_TIME_VALUE:
+ case ICAL_DATETIMEPERIOD_VALUE:
+ {
+ int r;
+
+ r = strcmp(icalvalue_as_ical_string(a),
+ icalvalue_as_ical_string(b));
+
+ if (r > 0) {
+ return ICAL_XLICCOMPARETYPE_GREATER;
+ } else if (r < 0){
+ return ICAL_XLICCOMPARETYPE_LESS;
+ } else {
+ return ICAL_XLICCOMPARETYPE_EQUAL;
+ }
+
+
+ }
+
+ case ICAL_METHOD_VALUE:
+ {
+ if (icalvalue_get_method(a) == icalvalue_get_method(b)){
+ return ICAL_XLICCOMPARETYPE_EQUAL;
+ } else {
+ return ICAL_XLICCOMPARETYPE_NOTEQUAL;
+ }
+
+ }
+
+ case ICAL_STATUS_VALUE:
+ {
+ if (icalvalue_get_status(a) == icalvalue_get_status(b)){
+ return ICAL_XLICCOMPARETYPE_EQUAL;
+ } else {
+ return ICAL_XLICCOMPARETYPE_NOTEQUAL;
+ }
+
+ }
+
+ case ICAL_PERIOD_VALUE:
+ case ICAL_GEO_VALUE:
+ case ICAL_RECUR_VALUE:
+ case ICAL_NO_VALUE:
+ default:
+ {
+ icalerror_warn("Comparison not implemented for value type");
+ return ICAL_XLICCOMPARETYPE_REGEX+1; /* HACK */
+ }
+ }
+
+}
+
+void icalvalue_set_parent(icalvalue* value,
+ icalproperty* property)
+{
+ struct icalvalue_impl* v = (struct icalvalue_impl*)value;
+
+ v->parent = property;
+
+}
+
+icalproperty* icalvalue_get_parent(icalvalue* value)
+{
+ struct icalvalue_impl* v = (struct icalvalue_impl*)value;
+
+
+ return v->parent;
+}
+
+
+
+/* The remaining interfaces are 'new', 'set' and 'get' for each of the value
+ types */
+
+
+/* Everything below this line is machine generated. Do not edit. */
diff --git a/src/plugins/vcalendar/libical/libical/icalvalue.h b/src/plugins/vcalendar/libical/libical/icalvalue.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalvalue.h
+ CREATOR: eric 20 March 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 icalvalue.h
+
+ ======================================================================*/
+
+#ifndef ICALVALUE_H
+#define ICALVALUE_H
+
+#include <time.h>
+#include "icalenums.h"
+#include "icaltypes.h"
+#include "icalrecur.h"
+#include "icalduration.h"
+#include "icalperiod.h"
+#include "icalderivedproperty.h" /* For icalproperty_method, etc. */
+#include "icalderivedparameter.h"
+#include "icalderivedvalue.h"
+
+/* Defined in icalderivedvalue.h */
+/*typedef void icalvalue;*/
+
+icalvalue* icalvalue_new(icalvalue_kind kind);
+
+icalvalue* icalvalue_new_clone(icalvalue* value);
+
+icalvalue* icalvalue_new_from_string(icalvalue_kind kind, const char* str);
+
+void icalvalue_free(icalvalue* value);
+
+int icalvalue_is_valid(icalvalue* value);
+
+const char* icalvalue_as_ical_string(icalvalue* value);
+
+icalvalue_kind icalvalue_isa(icalvalue* value);
+
+int icalvalue_isa_value(void*);
+
+icalparameter_xliccomparetype icalvalue_compare(icalvalue* a, icalvalue *b);
+
+
+/* Special, non autogenerated value accessors */
+
+icalvalue* icalvalue_new_recur (struct icalrecurrencetype v);
+void icalvalue_set_recur(icalvalue* value, struct icalrecurrencetype v);
+struct icalrecurrencetype icalvalue_get_recur(icalvalue* value);
+
+icalvalue* icalvalue_new_trigger (struct icaltriggertype v);
+void icalvalue_set_trigger(icalvalue* value, struct icaltriggertype v);
+struct icaltriggertype icalvalue_get_trigger(icalvalue* value);
+
+icalvalue* icalvalue_new_datetimeperiod (struct icaldatetimeperiodtype v);
+void icalvalue_set_datetimeperiod(icalvalue* value,
+ struct icaldatetimeperiodtype v);
+struct icaldatetimeperiodtype icalvalue_get_datetimeperiod(icalvalue* value);
+
+/* Convert enumerations */
+
+icalvalue_kind icalvalue_string_to_kind(const char* str);
+const char* icalvalue_kind_to_string(icalvalue_kind kind);
+
+
+#endif /*ICALVALUE_H*/
diff --git a/src/plugins/vcalendar/libical/libical/icalvalueimpl.h b/src/plugins/vcalendar/libical/libical/icalvalueimpl.h
@@ -0,0 +1,91 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalvalue.c
+ CREATOR: eric 02 May 1999
+
+ $Id$
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The original code is icalvalue.c
+
+ Contributions from:
+ Graham Davison (g.m.davison@computer.org)
+
+
+======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef ICALVALUEIMPL_H
+#define ICALVALUEIMPL_H
+
+#include "icalenums.h"
+
+
+struct icalvalue_impl {
+ icalvalue_kind kind; /*this is the kind that is visible from the outside*/
+
+ char id[5];
+ int size;
+ icalproperty* parent;
+ const char* x_value;
+
+ union data {
+ struct icalattachtype v_attach;
+ /* void *v_binary; */ /* use v_attach */
+ const char *v_string;
+ /*char *v_text;*/
+ /*char *v_caladdress;*/
+ /*char *v_uri;*/
+ float v_float;
+ int v_int;
+ /*int v_boolean;*/
+ /*int v_integer;*/
+ struct icaldurationtype v_duration;
+ /*int v_utcoffset;*/
+
+ struct icalperiodtype v_period;
+ /*struct icalperiodtype v_datetimeperiod;*/
+ struct icalgeotype v_geo;
+ /*time_t v_time;*/
+ struct icaltimetype v_time;
+ /*struct icaltimetype v_date;*/
+ /*struct icaltimetype v_datetime;*/
+ /*struct icaltimetype v_datetimedate;*/
+
+ /* struct icalrecurrencetype was once included
+ directly ( not referenced ) in this union, but it
+ contributes 2000 bytes to every value, so now it is
+ a reference*/
+
+ struct icalrecurrencetype *v_recur;
+ struct icaltriggertype v_trigger;
+
+ int v_enum;
+ /* v_enum takes care of several enumerated types including:
+ icalproperty_method v_method;
+ icalproperty_status v_status;
+ icalproperty_action v_action;
+ icalproperty_class v_class;
+ icalproperty_transp v_transp;
+ */
+
+ } data;
+};
+
+#endif
diff --git a/src/plugins/vcalendar/libical/libical/icalversion.h b/src/plugins/vcalendar/libical/libical/icalversion.h
@@ -0,0 +1,7 @@
+#ifndef ICAL_VERSION_H
+#define ICAL_VERSION_H
+
+#define ICAL_PACKAGE "claws-mail"
+#define ICAL_VERSION "3.9.0cvs64"
+
+#endif
diff --git a/src/plugins/vcalendar/libical/libical/icalversion.h.in b/src/plugins/vcalendar/libical/libical/icalversion.h.in
@@ -0,0 +1,7 @@
+#ifndef ICAL_VERSION_H
+#define ICAL_VERSION_H
+
+#define ICAL_PACKAGE "@PACKAGE@"
+#define ICAL_VERSION "@VERSION@"
+
+#endif
diff --git a/src/plugins/vcalendar/libical/libical/icalyacc.output b/src/plugins/vcalendar/libical/libical/icalyacc.output
@@ -0,0 +1,830 @@
+Nonterminals useless in grammar
+
+ trigger
+
+
+Terminals unused in grammar
+
+ FLOATNUMBER
+ STRING
+ EOL
+ EQUALS
+ CHARACTER
+ COLON
+ COMMA
+ SEMICOLON
+ MINUS
+ TIMESEPERATOR
+ TRUE
+ FALSE
+ FREQ
+ BYDAY
+ BYHOUR
+ BYMINUTE
+ BYMONTH
+ BYMONTHDAY
+ BYSECOND
+ BYSETPOS
+ BYWEEKNO
+ BYYEARDAY
+ DAILY
+ MINUTELY
+ MONTHLY
+ SECONDLY
+ WEEKLY
+ HOURLY
+ YEARLY
+ INTERVAL
+ COUNT
+ UNTIL
+ WKST
+ MO
+ SA
+ SU
+ TU
+ WE
+ TH
+ FR
+ BIT8
+ ACCEPTED
+ ADD
+ AUDIO
+ BASE64
+ BINARY
+ BOOLEAN
+ BUSY
+ BUSYTENTATIVE
+ BUSYUNAVAILABLE
+ CALADDRESS
+ CANCEL
+ CANCELLED
+ CHAIR
+ CHILD
+ COMPLETED
+ CONFIDENTIAL
+ CONFIRMED
+ COUNTER
+ DATE
+ DATETIME
+ DECLINECOUNTER
+ DECLINED
+ DELEGATED
+ DISPLAY
+ DRAFT
+ DURATION
+ EMAIL
+ END
+ FINAL
+ FLOAT
+ FREE
+ GREGORIAN
+ GROUP
+ INDIVIDUAL
+ INPROCESS
+ INTEGER
+ NEEDSACTION
+ NONPARTICIPANT
+ OPAQUE
+ OPTPARTICIPANT
+ PARENT
+ PERIOD
+ PRIVATE
+ PROCEDURE
+ PUBLIC
+ PUBLISH
+ RECUR
+ REFRESH
+ REPLY
+ REQPARTICIPANT
+ REQUEST
+ RESOURCE
+ ROOM
+ SIBLING
+ START
+ TENTATIVE
+ TEXT
+ THISANDFUTURE
+ THISANDPRIOR
+ TIME
+ TRANSPAENT
+ UNKNOWN
+ UTCOFFSET
+ XNAME
+ ALTREP
+ CN
+ CUTYPE
+ DAYLIGHT
+ DIR
+ ENCODING
+ EVENT
+ FBTYPE
+ FMTTYPE
+ LANGUAGE
+ MEMBER
+ PARTSTAT
+ RANGE
+ RELATED
+ RELTYPE
+ ROLE
+ RSVP
+ SENTBY
+ STANDARD
+ URI
+ CHARSET
+
+
+Rules useless in grammar
+
+ 37 trigger: /* empty */
+
+
+Grammar
+
+ 0 $accept: value $end
+
+ 1 value: date_value
+ 2 | datetime_value
+ 3 | duration_value
+ 4 | period_value
+ 5 | utcoffset_value
+ 6 | error
+
+ 7 date_value: DIGITS
+
+ 8 utc_char: /* empty */
+ 9 | UTC_CHAR
+
+ 10 utc_char_b: /* empty */
+ 11 | UTC_CHAR
+
+ 12 datetime_value: DIGITS TIME_CHAR DIGITS utc_char
+
+ 13 dur_date: dur_day
+ 14 | dur_day dur_time
+
+ 15 dur_week: DIGITS 'W'
+
+ 16 dur_time: TIME_CHAR dur_hour
+ 17 | TIME_CHAR dur_minute
+ 18 | TIME_CHAR dur_second
+
+ 19 dur_hour: DIGITS 'H'
+ 20 | DIGITS 'H' dur_minute
+
+ 21 dur_minute: DIGITS 'M'
+ 22 | DIGITS 'M' dur_second
+
+ 23 dur_second: DIGITS 'S'
+
+ 24 dur_day: DIGITS 'D'
+
+ 25 dur_prefix: /* empty */
+ 26 | '+'
+ 27 | '-'
+
+ 28 duration_value: dur_prefix 'P' dur_date
+ 29 | dur_prefix 'P' dur_time
+ 30 | dur_prefix 'P' dur_week
+
+ 31 period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS utc_char_b
+ 32 | DIGITS TIME_CHAR DIGITS utc_char '/' duration_value
+
+ 33 plusminus: '+'
+ 34 | '-'
+
+ 35 utcoffset_value: plusminus INTNUMBER INTNUMBER
+ 36 | plusminus INTNUMBER INTNUMBER INTNUMBER
+
+
+Terminals, with rules where they appear
+
+$end (0) 0
+'+' (43) 26 33
+'-' (45) 27 34
+'/' (47) 31 32
+'D' (68) 24
+'H' (72) 19 20
+'M' (77) 21 22
+'P' (80) 28 29 30
+'S' (83) 23
+'W' (87) 15
+error (256) 6
+DIGITS (258) 7 12 15 19 20 21 22 23 24 31 32
+INTNUMBER (259) 35 36
+FLOATNUMBER (260)
+STRING (261)
+EOL (262)
+EQUALS (263)
+CHARACTER (264)
+COLON (265)
+COMMA (266)
+SEMICOLON (267)
+MINUS (268)
+TIMESEPERATOR (269)
+TRUE (270)
+FALSE (271)
+FREQ (272)
+BYDAY (273)
+BYHOUR (274)
+BYMINUTE (275)
+BYMONTH (276)
+BYMONTHDAY (277)
+BYSECOND (278)
+BYSETPOS (279)
+BYWEEKNO (280)
+BYYEARDAY (281)
+DAILY (282)
+MINUTELY (283)
+MONTHLY (284)
+SECONDLY (285)
+WEEKLY (286)
+HOURLY (287)
+YEARLY (288)
+INTERVAL (289)
+COUNT (290)
+UNTIL (291)
+WKST (292)
+MO (293)
+SA (294)
+SU (295)
+TU (296)
+WE (297)
+TH (298)
+FR (299)
+BIT8 (300)
+ACCEPTED (301)
+ADD (302)
+AUDIO (303)
+BASE64 (304)
+BINARY (305)
+BOOLEAN (306)
+BUSY (307)
+BUSYTENTATIVE (308)
+BUSYUNAVAILABLE (309)
+CALADDRESS (310)
+CANCEL (311)
+CANCELLED (312)
+CHAIR (313)
+CHILD (314)
+COMPLETED (315)
+CONFIDENTIAL (316)
+CONFIRMED (317)
+COUNTER (318)
+DATE (319)
+DATETIME (320)
+DECLINECOUNTER (321)
+DECLINED (322)
+DELEGATED (323)
+DISPLAY (324)
+DRAFT (325)
+DURATION (326)
+EMAIL (327)
+END (328)
+FINAL (329)
+FLOAT (330)
+FREE (331)
+GREGORIAN (332)
+GROUP (333)
+INDIVIDUAL (334)
+INPROCESS (335)
+INTEGER (336)
+NEEDSACTION (337)
+NONPARTICIPANT (338)
+OPAQUE (339)
+OPTPARTICIPANT (340)
+PARENT (341)
+PERIOD (342)
+PRIVATE (343)
+PROCEDURE (344)
+PUBLIC (345)
+PUBLISH (346)
+RECUR (347)
+REFRESH (348)
+REPLY (349)
+REQPARTICIPANT (350)
+REQUEST (351)
+RESOURCE (352)
+ROOM (353)
+SIBLING (354)
+START (355)
+TENTATIVE (356)
+TEXT (357)
+THISANDFUTURE (358)
+THISANDPRIOR (359)
+TIME (360)
+TRANSPAENT (361)
+UNKNOWN (362)
+UTCOFFSET (363)
+XNAME (364)
+ALTREP (365)
+CN (366)
+CUTYPE (367)
+DAYLIGHT (368)
+DIR (369)
+ENCODING (370)
+EVENT (371)
+FBTYPE (372)
+FMTTYPE (373)
+LANGUAGE (374)
+MEMBER (375)
+PARTSTAT (376)
+RANGE (377)
+RELATED (378)
+RELTYPE (379)
+ROLE (380)
+RSVP (381)
+SENTBY (382)
+STANDARD (383)
+URI (384)
+CHARSET (385)
+TIME_CHAR (386) 12 16 17 18 31 32
+UTC_CHAR (387) 9 11
+
+
+Nonterminals, with rules where they appear
+
+$accept (142)
+ on left: 0
+value (143)
+ on left: 1 2 3 4 5 6, on right: 0
+date_value (144)
+ on left: 7, on right: 1
+utc_char (145)
+ on left: 8 9, on right: 12 31 32
+utc_char_b (146)
+ on left: 10 11, on right: 31
+datetime_value (147)
+ on left: 12, on right: 2
+dur_date (148)
+ on left: 13 14, on right: 28
+dur_week (149)
+ on left: 15, on right: 30
+dur_time (150)
+ on left: 16 17 18, on right: 14 29
+dur_hour (151)
+ on left: 19 20, on right: 16
+dur_minute (152)
+ on left: 21 22, on right: 17 20
+dur_second (153)
+ on left: 23, on right: 18 22
+dur_day (154)
+ on left: 24, on right: 13 14
+dur_prefix (155)
+ on left: 25 26 27, on right: 28 29 30
+duration_value (156)
+ on left: 28 29 30, on right: 3 32
+period_value (157)
+ on left: 31 32, on right: 4
+plusminus (158)
+ on left: 33 34, on right: 35 36
+utcoffset_value (159)
+ on left: 35 36, on right: 5
+
+
+state 0
+
+ 0 $accept: . value $end
+
+ error shift, and go to state 1
+ DIGITS shift, and go to state 2
+ '+' shift, and go to state 3
+ '-' shift, and go to state 4
+
+ 'P' reduce using rule 25 (dur_prefix)
+
+ value go to state 5
+ date_value go to state 6
+ datetime_value go to state 7
+ dur_prefix go to state 8
+ duration_value go to state 9
+ period_value go to state 10
+ plusminus go to state 11
+ utcoffset_value go to state 12
+
+
+state 1
+
+ 6 value: error .
+
+ $default reduce using rule 6 (value)
+
+
+state 2
+
+ 7 date_value: DIGITS .
+ 12 datetime_value: DIGITS . TIME_CHAR DIGITS utc_char
+ 31 period_value: DIGITS . TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS utc_char_b
+ 32 | DIGITS . TIME_CHAR DIGITS utc_char '/' duration_value
+
+ TIME_CHAR shift, and go to state 13
+
+ $default reduce using rule 7 (date_value)
+
+
+state 3
+
+ 26 dur_prefix: '+' .
+ 33 plusminus: '+' .
+
+ INTNUMBER reduce using rule 33 (plusminus)
+ $default reduce using rule 26 (dur_prefix)
+
+
+state 4
+
+ 27 dur_prefix: '-' .
+ 34 plusminus: '-' .
+
+ INTNUMBER reduce using rule 34 (plusminus)
+ $default reduce using rule 27 (dur_prefix)
+
+
+state 5
+
+ 0 $accept: value . $end
+
+ $end shift, and go to state 14
+
+
+state 6
+
+ 1 value: date_value .
+
+ $default reduce using rule 1 (value)
+
+
+state 7
+
+ 2 value: datetime_value .
+
+ $default reduce using rule 2 (value)
+
+
+state 8
+
+ 28 duration_value: dur_prefix . 'P' dur_date
+ 29 | dur_prefix . 'P' dur_time
+ 30 | dur_prefix . 'P' dur_week
+
+ 'P' shift, and go to state 15
+
+
+state 9
+
+ 3 value: duration_value .
+
+ $default reduce using rule 3 (value)
+
+
+state 10
+
+ 4 value: period_value .
+
+ $default reduce using rule 4 (value)
+
+
+state 11
+
+ 35 utcoffset_value: plusminus . INTNUMBER INTNUMBER
+ 36 | plusminus . INTNUMBER INTNUMBER INTNUMBER
+
+ INTNUMBER shift, and go to state 16
+
+
+state 12
+
+ 5 value: utcoffset_value .
+
+ $default reduce using rule 5 (value)
+
+
+state 13
+
+ 12 datetime_value: DIGITS TIME_CHAR . DIGITS utc_char
+ 31 period_value: DIGITS TIME_CHAR . DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS utc_char_b
+ 32 | DIGITS TIME_CHAR . DIGITS utc_char '/' duration_value
+
+ DIGITS shift, and go to state 17
+
+
+state 14
+
+ 0 $accept: value $end .
+
+ $default accept
+
+
+state 15
+
+ 28 duration_value: dur_prefix 'P' . dur_date
+ 29 | dur_prefix 'P' . dur_time
+ 30 | dur_prefix 'P' . dur_week
+
+ DIGITS shift, and go to state 18
+ TIME_CHAR shift, and go to state 19
+
+ dur_date go to state 20
+ dur_week go to state 21
+ dur_time go to state 22
+ dur_day go to state 23
+
+
+state 16
+
+ 35 utcoffset_value: plusminus INTNUMBER . INTNUMBER
+ 36 | plusminus INTNUMBER . INTNUMBER INTNUMBER
+
+ INTNUMBER shift, and go to state 24
+
+
+state 17
+
+ 12 datetime_value: DIGITS TIME_CHAR DIGITS . utc_char
+ 31 period_value: DIGITS TIME_CHAR DIGITS . utc_char '/' DIGITS TIME_CHAR DIGITS utc_char_b
+ 32 | DIGITS TIME_CHAR DIGITS . utc_char '/' duration_value
+
+ UTC_CHAR shift, and go to state 25
+
+ $default reduce using rule 8 (utc_char)
+
+ utc_char go to state 26
+
+
+state 18
+
+ 15 dur_week: DIGITS . 'W'
+ 24 dur_day: DIGITS . 'D'
+
+ 'W' shift, and go to state 27
+ 'D' shift, and go to state 28
+
+
+state 19
+
+ 16 dur_time: TIME_CHAR . dur_hour
+ 17 | TIME_CHAR . dur_minute
+ 18 | TIME_CHAR . dur_second
+
+ DIGITS shift, and go to state 29
+
+ dur_hour go to state 30
+ dur_minute go to state 31
+ dur_second go to state 32
+
+
+state 20
+
+ 28 duration_value: dur_prefix 'P' dur_date .
+
+ $default reduce using rule 28 (duration_value)
+
+
+state 21
+
+ 30 duration_value: dur_prefix 'P' dur_week .
+
+ $default reduce using rule 30 (duration_value)
+
+
+state 22
+
+ 29 duration_value: dur_prefix 'P' dur_time .
+
+ $default reduce using rule 29 (duration_value)
+
+
+state 23
+
+ 13 dur_date: dur_day .
+ 14 | dur_day . dur_time
+
+ TIME_CHAR shift, and go to state 19
+
+ $default reduce using rule 13 (dur_date)
+
+ dur_time go to state 33
+
+
+state 24
+
+ 35 utcoffset_value: plusminus INTNUMBER INTNUMBER .
+ 36 | plusminus INTNUMBER INTNUMBER . INTNUMBER
+
+ INTNUMBER shift, and go to state 34
+
+ $default reduce using rule 35 (utcoffset_value)
+
+
+state 25
+
+ 9 utc_char: UTC_CHAR .
+
+ $default reduce using rule 9 (utc_char)
+
+
+state 26
+
+ 12 datetime_value: DIGITS TIME_CHAR DIGITS utc_char .
+ 31 period_value: DIGITS TIME_CHAR DIGITS utc_char . '/' DIGITS TIME_CHAR DIGITS utc_char_b
+ 32 | DIGITS TIME_CHAR DIGITS utc_char . '/' duration_value
+
+ '/' shift, and go to state 35
+
+ $default reduce using rule 12 (datetime_value)
+
+
+state 27
+
+ 15 dur_week: DIGITS 'W' .
+
+ $default reduce using rule 15 (dur_week)
+
+
+state 28
+
+ 24 dur_day: DIGITS 'D' .
+
+ $default reduce using rule 24 (dur_day)
+
+
+state 29
+
+ 19 dur_hour: DIGITS . 'H'
+ 20 | DIGITS . 'H' dur_minute
+ 21 dur_minute: DIGITS . 'M'
+ 22 | DIGITS . 'M' dur_second
+ 23 dur_second: DIGITS . 'S'
+
+ 'H' shift, and go to state 36
+ 'M' shift, and go to state 37
+ 'S' shift, and go to state 38
+
+
+state 30
+
+ 16 dur_time: TIME_CHAR dur_hour .
+
+ $default reduce using rule 16 (dur_time)
+
+
+state 31
+
+ 17 dur_time: TIME_CHAR dur_minute .
+
+ $default reduce using rule 17 (dur_time)
+
+
+state 32
+
+ 18 dur_time: TIME_CHAR dur_second .
+
+ $default reduce using rule 18 (dur_time)
+
+
+state 33
+
+ 14 dur_date: dur_day dur_time .
+
+ $default reduce using rule 14 (dur_date)
+
+
+state 34
+
+ 36 utcoffset_value: plusminus INTNUMBER INTNUMBER INTNUMBER .
+
+ $default reduce using rule 36 (utcoffset_value)
+
+
+state 35
+
+ 31 period_value: DIGITS TIME_CHAR DIGITS utc_char '/' . DIGITS TIME_CHAR DIGITS utc_char_b
+ 32 | DIGITS TIME_CHAR DIGITS utc_char '/' . duration_value
+
+ DIGITS shift, and go to state 39
+ '+' shift, and go to state 40
+ '-' shift, and go to state 41
+
+ $default reduce using rule 25 (dur_prefix)
+
+ dur_prefix go to state 8
+ duration_value go to state 42
+
+
+state 36
+
+ 19 dur_hour: DIGITS 'H' .
+ 20 | DIGITS 'H' . dur_minute
+
+ DIGITS shift, and go to state 43
+
+ $default reduce using rule 19 (dur_hour)
+
+ dur_minute go to state 44
+
+
+state 37
+
+ 21 dur_minute: DIGITS 'M' .
+ 22 | DIGITS 'M' . dur_second
+
+ DIGITS shift, and go to state 45
+
+ $default reduce using rule 21 (dur_minute)
+
+ dur_second go to state 46
+
+
+state 38
+
+ 23 dur_second: DIGITS 'S' .
+
+ $default reduce using rule 23 (dur_second)
+
+
+state 39
+
+ 31 period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS . TIME_CHAR DIGITS utc_char_b
+
+ TIME_CHAR shift, and go to state 47
+
+
+state 40
+
+ 26 dur_prefix: '+' .
+
+ $default reduce using rule 26 (dur_prefix)
+
+
+state 41
+
+ 27 dur_prefix: '-' .
+
+ $default reduce using rule 27 (dur_prefix)
+
+
+state 42
+
+ 32 period_value: DIGITS TIME_CHAR DIGITS utc_char '/' duration_value .
+
+ $default reduce using rule 32 (period_value)
+
+
+state 43
+
+ 21 dur_minute: DIGITS . 'M'
+ 22 | DIGITS . 'M' dur_second
+
+ 'M' shift, and go to state 37
+
+
+state 44
+
+ 20 dur_hour: DIGITS 'H' dur_minute .
+
+ $default reduce using rule 20 (dur_hour)
+
+
+state 45
+
+ 23 dur_second: DIGITS . 'S'
+
+ 'S' shift, and go to state 38
+
+
+state 46
+
+ 22 dur_minute: DIGITS 'M' dur_second .
+
+ $default reduce using rule 22 (dur_minute)
+
+
+state 47
+
+ 31 period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR . DIGITS utc_char_b
+
+ DIGITS shift, and go to state 48
+
+
+state 48
+
+ 31 period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS . utc_char_b
+
+ UTC_CHAR shift, and go to state 49
+
+ $default reduce using rule 10 (utc_char_b)
+
+ utc_char_b go to state 50
+
+
+state 49
+
+ 11 utc_char_b: UTC_CHAR .
+
+ $default reduce using rule 11 (utc_char_b)
+
+
+state 50
+
+ 31 period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS utc_char_b .
+
+ $default reduce using rule 31 (period_value)
diff --git a/src/plugins/vcalendar/libical/libical/icalyacc.y b/src/plugins/vcalendar/libical/libical/icalyacc.y
@@ -0,0 +1,405 @@
+%{
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalitip.y
+ CREATOR: eric 10 June 1999
+
+ DESCRIPTION:
+
+ $Id$
+ $Locker$
+
+ (C) COPYRIGHT 1999 Eric Busboom
+ http://www.softwarestudio.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+ The original author is Eric Busboom
+ The original code is icalitip.y
+
+
+
+ =======================================================================*/
+
+#include <stdlib.h>
+#include <string.h> /* for strdup() */
+#include "icalparser.h"
+#include "pvl.h"
+
+icalvalue *icalparser_yy_value; /* Current Value */
+
+void ical_yyerror(char* s);
+void icalparser_clear_flex_input();
+int ical_yy_lex(void);
+
+/* Globals for UTCOFFSET values */
+int utc;
+int utc_b;
+int utcsign;
+
+/* Globals for DURATION values */
+struct icaldurationtype duration;
+
+/* Globals for TRIGGER values */
+struct icaltriggertype trigger;
+
+void copy_list(short* array, size_t size);
+void add_prop(icalproperty_kind);
+void icalparser_fill_date(struct tm* t, char* dstr);
+void icalparser_fill_time(struct tm* t, char* tstr);
+void set_value_type(icalvalue_kind kind);
+void set_parser_value_state();
+struct icaltimetype fill_datetime(char* d, char* t);
+void ical_yy_error(char *s); /* Don't know why I need this.... */
+int yylex(void); /* Or this. */
+
+
+
+/* Set the state of the lexer so it will interpret values ( iCAL
+ VALUEs, that is, ) correctly. */
+
+%}
+
+%union {
+ float v_float;
+ int v_int;
+ char* v_string;
+}
+
+
+ /* Renaming hack */
+
+/*
+#define yymaxdepth ical_yy_maxdepth
+#define yyparse ical_yy_parse
+#define yyerror ical_yy_error
+#define yylval ical_yy_lval
+#define yychar ical_yy_char
+#define yydebug ical_yy_debug
+#define yypact ical_yy_pact
+#define yyr1 ical_yy_r1
+#define yyr2 ical_yy_r2
+#define yydef ical_yy_def
+#define yychk ical_yy_chk
+#define yypgo ical_yy_pgo
+#define yyact ical_yy_act
+#define yyexca ical_yy_exca
+#define yyerrflag ical_yy_errflag
+#define yynerrs ical_yy_nerrs
+#define yyps ical_yy_ps
+#define yypv ical_yy_pv
+#define yys ical_yy_s
+#define yy_yys ical_yy_yys
+#define yystate ical_yy_state
+#define yytmp ical_yy_tmp
+#define yyv ical_yy_v
+#define yy_yyv ical_yy_yyv
+#define yyval ical_yy_val
+#define yylloc ical_yy_lloc
+#define yyreds ical_yy_reds
+#define yytoks ical_yy_toks
+#define yylhs ical_yy_yylhs
+#define yylen ical_yy_yylen
+#define yydefred ical_yy_yydefred
+#define yydgoto ical_yy_yydgoto
+#define yydefred ical_yy_yydefred
+#define yydgoto ical_yy_yydgoto
+#define yysindex ical_yy_yysindex
+#define yyrindex ical_yy_yyrindex
+#define yygindex ical_yy_yygindex
+#define yytable ical_yy_yytable
+#define yycheck ical_yy_yycheck
+#define yyname ical_yy_yyname
+#define yyrule ical_yy_yyrule
+#define yy_scan_bytes ical_yy_scan_bytes
+#define yy_scan_string ical_yy_scan_string
+#define yy_scan_buffer ical_yy_scan_buffer
+*/
+
+/* These are redefined with the -P option to flex */
+/*
+#define yy_create_buffer ical_yy_create_buffer
+#define yy_delete_buffer ical_yy_delete_buffer
+#define yy_flex_debug ical_yy_flex_debug
+#define yy_init_buffer ical_yy_init_buffer
+#define yy_flush_buffer ical_yy_flush_buffer
+#define yy_load_buffer_state ical_yy_load_buffer_state
+#define yy_switch_to_buffer ical_yy_switch_to_buffer
+#define yyin ical_yyin
+#define yyleng ical_yyleng
+#define yylex ical_yylex
+#define yylineno ical_yylineno
+#define yyout ical_yyout
+#define yyrestart ical_yyrestart
+#define yytext ical_yytext
+#define yywrap ical_yywrap
+*/
+
+
+%token <v_string> DIGITS
+%token <v_int> INTNUMBER
+%token <v_float> FLOATNUMBER
+%token <v_string> STRING
+%token EOL EQUALS CHARACTER COLON COMMA SEMICOLON MINUS TIMESEPERATOR
+
+%token TRUE FALSE
+
+%token FREQ BYDAY BYHOUR BYMINUTE BYMONTH BYMONTHDAY BYSECOND BYSETPOS BYWEEKNO
+%token BYYEARDAY DAILY MINUTELY MONTHLY SECONDLY WEEKLY HOURLY YEARLY
+%token INTERVAL COUNT UNTIL WKST MO SA SU TU WE TH FR
+
+%token BIT8 ACCEPTED ADD AUDIO BASE64 BINARY BOOLEAN BUSY BUSYTENTATIVE
+%token BUSYUNAVAILABLE CALADDRESS CANCEL CANCELLED CHAIR CHILD COMPLETED
+%token CONFIDENTIAL CONFIRMED COUNTER DATE DATETIME DECLINECOUNTER DECLINED
+%token DELEGATED DISPLAY DRAFT DURATION EMAIL END FINAL FLOAT FREE GREGORIAN
+%token GROUP INDIVIDUAL INPROCESS INTEGER NEEDSACTION NONPARTICIPANT
+%token OPAQUE OPTPARTICIPANT PARENT PERIOD PRIVATE PROCEDURE PUBLIC PUBLISH
+%token RECUR REFRESH REPLY REQPARTICIPANT REQUEST RESOURCE ROOM SIBLING
+%token START TENTATIVE TEXT THISANDFUTURE THISANDPRIOR TIME TRANSPAENT
+%token UNKNOWN UTCOFFSET XNAME
+
+%token ALTREP CN CUTYPE DAYLIGHT DIR ENCODING EVENT FBTYPE FMTTYPE LANGUAGE
+%token MEMBER PARTSTAT RANGE RELATED RELTYPE ROLE RSVP SENTBY STANDARD URI
+%token CHARSET
+
+%token TIME_CHAR UTC_CHAR
+
+
+%%
+
+value:
+ date_value
+ | datetime_value
+ | duration_value
+ | period_value
+ | utcoffset_value
+ | error {
+ icalparser_yy_value = 0;
+ icalparser_clear_flex_input();
+ yyclearin;
+ }
+
+
+date_value: DIGITS
+ {
+ struct icaltimetype stm;
+
+ stm = fill_datetime($1,0);
+
+ stm.hour = -1;
+ stm.minute = -1;
+ stm.second = -1;
+ stm.is_utc = 0;
+ stm.is_date = 1;
+
+ icalparser_yy_value = icalvalue_new_date(stm);
+ }
+
+utc_char:
+ /*empty*/ {utc = 0;}
+ | UTC_CHAR {utc = 1;}
+
+/* This is used in the period_value, where there may be two utc characters per rule. */
+utc_char_b:
+ /*empty*/ {utc_b = 0;}
+ | UTC_CHAR {utc_b = 1;}
+
+datetime_value:
+ DIGITS TIME_CHAR DIGITS utc_char
+ {
+ struct icaltimetype stm;
+ stm = fill_datetime($1, $3);
+ stm.is_utc = utc;
+ stm.is_date = 0;
+
+ icalparser_yy_value =
+ icalvalue_new_datetime(stm);
+ }
+
+
+/* Duration */
+
+
+dur_date: dur_day
+ | dur_day dur_time
+
+dur_week: DIGITS 'W'
+ {
+ duration.weeks = atoi($1);
+ }
+
+dur_time: TIME_CHAR dur_hour
+ {
+ }
+ | TIME_CHAR dur_minute
+ {
+ }
+ | TIME_CHAR dur_second
+ {
+ }
+
+dur_hour: DIGITS 'H'
+ {
+ duration.hours = atoi($1);
+ }
+ | DIGITS 'H' dur_minute
+ {
+ duration.hours = atoi($1);
+ }
+
+dur_minute: DIGITS 'M'
+ {
+ duration.minutes = atoi($1);
+ }
+ | DIGITS 'M' dur_second
+ {
+ duration.minutes = atoi($1);
+ }
+
+dur_second: DIGITS 'S'
+ {
+ duration.seconds = atoi($1);
+ }
+
+dur_day: DIGITS 'D'
+ {
+ duration.days = atoi($1);
+ }
+
+dur_prefix: /* empty */
+ {
+ duration.is_neg = 0;
+ }
+ | '+'
+ {
+ duration.is_neg = 0;
+ }
+ | '-'
+ {
+ duration.is_neg = 1;
+ }
+
+duration_value: dur_prefix 'P' dur_date
+ {
+ icalparser_yy_value = icalvalue_new_duration(duration);
+ memset(&duration,0, sizeof(duration));
+ }
+ | dur_prefix 'P' dur_time
+ {
+ icalparser_yy_value = icalvalue_new_duration(duration);
+ memset(&duration,0, sizeof(duration));
+ }
+ | dur_prefix 'P' dur_week
+ {
+ icalparser_yy_value = icalvalue_new_duration(duration);
+ memset(&duration,0, sizeof(duration));
+ }
+
+
+/* Period */
+
+period_value: DIGITS TIME_CHAR DIGITS utc_char '/' DIGITS TIME_CHAR DIGITS utc_char_b
+ {
+ struct icalperiodtype p;
+
+ p.start = fill_datetime($1,$3);
+ p.start.is_utc = utc;
+ p.start.is_date = 0;
+
+
+ p.end = fill_datetime($6,$8);
+ p.end.is_utc = utc_b;
+ p.end.is_date = 0;
+
+ p.duration.days = -1;
+ p.duration.weeks = -1;
+ p.duration.hours = -1;
+ p.duration.minutes = -1;
+ p.duration.seconds = -1;
+
+ icalparser_yy_value = icalvalue_new_period(p);
+ }
+ | DIGITS TIME_CHAR DIGITS utc_char '/' duration_value
+ {
+ struct icalperiodtype p;
+
+ p.start = fill_datetime($1,$3);
+ p.start.is_utc = utc;
+ p.start.is_date = 0;
+
+ p.end.year = -1;
+ p.end.month = -1;
+ p.end.day = -1;
+ p.end.hour = -1;
+ p.end.minute = -1;
+ p.end.second = -1;
+
+ /* The duration_value rule setes the global 'duration'
+ variable, but it also creates a new value in
+ icalparser_yy_value. So, free that, then copy
+ 'duration' into the icalperiodtype struct. */
+
+ p.duration = icalvalue_get_duration(icalparser_yy_value);
+ icalvalue_free(icalparser_yy_value);
+ icalparser_yy_value = 0;
+
+ icalparser_yy_value = icalvalue_new_period(p);
+
+ }
+
+
+trigger:
+
+
+
+/* UTC Offset */
+
+plusminus: '+' { utcsign = 1; }
+ | '-' { utcsign = -1; }
+
+utcoffset_value:
+ plusminus INTNUMBER INTNUMBER
+ {
+ icalparser_yy_value = icalvalue_new_utcoffset( utcsign * ($2*3600) + ($3*60) );
+ }
+
+ | plusminus INTNUMBER INTNUMBER INTNUMBER
+ {
+ icalparser_yy_value = icalvalue_new_utcoffset(utcsign * ($2*3600) + ($3*60) +($4));
+ }
+
+%%
+
+struct icaltimetype fill_datetime(char* datestr, char* timestr)
+{
+ struct icaltimetype stm;
+
+ memset(&stm,0,sizeof(stm));
+
+ if (datestr != 0){
+ sscanf(datestr,"%4d%2d%2d",&(stm.year), &(stm.month),
+ &(stm.day));
+ }
+
+ if (timestr != 0){
+ sscanf(timestr,"%2d%2d%2d", &(stm.hour), &(stm.minute),
+ &(stm.second));
+ }
+
+ return stm;
+
+}
+
+void ical_yyerror(char* s)
+{
+ /*fprintf(stderr,"Parse error \'%s\'\n", s);*/
+}
+
diff --git a/src/plugins/vcalendar/libical/libical/pvl.c b/src/plugins/vcalendar/libical/libical/pvl.c
@@ -0,0 +1,762 @@
+/*======================================================================
+ FILE: pvl.c
+ CREATOR: eric November, 1995
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pvl.h"
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+
+
+
+/*
+ struct pvl_list_t
+
+ The list structure. This is the hanlde for the entire list
+
+ This type is also private. Use pvl_list instead
+
+ */
+
+typedef struct pvl_list_t
+{
+ int MAGIC; /* Magic Identifier */
+ struct pvl_elem_t *head; /* Head of list */
+ struct pvl_elem_t *tail; /* Tail of list */
+ int count; /* Number of items in the list */
+ struct pvl_elem_t *p; /* Pointer used for iterators */
+} pvl_list_t;
+
+
+
+
+/* This global is incremented for each call to pvl_new_element(); it gives each
+ * list a unique identifer */
+
+int pvl_elem_count = 0;
+int pvl_list_count = 0;
+
+
+/*----------------------------------------------------------------------
+ Function: pvl_list pvl_newlist()
+
+ Purpose:
+
+ Creates a new list, clears the pointers and assigns a magic number
+
+ Returns:
+
+ Pointer to the new list
+ 0 if there is no available memory.
+ *----------------------------------------------------------------------*/
+
+pvl_list
+pvl_newlist()
+{
+ struct pvl_list_t *L;
+
+ if ( ( L = (struct pvl_list_t*)malloc(sizeof(struct pvl_list_t))) == 0)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ L->MAGIC = pvl_list_count;
+ pvl_list_count++;
+ L->head = 0;
+ L->tail = 0;
+ L->count = 0;
+ L->p = 0;
+
+ return L;
+}
+
+void
+pvl_free(pvl_list l)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+
+ pvl_clear(l);
+
+ free(L);
+}
+
+/*----------------------------------------------------------------------
+ Function: pvl_new_element(void *d, struct pvl_elem_t *next,struct pvl_elem_t *prior)
+
+ Purpose:
+ Creates a new list element, assigns a magic number, and assigns
+ the next and previous pointers.
+
+ Passing in the next and previous points may seem odd, but it allos the user
+ to set them while keeping the internal data hidden. In nearly all cases,
+ the user is the pvl library itself.
+
+ Parameters:
+
+ d The data item to be stored in the list
+ next Pointer value to assign to the member "next"
+ prior Pointer value to assign to the member "prior"
+
+ Returns:
+
+ A pointer to the new element.
+ 0 if there is no memory available.
+
+ *----------------------------------------------------------------------*/
+
+pvl_elem
+pvl_new_element(void *d, pvl_elem next,pvl_elem prior)
+{
+ struct pvl_elem_t *E;
+
+ if ( ( E = (struct pvl_elem_t*)malloc(sizeof(struct pvl_elem_t))) == 0)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ E->MAGIC = pvl_elem_count++;
+ E->d = d;
+ E->next = next;
+ E->prior = prior;
+
+ return (pvl_elem)E;
+}
+
+/*----------------------------------------------------------------------
+ Function: pvl_unshift(pvl_list l,void *d)
+
+ Purpose:
+
+ Add a new element to the from of the list
+
+ Parameters:
+
+ l The list to add the item to
+ d Pointer to the item to add
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+void
+pvl_unshift(pvl_list l,void *d)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+ struct pvl_elem_t *E = pvl_new_element(d,L->head,0);
+
+ if (E->next != 0)
+ {
+ /* Link the head node to it */
+ E->next->prior = E;
+ }
+
+ /* move the head */
+ L->head = E;
+
+ /* maybe move the tail */
+
+ if (L->tail == 0)
+ {
+ L->tail = E;
+ }
+
+ L->count++;
+}
+
+/*----------------------------------------------------------------------
+ Function: pvl_shift(pvl_list l)
+
+ Purpose:
+
+ Remove an element from the front of the list
+
+ Parameters:
+
+ l The list to operate on
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+void*
+pvl_shift(pvl_list l)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+
+ if (L->head == 0)
+ {
+ return 0;
+ }
+
+ return pvl_remove(l,(void*)L->head);
+
+}
+
+/*----------------------------------------------------------------------
+ Function: void pvl_push(pvl_list l,void *d)
+
+ Purpose:
+
+ Add a new item to the tail of the list
+
+ Paramters:
+
+ l The list to operate on
+ d Pointer to the item to add
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+void
+pvl_push(pvl_list l,void *d)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+ struct pvl_elem_t *E = pvl_new_element(d,0,L->tail);
+
+ /* These are done in pvl_new_element
+ E->next = 0;
+ E->prior = L->tail;
+ */
+
+ if (L->tail != 0)
+ {
+ L->tail->next = E;
+ }
+
+ if (L->head == 0)
+ {
+ L->head = E;
+ }
+
+ L->tail = E;
+
+ L->count++;
+
+}
+
+/*----------------------------------------------------------------------
+ Function: void* pvl_pop(pvl_list l)
+
+ Purpose:
+
+ Remove an element from the tail of the list
+
+ Paramters:
+
+ l The list to operate on
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+void*
+pvl_pop(pvl_list l)
+{
+
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+
+ if ( L->tail == 0)
+ {
+ return 0;
+ }
+
+ return pvl_remove(l,(void*) L->tail);;
+
+}
+
+
+/*----------------------------------------------------------------------
+ Function: void pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d)
+
+ Purpose:
+
+ Add a new item to a list that is ordered by a comparison function.
+ This routine assumes that the list is properly ordered.
+
+ l The list to operate on
+ f Pointer to a comparison function
+ d Pointer to data to pass to the comparison function
+
+ Returns:
+
+ void
+
+ *----------------------------------------------------------------------*/
+
+void
+pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+
+ struct pvl_elem_t *P;
+
+ L->count++;
+
+ /* Empty list, add to head */
+
+ if(L->head == 0)
+ {
+ pvl_unshift(l,d);
+ return;
+ }
+
+ /* smaller than head, add to head */
+
+ if ( ((*f)(d,L->head->d)) <= 0)
+ {
+ pvl_unshift(l,d);
+ return;
+ }
+
+ /* larger than tail, add to tail */
+ if ( (*f)(d,L->tail->d) >= 0)
+ {
+ pvl_push(l,d);
+ return;
+ }
+
+
+ /* Search for the first element that is smaller, and add before it */
+
+ for (P=L->head; P != 0; P = P->next)
+ {
+ if ( (*f)(P->d,d) >= 0)
+ {
+ pvl_insert_before(l,P,d);
+ return;
+ }
+ }
+
+ /* badness, choke */
+
+ assert(0);
+
+}
+
+/*----------------------------------------------------------------------
+ Function: void pvl_insert_after(pvl_list l,pvl_elem p,void *d)
+
+ Purpose:
+
+ Add a new item after the referenced element.
+
+ Parameters:
+
+ l The list to operate on
+ p The list element to add the item after
+ d Pointer to the item to add.
+
+ Returns:
+
+ void
+
+ *----------------------------------------------------------------------*/
+
+void
+pvl_insert_after(pvl_list l,pvl_elem p,void *d)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+ struct pvl_elem_t *P = (struct pvl_elem_t *)p;
+ struct pvl_elem_t *E = 0;
+
+ L->count++;
+
+ if (P == 0)
+ {
+ pvl_unshift(l,d);
+ return;
+ }
+
+ if ( P == L->tail)
+ {
+ E = pvl_new_element(d,0,P);
+ L->tail = E;
+ E->prior->next = E;
+ }
+ else
+ {
+ E = pvl_new_element(d,P->next,P);
+ E->next->prior = E;
+ E->prior->next = E;
+ }
+}
+
+/*----------------------------------------------------------------------
+ Function: void pvl_insert_before(pvl_list l,pvl_elem p,void *d)
+
+ Purpose:
+
+ Add an item after a referenced item
+
+ Parameters:
+
+ l The list to operate on
+ p The list element to add the item before
+ d Pointer to the data to be added.
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+void
+pvl_insert_before(pvl_list l,pvl_elem p,void *d)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+ struct pvl_elem_t *P = (struct pvl_elem_t *)p;
+ struct pvl_elem_t *E = 0;
+
+ L->count++;
+
+ if (P == 0)
+ {
+ pvl_unshift(l,d);
+ return;
+ }
+
+ if ( P == L->head)
+ {
+ E = pvl_new_element(d,P,0);
+ E->next->prior = E;
+ L->head = E;
+ }
+ else
+ {
+ E = pvl_new_element(d,P,P->prior);
+ E->prior->next = E;
+ E->next->prior = E;
+ }
+}
+
+/*----------------------------------------------------------------------
+ Function: void pvl_remove(pvl_list l,pvl_elem e)
+
+ Purpose:
+
+ Remove the referenced item from the list
+
+ This routine will free the element, but not the data item that the
+ element contains.
+
+ Parameters:
+
+ l The list to operate on
+ e The element to remove.
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+void*
+pvl_remove(pvl_list l,pvl_elem e)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+ struct pvl_elem_t *E = (struct pvl_elem_t *)e;
+ void* data;
+
+ if (E == L->head)
+ {
+ if (E->next != 0)
+ {
+ E->next->prior = 0;
+ L->head = E->next;
+ } else {
+ /* E Also points to tail -> only one element in list */
+ L->tail = 0;
+ L->head = 0;
+ }
+ }
+ else if (E == L->tail)
+ {
+ if (E->prior != 0)
+ {
+ E->prior->next = 0;
+ L->tail = E->prior;
+ } else {
+ /* E points to the head, so it was the last element */
+ /* This case should be taken care of in the previous clause */
+ L->head = 0;
+ L->tail = 0;
+ }
+ }
+ else
+ {
+ E->prior->next = E->next;
+ E->next->prior = E->prior;
+ }
+
+
+ L->count--;
+
+ data = E->d;
+
+ E->prior = 0;
+ E->next = 0;
+ E->d = 0;
+
+ free(E);
+
+ return data;
+
+}
+
+/*----------------------------------------------------------------------
+ Function: pvl_elem pvl_find(pvl_list l,pvl_findf f,void* v)
+
+ Purpose:
+
+ Return a pointer to data that satisfies a function
+
+ This routine will interate through the entire list and call the
+ find function for each item. It will break and return a pointer to the
+ data that causes the find function to return 1.
+
+ Parameters:
+
+ l The list to operate on
+ f Pointer to the find function
+ v Pointer to constant data to pass into the function
+
+ Returns:
+
+ Pointer to the element that the find function found.
+
+ *----------------------------------------------------------------------*/
+
+pvl_elem
+pvl_find(pvl_list l,pvl_findf f,void* v)
+{
+ pvl_elem e;
+
+ for (e=pvl_head(l); e!= 0; e = pvl_next(e))
+ {
+ if ( (*f)(((struct pvl_elem_t *)e)->d,v) == 1)
+ {
+ /* Save this elem for a call to find_next */
+ ((struct pvl_list_t *)l)->p = e;
+ return e;
+ }
+ }
+
+ return 0;
+
+}
+/*----------------------------------------------------------------------
+ Function: void* pvl_find_next(pvl_list l,pvl_findf f,void* v)
+
+ Purpose:
+
+ Like pvl_find(), but continues the search where the last find() or
+ find_next() left off
+
+ Parameters:
+
+ l The list to operate on
+ f Pointer to the find function
+ v Pointer to constant data to pass into the function
+
+ Returns:
+
+ Pointer to the element that the find function found.
+
+ *----------------------------------------------------------------------*/
+
+pvl_elem
+pvl_find_next(pvl_list l,pvl_findf f,void* v)
+{
+
+ pvl_elem e;
+
+ for (e=pvl_head(l); e!= 0; e = pvl_next(e))
+ {
+ if ( (*f)(((struct pvl_elem_t *)e)->d,v) == 1)
+ {
+ /* Save this elem for a call to find_next */
+ ((struct pvl_list_t *)l)->p = e;
+ return e;
+ }
+ }
+
+ return 0;
+
+}
+
+/*----------------------------------------------------------------------
+ Function: void pvl_clear(pvl_list l)
+
+ Purpose:
+
+ Remove the all the elements in the list. The does not free the data items
+ the elements hold.
+
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+void
+pvl_clear(pvl_list l)
+{
+ pvl_elem e = pvl_head(l);
+ pvl_elem next;
+
+ if (e == 0) {
+ return;
+ }
+
+ while(e != 0)
+ {
+ next = pvl_next(e);
+ pvl_remove(l,e);
+ e = next;
+ }
+}
+
+/*----------------------------------------------------------------------
+ Function: int pvl_count(pvl_list l)
+
+ Purpose:
+
+ Returns the number of items in the list.
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+int
+pvl_count(pvl_list l)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+
+ return L->count;
+}
+
+
+/*----------------------------------------------------------------------
+ Function: pvl_elem pvl_next(pvl_elem e)
+
+ Purpose:
+ Returns a pointer to the given element
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+pvl_elem
+pvl_next(pvl_elem e)
+{
+ struct pvl_elem_t *E = (struct pvl_elem_t *)e;
+
+ if (E == 0){
+ return 0;
+ }
+
+ return (pvl_elem)E->next;
+}
+
+/*----------------------------------------------------------------------
+ Function: pvl_elem pvl_prior(pvl_elem e)
+
+ Purpose:
+
+ Returns a pointer to the element previous to the element given.
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+pvl_elem
+pvl_prior(pvl_elem e)
+{
+ struct pvl_elem_t *E = (struct pvl_elem_t *)e;
+
+ return (pvl_elem)E->prior;
+}
+
+/*----------------------------------------------------------------------
+ Function: pvl_elem pvl_head(pvl_list l )
+
+ Purpose:
+
+ Returns a pointer to the first item in the list.
+
+ Returns:
+ *----------------------------------------------------------------------*/
+pvl_elem
+pvl_head(pvl_list l )
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+ if (L == NULL)
+ return NULL;
+ return (pvl_elem)L->head;
+}
+
+/*----------------------------------------------------------------------
+ Function: pvl_elem pvl_tail(pvl_list l)
+
+ Purpose:
+
+ Returns a pointer to the last item in the list.
+
+ Returns:
+ *----------------------------------------------------------------------*/
+pvl_elem
+pvl_tail(pvl_list l)
+{
+ struct pvl_list_t *L = (struct pvl_list_t *)l;
+ return (pvl_elem)L->tail;
+}
+
+/*----------------------------------------------------------------------
+ Function:
+
+
+ Purpose:
+
+
+ Returns:
+ *----------------------------------------------------------------------*/
+
+#ifndef PVL_USE_MACROS
+void*
+pvl_data(pvl_elem e)
+{
+ struct pvl_elem_t *E = (struct pvl_elem_t *)e;
+
+ if ( e == 0){
+ return 0;
+ }
+
+ return E->d;
+}
+#endif
+
+/*----------------------------------------------------------------------
+ Function: void pvl_apply(pvl_list l,pvl_applyf f, void *v)
+
+ Purpose:
+
+ Call a function for every item in the list.
+
+ Paramters:
+
+ l The list to operate on
+ f Pointer to the function to call
+ v Data to pass to the function on every iteration
+
+ Returns:
+
+ void
+ *----------------------------------------------------------------------*/
+
+void
+pvl_apply(pvl_list l,pvl_applyf f, void *v)
+{
+ pvl_elem e;
+
+ for (e=pvl_head(l); e!= 0; e = pvl_next(e))
+ {
+ (*f)(((struct pvl_elem_t *)e)->d,v);
+ }
+
+}
diff --git a/src/plugins/vcalendar/libical/libical/pvl.h b/src/plugins/vcalendar/libical/libical/pvl.h
@@ -0,0 +1,94 @@
+/*======================================================================
+ FILE: pvl.h
+ CREATOR: eric November, 1995
+
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+======================================================================*/
+
+
+#ifndef __PVL_H__
+#define __PVL_H__
+
+typedef void* pvl_list;
+typedef void* pvl_elem;
+
+/*
+ struct pvl_elem_t
+
+ This type is private. Always use pvl_elem instead. The struct would
+ not even appear in this header except to make code in the USE_MACROS
+ blocks work
+
+ */
+typedef struct pvl_elem_t
+{
+ int MAGIC; /* Magic Identifier */
+ void *d; /* Pointer to data user is storing */
+ struct pvl_elem_t *next; /* Next element */
+ struct pvl_elem_t *prior; /* prior element */
+} pvl_elem_t;
+
+
+
+/* This global is incremented for each call to pvl_new_element(); it gives each
+ * list a unique identifer */
+
+extern int pvl_elem_count;
+extern int pvl_list_count;
+
+/* Create new lists or elements */
+pvl_elem pvl_new_element(void* d, pvl_elem next,pvl_elem prior);
+pvl_list pvl_newlist(void);
+void pvl_free(pvl_list);
+
+/* Add, remove, or get the head of the list */
+void pvl_unshift(pvl_list l,void *d);
+void* pvl_shift(pvl_list l);
+pvl_elem pvl_head(pvl_list);
+
+/* Add, remove or get the tail of the list */
+void pvl_push(pvl_list l,void *d);
+void* pvl_pop(pvl_list l);
+pvl_elem pvl_tail(pvl_list);
+
+/* Insert elements in random places */
+typedef int (*pvl_comparef)(void* a, void* b); /* a, b are of the data type*/
+void pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d);
+void pvl_insert_after(pvl_list l,pvl_elem e,void *d);
+void pvl_insert_before(pvl_list l,pvl_elem e,void *d);
+
+/* Remove an element, or clear the entire list */
+void* pvl_remove(pvl_list,pvl_elem); /* Remove element, return data */
+void pvl_clear(pvl_list); /* Remove all elements, de-allocate all data */
+
+int pvl_count(pvl_list);
+
+/* Navagate the list */
+pvl_elem pvl_next(pvl_elem e);
+pvl_elem pvl_prior(pvl_elem e);
+
+/* get the data in the list */
+#ifndef PVL_USE_MACROS
+void* pvl_data(pvl_elem);
+#else
+#define pvl_data(x) x==0 ? 0 : ((struct pvl_elem_t *)x)->d;
+#endif
+
+
+/* Find an element for which a function returns true */
+typedef int (*pvl_findf)(void* a, void* b); /*a is list elem, b is other data*/
+pvl_elem pvl_find(pvl_list l,pvl_findf f,void* v);
+pvl_elem pvl_find_next(pvl_list l,pvl_findf f,void* v);
+
+/* Pass each element in the list to a function */
+typedef void (*pvl_applyf)(void* a, void* b); /*a is list elem, b is other data*/
+void pvl_apply(pvl_list l,pvl_applyf f, void *v);
+
+
+#endif /* __PVL_H__ */
+
+
+
+
+
diff --git a/src/plugins/vcalendar/libical/libical/sspm.c b/src/plugins/vcalendar/libical/libical/sspm.c
@@ -0,0 +1,1613 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: sspm.c Parse Mime
+ CREATOR: eric 25 June 2000
+
+ $Id$
+ $Locker$
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+
+ 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 Initial Developer of the Original Code is Eric Busboom
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+ ======================================================================*/
+
+#include <stdio.h>
+#include <string.h>
+#include "sspm.h"
+#include <assert.h>
+#include <ctype.h> /* for tolower */
+#include <stdlib.h> /* for malloc, free */
+#include <string.h> /* for strcasecmp */
+
+#ifdef DMALLOC
+#include "dmalloc.h"
+#endif
+
+#define TMP_BUF_SIZE 1024
+
+
+enum mime_state {
+ UNKNOWN_STATE,
+ IN_HEADER,
+ END_OF_HEADER,
+ IN_BODY,
+ OPENING_PART,
+ END_OF_PART,
+ TERMINAL_END_OF_PART,
+ END_OF_INPUT
+};
+
+struct mime_impl{
+ struct sspm_part *parts;
+ size_t max_parts;
+ int part_no;
+ int level;
+ struct sspm_action_map *actions;
+ char* (*get_string)(char *s, size_t size, void* data);
+ void* get_string_data;
+ char temp[TMP_BUF_SIZE];
+ enum mime_state state;
+};
+
+void sspm_free_header(struct sspm_header *header);
+void* sspm_make_multipart_part(struct mime_impl *impl,struct sspm_header *header);
+void sspm_read_header(struct mime_impl *impl,struct sspm_header *header);
+
+char* sspm_strdup(char* str){
+
+ char* s;
+
+ s = strdup(str);
+
+ return s;
+}
+
+
+struct major_content_type_map
+{
+ enum sspm_major_type type;
+ char* str;
+
+} major_content_type_map[] =
+{
+ {SSPM_MULTIPART_MAJOR_TYPE,"multipart" },
+ {SSPM_TEXT_MAJOR_TYPE,"text" },
+ {SSPM_TEXT_MAJOR_TYPE,"text" },
+ {SSPM_IMAGE_MAJOR_TYPE,"image" },
+ {SSPM_AUDIO_MAJOR_TYPE,"audio" },
+ {SSPM_VIDEO_MAJOR_TYPE,"video" },
+ {SSPM_APPLICATION_MAJOR_TYPE,"application" },
+ {SSPM_MULTIPART_MAJOR_TYPE,"multipart" },
+ {SSPM_MESSAGE_MAJOR_TYPE,"message" },
+ {SSPM_UNKNOWN_MAJOR_TYPE,"" },
+};
+
+struct minor_content_type_map
+{
+ enum sspm_minor_type type;
+ char* str;
+
+} minor_content_type_map[] =
+{
+ {SSPM_ANY_MINOR_TYPE,"*" },
+ {SSPM_PLAIN_MINOR_TYPE,"plain" },
+ {SSPM_RFC822_MINOR_TYPE,"rfc822" },
+ {SSPM_DIGEST_MINOR_TYPE,"digest" },
+ {SSPM_CALENDAR_MINOR_TYPE,"calendar" },
+ {SSPM_MIXED_MINOR_TYPE,"mixed" },
+ {SSPM_RELATED_MINOR_TYPE,"related" },
+ {SSPM_ALTERNATIVE_MINOR_TYPE,"alternative" },
+ {SSPM_PARALLEL_MINOR_TYPE, "parallel" },
+ {SSPM_UNKNOWN_MINOR_TYPE,"" }
+};
+
+
+
+struct encoding_map {
+ enum sspm_encoding encoding;
+ char* str;
+} sspm_encoding_map[] =
+{
+ {SSPM_NO_ENCODING,""},
+ {SSPM_QUOTED_PRINTABLE_ENCODING,"quoted-printable"},
+ {SSPM_8BIT_ENCODING,"8bit"},
+ {SSPM_7BIT_ENCODING,"7bit"},
+ {SSPM_BINARY_ENCODING,"binary"},
+ {SSPM_BASE64_ENCODING,"base64"},
+ {SSPM_UNKNOWN_ENCODING,""}
+
+};
+
+
+char* sspm_get_parameter(char* line, char* parameter)
+{
+ char *p,*s,*q;
+ static char name[1024];
+
+ /* Find where the parameter name is in the line */
+ p = strstr(line,parameter);
+
+ if( p == 0){
+ return 0;
+ }
+
+ /* skip over the parameter name, the '=' and any blank spaces */
+
+ p+=strlen(parameter);
+
+ while(*p==' ' || *p == '='){
+ p++;
+ }
+
+ /*now find the next semicolon*/
+
+ s = strchr(p,';');
+
+ /* Strip of leading quote */
+ q = strchr(p,'\"');
+
+ if(q !=0){
+ p = q+1;
+ }
+
+ if(s != 0){
+ strncpy(name,p,(size_t)s-(size_t)p);
+ } else {
+ strcpy(name,p);
+ }
+
+ /* Strip off trailing quote, if it exists */
+
+ q = strrchr(name,'\"');
+
+ if (q != 0){
+ *q='\0';
+ }
+
+ return name;
+}
+
+char* sspm_property_name(char* line)
+{
+ static char name[1024];
+ char *c = strchr(line,':');
+
+ if(c != 0){
+ strncpy(name,line,(size_t)c-(size_t)line);
+ name[(size_t)c-(size_t)line] = '\0';
+ return name;
+ } else {
+ return 0;
+ }
+}
+
+char* sspm_value(char* line)
+{
+ static char value[1024];
+
+ char *c,*s, *p;
+
+ /* Find the first colon and the next semicolon */
+
+ c = strchr(line,':');
+ s = strchr(c,';');
+
+ /* Skip the colon */
+ c++;
+
+ if (s == 0){
+ s = c+strlen(line);
+ }
+
+ for(p=value; c != s; c++){
+ if(*c!=' ' && *c!='\n'){
+ *(p++) = *c;
+ }
+ }
+
+ *p='\0';
+
+ return value;
+
+}
+
+char *mime_headers[] = {
+ "Content-Type",
+ "Content-Transfer-Encoding",
+ "Content-Disposition",
+ "Content-Id",
+ "Mime-Version",
+ 0
+};
+
+
+void* sspm_default_new_part()
+{
+ return 0;
+}
+void sspm_default_add_line(void *part, struct sspm_header *header,
+ char* line, size_t size)
+{
+}
+
+void* sspm_default_end_part(void* part)
+{
+ return 0;
+}
+
+void sspm_default_free_part(void *part)
+{
+}
+
+
+
+struct sspm_action_map sspm_action_map[] =
+{
+ {SSPM_UNKNOWN_MAJOR_TYPE,SSPM_UNKNOWN_MINOR_TYPE,sspm_default_new_part,sspm_default_add_line,sspm_default_end_part,sspm_default_free_part},
+};
+
+int sspm_is_mime_header(char *line)
+{
+ char *name = sspm_property_name(line);
+ int i;
+
+ if(name == 0){
+ return 0;
+ }
+
+ for(i = 0; mime_headers[i] != 0; i++){
+ if(strcasecmp(name, mime_headers[i]) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int sspm_is_mail_header(char* line)
+{
+ char *name = sspm_property_name(line);
+
+ if (name != 0){
+ return 1;
+ }
+
+ return 0;
+
+}
+
+int sspm_is_blank(char* line)
+{
+ char *p;
+ char c =0;
+
+ for(p=line; *p!=0; p++){
+ if( ! (*p == ' '|| *p == '\t' || *p=='\n') ){
+ c++;
+ }
+ }
+
+ if (c==0){
+ return 1;
+ }
+
+ return 0;
+
+}
+
+int sspm_is_continuation_line(char* line)
+{
+ if (line[0] == ' '|| line[0] == '\t' ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int sspm_is_mime_boundary(char *line)
+{
+ if( line[0] == '-' && line[1] == '-') {
+ return 1;
+ }
+
+ return 0;
+}
+
+int sspm_is_mime_terminating_boundary(char *line)
+{
+
+
+ if (sspm_is_mime_boundary(line) &&
+ strstr(line,"--\n")){
+ return 1;
+ }
+
+ return 0;
+}
+
+enum line_type {
+ EMPTY,
+ BLANK,
+ MIME_HEADER,
+ MAIL_HEADER,
+ HEADER_CONTINUATION,
+ BOUNDARY,
+ TERMINATING_BOUNDARY,
+ UNKNOWN_TYPE
+};
+
+
+enum line_type get_line_type(char* line){
+
+ if (line == 0){
+ return EMPTY;
+ } else if(sspm_is_blank(line)){
+ return BLANK;
+ } else if (sspm_is_mime_header(line)){
+ return MIME_HEADER;
+ } else if (sspm_is_mail_header(line)){
+ return MAIL_HEADER;
+ } else if (sspm_is_continuation_line(line)){
+ return HEADER_CONTINUATION;
+ } else if (sspm_is_mime_terminating_boundary(line)){
+ return TERMINATING_BOUNDARY;
+ } else if (sspm_is_mime_boundary(line)) {
+ return BOUNDARY;
+ } else {
+ return UNKNOWN_TYPE;
+ }
+
+
+}
+
+
+struct sspm_action_map get_action(struct mime_impl *impl,
+ enum sspm_major_type major,
+ enum sspm_minor_type minor)
+{
+ int i;
+
+ /* Read caller suppled action map */
+
+ if (impl->actions != 0){
+ for(i=0; impl->actions[i].major != SSPM_UNKNOWN_MAJOR_TYPE; i++){
+ if((major == impl->actions[i].major &&
+ minor == impl->actions[i].minor) ||
+ (major == impl->actions[i].major &&
+ minor == SSPM_ANY_MINOR_TYPE)){
+ return impl->actions[i];
+ }
+ }
+ }
+
+ /* Else, read default action map */
+
+ for(i=0; sspm_action_map[i].major != SSPM_UNKNOWN_MAJOR_TYPE; i++){
+ if((major == sspm_action_map[i].major &&
+ minor == sspm_action_map[i].minor) ||
+ (major == sspm_action_map[i].major &&
+ minor == SSPM_ANY_MINOR_TYPE)){
+ break;
+ }
+ }
+
+ return sspm_action_map[i];
+}
+
+
+char* sspm_lowercase(char* str)
+{
+ char* p = 0;
+ char* new = sspm_strdup(str);
+
+ if(str ==0){
+ return 0;
+ }
+
+ for(p = new; *p!=0; p++){
+ *p = tolower(*p);
+ }
+
+ return new;
+}
+
+enum sspm_major_type sspm_find_major_content_type(char* type)
+{
+ int i;
+
+ char* ltype = sspm_lowercase(type);
+
+ for (i=0; major_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE; i++){
+ if(strncmp(ltype, major_content_type_map[i].str,
+ strlen(major_content_type_map[i].str))==0){
+ free(ltype);
+ return major_content_type_map[i].type;
+ }
+ }
+ free(ltype);
+ return major_content_type_map[i].type; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
+}
+
+enum sspm_minor_type sspm_find_minor_content_type(char* type)
+{
+ int i;
+ char* ltype = sspm_lowercase(type);
+
+ char *p = strchr(ltype,'/');
+
+ if (p==0){
+ return SSPM_UNKNOWN_MINOR_TYPE;
+ }
+
+ p++; /* Skip the '/' */
+
+ for (i=0; minor_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE; i++){
+ if(strncmp(p, minor_content_type_map[i].str,
+ strlen(minor_content_type_map[i].str))==0){
+ free(ltype);
+ return minor_content_type_map[i].type;
+ }
+ }
+
+ free(ltype);
+ return minor_content_type_map[i].type; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
+}
+
+char* sspm_major_type_string(enum sspm_major_type type)
+{
+ int i;
+
+ for (i=0; major_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE;
+ i++){
+
+ if(type == major_content_type_map[i].type){
+ return major_content_type_map[i].str;
+ }
+ }
+
+ return major_content_type_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
+}
+
+char* sspm_minor_type_string(enum sspm_minor_type type)
+{
+ int i;
+ for (i=0; minor_content_type_map[i].type != SSPM_UNKNOWN_MINOR_TYPE;
+ i++){
+ if(type == minor_content_type_map[i].type){
+ return minor_content_type_map[i].str;
+ }
+ }
+
+ return minor_content_type_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
+}
+
+
+char* sspm_encoding_string(enum sspm_encoding type)
+{
+ int i;
+ for (i=0; sspm_encoding_map[i].encoding != SSPM_UNKNOWN_ENCODING;
+ i++){
+ if(type == sspm_encoding_map[i].encoding){
+ return sspm_encoding_map[i].str;
+ }
+ }
+
+ return sspm_encoding_map[i].str; /* Should return SSPM_UNKNOWN_MINOR_TYPE */
+}
+
+/* Interpret a header line and add its data to the header
+ structure. */
+void sspm_build_header(struct sspm_header *header, char* line)
+{
+ char *prop;
+ char *val;
+
+ val = sspm_strdup(sspm_value(line));
+ prop = sspm_strdup(sspm_property_name(line));
+
+ if(strcmp(prop,"Content-Type") == 0){
+
+ /* Create a new mime_header, fill in content-type
+ and possibly boundary */
+
+ char* boundary= sspm_get_parameter(line,"boundary");
+
+ header->def = 0;
+ header->major = sspm_find_major_content_type(val);
+ header->minor = sspm_find_minor_content_type(val);
+
+ if(header->minor == SSPM_UNKNOWN_MINOR_TYPE){
+ char *p = strchr(val,'/');
+
+ if (p != 0){
+ p++; /* Skip the '/' */
+
+ header->minor_text = sspm_strdup(p);
+ } else {
+ /* Error, malformed content type */
+ header->minor_text = sspm_strdup("unknown");
+ }
+ }
+ if (boundary != 0){
+ header->boundary = sspm_strdup(boundary);
+ }
+
+ } else if(strcmp(prop,"Content-Transfer-Encoding")==0){
+ char* encoding = sspm_value(line);
+ char* lencoding = sspm_lowercase(encoding);
+
+ if(strcmp(lencoding,"base64")==0){
+ header->encoding = SSPM_BASE64_ENCODING;
+ } else if(strcmp(lencoding,"quoted-printable")==0){
+ header->encoding = SSPM_QUOTED_PRINTABLE_ENCODING;
+ } else if(strcmp(lencoding,"binary")==0){
+ header->encoding = SSPM_BINARY_ENCODING;
+ } else if(strcmp(lencoding,"7bit")==0){
+ header->encoding = SSPM_7BIT_ENCODING;
+ } else if(strcmp(lencoding,"8bit")==0){
+ header->encoding = SSPM_8BIT_ENCODING;
+ } else {
+ header->encoding = SSPM_UNKNOWN_ENCODING;
+ }
+
+
+ free(lencoding);
+
+ header->def = 0;
+
+ } else if(strcmp(prop,"Content-Id")==0){
+ char* cid = sspm_value(line);
+ header->content_id = sspm_strdup(cid);
+ header->def = 0;
+
+ }
+ free(val);
+ free(prop);
+}
+
+char* sspm_get_next_line(struct mime_impl *impl)
+{
+ char* s;
+ s = impl->get_string(impl->temp,TMP_BUF_SIZE,impl->get_string_data);
+
+ if(s == 0){
+ impl->state = END_OF_INPUT;
+ }
+ return s;
+}
+
+
+void sspm_store_part(struct mime_impl *impl, struct sspm_header header,
+ int level, void *part, size_t size)
+{
+
+ impl->parts[impl->part_no].header = header;
+ impl->parts[impl->part_no].level = level;
+ impl->parts[impl->part_no].data = part;
+ impl->parts[impl->part_no].data_size = size;
+ impl->part_no++;
+}
+
+void sspm_set_error(struct sspm_header* header, enum sspm_error error,
+ char* message)
+{
+ header->error = error;
+
+ if(header->error_text!=0){
+ free(header->error_text);
+ }
+
+ header->def = 0;
+
+ if(message != 0){
+ header->error_text = sspm_strdup(message);
+ } else {
+ header->error_text = 0;
+ }
+
+}
+
+void* sspm_make_part(struct mime_impl *impl,
+ struct sspm_header *header,
+ struct sspm_header *parent_header,
+ void **end_part,
+ size_t *size)
+{
+
+ /* For a single part type, read to the boundary, if there is a
+ boundary. Otherwise, read until the end of input. This routine
+ assumes that the caller has read the header and has left the input
+ at the first blank line */
+
+ char *line;
+ void *part;
+ int end = 0;
+
+ struct sspm_action_map action = get_action(
+ impl,
+ header->major,
+ header->minor);
+
+ *size = 0;
+ part =action.new_part();
+
+ impl->state = IN_BODY;
+
+ while(end == 0 && (line = sspm_get_next_line(impl)) != 0){
+
+ if(sspm_is_mime_boundary(line)){
+
+ /* If there is a boundary, then this must be a multipart
+ part, so there must be a parent_header. */
+ if(parent_header == 0){
+ char* boundary;
+ end = 1;
+ *end_part = 0;
+
+ sspm_set_error(header,SSPM_UNEXPECTED_BOUNDARY_ERROR,line);
+
+ /* Read until the paired terminating boundary */
+ if((boundary = (char*)malloc(strlen(line)+5)) == 0){
+ fprintf(stderr,"Out of memory");
+ abort();
+ }
+ strcpy(boundary,line);
+ strcat(boundary,"--");
+ while((line = sspm_get_next_line(impl)) != 0){
+ /*printf("Error: %s\n",line);*/
+ if(strcmp(boundary,line)==0){
+ break;
+ }
+ }
+ free(boundary);
+
+ break;
+ }
+
+ if(strncmp((line+2),parent_header->boundary,
+ sizeof(parent_header->boundary)) == 0){
+ *end_part = action.end_part(part);
+
+ if(sspm_is_mime_boundary(line)){
+ impl->state = END_OF_PART;
+ } else if ( sspm_is_mime_terminating_boundary(line)){
+ impl->state = TERMINAL_END_OF_PART;
+ }
+ end = 1;
+ } else {
+ /* Error, this is not the correct terminating boundary*/
+
+ /* read and discard until we get the right boundary. */
+ char* boundary;
+ char msg[256];
+
+ snprintf(msg,256,
+ "Expected: %s--. Got: %s",
+ parent_header->boundary,line);
+
+ sspm_set_error(parent_header,
+ SSPM_WRONG_BOUNDARY_ERROR,msg);
+
+ /* Read until the paired terminating boundary */
+ if((boundary = (char*)malloc(strlen(line)+5)) == 0){
+ fprintf(stderr,"Out of memory");
+ abort();
+ }
+ strcpy(boundary,line);
+ strcat(boundary,"--");
+ while((line = sspm_get_next_line(impl)) != 0){
+ if(strcmp(boundary,line)==0){
+ break;
+ }
+ }
+ free(boundary);
+
+ }
+ } else {
+ char* data=0;
+ char* rtrn=0;
+ *size = strlen(line);
+
+ data = (char*)malloc(*size+2);
+ assert(data != 0);
+ if (header->encoding == SSPM_BASE64_ENCODING){
+ rtrn = decode_base64(data,line,size);
+ } else if(header->encoding == SSPM_QUOTED_PRINTABLE_ENCODING){
+ rtrn = decode_quoted_printable(data,line,size);
+ }
+
+ if(rtrn == 0){
+ strcpy(data,line);
+ }
+
+ /* add a end-of-string after the data, just in case binary
+ data from decode64 gets passed to a tring handling
+ routine in add_line */
+ data[*size+1]='\0';
+
+ action.add_line(part,header,data,*size);
+
+ free(data);
+ }
+ }
+
+ if (end == 0){
+ /* End the part if the input is exhausted */
+ *end_part = action.end_part(part);
+ }
+
+ return end_part;
+}
+
+
+void* sspm_make_multipart_subpart(struct mime_impl *impl,
+ struct sspm_header *parent_header)
+{
+ struct sspm_header header;
+ char *line;
+ void* part;
+ size_t size;
+
+ if(parent_header->boundary == 0){
+ /* Error. Multipart headers must have a boundary*/
+
+ sspm_set_error(parent_header,SSPM_NO_BOUNDARY_ERROR,0);
+ /* read all of the reamining lines */
+ while((line = sspm_get_next_line(impl)) != 0){
+ }
+
+ return 0;
+ }
+
+
+ /* Step 1: Read the opening boundary */
+
+ if(get_line_type(impl->temp) != BOUNDARY){
+ while((line=sspm_get_next_line(impl)) != 0 ){
+ if(sspm_is_mime_boundary(line)){
+
+ assert(parent_header != 0);
+
+ /* Check if it is the right boundary */
+ if(!sspm_is_mime_terminating_boundary(line) &&
+ strncmp((line+2),parent_header->boundary,
+ sizeof(parent_header->boundary))
+ == 0){
+ /* The +2 in strncmp skips over the leading "--" */
+
+ break;
+ } else {
+ /* Got the wrong boundary, so read and discard
+ until we get the right boundary. */
+ char* boundary;
+ char msg[256];
+
+ snprintf(msg,256,
+ "Expected: %s. Got: %s",
+ parent_header->boundary,line);
+
+ sspm_set_error(parent_header,
+ SSPM_WRONG_BOUNDARY_ERROR,msg);
+
+ /* Read until the paired terminating boundary */
+ if((boundary = (char*)malloc(strlen(line)+5)) == 0){
+ fprintf(stderr,"Out of memory");
+ abort();
+ }
+ strcpy(boundary,line);
+ strcat(boundary,"--");
+ while((line = sspm_get_next_line(impl)) != 0){
+ if(strcmp(boundary,line)==0){
+ break;
+ }
+ }
+ free(boundary);
+
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* Step 2: Get the part header */
+ sspm_read_header(impl,&header);
+
+ /* If the header is still listed as default, there was probably an
+ error */
+ if(header.def == 1 && header.error != SSPM_NO_ERROR){
+ sspm_set_error(&header,SSPM_NO_HEADER_ERROR,0);
+ return 0;
+ }
+
+ if(header.error!= SSPM_NO_ERROR){
+ sspm_store_part(impl,header,impl->level,0,0);
+ return 0;
+ }
+
+ /* Step 3: read the body */
+
+ if(header.major == SSPM_MULTIPART_MAJOR_TYPE){
+ struct sspm_header *child_header;
+ child_header = &(impl->parts[impl->part_no].header);
+
+ /* Store the multipart part */
+ sspm_store_part(impl,header,impl->level,0,0);
+
+ /* now get all of the sub-parts */
+ part = sspm_make_multipart_part(impl,child_header);
+
+ if(get_line_type(impl->temp) != TERMINATING_BOUNDARY){
+
+ sspm_set_error(child_header,SSPM_NO_BOUNDARY_ERROR,impl->temp);
+ return 0;
+ }
+
+ sspm_get_next_line(impl); /* Step past the terminating boundary */
+
+ } else {
+ sspm_make_part(impl, &header,parent_header,&part,&size);
+
+ memset(&(impl->parts[impl->part_no]), 0, sizeof(struct sspm_part));
+
+ sspm_store_part(impl,header,impl->level,part,size);
+
+ }
+
+ return part;
+}
+
+void* sspm_make_multipart_part(struct mime_impl *impl,struct sspm_header *header)
+{
+ void *part=0;
+
+ /* Now descend a level into each of the children of this part */
+ impl->level++;
+
+ /* Now we are working on the CHILD */
+ memset(&(impl->parts[impl->part_no]), 0, sizeof(struct sspm_part));
+
+ do{
+ part = sspm_make_multipart_subpart(impl,header);
+
+ if (part==0){
+ /* Clean up the part in progress */
+ impl->parts[impl->part_no].header.major
+ = SSPM_NO_MAJOR_TYPE;
+ impl->parts[impl->part_no].header.minor
+ = SSPM_NO_MINOR_TYPE;
+
+ }
+
+
+ } while (get_line_type(impl->temp) != TERMINATING_BOUNDARY &&
+ impl->state != END_OF_INPUT);
+
+ impl->level--;
+
+ return 0;
+}
+
+
+void sspm_read_header(struct mime_impl *impl,struct sspm_header *header)
+{
+#define BUF_SIZE 1024
+#define MAX_HEADER_LINES 25
+
+ char *buf;
+ char header_lines[MAX_HEADER_LINES][BUF_SIZE]; /* HACK, hard limits */
+ int current_line = -1;
+ int end = 0;
+
+ memset(header_lines,0,sizeof(header_lines));
+ memset(header,0,sizeof(struct sspm_header));
+
+ /* Set up default header */
+ header->def = 1;
+ header->major = SSPM_TEXT_MAJOR_TYPE;
+ header->minor = SSPM_PLAIN_MINOR_TYPE;
+ header->error = SSPM_NO_ERROR;
+ header->error_text = 0;
+
+ /* Read all of the lines into memory */
+ while(end==0&& (buf=sspm_get_next_line(impl)) != 0){
+
+ enum line_type line_type = get_line_type(buf);
+
+ switch(line_type){
+ case BLANK: {
+ end = 1;
+ impl->state = END_OF_HEADER;
+ break;
+ }
+
+ case MAIL_HEADER:
+ case MIME_HEADER: {
+ impl->state = IN_HEADER;
+ current_line++;
+
+ assert(strlen(buf) < BUF_SIZE);
+
+ strcpy(header_lines[current_line],buf);
+
+ break;
+ }
+
+ case HEADER_CONTINUATION: {
+ char* last_line, *end;
+ char *buf_start;
+
+ if(current_line < 0){
+ /* This is not really a continuation line, since
+ we have not see any header line yet */
+ sspm_set_error(header,SSPM_MALFORMED_HEADER_ERROR,buf);
+ return;
+ }
+
+ last_line = header_lines[current_line];
+ end = (char*) ( (size_t)strlen(last_line)+
+ (size_t)last_line);
+
+ impl->state = IN_HEADER;
+
+
+ /* skip over the spaces in buf start, and remove the new
+ line at the end of the lat line */
+ if (last_line[strlen(last_line)-1] == '\n'){
+ last_line[strlen(last_line)-1] = '\0';
+ }
+ buf_start = buf;
+ while(*buf_start == ' ' ||*buf_start == '\t' ){
+ buf_start++;
+ }
+
+ assert( strlen(buf_start) + strlen(last_line) < BUF_SIZE);
+
+ strcat(last_line,buf_start);
+
+ break;
+ }
+
+ default: {
+ sspm_set_error(header,SSPM_MALFORMED_HEADER_ERROR,buf);
+ return;
+ }
+ }
+ }
+
+
+ for(current_line = 0;
+ current_line < MAX_HEADER_LINES && header_lines[current_line][0] != 0;
+ current_line++){
+
+ sspm_build_header(header,header_lines[current_line]);
+ }
+
+
+}
+
+/* Root routine for parsing mime entries*/
+int sspm_parse_mime(struct sspm_part *parts,
+ size_t max_parts,
+ struct sspm_action_map *actions,
+ char* (*get_string)(char *s, size_t size, void* data),
+ void *get_string_data,
+ struct sspm_header *first_header
+ )
+{
+ struct mime_impl impl;
+ struct sspm_header header;
+ void *part;
+ int i;
+
+ /* Initialize all of the data */
+ memset(&impl,0,sizeof(struct mime_impl));
+ memset(&header,0,sizeof(struct sspm_header));
+
+ for(i = 0; i<(int)max_parts; i++){
+ parts[i].header.major = SSPM_NO_MAJOR_TYPE;
+ parts[i].header.minor = SSPM_NO_MINOR_TYPE;
+ }
+
+ impl.parts = parts;
+ impl.max_parts = max_parts;
+ impl.part_no = 0;
+ impl.actions = actions;
+ impl.get_string = get_string;
+ impl.get_string_data = get_string_data;
+
+ /* Read the header of the message. This will be the email header,
+ unless first_header is specified. But ( HACK) that var is not
+ currently being used */
+ sspm_read_header(&impl,&header);
+
+ if(header.major == SSPM_MULTIPART_MAJOR_TYPE){
+ struct sspm_header *child_header;
+ child_header = &(impl.parts[impl.part_no].header);
+
+ sspm_store_part(&impl,header,impl.level,0,0);
+
+ part = sspm_make_multipart_part(&impl,child_header);
+
+ } else {
+ void *part;
+ size_t size;
+ sspm_make_part(&impl, &header, 0,&part,&size);
+
+ memset(&(impl.parts[impl.part_no]), 0, sizeof(struct sspm_part));
+
+ sspm_store_part(&impl,header,impl.level,part,size);
+ }
+
+ return 0;
+}
+
+void sspm_free_parts(struct sspm_part *parts, size_t max_parts)
+{
+ int i;
+
+ for(i = 0; i<(int)max_parts && parts[i].header.major != SSPM_NO_MAJOR_TYPE;
+ i++){
+ sspm_free_header(&(parts[i].header));
+ }
+}
+
+void sspm_free_header(struct sspm_header *header)
+{
+ if(header->boundary!=0){
+ free(header->boundary);
+ }
+ if(header->minor_text!=0){
+ free(header->minor_text);
+ }
+ if(header->charset!=0){
+ free(header->charset);
+ }
+ if(header->filename!=0){
+ free(header->filename);
+ }
+ if(header->content_id!=0){
+ free(header->content_id);
+ }
+ if(header->error_text!=0){
+ free(header->error_text);
+ }
+}
+
+/***********************************************************************
+The remaining code is beased on code from the mimelite distribution,
+which has the following notice:
+
+| Authorship:
+| Copyright (c) 1994 Gisle Hannemyr.
+| Permission is granted to hack, make and distribute copies of this
+| program as long as this copyright notice is not removed.
+| Flames, bug reports, comments and improvements to:
+| snail: Gisle Hannemyr, Brageveien 3A, 0452 Oslo, Norway
+| email: Inet: gisle@oslonett.no
+
+The code is heavily modified by Eric Busboom.
+
+***********************************************************************/
+
+char *decode_quoted_printable(char *dest,
+ char *src,
+ size_t *size)
+{
+ int cc;
+ size_t i=0;
+
+ while (*src != 0 && i < *size) {
+ if (*src == '=') {
+
+ src++;
+ if (!*src) {
+ break;
+ }
+
+ /* remove soft line breaks*/
+ if ((*src == '\n') || (*src == '\r')){
+ src++;
+ if ((*src == '\n') || (*src == '\r')){
+ src++;
+ }
+ continue;
+ }
+
+ cc = isdigit(*src) ? (*src - '0') : (*src - 55);
+ cc *= 0x10;
+ src++;
+ if (!*src) {
+ break;
+ }
+ cc += isdigit(*src) ? (*src - '0') : (*src - 55);
+
+ *dest = cc;
+
+ } else {
+ *dest = *src;
+ }
+
+ dest++;
+ src++;
+ i++;
+ }
+
+ *dest = '\0';
+
+ *size = i;
+ return(dest);
+}
+
+char *decode_base64(char *dest,
+ char *src,
+ size_t *size)
+{
+ int cc = 0;
+ char buf[4] = {0,0,0,0};
+ int p = 0;
+ int valid_data = 0;
+ size_t size_out=0;
+
+ while (*src && p<(int)*size && (cc!= -1)) {
+
+ /* convert a character into the Base64 alphabet */
+ cc = *src++;
+
+ if ((cc >= 'A') && (cc <= 'Z')) cc = cc - 'A';
+ else if ((cc >= 'a') && (cc <= 'z')) cc = cc - 'a' + 26;
+ else if ((cc >= '0') && (cc <= '9')) cc = cc - '0' + 52;
+ else if (cc == '/') cc = 63;
+ else if (cc == '+') cc = 62;
+ else cc = -1;
+
+ assert(cc<64);
+
+ /* If we've reached the end, fill the remaining slots in
+ the bucket and do a final conversion */
+ if(cc== -1){
+ if(valid_data == 0){
+ return 0;
+ }
+
+ while(p%4!=3){
+ p++;
+ buf[p%4] = 0;
+ }
+ } else {
+ buf[p%4] = cc;
+ size_out++;
+ valid_data = 1;
+ }
+
+
+ /* When we have 4 base64 letters, convert them into three
+ bytes */
+ if (p%4 == 3) {
+ *dest++ =(buf[0]<< 2)|((buf[1] & 0x30) >> 4);
+ *dest++ =((buf[1] & 0x0F) << 4)|((buf[2] & 0x3C) >> 2);
+ *dest++ =((buf[2] & 0x03) << 6)|(buf[3] & 0x3F);
+
+ memset(buf,0,4);
+ }
+
+ p++;
+
+ }
+ /* Calculate the size of the converted data*/
+ *size = ((int)(size_out/4))*3;
+ if(size_out%4 == 2) *size+=1;
+ if(size_out%4 == 3) *size+=2;
+
+ return(dest);
+}
+
+
+/***********************************************************************
+
+ Routines to output MIME
+
+**********************************************************************/
+
+
+struct sspm_buffer {
+ char* buffer;
+ char* pos;
+ size_t buf_size;
+ int line_pos;
+};
+
+void sspm_append_string(struct sspm_buffer* buf, char* string);
+void sspm_write_part(struct sspm_buffer *buf,struct sspm_part *part, int *part_num);
+
+void sspm_append_hex(struct sspm_buffer* buf, char ch)
+{
+ char tmp[3];
+
+ sprintf(tmp,"=%02X",ch);
+
+ sspm_append_string(buf,tmp);
+}
+
+/* a copy of icalmemory_append_char */
+void sspm_append_char(struct sspm_buffer* buf, char ch)
+{
+ char *new_buf;
+ char *new_pos;
+
+ size_t data_length, final_length;
+
+ data_length = (size_t)buf->pos - (size_t)buf->buffer;
+
+ final_length = data_length + 2;
+
+ if ( final_length > (size_t) buf->buf_size ) {
+
+ buf->buf_size = (buf->buf_size) * 2 + final_length +1;
+
+ new_buf = realloc(buf->buffer,buf->buf_size);
+
+ new_pos = (void*)((size_t)new_buf + data_length);
+
+ buf->pos = new_pos;
+ buf->buffer = new_buf;
+ }
+
+ *(buf->pos) = ch;
+ buf->pos += 1;
+ *(buf->pos) = 0;
+}
+/* A copy of icalmemory_append_string */
+void sspm_append_string(struct sspm_buffer* buf, char* string)
+{
+ char *new_buf;
+ char *new_pos;
+
+ size_t data_length, final_length, string_length;
+
+ string_length = strlen(string);
+ data_length = (size_t)buf->pos - (size_t)buf->buffer;
+ final_length = data_length + string_length;
+
+ if ( final_length >= (size_t) buf->buf_size) {
+
+
+ buf->buf_size = (buf->buf_size) * 2 + final_length;
+
+ new_buf = realloc(buf->buffer,buf->buf_size);
+
+ new_pos = (void*)((size_t)new_buf + data_length);
+
+ buf->pos = new_pos;
+ buf->buffer = new_buf;
+ }
+
+ strcpy(buf->pos, string);
+
+ buf->pos += string_length;
+}
+
+
+
+static int sspm_is_printable(char c)
+{
+ return (c >= 33) && (c <= 126) && (c != '=');
+
+}
+
+
+void sspm_encode_quoted_printable(struct sspm_buffer *buf, char* data)
+{
+ char *p;
+ int lpos = 0;
+
+ for(p = data; *p != 0; p++){
+
+ if(sspm_is_printable(*p)){
+ /* plain characters can represent themselves */
+ /* RFC2045 Rule #2 */
+ sspm_append_char(buf,*p);
+ lpos++;
+ } else if ( *p == '\t' || *p == ' ' ) {
+
+ /* For tabs and spaces, only encode if they appear at the
+ end of the line */
+ /* RFC2045 Rule #3 */
+
+ char n = *(p+1);
+
+ if( n == '\n' || n == '\r'){
+ sspm_append_hex(buf,*p);
+ lpos += 3;
+ } else {
+ sspm_append_char(buf,*p);
+ lpos++;
+ }
+
+ } else if( *p == '\n' || *p == '\r'){
+ sspm_append_char(buf,*p);
+
+ lpos=0;
+
+ } else {
+ /* All others need to be encoded */
+ sspm_append_hex(buf,*p);
+ lpos+=3;
+ }
+
+
+ /* Add line breaks */
+ if (lpos > 72){
+ lpos = 0;
+ sspm_append_string(buf,"=\n");
+ }
+ }
+}
+
+static char BaseTable[64] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+void sspm_write_base64(struct sspm_buffer *buf, char* inbuf,int size )
+{
+
+ char outbuf[4];
+ int i;
+
+ outbuf[0] = outbuf[1] = outbuf[2] = outbuf[3] = 65;
+
+ switch(size){
+
+ case 4:
+ outbuf[3] = inbuf[2] & 0x3F;
+
+ case 3:
+ outbuf[2] = ((inbuf[1] & 0x0F) << 2) | ((inbuf[2] & 0xC0) >> 6);
+
+ case 2:
+ outbuf[0] = (inbuf[0] & 0xFC) >> 2;
+ outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf[1] & 0xF0) >> 4);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ for(i = 0; i < 4; i++){
+
+ if(outbuf[i] == 65){
+ sspm_append_char(buf,'=');
+ } else {
+ sspm_append_char(buf,BaseTable[(int)outbuf[i]]);
+ }
+ }
+}
+
+void sspm_encode_base64(struct sspm_buffer *buf, char* data, size_t size)
+{
+
+ char *p;
+ char inbuf[3];
+ int i = 0;
+ int first = 1;
+ int lpos = 0;
+
+ inbuf[0] = inbuf[1] = inbuf[2] = 0;
+
+ for (p = data; *p !=0; p++){
+
+ if (i%3 == 0 && first == 0){
+
+ sspm_write_base64(buf, inbuf, 4);
+ lpos+=4;
+
+ inbuf[0] = inbuf[1] = inbuf[2] = 0;
+ }
+
+ assert(lpos%4 == 0);
+
+ if (lpos == 72){
+ sspm_append_string(buf,"\n");
+ lpos = 0;
+ }
+
+ inbuf[i%3] = *p;
+
+ i++;
+ first = 0;
+
+ }
+
+
+ /* If the inbuf was not exactly filled on the last byte, we need
+ to spit out the odd bytes that did get in -- either one or
+ two. This will result in an output of two bytes and '==' or
+ three bytes and '=', respectively */
+
+ if (i%3 == 1 && first == 0){
+ sspm_write_base64(buf, inbuf, 2);
+ } else if (i%3 == 2 && first == 0){
+ sspm_write_base64(buf, inbuf, 3);
+ }
+
+}
+
+void sspm_write_header(struct sspm_buffer *buf,struct sspm_header *header)
+{
+
+ int i;
+ char temp[TMP_BUF_SIZE];
+ char* major;
+ char* minor;
+
+ /* Content-type */
+
+ major = sspm_major_type_string(header->major);
+ minor = sspm_minor_type_string(header->minor);
+
+ if(header->minor == SSPM_UNKNOWN_MINOR_TYPE ){
+ assert(header->minor_text !=0);
+ minor = header->minor_text;
+ }
+
+ sprintf(temp,"Content-Type: %s/%s",major,minor);
+
+ sspm_append_string(buf,temp);
+
+ if(header->boundary != 0){
+ sprintf(temp,";boundary=\"%s\"",header->boundary);
+ sspm_append_string(buf,temp);
+ }
+
+ /* Append any content type parameters */
+ if(header->content_type_params != 0){
+ for(i=0; *(header->content_type_params[i])!= 0;i++){
+ sprintf(temp,"%s",header->content_type_params[i]);
+ sspm_append_char(buf,';');
+ sspm_append_string(buf,temp);
+ }
+ }
+
+ sspm_append_char(buf,'\n');
+
+ /*Content-Transfer-Encoding */
+
+ if(header->encoding != SSPM_UNKNOWN_ENCODING &&
+ header->encoding != SSPM_NO_ENCODING){
+ sprintf(temp,"Content-Transfer-Encoding: %s\n",
+ sspm_encoding_string(header->encoding));
+ }
+
+ sspm_append_char(buf,'\n');
+
+}
+
+void sspm_write_multipart_part(struct sspm_buffer *buf,
+ struct sspm_part *parts,
+ int* part_num)
+{
+
+ int parent_level, level;
+ struct sspm_header *header = &(parts[*part_num].header);
+ /* Write the header for the multipart part */
+ sspm_write_header(buf,header);
+
+ parent_level = parts[*part_num].level;
+
+ (*part_num)++;
+
+ level = parts[*part_num].level;
+
+ while(parts[*part_num].header.major != SSPM_NO_MAJOR_TYPE &&
+ level == parent_level+1){
+
+ assert(header->boundary);
+ sspm_append_string(buf,header->boundary);
+ sspm_append_char(buf,'\n');
+
+ if (parts[*part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){
+ sspm_write_multipart_part(buf,parts,part_num);
+ } else {
+ sspm_write_part(buf, &(parts[*part_num]), part_num);
+ }
+
+ (*part_num)++;
+ level = parts[*part_num].level;
+ }
+
+ sspm_append_string(buf,"\n\n--");
+ sspm_append_string(buf,header->boundary);
+ sspm_append_string(buf,"\n");
+
+ (*part_num)--; /* undo last, spurious, increment */
+}
+
+void sspm_write_part(struct sspm_buffer *buf,struct sspm_part *part,int *part_num)
+{
+
+ /* Write header */
+ sspm_write_header(buf,&(part->header));
+
+ /* Write part data */
+
+ if(part->data == 0){
+ return;
+ }
+
+ if(part->header.encoding == SSPM_BASE64_ENCODING) {
+ assert(part->data_size != 0);
+ sspm_encode_base64(buf,part->data,part->data_size);
+ } else if(part->header.encoding == SSPM_QUOTED_PRINTABLE_ENCODING) {
+ sspm_encode_quoted_printable(buf,part->data);
+ } else {
+ sspm_append_string(buf,part->data);
+ }
+
+ sspm_append_string(buf,"\n\n");
+}
+
+int sspm_write_mime(struct sspm_part *parts,size_t num_parts,
+ char **output_string, char* header)
+{
+ struct sspm_buffer buf;
+ int part_num =0;
+
+ buf.buffer = malloc(4096);
+ buf.pos = buf.buffer;
+ buf.buf_size = 10;
+ buf.line_pos = 0;
+
+ /* write caller's header */
+ if(header != 0){
+ sspm_append_string(&buf,header);
+ }
+
+ if(buf.buffer[strlen(buf.buffer)-1] != '\n'){
+ sspm_append_char(&buf,'\n');
+ }
+
+ /* write mime-version header */
+ sspm_append_string(&buf,"Mime-Version: 1.0\n");
+
+ /* End of header */
+
+ /* Write body parts */
+ while(parts[part_num].header.major != SSPM_NO_MAJOR_TYPE){
+ if (parts[part_num].header.major == SSPM_MULTIPART_MAJOR_TYPE){
+ sspm_write_multipart_part(&buf,parts,&part_num);
+ } else {
+ sspm_write_part(&buf, &(parts[part_num]), &part_num);
+ }
+
+ part_num++;
+ }
+
+
+ *output_string = buf.buffer;
+
+ return 0;
+}
+
diff --git a/src/plugins/vcalendar/libical/libical/sspm.h b/src/plugins/vcalendar/libical/libical/sspm.h
@@ -0,0 +1,143 @@
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: sspm.h Mime Parser
+ CREATOR: eric 25 June 2000
+
+ $Id$
+ $Locker$
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+
+ 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 Initial Developer of the Original Code is Eric Busboom
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+ ======================================================================*/
+
+#ifndef SSPM_H
+#define SSPM_H
+
+enum sspm_major_type {
+ SSPM_NO_MAJOR_TYPE,
+ SSPM_TEXT_MAJOR_TYPE,
+ SSPM_IMAGE_MAJOR_TYPE,
+ SSPM_AUDIO_MAJOR_TYPE,
+ SSPM_VIDEO_MAJOR_TYPE,
+ SSPM_APPLICATION_MAJOR_TYPE,
+ SSPM_MULTIPART_MAJOR_TYPE,
+ SSPM_MESSAGE_MAJOR_TYPE,
+ SSPM_UNKNOWN_MAJOR_TYPE
+};
+
+enum sspm_minor_type {
+ SSPM_NO_MINOR_TYPE,
+ SSPM_ANY_MINOR_TYPE,
+ SSPM_PLAIN_MINOR_TYPE,
+ SSPM_RFC822_MINOR_TYPE,
+ SSPM_DIGEST_MINOR_TYPE,
+ SSPM_CALENDAR_MINOR_TYPE,
+ SSPM_MIXED_MINOR_TYPE,
+ SSPM_RELATED_MINOR_TYPE,
+ SSPM_ALTERNATIVE_MINOR_TYPE,
+ SSPM_PARALLEL_MINOR_TYPE,
+ SSPM_UNKNOWN_MINOR_TYPE
+};
+
+enum sspm_encoding {
+ SSPM_NO_ENCODING,
+ SSPM_QUOTED_PRINTABLE_ENCODING,
+ SSPM_8BIT_ENCODING,
+ SSPM_7BIT_ENCODING,
+ SSPM_BINARY_ENCODING,
+ SSPM_BASE64_ENCODING,
+ SSPM_UNKNOWN_ENCODING
+};
+
+enum sspm_error{
+ SSPM_NO_ERROR,
+ SSPM_UNEXPECTED_BOUNDARY_ERROR,
+ SSPM_WRONG_BOUNDARY_ERROR,
+ SSPM_NO_BOUNDARY_ERROR,
+ SSPM_NO_HEADER_ERROR,
+ SSPM_MALFORMED_HEADER_ERROR
+};
+
+
+struct sspm_header
+{
+ int def;
+ char* boundary;
+ enum sspm_major_type major;
+ enum sspm_minor_type minor;
+ char *minor_text;
+ char ** content_type_params;
+ char* charset;
+ enum sspm_encoding encoding;
+ char* filename;
+ char* content_id;
+ enum sspm_error error;
+ char* error_text;
+};
+
+struct sspm_part {
+ struct sspm_header header;
+ int level;
+ size_t data_size;
+ void *data;
+};
+
+struct sspm_action_map {
+ enum sspm_major_type major;
+ enum sspm_minor_type minor;
+ void* (*new_part)();
+ void (*add_line)(void *part, struct sspm_header *header,
+ char* line, size_t size);
+ void* (*end_part)(void* part);
+ void (*free_part)(void *part);
+};
+
+char* sspm_major_type_string(enum sspm_major_type type);
+char* sspm_minor_type_string(enum sspm_minor_type type);
+char* sspm_encoding_string(enum sspm_encoding type);
+
+int sspm_parse_mime(struct sspm_part *parts,
+ size_t max_parts,
+ struct sspm_action_map *actions,
+ char* (*get_string)(char *s, size_t size, void* data),
+ void *get_string_data,
+ struct sspm_header *first_header
+ );
+
+void sspm_free_parts(struct sspm_part *parts, size_t max_parts);
+
+char *decode_quoted_printable(char *dest,
+ char *src,
+ size_t *size);
+char *decode_base64(char *dest,
+ char *src,
+ size_t *size);
+
+
+int sspm_write_mime(struct sspm_part *parts,size_t num_parts,
+ char **output_string, char* header);
+
+#endif /*SSPM_H*/
diff --git a/src/plugins/vcalendar/libical/libical/vsnprintf.c b/src/plugins/vcalendar/libical/libical/vsnprintf.c
@@ -0,0 +1,167 @@
+#ifdef __osf__
+/*
+ * Revision 12: http://theos.com/~deraadt/snprintf.c
+ *
+ * Copyright (c) 1997 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#if __STDC__
+#include <stdarg.h>
+#include <stdlib.h>
+#else
+#include <varargs.h>
+#endif
+#include <setjmp.h>
+
+#ifndef roundup
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#endif
+
+static int pgsize;
+static char *curobj;
+static sigjmp_buf bail;
+
+#define EXTRABYTES 2 /* XXX: why 2? you don't want to know */
+
+static char *
+msetup(str, n)
+ char *str;
+ size_t n;
+{
+ char *e;
+
+ if (n == 0)
+ return NULL;
+ if (pgsize == 0)
+ pgsize = getpagesize();
+ curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2);
+ if (curobj == NULL)
+ return NULL;
+ e = curobj + n + EXTRABYTES;
+ e = (char *)roundup((unsigned long)e, pgsize);
+ if (mprotect(e, pgsize, PROT_NONE) == -1) {
+ free(curobj);
+ curobj = NULL;
+ return NULL;
+ }
+ e = e - n - EXTRABYTES;
+ *e = '\0';
+ return (e);
+}
+
+static void
+mcatch(int i)
+{
+ siglongjmp(bail, 1);
+}
+
+static void
+mcleanup(str, n, p)
+ char *str;
+ size_t n;
+ char *p;
+{
+ strncpy(str, p, n-1);
+ str[n-1] = '\0';
+ if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
+ PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
+ mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
+ PROT_READ|PROT_WRITE);
+ free(curobj);
+}
+
+int
+#if __STDC__
+vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
+#else
+vsnprintf(str, n, fmt, ap)
+ char *str;
+ size_t n;
+ char *fmt;
+ char *ap;
+#endif
+{
+ struct sigaction osa, nsa;
+ char *p;
+ int ret = n + 1; /* if we bail, indicated we overflowed */
+
+ memset(&nsa, 0, sizeof nsa);
+ nsa.sa_handler = mcatch;
+ sigemptyset(&nsa.sa_mask);
+
+ p = msetup(str, n);
+ if (p == NULL) {
+ *str = '\0';
+ return 0;
+ }
+ if (sigsetjmp(bail, 1) == 0) {
+ if (sigaction(SIGSEGV, &nsa, &osa) == -1) {
+ mcleanup(str, n, p);
+ return (0);
+ }
+ ret = vsprintf(p, fmt, ap);
+ }
+ mcleanup(str, n, p);
+ (void) sigaction(SIGSEGV, &osa, NULL);
+ return (ret);
+}
+
+int
+#if __STDC__
+snprintf(char *str, size_t n, char const *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+ char *str;
+ size_t n;
+ char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+
+ return (vsnprintf(str, n, fmt, ap));
+ va_end(ap);
+}
+
+
+#else
+
+/* ANSI C forbids an empty source file... */
+
+static void vsnprintf_dummy_func() {
+ vsnprintf_dummy_func();
+}
+
+#endif
diff --git a/src/plugins/vcalendar/libical/scripts/.cvsignore b/src/plugins/vcalendar/libical/scripts/.cvsignore
@@ -0,0 +1,6 @@
+.libs
+.deps
+Makefile
+Makefile.in
+*.lo
+*.la
diff --git a/src/plugins/vcalendar/libical/scripts/Makefile.am b/src/plugins/vcalendar/libical/scripts/Makefile.am
@@ -0,0 +1,9 @@
+EXTRA_DIST = \
+mkderivedcomponents.pl \
+mkderivedparameters.pl \
+mkderivedproperties.pl \
+mkderivedvalues.pl \
+mkparameterrestrictions.pl \
+mkrestrictionrecords.pl \
+mkrestrictiontable.pl \
+readvaluesfile.pl
diff --git a/src/plugins/vcalendar/libical/scripts/Makefile.in b/src/plugins/vcalendar/libical/scripts/Makefile.in
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/plugins/vcalendar/libical/scripts
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/check-type.m4 \
+ $(top_srcdir)/m4/gnupg-check-typedef.m4 \
+ $(top_srcdir)/m4/gnupg.m4 $(top_srcdir)/m4/gpgme.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/spamassassin.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h \
+ $(top_builddir)/claws-features.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPFACE_LIBS = @COMPFACE_LIBS@
+CONIC_CFLAGS = @CONIC_CFLAGS@
+CONIC_LIBS = @CONIC_LIBS@
+CONTACTS_CFLAGS = @CONTACTS_CFLAGS@
+CONTACTS_LIBS = @CONTACTS_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPT_LIBS = @CRYPT_LIBS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOCBOOK2HTML = @DOCBOOK2HTML@
+DOCBOOK2PDF = @DOCBOOK2PDF@
+DOCBOOK2PS = @DOCBOOK2PS@
+DOCBOOK2TXT = @DOCBOOK2TXT@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCHANT_CFLAGS = @ENCHANT_CFLAGS@
+ENCHANT_LIBS = @ENCHANT_LIBS@
+EXEEXT = @EXEEXT@
+EXTRA_VERSION = @EXTRA_VERSION@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNOME2_CFLAGS = @GNOME2_CFLAGS@
+GNOME2_LIBS = @GNOME2_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GPGME_CFLAGS = @GPGME_CFLAGS@
+GPGME_CONFIG = @GPGME_CONFIG@
+GPGME_LIBS = @GPGME_LIBS@
+GREP = @GREP@
+GTKPRINTUNIX_CFLAGS = @GTKPRINTUNIX_CFLAGS@
+GTKPRINTUNIX_LIBS = @GTKPRINTUNIX_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JPILOT_LIBS = @JPILOT_LIBS@
+LD = @LD@
+LDAP_LIBS = @LDAP_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBETPAN_FLAGS = @LIBETPAN_FLAGS@
+LIBETPAN_LIBS = @LIBETPAN_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBRESOLV = @LIBRESOLV@
+LIBS = @LIBS@
+LIBSOUP_GNOME_CFLAGS = @LIBSOUP_GNOME_CFLAGS@
+LIBSOUP_GNOME_LIBS = @LIBSOUP_GNOME_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAEMO_CFLAGS = @MAEMO_CFLAGS@
+MAEMO_LIBS = @MAEMO_LIBS@
+MAINT = @MAINT@
+MAJOR_VERSION = @MAJOR_VERSION@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MICRO_VERSION = @MICRO_VERSION@
+MINOR_VERSION = @MINOR_VERSION@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETWORKMANAGER_SUPPORT_CFLAGS = @NETWORKMANAGER_SUPPORT_CFLAGS@
+NETWORKMANAGER_SUPPORT_LIBS = @NETWORKMANAGER_SUPPORT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PASSCRYPT_KEY = @PASSCRYPT_KEY@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SM_LIBS = @SM_LIBS@
+STARTUP_NOTIFICATION_CFLAGS = @STARTUP_NOTIFICATION_CFLAGS@
+STARTUP_NOTIFICATION_LIBS = @STARTUP_NOTIFICATION_LIBS@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VERSION = @VERSION@
+WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
+WEBKIT_LIBS = @WEBKIT_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_cv_enable_crash_dialog = @ac_cv_enable_crash_dialog@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gnomedatadir = @gnomedatadir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libetpanconfig = @libetpanconfig@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+manualdir = @manualdir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+mkderivedcomponents.pl \
+mkderivedparameters.pl \
+mkderivedproperties.pl \
+mkderivedvalues.pl \
+mkparameterrestrictions.pl \
+mkrestrictionrecords.pl \
+mkrestrictiontable.pl \
+readvaluesfile.pl
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/scripts/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/vcalendar/libical/scripts/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/plugins/vcalendar/libical/scripts/mkderivedcomponents.pl b/src/plugins/vcalendar/libical/scripts/mkderivedcomponents.pl
@@ -0,0 +1,170 @@
+#!/usr/local/bin/perl
+
+use Getopt::Std;
+getopts('chspi:');
+
+
+# ARG 0 is components.txt
+open(PV,"$ARGV[0]") || die "Can't open components file $ARGV[0]:$!";
+
+my @components;
+
+while (<PV>){
+
+ s/#.*//;
+
+ chop;
+
+ push(@components,$_);
+
+}
+
+close PV;
+
+# Write the file inline by copying everything before a demarcation
+# line, and putting the generated data after the demarcation
+
+if ($opt_i) {
+
+ open(IN,$opt_i) || die "Can't open input file \"$opt_i\"";
+
+ while(<IN>){
+
+ if (/Do not edit/){
+ last;
+ }
+
+ print;
+
+ }
+
+ if($opt_i){
+ print "# Everything below this line is machine generated. Do not edit. \n";
+ } else {
+ print "/* Everything below this line is machine generated. Do not edit. */\n";
+ }
+
+}
+
+if ($opt_c or $opt_h and !$opt_i){
+
+print <<EOM;
+/* -*- Mode: C -*-
+ ======================================================================
+ FILE: icalderivedproperties.{c,h}
+ CREATOR: eric 09 May 1999
+
+ \044Id:\044
+
+ (C) COPYRIGHT 1999 Eric Busboom
+ http://www.softwarestudio.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+
+ ======================================================================*/
+
+/*
+ * THIS FILE IS MACHINE GENERATED DO NOT EDIT
+ */
+
+#include <stdarg.h> /* for va_arg functions */
+
+EOM
+
+}
+
+if ($opt_p and !$opt_i){
+
+print <<EOM;
+
+EOM
+
+}
+
+
+foreach $comp (@components) {
+
+ next if !$comp;
+
+ my $ucf = join("",map {ucfirst(lc($_));} split(/-/,$comp));
+ my $lc = lc($ucf);
+ my $uc = uc($lc);
+
+ if($opt_c) { # Make C source
+ print<<EOM;
+
+/* $comp */
+
+icalcomponent* icalcomponent_new_${lc}()
+{
+ return (icalcomponent*)icalcomponent_new_impl(ICAL_${uc}_COMPONENT);
+}
+
+icalcomponent* icalcomponent_vanew_${lc}(...)
+{
+ va_list args;
+ struct icalcomponent_impl *impl = icalcomponent_new_impl(ICAL_${uc}_component);
+
+ va_start(args,v);
+ icalcomponent_add_properties(impl, args);
+ va_end(args);
+
+ return (icalcomponent*)impl;
+}
+
+EOM
+
+
+ } elsif ($opt_h) { # Make a C header
+ print<<EOM;
+
+/* $comp */
+icalcomponent* icalcomponent_new_${lc}();
+icalcomponent* icalcomponent_vanew_${lc}(...);
+EOM
+
+} elsif ($opt_s) { # Make something for a switch statement
+
+print <<EOM;
+case ICAL_${uc}_PROPERTY:
+EOM
+
+} elsif ($opt_p) { # make perl source
+
+print <<EOM;
+
+# $comp
+package Net::ICal::Component::${ucf};
+\@ISA=qw(Net::ICal::Component);
+
+sub new
+{
+ my \$package = shift;
+ my \$c = Net::ICal::icalcomponent_new(\$Net::ICal::ICAL_${uc}_COMPONENT);
+
+ my \$self = Net::ICal::Component::new_from_ref(\$c);
+ Net::ICal::Component::_add_elements(\$self,\\\@_);
+
+ # Self is blessed in new_from_ref
+
+ return \$self;
+
+}
+EOM
+
+}
+
+
+
+}
+
+
diff --git a/src/plugins/vcalendar/libical/scripts/mkderivedparameters.pl b/src/plugins/vcalendar/libical/scripts/mkderivedparameters.pl
@@ -0,0 +1,321 @@
+#!/usr/local/bin/perl
+
+require "readvaluesfile.pl";
+
+use Getopt::Std;
+getopts('chspi:');
+
+%no_xname = (RELATED=>1,RANGE=>1,RSVP=>1,XLICERRORTYPE=>1,XLICCOMPARETYPE=>1);
+
+%params = read_parameters_file($ARGV[0]);
+
+
+# Write the file inline by copying everything before a demarcation
+# line, and putting the generated data after the demarcation
+
+if ($opt_i) {
+
+ open(IN,$opt_i) || die "Can't open input file $opt_i";
+
+ while(<IN>){
+
+ if (/Do not edit/){
+ last;
+ }
+
+ print;
+
+ }
+
+ if($opt_p){
+ print "# Everything below this line is machine generated. Do not edit. \n";
+ } else {
+ print "/* Everything below this line is machine generated. Do not edit. */\n";
+ }
+
+}
+
+
+# Write parameter string map
+if ($opt_c){
+}
+
+# Write parameter enumerations and datatypes
+
+if($opt_h){
+ print "typedef enum icalparameter_kind {\n ICAL_ANY_PARAMETER = 0,\n";
+ foreach $param (sort keys %params) {
+
+ next if !$param;
+
+ next if $param eq 'NO' or $param eq 'ANY';
+
+ my $uc = join("",map {uc($_);} split(/-/,$param));
+
+ my @enums = @{$params{$param}->{'enums'}};
+
+ print " ICAL_${uc}_PARAMETER, \n";
+
+ }
+ print " ICAL_NO_PARAMETER\n} icalparameter_kind;\n\n";
+
+ # Now create enumerations for parameter values
+ $idx = 20000;
+
+ print "#define ICALPARAMETER_FIRST_ENUM $idx\n\n";
+
+ foreach $param (sort keys %params) {
+
+ next if !$param;
+
+ next if $param eq 'NO' or $prop eq 'ANY';
+
+ my $type = $params{$param}->{"C"};
+ my $ucv = join("",map {uc(lc($_));} split(/-/,$param));
+ my @enums = @{$params{$param}->{'enums'}};
+
+ if(@enums){
+
+ print "typedef enum $type {\n";
+ my $first = 1;
+
+ unshift(@enums,"X");
+
+ push(@enums,"NONE");
+
+ foreach $e (@enums) {
+ if (!$first){
+ print ",\n";
+ } else {
+ $first = 0;
+ }
+
+ my $uce = join("",map {uc(lc($_));} split(/-/,$e));
+
+ print " ICAL_${ucv}_${uce} = $idx";
+
+ $idx++;
+ }
+ $c_type =~ s/enum //;
+
+ print "\n} $type;\n\n";
+ }
+ }
+
+ print "#define ICALPARAMETER_LAST_ENUM $idx\n\n";
+
+}
+
+if ($opt_c){
+
+ # Create the icalparameter_value to icalvalue_kind conversion table
+ print "static struct icalparameter_value_kind_map value_kind_map[] = {\n";
+
+ foreach $enum (@{$params{'VALUE'}->{'enums'}}){
+ next if $enum eq 'NO' or $enum eq 'ERROR';
+ $uc = join("",map {uc(lc($_));} split(/-/,$enum));
+ print " {ICAL_VALUE_${uc},ICAL_${uc}_VALUE},\n";
+ }
+
+ print " {ICAL_VALUE_X,ICAL_X_VALUE},\n";
+ print " {ICAL_VALUE_NONE,ICAL_NO_VALUE}\n};\n\n";
+
+ #Create the parameter Name map
+ print "static struct icalparameter_kind_map parameter_map[] = { \n";
+
+ foreach $param (sort keys %params) {
+
+ next if !$param;
+
+ next if $param eq 'NO' or $prop eq 'ANY';
+
+ my $lc = join("",map {lc($_);} split(/-/,$param));
+ my $uc = join("",map {uc(lc($_));} split(/-/,$param));
+
+
+ print " {ICAL_${uc}_PARAMETER,\"$param\"},\n";
+
+ }
+
+ print " { ICAL_NO_PARAMETER, \"\"}\n};\n\n";
+
+ # Create the parameter value map
+
+ print "static struct icalparameter_map icalparameter_map[] = {\n";
+ print "{ICAL_ANY_PARAMETER,0,\"\"},\n";
+
+ foreach $param (sort keys %params) {
+
+ next if !$param;
+
+ next if $param eq 'NO' or $prop eq 'ANY';
+
+ my $type = $params{$param}->{"C"};
+ my $uc = join("",map {uc(lc($_));} split(/-/,$param));
+ my @enums = @{$params{$param}->{'enums'}};
+
+ if(@enums){
+
+ foreach $e (@enums){
+ my $uce = join("",map {uc(lc($_));} split(/-/,$e));
+
+ print " {ICAL_${uc}_PARAMETER,ICAL_${uc}_${uce},\"$e\"},\n";
+ }
+
+ }
+ }
+
+ print " {ICAL_NO_PARAMETER,0,\"\"}};\n\n";
+
+}
+
+foreach $param (keys %params){
+
+ my $type = $params{$param}->{'C'};
+
+ my $ucf = join("",map {ucfirst(lc($_));} split(/-/,$param));
+
+ my $lc = lc($ucf);
+ my $uc = uc($lc);
+
+ my $charorenum;
+ my $set_code;
+ my $pointer_check;
+ my $pointer_check_v;
+ my $xrange;
+
+ if ($type=~/char/ ) {
+
+ $charorenum = " icalerror_check_arg_rz( (param!=0), \"param\");\n return ($type)((struct icalparameter_impl*)param)->string;";
+
+ $set_code = "((struct icalparameter_impl*)param)->string = icalmemory_strdup(v);";
+
+ $pointer_check = "icalerror_check_arg_rz( (v!=0),\"v\");";
+ $pointer_check_v = "icalerror_check_arg_rv( (v!=0),\"v\");";
+
+ } else {
+
+ $xrange =" if ( ((struct icalparameter_impl*)param)->string != 0){\n return ICAL_${uc}_X;\n }\n" if !exists $no_xname{$uc};
+
+ $charorenum= "icalerror_check_arg( (param!=0), \"param\");\n$xrange\nreturn ($type)((struct icalparameter_impl*)param)->data;";
+
+ $pointer_check = "icalerror_check_arg_rz(v >= ICAL_${uc}_X,\"v\");\n icalerror_check_arg_rz(v < ICAL_${uc}_NONE,\"v\");";
+
+ $pointer_check_v = "icalerror_check_arg_rv(v >= ICAL_${uc}_X,\"v\");\n icalerror_check_arg_rv(v < ICAL_${uc}_NONE,\"v\");";
+
+ $set_code = "((struct icalparameter_impl*)param)->data = (int)v;";
+
+ }
+
+
+
+ if ($opt_c) {
+
+ print <<EOM;
+/* $param */
+icalparameter* icalparameter_new_${lc}($type v)
+{
+ struct icalparameter_impl *impl;
+ icalerror_clear_errno();
+ $pointer_check
+ impl = icalparameter_new_impl(ICAL_${uc}_PARAMETER);
+ if (impl == 0) {
+ return 0;
+ }
+
+ icalparameter_set_${lc}((icalparameter*) impl,v);
+ if (icalerrno != ICAL_NO_ERROR) {
+ icalparameter_free((icalparameter*) impl);
+ return 0;
+ }
+
+ return (icalparameter*) impl;
+}
+
+${type} icalparameter_get_${lc}(icalparameter* param)
+{
+ icalerror_clear_errno();
+$charorenum
+}
+
+void icalparameter_set_${lc}(icalparameter* param, ${type} v)
+{
+ $pointer_check_v
+ icalerror_check_arg_rv( (param!=0), "param");
+ icalerror_clear_errno();
+
+ $set_code
+}
+
+EOM
+
+ } elsif( $opt_h) {
+
+ print <<EOM;
+/* $param */
+icalparameter* icalparameter_new_${lc}($type v);
+${type} icalparameter_get_${lc}(icalparameter* value);
+void icalparameter_set_${lc}(icalparameter* value, ${type} v);
+
+EOM
+
+}
+
+if ($opt_p) {
+
+ print <<EOM;
+
+# $param
+
+package Net::ICal::Parameter::${ucf};
+\@ISA=qw(Net::ICal::Parameter);
+
+sub new
+{
+ my \$self = [];
+ my \$package = shift;
+ my \$value = shift;
+
+ bless \$self, \$package;
+
+ my \$p;
+
+ if (\$value) {
+ \$p = Net::ICal::icalparameter_new_from_string(\$Net::ICal::ICAL_${uc}_PARAMETER,\$value);
+ } else {
+ \$p = Net::ICal::icalparameter_new(\$Net::ICal::ICAL_${uc}_PARAMETER);
+ }
+
+ \$self->[0] = \$p;
+
+ return \$self;
+}
+
+sub get
+{
+ my \$self = shift;
+ my \$impl = \$self->_impl();
+
+ return Net::ICal::icalparameter_as_ical_string(\$impl);
+
+}
+
+sub set
+{
+ # This is hard to implement, so I've punted for now.
+ die "Set is not implemented";
+}
+
+EOM
+
+}
+
+}
+
+if ($opt_h){
+
+print <<EOM;
+#endif /*ICALPARAMETER_H*/
+
+EOM
+}
diff --git a/src/plugins/vcalendar/libical/scripts/mkderivedproperties.pl b/src/plugins/vcalendar/libical/scripts/mkderivedproperties.pl
@@ -0,0 +1,217 @@
+#!/usr/local/bin/perl
+
+require "readvaluesfile.pl";
+
+use Getopt::Std;
+getopts('chspmi:');
+
+# ARG 0 is properties.csv
+%propmap = read_properties_file($ARGV[0]);
+
+# ARG 1 is value-types.txt
+%valuemap = read_values_file($ARGV[1]);
+
+
+# Write the file inline by copying everything before a demarcation
+# line, and putting the generated data after the demarcation
+
+if ($opt_i) {
+
+ open(IN,$opt_i) || die "Can't open input file $opt_i";
+
+ while(<IN>){
+
+ if (/Do not edit/){
+ last;
+ }
+
+ print;
+
+ }
+
+ print "/* Everything below this line is machine generated. Do not edit. */\n";
+
+
+}
+
+sub fudge_data {
+ my $prop = shift;
+
+ my $value = $propmap{$prop}->{'lic_value'};
+
+ if (!$value){
+ die "Can't find value for property \"$prop\"\n";
+ }
+ my $ucf = join("",map {ucfirst(lc($_));} split(/-/,$prop));
+ my $lc = lc($ucf);
+ my $uc = uc($lc);
+
+ my $ucfvalue = join("",map {ucfirst(lc($_));} split(/-/,$value));
+ my $lcvalue = lc($ucfvalue);
+ my $ucvalue = uc($lcvalue);
+
+ my $type = $valuemap{$value}->{C}->[1];
+
+ return ($uc,$lc,$lcvalue,$ucvalue,$type);
+
+}
+
+# Create the property map data
+if($opt_c){
+
+ print "static struct icalproperty_map property_map[] = {\n";
+
+ foreach $prop (sort keys %propmap) {
+
+ next if !$prop;
+
+ next if $prop eq 'NO';
+
+ my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
+
+ print "{ICAL_${uc}_PROPERTY,\"$prop\",ICAL_${ucvalue}_VALUE},\n";
+
+ }
+
+ $prop = "NO";
+
+ my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
+
+ print "{ICAL_${uc}_PROPERTY,\"\",ICAL_NO_VALUE}};\n\n";
+
+
+ print "static struct icalproperty_enum_map enum_map[] = {\n";
+
+ $idx = 10000;
+
+ foreach $value (sort keys %valuemap) {
+
+ next if !$value;
+ next if $value eq 'NO' or $prop eq 'ANY';
+
+ my $ucv = join("",map {uc(lc($_));} split(/-/,$value));
+ my @enums = @{$valuemap{$value}->{'enums'}};
+
+ if(@enums){
+
+ my ($c_autogen,$c_type) = @{$valuemap{$value}->{'C'}};
+
+ unshift(@enums,"X");
+ push(@enums,"NONE");
+
+ foreach $e (@enums) {
+
+ my $uce = join("",map {uc(lc($_));} split(/-/,$e));
+
+ if($e ne "X" and $e ne "NONE"){
+ $str = $e;
+ } else {
+ $str = "";
+ }
+
+ print " {ICAL_${ucv}_PROPERTY,ICAL_${ucv}_${uce},\"$str\" }, /*$idx*/\n";
+
+ $idx++;
+ }
+
+ }
+ }
+ print " {ICAL_NO_PROPERTY,0,\"\"}\n};\n\n";
+
+
+}
+
+
+if($opt_h){
+
+ # Create the property enumerations list
+ print "typedef enum icalproperty_kind {\n ICAL_ANY_PROPERTY = 0,\n";
+ foreach $prop (sort keys %propmap) {
+
+ next if !$prop;
+
+ next if $prop eq 'NO' or $prop eq 'ANY';
+
+ my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
+
+ print " ICAL_${uc}_PROPERTY, \n";
+
+ }
+ print " ICAL_NO_PROPERTY\n} icalproperty_kind;\n\n";
+
+
+}
+
+
+foreach $prop (sort keys %propmap) {
+
+ next if !$prop;
+
+ next if $prop eq 'NO' or $prop eq 'ANY';
+
+ my ($uc,$lc,$lcvalue,$ucvalue,$type) = fudge_data($prop);
+
+
+ my $pointer_check;
+ if ($type =~ /\*/){
+ $pointer_check = "icalerror_check_arg_rz( (v!=0),\"v\");\n" if $type =~ /\*/;
+ } elsif ( $type eq "void" ){
+ $pointer_check = "icalerror_check_arg_rv( (v!=0),\"v\");\n" if $type =~ /\*/;
+
+ }
+
+ my $set_pointer_check = "icalerror_check_arg_rv( (v!=0),\"v\");\n" if $type =~ /\*/;
+
+ if($opt_c) { # Generate C source
+ print<<EOM;
+/* $prop */
+icalproperty* icalproperty_new_${lc}($type v) {
+ struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_${uc}_PROPERTY); $pointer_check
+ icalproperty_set_${lc}((icalproperty*)impl,v);
+ return (icalproperty*)impl;
+}
+icalproperty* icalproperty_vanew_${lc}($type v, ...){
+ va_list args;
+ struct icalproperty_impl *impl = icalproperty_new_impl(ICAL_${uc}_PROPERTY); $pointer_check
+ icalproperty_set_${lc}((icalproperty*)impl,v);
+ va_start(args,v);
+ icalproperty_add_parameters(impl, args);
+ va_end(args);
+ return (icalproperty*)impl;
+}
+void icalproperty_set_${lc}(icalproperty* prop, $type v){
+ icalvalue *value;
+ $set_pointer_check
+ icalerror_check_arg_rv( (prop!=0),"prop");
+ value = icalvalue_new_${lcvalue}(v);
+ icalproperty_set_value(prop,value);
+}
+$type icalproperty_get_${lc}(icalproperty* prop){
+ icalvalue *value;
+ icalerror_check_arg( (prop!=0),"prop");
+ value = icalproperty_get_value(prop);
+ return icalvalue_get_${lcvalue}(value);
+}
+EOM
+
+
+ } elsif ($opt_h) { # Generate C Header file
+ print "\
+/* $prop */\
+icalproperty* icalproperty_new_${lc}($type v);\
+icalproperty* icalproperty_vanew_${lc}($type v, ...);\
+void icalproperty_set_${lc}(icalproperty* prop, $type v);\
+$type icalproperty_get_${lc}(icalproperty* prop);";
+
+}
+
+
+} # This brace terminates the main loop
+
+
+
+if ($opt_h){
+
+print "\n\n#endif /*ICALPROPERTY_H*/\n"
+}
+
diff --git a/src/plugins/vcalendar/libical/scripts/mkderivedvalues.pl b/src/plugins/vcalendar/libical/scripts/mkderivedvalues.pl
@@ -0,0 +1,229 @@
+#!/usr/bin/perl
+
+use lib '.';
+
+require 'readvaluesfile.pl';
+
+use Getopt::Std;
+getopts('chi:');
+
+ #Options
+ # c -> generate c code file
+ # h-> generate header file
+
+ # Open with value-types.txt
+
+my %h = read_values_file($ARGV[0]);
+
+
+ # Write the file inline by copying everything before a demarcation
+ # line, and putting the generated data after the demarcation
+
+if ($opt_i) {
+
+ open(IN,$opt_i) || die "Can't open input file $opt_i";
+
+ while(<IN>){
+ print;
+ }
+}
+
+
+ # Map type names to the value in the icalvalue_impl data union */
+
+%union_map = (
+ BOOLEAN => 'int',
+ CALADDRESS=>'string',
+ DATE=>'time',
+ DATETIME=>'time',
+ DATETIMEDATE=>'time',
+ DATETIMEPERIOD=>'period',
+ DURATION=>'duration',
+ INTEGER=>'int',
+ TEXT=>'string',
+ URI=>'string',
+ UTCOFFSET=>'int',
+ QUERY=>'string',
+ BINARY=>'string',
+ X=>'string'
+ );
+
+
+if($opt_h){
+
+ # First print out the value enumerations
+ $idx = 5000;
+ print "typedef enum icalvalue_kind {\n";
+ print " ICAL_ANY_VALUE=$idx,\n";
+
+ foreach $value (keys %h) {
+
+ $idx++;
+ my $ucv = join("",map {uc(lc($_));} split(/-/,$value));
+
+ next if $value eq "NO";
+
+ print " ICAL_${ucv}_VALUE=$idx,\n";
+ }
+
+ $idx++;
+ print " ICAL_NO_VALUE=$idx\n} icalvalue_kind ;\n\n";
+
+ # Now create enumerations for property values
+ $idx = 10000;
+
+ print "#define ICALPROPERTY_FIRST_ENUM $idx\n\n";
+
+ foreach $value (sort keys %h) {
+
+ next if !$value;
+
+ next if $value eq 'NO' or $prop eq 'ANY';
+
+ my $ucv = join("",map {uc(lc($_));} split(/-/,$value));
+ my @enums = @{$h{$value}->{'enums'}};
+
+ if(@enums){
+
+ my ($c_autogen,$c_type) = @{$h{$value}->{'C'}};
+ print "typedef $c_type {\n";
+ my $first = 1;
+
+ unshift(@enums,"X");
+
+ push(@enums,"NONE");
+
+ foreach $e (@enums) {
+ if (!$first){
+ print ",\n";
+ } else {
+ $first = 0;
+ }
+
+ my $uce = join("",map {uc(lc($_));} split(/-/,$e));
+
+ print " ICAL_${ucv}_${uce} = $idx";
+
+ $idx++;
+ }
+
+ $c_type =~ s/enum //;
+
+ print "\n} $c_type;\n\n";
+ }
+ }
+
+ print "#define ICALPROPERTY_LAST_ENUM $idx\n\n";
+
+}
+
+
+if($opt_c){
+
+ # print out the value to string map
+
+ print "static struct icalvalue_kind_map value_map[]={\n";
+
+ foreach $value (keys %h) {
+
+ $idx++;
+ my $ucv = join("",map {uc(lc($_));} split(/-/,$value));
+
+ next if $value eq "NO";
+
+ print " {ICAL_${ucv}_VALUE,\"$value\"},\n";
+ }
+
+
+ print " {ICAL_NO_VALUE,\"\"}\n};";
+
+}
+
+
+foreach $value (keys %h) {
+
+ my $autogen = $h{$value}->{C}->[0];
+ my $type = $h{$value}->{C}->[1];
+
+ my $ucf = join("",map {ucfirst(lc($_));} split(/-/,$value));
+
+ my $lc = lc($ucf);
+ my $uc = uc($lc);
+
+ my $pointer_check = "icalerror_check_arg_rz( (v!=0),\"v\");\n" if $type =~ /\*/;
+ my $pointer_check_rv = "icalerror_check_arg_rv( (v!=0),\"v\");\n" if $type =~ /\*/;
+
+ my $assign;
+
+ if ($type =~ /char/){
+ $assign = "icalmemory_strdup(v);\n\n if (impl->data.v_string == 0){\n errno = ENOMEM;\n }\n";
+ } else {
+ $assign = "v;";
+ }
+
+ my $union_data;
+
+ if(@{$h{$value}->{'enums'}}){
+ $union_data = 'enum';
+
+ } elsif (exists $union_map{$uc} ){
+ $union_data=$union_map{$uc};
+ } else {
+ $union_data = $lc;
+ }
+
+ if ($opt_c && $autogen) {
+
+ print "\n\n\
+icalvalue* icalvalue_new_${lc} ($type v){\
+ struct icalvalue_impl* impl = icalvalue_new_impl(ICAL_${uc}_VALUE);\
+ $pointer_check\
+ icalvalue_set_${lc}((icalvalue*)impl,v);\
+ return (icalvalue*)impl;\
+}\
+void icalvalue_set_${lc}(icalvalue* value, $type v) {\
+ struct icalvalue_impl* impl; \
+ icalerror_check_arg_rv( (value!=0),\"value\");\
+ $pointer_check_rv\
+ icalerror_check_value_type(value, ICAL_${uc}_VALUE);\
+ impl = (struct icalvalue_impl*)value;\n";
+
+ if( $union_data eq 'string') {
+
+ print " if(impl->data.v_${union_data}!=0) {free((void*)impl->data.v_${union_data});}\n";
+ }
+
+
+ print "\n impl->data.v_$union_data = $assign \n }\n";
+
+ if ($type =~ /char/){
+ print "$type\ icalvalue_get_${lc}(icalvalue* value)\ {\n\
+ icalerror_check_arg_rz( (value!=0),\"value\");\
+ icalerror_check_value_type(value, ICAL_${uc}_VALUE);\
+ return ((struct icalvalue_impl*)value)->data.v_${union_data};\n}\n";
+ } else {
+ print "$type\ icalvalue_get_${lc}(icalvalue* value)\ {\n\
+ icalerror_check_arg( (value!=0),\"value\");\
+ icalerror_check_value_type(value, ICAL_${uc}_VALUE);\
+ return ((struct icalvalue_impl*)value)->data.v_${union_data};\n}\n";
+ }
+
+ } elsif($opt_h && $autogen) {
+
+ print "\n /* $value */ \
+icalvalue* icalvalue_new_${lc}($type v); \
+$type icalvalue_get_${lc}(icalvalue* value); \
+void icalvalue_set_${lc}(icalvalue* value, ${type} v);\n\n";
+
+ }
+
+}
+
+
+if ($opt_h){
+ print "#endif /*ICALVALUE_H*/\n";
+ }
+
+
+ __END__
+
diff --git a/src/plugins/vcalendar/libical/scripts/mkparameterrestrictions.pl b/src/plugins/vcalendar/libical/scripts/mkparameterrestrictions.pl
@@ -0,0 +1,85 @@
+#!/usr/bin/perl
+
+# Version: 1.0
+# Script last updated: 30May1999 GMD
+# Change log:
+# <none>
+
+
+# usually open params-in-prop.txt
+open(F,"$ARGV[0]") || die "Can't open restriction file $ARGV[0]:$!";
+
+print <<EOM;
+/*
+ ======================================================================
+ File: parameterrestrictions.c
+
+ (C) COPYRIGHT 1999 Graham Davison
+ mailto:g.m.davison\@computer.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+
+ ======================================================================*/
+
+/*
+ * THIS FILE IS MACHINE GENERATED DO NOT EDIT
+ */
+
+
+int icalrestriction_is_parameter_allowed(icalproperty_kind prop,icalparameter_kind param)
+{
+ switch (prop)
+ {
+EOM
+
+while(<F>)
+{
+ chop;
+
+ # split line by whitespace
+ my @v = split(/\s+/,$_);
+ # property is first item on line
+ my $prop = shift @v;
+ my $prop_name = $prop;
+ if (substr($prop,0,1) eq "X") { $prop = "X"; }
+ $prop = join("",split(/-/,$prop));
+
+print <<EOM;
+
+ /* ${prop_name} */
+ case ICAL_${prop}_PROPERTY:
+ switch (param)
+ {
+EOM
+
+ foreach $param (@v)
+ {
+ $param = join("",split(/-/,$param));
+ print "\t\t\t\tcase ICAL_${param}_PARAMETER:\n";
+ }
+
+print <<EOM;
+ return 1;
+ default:
+ return 0;
+ }
+
+EOM
+
+}
+
+print <<EOM;
+ }
+
+ return 0;
+}
+EOM
diff --git a/src/plugins/vcalendar/libical/scripts/mkrestrictionrecords.pl b/src/plugins/vcalendar/libical/scripts/mkrestrictionrecords.pl
@@ -0,0 +1,109 @@
+#!/usr/bin/perl
+
+# Version: 1.0
+# Script last updated: 30May1999 GMD
+# Change log:
+# <none>
+
+# usually open restrictions.csv
+open(F,"$ARGV[0]") || die "Can't open restriction file $ARGV[0]:$!";
+
+print <<EOM;
+/*
+ ======================================================================
+ File: restrictionrecords.c
+
+ (C) COPYRIGHT 1999 Graham Davison
+ mailto:g.m.davison\@computer.org
+
+ The contents of this file are subject to the Mozilla Public License
+ Version 1.0 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and
+ limitations under the License.
+
+
+ ======================================================================*/
+
+
+/*
+ * THIS FILE IS MACHINE GENERATED DO NOT EDIT
+ */
+
+
+typedef struct icalrestriction_record {
+ icalproperty_method method;
+ icalcomponent_kind component;
+ icalproperty_kind property;
+ icalcomponent_kind subcomponent;
+ icalrestriction_kind restriction;
+} icalrestriction_record;
+
+
+icalrestriction_record icalrestriction_records[] =
+{
+EOM
+
+my $last_method = "";
+my $last_component = "";
+my $last_property = "";
+my $need_header = 0;
+
+while(<F>)
+{
+ chop;
+
+ # split line at commas
+ my ($method,$component,$property,$subcomponent,$restriction)=split(/\,/,$_);
+
+ #
+ #put in code to generate comments here!
+ #
+ if ($method ne $last_method)
+ {
+ $need_header = 1;
+ $last_method = $method;
+ }
+ if ($component ne $last_component)
+ {
+ $need_header = 1;
+ $last_component = $component;
+ }
+
+ if ($need_header)
+ {
+ print "\n\t/* METHOD: ${method}, COMPONENT: ${component} */\n";
+ $need_header = 0;
+ }
+
+ foreach $item ($component,$property,$subcomponent,$restriction)
+ {
+ # handle special cases.
+ if ($item eq "NONE")
+ { $item = "NO"; }
+ else { if (substr($item,0,1) eq "X")
+ { $item = "X"; }}
+
+ # strip out dashes
+ $item = join("",split(/-/,$item));
+ }
+ # strip leading V from component names
+ $component =~ s/^(V?)(\w+?)((SAVINGS)?)((TIME)?)$/$2/;
+ $subcomponent =~ s/^V(\w+)/$1/;
+
+ print "\t\{ICAL_METHOD_${method},ICAL_${component}_COMPONENT,";
+ print "ICAL_${property}_PROPERTY,ICAL_${subcomponent}_COMPONENT,";
+ print "ICAL_RESTRICTION_${restriction}\},\n";
+
+}
+
+print <<EOM;
+
+ /* END */
+ {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_NO_COMPONENT,ICAL_RESTRICTION_NONE}
+};
+EOM
diff --git a/src/plugins/vcalendar/libical/scripts/mkrestrictiontable.pl b/src/plugins/vcalendar/libical/scripts/mkrestrictiontable.pl
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+
+use Getopt::Std;
+getopts('i:');
+
+# the argument should be the path to the restriction datafile, usually
+# design-data/restrictions.csv
+open(F,"$ARGV[0]") || die "Can't open restriction data file $ARGV[0]:$!";
+
+# Write the file inline by copying everything before a demarcation
+# line, and putting the generated data after the demarcation
+
+if ($opt_i) {
+
+ open(IN,$opt_i) || die "Can't open input file $opt_i";
+
+ while(<IN>){
+
+ if (/Do not edit/){
+ last;
+ }
+
+ print;
+
+ }
+
+ print "/* Everything below this line is machine generated. Do not edit. */\n";
+
+
+ close IN;
+}
+
+# First build the property restriction table
+print "icalrestriction_property_record icalrestriction_property_records[] = {\n";
+
+while(<F>)
+{
+
+ chop;
+
+ s/\#.*$//;
+
+ my($method,$targetcomp,$prop,$subcomp,$restr,$sub) = split(/,/,$_);
+
+ next if !$method;
+
+ if(!$sub) {
+ $sub = "0";
+ } else {
+ $sub = "icalrestriction_".$sub;
+ }
+
+ if($prop ne "NONE"){
+ print(" \{ICAL_METHOD_${method},ICAL_${targetcomp}_COMPONENT,ICAL_${prop}_PROPERTY,ICAL_RESTRICTION_${restr},$sub},\n");
+ }
+
+}
+
+
+# Print the terminating line
+print " {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_RESTRICTION_NONE}\n";
+
+print "};\n";
+
+print "icalrestriction_component_record icalrestriction_component_records[] = {\n";
+
+
+# Go back through the entire file and build the component restriction table
+close(F);
+open(F,"$ARGV[0]") || die "Can't open restriction data file $ARGV[0]:$!";
+
+while(<F>)
+{
+
+ chop;
+
+ s/\#.*$//;
+
+ my($method,$targetcomp,$prop,$subcomp,$restr,$sub) = split(/,/,$_);
+
+ next if !$method;
+
+ if(!$sub) {
+ $sub = "0";
+ } else {
+ $sub = "icalrestriction_".$sub;
+ }
+
+
+ if($subcomp ne "NONE"){
+ print(" \{ICAL_METHOD_${method},ICAL_${targetcomp}_COMPONENT,ICAL_${subcomp}_COMPONENT,ICAL_RESTRICTION_${restr},$sub\},\n");
+ }
+
+}
+
+# print the terminating line
+print " {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_COMPONENT,ICAL_RESTRICTION_NONE}\n";
+print "};\n";
diff --git a/src/plugins/vcalendar/libical/scripts/readvaluesfile.pl b/src/plugins/vcalendar/libical/scripts/readvaluesfile.pl
@@ -0,0 +1,130 @@
+
+
+sub read_values_file {
+
+ my $path = shift;
+ my %h;
+
+ open(F,$path) || die "Can't open values file $path";
+
+ while(<F>){
+
+ chop;
+
+ s/#.*$//g;
+ s/\"//g;
+
+ next if ! $_;
+
+ @column = split(/,/,$_);
+
+ my $value_name = $column[0];
+
+ my $c_type_str = $column[1];
+ my $c_autogen = ($c_type_str =~ /\(a\)/);
+
+ my $c_type = $c_type_str;
+ $c_type =~ s/\(.\)//;
+
+ my $python_type = $column[2];
+ my $components = $column[3];
+ my $enum_values = $column[4];
+
+ my @components;
+ if($components ne "unitary"){
+ @components = split(/;/,$components);
+ } else {
+ @components = ();
+ }
+
+ my @enums;
+ if($enum_values) {
+ @enums = split(/;/,$enum_values);
+
+ } else {
+ @enums = ();
+ }
+
+ $h{$value_name} = { C => [$c_autogen,$c_type],
+ perl => $perl_type,
+ python => $python_type,
+ components=>[@components],
+ enums=>[@enums]
+ };
+ }
+
+ return %h;
+}
+
+sub read_properties_file {
+
+ my $path = shift;
+ my %h;
+
+ open(F,$path) || die "Can't open properties file $path";
+
+ while(<F>){
+
+ chop;
+
+ s/#.*$//g;
+ s/\"//g;
+
+ next if ! $_;
+
+ @column = split(/,/,$_);
+
+ my $property_name = $column[0];
+
+ my $lic_value = $column[1];
+ my $default_value = $column[2];
+
+ $h{$property_name} = { lic_value => $lic_value,
+ default_value => $default_value
+ };
+ }
+
+ return %h;
+}
+
+sub read_parameters_file {
+
+ my $path = shift;
+ my %h;
+
+ open(F,$path) || die "Can't open parameters file $path";
+
+ while(<F>){
+
+ chop;
+
+ s/#.*$//g;
+ s/\"//g;
+
+ next if ! $_;
+
+ @column = split(/\,/,$_);
+
+ my $parameter_name = $column[0];
+
+ my $data_type = $column[1];
+ my $enum_string = $column[2];
+
+ my @enums;
+ if($enum_string){
+ @enums = split(/;/,$enum_string);
+ }
+
+ $h{$parameter_name} = { C => $data_type,
+ enums => [@enums]
+ };
+ }
+
+ close(F);
+
+ return %h;
+}
+
+
+
+1;
diff --git a/src/plugins/vcalendar/month-view.c b/src/plugins/vcalendar/month-view.c
@@ -0,0 +1,1020 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ *
+ * Copyright (c) 2007-2008 Juha Kautto (juha at xfce.org)
+ * Copyright (c) 2008 Colin Leroy (colin@colino.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "defs.h"
+
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "summaryview.h"
+#include "vcalendar.h"
+#include "vcal_folder.h"
+#include "vcal_prefs.h"
+#include "vcal_manager.h"
+#include "common-views.h"
+#include "vcal_meeting_gtk.h"
+
+#define MAX_DAYS 40
+struct _month_win
+{
+ GtkAccelGroup *accel_group;
+#if !GTK_CHECK_VERSION(2,12,0)
+ GtkTooltips *Tooltips;
+#endif
+ GtkWidget *Window;
+ GtkWidget *Vbox;
+
+ GtkWidget *Menubar;
+ GtkWidget *File_menu;
+ GtkWidget *File_menu_new;
+ GtkWidget *File_menu_close;
+ GtkWidget *View_menu;
+ GtkWidget *View_menu_refresh;
+ GtkWidget *Go_menu;
+ GtkWidget *Go_menu_today;
+ GtkWidget *Go_menu_prev;
+ GtkWidget *Go_menu_next;
+
+ GtkWidget *Toolbar;
+ GtkWidget *Create_toolbutton;
+ GtkWidget *Previous_toolbutton;
+ GtkWidget *Today_toolbutton;
+ GtkWidget *Next_toolbutton;
+ GtkWidget *Refresh_toolbutton;
+ GtkWidget *Close_toolbutton;
+
+ GtkWidget *StartDate_button;
+ GtkRequisition StartDate_button_req;
+ GtkWidget *day_spin;
+
+ GtkWidget *month_view_vbox;
+ GtkWidget *scroll_win_h;
+ GtkWidget *dtable_h; /* header of day table */
+ GtkWidget *scroll_win;
+ GtkWidget *dtable; /* day table */
+ GtkRequisition hour_req;
+
+ GtkWidget *header[MAX_DAYS];
+ GtkWidget *element[6][MAX_DAYS];
+ GtkWidget *line[6][MAX_DAYS];
+
+ guint upd_timer;
+ gdouble scroll_pos; /* remember the scroll position */
+
+ GdkColor bg1, bg2, line_color, bg_today, fg_sunday;
+ GList *apptw_list; /* keep track of appointments being updated */
+ struct tm startdate;
+ FolderItem *item;
+ gulong selsig;
+ GtkWidget *view_menu;
+ GtkWidget *event_menu;
+ GtkActionGroup *event_group;
+ GtkUIManager *ui_manager;
+};
+
+gchar *dayname[7] = {
+ N_("Monday"),
+ N_("Tuesday"),
+ N_("Wednesday"),
+ N_("Thursday"),
+ N_("Friday"),
+ N_("Saturday"),
+ N_("Sunday")
+ };
+gchar *monthname[12] = {
+ N_("January"),
+ N_("February"),
+ N_("March"),
+ N_("April"),
+ N_("May"),
+ N_("June"),
+ N_("July"),
+ N_("August"),
+ N_("September"),
+ N_("October"),
+ N_("November"),
+ N_("December")
+ };
+
+static gchar *get_locale_date(struct tm *tmdate)
+{
+ gchar *d = g_malloc(100);
+ strftime(d, 99, "%x", tmdate);
+ return d;
+}
+
+void mw_close_window(month_win *mw)
+{
+ vcal_view_set_summary_page(mw->Vbox, mw->selsig);
+
+#if !(GTK_CHECK_VERSION(2,12,0))
+ gtk_object_destroy(G_OBJECT(mw->Tooltips));
+#endif
+ g_free(mw);
+ mw = NULL;
+}
+
+static char *orage_tm_date_to_i18_date(struct tm *tm_date)
+{
+ static char i18_date[32];
+ struct tm t;
+ t.tm_mday = tm_date->tm_mday;
+ t.tm_mon = tm_date->tm_mon - 1;
+ t.tm_year = tm_date->tm_year - 1900;
+ if (strftime(i18_date, 32, "%x", &t) == 0)
+ g_error("Orage: orage_tm_date_to_i18_date too long string in strftime");
+ return(i18_date);
+}
+
+static void changeSelectedDate(month_win *mw, gint month)
+{
+ gint curmon = mw->startdate.tm_mon;
+ if (month > 0) {
+ do { /* go to first of next month */
+ orage_move_day(&(mw->startdate), 1);
+ } while (curmon == mw->startdate.tm_mon);
+ } else {
+ do { /* go to last day of last month */
+ orage_move_day(&(mw->startdate), -1);
+ } while (curmon == mw->startdate.tm_mon);
+ do { /* go to first of last month */
+ orage_move_day(&(mw->startdate), -1);
+ } while (mw->startdate.tm_mday > 1);
+ }
+}
+
+static gint on_Previous_clicked(GtkWidget *button, GdkEventButton *event,
+ month_win *mw)
+{
+ changeSelectedDate(mw, -1);
+ refresh_month_win(mw);
+ return TRUE;
+}
+
+static gint on_Next_clicked(GtkWidget *button, GdkEventButton *event,
+ month_win *mw)
+{
+ changeSelectedDate(mw, +1);
+ refresh_month_win(mw);
+ return TRUE;
+}
+
+static void mw_summary_selected(GtkCMCTree *ctree, GtkCMCTreeNode *row,
+ gint column, month_win *mw)
+{
+ MsgInfo *msginfo = gtk_cmctree_node_get_row_data(ctree, row);
+
+ if (msginfo && msginfo->msgid) {
+ VCalEvent *event = vcal_manager_load_event(msginfo->msgid);
+ if (event) {
+ struct tm tm_start;
+ time_t t_start = icaltime_as_timet(icaltime_from_string(event->dtstart));
+ gboolean changed = FALSE;
+
+#ifdef G_OS_WIN32
+ if (t_start < 0)
+ t_start = 1;
+#endif
+ localtime_r(&t_start, &tm_start);
+ while (tm_start.tm_year < mw->startdate.tm_year) {
+ changeSelectedDate(mw, -1);
+ changed = TRUE;
+ }
+ while (tm_start.tm_year > mw->startdate.tm_year) {
+ changeSelectedDate(mw, +1);
+ changed = TRUE;
+ }
+ while (tm_start.tm_mon < mw->startdate.tm_mon) {
+ changeSelectedDate(mw, -1);
+ changed = TRUE;
+ }
+ while (tm_start.tm_mon > mw->startdate.tm_mon) {
+ changeSelectedDate(mw, +1);
+ changed = TRUE;
+ }
+ if (changed)
+ refresh_month_win(mw);
+ }
+ vcal_manager_free_event(event);
+ }
+}
+
+static void month_view_new_meeting_cb(month_win *mw, gpointer data_i, gpointer data_s)
+{
+ int offset = GPOINTER_TO_INT(data_i);
+ struct tm tm_date = mw->startdate;
+
+ while (offset > tm_date.tm_mday) {
+ orage_move_day(&tm_date, 1);
+ }
+ while (offset < tm_date.tm_mday) {
+ orage_move_day(&tm_date, -1);
+ }
+ tm_date.tm_hour = 0;
+ vcal_meeting_create_with_start(NULL, &tm_date);
+}
+
+static void month_view_edit_meeting_cb(month_win *mw, gpointer data_i, gpointer data_s)
+{
+ const gchar *uid = (gchar *)data_s;
+ vcal_view_select_event (uid, mw->item, TRUE,
+ G_CALLBACK(mw_summary_selected), mw);
+}
+
+static void month_view_cancel_meeting_cb(month_win *mw, gpointer data_i, gpointer data_s)
+{
+ const gchar *uid = (gchar *)data_s;
+ vcalendar_cancel_meeting(mw->item, uid);
+}
+
+static void month_view_today_cb(month_win *mw, gpointer data_i, gpointer data_s)
+{
+ time_t now = time(NULL);
+ struct tm tm_today;
+ localtime_r(&now, &tm_today);
+
+ while (tm_today.tm_mday != 1)
+ orage_move_day(&tm_today, -1);
+
+ mw->startdate = tm_today;
+ refresh_month_win(mw);
+}
+
+static void header_button_clicked_cb(GtkWidget *button
+ , GdkEventButton *event, gpointer *user_data)
+{
+ month_win *mw = (month_win *)user_data;
+ int offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "day"));
+
+ if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
+ month_view_new_meeting_cb(mw, GINT_TO_POINTER(offset), NULL);
+ }
+ if (event->button == 3) {
+ g_object_set_data(G_OBJECT(mw->Vbox), "menu_win",
+ mw);
+ g_object_set_data(G_OBJECT(mw->Vbox), "menu_data_i",
+ GINT_TO_POINTER(offset));
+ g_object_set_data(G_OBJECT(mw->Vbox), "menu_data_s",
+ NULL);
+ g_object_set_data(G_OBJECT(mw->Vbox), "new_meeting_cb",
+ month_view_new_meeting_cb);
+ g_object_set_data(G_OBJECT(mw->Vbox), "go_today_cb",
+ month_view_today_cb);
+ gtk_menu_popup(GTK_MENU(mw->view_menu),
+ NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ }
+}
+
+static void on_button_press_event_cb(GtkWidget *widget
+ , GdkEventButton *event, gpointer *user_data)
+{
+ month_win *mw = (month_win *)user_data;
+ gchar *uid = g_object_get_data(G_OBJECT(widget), "UID");;
+ gpointer offset = g_object_get_data(G_OBJECT(widget), "offset");
+
+ if (event->button == 1) {
+ if (uid)
+ vcal_view_select_event (uid, mw->item, (event->type==GDK_2BUTTON_PRESS),
+ G_CALLBACK(mw_summary_selected), mw);
+ else if (event->type == GDK_2BUTTON_PRESS) {
+ month_view_new_meeting_cb(mw, GINT_TO_POINTER(offset), NULL);
+ }
+ }
+ if (event->button == 3) {
+ g_object_set_data(G_OBJECT(mw->Vbox), "menu_win",
+ mw);
+ g_object_set_data(G_OBJECT(mw->Vbox), "menu_data_i",
+ offset);
+ g_object_set_data(G_OBJECT(mw->Vbox), "menu_data_s",
+ uid);
+ g_object_set_data(G_OBJECT(mw->Vbox), "new_meeting_cb",
+ month_view_new_meeting_cb);
+ g_object_set_data(G_OBJECT(mw->Vbox), "edit_meeting_cb",
+ month_view_edit_meeting_cb);
+ g_object_set_data(G_OBJECT(mw->Vbox), "cancel_meeting_cb",
+ month_view_cancel_meeting_cb);
+ g_object_set_data(G_OBJECT(mw->Vbox), "go_today_cb",
+ month_view_today_cb);
+ gtk_menu_popup(GTK_MENU(mw->event_menu),
+ NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ }
+}
+
+static void add_row(month_win *mw, VCalEvent *event, gint days)
+{
+ gint row, start_row, end_row, first_row, last_row;
+ gint col, start_col, end_col, first_col, last_col;
+ gint width, start_width, end_width;
+ gchar *text, *tip, *start_date, *end_date;
+ GtkWidget *ev = NULL, *lab = NULL, *hb;
+ time_t t_start, t_end;
+ struct tm tm_first, tm_start, tm_end;
+ guint monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ int weekoffset = -1;
+ gboolean pack = TRUE, update_tip = FALSE;
+ time_t now = time(NULL);
+ struct tm tm_today;
+ gboolean start_prev_mon = FALSE;
+
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = mw->Tooltips;
+#endif
+
+ localtime_r(&now, &tm_today);
+
+ tm_today.tm_year += 1900;
+ tm_today.tm_mon++;
+
+ /* First clarify timings */
+ t_start = icaltime_as_timet(icaltime_from_string(event->dtstart));
+ if (event->dtend && *event->dtend)
+ t_end = icaltime_as_timet(icaltime_from_string(event->dtend));
+ else
+ t_end = t_start;
+
+#ifdef G_OS_WIN32
+ if (t_start < 0)
+ t_start = 1;
+ if (t_end < 0)
+ t_end = 1;
+#endif
+ localtime_r(&t_start, &tm_start);
+ localtime_r(&t_end, &tm_end);
+ tm_first = mw->startdate;
+
+ tm_first.tm_year += 1900;
+
+ if (((tm_first.tm_year%4) == 0)
+ && (((tm_first.tm_year%100) != 0) || ((tm_first.tm_year%400) == 0)))
+ ++monthdays[1]; /* leap year, february has 29 days */
+
+
+ tm_first.tm_mon += 1;
+ tm_start.tm_year += 1900;
+ tm_start.tm_mon += 1;
+ tm_end.tm_year += 1900;
+ tm_end.tm_mon += 1;
+
+ start_col = orage_days_between(&tm_first, &tm_start)+1;
+ end_col = orage_days_between(&tm_first, &tm_end)+1;
+
+ if (start_col < 0)
+ start_prev_mon = TRUE;
+
+ if (end_col < 1) {
+ return;
+ }
+ if (start_col > 0 && start_col > monthdays[tm_first.tm_mon-1]) {
+ return;
+ }
+ else {
+ GDate *edate = g_date_new_dmy(tm_end.tm_mday, tm_end.tm_mon, tm_end.tm_year);
+ GDate *fdate = g_date_new_dmy(1, tm_first.tm_mon, tm_first.tm_year);
+ GDate *sdate;
+ if (start_col >= 1) {
+ sdate = g_date_new_dmy(tm_start.tm_mday, tm_start.tm_mon, tm_start.tm_year);
+ } else {
+ sdate = g_date_new_dmy(1, tm_first.tm_mon, tm_first.tm_year);
+ } /* endif */
+
+ col = start_col = (int)g_date_get_weekday(sdate);
+ end_col = (int)g_date_get_weekday(edate);
+ weekoffset = (int)g_date_get_monday_week_of_year(fdate);
+ row = start_row = (int)g_date_get_monday_week_of_year(sdate) - weekoffset;
+ end_row = (int)g_date_get_monday_week_of_year(edate) - weekoffset;
+ g_date_free(fdate);
+ g_date_free(sdate);
+ g_date_free(edate);
+ }
+
+ if (end_col > 7)
+ end_col = 7;
+
+ /* then add the appointment */
+ text = g_strdup(event->summary?event->summary : _("Unknown"));
+
+ if (mw->element[row][col] == NULL) {
+ hb = gtk_vbox_new(TRUE, 1);
+ mw->element[row][col] = hb;
+ }
+ else {
+ GList *children = NULL;
+ hb = mw->element[row][col];
+ /* FIXME: set some real bar here to make it visible that we
+ * have more than 1 appointment here
+ */
+ children = gtk_container_get_children(GTK_CONTAINER(hb));
+ if (g_list_length(children) > 2) {
+ pack = FALSE;
+ update_tip = TRUE;
+ } else if (g_list_length(children) > 1) {
+ pack = FALSE;
+ update_tip = FALSE;
+ }
+ g_list_free(children);
+ }
+ if (pack || !update_tip) {
+ ev = gtk_event_box_new();
+ lab = gtk_label_new(text);
+ gtk_misc_set_alignment(GTK_MISC(lab), 0.0, 0.0);
+ gtk_label_set_ellipsize(GTK_LABEL(lab), PANGO_ELLIPSIZE_END);
+ if ((row % 2) == 1)
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &mw->bg1);
+ else
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &mw->bg2);
+ } else if (!pack && update_tip) {
+ GList *children = gtk_container_get_children(GTK_CONTAINER(hb));
+ ev = GTK_WIDGET(g_list_last(children)->data);
+ g_list_free(children);
+ }
+
+ if (ev && tm_start.tm_mday == tm_today.tm_mday && tm_start.tm_mon == tm_today.tm_mon
+ && tm_start.tm_year == tm_today.tm_year)
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &mw->bg_today);
+
+ if (orage_days_between(&tm_start, &tm_end) == 0)
+ tip = g_strdup_printf("%s\n%02d:%02d-%02d:%02d\n%s"
+ , text, tm_start.tm_hour, tm_start.tm_min
+ , tm_end.tm_hour, tm_end.tm_min, event->description);
+ else {
+/* we took the date in unnormalized format, so we need to do that now */
+ start_date = g_strdup(orage_tm_date_to_i18_date(&tm_start));
+ end_date = g_strdup(orage_tm_date_to_i18_date(&tm_end));
+ tip = g_strdup_printf("%s\n%s %02d:%02d - %s %02d:%02d\n%s"
+ , text
+ , start_date, tm_start.tm_hour, tm_start.tm_min
+ , end_date, tm_end.tm_hour, tm_end.tm_min
+ , event->description);
+ g_free(start_date);
+ g_free(end_date);
+ }
+ if (pack) {
+ gtk_container_add(GTK_CONTAINER(ev), lab);
+ CLAWS_SET_TIP(ev, tip);
+ gtk_box_pack_start(GTK_BOX(hb), ev, TRUE, TRUE, 0);
+ } else if (!update_tip) {
+ gtk_label_set_label(GTK_LABEL(lab), "...");
+ gtk_container_add(GTK_CONTAINER(ev), lab);
+ CLAWS_SET_TIP(ev, tip);
+ gtk_box_pack_start(GTK_BOX(hb), ev, TRUE, TRUE, 0);
+ } else {
+#if !GTK_CHECK_VERSION(2,12,0)
+ GtkTooltipsData *tdata = gtk_tooltips_data_get(ev);
+ gchar *new = g_strdup_printf("%s\n\n%s", tdata?tdata->tip_text:"", tip);
+#else
+ gchar *old = gtk_widget_get_tooltip_text(ev);
+ gchar *new = g_strdup_printf("%s\n\n%s", old?old:"", tip);
+ g_free(old);
+#endif
+ CLAWS_SET_TIP(ev, new);
+ g_free(new);
+ }
+ g_object_set_data_full(G_OBJECT(ev), "UID", g_strdup(event->uid), g_free);
+ g_object_set_data(G_OBJECT(ev), "offset", GINT_TO_POINTER(tm_start.tm_mday));
+ g_signal_connect((gpointer)ev, "button-press-event"
+ , G_CALLBACK(on_button_press_event_cb), mw);
+ g_free(tip);
+ g_free(text);
+
+ /* and finally draw the line to show how long the appointment is,
+ * but only if it is Busy type event (=availability != 0)
+ * and it is not whole day event */
+ if (TRUE) {
+ width = mw->StartDate_button_req.width;
+ /*
+ * same_date = !strncmp(start_ical_time, end_ical_time, 8);
+ * */
+ if (start_row < 0)
+ first_row = 0;
+ else
+ first_row = start_row;
+ if (end_row > 5)
+ last_row = 5;
+ else
+ last_row = end_row;
+ for (row = first_row; row <= last_row; row++) {
+ if (row == start_row)
+ first_col = start_col;
+ else
+ first_col = 0;
+ if (row == end_row)
+ last_col = end_col;
+ else
+ last_col = 7;
+ for (col = first_col; col <= last_col; col++) {
+ if (row == start_row && col == start_col && !start_prev_mon)
+ start_width = ((tm_start.tm_hour*60)+(tm_start.tm_min))*width/(24*60);
+ else
+ start_width = 0;
+ if (row == last_row && col == last_col)
+ end_width = ((tm_end.tm_hour*60)+(tm_end.tm_min))*width/(24*60);
+ else
+ end_width = width;
+
+ mw->line[row][col] = build_line(start_width, 0
+ , end_width-start_width, 2, mw->line[row][col]
+ , &mw->line_color);
+ }
+ }
+ }
+}
+
+static void app_rows(month_win *mw, FolderItem *item)
+{
+ GSList *events = vcal_get_events_list(item);
+ GSList *cur = NULL;
+ int days = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mw->day_spin));
+ for (cur = events; cur ; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *) (cur->data);
+ add_row(mw, event, days);
+ vcal_manager_free_event(event);
+ }
+ g_slist_free(events);
+}
+
+static void app_data(month_win *mw, FolderItem *item)
+{
+ app_rows(mw, item);
+}
+
+
+static void fill_days(month_win *mw, gint days, FolderItem *item)
+{
+ gint day, col, height, width;
+ GtkWidget *ev, *vb, *hb;
+ guint monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ struct tm t = mw->startdate;
+ int weekoffset = -1;
+ time_t now = time(NULL);
+ struct tm tm_today;
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = mw->Tooltips;
+#endif
+
+
+ localtime_r(&now, &tm_today);
+
+ t.tm_year += 1900;
+ t.tm_mon++;
+ tm_today.tm_year += 1900;
+ tm_today.tm_mon++;
+
+ if (((t.tm_year%4) == 0)
+ && (((t.tm_year%100) != 0) || ((t.tm_year%400) == 0)))
+ ++monthdays[1]; /* leap year, february has 29 days */
+
+ height = mw->StartDate_button_req.height;
+ width = mw->StartDate_button_req.width;
+
+ /* first clear the structure */
+ for (col = 1; col < days+1; col++) {
+ mw->header[col] = NULL;
+ }
+ for (day = 0; day < MAX_DAYS; day++)
+ for (col = 0; col < 6; col++)
+ mw->line[col][day] = NULL;
+ for (day = 1; day <= monthdays[t.tm_mon-1]; day++) {
+ GDate *date = g_date_new_dmy(day, t.tm_mon, t.tm_year);
+ int dcol = (int)g_date_get_weekday(date);
+ int row = (int)g_date_get_monday_week_of_year(date);
+ if (weekoffset == -1) {
+ weekoffset = row;
+ row = 0;
+ } else {
+ row = row - weekoffset;
+ }
+ mw->element[row][dcol] = NULL;
+ mw->line[row][dcol] = build_line(0, 0, width, 3, NULL
+ , &mw->line_color);
+ g_date_free(date);
+ }
+
+ app_data(mw, item);
+
+ /* check rows */
+ for (day = 1; day <= monthdays[t.tm_mon-1]; day++) {
+ GDate *date = g_date_new_dmy(day, t.tm_mon, t.tm_year);
+ int col = (int)g_date_get_weekday(date);
+ int row = (int)g_date_get_monday_week_of_year(date);
+ gchar *label;
+ gchar *tmp;
+ GtkWidget *name;
+
+ if (weekoffset == -1) {
+ weekoffset = row;
+ row = 0;
+ } else {
+ row = row - weekoffset;
+ }
+ vb = gtk_vbox_new(FALSE, 0);
+ gtk_widget_set_size_request(vb, width, height);
+ if (g_date_get_day(date) == 1)
+ label = g_strdup_printf("%d %s", g_date_get_day(date),
+ _(monthname[g_date_get_month(date)-1]));
+ else
+ label = g_strdup_printf("%d", g_date_get_day(date));
+ tmp = g_strdup_printf("%s %d %s %d",
+ _(dayname[col-1]),
+ g_date_get_day(date),
+ _(monthname[g_date_get_month(date)-1]),
+ g_date_get_year(date));
+
+ ev = gtk_event_box_new();
+ g_object_set_data(G_OBJECT(ev), "day", GINT_TO_POINTER((int)g_date_get_day(date)));
+ g_signal_connect((gpointer)ev, "button-press-event"
+ , G_CALLBACK(header_button_clicked_cb), mw);
+ name = gtk_label_new(label);
+ gtk_misc_set_alignment(GTK_MISC(name), 0.0, 0.0);
+
+ CLAWS_SET_TIP(ev, tmp);
+ gtk_container_add(GTK_CONTAINER(ev), name);
+ g_free(tmp);
+ g_free(label);
+
+ if ((row % 2) == 1)
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &mw->bg1);
+ else
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &mw->bg2);
+ if (col == 7)
+ gtk_widget_modify_fg(name, GTK_STATE_NORMAL, &mw->fg_sunday);
+ if (day == tm_today.tm_mday && t.tm_mon == tm_today.tm_mon && t.tm_year == tm_today.tm_year)
+ gtk_widget_modify_bg(ev, GTK_STATE_NORMAL, &mw->bg_today);
+
+ hb = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hb), ev, TRUE, TRUE, 1);
+ gtk_box_pack_start(GTK_BOX(vb), hb, TRUE, TRUE, 0);
+ if (mw->element[row][col]) {
+ gtk_box_pack_start(GTK_BOX(vb), mw->element[row][col], TRUE, TRUE, 0);
+ }
+ gtk_box_pack_start(GTK_BOX(vb), mw->line[row][col]
+ , FALSE, FALSE, 0);
+
+ gtk_table_attach(GTK_TABLE(mw->dtable), vb, col, col+1, row, row+1
+ , (GTK_FILL), (0), 0, 0);
+ g_date_free(date);
+ }
+}
+
+static void build_month_view_header(month_win *mw, char *start_date)
+{
+ GtkWidget *hbox, *label, *space_label;
+
+ hbox = gtk_hbox_new(FALSE, 0);
+
+ label = gtk_label_new(_("Start"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
+
+ /* start date button */
+ mw->StartDate_button = gtk_button_new();
+ gtk_box_pack_start(GTK_BOX(hbox), mw->StartDate_button, FALSE, FALSE, 0);
+
+ space_label = gtk_label_new(" ");
+ gtk_box_pack_start(GTK_BOX(hbox), space_label, FALSE, FALSE, 0);
+
+ space_label = gtk_label_new(" ");
+ gtk_box_pack_start(GTK_BOX(hbox), space_label, FALSE, FALSE, 0);
+
+ label = gtk_label_new(_("Show"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
+
+ /* show days spin = how many days to show */
+ mw->day_spin = gtk_spin_button_new_with_range(1, MAX_DAYS, 1);
+ gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(mw->day_spin), TRUE);
+ gtk_widget_set_size_request(mw->day_spin, 40, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), mw->day_spin, FALSE, FALSE, 0);
+ label = gtk_label_new(_("days"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+
+ space_label = gtk_label_new(" ");
+ gtk_box_pack_start(GTK_BOX(hbox), space_label, FALSE, FALSE, 0);
+
+ /* sizes */
+ gtk_button_set_label(GTK_BUTTON(mw->StartDate_button)
+ , (const gchar *)start_date);
+ gtk_widget_size_request(mw->StartDate_button, &mw->StartDate_button_req);
+ mw->StartDate_button_req.width += mw->StartDate_button_req.width/10;
+ label = gtk_label_new("00");
+ gtk_widget_size_request(label, &mw->hour_req);
+}
+
+static void build_month_view_colours(month_win *mw)
+{
+ GtkStyle *def_style;
+ GdkColormap *pic1_cmap;
+ GtkWidget *ctree = NULL;
+ def_style = gtk_widget_get_default_style();
+ pic1_cmap = gdk_colormap_get_system();
+
+ if (mainwindow_get_mainwindow()) {
+ ctree = mainwindow_get_mainwindow()->summaryview->ctree;
+ }
+ if (ctree) {
+ mw->bg1 = ctree->style->bg[GTK_STATE_NORMAL];
+ mw->bg2 = ctree->style->bg[GTK_STATE_NORMAL];
+ } else {
+ mw->bg1 = def_style->bg[GTK_STATE_NORMAL];
+ mw->bg2 = def_style->bg[GTK_STATE_NORMAL];
+ }
+
+ mw->bg1.red += (mw->bg1.red < 63000 ? 2000 : -2000);
+ mw->bg1.green += (mw->bg1.green < 63000 ? 2000 : -2000);
+ mw->bg1.blue += (mw->bg1.blue < 63000 ? 2000 : -2000);
+ gdk_colormap_alloc_color(pic1_cmap, &mw->bg1, FALSE, TRUE);
+
+ mw->bg2.red += (mw->bg2.red > 1000 ? -1000 : 1000);
+ mw->bg2.green += (mw->bg2.green > 1000 ? -1000 : 1000);
+ mw->bg2.blue += (mw->bg2.blue > 1000 ? -1000 : 1000);
+ gdk_colormap_alloc_color(pic1_cmap, &mw->bg2, FALSE, TRUE);
+
+ if (!gdk_color_parse("white", &mw->line_color)) {
+ mw->line_color.red = 239 * (65535/255);
+ mw->line_color.green = 235 * (65535/255);
+ mw->line_color.blue = 230 * (65535/255);
+ }
+
+ if (!gdk_color_parse("blue", &mw->fg_sunday)) {
+ g_warning("color parse failed: red\n");
+ mw->fg_sunday.red = 10 * (65535/255);
+ mw->fg_sunday.green = 10 * (65535/255);
+ mw->fg_sunday.blue = 255 * (65535/255);
+ }
+
+ if (!gdk_color_parse("gold", &mw->bg_today)) {
+ g_warning("color parse failed: gold\n");
+ mw->bg_today.red = 255 * (65535/255);
+ mw->bg_today.green = 215 * (65535/255);
+ mw->bg_today.blue = 115 * (65535/255);
+ }
+
+ if (ctree) {
+ mw->fg_sunday.red = (mw->fg_sunday.red + ctree->style->fg[GTK_STATE_SELECTED].red)/2;
+ mw->fg_sunday.green = (mw->fg_sunday.green + ctree->style->fg[GTK_STATE_SELECTED].red)/2;
+ mw->fg_sunday.blue = (3*mw->fg_sunday.blue + ctree->style->fg[GTK_STATE_SELECTED].red)/4;
+ mw->bg_today.red = (3*mw->bg_today.red + ctree->style->bg[GTK_STATE_NORMAL].red)/4;
+ mw->bg_today.green = (3*mw->bg_today.green + ctree->style->bg[GTK_STATE_NORMAL].red)/4;
+ mw->bg_today.blue = (3*mw->bg_today.blue + ctree->style->bg[GTK_STATE_NORMAL].red)/4;
+ }
+ gdk_colormap_alloc_color(pic1_cmap, &mw->line_color, FALSE, TRUE);
+ gdk_colormap_alloc_color(pic1_cmap, &mw->fg_sunday, FALSE, TRUE);
+ gdk_colormap_alloc_color(pic1_cmap, &mw->bg_today, FALSE, TRUE);
+}
+
+static void fill_hour(month_win *mw, gint col, gint row, char *text)
+{
+ GtkWidget *name, *ev;
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = mw->Tooltips;
+#endif
+
+ ev = gtk_event_box_new();
+ name = gtk_label_new(text);
+ gtk_misc_set_alignment(GTK_MISC(name), 0, 0.5);
+ CLAWS_SET_TIP(ev, _("Week number"));
+ gtk_container_add(GTK_CONTAINER(ev), name);
+ gtk_widget_set_size_request(ev, mw->hour_req.width
+ , mw->StartDate_button_req.height);
+ if (text)
+ gtk_table_attach(GTK_TABLE(mw->dtable), ev, col, col+1, row, row+1
+ , (GTK_FILL), (0), 0, 0);
+ else /* special, needed for header table full day events */
+ gtk_table_attach(GTK_TABLE(mw->dtable_h), ev, col, col+1, row, row+1
+ , (GTK_FILL), (0), 0, 0);
+}
+
+static void build_month_view_table(month_win *mw)
+{
+ gint days; /* number of days to show */
+ int year, month, day;
+ gint i = 0;
+ GtkWidget *button;
+ struct tm tm_date, tm_today;
+ guint monthdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ GtkWidget *vp;
+ time_t t = time(NULL);
+ GtkWidget *arrow;
+ int avail_w = 0, avail_d = 0;
+ int avail_h = 0;
+ int weekoffset = -1;
+ GDate *date;
+ int first_week=0;
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = mw->Tooltips;
+#endif
+
+ if (mainwindow_get_mainwindow()) {
+ GtkAllocation allocation;
+ SummaryView *summaryview = mainwindow_get_mainwindow()->summaryview;
+ GTK_EVENTS_FLUSH();
+ allocation = summaryview->mainwidget_book->allocation;
+
+ avail_w = allocation.width - 25 - 2*(mw->hour_req.width);
+ avail_h = allocation.height - 20;
+ if (avail_h < 250)
+ avail_h = 250;
+ avail_d = avail_w / mw->StartDate_button_req.width;
+ }
+ avail_d = 7;
+ gtk_widget_set_size_request(mw->StartDate_button, avail_w / avail_d,
+ (avail_h)/6);
+ gtk_widget_size_request(mw->StartDate_button, &mw->StartDate_button_req);
+
+ /* initial values */
+ if (avail_d)
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(mw->day_spin), avail_d);
+
+#ifdef G_OS_WIN32
+ if (t < 0)
+ t = 1;
+#endif
+ localtime_r(&t, &tm_today);
+ days = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mw->day_spin));
+ /****** header of day table = days columns ******/
+ mw->scroll_win_h = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(mw->scroll_win_h)
+ , GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
+ gtk_box_pack_start(GTK_BOX(mw->Vbox), mw->scroll_win_h
+ , TRUE, TRUE, 0);
+ mw->month_view_vbox = gtk_vbox_new(FALSE, 0);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(mw->scroll_win_h)
+ , mw->month_view_vbox);
+ /*
+ gtk_container_add(GTK_CONTAINER(mw->scroll_win_h), mw->month_view_vbox);
+ */
+ /* row 1= day header buttons
+ * row 2= full day events after the buttons */
+ mw->dtable_h = gtk_table_new(2 , days+2, FALSE);
+ gtk_box_pack_start(GTK_BOX(mw->month_view_vbox), mw->dtable_h
+ , FALSE, FALSE, 0);
+
+ tm_date = mw->startdate;
+
+ year = tm_date.tm_year + 1900;
+ month = tm_date.tm_mon;
+ day = tm_date.tm_mday;
+ if (((tm_date.tm_year%4) == 0) && (((tm_date.tm_year%100) != 0)
+ || ((tm_date.tm_year%400) == 0)))
+ ++monthdays[1];
+
+
+ i=0;
+ mw->Previous_toolbutton = gtk_event_box_new();
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(mw->Previous_toolbutton), FALSE);
+ gtk_container_set_border_width(GTK_CONTAINER(mw->Previous_toolbutton), 0);
+ arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE);
+ gtk_container_add(GTK_CONTAINER(mw->Previous_toolbutton), arrow);
+ gtk_table_attach(GTK_TABLE(mw->dtable_h), mw->Previous_toolbutton, i, i+1, 0, 1
+ , (GTK_FILL), (0), 0, 0);
+ gtk_widget_show_all(mw->Previous_toolbutton);
+ g_signal_connect((gpointer)mw->Previous_toolbutton, "button_release_event"
+ , G_CALLBACK(on_Previous_clicked), mw);
+ CLAWS_SET_TIP(mw->Previous_toolbutton, _("Previous month"));
+ for (i = 1; i < days+1; i++) {
+ button = gtk_label_new(_(dayname[i-1]));
+
+ if (i == 8) {
+ gtk_widget_modify_fg(button, GTK_STATE_NORMAL, &mw->fg_sunday);
+ }
+ gtk_widget_set_size_request(button, mw->StartDate_button_req.width, -1);
+ g_object_set_data(G_OBJECT(button), "offset", GINT_TO_POINTER(i-1));
+ gtk_table_attach(GTK_TABLE(mw->dtable_h), button, i, i+1, 0, 1
+ , (GTK_FILL), (0), 0, 0);
+ }
+
+ mw->Next_toolbutton = gtk_event_box_new();
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(mw->Next_toolbutton), FALSE);
+ gtk_container_set_border_width(GTK_CONTAINER(mw->Next_toolbutton), 0);
+ arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
+ gtk_container_add(GTK_CONTAINER(mw->Next_toolbutton), arrow);
+ gtk_table_attach(GTK_TABLE(mw->dtable_h), mw->Next_toolbutton, i, i+1, 0, 1
+ , (GTK_FILL), (0), 0, 0);
+ gtk_widget_show_all(mw->Next_toolbutton);
+ g_signal_connect((gpointer)mw->Next_toolbutton, "button_release_event"
+ , G_CALLBACK(on_Next_clicked), mw);
+ CLAWS_SET_TIP(mw->Next_toolbutton, _("Next month"));
+
+ /****** body of day table ******/
+ mw->scroll_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(mw->scroll_win)
+ , GTK_SHADOW_NONE);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(mw->scroll_win)
+ , GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(mw->scroll_win)
+ , GTK_CORNER_TOP_LEFT);
+ gtk_box_pack_start(GTK_BOX(mw->month_view_vbox), mw->scroll_win
+ , TRUE, TRUE, 0);
+ vp = gtk_viewport_new(NULL, NULL);
+ gtk_viewport_set_shadow_type(GTK_VIEWPORT(vp), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(mw->scroll_win), vp);
+ mw->dtable = gtk_table_new(6, days+2, FALSE);
+ gtk_container_add(GTK_CONTAINER(vp), mw->dtable);
+
+ gtk_widget_show_all(mw->dtable_h);
+
+ date = g_date_new_dmy(1, 1, tm_date.tm_year+1900);
+ first_week = g_date_get_monday_week_of_year(date);
+
+ if (first_week == 0)
+ first_week = 1;
+ else
+ first_week = 0;
+ g_date_free(date);
+
+ /* hours column = hour rows */
+ for (i = 0; i <= 6; i++) {
+ for (day = 1; day <= monthdays[tm_date.tm_mon]; day++) {
+ date = g_date_new_dmy(day, tm_date.tm_mon+1, tm_date.tm_year+1900);
+ int row = (int)g_date_get_monday_week_of_year(date);
+ if (weekoffset == -1) {
+ weekoffset = row;
+ }
+ if (row - weekoffset == i) {
+ gchar *wn = g_strdup_printf("%d", row+first_week > 53?1:row+first_week);
+ fill_hour(mw, 0, i, wn);
+ fill_hour(mw, days+1, i, "");
+ g_free(wn);
+ g_date_free(date);
+ break;
+ }
+ g_date_free(date);
+ }
+ }
+ fill_days(mw, days, mw->item);
+}
+
+void refresh_month_win(month_win *mw)
+{
+ gtk_widget_destroy(mw->scroll_win_h);
+ build_month_view_table(mw);
+ gtk_widget_show_all(mw->scroll_win_h);
+}
+
+month_win *create_month_win(FolderItem *item, struct tm tmdate)
+{
+ month_win *mw;
+ char *start_date = get_locale_date(&tmdate);
+
+ /* initialisation + main window + base vbox */
+ mw = g_new0(month_win, 1);
+ mw->scroll_pos = -1; /* not set */
+#if !(GTK_CHECK_VERSION(2,12,0))
+ mw->Tooltips = tips;
+#endif
+ mw->accel_group = gtk_accel_group_new();
+
+ while (tmdate.tm_mday != 1)
+ orage_move_day(&tmdate, -1);
+
+ mw->startdate = tmdate;
+
+ mw->Vbox = gtk_vbox_new(FALSE, 0);
+
+ mw->item = item;
+ build_month_view_colours(mw);
+ build_month_view_header(mw, start_date);
+ build_month_view_table(mw);
+ gtk_widget_show_all(mw->Vbox);
+ mw->selsig = vcal_view_set_calendar_page(mw->Vbox,
+ G_CALLBACK(mw_summary_selected), mw);
+
+ vcal_view_create_popup_menus(mw->Vbox, &mw->view_menu,
+ &mw->event_menu, &mw->event_group,
+ &mw->ui_manager);
+ return(mw);
+}
diff --git a/src/plugins/vcalendar/placeholder.txt b/src/plugins/vcalendar/placeholder.txt
@@ -1 +0,0 @@
-Placeholder
diff --git a/src/plugins/vcalendar/plugin.c b/src/plugins/vcalendar/plugin.c
@@ -0,0 +1,106 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <time.h>
+#include <stddef.h>
+#include <curl/curl.h>
+
+#include "version.h"
+#include "vcalendar.h"
+#include "claws.h"
+#include "plugin.h"
+
+#include "vcal_dbus.h"
+
+gint plugin_init(gchar **error)
+{
+ if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
+ VERSION_NUMERIC, _("vCalendar"), error))
+ return -1;
+
+ tzset();
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ vcalendar_init();
+ connect_dbus();
+
+ return 0;
+}
+
+gboolean plugin_done(void)
+{
+ disconnect_dbus();
+ vcalendar_done();
+ return TRUE;
+}
+
+const gchar *plugin_name(void)
+{
+ return _("vCalendar");
+}
+
+const gchar *plugin_desc(void)
+{
+ return _("This plugin enables vCalendar message handling like that produced "
+ "by Evolution or Outlook.\n\n"
+ "When loaded, it will create a vCalendar mailbox in the Folder "
+ "List, which will be populated by meetings that you have accepted "
+ "or created.\n"
+ "Meeting requests that you receive will be presented in an "
+ "appropriate form and you will be able to accept or decline them.\n"
+ "To create a meeting right-click on the vCalendar or "
+ "Meetings folder and choose \"New meeting...\".\n\n"
+ "You will also be able to subscribe to remote webCal feeds,"
+ "export your meetings and calendars, publish your free/busy "
+ "information and retrieve that information from others.");
+}
+
+const gchar *plugin_type(void)
+{
+ return "GTK2";
+}
+
+const gchar *plugin_licence(void)
+{
+ return "GPL3+";
+}
+
+const gchar *plugin_version(void)
+{
+ return VERSION;
+}
+
+struct PluginFeature *plugin_provides(void)
+{
+ static struct PluginFeature features[] =
+ { {PLUGIN_MIMEVIEWER, "text/calendar"},
+ {PLUGIN_FOLDERCLASS, N_("Calendar")},
+ {PLUGIN_NOTHING, NULL}};
+ return features;
+}
diff --git a/src/plugins/vcalendar/vcal_dbus.c b/src/plugins/vcalendar/vcal_dbus.c
@@ -0,0 +1,209 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2011 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <ical.h>
+#include <gtk/gtk.h>
+
+#include "utils.h"
+#include "vcal_manager.h"
+#include "vcal_folder.h"
+
+#if(GLIB_CHECK_VERSION(2,26,0))
+
+static guint dbus_own_id;
+
+static void add_event_to_builder_if_match(VCalEvent *event, GVariantBuilder *array,
+ time_t start, time_t end)
+{
+ time_t evt_start = icaltime_as_timet((icaltime_from_string(event->dtstart)));
+ time_t evt_end = icaltime_as_timet((icaltime_from_string(event->dtend)));
+ if ((evt_start >= start && evt_start <= end)
+ || (evt_end >= start && evt_end <= end)) {
+ g_variant_builder_open(array,
+ G_VARIANT_TYPE("(sssbxxa{sv})"));
+ g_variant_builder_add(array, "s", event->uid);
+ g_variant_builder_add(array, "s", event->summary);
+ g_variant_builder_add(array, "s", event->description);
+ g_variant_builder_add(array, "b", FALSE);
+ g_variant_builder_add(array, "x", (gint64)evt_start);
+ g_variant_builder_add(array, "x", (gint64)evt_end);
+ g_variant_builder_open(array, G_VARIANT_TYPE("a{sv}"));
+ /* We don't put stuff there. */
+ g_variant_builder_close(array);
+ g_variant_builder_close(array);
+ }
+}
+
+static void handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ time_t start, end;
+ gboolean refresh;
+ GSList *list, *cur;
+ int i;
+ GVariantBuilder *array = g_variant_builder_new(
+ G_VARIANT_TYPE("(a(sssbxxa{sv}))"));
+ GVariant *value;
+
+ if (g_strcmp0(method_name, "GetEvents") != 0) {
+ debug_print("Unknown method %s\n", method_name);
+ }
+
+ g_variant_get(parameters, "(xxb)", &start, &end, &refresh);
+
+
+ g_variant_builder_open(array, G_VARIANT_TYPE("a(sssbxxa{sv})"));
+
+ /* First our own calendar */
+ list = vcal_folder_get_waiting_events();
+ for (cur = list, i = 0; cur; cur = cur->next, i++) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+
+ add_event_to_builder_if_match(event, array, start, end);
+
+ g_free(event);
+ }
+ g_slist_free(list);
+
+ /* Then subs. */
+ list = vcal_folder_get_webcal_events();
+ for (cur = list; cur; cur = cur->next) {
+ /* Don't free that, it's done when subscriptions are
+ * fetched */
+ icalcomponent *ical = (icalcomponent *)cur->data;
+ VCalEvent *event = vcal_get_event_from_ical(
+ icalcomponent_as_ical_string(ical), NULL);
+
+ add_event_to_builder_if_match(event, array, start, end);
+ g_free(event);
+ }
+ g_slist_free(list);
+
+ g_variant_builder_close(array);
+
+ value = g_variant_builder_end(array);
+ g_variant_builder_unref(array);
+
+ g_dbus_method_invocation_return_value (invocation, value);
+ g_variant_unref(value);
+}
+
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ handle_method_call,
+ NULL,
+ NULL
+};
+
+static GDBusNodeInfo *introspection_data = NULL;
+static GDBusInterfaceInfo *interface_info = NULL;
+
+static const gchar introspection_xml[] =
+ "<node>"
+ " <interface name='org.gnome.Shell.CalendarServer'>"
+ " <method name='GetEvents'>"
+ " <arg type='x' name='greeting' direction='in'/>"
+ " <arg type='x' name='greeting' direction='in'/>"
+ " <arg type='b' name='greeting' direction='in'/>"
+ " <arg type='a(sssbxxa{sv})' name='events' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+static void name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ debug_print("Acquired DBUS name %s\n", name);
+}
+
+static void name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ debug_print("Lost DBUS name %s\n", name);
+}
+
+static void bus_acquired(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ g_dbus_connection_register_object(connection,
+ "/org/gnome/Shell/CalendarServer",
+ introspection_data->interfaces[0],
+ &interface_vtable, NULL, NULL, &err);
+ if (err != NULL)
+ debug_print("Error: %s\n", err->message);
+}
+
+void connect_dbus(void)
+{
+ introspection_data = g_dbus_node_info_new_for_xml(
+ introspection_xml, NULL);
+ if (introspection_data == NULL) {
+ debug_print("Couldn't figure out XML.");
+ return;
+ }
+
+ interface_info = g_dbus_node_info_lookup_interface(
+ introspection_data,
+ "org.gnome.Shell.CalendarServer");
+ dbus_own_id = g_bus_own_name(G_BUS_TYPE_SESSION,
+ "org.gnome.Shell.CalendarServer",
+ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
+ | G_BUS_NAME_OWNER_FLAGS_REPLACE,
+ bus_acquired,
+ name_acquired,
+ name_lost,
+ NULL, NULL);
+}
+
+void disconnect_dbus(void)
+{
+ g_bus_unown_name(dbus_own_id);
+}
+
+#else
+void connect_dbus(void)
+{
+ debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
+}
+void disconnect_dbus(void)
+{
+ debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
+}
+#endif
diff --git a/src/plugins/vcalendar/vcal_dbus.h b/src/plugins/vcalendar/vcal_dbus.h
@@ -0,0 +1,27 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2011 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VCAL_DBUS_H__
+#define __VCAL_DBUS_H__
+
+void connect_dbus(void);
+void disconnect_dbus(void);
+
+#endif
diff --git a/src/plugins/vcalendar/vcal_folder.c b/src/plugins/vcalendar/vcal_folder.c
@@ -0,0 +1,2431 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <curl/curl.h>
+#include <curl/curlver.h>
+
+#include "account.h"
+#include "utils.h"
+#include "procmsg.h"
+#include "procheader.h"
+#include "folder.h"
+#include "folderview.h"
+#include "vcalendar.h"
+#include "vcal_folder.h"
+#include "vcal_prefs.h"
+#include "vcal_manager.h"
+#include "vcal_meeting_gtk.h"
+#include "vcal_interface.h"
+#include "prefs_account.h"
+#include "prefs_common.h"
+#include "claws.h"
+#include "menu.h"
+#include "inputdialog.h"
+#include "inc.h"
+#include "xml.h"
+#include "alertpanel.h"
+#include "log.h"
+#include "mainwindow.h"
+#include "statusbar.h"
+#include "msgcache.h"
+#include "timing.h"
+#include "messageview.h"
+
+#include <gtk/gtk.h>
+#include <dirent.h>
+
+#define VCAL_FOLDERITEM(item) ((VCalFolderItem *) item)
+
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+
+typedef struct _thread_data {
+ const gchar *url;
+ gchar *result;
+ gchar *error;
+ gboolean done;
+} thread_data;
+
+typedef struct _IcalFeedData {
+ icalcomponent *event;
+ gchar *pseudoevent_id;
+} IcalFeedData;
+
+typedef struct _VCalFolder VCalFolder;
+typedef struct _VCalFolderItem VCalFolderItem;
+
+static Folder *vcal_folder_new(const gchar * name,
+ const gchar * folder);
+static void vcal_folder_destroy(Folder * folder);
+static void vcal_item_destroy(Folder *folder, FolderItem *_item);
+static gchar *vcal_item_get_path(Folder *folder, FolderItem *item);
+
+static gint vcal_scan_tree(Folder * folder);
+static FolderItem *vcal_item_new(Folder * folder);
+static gint vcal_get_num_list(Folder * folder, FolderItem * item,
+ MsgNumberList ** list,
+ gboolean * old_uids_valid);
+static MsgInfo *vcal_get_msginfo(Folder * folder, FolderItem * item,
+ gint num);
+static gchar *vcal_fetch_msg(Folder * folder, FolderItem * item,
+ gint num);
+static gint vcal_add_msg(Folder * folder, FolderItem * _dest,
+ const gchar * file, MsgFlags * flags);
+static gint vcal_remove_msg(Folder * folder, FolderItem * _item,
+ gint num);
+static FolderItem *vcal_create_folder(Folder * folder,
+ FolderItem * parent,
+ const gchar * name);
+static gint vcal_create_tree(Folder *folder);
+static gint vcal_remove_folder(Folder *folder, FolderItem *item);
+static gboolean vcal_scan_required(Folder *folder, FolderItem *item);
+static void vcal_set_mtime(Folder *folder, FolderItem *item);
+static void vcal_change_flags(Folder *folder, FolderItem *_item, MsgInfo *msginfo, MsgPermFlags newflags);
+
+static void new_meeting_cb(GtkAction *action, gpointer data);
+static void export_cal_cb(GtkAction *action, gpointer data);
+static void subscribe_cal_cb(GtkAction *action, gpointer data);
+static void check_subs_cb(GtkAction *action, gpointer data);
+static void unsubscribe_cal_cb(GtkAction *action, gpointer data);
+static void rename_cb(GtkAction *action, gpointer data);
+static void set_view_cb(GtkAction *action, GtkRadioAction *current, gpointer data);
+
+static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item);
+static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item);
+
+static void update_subscription(const gchar *uri, gboolean verbose);
+static void vcal_folder_set_batch (Folder *folder,
+ FolderItem *item,
+ gboolean batch);
+
+gboolean vcal_subscribe_uri(Folder *folder, const gchar *uri);
+
+FolderClass vcal_class;
+
+static GSList *created_files = NULL;
+static GHashTable *hash_uids = NULL;
+
+struct _VCalFolder
+{
+ Folder folder;
+};
+
+struct _VCalFolderItem
+{
+ FolderItem item;
+ gchar *uri;
+ gchar *feed;
+ icalcomponent *cal;
+ GSList *numlist;
+ GSList *evtlist;
+ gboolean batching;
+ gboolean dirty;
+ day_win *dw;
+ month_win *mw;
+ time_t last_fetch;
+ int use_cal_view;
+};
+
+static char *vcal_popup_labels[] =
+{
+ N_("_New meeting..."),
+ N_("_Export calendar..."),
+ N_("_Subscribe to webCal..."),
+ N_("_Unsubscribe..."),
+ N_("_Rename..."),
+ N_("U_pdate subscriptions"),
+ N_("_List view"),
+ N_("_Week view"),
+ N_("_Month view"),
+ NULL
+};
+
+static GtkActionEntry vcal_popup_entries[] =
+{
+ {"FolderViewPopup/NewMeeting", NULL, NULL, NULL, NULL, G_CALLBACK(new_meeting_cb) },
+ {"FolderViewPopup/ExportCal", NULL, NULL, NULL, NULL, G_CALLBACK(export_cal_cb) },
+
+ {"FolderViewPopup/SubscribeCal", NULL, NULL, NULL, NULL, G_CALLBACK(subscribe_cal_cb) },
+ {"FolderViewPopup/UnsubscribeCal", NULL, NULL, NULL, NULL, G_CALLBACK(unsubscribe_cal_cb) },
+
+ {"FolderViewPopup/RenameFolder", NULL, NULL, NULL, NULL, G_CALLBACK(rename_cb) },
+
+ {"FolderViewPopup/CheckSubs", NULL, NULL, NULL, NULL, G_CALLBACK(check_subs_cb) },
+
+};
+
+static GtkRadioActionEntry vcal_popup_radio_entries[] = { /* set_view_cb */
+ {"FolderViewPopup/ListView", NULL, NULL, NULL, NULL, 0 },
+ {"FolderViewPopup/WeekView", NULL, NULL, NULL, NULL, 1 },
+ {"FolderViewPopup/MonthView", NULL, NULL, NULL, NULL, 2 },
+};
+
+static IcalFeedData *icalfeeddata_new(icalcomponent *evt, gchar *str)
+{
+ IcalFeedData *data = g_new0(IcalFeedData, 1);
+ if (str)
+ data->pseudoevent_id = g_strdup(str);
+ data->event = evt;
+ return data;
+}
+
+static void icalfeeddata_free(IcalFeedData *data)
+{
+ g_free(data->pseudoevent_id);
+ if (data->event)
+ icalcomponent_free(data->event);
+ g_free(data);
+}
+
+static void slist_free_icalfeeddata(GSList *list)
+{
+ while (list) {
+ IcalFeedData *data = (IcalFeedData *)list->data;
+ icalfeeddata_free(data);
+ list = list->next;
+ }
+}
+
+static void vcal_fill_popup_menu_labels(void)
+{
+ vcal_popup_entries[0].label = _(vcal_popup_labels[0]);
+ vcal_popup_entries[1].label = _(vcal_popup_labels[1]);
+ vcal_popup_entries[2].label = _(vcal_popup_labels[2]);
+ vcal_popup_entries[3].label = _(vcal_popup_labels[3]);
+ vcal_popup_entries[4].label = _(vcal_popup_labels[4]);
+ vcal_popup_entries[5].label = _(vcal_popup_labels[5]);
+ vcal_popup_radio_entries[0].label = _(vcal_popup_labels[6]);
+ vcal_popup_radio_entries[1].label = _(vcal_popup_labels[7]);
+ vcal_popup_radio_entries[2].label = _(vcal_popup_labels[8]);
+}
+
+static FolderViewPopup vcal_popup =
+{
+ "vCalendar",
+ "<vCalendar>",
+ vcal_popup_entries,
+ G_N_ELEMENTS(vcal_popup_entries),
+ NULL, 0,
+ vcal_popup_radio_entries,
+ G_N_ELEMENTS(vcal_popup_radio_entries), 1, set_view_cb,
+ add_menuitems,
+ set_sensitivity
+};
+
+static void vcal_item_set_xml(Folder *folder, FolderItem *item, XMLTag *tag)
+{
+ GList *cur;
+ folder_item_set_xml(folder, item, tag);
+ gboolean found_cal_view_setting = FALSE;
+
+ for (cur = tag->attr; cur != NULL; cur = g_list_next(cur)) {
+ XMLAttr *attr = (XMLAttr *) cur->data;
+
+ if (!attr || !attr->name || !attr->value) continue;
+ if (!strcmp(attr->name, "uri")) {
+ if (((VCalFolderItem *)item)->uri != NULL)
+ g_free(((VCalFolderItem *)item)->uri);
+ ((VCalFolderItem *)item)->uri = g_strdup(attr->value);
+ }
+ if (!strcmp(attr->name, "use_cal_view")) {
+ found_cal_view_setting = TRUE;
+ ((VCalFolderItem *)item)->use_cal_view = atoi(attr->value);
+ }
+ }
+ if (((VCalFolderItem *)item)->uri == NULL) {
+ /* give a path to inbox */
+ g_free(item->path);
+ item->path = g_strdup(".meetings");
+ }
+ if (!found_cal_view_setting)
+ ((VCalFolderItem *)item)->use_cal_view = 1; /*week view */
+
+}
+
+static XMLTag *vcal_item_get_xml(Folder *folder, FolderItem *item)
+{
+ XMLTag *tag;
+
+ tag = folder_item_get_xml(folder, item);
+
+ if (((VCalFolderItem *)item)->uri)
+ xml_tag_add_attr(tag, xml_attr_new("uri", ((VCalFolderItem *)item)->uri));
+
+ xml_tag_add_attr(tag, xml_attr_new_int("use_cal_view", ((VCalFolderItem *)item)->use_cal_view));
+
+ return tag;
+}
+
+static gint vcal_rename_folder(Folder *folder, FolderItem *item,
+ const gchar *name)
+{
+ if (!name)
+ return -1;
+ g_free(item->name);
+ item->name = g_strdup(name);
+ return 0;
+}
+
+static void vcal_get_sort_type(Folder *folder, FolderSortKey *sort_key,
+ FolderSortType *sort_type)
+{
+ if (sort_key)
+ *sort_key = SORT_BY_DATE;
+}
+
+static void vcal_item_opened(FolderItem *item)
+{
+ struct tm tmdate;
+ time_t t = time(NULL);
+#ifndef G_OS_WIN32
+ localtime_r(&t, &tmdate);
+#else
+ if (t < 0)
+ t = 1;
+ tmdate = *localtime(&t);
+#endif
+ if (!((VCalFolderItem *)(item))->dw
+ && ((VCalFolderItem *)(item))->use_cal_view == 1)
+ ((VCalFolderItem *)(item))->dw = create_day_win(item, tmdate);
+ else if (!((VCalFolderItem *)(item))->mw
+ && ((VCalFolderItem *)(item))->use_cal_view == 2)
+ ((VCalFolderItem *)(item))->mw = create_month_win(item, tmdate);
+ else if (((VCalFolderItem *)(item))->use_cal_view != 0)
+ vcal_folder_refresh_cal(item);
+}
+
+void vcal_folder_refresh_cal(FolderItem *item)
+{
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ if (item->folder != folder)
+ return;
+ if (((VCalFolderItem *)(item))->dw)
+ refresh_day_win(((VCalFolderItem *)(item))->dw);
+ if (((VCalFolderItem *)(item))->mw)
+ refresh_month_win(((VCalFolderItem *)(item))->mw);
+}
+
+static void vcal_item_closed(FolderItem *item)
+{
+ if (((VCalFolderItem *)(item))->dw) {
+ dw_close_window(((VCalFolderItem *)(item))->dw);
+ ((VCalFolderItem *)(item))->dw = NULL;
+ }
+ if (((VCalFolderItem *)(item))->mw) {
+ mw_close_window(((VCalFolderItem *)(item))->mw);
+ ((VCalFolderItem *)(item))->mw = NULL;
+ }
+}
+
+FolderClass *vcal_folder_get_class()
+{
+ if (vcal_class.idstr == NULL) {
+ debug_print("register class\n");
+ vcal_class.type = F_UNKNOWN;
+ vcal_class.idstr = "vCalendar";
+ vcal_class.uistr = "vCalendar";
+
+ /* Folder functions */
+ vcal_class.new_folder = vcal_folder_new;
+ vcal_class.destroy_folder = vcal_folder_destroy;
+ vcal_class.set_xml = folder_set_xml;
+ vcal_class.get_xml = folder_get_xml;
+ vcal_class.item_set_xml = vcal_item_set_xml;
+ vcal_class.item_get_xml = vcal_item_get_xml;
+ vcal_class.scan_tree = vcal_scan_tree;
+ vcal_class.create_tree = vcal_create_tree;
+ vcal_class.get_sort_type = vcal_get_sort_type;
+
+ /* FolderItem functions */
+ vcal_class.item_new = vcal_item_new;
+ vcal_class.item_destroy = vcal_item_destroy;
+ vcal_class.item_get_path = vcal_item_get_path;
+ vcal_class.create_folder = vcal_create_folder;
+ vcal_class.remove_folder = vcal_remove_folder;
+ vcal_class.rename_folder = vcal_rename_folder;
+ vcal_class.scan_required = vcal_scan_required;
+ vcal_class.set_mtime = vcal_set_mtime;
+ vcal_class.get_num_list = vcal_get_num_list;
+ vcal_class.set_batch = vcal_folder_set_batch;
+
+ /* Message functions */
+ vcal_class.get_msginfo = vcal_get_msginfo;
+ vcal_class.fetch_msg = vcal_fetch_msg;
+ vcal_class.add_msg = vcal_add_msg;
+ vcal_class.copy_msg = NULL;
+ vcal_class.remove_msg = vcal_remove_msg;
+ vcal_class.change_flags = vcal_change_flags;
+ vcal_class.subscribe = vcal_subscribe_uri;
+
+ /* FolderView functions */
+ vcal_class.item_opened = vcal_item_opened;
+ vcal_class.item_closed = vcal_item_closed;
+ debug_print("registered class for real\n");
+ }
+
+ return &vcal_class;
+}
+
+static void vcal_folder_set_batch (Folder *folder,
+ FolderItem *_item,
+ gboolean batch)
+{
+ VCalFolderItem *item = (VCalFolderItem *)_item;
+
+ g_return_if_fail(item != NULL);
+
+ if (item->batching == batch)
+ return;
+
+ if (batch) {
+ item->batching = TRUE;
+ debug_print("vcal switching to batch mode\n");
+ } else {
+ debug_print("vcal switching away from batch mode\n");
+ /* ici */
+ item->batching = FALSE;
+ if (item->dirty)
+ vcal_folder_export(folder);
+ item->dirty = FALSE;
+ }
+}
+
+static Folder *vcal_folder_new(const gchar * name,
+ const gchar * path)
+{
+ VCalFolder *folder;
+
+ debug_print("vcal_folder_new\n");
+ folder = g_new0(VCalFolder, 1);
+ FOLDER(folder)->klass = &vcal_class;
+ folder_init(FOLDER(folder), name);
+
+ return FOLDER(folder);
+}
+
+static void vcal_folder_destroy(Folder *_folder)
+{
+}
+
+static FolderItem *vcal_item_new(Folder *folder)
+{
+ VCalFolderItem *item;
+ item = g_new0(VCalFolderItem, 1);
+ item->use_cal_view = 1;
+ return (FolderItem *) item;
+
+}
+
+static void vcal_item_destroy(Folder *folder, FolderItem *_item)
+{
+ VCalFolderItem *item = (VCalFolderItem *)_item;
+ g_return_if_fail(item != NULL);
+ g_free(item);
+}
+
+static gchar *vcal_item_get_path(Folder *folder, FolderItem *item)
+{
+ VCalFolderItem *fitem = (VCalFolderItem *)item;
+ if (fitem->uri == NULL)
+ return g_strdup(vcal_manager_get_event_path());
+ else {
+ gchar *path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", G_DIR_SEPARATOR_S,
+ item->path, NULL);
+ return path;
+ }
+}
+
+static gint vcal_scan_tree(Folder *folder)
+{
+ g_return_val_if_fail(folder != NULL, -1);
+
+ folder->outbox = NULL;
+ folder->draft = NULL;
+ folder->queue = NULL;
+ folder->trash = NULL;
+
+ debug_print("scanning tree\n");
+ vcal_create_tree(folder);
+
+ return 0;
+}
+
+gboolean manual_update = TRUE;
+
+static gint feed_fetch(FolderItem *fitem, MsgNumberList ** list, gboolean *old_uids_valid)
+{
+ VCalFolderItem *item = (VCalFolderItem *)fitem;
+ icalcomponent *evt = NULL;
+ icalcomponent_kind type = ICAL_VEVENT_COMPONENT;
+ gint num = 1;
+ gint past_msg = -1, today_msg = -1, tomorrow_msg = -1,
+ thisweek_msg = -1, later_msg = -1;
+
+ debug_print("fetching\n");
+
+ if (!item->uri) {
+ debug_print("no uri!\n");
+ return -1;
+ }
+
+ update_subscription(item->uri, TRUE);
+
+ *old_uids_valid = FALSE;
+ *list = NULL;
+
+ if (item->cal) {
+ evt = icalcomponent_get_first_component(
+ item->cal, ICAL_VEVENT_COMPONENT);
+ if (evt == NULL) {
+ evt = icalcomponent_get_first_component(
+ item->cal, ICAL_VTODO_COMPONENT);
+ if (evt != NULL)
+ type = ICAL_VTODO_COMPONENT;
+ }
+ } else
+ debug_print("no cal!\n");
+
+ if (evt == NULL)
+ debug_print("no event\n");
+
+ if (item->numlist) {
+ g_slist_free(item->numlist);
+ item->numlist = NULL;
+ }
+
+ if (item->evtlist) {
+ slist_free_icalfeeddata(item->evtlist);
+ g_slist_free(item->evtlist);
+ item->evtlist = NULL;
+ }
+
+ while (evt) {
+ icalproperty *prop;
+ icalproperty *rprop = icalcomponent_get_first_property(evt, ICAL_RRULE_PROPERTY);
+ struct icalrecurrencetype recur;
+ struct icaltimetype next;
+ icalrecur_iterator* ritr = NULL;
+ EventTime days;
+
+ if (rprop) {
+ icalproperty *rprop2;
+ recur = icalproperty_get_rrule(rprop);
+ rprop2 = icalproperty_new_rrule(recur);
+ prop = icalcomponent_get_first_property(evt, ICAL_DTSTART_PROPERTY);
+ if (prop) {
+ ritr = icalrecur_iterator_new(recur, icalproperty_get_dtstart(prop));
+ next = icalrecur_iterator_next(ritr); /* skip first one */
+ }
+
+ rprop = rprop2;
+ }
+
+ prop = icalcomponent_get_first_property(evt, ICAL_UID_PROPERTY);
+ if (prop) {
+ gchar *orig_uid = NULL;
+ gchar *uid = g_strdup(icalproperty_get_uid(prop));
+ IcalFeedData *data = icalfeeddata_new(
+ icalcomponent_new_clone(evt), NULL);
+ int i = 0;
+ orig_uid = g_strdup(uid);
+
+add_new:
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ item->evtlist = g_slist_prepend(item->evtlist, data);
+ data = NULL;
+ debug_print("add %d : %s\n", num, uid);
+ g_free(uid);
+ num++;
+ prop = icalcomponent_get_first_property(evt, ICAL_DTSTART_PROPERTY);
+ if (prop) {
+ struct icaltimetype itt = icalproperty_get_dtstart(prop);
+ days = event_to_today(NULL, icaltime_as_timet(itt));
+ if (days == EVENT_PAST && past_msg == -1) {
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ data = icalfeeddata_new(NULL, EVENT_PAST_ID);
+ past_msg = num++;
+ } else if (days == EVENT_TODAY && today_msg == -1) {
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ data = icalfeeddata_new(NULL, EVENT_TODAY_ID);
+ today_msg = num++;
+ } else if (days == EVENT_TOMORROW && tomorrow_msg == -1) {
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ data = icalfeeddata_new(NULL, EVENT_TOMORROW_ID);
+ tomorrow_msg = num++;
+ } else if (days == EVENT_THISWEEK && thisweek_msg == -1) {
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ data = icalfeeddata_new(NULL, EVENT_THISWEEK_ID);
+ thisweek_msg = num++;
+ } else if (days == EVENT_LATER && later_msg == -1) {
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ data = icalfeeddata_new(NULL, EVENT_LATER_ID);
+ later_msg = num++;
+ }
+ } else {
+ if (past_msg == -1) {
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ data = icalfeeddata_new(NULL, EVENT_PAST_ID);
+ past_msg = num++;
+ }
+ }
+ if (data) {
+ item->evtlist = g_slist_prepend(item->evtlist, data);
+ data = NULL;
+ }
+ if (rprop) {
+ struct icaldurationtype ical_dur;
+ struct icaltimetype dtstart, dtend;
+ evt = icalcomponent_new_clone(evt);
+ prop = icalcomponent_get_first_property(evt, ICAL_RRULE_PROPERTY);
+ if (prop) {
+ icalcomponent_remove_property(evt, prop);
+ icalproperty_free(prop);
+ }
+ prop = icalcomponent_get_first_property(evt, ICAL_DTSTART_PROPERTY);
+ if (prop)
+ dtstart = icalproperty_get_dtstart(prop);
+ prop = icalcomponent_get_first_property(evt, ICAL_DTEND_PROPERTY);
+ if (prop)
+ dtend = icalproperty_get_dtend(prop);
+ ical_dur = icaltime_subtract(dtend, dtstart);
+ next = icalrecur_iterator_next(ritr);
+ if (!icaltime_is_null_time(next) &&
+ !icaltime_is_null_time(dtstart) && i < 100) {
+ prop = icalcomponent_get_first_property(evt, ICAL_DTSTART_PROPERTY);
+ icalproperty_set_dtstart(prop, next);
+
+ prop = icalcomponent_get_first_property(evt, ICAL_DTEND_PROPERTY);
+ if (prop)
+ icalproperty_set_dtend(prop, icaltime_add(next, ical_dur));
+
+ prop = icalcomponent_get_first_property(evt, ICAL_UID_PROPERTY);
+ uid = g_strdup_printf("%s-%d", orig_uid, i);
+ icalproperty_set_uid(prop, uid);
+ /* dont free uid, used after (add_new) */
+ data = icalfeeddata_new(evt, NULL);
+ i++;
+ goto add_new;
+ } else {
+ icalcomponent_free(evt);
+ evt = NULL;
+ }
+ }
+ g_free(orig_uid);
+ } else {
+ debug_print("no uid!\n");
+ }
+ if (rprop) {
+ icalproperty_free(rprop);
+ }
+ if (ritr) {
+ icalrecur_iterator_free(ritr);
+ ritr = NULL;
+ }
+ evt = icalcomponent_get_next_component(
+ item->cal, type);
+ }
+ if (today_msg == -1) {
+ IcalFeedData *data = icalfeeddata_new(NULL, EVENT_TODAY_ID);
+ item->numlist = g_slist_prepend(item->numlist, GINT_TO_POINTER(num));
+ today_msg = num++;
+ item->evtlist = g_slist_prepend(item->evtlist, data);
+ }
+ item->numlist = g_slist_reverse(item->numlist);
+ item->evtlist = g_slist_reverse(item->evtlist);
+
+ *list = item->numlist ? g_slist_copy(item->numlist) : NULL;
+ debug_print("return %d\n", num);
+ return num;
+}
+
+#define VCAL_FOLDER_ADD_EVENT(event) \
+{ \
+ \
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(n_msg)); \
+ debug_print("add %d %s\n", n_msg, event->uid); \
+ n_msg++; \
+ days = event_to_today(event, 0); \
+ \
+ if (days == EVENT_PAST && past_msg == -1) { \
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(n_msg)); \
+ past_msg = n_msg++; \
+ g_hash_table_insert(hash_uids, GINT_TO_POINTER(past_msg), g_strdup(EVENT_PAST_ID)); \
+ } else if (days == EVENT_TODAY && today_msg == -1) { \
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(n_msg)); \
+ today_msg = n_msg++; \
+ g_hash_table_insert(hash_uids, GINT_TO_POINTER(today_msg), g_strdup(EVENT_TODAY_ID)); \
+ } else if (days == EVENT_TOMORROW && tomorrow_msg == -1) { \
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(n_msg)); \
+ tomorrow_msg = n_msg++; \
+ g_hash_table_insert(hash_uids, GINT_TO_POINTER(tomorrow_msg), g_strdup(EVENT_TOMORROW_ID)); \
+ } else if (days == EVENT_THISWEEK && thisweek_msg == -1) { \
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(n_msg)); \
+ thisweek_msg = n_msg++; \
+ g_hash_table_insert(hash_uids, GINT_TO_POINTER(thisweek_msg), g_strdup(EVENT_THISWEEK_ID)); \
+ } else if (days == EVENT_LATER && later_msg == -1) { \
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(n_msg)); \
+ later_msg = n_msg++; \
+ g_hash_table_insert(hash_uids, GINT_TO_POINTER(later_msg), g_strdup(EVENT_LATER_ID)); \
+ } \
+}
+
+GSList *vcal_get_events_list(FolderItem *item)
+{
+ DIR *dp;
+ struct dirent *d;
+ GSList *events = NULL;
+
+ if (item != item->folder->inbox) {
+ GSList *subs = vcal_folder_get_webcal_events_for_folder(item);
+ GSList *cur = NULL;
+ for (cur = subs; cur; cur = cur->next) {
+ /* Don't free that, it's done when subscriptions are
+ * fetched */
+ icalcomponent *ical = (icalcomponent *)cur->data;
+ VCalEvent *event = vcal_get_event_from_ical(
+ icalcomponent_as_ical_string(ical), NULL);
+ events = g_slist_prepend(events, event);
+ }
+ g_slist_free(subs);
+ return events;
+ }
+
+ dp = opendir(vcal_manager_get_event_path());
+
+ if (!dp) {
+ FILE_OP_ERROR(vcal_manager_get_event_path(), "opendir");
+ return 0;
+ }
+
+ while ((d = readdir(dp)) != NULL) {
+ VCalEvent *event = NULL;
+ if (d->d_name[0] == '.' || strstr(d->d_name, ".bak")
+ || !strcmp(d->d_name, "internal.ics")
+ || !strcmp(d->d_name, "internal.ifb")
+ || !strcmp(d->d_name, "multisync"))
+ continue;
+
+ event = vcal_manager_load_event(d->d_name);
+ if (!event)
+ continue;
+ if (event->rec_occurence) {
+ vcal_manager_free_event(event);
+ claws_unlink(d->d_name);
+ continue;
+ }
+
+ if (event && event->method != ICAL_METHOD_CANCEL) {
+ PrefsAccount *account = vcal_manager_get_account_from_event(event);
+ enum icalparameter_partstat status =
+ account ? vcal_manager_get_reply_for_attendee(event, account->address): ICAL_PARTSTAT_NEEDSACTION;
+ if (status == ICAL_PARTSTAT_ACCEPTED
+ || status == ICAL_PARTSTAT_TENTATIVE) {
+ events = g_slist_prepend(events, event);
+ } else {
+ vcal_manager_free_event(event);
+ continue;
+ }
+ if ((status == ICAL_PARTSTAT_ACCEPTED
+ || status == ICAL_PARTSTAT_TENTATIVE)
+ && event->recur && *(event->recur)) {
+ struct icalrecurrencetype recur;
+ struct icaltimetype dtstart;
+ struct icaltimetype next;
+ icalrecur_iterator* ritr;
+ time_t duration = (time_t) NULL;
+ struct icaldurationtype ical_dur;
+ int i = 0;
+
+ debug_print("dumping recurring events from main event %s\n", d->d_name);
+ recur = icalrecurrencetype_from_string(event->recur);
+ dtstart = icaltime_from_string(event->dtstart);
+
+ duration = icaltime_as_timet(icaltime_from_string(event->dtend))
+ - icaltime_as_timet(icaltime_from_string(event->dtstart));
+
+ ical_dur = icaldurationtype_from_int(duration);
+
+ ritr = icalrecur_iterator_new(recur, dtstart);
+
+ next = icalrecur_iterator_next(ritr); /* skip first one */
+ if (!icaltime_is_null_time(next))
+ next = icalrecur_iterator_next(ritr);
+ debug_print("next time is %snull\n", icaltime_is_null_time(next)?"":"not ");
+ while (!icaltime_is_null_time(next) && i < 100) {
+ gchar *new_start = NULL, *new_end = NULL;
+ VCalEvent *nevent = NULL;
+ gchar *uid = g_strdup_printf("%s-%d", event->uid, i);
+ new_start = icaltime_as_ical_string(next);
+ new_end = icaltime_as_ical_string(
+ icaltime_add(next, ical_dur));
+ debug_print("adding with start/end %s:%s\n", new_start, new_end);
+ nevent = vcal_manager_new_event(uid, event->organizer, event->orgname,
+ event->location, event->summary, event->description,
+ new_start, new_end, NULL,
+ event->tzid, event->url, event->method,
+ event->sequence, event->type);
+ g_free(uid);
+ vcal_manager_copy_attendees(event, nevent);
+ nevent->rec_occurence = TRUE;
+ vcal_manager_save_event(nevent, FALSE);
+ account = vcal_manager_get_account_from_event(event);
+ status =
+ account ? vcal_manager_get_reply_for_attendee(event, account->address): ICAL_PARTSTAT_NEEDSACTION;
+ if (status == ICAL_PARTSTAT_ACCEPTED
+ || status == ICAL_PARTSTAT_TENTATIVE) {
+ events = g_slist_prepend(events, nevent);
+ } else {
+ vcal_manager_free_event(nevent);
+ }
+ next = icalrecur_iterator_next(ritr);
+ debug_print("next time is %snull\n", icaltime_is_null_time(next)?"":"not ");
+ i++;
+ }
+ icalrecur_iterator_free(ritr);
+ }
+ } else {
+ vcal_manager_free_event(event);
+ }
+ }
+ closedir(dp);
+ return g_slist_reverse(events);
+}
+
+static gint vcal_get_num_list(Folder *folder, FolderItem *item,
+ MsgNumberList ** list, gboolean *old_uids_valid)
+{
+ int n_msg = 1;
+ gint past_msg = -1, today_msg = -1, tomorrow_msg = -1,
+ thisweek_msg = -1, later_msg = -1;
+ GSList *events = NULL, *cur;
+ START_TIMING("");
+ g_return_val_if_fail (*list == NULL, 0); /* we expect a NULL list */
+
+ debug_print(" num for %s\n", ((VCalFolderItem *)item)->uri ? ((VCalFolderItem *)item)->uri:"(null)");
+
+ *old_uids_valid = FALSE;
+
+ if (((VCalFolderItem *)item)->uri)
+ return feed_fetch(item, list, old_uids_valid);
+
+ events = vcal_get_events_list(item);
+
+ debug_print("get_num_list\n");
+
+ if (hash_uids != NULL)
+ g_hash_table_destroy(hash_uids);
+
+ hash_uids = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, g_free);
+
+ for (cur = events; cur; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+
+ if (!event)
+ continue;
+ g_hash_table_insert(hash_uids, GINT_TO_POINTER(n_msg), g_strdup(event->uid));
+
+ if (event->rec_occurence) {
+ vcal_manager_free_event(event);
+ continue;
+ }
+
+ if (event->method != ICAL_METHOD_CANCEL) {
+ EventTime days;
+ VCAL_FOLDER_ADD_EVENT(event);
+ }
+ if (event)
+ vcal_manager_free_event(event);
+
+
+ }
+
+ if (today_msg == -1) {
+ *list = g_slist_prepend(*list, GINT_TO_POINTER(n_msg));
+ today_msg = n_msg++;
+ g_hash_table_insert(hash_uids, GINT_TO_POINTER(today_msg), g_strdup(EVENT_TODAY_ID));
+ }
+
+ g_slist_free(events);
+ vcal_folder_export(folder);
+
+ vcal_set_mtime(folder, item);
+
+ *list = g_slist_reverse(*list);
+ END_TIMING();
+ return g_slist_length(*list);
+}
+
+static MsgInfo *vcal_parse_msg(const gchar *file, FolderItem *item, int num)
+{
+ MsgInfo *msginfo = NULL;
+ MsgFlags flags;
+
+ debug_print("parse_msg\n");
+
+ flags.perm_flags = 0;
+ flags.tmp_flags = 0;
+ msginfo = procheader_parse_file(file, flags, TRUE, TRUE);
+
+ msginfo->msgnum = num;
+ msginfo->folder = item;
+ return msginfo;
+}
+
+static MsgInfo *vcal_get_msginfo(Folder * folder,
+ FolderItem * item, gint num)
+{
+ MsgInfo *msginfo = NULL;
+ gchar *file;
+
+ debug_print("get_msginfo\n");
+
+ g_return_val_if_fail(item != NULL, NULL);
+ g_return_val_if_fail(num > 0, NULL);
+
+ file = vcal_fetch_msg(folder, item, num);
+
+ if (!file) {
+ return NULL;
+ }
+
+ msginfo = vcal_parse_msg(file, item, num);
+
+ if (msginfo) {
+ msginfo->flags.perm_flags = 0;
+ msginfo->flags.tmp_flags = 0;
+
+ vcal_change_flags(NULL, NULL, msginfo, 0);
+
+ debug_print(" adding %d\n", num);
+ }
+ g_unlink(file);
+ g_free(file);
+
+ debug_print(" got msginfo %p\n", msginfo);
+
+ return msginfo;
+}
+
+static gchar *feed_fetch_item(FolderItem * fitem, gint num)
+{
+ gchar *filename = NULL;
+ VCalFolderItem *item = (VCalFolderItem *)fitem;
+ GSList *ncur, *ecur;
+ int i = 1;
+ IcalFeedData *data = NULL;
+
+ if (!item->numlist) {
+ folder_item_scan_full(fitem, FALSE);
+ }
+ if (!item->numlist) {
+ debug_print("numlist null\n");
+ return NULL;
+ }
+
+ ncur = item->numlist;
+ ecur = item->evtlist;
+
+ while (i < num) {
+ if (!ncur || !ecur) {
+ debug_print("list short end (%d to %d) %d,%d\n", i, num, ncur!=NULL, ecur!=NULL);
+ return NULL;
+ }
+ ncur = ncur->next;
+ ecur = ecur->next;
+ i++;
+ }
+
+ data = (IcalFeedData *)ecur->data;
+
+ if (!data) {
+ return NULL;
+ }
+
+ if (data->event)
+ filename = vcal_manager_icalevent_dump(data->event, fitem->name, NULL);
+ else if (data->pseudoevent_id) {
+ filename = vcal_manager_dateevent_dump(data->pseudoevent_id, fitem);
+ created_files = g_slist_prepend(created_files, g_strdup(filename));
+ } else {
+ debug_print("no event\n");
+ return NULL;
+ }
+
+ debug_print("feed item dump to %s\n", filename);
+ return filename;
+}
+
+static gchar *vcal_fetch_msg(Folder * folder, FolderItem * item,
+ gint num)
+{
+ gchar *filename = NULL;
+ const gchar *uid = NULL;
+
+ debug_print(" fetch for %s %d\n", (((VCalFolderItem *)item)->uri ? ((VCalFolderItem *)item)->uri:"(null)"), num);
+ if (((VCalFolderItem *)item)->uri)
+ return feed_fetch_item(item, num);
+
+ if (!uid) {
+ if (!hash_uids)
+ folder_item_scan_full(item, FALSE);
+ uid = g_hash_table_lookup(hash_uids, GINT_TO_POINTER(num));
+ }
+ if (uid &&
+ (!strcmp(uid, EVENT_PAST_ID) ||
+ !strcmp(uid, EVENT_TODAY_ID) ||
+ !strcmp(uid, EVENT_TOMORROW_ID) ||
+ !strcmp(uid, EVENT_THISWEEK_ID) ||
+ !strcmp(uid, EVENT_LATER_ID))) {
+ filename = vcal_manager_dateevent_dump(uid, item);
+ } else if (uid) {
+ VCalEvent *event = NULL;
+ event = vcal_manager_load_event(uid);
+ if (event)
+ filename = vcal_manager_event_dump(event, FALSE, TRUE, NULL, FALSE);
+
+ if (filename) {
+ created_files = g_slist_prepend(created_files, g_strdup(filename));
+ }
+
+ vcal_manager_free_event(event);
+ }
+
+ return filename;
+}
+
+static gint vcal_add_msg(Folder *folder, FolderItem *_dest, const gchar *file, MsgFlags *flags)
+{
+ gchar *contents = file_read_to_str(file);
+ if (contents) {
+ vcal_add_event(contents);
+ }
+ g_free(contents);
+ return 0;
+}
+
+static void vcal_remove_event (Folder *folder, MsgInfo *msginfo);
+
+static gint vcal_remove_msg(Folder *folder, FolderItem *_item, gint num)
+{
+ MsgInfo *msginfo = folder_item_get_msginfo(_item, num);
+
+ if (!msginfo)
+ return 0;
+
+ if (_item == folder->inbox)
+ vcal_remove_event(folder, msginfo);
+
+ procmsg_msginfo_free(msginfo);
+ return 0;
+}
+
+static FolderItem *vcal_create_folder(Folder * folder,
+ FolderItem * parent,
+ const gchar * name)
+{
+ gchar *path = NULL;
+ FolderItem *newitem = NULL;
+ debug_print("creating new vcal folder\n");
+
+ path = g_strconcat((parent->path != NULL) ? parent->path : "", ".", name, NULL);
+ newitem = folder_item_new(folder, name, path);
+ folder_item_append(parent, newitem);
+ g_free(path);
+
+ return newitem;
+}
+
+static gint vcal_create_tree(Folder *folder)
+{
+ FolderItem *rootitem, *inboxitem;
+ GNode *rootnode, *inboxnode;
+
+ if (!folder->node) {
+ rootitem = folder_item_new(folder, folder->name, NULL);
+ rootitem->folder = folder;
+ rootnode = g_node_new(rootitem);
+ folder->node = rootnode;
+ rootitem->node = rootnode;
+ } else {
+ rootitem = FOLDER_ITEM(folder->node->data);
+ rootnode = folder->node;
+ }
+
+ /* Add inbox folder */
+ if (!folder->inbox) {
+ inboxitem = folder_item_new(folder, "Meetings", ".meetings");
+ inboxitem->folder = folder;
+ inboxitem->stype = F_INBOX;
+ inboxnode = g_node_new(inboxitem);
+ inboxitem->node = inboxnode;
+ folder->inbox = inboxitem;
+ g_node_append(rootnode, inboxnode);
+ } else {
+ g_free(folder->inbox->path);
+ folder->inbox->path = g_strdup(".meetings");
+ }
+
+ debug_print("created new vcal tree\n");
+ return 0;
+}
+
+static gint vcal_remove_folder(Folder *folder, FolderItem *fitem)
+{
+ VCalFolderItem *item = (VCalFolderItem *)fitem;
+ if (!item->uri)
+ return -1;
+ else {
+ if (item->feed)
+ g_free(item->feed);
+ if (item->uri)
+ g_free(item->uri);
+ item->feed = NULL;
+ item->uri = NULL;
+ folder_item_remove(fitem);
+ return 0;
+ }
+}
+
+static gboolean vcal_scan_required(Folder *folder, FolderItem *item)
+{
+ struct stat s;
+ VCalFolderItem *vitem = (VCalFolderItem *)item;
+
+ g_return_val_if_fail(item != NULL, FALSE);
+
+ if (vitem->uri) {
+ return TRUE;
+ } else if (g_stat(vcal_manager_get_event_path(), &s) < 0) {
+ return TRUE;
+ } else if ((s.st_mtime > item->mtime) &&
+ (s.st_mtime - 3600 != item->mtime)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gint vcal_folder_lock_count = 0;
+
+static void vcal_set_mtime(Folder *folder, FolderItem *item)
+{
+ struct stat s;
+ gchar *path = folder_item_get_path(item);
+
+ if (folder->inbox != item)
+ return;
+
+ g_return_if_fail(path != NULL);
+
+ if (g_stat(path, &s) < 0) {
+ FILE_OP_ERROR(path, "stat");
+ g_free(path);
+ return;
+ }
+
+ item->mtime = s.st_mtime;
+ debug_print("VCAL: forced mtime of %s to %ld\n", item->name?item->name:"(null)", item->mtime);
+ g_free(path);
+}
+
+void vcal_folder_export(Folder *folder)
+{
+ FolderItem *item = folder?folder->inbox:NULL;
+ gboolean need_scan = folder?vcal_scan_required(folder, item):TRUE;
+
+ if (vcal_folder_lock_count) /* blocked */
+ return;
+ vcal_folder_lock_count++;
+ if (vcal_meeting_export_calendar(vcalprefs.export_path,
+ vcalprefs.export_user,
+ vcalprefs.export_pass,
+ TRUE)) {
+ debug_print("exporting calendar\n");
+ if (vcalprefs.export_enable &&
+ vcalprefs.export_command &&
+ strlen(vcalprefs.export_command))
+ execute_command_line(
+ vcalprefs.export_command, TRUE);
+ }
+ if (vcal_meeting_export_freebusy(vcalprefs.export_freebusy_path,
+ vcalprefs.export_freebusy_user,
+ vcalprefs.export_freebusy_pass)) {
+ debug_print("exporting freebusy\n");
+ if (vcalprefs.export_freebusy_enable &&
+ vcalprefs.export_freebusy_command &&
+ strlen(vcalprefs.export_freebusy_command))
+ execute_command_line(
+ vcalprefs.export_freebusy_command, TRUE);
+ }
+ vcal_folder_lock_count--;
+ if (!need_scan && folder) {
+ vcal_set_mtime(folder, folder->inbox);
+ }
+}
+
+static void vcal_remove_event (Folder *folder, MsgInfo *msginfo)
+{
+ const gchar *uid = msginfo->msgid;
+ VCalFolderItem *item = (VCalFolderItem *)msginfo->folder;
+
+ if (uid) {
+ gchar *file = vcal_manager_get_event_file(uid);
+ g_unlink(file);
+ g_free(file);
+ }
+
+ if (!item || !item->batching)
+ vcal_folder_export(folder);
+ else if (item) {
+ item->dirty = TRUE;
+ }
+}
+
+static void vcal_change_flags(Folder *folder, FolderItem *_item, MsgInfo *msginfo, MsgPermFlags newflags)
+{
+ EventTime date;
+
+ if (newflags & MSG_DELETED) {
+ /* delete the stuff */
+ msginfo->flags.perm_flags |= MSG_DELETED;
+ vcal_remove_event(folder, msginfo);
+ return;
+ }
+
+ /* accept the rest */
+ msginfo->flags.perm_flags = newflags;
+
+ /* but not color */
+ msginfo->flags.perm_flags &= ~MSG_CLABEL_FLAG_MASK;
+
+ date = event_to_today(NULL, msginfo->date_t);
+ switch(date) {
+ case EVENT_PAST:
+ break;
+ case EVENT_TODAY:
+ msginfo->flags.perm_flags |= MSG_COLORLABEL_TO_FLAGS(2); /* Red */
+ break;
+ case EVENT_TOMORROW:
+ break;
+ case EVENT_THISWEEK:
+ break;
+ case EVENT_LATER:
+ break;
+ }
+ if (msginfo->msgid) {
+ if (!strcmp(msginfo->msgid, EVENT_TODAY_ID) ||
+ !strcmp(msginfo->msgid, EVENT_TOMORROW_ID))
+ msginfo->flags.perm_flags |= MSG_MARKED;
+ }
+}
+
+void vcal_folder_gtk_init(void)
+{
+ vcal_fill_popup_menu_labels();
+
+ folderview_register_popup(&vcal_popup);
+}
+
+void vcal_folder_gtk_done(void)
+{
+ GSList *cur = created_files;
+ while (cur) {
+ gchar *file = (gchar *)cur->data;
+ cur = cur->next;
+ if (!file)
+ continue;
+ debug_print("removing %s\n", file);
+ g_unlink(file);
+ g_free(file);
+ }
+ g_slist_free(created_files);
+ folderview_unregister_popup(&vcal_popup);
+}
+
+static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item)
+{
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "NewMeeting", "FolderViewPopup/NewMeeting", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "ExportCal", "FolderViewPopup/ExportCal", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVcal1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SubscribeCal", "FolderViewPopup/SubscribeCal", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "UnsubscribeCal", "FolderViewPopup/UnsubscribeCal", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVcal2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVcal3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckSubs", "FolderViewPopup/CheckSubs", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVcal4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "ListView", "FolderViewPopup/ListView", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "WeekView", "FolderViewPopup/WeekView", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MonthView", "FolderViewPopup/MonthView", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorVcal5", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
+}
+
+static gboolean setting_sensitivity = FALSE;
+static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *fitem)
+{
+ VCalFolderItem *item = (VCalFolderItem *)fitem;
+
+#define SET_SENS(name, sens) \
+ cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)
+
+ setting_sensitivity = TRUE;
+
+ cm_toggle_menu_set_active_full(ui_manager, "Popup/FolderViewPopup/ListView", (item->use_cal_view == 0));
+ cm_toggle_menu_set_active_full(ui_manager, "Popup/FolderViewPopup/WeekView", (item->use_cal_view == 1));
+ cm_toggle_menu_set_active_full(ui_manager, "Popup/FolderViewPopup/MonthView", (item->use_cal_view == 2));
+ SET_SENS("FolderViewPopup/NewMeeting", item->uri == NULL);
+ SET_SENS("FolderViewPopup/ExportCal", TRUE);
+ SET_SENS("FolderViewPopup/SubscribeCal", item->uri == NULL);
+ SET_SENS("FolderViewPopup/UnsubscribeCal", item->uri != NULL);
+ SET_SENS("FolderViewPopup/RenameFolder", folder_item_parent(fitem) != NULL);
+ SET_SENS("FolderViewPopup/CheckSubs", TRUE);
+ SET_SENS("FolderViewPopup/ListView", folder_item_parent(fitem) != NULL);
+ SET_SENS("FolderViewPopup/WeekView", folder_item_parent(fitem) != NULL);
+ SET_SENS("FolderViewPopup/MonthView", folder_item_parent(fitem) != NULL);
+ setting_sensitivity = FALSE;
+#undef SET_SENS
+}
+
+static void new_meeting_cb(GtkAction *action, gpointer data)
+{
+ debug_print("new_meeting_cb\n");
+ vcal_meeting_create(NULL);
+}
+
+GSList * vcal_folder_get_waiting_events(void)
+{
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ return vcal_get_events_list(folder->inbox);
+}
+
+typedef struct _get_webcal_data {
+ GSList *list;
+ FolderItem *item;
+} GetWebcalData;
+
+static gboolean get_webcal_events_func(GNode *node, gpointer user_data)
+{
+ FolderItem *item = node->data;
+ GetWebcalData *data = user_data;
+ gboolean dummy = FALSE;
+ GSList *list = NULL, *cur = NULL;
+
+ if (data->item && data->item != item)
+ return FALSE;
+
+ feed_fetch(item, &list, &dummy);
+
+ g_slist_free(list);
+
+ for (cur = ((VCalFolderItem *)item)->evtlist; cur; cur = cur->next) {
+ IcalFeedData *fdata = (IcalFeedData *)cur->data;
+ if (fdata->event)
+ data->list = g_slist_prepend(data->list, fdata->event);
+ }
+ return FALSE;
+}
+
+GSList * vcal_folder_get_webcal_events(void)
+{
+ GetWebcalData *data = g_new0(GetWebcalData, 1);
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ GSList *list = NULL;
+ data->item = NULL;
+ g_node_traverse(folder->node, G_PRE_ORDER,
+ G_TRAVERSE_ALL, -1, get_webcal_events_func, data);
+
+ list = data->list;
+ g_free(data);
+
+ return g_slist_reverse(list);
+}
+
+static gboolean vcal_free_data_func(GNode *node, gpointer user_data)
+{
+ VCalFolderItem *item = node->data;
+
+ if (item->cal) {
+ icalcomponent_free(item->cal);
+ item->cal = NULL;
+ }
+ if (item->numlist) {
+ g_slist_free(item->numlist);
+ item->numlist = NULL;
+ }
+
+ if (item->evtlist) {
+ slist_free_icalfeeddata(item->evtlist);
+ g_slist_free(item->evtlist);
+ item->evtlist = NULL;
+ }
+
+ return FALSE;
+}
+
+void vcal_folder_free_data(void)
+{
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+
+ g_node_traverse(folder->node, G_PRE_ORDER,
+ G_TRAVERSE_ALL, -1, vcal_free_data_func, NULL);
+}
+
+GSList * vcal_folder_get_webcal_events_for_folder(FolderItem *item)
+{
+ GetWebcalData *data = g_new0(GetWebcalData, 1);
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ GSList *list = NULL;
+ data->item = item;
+ g_node_traverse(folder->node, G_PRE_ORDER,
+ G_TRAVERSE_ALL, -1, get_webcal_events_func, data);
+
+ list = data->list;
+ g_free(data);
+
+ return g_slist_reverse(list);
+}
+
+gchar* get_item_event_list_for_date(FolderItem *item, EventTime date)
+{
+ GSList *strs = NULL;
+ GSList *cur;
+ gchar *result = NULL;
+ gchar *datestr = NULL;
+
+ if (((VCalFolderItem *)item)->uri) {
+ for (cur = ((VCalFolderItem *)item)->evtlist; cur; cur = cur->next) {
+ IcalFeedData *fdata = (IcalFeedData *)cur->data;
+ icalproperty *prop;
+ struct icaltimetype itt;
+ gchar *summary = NULL;
+ EventTime days;
+ if (!fdata->event)
+ continue;
+ prop = icalcomponent_get_first_property((icalcomponent *)fdata->event, ICAL_DTSTART_PROPERTY);
+
+ if (!prop)
+ continue;
+ itt = icalproperty_get_dtstart(prop);
+ days = event_to_today(NULL, icaltime_as_timet(itt));
+ if (days != date)
+ continue;
+ prop = icalcomponent_get_first_property((icalcomponent *)fdata->event, ICAL_SUMMARY_PROPERTY);
+ if (prop) {
+ if (!g_utf8_validate(icalproperty_get_summary(prop), -1, NULL))
+ summary = conv_codeset_strdup(icalproperty_get_summary(prop),
+ conv_get_locale_charset_str(), CS_UTF_8);
+ else
+ summary = g_strdup(icalproperty_get_summary(prop));
+ } else
+ summary = g_strdup("-");
+
+ strs = g_slist_prepend(strs, summary);
+ }
+ } else {
+ GSList *evtlist = vcal_folder_get_waiting_events();
+ for (cur = evtlist; cur; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+ EventTime days;
+ days = event_to_today(event, 0);
+ gchar *summary = NULL;
+ if (days == date) {
+ summary = g_strdup(event->summary);
+ strs = g_slist_prepend(strs, summary);
+ }
+ vcal_manager_free_event(event);
+ }
+ }
+
+ switch(date) {
+ case EVENT_PAST:
+ datestr=_("in the past");
+ break;
+ case EVENT_TODAY:
+ datestr=_("today");
+ break;
+ case EVENT_TOMORROW:
+ datestr=_("tomorrow");
+ break;
+ case EVENT_THISWEEK:
+ datestr=_("this week");
+ break;
+ case EVENT_LATER:
+ datestr=_("later");
+ break;
+ }
+
+ result = g_strdup_printf(_("\nThese are the events planned %s:\n"),
+ datestr?datestr:"never");
+
+ strs = g_slist_reverse(strs);
+ for (cur = strs; cur; cur = cur->next) {
+ int e_len = strlen(result);
+ int n_len = strlen((gchar *)cur->data);
+ if (e_len) {
+ result = g_realloc(result, e_len+n_len+4);
+ *(result+e_len) = '\n';
+ strcpy(result+e_len+1, "- ");
+ strcpy(result+e_len+3, (gchar *)cur->data);
+ } else {
+ result = g_realloc(result, e_len+n_len+3);
+ strcpy(result+e_len, "- ");
+ strcpy(result+e_len+2, (gchar *)cur->data);
+ }
+ }
+ slist_free_strings(strs);
+ g_slist_free(strs);
+ return result;
+}
+
+static void export_cal_cb(GtkAction *action, gpointer data)
+{
+ vcal_meeting_export_calendar(NULL, NULL, NULL, FALSE);
+}
+
+struct CBuf {
+ gchar *str;
+};
+
+static size_t curl_recv(void *buf, size_t size, size_t nmemb, void *stream)
+{
+ struct CBuf *buffer = (struct CBuf *)stream;
+ gchar *tmp = NULL;
+ gchar tmpbuf[size*nmemb + 1];
+
+ memcpy(tmpbuf, buf, size*nmemb);
+ tmpbuf[size*nmemb] = '\0';
+
+ if (buffer->str) {
+ tmp = g_strconcat(buffer->str, tmpbuf, NULL);
+ g_free(buffer->str);
+ buffer->str = tmp;
+ } else {
+ buffer->str = g_strdup(tmpbuf);
+ }
+
+ return size*nmemb;
+}
+
+void *url_read_thread(void *data)
+{
+ thread_data *td = (thread_data *)data;
+ CURLcode res;
+ CURL *curl_ctx = NULL;
+ long response_code;
+ struct CBuf buffer = { NULL };
+ gchar *t_url = (gchar *)td->url;
+
+ while (*t_url == ' ')
+ t_url++;
+ if (strchr(t_url, ' '))
+ *(strchr(t_url, ' ')) = '\0';
+
+#ifdef USE_PTHREAD
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
+
+ curl_ctx = curl_easy_init();
+
+ curl_easy_setopt(curl_ctx, CURLOPT_URL, t_url);
+ curl_easy_setopt(curl_ctx, CURLOPT_WRITEFUNCTION, curl_recv);
+ curl_easy_setopt(curl_ctx, CURLOPT_WRITEDATA, &buffer);
+ curl_easy_setopt(curl_ctx, CURLOPT_TIMEOUT, prefs_common_get_prefs()->io_timeout_secs);
+ curl_easy_setopt(curl_ctx, CURLOPT_NOSIGNAL, 1);
+#if LIBCURL_VERSION_NUM >= 0x070a00
+ curl_easy_setopt(curl_ctx, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt(curl_ctx, CURLOPT_SSL_VERIFYHOST, 0);
+#endif
+ curl_easy_setopt(curl_ctx, CURLOPT_USERAGENT,
+ "Claws Mail vCalendar plugin "
+ "(" PLUGINS_URI ")");
+ curl_easy_setopt(curl_ctx, CURLOPT_FOLLOWLOCATION, 1);
+ res = curl_easy_perform(curl_ctx);
+
+ if (res != 0) {
+ debug_print("res %d %s\n", res, curl_easy_strerror(res));
+ td->error = g_strdup(curl_easy_strerror(res));
+
+ if(res == CURLE_OPERATION_TIMEOUTED)
+ log_error(LOG_PROTOCOL, _("Timeout (%d seconds) connecting to %s\n"),
+ prefs_common_get_prefs()->io_timeout_secs, t_url);
+ }
+
+ curl_easy_getinfo(curl_ctx, CURLINFO_RESPONSE_CODE, &response_code);
+ if( response_code >= 400 && response_code < 500 ) {
+ debug_print("VCalendar: got %ld\n", response_code);
+ switch(response_code) {
+ case 401:
+ td->error = g_strdup(_("401 (Authorisation required)"));
+ break;
+ case 403:
+ td->error = g_strdup(_("403 (Unauthorised)"));
+ break;
+ case 404:
+ td->error = g_strdup(_("404 (Not found)"));
+ break;
+ default:
+ td->error = g_strdup_printf(_("Error %ld"), response_code);
+ break;
+ }
+ }
+ curl_easy_cleanup(curl_ctx);
+ if (buffer.str) {
+ td->result = g_strdup(buffer.str);
+ g_free(buffer.str);
+ }
+
+ td->done = TRUE; /* let the caller thread join() */
+ return GINT_TO_POINTER(0);
+}
+
+gchar *vcal_curl_read(const char *url, const gchar *label, gboolean verbose,
+ void (*callback)(const gchar *url, gchar *data, gboolean verbose, gchar *error))
+{
+ gchar *result;
+ thread_data *td;
+#ifdef USE_PTHREAD
+ pthread_t pt;
+ pthread_attr_t pta;
+#endif
+ void *res;
+ gboolean killed;
+ gchar *error = NULL;
+ result = NULL;
+ td = g_new0(thread_data, 1);
+ res = NULL;
+ killed = FALSE;
+
+ td->url = url;
+ td->result = NULL;
+ td->done = FALSE;
+
+ STATUSBAR_PUSH(mainwindow_get_mainwindow(), label);
+
+#ifdef USE_PTHREAD
+ if (pthread_attr_init(&pta) != 0 ||
+ pthread_attr_setdetachstate(&pta, PTHREAD_CREATE_JOINABLE) != 0 ||
+ pthread_create(&pt, &pta,
+ url_read_thread, td) != 0) {
+ url_read_thread(td);
+ }
+ while (!td->done) {
+ claws_do_idle();
+ }
+
+ pthread_join(pt, &res);
+#else
+ url_read_thread(td);
+#endif
+
+ result = td->result;
+ error = td->error;
+ g_free(td);
+
+ STATUSBAR_POP(mainwindow_get_mainwindow());
+
+ if (callback) {
+ callback(url, result, verbose, error);
+ return NULL;
+ } else {
+ if (error)
+ g_free(error);
+ return result;
+ }
+}
+
+gboolean vcal_curl_put(gchar *url, FILE *fp, gint filesize, const gchar *user, const gchar *pass)
+{
+ gboolean res = TRUE;
+ CURL *curl_ctx = curl_easy_init();
+ long response_code = 0;
+ gchar *t_url = url;
+ gchar *userpwd = NULL;
+
+ struct curl_slist * headers = curl_slist_append(NULL,
+ "Content-Type: text/calendar; charset=\"utf-8\"" );
+
+ while (*t_url == ' ')
+ t_url++;
+ if (strchr(t_url, ' '))
+ *(strchr(t_url, ' ')) = '\0';
+
+ if (user && pass && *user && *pass) {
+ userpwd = g_strdup_printf("%s:%s",user,pass);
+ curl_easy_setopt(curl_ctx, CURLOPT_USERPWD, userpwd);
+ }
+ curl_easy_setopt(curl_ctx, CURLOPT_URL, t_url);
+ curl_easy_setopt(curl_ctx, CURLOPT_UPLOAD, 1);
+ curl_easy_setopt(curl_ctx, CURLOPT_READFUNCTION, NULL);
+ curl_easy_setopt(curl_ctx, CURLOPT_READDATA, fp);
+ curl_easy_setopt(curl_ctx, CURLOPT_HTTPHEADER, headers);
+#if LIBCURL_VERSION_NUM >= 0x070a00
+ curl_easy_setopt(curl_ctx, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt(curl_ctx, CURLOPT_SSL_VERIFYHOST, 0);
+#endif
+ curl_easy_setopt(curl_ctx, CURLOPT_USERAGENT,
+ "Claws Mail vCalendar plugin "
+ "(http://www.claws-mail.org/plugins.php)");
+ curl_easy_setopt(curl_ctx, CURLOPT_INFILESIZE, filesize);
+ res = curl_easy_perform(curl_ctx);
+ g_free(userpwd);
+
+ if (res != 0) {
+ debug_print("res %d %s\n", res, curl_easy_strerror(res));
+ } else {
+ res = TRUE;
+ }
+
+ curl_easy_getinfo(curl_ctx, CURLINFO_RESPONSE_CODE, &response_code);
+ if (response_code < 200 || response_code >= 300) {
+ g_warning("Can't export calendar, got code %ld\n", response_code);
+ res = FALSE;
+ }
+ curl_easy_cleanup(curl_ctx);
+ curl_slist_free_all(headers);
+ return res;
+}
+
+static gboolean folder_item_find_func(GNode *node, gpointer data)
+{
+ FolderItem *item = node->data;
+ gpointer *d = data;
+ const gchar *uri = d[0];
+
+ if (!uri || !((VCalFolderItem *)item)->uri
+ || strcmp(uri, ((VCalFolderItem *)item)->uri))
+ return FALSE;
+
+ d[1] = item;
+
+ return TRUE;
+}
+
+static FolderItem *get_folder_item_for_uri(const gchar *uri)
+{
+ Folder *root = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ gpointer d[2];
+
+ if (root == NULL)
+ return NULL;
+
+ d[0] = (gpointer)uri;
+ d[1] = NULL;
+ g_node_traverse(root->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+ folder_item_find_func, d);
+ return d[1];
+}
+
+static gchar *feed_get_title(const gchar *str)
+{
+ gchar *title = NULL;
+ if (strstr(str, "X-WR-CALNAME:")) {
+ title = g_strdup(strstr(str, "X-WR-CALNAME:")+strlen("X-WR-CALNAME:"));
+ if (strstr(title, "\n"))
+ *(strstr(title, "\n")) = '\0';
+ if (strstr(title, "\r"))
+ *(strstr(title, "\r")) = '\0';
+ } else if (strstr(str, "X-WR-CALDESC:")) {
+ title = g_strdup(strstr(str, "X-WR-CALDESC:")+strlen("X-WR-CALDESC:"));
+ if (strstr(title, "\n"))
+ *(strstr(title, "\n")) = '\0';
+ if (strstr(title, "\r"))
+ *(strstr(title, "\r")) = '\0';
+ }
+
+ return title;
+}
+
+static void update_subscription_finish(const gchar *uri, gchar *feed, gboolean verbose, gchar *error)
+{
+ Folder *root = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ FolderItem *item = NULL;
+ icalcomponent *cal = NULL;
+
+ if (root == NULL) {
+ g_warning("can't get root folder\n");
+ g_free(feed);
+ if (error)
+ g_free(error);
+ return;
+ }
+
+ if (feed == NULL) {
+ if (verbose && manual_update) {
+ gchar *tmp;
+ tmp = g_strdup(uri);
+ if (strlen(uri) > 61) {
+ tmp[55]='[';
+ tmp[56]='.';
+ tmp[57]='.';
+ tmp[58]='.';
+ tmp[59]=']';
+ tmp[60]='\0';
+ }
+ alertpanel_error(_("Could not retrieve the Webcal URL:\n%s:\n\n%s"),
+ tmp, error ? error:_("Unknown error"));
+ g_free(tmp);
+ } else {
+ log_error(LOG_PROTOCOL, _("Could not retrieve the Webcal URL:\n%s:\n\n%s\n"),
+ uri, error ? error:_("Unknown error"));
+ }
+ main_window_cursor_normal(mainwindow_get_mainwindow());
+ g_free(feed);
+ if (error)
+ g_free(error);
+ return;
+ }
+ if (strncmp(feed, "BEGIN:VCALENDAR", strlen("BEGIN:VCALENDAR"))) {
+ if (verbose && manual_update) {
+ alertpanel_error(_("This URL does not look like a WebCal URL:\n%s\n%s"),
+ uri, error ? error:_("Unknown error"));
+ } else {
+ log_error(LOG_PROTOCOL, _("This URL does not look like a WebCal URL:\n%s\n%s\n"),
+ uri, error ? error:_("Unknown error"));
+ }
+ g_free(feed);
+ main_window_cursor_normal(mainwindow_get_mainwindow());
+ if (error)
+ g_free(error);
+ return;
+ }
+
+ if (error)
+ g_free(error);
+ item = get_folder_item_for_uri(uri);
+ if (item == NULL) {
+ gchar *title = feed_get_title(feed);
+ if (title == NULL) {
+ if (strstr(uri, "://"))
+ title = g_strdup(strstr(uri,"://")+3);
+ else
+ title = g_strdup(uri);
+ subst_for_filename(title);
+ if (strlen(title) > 32) {
+ title[29]=title[30]=title[31]='.';
+ title[32]='\0';
+ }
+ }
+ item = folder_create_folder(root->node->data, title);
+ debug_print("item done %s\n", title);
+ ((VCalFolderItem *)item)->uri = g_strdup(uri);
+ ((VCalFolderItem *)item)->feed = feed;
+ g_free(title);
+ } else {
+ if (((VCalFolderItem *)item)->feed)
+ g_free(((VCalFolderItem *)item)->feed);
+
+ ((VCalFolderItem *)item)->feed = feed;
+ /* if title differs, update it */
+ }
+ cal = icalparser_parse_string(feed);
+
+ if (((VCalFolderItem *)item)->cal)
+ icalcomponent_free(((VCalFolderItem *)item)->cal);
+
+ ((VCalFolderItem *)item)->cal = cal;
+
+ main_window_cursor_normal(mainwindow_get_mainwindow());
+ ((VCalFolderItem *)item)->last_fetch = time(NULL);
+}
+
+static void update_subscription(const gchar *uri, gboolean verbose)
+{
+ FolderItem *item = get_folder_item_for_uri(uri);
+ gchar *label;
+
+ if (prefs_common_get_prefs()->work_offline) {
+ if (!verbose ||
+ !inc_offline_should_override(TRUE,
+ _("Claws Mail needs network access in order "
+ "to update the Webcal feed.")))
+ return;
+ }
+ if (item) {
+ if (time(NULL) - ((VCalFolderItem *)(item))->last_fetch < 60 &&
+ ((VCalFolderItem *)(item))->cal)
+ return;
+ }
+ main_window_cursor_wait(mainwindow_get_mainwindow());
+
+ label = g_strdup_printf(_("Fetching calendar for %s..."),
+ item && item->name ? item->name : _("new subscription"));
+ vcal_curl_read(uri, label, verbose, update_subscription_finish);
+ g_free(label);
+}
+
+static void check_subs_cb(GtkAction *action, gpointer data)
+{
+ Folder *root = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+
+ if (prefs_common_get_prefs()->work_offline &&
+ !inc_offline_should_override(TRUE,
+ _("Claws Mail needs network access in order "
+ "to update the subscription.")))
+ return;
+
+ folderview_check_new(root);
+}
+
+static void subscribe_cal_cb(GtkAction *action, gpointer data)
+{
+ gchar *uri = NULL;
+ gchar *tmp = NULL;
+
+ tmp = input_dialog(_("Subscribe to WebCal"), _("Enter the WebCal URL:"), NULL);
+ if (tmp == NULL)
+ return;
+
+ if (!strncmp(tmp, "http://", 7)) {
+ uri = tmp;
+ } else if (!strncmp(tmp, "file://", 7)) {
+ uri = tmp;
+ } else if (!strncmp(tmp, "https://", 8)) {
+ uri = tmp;
+ } else if (!strncmp(tmp, "webcal://", 9)) {
+ uri = g_strconcat("http://", tmp+9, NULL);
+ g_free(tmp);
+ } else {
+ alertpanel_error(_("Could not parse the URL."));
+ g_free(tmp);
+ return;
+ }
+ debug_print("uri %s\n", uri);
+
+ update_subscription(uri, TRUE);
+ folder_write_list();
+ g_free(uri);
+}
+
+static void unsubscribe_cal_cb(GtkAction *action, gpointer data)
+{
+ FolderView *folderview = (FolderView *)data;
+ GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
+ FolderItem *item;
+ gchar *message;
+ AlertValue avalue;
+ gchar *old_path;
+ gchar *old_id;
+
+ if (!folderview->selected) return;
+
+ item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
+ g_return_if_fail(item != NULL);
+ g_return_if_fail(item->path != NULL);
+ g_return_if_fail(item->folder != NULL);
+
+ message = g_strdup_printf
+ (_("Do you really want to unsubscribe?"));
+ avalue = alertpanel_full(_("Delete folder"), message,
+ GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL,
+ FALSE, NULL, ALERT_WARNING, G_ALERTDEFAULT);
+ g_free(message);
+ if (avalue != G_ALERTALTERNATE) return;
+
+ Xstrdup_a(old_path, item->path, return);
+ old_id = folder_item_get_identifier(item);
+
+ vcal_item_closed(item);
+
+ if (folderview->opened == folderview->selected ||
+ gtk_cmctree_is_ancestor(ctree,
+ folderview->selected,
+ folderview->opened)) {
+ summary_clear_all(folderview->summaryview);
+ folderview->opened = NULL;
+ }
+
+ if (item->folder->klass->remove_folder(item->folder, item) < 0) {
+ folder_item_scan(item);
+ alertpanel_error(_("Can't remove the folder '%s'."), item->name);
+ g_free(old_id);
+ return;
+ }
+
+ folder_write_list();
+
+ prefs_filtering_delete_path(old_id);
+ g_free(old_id);
+}
+
+gboolean vcal_subscribe_uri(Folder *folder, const gchar *uri)
+{
+ gchar *tmp = NULL;
+ if (folder->klass != vcal_folder_get_class())
+ return FALSE;
+
+ if (!strncmp(uri, "webcal://", 9)) {
+ tmp = g_strconcat("http://", uri+9, NULL);
+ } else {
+ return FALSE;
+ }
+ debug_print("uri %s\n", tmp);
+
+ update_subscription(tmp, FALSE);
+ folder_write_list();
+ return TRUE;
+}
+
+static void rename_cb(GtkAction *action, gpointer data)
+{
+ FolderView *folderview = (FolderView *)data;
+ FolderItem *item;
+ gchar *new_folder;
+ gchar *name;
+ gchar *message;
+
+ item = folderview_get_selected_item(folderview);
+ g_return_if_fail(item != NULL);
+ g_return_if_fail(item->path != NULL);
+ g_return_if_fail(item->folder != NULL);
+
+ name = trim_string(item->name, 32);
+ message = g_strdup_printf(_("Input new name for '%s':"), name);
+ new_folder = input_dialog(_("Rename folder"), message, name);
+ g_free(message);
+ g_free(name);
+ if (!new_folder) return;
+ AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});
+
+ if (strchr(new_folder, G_DIR_SEPARATOR) != NULL) {
+ alertpanel_error(_("'%c' can't be included in folder name."),
+ G_DIR_SEPARATOR);
+ return;
+ }
+
+ if (folder_find_child_item_by_name(folder_item_parent(item), new_folder)) {
+ name = trim_string(new_folder, 32);
+ alertpanel_error(_("The folder '%s' already exists."), name);
+ g_free(name);
+ return;
+ }
+
+ if (folder_item_rename(item, new_folder) < 0) {
+ alertpanel_error(_("The folder could not be renamed.\n"
+ "The new folder name is not allowed."));
+ return;
+ }
+
+ folder_item_prefs_save_config_recursive(item);
+ folder_write_list();
+}
+
+static void set_view_cb(GtkAction *gaction, GtkRadioAction *current, gpointer data)
+{
+ FolderView *folderview = (FolderView *)data;
+ gint action = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (current));
+ GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
+ FolderItem *item = NULL, *oitem = NULL;
+
+ if (!folderview->selected) return;
+ if (setting_sensitivity) return;
+
+ oitem = gtk_cmctree_node_get_row_data(ctree, folderview->opened);
+ item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
+
+ if (((VCalFolderItem *)(item))->use_cal_view == action)
+ return;
+ debug_print("set view %d\n", action);
+ if (oitem && item == oitem && oitem->folder->klass == vcal_folder_get_class())
+ oitem->folder->klass->item_closed(oitem);
+ ((VCalFolderItem *)(item))->use_cal_view = action;
+ if (((VCalFolderItem *)(item))->use_cal_view) {
+ if (oitem && item == oitem && oitem->folder->klass == vcal_folder_get_class())
+ oitem->folder->klass->item_opened(oitem);
+ }
+}
+
+gchar *vcal_get_event_as_ical_str(VCalEvent *event)
+{
+ gchar *ical;
+ icalcomponent *calendar = icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalproperty_new_version("2.0"),
+ icalproperty_new_prodid(
+ "-//Claws Mail//NONSGML Claws Mail Calendar//EN"),
+ icalproperty_new_calscale("GREGORIAN"),
+ 0);
+ vcal_manager_event_dump(event, FALSE, FALSE, calendar, FALSE);
+ ical = g_strdup(icalcomponent_as_ical_string(calendar));
+ icalcomponent_free(calendar);
+
+ return ical;
+}
+
+static gchar *get_name_from_property(icalproperty *p)
+{
+ gchar *tmp = NULL;
+
+ if (p && icalproperty_get_parameter_as_string(p, "CN") != NULL)
+ tmp = g_strdup(icalproperty_get_parameter_as_string(p, "CN"));
+
+ return tmp;
+}
+
+static gchar *get_email_from_property(icalproperty *p)
+{
+ gchar *tmp = NULL;
+ gchar *email = NULL;
+
+ if (p)
+ tmp = g_strdup(icalproperty_get_organizer(p));
+
+ if (!tmp)
+ return NULL;
+
+ if (!strncasecmp(tmp, "MAILTO:", strlen("MAILTO:")))
+ email = g_strdup(tmp+strlen("MAILTO:"));
+ else
+ email = g_strdup(tmp);
+ g_free(tmp);
+
+ return email;
+}
+
+#define GET_PROP(comp,prop,kind) { \
+ prop = NULL; \
+ if (!(prop = icalcomponent_get_first_property(comp, kind))) { \
+ prop = inner \
+ ? icalcomponent_get_first_property(inner, kind) \
+ : NULL; \
+ } \
+}
+
+#define GET_PROP_LIST(comp,list,kind) { \
+ list = NULL; \
+ if (!(prop = icalcomponent_get_first_property(comp, kind))) { \
+ prop = inner \
+ ? icalcomponent_get_first_property(inner, kind) \
+ : NULL; \
+ if (prop) do { \
+ list = g_slist_prepend(list, prop); \
+ } while ((prop = icalcomponent_get_next_property(inner, kind)));\
+ }else do { \
+ list = g_slist_prepend(list, prop); \
+ } while ((prop = icalcomponent_get_next_property(comp, kind))); \
+}
+
+#define TO_UTF8(string) { \
+ if (string && !g_utf8_validate(string, -1, NULL)) { \
+ gchar *tmp = conv_codeset_strdup(string, \
+ charset ? charset:conv_get_locale_charset_str(),\
+ CS_UTF_8); \
+ g_free(string); \
+ string = tmp; \
+ } \
+}
+
+VCalEvent *vcal_get_event_from_ical(const gchar *ical, const gchar *charset)
+{
+ VCalEvent *event = NULL;
+ gchar *int_ical = g_strdup(ical);
+ icalcomponent *comp = icalcomponent_new_from_string(int_ical);
+ icalcomponent *inner = NULL;
+ icalproperty *prop = NULL;
+ GSList *list = NULL, *cur = NULL;
+ gchar *uid = NULL;
+ gchar *location = NULL;
+ gchar *summary = NULL;
+ gchar *dtstart = NULL;
+ gchar *dtend = NULL;
+ gchar *org_email = NULL, *org_name = NULL;
+ gchar *description = NULL;
+ gchar *url = NULL;
+ gchar *tzid = NULL;
+ gchar *recur = NULL;
+ int sequence = 0;
+ enum icalproperty_method method = ICAL_METHOD_REQUEST;
+ enum icalproperty_kind type = ICAL_VEVENT_COMPONENT;
+ GSList *attendees = NULL;
+
+ if (comp == NULL) {
+ g_free(int_ical);
+ return NULL;
+ }
+
+ if ((inner = icalcomponent_get_inner(comp)) != NULL)
+ type = icalcomponent_isa(inner);
+
+ GET_PROP(comp, prop, ICAL_UID_PROPERTY);
+ if (prop) {
+ uid = g_strdup(icalproperty_get_uid(prop));
+ TO_UTF8(uid);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_LOCATION_PROPERTY);
+ if (prop) {
+ location = g_strdup(icalproperty_get_location(prop));
+ TO_UTF8(location);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_SUMMARY_PROPERTY);
+ if (prop) {
+ summary = g_strdup(icalproperty_get_summary(prop));
+ TO_UTF8(summary);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_DTSTART_PROPERTY);
+ if (prop) {
+ dtstart = g_strdup(icaltime_as_ical_string(icalproperty_get_dtstart(prop)));
+ TO_UTF8(dtstart);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_DTEND_PROPERTY);
+ if (prop) {
+ dtend = g_strdup(icaltime_as_ical_string(icalproperty_get_dtend(prop)));
+ TO_UTF8(dtend);
+ icalproperty_free(prop);
+ } else {
+ GET_PROP(comp, prop, ICAL_DURATION_PROPERTY);
+ if (prop) {
+ struct icaldurationtype duration = icalproperty_get_duration(prop);
+ struct icaltimetype itt;
+ icalproperty_free(prop);
+ GET_PROP(comp, prop, ICAL_DTSTART_PROPERTY);
+ itt = icalproperty_get_dtstart(prop);
+ if (prop) {
+ icalproperty_free(prop);
+ dtend = g_strdup(icaltime_as_ical_string(icaltime_add(itt,duration)));
+ TO_UTF8(dtend);
+ }
+ }
+ }
+ GET_PROP(comp, prop, ICAL_SEQUENCE_PROPERTY);
+ if (prop) {
+ sequence = icalproperty_get_sequence(prop);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_METHOD_PROPERTY);
+ if (prop) {
+ method = icalproperty_get_method(prop);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_ORGANIZER_PROPERTY);
+ if (prop) {
+ org_email = get_email_from_property(prop);
+ TO_UTF8(org_email);
+ org_name = get_name_from_property(prop);
+ TO_UTF8(org_name);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_DESCRIPTION_PROPERTY);
+ if (prop) {
+ description = g_strdup(icalproperty_get_description(prop));
+ TO_UTF8(description);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_URL_PROPERTY);
+ if (prop) {
+ url = g_strdup(icalproperty_get_url(prop));
+ TO_UTF8(url);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_TZID_PROPERTY);
+ if (prop) {
+ tzid = g_strdup(icalproperty_get_tzid(prop));
+ TO_UTF8(tzid);
+ icalproperty_free(prop);
+ }
+ GET_PROP(comp, prop, ICAL_RRULE_PROPERTY);
+ if (prop) {
+ struct icalrecurrencetype rrule = icalproperty_get_rrule(prop);
+ recur = g_strdup(icalrecurrencetype_as_string(&rrule));
+ TO_UTF8(recur);
+ icalproperty_free(prop);
+ }
+ GET_PROP_LIST(comp, list, ICAL_ATTENDEE_PROPERTY);
+ for (cur = list; cur; cur = cur->next) {
+ enum icalparameter_partstat partstat = 0;
+ enum icalparameter_cutype cutype = 0;
+ icalparameter *param = NULL;
+ gchar *email = NULL;
+ gchar *name = NULL;
+ Answer *answer = NULL;
+
+ prop = (icalproperty *)(cur->data);
+
+ email = get_email_from_property(prop);
+ TO_UTF8(email);
+ name = get_name_from_property(prop);
+ TO_UTF8(name);
+
+ param = icalproperty_get_first_parameter(prop, ICAL_PARTSTAT_PARAMETER);
+ if (param)
+ partstat = icalparameter_get_partstat(param);
+
+ param = icalproperty_get_first_parameter(prop, ICAL_CUTYPE_PARAMETER);
+ if (param)
+ cutype= icalparameter_get_cutype(param);
+
+ if (!partstat)
+ partstat = ICAL_PARTSTAT_NEEDSACTION;
+ if (!cutype)
+ cutype = ICAL_CUTYPE_INDIVIDUAL;
+ answer = answer_new(email, name, partstat, cutype);
+ attendees = g_slist_prepend(attendees, answer);
+ g_free(email);
+ g_free(name);
+ icalproperty_free(prop);
+ }
+ g_slist_free(list);
+
+ event = vcal_manager_new_event (uid, org_email, org_name,
+ location, summary, description,
+ dtstart, dtend, recur,
+ tzid, url,
+ method, sequence, type);
+ event->answers = attendees;
+ g_free(uid);
+ g_free(location);
+ g_free(summary);
+ g_free(dtstart);
+ g_free(dtend);
+ g_free(org_email);
+ g_free(org_name);
+ g_free(description);
+ g_free(url);
+ g_free(tzid);
+ g_free(recur);
+ g_free(int_ical);
+ icalcomponent_free(comp);
+ return event;
+}
+
+gboolean vcal_event_exists(const gchar *id)
+{
+ MsgInfo *info = NULL;
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ if (!folder)
+ return FALSE;
+
+ info = folder_item_get_msginfo_by_msgid(folder->inbox, id);
+ if (info != NULL) {
+ procmsg_msginfo_free(info);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void vcal_foreach_event(gboolean (*cb_func)(const gchar *vevent))
+{
+ GSList *list = vcal_folder_get_waiting_events();
+ GSList *cur = NULL;
+ if (!cb_func)
+ return;
+ debug_print("calling cb_func...\n");
+ for (cur = list; cur; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+ gchar *tmp = vcal_get_event_as_ical_str(event);
+ if (tmp) {
+ debug_print(" ...for event %s\n", event->uid);
+ cb_func(tmp);
+ }
+ vcal_manager_free_event(event);
+ g_free(tmp);
+ }
+}
+
+/* please call vcalendar_refresh_folder_contents() after one or more
+ * calls to this function */
+gboolean vcal_delete_event(const gchar *id)
+{
+ MsgInfo *info = NULL;
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ if (!folder)
+ return FALSE;
+
+ info = folder_item_get_msginfo_by_msgid(folder->inbox, id);
+ if (info != NULL) {
+ debug_print("removing event %s\n", id);
+ vcal_remove_event(folder, info);
+ procmsg_msginfo_free(info);
+ folder_item_scan(folder->inbox);
+ return TRUE;
+ }
+ debug_print("not removing unexisting event %s\n", id);
+ return FALSE;
+}
+
+/* please call vcalendar_refresh_folder_contents() after one or more
+ * calls to this function */
+gchar* vcal_add_event(const gchar *vevent)
+{
+ VCalEvent *event = vcal_get_event_from_ical(vevent, NULL);
+ gchar *retVal = NULL;
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ if (!folder)
+ return NULL;
+
+ if (event) {
+ if (vcal_event_exists(event->uid)) {
+ debug_print("event %s already exists\n", event->uid);
+ vcal_manager_free_event(event);
+ return retVal;
+ }
+ debug_print("adding event %s\n", event->uid);
+ if (!account_find_from_address(event->organizer, FALSE) &&
+ !vcal_manager_get_account_from_event(event)) {
+ PrefsAccount *account = account_get_default();
+ vcal_manager_update_answer(event, account->address,
+ account->name,
+ ICAL_PARTSTAT_ACCEPTED,
+ ICAL_CUTYPE_INDIVIDUAL);
+ debug_print("can't find our accounts in event, adding default\n");
+ }
+ vcal_manager_save_event(event, TRUE);
+ folder_item_scan(folder->inbox);
+ retVal = vcal_get_event_as_ical_str(event);
+ vcal_manager_free_event(event);
+ }
+
+ return retVal;
+}
+
+/* please call vcalendar_refresh_folder_contents() after one or more
+ * calls to this function */
+gchar* vcal_update_event(const gchar *vevent)
+{
+ VCalEvent *event = vcal_get_event_from_ical(vevent, NULL);
+ gboolean r = FALSE;
+ if (event) {
+ r = vcal_delete_event(event->uid);
+ vcal_manager_free_event(event);
+ if (r)
+ return vcal_add_event(vevent);
+ }
+ return NULL;
+}
diff --git a/src/plugins/vcalendar/vcal_folder.h b/src/plugins/vcalendar/vcal_folder.h
@@ -0,0 +1,58 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VCAL_FOLDER_H__
+#define __VCAL_FOLDER_H__
+
+#include <glib.h>
+#include "folder.h"
+
+extern gboolean manual_update;
+typedef struct _day_win day_win;
+typedef struct _month_win month_win;
+FolderClass *vcal_folder_get_class();
+void vcal_folder_gtk_init(void);
+void vcal_folder_gtk_done(void);
+GSList *vcal_folder_get_waiting_events(void);
+GSList *vcal_folder_get_webcal_events(void);
+GSList * vcal_folder_get_webcal_events_for_folder(FolderItem *item);
+void vcal_folder_export(Folder *folder);
+
+gboolean vcal_curl_put(gchar *url, FILE *fp, gint filesize, const gchar *user, const gchar *pass);
+gchar *vcal_curl_read(const char *url, const gchar *label, gboolean verbose,
+ void (*callback)(const gchar *url, gchar *data, gboolean verbose, gchar
+ *error));
+gchar* get_item_event_list_for_date(FolderItem *item, EventTime date);
+void vcal_folder_block_export(gboolean block);
+void vcal_folder_refresh_cal(FolderItem *item);
+GSList *vcal_get_events_list(FolderItem *item);
+
+day_win *create_day_win(FolderItem *item, struct tm tmdate);
+void refresh_day_win(day_win *dw);
+void dw_close_window(day_win *dw);
+
+month_win *create_month_win(FolderItem *item, struct tm tmdate);
+void refresh_month_win(month_win *dw);
+void mw_close_window(month_win *dw);
+
+VCalEvent *vcal_get_event_from_ical(const gchar *ical, const gchar *charset);
+
+void vcal_folder_free_data(void);
+#endif
diff --git a/src/plugins/vcalendar/vcal_interface.h b/src/plugins/vcalendar/vcal_interface.h
@@ -0,0 +1,26 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+gboolean vcal_event_exists(const gchar *id);
+void vcal_foreach_event(gboolean (*cb_func)(const gchar *vevent));
+gboolean vcal_delete_event(const gchar *id);
+gchar* vcal_add_event(const gchar *vevent);
+gchar* vcal_update_event(const gchar *vevent);
+void vcalendar_refresh_folder_contents(FolderItem *item);
diff --git a/src/plugins/vcalendar/vcal_manager.c b/src/plugins/vcalendar/vcal_manager.c
@@ -0,0 +1,1543 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+#include <ical.h>
+#include "vcalendar.h"
+#include "vcal_folder.h"
+#include "vcal_manager.h"
+#include "vcal_meeting_gtk.h"
+#include "vcal_prefs.h"
+#include "xml.h"
+#include "xmlprops.h"
+#include "prefs.h"
+#include "prefs_common.h"
+#include "prefs_account.h"
+#include "alertpanel.h"
+#include "account.h"
+#include "codeconv.h"
+#include <time.h>
+#include "folder.h"
+#include "quoted-printable.h"
+#include "utils.h"
+
+#ifdef G_OS_WIN32
+#define getuid() 0
+#endif
+
+Answer *answer_new(const gchar *attendee,
+ const gchar *name,
+ enum icalparameter_partstat ans,
+ enum icalparameter_cutype cutype)
+{
+ Answer *answer = g_new0(Answer, 1);
+ answer->attendee = g_strdup(attendee);
+ answer->name = g_strdup(name);
+ if (!answer->name)
+ answer->name = g_strdup("");
+ if (!answer->attendee)
+ answer->attendee = g_strdup("");
+ answer->answer = ans;
+ answer->cutype = cutype;
+ return answer;
+}
+
+static void answer_free(Answer *answer)
+{
+ g_free(answer->attendee);
+ g_free(answer->name);
+ g_free(answer);
+}
+
+static GSList *answer_find(VCalEvent *event, Answer *answer)
+{
+ GSList *cur = event->answers;
+ while (cur && cur->data) {
+ Answer *b = (Answer *)cur->data;
+ if (!strcasecmp(b->attendee, answer->attendee))
+ return cur;
+ cur = cur->next;
+ }
+ return NULL;
+}
+
+void vcal_manager_copy_attendees(VCalEvent *src, VCalEvent *dest)
+{
+ GSList *cur = src->answers;
+ while (cur && cur->data) {
+ Answer *a = (Answer *)cur->data;
+ Answer *b = answer_new(a->attendee, a->name, a->answer, a->cutype);
+ dest->answers = g_slist_prepend(dest->answers, b);
+ cur = cur->next;
+ }
+ dest->answers = g_slist_reverse(dest->answers);
+}
+
+gchar *vcal_manager_answer_get_text(enum icalparameter_partstat ans)
+{
+ static gchar *replies[5]={
+ N_("accepted"),
+ N_("tentatively accepted"),
+ N_("declined"),
+ N_("did not answer"),
+ N_("unknown")
+ };
+
+ switch (ans) {
+ case ICAL_PARTSTAT_ACCEPTED:
+ return _(replies[0]);
+ break;
+ case ICAL_PARTSTAT_DECLINED:
+ return _(replies[2]);
+ break;
+ case ICAL_PARTSTAT_TENTATIVE:
+ return _(replies[1]);
+ break;
+ case ICAL_PARTSTAT_NEEDSACTION:
+ return _(replies[3]);
+ case ICAL_PARTSTAT_DELEGATED:
+ case ICAL_PARTSTAT_COMPLETED:
+ case ICAL_PARTSTAT_X:
+ case ICAL_PARTSTAT_INPROCESS:
+ case ICAL_PARTSTAT_NONE:
+ return _(replies[4]);
+ break;
+ }
+ return NULL;
+}
+
+gchar *vcal_manager_cutype_get_text(enum icalparameter_cutype type)
+{
+ static gchar *replies[5]={
+ N_("individual"),
+ N_("group"),
+ N_("resource"),
+ N_("room"),
+ N_("unknown")
+ };
+
+ switch (type) {
+ case ICAL_CUTYPE_INDIVIDUAL:
+ return _(replies[0]);
+ break;
+ case ICAL_CUTYPE_GROUP:
+ return _(replies[1]);
+ break;
+ case ICAL_CUTYPE_RESOURCE:
+ return _(replies[2]);
+ break;
+ case ICAL_CUTYPE_ROOM:
+ return _(replies[3]);
+ default:
+ return _(replies[4]);
+ break;
+ }
+ return NULL;
+}
+
+static GSList *answer_remove(VCalEvent *event, Answer *answer)
+{
+ GSList *cur = answer_find(event, answer);
+ if (cur) {
+ Answer *b = (Answer *)cur->data;
+ event->answers = g_slist_remove(event->answers, b);
+ answer_free(b);
+ }
+ return event->answers;
+}
+
+static GSList *answer_add(VCalEvent *event, Answer *answer)
+{
+ event->answers = g_slist_append(event->answers, answer);
+ return event->answers;
+}
+
+GSList *vcal_manager_get_answers_emails(VCalEvent *event)
+{
+ GSList *new = NULL;
+ GSList *cur = event->answers;
+ while (cur && cur->data) {
+ Answer *b = (Answer *)cur->data;
+ new = g_slist_prepend(new, b->attendee);
+ cur = cur->next;
+ }
+ new = g_slist_reverse(new);
+ return new;
+}
+
+enum icalparameter_partstat vcal_manager_get_reply_for_attendee(VCalEvent *event, const gchar *att)
+{
+ Answer *a = answer_new(att, NULL, 0, 0);
+ GSList *ans = answer_find(event, a);
+ enum icalparameter_partstat res = 0;
+ if (ans) {
+ Answer *b = (Answer *)ans->data;
+ res = b->answer;
+ }
+ answer_free(a);
+ return res;
+}
+
+gchar *vcal_manager_get_cutype_text_for_attendee(VCalEvent *event, const gchar *att)
+{
+ enum icalparameter_cutype status = vcal_manager_get_cutype_for_attendee(event, att);
+ gchar *res = NULL;
+ if (status != 0)
+ res = g_strdup(vcal_manager_cutype_get_text(status));
+
+ return res;
+}
+
+enum icalparameter_partstat vcal_manager_get_cutype_for_attendee(VCalEvent *event, const gchar *att)
+{
+ Answer *a = answer_new(att, NULL, 0, 0);
+ GSList *ans = answer_find(event, a);
+ enum icalparameter_cutype res = 0;
+ if (ans) {
+ Answer *b = (Answer *)ans->data;
+ res = b->cutype;
+ }
+ answer_free(a);
+ return res;
+}
+
+gchar *vcal_manager_get_reply_text_for_attendee(VCalEvent *event, const gchar *att)
+{
+ enum icalparameter_partstat status = vcal_manager_get_reply_for_attendee(event, att);
+ gchar *res = NULL;
+ if (status != 0)
+ res = g_strdup(vcal_manager_answer_get_text(status));
+
+ return res;
+}
+
+gchar *vcal_manager_get_attendee_name(VCalEvent *event, const gchar *att)
+{
+ Answer *a = answer_new(att, NULL, 0, 0);
+ GSList *ans = answer_find(event, a);
+ gchar *res = NULL;
+ if (ans) {
+ Answer *b = (Answer *)ans->data;
+ if (b->name)
+ res = g_strdup(b->name);
+ }
+ answer_free(a);
+ return res;
+}
+
+void vcal_manager_event_print(VCalEvent *event)
+{
+ GSList *list = event->answers;
+ printf( "event->uid\t\t%s\n"
+ "event->organizer\t\t%s\n"
+ "event->start\t\t%s\n"
+ "event->end\t\t%s\n"
+ "event->location\t\t%s\n"
+ "event->summary\t\t%s\n"
+ "event->description\t%s\n"
+ "event->url\t%s\n"
+ "event->dtstart\t\t%s\n"
+ "event->dtend\t\t%s\n"
+ "event->recur\t\t%s\n"
+ "event->tzid\t\t%s\n"
+ "event->method\t\t%d\n"
+ "event->sequence\t\t%d\n",
+ event->uid,
+ event->organizer,
+ event->start,
+ event->end,
+ event->location,
+ event->summary,
+ event->description,
+ event->url,
+ event->dtstart,
+ event->dtend,
+ event->recur,
+ event->tzid,
+ event->method,
+ event->sequence);
+ while (list && list->data) {
+ Answer *a = (Answer *)list->data;
+ printf(" ans: %s %s, %s\n", a->name, a->attendee, vcal_manager_answer_get_text(a->answer));
+ list = list->next;
+ }
+
+}
+
+static gchar *write_headers(PrefsAccount *account,
+ VCalEvent *event,
+ gboolean short_headers,
+ gboolean is_reply,
+ gboolean is_pseudo_event);
+
+gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_pseudo_event,
+ icalcomponent *use_calendar, gboolean modif)
+{
+ gchar *organizer = g_strdup_printf("MAILTO:%s", event->organizer);
+ PrefsAccount *account = vcal_manager_get_account_from_event(event);
+ gchar *attendee = NULL;
+ gchar *body, *headers;
+ gchar *tmpfile = NULL;
+ icalcomponent *calendar, *ievent, *timezone, *tzc;
+ icalproperty *attprop;
+ icalproperty *orgprop;
+ enum icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
+ gchar *sanitized_uid = g_strdup(event->uid);
+
+ subst_for_filename(sanitized_uid);
+
+ tmpfile = g_strdup_printf("%s%cevt-%d-%s", get_tmp_dir(),
+ G_DIR_SEPARATOR, getuid(), sanitized_uid);
+ g_free(sanitized_uid);
+
+ if (!account) {
+ g_free(organizer);
+ g_free(tmpfile);
+ debug_print("no account found\n");
+ return NULL;
+ }
+
+ attendee = g_strdup_printf("MAILTO:%s", account->address);
+
+ if (vcal_manager_get_reply_for_attendee(event, account->address) != 0)
+ status = vcal_manager_get_reply_for_attendee(event, account->address);
+
+ tzset();
+
+ if (use_calendar != NULL) {
+ calendar = use_calendar;
+ g_free(tmpfile);
+ tmpfile = NULL;
+ } else
+ calendar =
+ icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalproperty_new_version("2.0"),
+ icalproperty_new_prodid(
+ "-//Claws Mail//NONSGML Claws Mail Calendar//EN"),
+ icalproperty_new_calscale("GREGORIAN"),
+ icalproperty_new_method(is_reply ? ICAL_METHOD_REPLY:event->method),
+ 0
+ );
+
+ if (!calendar) {
+ g_warning ("can't generate calendar");
+ g_free(organizer);
+ g_free(tmpfile);
+ g_free(attendee);
+ return NULL;
+ }
+
+ orgprop = icalproperty_new_organizer(organizer);
+
+ timezone = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
+
+ icalcomponent_add_property(timezone,
+ icalproperty_new_tzid("UTC")); /* free */
+
+ tzc = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
+ icalcomponent_add_property(tzc,
+ icalproperty_new_dtstart(
+ icaltime_from_string("19700101T000000")));
+ icalcomponent_add_property(tzc,
+ icalproperty_new_tzoffsetfrom(0.0));
+ icalcomponent_add_property(tzc,
+ icalproperty_new_tzoffsetto(0.0));
+ icalcomponent_add_property(tzc,
+ icalproperty_new_tzname("Greenwich meridian time"));
+
+ icalcomponent_add_component(timezone, tzc);
+
+ ievent =
+ icalcomponent_vanew(
+ ICAL_VEVENT_COMPONENT, 0);
+
+ if (!ievent) {
+ g_warning ("can't generate event");
+ g_free(organizer);
+ g_free(tmpfile);
+ g_free(attendee);
+ return NULL;
+ }
+
+ icalcomponent_add_property(ievent,
+ icalproperty_new_uid(event->uid));
+ icalcomponent_add_property(ievent,
+ icalproperty_vanew_dtstamp(icaltime_from_timet(time(NULL), TRUE), 0));
+ icalcomponent_add_property(ievent,
+ icalproperty_vanew_dtstart((icaltime_from_string(event->dtstart)), 0));
+ icalcomponent_add_property(ievent,
+ icalproperty_vanew_dtend((icaltime_from_string(event->dtend)), 0));
+ if (event->recur && *(event->recur)) {
+ icalcomponent_add_property(ievent,
+ icalproperty_vanew_rrule((icalrecurrencetype_from_string(event->recur)), 0));
+ }
+ icalcomponent_add_property(ievent,
+ icalproperty_new_description(event->description));
+ icalcomponent_add_property(ievent,
+ icalproperty_new_summary(event->summary));
+ icalcomponent_add_property(ievent,
+ icalproperty_new_sequence(modif && !is_reply ? event->sequence + 1 : event->sequence));
+ icalcomponent_add_property(ievent,
+ icalproperty_new_class("PUBLIC"));
+ icalcomponent_add_property(ievent,
+ icalproperty_new_transp("OPAQUE"));
+ if (event->location && *event->location)
+ icalcomponent_add_property(ievent,
+ icalproperty_new_location(event->location));
+ else
+ icalcomponent_add_property(ievent,
+ icalproperty_new_location(""));
+ icalcomponent_add_property(ievent,
+ icalproperty_new_status(ICAL_STATUS_CONFIRMED));
+ icalcomponent_add_property(ievent,
+ icalproperty_vanew_created(icaltime_from_timet(time(NULL), TRUE), 0));
+ icalcomponent_add_property(ievent,
+ icalproperty_vanew_lastmodified(icaltime_from_timet(time(NULL), TRUE), 0));
+ icalcomponent_add_property(ievent,
+ orgprop);
+
+ if (!icalcomponent_get_first_component(calendar, ICAL_VTIMEZONE_COMPONENT))
+ icalcomponent_add_component(calendar, timezone);
+ else
+ icalcomponent_free(timezone);
+
+ icalcomponent_add_component(calendar, ievent);
+
+ if (event->url && *(event->url)) {
+ attprop = icalproperty_new_url(event->url);
+ icalcomponent_add_property(ievent, attprop);
+ }
+
+ if (is_reply) {
+ /* dump only this attendee */
+ attprop =
+ icalproperty_vanew_attendee(
+ attendee,
+ icalparameter_new_role(
+ ICAL_ROLE_REQPARTICIPANT),
+ icalparameter_new_rsvp(ICAL_RSVP_TRUE),
+ icalparameter_new_partstat(status),
+ 0
+ );
+ icalcomponent_add_property(ievent, attprop);
+ } else {
+ /* dump all attendees */
+ GSList *cur = event->answers;
+ while (cur && cur->data) {
+ Answer *a = (Answer *)cur->data;
+
+ if (a->cutype == 0)
+ a->cutype = ICAL_CUTYPE_INDIVIDUAL;
+ if (a->answer == 0)
+ a->answer = ICAL_PARTSTAT_NEEDSACTION;
+
+ attprop =
+ icalproperty_vanew_attendee(
+ a->attendee,
+ icalparameter_new_role(
+ ICAL_ROLE_REQPARTICIPANT),
+ icalparameter_new_rsvp(ICAL_RSVP_TRUE),
+ icalparameter_new_cutype(a->cutype),
+ icalparameter_new_partstat(a->answer),
+ 0
+ );
+
+ icalcomponent_add_property(ievent, attprop);
+ cur = cur->next;
+ }
+ }
+
+ if (use_calendar) {
+ g_free(organizer);
+ g_free(tmpfile);
+ g_free(attendee);
+ return NULL;
+ }
+
+ headers = write_headers(account, event, is_pseudo_event, is_reply, is_pseudo_event);
+
+ if (!headers) {
+ g_warning("can't get headers");
+ g_free(organizer);
+ g_free(tmpfile);
+ g_free(attendee);
+ return NULL;
+ }
+
+ body = g_strdup_printf("%s"
+ "\n"
+ "%s", headers, icalcomponent_as_ical_string(calendar));
+
+ if (str_write_to_file(body, tmpfile) < 0) {
+ g_free(tmpfile);
+ tmpfile = NULL;
+ }
+
+ chmod(tmpfile, S_IRUSR|S_IWUSR);
+
+ g_free(body);
+ g_free(headers);
+ icalcomponent_free(calendar);
+ g_free(attendee);
+ g_free(organizer);
+
+ tzset();
+
+ return tmpfile;
+}
+
+static void get_rfc822_date_from_time_t(gchar *buf, gint len, time_t t)
+{
+ struct tm *lt;
+ gchar day[4], mon[4];
+ gint dd, hh, mm, ss, yyyy;
+ gchar buft1[512];
+ struct tm buft2;
+
+#ifndef G_OS_WIN32
+ lt = localtime_r(&t, &buft2);
+#else
+ if (t < 0)
+ t = 1;
+ lt = localtime(&t);
+#endif
+
+ sscanf(asctime_r(lt, buft1), "%3s %3s %d %d:%d:%d %d\n",
+ day, mon, &dd, &hh, &mm, &ss, &yyyy);
+ g_snprintf(buf, len, "%s, %d %s %d %02d:%02d:%02d %s",
+ day, dd, mon, yyyy, hh, mm, ss, tzoffset(&t));
+}
+
+static gchar *write_headers_date(const gchar *uid)
+{
+ gchar subject[512];
+ gchar *t_subject;
+ gchar date[128];
+ time_t t;
+ struct tm lt;
+ struct tm buft;
+
+ memset(subject, 0, sizeof(subject));
+ memset(date, 0, sizeof(date));
+
+ if (!strcmp(uid, EVENT_PAST_ID)) {
+ t = 1;
+ t_subject = _("Past");
+ } else if (!strcmp(uid, EVENT_TODAY_ID)) {
+ t = time(NULL);
+ t_subject = _("Today");
+ } else if (!strcmp(uid, EVENT_TOMORROW_ID)) {
+ t = time(NULL) + 86400;
+ t_subject = _("Tomorrow");
+ } else if (!strcmp(uid, EVENT_THISWEEK_ID)) {
+ t = time(NULL) + (86400*2);
+ t_subject = _("This week");
+ } else if (!strcmp(uid, EVENT_LATER_ID)) {
+ t = time(NULL) + (86400*7);
+ t_subject = _("Later");
+ } else {
+ g_warning("unknown spec date\n");
+ return NULL;
+ }
+
+#ifndef G_OS_WIN32
+ lt = *localtime_r(&t, &buft);
+#else
+ if (t < 0)
+ t = 1;
+ lt = *localtime(&t);
+#endif
+ lt.tm_hour = lt.tm_min = lt.tm_sec = 0;
+ t = mktime(<);
+ get_rfc822_date_from_time_t(date, sizeof(date), t);
+ conv_encode_header(subject, 511, t_subject, strlen("Subject: "), FALSE);
+
+ return g_strdup_printf("From: -\n"
+ "To: -\n"
+ "Subject: %s\n"
+ "Date: %s\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=\"UTF-8\";\n"
+ "Content-Transfer-Encoding: quoted-printable\n"
+ "Message-ID: <%s>\n",
+ subject,
+ date,
+ uid);
+}
+
+gchar *vcal_manager_dateevent_dump(const gchar *uid, FolderItem *item)
+{
+ gchar *sanitized_uid = NULL;
+ gchar *headers = NULL;
+ gchar *lines, *body, *tmpfile;
+ EventTime date;
+ sanitized_uid = g_strdup(uid);
+ subst_for_filename(sanitized_uid);
+
+ tmpfile = g_strdup_printf("%s%cevt-%d-%s", get_tmp_dir(),
+ G_DIR_SEPARATOR, getuid(), sanitized_uid);
+ g_free(sanitized_uid);
+
+ headers = write_headers_date(uid);
+
+ if (!headers) {
+ g_warning("can't get headers");
+ g_free(tmpfile);
+ return NULL;
+ }
+
+ if (!strcmp(uid, EVENT_PAST_ID))
+ date = EVENT_PAST;
+ else if (!strcmp(uid, EVENT_TODAY_ID))
+ date = EVENT_TODAY;
+ else if (!strcmp(uid, EVENT_TOMORROW_ID))
+ date = EVENT_TOMORROW;
+ else if (!strcmp(uid, EVENT_THISWEEK_ID))
+ date = EVENT_THISWEEK;
+ else if (!strcmp(uid, EVENT_LATER_ID))
+ date = EVENT_LATER;
+ else
+ date = EVENT_PAST;
+
+ lines = get_item_event_list_for_date(item, date);
+ body = g_strdup_printf("%s"
+ "\n"
+ "%s", headers, lines);
+ g_free(lines);
+ if (str_write_to_file(body, tmpfile) < 0) {
+ g_free(tmpfile);
+ tmpfile = NULL;
+ }
+ chmod(tmpfile, S_IRUSR|S_IWUSR);
+
+ g_free(body);
+ g_free(headers);
+
+ return tmpfile;
+}
+
+static gchar *write_headers_ical(PrefsAccount *account,
+ icalcomponent *ievent,
+ gchar *orga);
+
+gchar *vcal_manager_icalevent_dump(icalcomponent *event, gchar *orga, icalcomponent *use_calendar)
+{
+ PrefsAccount *account = account_get_cur_account();
+ gchar *body, *headers, *qpbody;
+ gchar **lines = NULL;
+ gchar *tmpfile = NULL;
+ icalcomponent *calendar;
+ icalproperty *prop;
+ icalcomponent *ievent = NULL;
+ int i = 0;
+
+ ievent = icalcomponent_new_clone(event);
+
+ prop = icalcomponent_get_first_property(ievent, ICAL_UID_PROPERTY);
+ if (prop) {
+ gchar *sanitized_uid = g_strdup(icalproperty_get_uid(prop));
+
+ subst_for_filename(sanitized_uid);
+
+ tmpfile = g_strdup_printf("%s%cevt-%d-%s", get_tmp_dir(),
+ G_DIR_SEPARATOR, getuid(), sanitized_uid);
+ g_free(sanitized_uid);
+ icalproperty_free(prop);
+ } else {
+ tmpfile = g_strdup_printf("%s%cevt-%d-%p", get_tmp_dir(),
+ G_DIR_SEPARATOR, getuid(), ievent);
+ }
+
+ if (!account) {
+ g_free(tmpfile);
+ icalcomponent_free(ievent);
+ return NULL;
+ }
+
+ tzset();
+
+ if (use_calendar != NULL) {
+ calendar = use_calendar;
+ g_free(tmpfile);
+ tmpfile = NULL;
+ } else
+ calendar =
+ icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalproperty_new_version("2.0"),
+ icalproperty_new_prodid(
+ "-//Claws Mail//NONSGML Claws Mail Calendar//EN"),
+ icalproperty_new_calscale("GREGORIAN"),
+ icalproperty_new_method(ICAL_METHOD_PUBLISH),
+ 0
+ );
+
+ if (!calendar) {
+ g_warning ("can't generate calendar");
+ g_free(tmpfile);
+ icalcomponent_free(ievent);
+ return NULL;
+ }
+
+ icalcomponent_add_component(calendar, ievent);
+
+ if (use_calendar)
+ return NULL;
+
+ headers = write_headers_ical(account, ievent, orga);
+
+ if (!headers) {
+ g_warning("can't get headers");
+ g_free(tmpfile);
+ icalcomponent_free(calendar);
+ return NULL;
+ }
+
+ lines = g_strsplit(icalcomponent_as_ical_string(calendar), "\n", 0);
+ qpbody = g_strdup("");
+
+ /* encode to quoted-printable */
+ while (lines[i]) {
+ gchar buf[256];
+ gint e_len = strlen(qpbody), n_len = 0;
+ gchar *outline = conv_codeset_strdup(lines[i], CS_UTF_8, conv_get_outgoing_charset_str());
+
+ qp_encode_line(buf, (guchar *)outline);
+ n_len = strlen(buf);
+
+ qpbody = g_realloc(qpbody, e_len + n_len + 1);
+ strcpy(qpbody+e_len, buf);
+ *(qpbody+n_len+e_len) = '\0';
+
+ g_free(outline);
+ i++;
+ }
+
+ body = g_strdup_printf("%s"
+ "\n"
+ "%s", headers, qpbody);
+
+ if (str_write_to_file(body, tmpfile) < 0) {
+ g_free(tmpfile);
+ tmpfile = NULL;
+ }
+ chmod(tmpfile, S_IRUSR|S_IWUSR);
+
+ g_strfreev(lines);
+ g_free(body);
+ g_free(qpbody);
+ g_free(headers);
+ icalcomponent_free(calendar);
+
+ return tmpfile;
+}
+
+VCalEvent * vcal_manager_new_event (const gchar *uid,
+ const gchar *organizer,
+ const gchar *orgname,
+ const gchar *location,
+ const gchar *summary,
+ const gchar *description,
+ const gchar *dtstart,
+ const gchar *dtend,
+ const gchar *recur,
+ const gchar *tzid,
+ const gchar *url,
+ enum icalproperty_method method,
+ gint sequence,
+ enum icalproperty_kind type)
+{
+ VCalEvent *event = g_new0(VCalEvent, 1);
+
+ event->uid = g_strdup(uid?uid:"");
+ event->organizer = g_strdup(organizer?organizer:"");
+ event->orgname = g_strdup(orgname?orgname:"");
+
+ if (dtend && *(dtend)) {
+ time_t tmp = icaltime_as_timet((icaltime_from_string(dtend)));
+ gchar buft[512];
+ tzset();
+ event->end = g_strdup(ctime_r(&tmp, buft));
+ }
+
+ if (dtstart && *(dtstart)) {
+ time_t tmp = icaltime_as_timet((icaltime_from_string(dtstart)));
+ gchar buft[512];
+ tzset();
+ event->start = g_strdup(ctime_r(&tmp, buft));
+ }
+ event->dtstart = g_strdup(dtstart?dtstart:"");
+ event->dtend = g_strdup(dtend?dtend:"");
+ event->recur = g_strdup(recur?recur:"");
+ event->location = g_strdup(location?location:"");
+ event->summary = g_strdup(summary?summary:"");
+ event->description = g_strdup(description?description:"");
+ event->url = g_strdup(url?url:"");
+ event->tzid = g_strdup(tzid?tzid:"");
+ event->method = method;
+ event->sequence = sequence;
+ event->type = type;
+ event->rec_occurence = FALSE;
+ while (strchr(event->summary, '\n'))
+ *(strchr(event->summary, '\n')) = ' ';
+
+ return event;
+}
+
+void vcal_manager_free_event (VCalEvent *event)
+{
+ GSList *cur;
+ if (!event)
+ return;
+
+ g_free(event->uid);
+ g_free(event->organizer);
+ g_free(event->orgname);
+ g_free(event->start);
+ g_free(event->end);
+ g_free(event->location);
+ g_free(event->summary);
+ g_free(event->dtstart);
+ g_free(event->dtend);
+ g_free(event->recur);
+ g_free(event->tzid);
+ g_free(event->description);
+ g_free(event->url);
+ for (cur = event->answers; cur; cur = cur->next) {
+ answer_free((Answer *)cur->data);
+ }
+ g_slist_free(event->answers);
+ g_free(event);
+}
+
+gchar *vcal_manager_get_event_path(void)
+{
+ static gchar *event_path = NULL;
+ if (!event_path)
+ event_path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", NULL);
+
+ return event_path;
+}
+
+gchar *vcal_manager_get_event_file(const gchar *uid)
+{
+ gchar *tmp = g_strdup(uid);
+ gchar *res = NULL;
+
+ subst_for_filename(tmp);
+ res = g_strconcat(vcal_manager_get_event_path(), G_DIR_SEPARATOR_S,
+ tmp, NULL);
+ g_free(tmp);
+ return res;
+}
+
+PrefsAccount *vcal_manager_get_account_from_event(VCalEvent *event)
+{
+ GSList *list = vcal_manager_get_answers_emails(event);
+ GSList *cur = list;
+
+ /* find an attendee corresponding to one of our accounts */
+ while (cur && cur->data) {
+ gchar *email = (gchar *)cur->data;
+ if (account_find_from_address(email, FALSE)) {
+ g_slist_free(list);
+ return account_find_from_address(email, FALSE);
+ }
+ cur = cur->next;
+ }
+ g_slist_free(list);
+ return NULL;
+}
+
+void vcal_manager_save_event (VCalEvent *event, gboolean export_after)
+{
+ XMLTag *tag = NULL;
+ XMLNode *xmlnode = NULL;
+ GNode *rootnode = NULL;
+ PrefFile *pfile;
+ gchar *path = NULL;
+ GSList *answers = event->answers;
+ gchar *tmp = NULL;
+ gint tmp_method = event->method;
+
+ tag = xml_tag_new("event");
+ xml_tag_add_attr(tag, xml_attr_new("organizer", event->organizer));
+ xml_tag_add_attr(tag, xml_attr_new("orgname", event->orgname));
+ xml_tag_add_attr(tag, xml_attr_new("location", event->location));
+ xml_tag_add_attr(tag, xml_attr_new("summary", event->summary));
+ xml_tag_add_attr(tag, xml_attr_new("description", event->description));
+ xml_tag_add_attr(tag, xml_attr_new("url", event->url));
+ xml_tag_add_attr(tag, xml_attr_new("dtstart", event->dtstart));
+ xml_tag_add_attr(tag, xml_attr_new("dtend", event->dtend));
+ xml_tag_add_attr(tag, xml_attr_new("recur", event->recur));
+ xml_tag_add_attr(tag, xml_attr_new("tzid", event->tzid));
+
+ /* updating answers saves events, don't save them with reply type */
+ if (tmp_method == ICAL_METHOD_REPLY)
+ tmp_method = ICAL_METHOD_REQUEST;
+
+ tmp = g_strdup_printf("%d", tmp_method);
+ xml_tag_add_attr(tag, xml_attr_new("method", tmp));
+ g_free(tmp);
+
+ tmp = g_strdup_printf("%d", event->sequence);
+ xml_tag_add_attr(tag, xml_attr_new("sequence", tmp));
+ g_free(tmp);
+
+ tmp = g_strdup_printf("%d", event->type);
+ xml_tag_add_attr(tag, xml_attr_new("type", tmp));
+ g_free(tmp);
+
+ tmp = g_strdup_printf("%lu", event->postponed);
+ xml_tag_add_attr(tag, xml_attr_new("postponed", tmp));
+ g_free(tmp);
+
+ tmp = g_strdup_printf("%d", event->rec_occurence);
+ xml_tag_add_attr(tag, xml_attr_new("rec_occurence", tmp));
+ g_free(tmp);
+
+ xmlnode = xml_node_new(tag, NULL);
+ rootnode = g_node_new(xmlnode);
+
+ while (answers && answers->data) {
+ XMLNode *ansxmlnode = NULL;
+ GNode *ansnode = NULL;
+ XMLTag *anstag = xml_tag_new("answer");
+ Answer *a = (Answer *)answers->data;
+ xml_tag_add_attr(anstag, xml_attr_new("attendee", a->attendee));
+ xml_tag_add_attr(anstag, xml_attr_new("name", a->name?a->name:""));
+ tmp = g_strdup_printf("%d", a->answer);
+ xml_tag_add_attr(anstag, xml_attr_new("answer", tmp));
+ g_free(tmp);
+ tmp = g_strdup_printf("%d", a->cutype);
+ xml_tag_add_attr(anstag, xml_attr_new("cutype", tmp));
+ g_free(tmp);
+ ansxmlnode = xml_node_new(anstag, NULL);
+ ansnode = g_node_new(ansxmlnode);
+ g_node_append(rootnode, ansnode);
+ answers = answers->next;
+ }
+
+ path = vcal_manager_get_event_file(event->uid);
+
+ if ((pfile = prefs_write_open(path)) == NULL) {
+ make_dir(vcal_manager_get_event_path());
+ if ((pfile = prefs_write_open(path)) == NULL) {
+ free(path);
+ return;
+ }
+ }
+
+ free(path);
+ xml_file_put_xml_decl(pfile->fp);
+ xml_write_tree(rootnode, pfile->fp);
+ xml_free_tree(rootnode);
+
+ if (prefs_file_close(pfile) < 0) {
+ g_warning("failed to write event.\n");
+ return;
+ }
+
+ if (export_after)
+ vcal_folder_export(NULL);
+}
+
+static VCalEvent *event_get_from_xml (const gchar *uid, GNode *node)
+{
+ XMLNode *xmlnode;
+ GList *list;
+ gchar *org = NULL, *location = NULL, *summary = NULL, *orgname = NULL;
+ gchar *dtstart = NULL, *dtend = NULL, *tzid = NULL;
+ gchar *description = NULL, *url = NULL, *recur = NULL;
+ VCalEvent *event = NULL;
+ enum icalproperty_method method = ICAL_METHOD_REQUEST;
+ enum icalproperty_kind type = ICAL_VEVENT_COMPONENT;
+ gint sequence = 0, rec_occurence = 0;
+ time_t postponed = (time_t)0;
+
+ g_return_val_if_fail(node->data != NULL, NULL);
+
+ xmlnode = node->data;
+ if (strcmp2(xmlnode->tag->tag, "event") != 0) {
+ g_warning("tag name != \"event\"\n");
+ return NULL;
+ }
+
+ list = xmlnode->tag->attr;
+ for (; list != NULL; list = list->next) {
+ XMLAttr *attr = list->data;
+
+ if (!attr || !attr->name || !attr->value) continue;
+ if (!strcmp(attr->name, "organizer"))
+ org = g_strdup(attr->value);
+ if (!strcmp(attr->name, "orgname"))
+ orgname = g_strdup(attr->value);
+ if (!strcmp(attr->name, "location"))
+ location = g_strdup(attr->value);
+ if (!strcmp(attr->name, "summary"))
+ summary = g_strdup(attr->value);
+ if (!strcmp(attr->name, "description"))
+ description = g_strdup(attr->value);
+ if (!strcmp(attr->name, "url"))
+ url = g_strdup(attr->value);
+ if (!strcmp(attr->name, "dtstart"))
+ dtstart = g_strdup(attr->value);
+ if (!strcmp(attr->name, "dtend"))
+ dtend = g_strdup(attr->value);
+ if (!strcmp(attr->name, "recur"))
+ recur = g_strdup(attr->value);
+ if (!strcmp(attr->name, "tzid"))
+ tzid = g_strdup(attr->value);
+ if (!strcmp(attr->name, "type"))
+ type = atoi(attr->value);
+ if (!strcmp(attr->name, "method"))
+ method = atoi(attr->value);
+ if (!strcmp(attr->name, "sequence"))
+ sequence = atoi(attr->value);
+ if (!strcmp(attr->name, "postponed"))
+ postponed = atoi(attr->value);
+ if (!strcmp(attr->name, "rec_occurence"))
+ rec_occurence = atoi(attr->value);
+ }
+
+ event = vcal_manager_new_event(uid, org, orgname, location, summary, description,
+ dtstart, dtend, recur, tzid, url, method,
+ sequence, type);
+
+ event->postponed = postponed;
+ event->rec_occurence = rec_occurence;
+
+ g_free(org);
+ g_free(orgname);
+ g_free(location);
+ g_free(summary);
+ g_free(description);
+ g_free(url);
+ g_free(dtstart);
+ g_free(dtend);
+ g_free(recur);
+ g_free(tzid);
+
+ node = node->children;
+ while (node != NULL) {
+ gchar *attendee = NULL;
+ gchar *name = NULL;
+ enum icalparameter_partstat answer = ICAL_PARTSTAT_NEEDSACTION;
+ enum icalparameter_cutype cutype = ICAL_CUTYPE_INDIVIDUAL;
+
+ xmlnode = node->data;
+ if (strcmp2(xmlnode->tag->tag, "answer") != 0) {
+ g_warning("tag name != \"answer\"\n");
+ return event;
+ }
+ list = xmlnode->tag->attr;
+ for (; list != NULL; list = list->next) {
+ XMLAttr *attr = list->data;
+
+ if (!attr || !attr->name || !attr->value) continue;
+ if (!strcmp(attr->name, "attendee"))
+ attendee = g_strdup(attr->value);
+ if (!strcmp(attr->name, "name"))
+ name = g_strdup(attr->value);
+ if (!strcmp(attr->name, "answer"))
+ answer = atoi(attr->value);
+ if (!strcmp(attr->name, "cutype"))
+ cutype = atoi(attr->value);
+ }
+
+ event->answers = g_slist_prepend(event->answers, answer_new(attendee, name, answer, cutype));
+ g_free(attendee);
+ g_free(name);
+ node = node->next;
+ }
+ event->answers = g_slist_reverse(event->answers);
+
+ return event;
+}
+
+VCalEvent *vcal_manager_load_event (const gchar *uid)
+{
+ GNode *node;
+ gchar *path = NULL;
+ VCalEvent *event = NULL;
+
+ path = vcal_manager_get_event_file(uid);
+
+ if (!is_file_exist(path)) {
+ g_free(path);
+ return NULL;
+ }
+
+ node = xml_parse_file(path);
+
+ g_free(path);
+
+ if (!node) {
+ g_warning("no node\n");
+ return NULL;
+ }
+
+ event = event_get_from_xml(uid, node);
+ /* vcal_manager_event_print(event); */
+ xml_free_tree(node);
+
+ if (!event)
+ return NULL;
+
+ while (strchr(event->summary, '\n'))
+ *(strchr(event->summary, '\n')) = ' ';
+
+ return event;
+
+}
+
+void vcal_manager_update_answer (VCalEvent *event,
+ const gchar *attendee,
+ const gchar *name,
+ enum icalparameter_partstat ans,
+ enum icalparameter_cutype cutype)
+{
+ Answer *answer = NULL;
+ GSList *existing = NULL;
+ Answer *existing_a = NULL;
+
+ if (!ans)
+ return;
+
+ answer = answer_new(attendee, name, ans, cutype);
+ existing = answer_find(event, answer);
+
+ if (existing) {
+ existing_a = (Answer *)existing->data;
+
+ if (!answer->name && existing_a->name)
+ answer->name = g_strdup(existing_a->name);
+ if (!answer->cutype && existing_a->cutype)
+ answer->cutype = existing_a->cutype;
+
+ answer_remove(event, answer);
+ }
+
+ answer_add(event, answer);
+
+ vcal_manager_save_event(event, FALSE);
+}
+
+static gchar *write_headers(PrefsAccount *account,
+ VCalEvent *event,
+ gboolean short_headers,
+ gboolean is_reply,
+ gboolean is_pseudo_display)
+{
+ gchar *subject = NULL;
+ gchar date[128];
+ gchar *save_folder = NULL;
+ gchar *result = NULL;
+ gchar *queue_headers = NULL;
+ gchar *method_str = NULL;
+ gchar *attendees = NULL;
+ enum icalparameter_partstat status;
+ gchar *prefix = NULL;
+ gchar enc_subject[512], enc_from[512], *from = NULL;
+ gchar msgid[128];
+ gchar *calmsgid = NULL;
+
+ memset(date, 0, sizeof(date));
+
+ if (is_pseudo_display) {
+ struct icaltimetype itt = (icaltime_from_string(event->dtstart));
+ time_t t = icaltime_as_timet(itt);
+ get_rfc822_date_from_time_t(date, sizeof(date), t);
+ } else {
+ get_rfc822_date(date, sizeof(date));
+ }
+
+ if (account_get_special_folder(account, F_OUTBOX)) {
+ save_folder = folder_item_get_identifier(account_get_special_folder
+ (account, F_OUTBOX));
+ }
+
+ if (!is_reply) {
+ GSList *cur = event->answers;
+ while (cur && cur->data) {
+ gchar *tmp = NULL;
+ Answer *a = (Answer *)cur->data;
+
+ if (strcasecmp(a->attendee, event->organizer)) {
+ if (attendees) {
+ tmp = g_strdup_printf("%s>,\n <%s", attendees, a->attendee);
+ g_free(attendees);
+ attendees = tmp;
+ } else {
+ attendees = g_strdup_printf("%s", a->attendee);
+ }
+ }
+ cur = cur->next;
+ }
+ }
+
+ if (!short_headers) {
+ queue_headers = g_strdup_printf("S:%s\n"
+ "SSV:%s\n"
+ "R:<%s>\n"
+ "MAID:%d\n"
+ "%s%s%s"
+ "X-Claws-End-Special-Headers: 1\n",
+ account->address,
+ account->smtp_server,
+ is_reply ? event->organizer:attendees,
+ account->account_id,
+ save_folder?"SCF:":"",
+ save_folder?save_folder:"",
+ save_folder?"\n":"");
+ } else {
+ queue_headers = g_strdup("");
+ }
+
+ prefix = "";
+ if (is_reply) {
+ method_str = "REPLY";
+ status = vcal_manager_get_reply_for_attendee(event, account->address);
+ if (status == ICAL_PARTSTAT_ACCEPTED)
+ prefix = _("Accepted: ");
+ else if (status == ICAL_PARTSTAT_DECLINED)
+ prefix = _("Declined: ");
+ else if (status == ICAL_PARTSTAT_TENTATIVE)
+ prefix = _("Tentatively Accepted: ");
+ else
+ prefix = "Re: ";
+ } else if (event->method == ICAL_METHOD_PUBLISH)
+ method_str = "PUBLISH";
+ else
+ method_str = "REQUEST";
+
+ subject = g_strdup_printf("%s%s", prefix, event->summary);
+
+ conv_encode_header_full(enc_subject, sizeof(enc_subject), subject, strlen("Subject: "),
+ FALSE, conv_get_outgoing_charset_str());
+ from = is_reply?account->name:(event->orgname?event->orgname:"");
+ conv_encode_header_full(enc_from, sizeof(enc_from), from, strlen("From: "),
+ TRUE, conv_get_outgoing_charset_str());
+
+ if (is_pseudo_display && event->uid) {
+ calmsgid = g_strdup_printf("Message-ID: <%s>\n",event->uid);
+ } else {
+ calmsgid = g_strdup("");
+ }
+
+ if (account && account->set_domain && account->domain) {
+ g_snprintf(msgid, sizeof(msgid), "%s", account->domain);
+ } else if (!strncmp(get_domain_name(), "localhost", strlen("localhost"))) {
+ g_snprintf(msgid, sizeof(msgid), "%s",
+ strchr(account->address, '@') ?
+ strchr(account->address, '@')+1 :
+ account->address);
+ } else {
+ g_snprintf(msgid, sizeof(msgid), "%s", "");
+ }
+
+ generate_msgid(msgid, sizeof(msgid), account->address);
+
+ result = g_strdup_printf("%s"
+ "From: %s <%s>\n"
+ "To: <%s>\n"
+ "Subject: %s\n"
+ "Date: %s\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/calendar; method=%s; charset=\"%s\"\n"
+ "Content-Transfer-Encoding: 8bit\n"
+ "%s"
+ "%s: <%s>\n",
+ queue_headers,
+ enc_from,
+ is_reply ? account->address:event->organizer,
+ is_reply ? event->organizer:(attendees?attendees:event->organizer),
+ enc_subject,
+ date,
+ method_str,
+ CS_UTF_8,
+ calmsgid,
+ is_pseudo_display?
+ "In-Reply-To":"Message-ID",
+ is_pseudo_display?
+ event_to_today_str(event, 0):msgid);
+ g_free(calmsgid);
+ g_free(subject);
+ g_free(save_folder);
+ g_free(queue_headers);
+ g_free(attendees);
+ return result;
+
+
+}
+
+static gchar *write_headers_ical(PrefsAccount *account,
+ icalcomponent *ievent,
+ gchar *orga)
+{
+ gchar subject[512];
+ gchar date[128];
+ gchar *result = NULL;
+ gchar *method_str = NULL;
+ gchar *summary = NULL;
+ gchar *organizer = NULL;
+ gchar *orgname = NULL;
+ icalproperty *prop = NULL;
+ gchar *calmsgid = NULL;
+
+ time_t t = (time_t)0;
+
+ memset(subject, 0, sizeof(subject));
+ memset(date, 0, sizeof(date));
+
+ prop = icalcomponent_get_first_property(ievent, ICAL_SUMMARY_PROPERTY);
+ if (prop) {
+ summary = g_strdup(icalproperty_get_summary(prop));
+ icalproperty_free(prop);
+ } else {
+ summary = g_strdup("");
+ }
+
+ while (strchr(summary, '\n'))
+ *(strchr(summary, '\n')) = ' ';
+
+ prop = icalcomponent_get_first_property(ievent, ICAL_ORGANIZER_PROPERTY);
+ if (prop) {
+ organizer = g_strdup(icalproperty_get_organizer(prop));
+ if (icalproperty_get_parameter_as_string(prop, "CN") != NULL)
+ orgname = g_strdup(icalproperty_get_parameter_as_string(prop, "CN"));
+
+ icalproperty_free(prop);
+ } else {
+ organizer = orga? g_strdup(orga):g_strdup("");
+ }
+
+ prop = icalcomponent_get_first_property(ievent, ICAL_DTSTART_PROPERTY);
+ if (prop) {
+ t = icaltime_as_timet(icalproperty_get_dtstart(prop));
+ get_rfc822_date_from_time_t(date, sizeof(date), t);
+ } else {
+ get_rfc822_date(date, sizeof(date));
+ }
+
+ conv_encode_header(subject, 511, summary, strlen("Subject: "), FALSE);
+
+ method_str = "PUBLISH";
+
+ prop = icalcomponent_get_first_property(ievent, ICAL_UID_PROPERTY);
+ if (prop) {
+ calmsgid = g_strdup_printf("Message-ID: <%s>\n",icalproperty_get_uid(prop));
+ icalproperty_free(prop);
+ } else {
+ calmsgid = g_strdup("");
+ }
+
+
+ result = g_strdup_printf("From: %s <%s>\n"
+ "To: <%s>\n"
+ "Subject: %s%s\n"
+ "Date: %s\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/calendar; method=%s; charset=\"%s\"; vcalsave=\"no\"\n"
+ "Content-Transfer-Encoding: quoted-printable\n"
+ "%s"
+ "In-Reply-To: <%s>\n",
+ orgname?orgname:"",
+ !strncmp(organizer, "MAILTO:", 7) ? organizer+7 : organizer,
+ account->address,
+ "",
+ subject,
+ date,
+ method_str,
+ conv_get_outgoing_charset_str(),
+ calmsgid,
+ event_to_today_str(NULL, t));
+
+ g_free(calmsgid);
+ g_free(orgname);
+ g_free(organizer);
+ g_free(summary);
+
+ return result;
+
+
+}
+
+static gboolean vcal_manager_send (PrefsAccount *account,
+ VCalEvent *event,
+ gboolean is_reply)
+{
+ gchar *tmpfile = NULL;
+ gint msgnum;
+ FolderItem *folderitem;
+ gchar *msgpath = NULL;
+ Folder *folder = NULL;
+
+ tmpfile = vcal_manager_event_dump(event, is_reply, FALSE, NULL, TRUE);
+
+ if (!tmpfile)
+ return FALSE;
+
+ folderitem = account_get_special_folder(account, F_QUEUE);
+ if (!folderitem) {
+ g_warning("can't find queue folder for %s\n", account->address);
+ g_unlink(tmpfile);
+ g_free(tmpfile);
+ return FALSE;
+ }
+ folder_item_scan(folderitem);
+
+ if ((msgnum = folder_item_add_msg(folderitem, tmpfile, NULL, TRUE)) < 0) {
+ g_warning("can't queue the message\n");
+ g_unlink(tmpfile);
+ g_free(tmpfile);
+ return FALSE;
+ }
+
+ msgpath = folder_item_fetch_msg(folderitem, msgnum);
+
+ if (!prefs_common_get_prefs()->work_offline) {
+ gchar *err = NULL;
+ gboolean queued_removed = FALSE;
+ gint val = procmsg_send_message_queue_with_lock(msgpath, &err, folderitem, msgnum, &queued_removed);
+ if (val == 0) {
+ if (!queued_removed)
+ folder_item_remove_msg(folderitem, msgnum);
+ folder_item_scan(folderitem);
+ } else if (err) {
+ alertpanel_error_log("%s", err);
+ g_free(err);
+ }
+ }
+ g_unlink(tmpfile);
+ g_free(tmpfile);
+ g_free(msgpath);
+
+ folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ if (folder)
+ folder_item_scan(folder->inbox);
+
+ vcalviewer_reload(folder->inbox);
+ return TRUE;
+}
+
+gboolean vcal_manager_reply (PrefsAccount *account,
+ VCalEvent *event)
+{
+ return vcal_manager_send(account, event, TRUE);
+}
+
+gboolean vcal_manager_request (PrefsAccount *account,
+ VCalEvent *event)
+{
+ return vcal_manager_send(account, event, FALSE);
+}
+
+EventTime event_to_today(VCalEvent *event, time_t t)
+{
+ struct tm evtstart, today;
+ time_t evtstart_t, today_t;
+ struct icaltimetype itt;
+ struct tm buft;
+
+ tzset();
+
+ today_t = time(NULL);
+ if (event) {
+ itt = icaltime_from_string(event->dtstart);
+ evtstart_t = icaltime_as_timet(itt);
+ } else {
+ evtstart_t = t;
+ }
+
+#ifndef G_OS_WIN32
+ today = *localtime_r(&today_t, &buft);
+ localtime_r(&evtstart_t, &evtstart);
+#else
+ if (today_t < 0)
+ today_t = 1;
+ if (evtstart_t < 0)
+ evtstart_t = 1;
+ today = *localtime(&today_t);
+ evtstart = *localtime(&evtstart_t);
+#endif
+
+ if (today.tm_year == evtstart.tm_year) {
+ int days = evtstart.tm_yday - today.tm_yday;
+ if (days < 0) {
+ return EVENT_PAST;
+ } else if (days == 0) {
+ return EVENT_TODAY;
+ } else if (days == 1) {
+ return EVENT_TOMORROW;
+ } else if (days > 1 && days < 7) {
+ return EVENT_THISWEEK;
+ } else {
+ return EVENT_LATER;
+ }
+ } else if (today.tm_year > evtstart.tm_year) {
+ return EVENT_PAST;
+ } else if (today.tm_year == evtstart.tm_year - 1) {
+ int days = ((365 - today.tm_yday) + evtstart.tm_yday);
+ if (days == 0) {
+ return EVENT_TODAY;
+ } else if (days == 1) {
+ return EVENT_TOMORROW;
+ } else if (days > 1 && days < 7) {
+ return EVENT_THISWEEK;
+ } else {
+ return EVENT_LATER;
+ }
+ } else
+ return EVENT_LATER;
+}
+
+const gchar *event_to_today_str(VCalEvent *event, time_t t)
+{
+ EventTime days = event_to_today(event, t);
+ switch(days) {
+ case EVENT_PAST:
+ return EVENT_PAST_ID;
+ case EVENT_TODAY:
+ return EVENT_TODAY_ID;
+ case EVENT_TOMORROW:
+ return EVENT_TOMORROW_ID;
+ case EVENT_THISWEEK:
+ return EVENT_THISWEEK_ID;
+ case EVENT_LATER:
+ return EVENT_LATER_ID;
+ }
+ return NULL;
+}
diff --git a/src/plugins/vcalendar/vcal_manager.h b/src/plugins/vcalendar/vcal_manager.h
@@ -0,0 +1,130 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VCAL_MANAGER_H__
+#define __VCAL_MANAGER_H__
+
+#include <glib.h>
+#include <ical.h>
+#include "prefs_account.h"
+#include "folder.h"
+
+#define EVENT_PAST_ID "past-events@vcal"
+#define EVENT_TODAY_ID "today-events@vcal"
+#define EVENT_TOMORROW_ID "tomorrow-events@vcal"
+#define EVENT_THISWEEK_ID "thisweek-events@vcal"
+#define EVENT_LATER_ID "later-events@vcal"
+typedef struct _VCalEvent VCalEvent;
+
+struct _VCalEvent
+{
+ gchar *uid;
+ gchar *organizer;
+ gchar *orgname;
+ gchar *start;
+ gchar *end;
+ gchar *dtstart;
+ gchar *dtend;
+ gchar *recur;
+ gchar *tzid;
+ gchar *location;
+ gchar *summary;
+ gchar *description;
+ GSList *answers;
+ enum icalproperty_method method;
+ gint sequence;
+ gchar *url;
+ enum icalproperty_kind type;
+ time_t postponed;
+ gboolean rec_occurence;
+};
+
+typedef struct _Answer Answer;
+
+struct _Answer {
+ gchar *attendee;
+ gchar *name;
+ enum icalparameter_partstat answer;
+ enum icalparameter_cutype cutype;
+};
+
+typedef enum {
+ EVENT_PAST = 0,
+ EVENT_TODAY,
+ EVENT_TOMORROW,
+ EVENT_THISWEEK,
+ EVENT_LATER
+} EventTime;
+VCalEvent *vcal_manager_new_event (const gchar *uid,
+ const gchar *organizer,
+ const gchar *orgname,
+ const gchar *location,
+ const gchar *summary,
+ const gchar *description,
+ const gchar *dtstart,
+ const gchar *dtend,
+ const gchar *recur,
+ const gchar *tzid,
+ const gchar *url,
+ enum icalproperty_method method,
+ gint sequence,
+ enum icalproperty_kind type);
+
+void vcal_manager_free_event (VCalEvent *event);
+void vcal_manager_save_event (VCalEvent *event, gboolean export_after);
+void vcal_manager_update_answer (VCalEvent *event,
+ const gchar *attendee,
+ const gchar *name,
+ enum icalparameter_partstat ans,
+ enum icalparameter_cutype cutype);
+
+VCalEvent *vcal_manager_load_event (const gchar *uid);
+gboolean vcal_manager_reply (PrefsAccount *account,
+ VCalEvent *event);
+gboolean vcal_manager_request (PrefsAccount *account,
+ VCalEvent *event);
+
+GSList *vcal_manager_get_answers_emails(VCalEvent *event);
+gchar *vcal_manager_get_attendee_name(VCalEvent *event, const gchar *attendee);
+gchar *vcal_manager_get_reply_text_for_attendee(VCalEvent *event, const gchar *att);
+gchar *vcal_manager_get_cutype_text_for_attendee(VCalEvent *event, const gchar *att);
+enum icalparameter_partstat vcal_manager_get_reply_for_attendee(VCalEvent *event, const gchar *att);
+enum icalparameter_partstat vcal_manager_get_cutype_for_attendee(VCalEvent *event, const gchar *att);
+gchar *vcal_manager_get_event_path(void);
+gchar *vcal_manager_get_event_file(const gchar *uid);
+gchar *vcal_manager_event_dump(VCalEvent *event, gboolean change_date, gboolean
+ change_from, icalcomponent *use_calendar, gboolean modif);
+gchar *vcal_manager_icalevent_dump(icalcomponent *event, gchar *orga, icalcomponent *use_calendar);
+gchar *vcal_manager_dateevent_dump(const gchar *uid, FolderItem *item);
+
+gchar *vcal_manager_answer_get_text(enum icalparameter_partstat ans);
+gchar *vcal_manager_cutype_get_text(enum icalparameter_cutype type);
+
+PrefsAccount *vcal_manager_get_account_from_event(VCalEvent *event);
+
+void vcal_manager_event_print(VCalEvent *event);
+EventTime event_to_today(VCalEvent *event, time_t t);
+const gchar *event_to_today_str(VCalEvent *event, time_t t);
+void vcal_manager_copy_attendees(VCalEvent *src, VCalEvent *dest);
+Answer *answer_new(const gchar *attendee,
+ const gchar *name,
+ enum icalparameter_partstat ans,
+ enum icalparameter_cutype cutype);
+#endif
diff --git a/src/plugins/vcalendar/vcal_meeting_gtk.c b/src/plugins/vcalendar/vcal_meeting_gtk.c
@@ -0,0 +1,2284 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "defs.h"
+
+#ifdef USE_PTHREAD
+#include <pthread.h>
+#endif
+#include <ical.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <curl/curl.h>
+#include <curl/curlver.h>
+#include "combobox.h"
+
+#include "vcalendar.h"
+#include "vcal_folder.h"
+#include "vcal_manager.h"
+#include "vcal_meeting_gtk.h"
+#include "vcal_prefs.h"
+#include "common-views.h"
+#include "mainwindow.h"
+#include "prefs_account.h"
+#include "account.h"
+#include "filesel.h"
+#include "alertpanel.h"
+#include "addr_compl.h"
+#include "gtkutils.h"
+#include "log.h"
+#include "utils.h"
+
+struct _VCalMeeting
+{
+ gchar *uid;
+ gint sequence;
+ gint method;
+ GtkWidget *window;
+#ifndef GENERIC_UMPC
+ GtkWidget *table;
+#else
+ GtkWidget *table1;
+ GtkWidget *table2;
+#endif
+ GtkWidget *type;
+ GtkWidget *who;
+ GtkWidget *avail_evtbox;
+ GtkWidget *avail_img;
+ GtkWidget *start_c;
+ GtkWidget *start_time;
+ GtkWidget *end_c;
+ GtkWidget *end_time;
+ GtkWidget *location;
+ GtkWidget *summary;
+ GtkWidget *description;
+ GSList *attendees;
+ GtkWidget *attendees_vbox;
+ GtkWidget *save_btn;
+ GtkWidget *avail_btn;
+ GSList *avail_accounts;
+ GtkWidget *total_avail_evtbox;
+ GtkWidget *total_avail_img;
+ GtkWidget *total_avail_msg;
+ PrefsAccount *account;
+ gboolean visible;
+#if !GTK_CHECK_VERSION(2,12,0)
+ GtkTooltips *tips;
+#endif
+};
+
+struct _VCalAttendee {
+ GtkWidget *address;
+ GtkWidget *remove_btn;
+ GtkWidget *add_btn;
+ GtkWidget *cutype;
+ GtkWidget *hbox;
+ VCalMeeting *meet;
+ gchar *status;
+ GtkWidget *avail_evtbox;
+ GtkWidget *avail_img;
+ gchar *cached_contents;
+ gboolean org;
+};
+
+static GdkCursor *watch_cursor = NULL;
+
+VCalAttendee *attendee_add(VCalMeeting *meet, gchar *address, gchar *name, gchar *partstat, gchar *cutype, gboolean first);
+
+#ifndef GENERIC_UMPC
+#define TABLE_ADD_LINE(label_text, widget, do_space) { \
+ gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>", \
+ label_text?label_text:""); \
+ GtkWidget *label = NULL; \
+ GtkWidget *spacer = NULL; \
+ GtkWidget *s_hbox = NULL; \
+ if (do_space) { \
+ spacer = gtk_label_new(""); \
+ gtk_widget_set_size_request(spacer, 18, 16); \
+ s_hbox = gtk_hbox_new(FALSE, 6); \
+ gtk_box_pack_start(GTK_BOX(s_hbox), spacer, FALSE, FALSE, 0); \
+ gtk_box_pack_start(GTK_BOX(s_hbox), widget, TRUE, TRUE, 0); \
+ } \
+ if (label_text) { \
+ label = gtk_label_new(tmpstr); \
+ g_free(tmpstr); \
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE); \
+ gtk_misc_set_alignment (GTK_MISC(label), 1, 0.5); \
+ gtk_table_attach (GTK_TABLE (meet->table), \
+ label, 0, 1, i, i+1, \
+ GTK_FILL, GTK_FILL, 6, 6); \
+ gtk_table_attach (GTK_TABLE (meet->table), \
+ do_space?s_hbox:widget, 1, 2, i, i+1, \
+ GTK_FILL|GTK_EXPAND, GTK_FILL, 6, 6); \
+ if (GTK_IS_LABEL(widget)) { \
+ gtk_label_set_use_markup(GTK_LABEL (widget), TRUE); \
+ gtk_misc_set_alignment (GTK_MISC(widget),0, 0); \
+ gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); \
+ } \
+ } else { \
+ g_free(tmpstr); \
+ gtk_table_attach (GTK_TABLE (meet->table), \
+ do_space?s_hbox:widget, 0, 2, i, i+1, \
+ GTK_FILL|GTK_EXPAND, GTK_FILL, 6, 6); \
+ } \
+ i++; \
+}
+#else
+#define TABLE_ADD_LINE(label_text, widget, do_space, intable1) { \
+ gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>", \
+ label_text?label_text:""); \
+ GtkWidget *label = NULL; \
+ GtkWidget *spacer = NULL; \
+ GtkWidget *s_hbox = NULL; \
+ if (do_space) { \
+ spacer = gtk_label_new(""); \
+ gtk_widget_set_size_request(spacer, 18, 16); \
+ s_hbox = gtk_hbox_new(FALSE, 6); \
+ gtk_box_pack_start(GTK_BOX(s_hbox), spacer, FALSE, FALSE, 0); \
+ gtk_box_pack_start(GTK_BOX(s_hbox), widget, TRUE, TRUE, 0); \
+ } \
+ if (label_text) { \
+ label = gtk_label_new(tmpstr); \
+ g_free(tmpstr); \
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE); \
+ gtk_misc_set_alignment (GTK_MISC(label), 1, 0.5); \
+ if(intable1) { \
+ gtk_table_attach (GTK_TABLE (meet->table1), \
+ label, 0, 1, i, i+1, \
+ GTK_FILL, GTK_FILL, 1, 1); \
+ } \
+ else { \
+ gtk_table_attach (GTK_TABLE (meet->table2), \
+ label, 0, 1, i, i+1, \
+ GTK_FILL, GTK_FILL, 1, 1); \
+ } \
+ if(intable1) { \
+ gtk_table_attach (GTK_TABLE (meet->table1), \
+ do_space?s_hbox:widget, 1, 2, i, i+1, \
+ GTK_FILL|GTK_EXPAND, GTK_FILL, 1, 1); \
+ } \
+ else { \
+ gtk_table_attach (GTK_TABLE (meet->table2), \
+ do_space?s_hbox:widget, 1, 2, i, i+1, \
+ GTK_FILL|GTK_EXPAND, GTK_FILL, 1, 1); \
+ } \
+ if (GTK_IS_LABEL(widget)) { \
+ gtk_label_set_use_markup(GTK_LABEL (widget), TRUE); \
+ gtk_misc_set_alignment (GTK_MISC(widget),0, 0); \
+ gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); \
+ } \
+ } else { \
+ g_free(tmpstr); \
+ if(intable1) { \
+ gtk_table_attach (GTK_TABLE (meet->table1), \
+ do_space?s_hbox:widget, 0, 2, i, i+1, \
+ GTK_FILL|GTK_EXPAND, GTK_FILL, 1, 1); \
+ } \
+ else { \
+ gtk_table_attach (GTK_TABLE (meet->table2), \
+ do_space?s_hbox:widget, 0, 2, i, i+1, \
+ GTK_FILL|GTK_EXPAND, GTK_FILL, 1, 1); \
+ } \
+ } \
+ i++; \
+}
+#endif
+enum {
+ DAY,
+ MONTH,
+ YEAR,
+ HOUR,
+ MINUTE
+};
+
+static gboolean avail_btn_can_be_sensitive(void)
+{
+ if (vcalprefs.freebusy_get_url == NULL
+ || *vcalprefs.freebusy_get_url == '\0')
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static gint get_dtdate(const gchar *str, gint field)
+{
+ time_t t = icaltime_as_timet((icaltime_from_string(str)));
+ struct tm buft;
+ struct tm *lt;
+
+ tzset();
+
+#ifdef G_OS_WIN32
+ if (t < 0)
+ t = 1;
+#endif
+ lt = localtime_r(&t, &buft);
+
+ switch(field){
+ case DAY:
+ return lt->tm_mday;
+ case MONTH:
+ return lt->tm_mon + 1;
+ case YEAR:
+ return lt->tm_year + 1900;
+ case HOUR:
+ return lt->tm_hour;
+ case MINUTE:
+ return lt->tm_min;
+ }
+ return -1;
+
+}
+
+static gboolean add_btn_cb(GtkButton *widget, gpointer data)
+{
+ VCalAttendee *attendee = (VCalAttendee *)data;
+ attendee_add(attendee->meet, NULL, NULL, NULL, NULL, FALSE);
+ return TRUE;
+}
+
+static gboolean remove_btn_cb(GtkButton *widget, gpointer data)
+{
+ VCalAttendee *attendee = (VCalAttendee *)data;
+ gtk_container_remove(GTK_CONTAINER(attendee->meet->attendees_vbox), attendee->hbox);
+ attendee->meet->attendees = g_slist_remove(attendee->meet->attendees, attendee);
+
+ g_free(attendee->status);
+
+ return TRUE;
+}
+
+VCalAttendee *attendee_add(VCalMeeting *meet, gchar *address, gchar *name, gchar *partstat, gchar *cutype, gboolean first)
+{
+ GtkWidget *att_hbox = gtk_hbox_new(FALSE, 6);
+ VCalAttendee *attendee = g_new0(VCalAttendee, 1);
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = meet->tips;
+#endif
+
+ attendee->address = gtk_entry_new();
+ attendee->cutype = gtk_combo_box_new_text();
+ attendee->avail_evtbox = gtk_event_box_new();
+ attendee->avail_img = gtk_image_new_from_stock
+ (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+ gtk_widget_show(attendee->address);
+ gtk_widget_show(attendee->cutype);
+ gtk_widget_show(attendee->avail_evtbox);
+
+ CLAWS_SET_TIP(attendee->address, _("Use <tab> to autocomplete from addressbook"));
+ gtk_widget_set_size_request(attendee->avail_evtbox, 18, 16);
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(attendee->avail_evtbox), FALSE);
+ gtk_container_add (GTK_CONTAINER(attendee->avail_evtbox), attendee->avail_img);
+
+ if (address) {
+ gchar *str = g_strdup_printf("%s%s%s%s",
+ (name && strlen(name))?name:"",
+ (name && strlen(name))?" <":"",
+ address,
+ (name && strlen(name))?">":"");
+ gtk_entry_set_text(GTK_ENTRY(attendee->address), str);
+ g_free(str);
+ }
+
+ if (partstat)
+ attendee->status = g_strdup(partstat);
+
+ gtk_combo_box_append_text(GTK_COMBO_BOX(attendee->cutype), _("Individual"));
+ gtk_combo_box_append_text(GTK_COMBO_BOX(attendee->cutype), _("Group"));
+ gtk_combo_box_append_text(GTK_COMBO_BOX(attendee->cutype), _("Resource"));
+ gtk_combo_box_append_text(GTK_COMBO_BOX(attendee->cutype), _("Room"));
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(attendee->cutype), 0);
+
+ if (cutype) {
+ if (!strcmp(cutype, "group"))
+ gtk_combo_box_set_active(GTK_COMBO_BOX(attendee->cutype), 1);
+ if (!strcmp(cutype, "resource"))
+ gtk_combo_box_set_active(GTK_COMBO_BOX(attendee->cutype), 2);
+ if (!strcmp(cutype, "room"))
+ gtk_combo_box_set_active(GTK_COMBO_BOX(attendee->cutype), 3);
+ }
+
+ attendee->add_btn = gtk_button_new_with_label(_("Add..."));
+ attendee->remove_btn = gtk_button_new_with_label(_("Remove"));
+ attendee->meet = meet;
+ attendee->hbox = att_hbox;
+
+ gtk_widget_show(attendee->add_btn);
+ gtk_widget_show(attendee->remove_btn);
+ gtk_widget_show(attendee->hbox);
+
+ gtk_box_pack_start(GTK_BOX(attendee->hbox), attendee->avail_evtbox, FALSE, FALSE, 0);
+ gtk_widget_set_sensitive(attendee->remove_btn, !first);
+ meet->attendees = g_slist_append(meet->attendees, attendee);
+
+ g_signal_connect(G_OBJECT(attendee->remove_btn), "clicked",
+ G_CALLBACK(remove_btn_cb), attendee);
+ g_signal_connect(G_OBJECT(attendee->add_btn), "clicked",
+ G_CALLBACK(add_btn_cb), attendee);
+
+ gtk_box_pack_start(GTK_BOX(att_hbox), attendee->address, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(att_hbox), attendee->cutype, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(att_hbox), attendee->add_btn, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(att_hbox), attendee->remove_btn, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(meet->attendees_vbox), att_hbox, FALSE, FALSE, 0);
+ address_completion_register_entry(GTK_ENTRY(attendee->address), FALSE);
+#ifndef GENERIC_UMPC
+ gtk_widget_set_size_request(attendee->address, 320, -1);
+#else
+ gtk_widget_set_size_request(attendee->address, 220, -1);
+#endif
+ return attendee;
+}
+
+static gchar *get_organizer(VCalMeeting *meet)
+{
+ int index = gtk_combo_box_get_active(GTK_COMBO_BOX(meet->who));
+ int i = 0;
+ GSList *cur = meet->avail_accounts;
+ while (i < index && cur && cur->data) {
+ debug_print("%d:skipping %s\n",i,((PrefsAccount *)(cur->data))->address);
+ cur = cur->next;
+ i++;
+ }
+ if (cur)
+ return g_strdup(((PrefsAccount *)(cur->data))->address);
+ else
+ return g_strdup("");
+}
+
+static gchar *get_organizer_name(VCalMeeting *meet)
+{
+ int index = gtk_combo_box_get_active(GTK_COMBO_BOX(meet->who));
+ int i = 0;
+ GSList *cur = meet->avail_accounts;
+ while (i < index && cur && cur->data) {
+ debug_print("%d:skipping %s\n",i,((PrefsAccount *)(cur->data))->address);
+ cur = cur->next;
+ i++;
+ }
+ if (cur)
+ return g_strdup(((PrefsAccount *)(cur->data))->name);
+ else
+ return g_strdup("");
+}
+
+static void get_time_from_combo(GtkWidget *combo, int *h, int *m)
+{
+ gchar *tmp;
+ gchar **parts;
+
+ if (!h || !m)
+ return;
+
+ tmp = gtk_editable_get_chars(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(combo))), 0, -1);
+ parts = g_strsplit(tmp, ":", 2);
+ if (parts[0] && parts[1] && *parts[0] && *parts[1]) {
+ *h = atoi(parts[0]);
+ *m = atoi(parts[1]);
+ }
+ g_strfreev(parts);
+ g_free(tmp);
+}
+
+static int get_current_gmt_offset(void)
+{
+ time_t now = time(NULL);
+ struct tm gmt;
+ struct tm local;
+
+ tzset();
+
+#ifdef G_OS_WIN32
+ if (now < 0)
+ now = 1;
+#endif
+ gmtime_r(& now, & gmt);
+ localtime_r(& now, & local);
+
+ local.tm_isdst = 0;
+ return mktime(&local)-mktime(&gmt);
+}
+
+static int get_gmt_offset_at_time(time_t then)
+{
+ struct tm gmt;
+ struct tm local;
+
+ tzset();
+
+#ifdef G_OS_WIN32
+ if (then < 0)
+ then = 1;
+#endif
+ gmtime_r(& then, & gmt);
+ localtime_r(& then, & local);
+
+ local.tm_isdst = 0;
+ return mktime(&local)-mktime(&gmt);
+}
+
+static gchar *get_date(VCalMeeting *meet, int start)
+{
+ struct tm *lt;
+ time_t t;
+ guint d, m, y;
+ int dst_offset = 0;
+ struct tm buft;
+
+ tzset();
+
+ t = time(NULL);
+#ifdef G_OS_WIN32
+ if (t < 0)
+ t = 1;
+#endif
+ lt = localtime_r(&t, &buft);
+
+ gtk_calendar_get_date(GTK_CALENDAR(start ? meet->start_c : meet->end_c), &y, &m, &d);
+ lt->tm_mday = d;
+ lt->tm_mon = m;
+ lt->tm_year = y - 1900;
+ lt->tm_hour = 0;
+ lt->tm_min = 0;
+ lt->tm_sec = 0;
+
+ if (start) {
+ get_time_from_combo(meet->start_time, <->tm_hour, <->tm_min);
+ } else {
+ get_time_from_combo(meet->end_time, <->tm_hour, <->tm_min);
+ }
+
+ debug_print("%d %d %d, %d:%d\n", lt->tm_mday, lt->tm_mon, lt->tm_year, lt->tm_hour, lt->tm_min);
+ t = mktime(lt);
+
+ dst_offset = get_current_gmt_offset() - get_gmt_offset_at_time(t);
+ debug_print("DST change offset to apply to time %d\n", dst_offset);
+ t += dst_offset;
+ debug_print("%s\n", ctime(&t));
+ return g_strdup(icaltime_as_ical_string(icaltime_from_timet(t, FALSE)));
+}
+
+static gchar *get_location(VCalMeeting *meet)
+{
+ return gtk_editable_get_chars(GTK_EDITABLE(meet->location),0, -1);
+}
+
+static gchar *get_summary(VCalMeeting *meet)
+{
+ return gtk_editable_get_chars(GTK_EDITABLE(meet->summary),0, -1);
+}
+
+static gchar *get_description(VCalMeeting *meet)
+{
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(meet->description));
+ GtkTextIter start, end;
+
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+}
+
+void vcal_meeting_free(VCalMeeting *meet)
+{
+ debug_print("freeing meeting\n");
+ g_free(meet->uid);
+ address_completion_end(meet->window);
+ g_slist_free(meet->avail_accounts);
+ g_slist_free(meet->attendees);
+ g_free(meet);
+}
+
+static void destroy_meeting_cb(GtkWidget *widget, gpointer data)
+{
+ VCalMeeting *meet = (VCalMeeting *)data;
+ vcal_meeting_free(meet);
+}
+
+static void vcal_destroy(VCalMeeting *meet)
+{
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(meet->description));
+ gtk_text_buffer_remove_selection_clipboard(buffer, gtk_clipboard_get(GDK_SELECTION_PRIMARY));
+ gtk_widget_destroy(meet->window);
+}
+
+static gboolean meeting_key_pressed(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data)
+{
+ VCalMeeting *meet = (VCalMeeting *)data;
+
+ if (event && event->keyval == GDK_Escape) {
+ vcal_destroy(meet);
+ }
+ return FALSE;
+}
+
+static int get_list_item_num(int h, int m)
+{
+ if (m % 15 != 0)
+ return -1;
+
+ return (h*4 + m/15);
+}
+
+static void meeting_end_changed(GtkWidget *widget, gpointer data);
+
+static void meeting_start_changed(GtkWidget *widget, gpointer data)
+{
+ VCalMeeting *meet = (VCalMeeting *)data;
+ struct tm start_lt;
+ struct tm end_lt;
+ time_t start_t, end_t;
+ guint d, m, y;
+ int num = -1;
+
+ if (strlen(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(meet->start_time))))) < 5)
+ return;
+ tzset();
+
+ start_t = time(NULL);
+ end_t = time(NULL);
+#ifdef G_OS_WIN32
+ if (start_t < 0)
+ start_t = 1;
+ if (end_t < 0)
+ end_t = 1;
+#endif
+ localtime_r(&start_t, &start_lt);
+ localtime_r(&end_t, &end_lt);
+
+ gtk_calendar_get_date(GTK_CALENDAR(meet->start_c), &y, &m, &d);
+ start_lt.tm_mday = d; start_lt.tm_mon = m; start_lt.tm_year = y - 1900;
+ get_time_from_combo(meet->start_time, &start_lt.tm_hour, &start_lt.tm_min);
+
+ start_t = mktime(&start_lt);
+ debug_print("start %s\n", ctime(&start_t));
+
+ gtk_calendar_get_date(GTK_CALENDAR(meet->end_c), &y, &m, &d);
+ end_lt.tm_mday = d; end_lt.tm_mon = m; end_lt.tm_year = y - 1900;
+
+ get_time_from_combo(meet->end_time, &end_lt.tm_hour, &end_lt.tm_min);
+ end_t = mktime(&end_lt);
+
+ debug_print("end %s\n", ctime(&end_t));
+
+ if (end_t > start_t) {
+ debug_print("ok\n");
+ return;
+ }
+ end_t = start_t + 3600;
+
+#ifdef G_OS_WIN32
+ if (end_t < 0)
+ end_t = 1;
+#endif
+ localtime_r(&end_t, &end_lt);
+ debug_print("n %d %d %d, %d:%d\n", end_lt.tm_mday, end_lt.tm_mon, end_lt.tm_year, end_lt.tm_hour, end_lt.tm_min);
+
+ g_signal_handlers_block_by_func(gtk_bin_get_child(GTK_BIN(meet->end_time)), meeting_end_changed, meet);
+ g_signal_handlers_block_by_func(meet->end_c, meeting_end_changed, meet);
+
+ gtk_calendar_select_day(GTK_CALENDAR(meet->end_c), end_lt.tm_mday);
+
+ gtk_calendar_select_month(GTK_CALENDAR(meet->end_c),
+ end_lt.tm_mon,
+ end_lt.tm_year + 1900);
+
+ num = get_list_item_num(end_lt.tm_hour, end_lt.tm_min);
+ if (num > -1) {
+ gchar *time_text = g_strdup_printf("%02d:%02d", end_lt.tm_hour, end_lt.tm_min);
+ combobox_select_by_text(GTK_COMBO_BOX(meet->end_time), time_text);
+ g_free(time_text);
+ } else {
+ gchar *tmp = g_strdup_printf("%02d:%02d",
+ end_lt.tm_hour,
+ end_lt.tm_min);
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(meet->end_time))),
+ tmp);
+ g_free(tmp);
+ }
+ g_signal_handlers_unblock_by_func(gtk_bin_get_child(GTK_BIN(meet->end_time)), meeting_end_changed, meet);
+ g_signal_handlers_unblock_by_func(meet->end_c, meeting_end_changed, meet);
+}
+
+static void meeting_end_changed(GtkWidget *widget, gpointer data)
+{
+ VCalMeeting *meet = (VCalMeeting *)data;
+ struct tm start_lt;
+ struct tm end_lt;
+ time_t start_t, end_t;
+ guint d, m, y;
+ int num = -1;
+
+ if (strlen(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(meet->end_time))))) < 5)
+ return;
+ start_t = time(NULL);
+ end_t = time(NULL);
+
+ tzset();
+
+#ifdef G_OS_WIN32
+ if (start_t < 0)
+ start_t = 1;
+ if (end_t < 0)
+ end_t = 1;
+#endif
+ localtime_r(&start_t, &start_lt);
+ localtime_r(&end_t, &end_lt);
+
+ gtk_calendar_get_date(GTK_CALENDAR(meet->start_c), &y, &m, &d);
+ start_lt.tm_mday = d; start_lt.tm_mon = m; start_lt.tm_year = y - 1900;
+ get_time_from_combo(meet->start_time, &start_lt.tm_hour, &start_lt.tm_min);
+
+ start_t = mktime(&start_lt);
+ debug_print("start %s\n", ctime(&start_t));
+
+ gtk_calendar_get_date(GTK_CALENDAR(meet->end_c), &y, &m, &d);
+ end_lt.tm_mday = d; end_lt.tm_mon = m; end_lt.tm_year = y - 1900;
+ get_time_from_combo(meet->end_time, &end_lt.tm_hour, &end_lt.tm_min);
+
+ end_t = mktime(&end_lt);
+
+ debug_print("end %s\n", ctime(&end_t));
+
+ if (end_t > start_t) {
+ debug_print("ok\n");
+ return;
+ }
+ start_t = end_t - 3600;
+
+ tzset();
+
+#ifdef G_OS_WIN32
+ if (start_t < 0)
+ start_t = 1;
+#endif
+ localtime_r(&start_t, &start_lt);
+ debug_print("n %d %d %d, %d:%d\n", start_lt.tm_mday, start_lt.tm_mon, start_lt.tm_year, start_lt.tm_hour, start_lt.tm_min);
+
+ g_signal_handlers_block_by_func(gtk_bin_get_child(GTK_BIN(meet->start_time)), meeting_start_changed, meet);
+ g_signal_handlers_block_by_func(meet->start_c, meeting_start_changed, meet);
+
+ gtk_calendar_select_day(GTK_CALENDAR(meet->start_c), start_lt.tm_mday);
+
+ gtk_calendar_select_month(GTK_CALENDAR(meet->start_c),
+ start_lt.tm_mon,
+ start_lt.tm_year + 1900);
+
+ num = get_list_item_num(start_lt.tm_hour, start_lt.tm_min);
+ if (num > -1) {
+ gchar *time_text = g_strdup_printf("%02d:%02d", start_lt.tm_hour, start_lt.tm_min);
+ combobox_select_by_text(GTK_COMBO_BOX(meet->start_time), time_text);
+ g_free(time_text);
+ } else {
+ gchar *tmp = g_strdup_printf("%02d:%02d",
+ start_lt.tm_hour,
+ start_lt.tm_min);
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(meet->start_time))),
+ tmp);
+ g_free(tmp);
+ }
+
+ g_signal_handlers_unblock_by_func(gtk_bin_get_child(GTK_BIN(meet->start_time)), meeting_start_changed, meet);
+ g_signal_handlers_unblock_by_func(meet->start_c, meeting_start_changed, meet);
+}
+
+static void att_update_icon(VCalMeeting *meet, VCalAttendee *attendee, gint avail, gchar *text)
+{
+ const gchar *icon = GTK_STOCK_DIALOG_INFO;
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = meet->tips;
+#endif
+
+ switch (avail) {
+ case 0: icon = GTK_STOCK_DIALOG_WARNING; break;
+ case 1: icon = GTK_STOCK_DIALOG_INFO; break;
+ default: icon = GTK_STOCK_DIALOG_QUESTION; break;
+ }
+ if (!gtk_entry_get_text(GTK_ENTRY(attendee->address))
+ || strlen(gtk_entry_get_text(GTK_ENTRY(attendee->address)))==0) {
+ if (attendee->avail_img) {
+ gtk_widget_hide(attendee->avail_img);
+ }
+ CLAWS_SET_TIP(attendee->avail_evtbox, NULL);
+ } else if (attendee->avail_img) {
+ gtk_image_set_from_stock
+ (GTK_IMAGE(attendee->avail_img),
+ icon,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_widget_show(attendee->avail_img);
+ CLAWS_SET_TIP(attendee->avail_evtbox, text);
+ }
+}
+
+gboolean attendee_available(VCalAttendee *attendee, const gchar *dtstart, const gchar *dtend, const gchar *contents)
+{
+ icalcomponent *toplvl, *vfreebusy;
+ icalproperty *busyprop;
+ struct icaltimetype start = icaltime_from_string(dtstart);
+ struct icaltimetype end = icaltime_from_string(dtend);
+ gboolean result = TRUE;
+
+
+ if (contents == NULL)
+ return TRUE;
+
+ toplvl = icalcomponent_new_from_string((gchar *)contents);
+
+ if (toplvl == NULL)
+ return TRUE;
+
+ vfreebusy = icalcomponent_get_first_component(toplvl, ICAL_VFREEBUSY_COMPONENT);
+ while (vfreebusy && icalcomponent_isa(vfreebusy) != ICAL_VFREEBUSY_COMPONENT)
+ vfreebusy = icalcomponent_get_next_component(toplvl, ICAL_VFREEBUSY_COMPONENT);
+
+ if (vfreebusy) {
+ busyprop = icalcomponent_get_first_property(vfreebusy, ICAL_FREEBUSY_PROPERTY);
+ while (busyprop) {
+ struct icalperiodtype ipt = icalproperty_get_freebusy(busyprop);
+
+ if ( icaltime_compare(start, ipt.end) >= 0 || icaltime_compare(end, ipt.start) <= 0 ) {
+ result = TRUE;
+ } else {
+ result = FALSE;
+ break;
+ }
+ busyprop = icalcomponent_get_next_property(vfreebusy, ICAL_FREEBUSY_PROPERTY);
+ }
+ }
+
+ icalcomponent_free(toplvl);
+ return result;
+}
+
+static gchar *get_avail_msg(const gchar *unavailable_persons, gboolean multiple,
+ gboolean short_version, gint offset_before, gint offset_after)
+{
+ gchar *msg, *intro = NULL, *outro = NULL, *before = NULL, *after = NULL;
+
+ if (multiple)
+ intro = g_strdup(_("The following person(s) are busy at the time of your planned meeting:\n- "));
+ else if (!strcmp(unavailable_persons, _("You")))
+ intro = g_strdup(_("You are busy at the time of your planned meeting"));
+ else
+ intro = g_strdup_printf(_("%s is busy at the time of your planned meeting"), unavailable_persons);
+ if (offset_before == 3600)
+ before = g_strdup_printf(_("%d hour sooner"), offset_before/3600);
+ else if (offset_before > 3600 && offset_before%3600 == 0)
+ before = g_strdup_printf(_("%d hours sooner"), offset_before/3600);
+ else if (offset_before > 3600)
+ before = g_strdup_printf(_("%d hours and %d minutes sooner"), offset_before/3600, (offset_before%3600)/60);
+ else if (offset_before == 1800)
+ before = g_strdup_printf(_("%d minutes sooner"), offset_before/60);
+ else
+ before = NULL;
+
+ if (offset_after == 3600)
+ after = g_strdup_printf(_("%d hour later"), offset_after/3600);
+ else if (offset_after > 3600 && offset_after%3600 == 0)
+ after = g_strdup_printf(_("%d hours later"), offset_after/3600);
+ else if (offset_after > 3600)
+ after = g_strdup_printf(_("%d hours and %d minutes later"), offset_after/3600, (offset_after%3600)/60);
+ else if (offset_after == 1800)
+ after = g_strdup_printf(_("%d minutes later"), offset_after/60);
+ else
+ after = NULL;
+
+ if (multiple) {
+ if (before && after)
+ outro = g_strdup_printf(_("\n\nEveryone would be available %s or %s."), before, after);
+ else if (before || after)
+ outro = g_strdup_printf(_("\n\nEveryone would be available %s."), before?before:after);
+ else
+ outro = g_strdup_printf(_("\n\nIt isn't possible to have this meeting with everyone "
+ "in the previous or next 6 hours."));
+ } else {
+ if (short_version) {
+ if (before && after)
+ outro = g_markup_printf_escaped(_("would be available %s or %s"), before, after);
+ else if (before || after)
+ outro = g_markup_printf_escaped(_("would be available %s"), before?before:after);
+ else
+ outro = g_strdup_printf(_("not available"));
+ } else {
+ if (before && after)
+ outro = g_markup_printf_escaped(_(", but would be available %s or %s."), before, after);
+ else if (before || after)
+ outro = g_markup_printf_escaped(_(", but would be available %s."), before?before:after);
+ else
+ outro = g_strdup_printf(_(", and isn't available "
+ "in the previous or next 6 hours."));
+ }
+ }
+ if (multiple && short_version)
+ msg = g_strconcat(outro+2, NULL);
+ else if (multiple)
+ msg = g_strconcat(intro, unavailable_persons, outro, NULL);
+ else if (short_version)
+ msg = g_strdup(outro);
+ else
+ msg = g_strconcat(intro, outro, NULL);
+ g_free(intro);
+ g_free(outro);
+ g_free(before);
+ g_free(after);
+ return msg;
+}
+
+static gboolean find_availability(const gchar *dtstart, const gchar *dtend, GSList *attendees, gboolean for_send, VCalMeeting *meet)
+{
+ GSList *cur;
+ gint offset = -1800, offset_before = 0, offset_after = 0;
+ gboolean found = FALSE;
+ gchar *unavailable_persons = NULL;
+ gchar *msg = NULL;
+ struct icaltimetype start = icaltime_from_string(dtstart);
+ struct icaltimetype end = icaltime_from_string(dtend);
+ AlertValue val = G_ALERTALTERNATE;
+ gint total = 0;
+ GHashTable *avail_table_avail = g_hash_table_new(NULL, g_direct_equal);
+ GHashTable *avail_table_before = g_hash_table_new(NULL, g_direct_equal);
+ GHashTable *avail_table_after = g_hash_table_new(NULL, g_direct_equal);
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = meet->tips;
+#endif
+
+ for (cur = attendees; cur; cur = cur->next) {
+ VCalAttendee *attendee = (VCalAttendee *)cur->data;
+ if (!attendee_available(attendee, icaltime_as_ical_string(start), icaltime_as_ical_string(end),
+ attendee->cached_contents)) {
+ gchar *mail = NULL;
+
+ if (attendee->org)
+ mail = g_strdup(_("You"));
+ else
+ mail = gtk_editable_get_chars(GTK_EDITABLE(attendee->address), 0, -1);
+
+ if (unavailable_persons == NULL) {
+ unavailable_persons = g_markup_printf_escaped("%s", mail);
+ } else {
+ gchar *tmp = g_markup_printf_escaped("%s,\n- %s", unavailable_persons, mail);
+ g_free(unavailable_persons);
+ unavailable_persons = tmp;
+ }
+ total++;
+ g_free(mail);
+ att_update_icon(meet, attendee, 0, _("not available"));
+ } else {
+ if (attendee->cached_contents != NULL)
+ att_update_icon(meet, attendee, 1, _("available"));
+ else
+ att_update_icon(meet, attendee, 2, _("Free/busy retrieval failed"));
+
+ g_hash_table_insert(avail_table_avail, attendee, GINT_TO_POINTER(1));
+ }
+ }
+ offset = -1800;
+ found = FALSE;
+ while (!found && offset >= -3600*6) {
+ gboolean ok = TRUE;
+ struct icaltimetype new_start = icaltime_from_timet(icaltime_as_timet(start)+offset, FALSE);
+ struct icaltimetype new_end = icaltime_from_timet(icaltime_as_timet(end)+offset, FALSE);
+ for (cur = attendees; cur; cur = cur->next) {
+ VCalAttendee *attendee = (VCalAttendee *)cur->data;
+ debug_print("trying %s - %s (offset %d)\n",
+ icaltime_as_ical_string(new_start), icaltime_as_ical_string(new_end), offset);
+ if (!attendee_available(attendee, icaltime_as_ical_string(new_start), icaltime_as_ical_string(new_end),
+ attendee->cached_contents)) {
+ ok = FALSE;
+ break;
+ } else {
+ if (!g_hash_table_lookup(avail_table_before, attendee)
+ && !g_hash_table_lookup(avail_table_avail, attendee))
+ g_hash_table_insert(avail_table_before, attendee, GINT_TO_POINTER(-offset));
+ }
+ }
+ if (ok) {
+ found = TRUE;
+ offset_before = -offset;
+ }
+ offset -= 1800;
+ }
+ found = FALSE;
+ offset = 1800;
+ while (!found && offset <= 3600*6) {
+ gboolean ok = TRUE;
+ struct icaltimetype new_start = icaltime_from_timet(icaltime_as_timet(start)+offset, FALSE);
+ struct icaltimetype new_end = icaltime_from_timet(icaltime_as_timet(end)+offset, FALSE);
+ for (cur = attendees; cur; cur = cur->next) {
+ VCalAttendee *attendee = (VCalAttendee *)cur->data;
+ debug_print("trying %s - %s (offset %d)\n",
+ icaltime_as_ical_string(new_start), icaltime_as_ical_string(new_end), offset);
+ if (!attendee_available(attendee, icaltime_as_ical_string(new_start), icaltime_as_ical_string(new_end),
+ attendee->cached_contents)) {
+ ok = FALSE;
+ break;
+ } else {
+ if (!g_hash_table_lookup(avail_table_after, attendee)
+ && !g_hash_table_lookup(avail_table_avail, attendee))
+ g_hash_table_insert(avail_table_after, attendee, GINT_TO_POINTER(offset));
+ }
+ }
+ if (ok) {
+ found = TRUE;
+ offset_after = offset;
+ }
+
+ offset += 1800;
+ }
+
+ for (cur = attendees; cur; cur = cur->next) {
+ VCalAttendee *attendee = (VCalAttendee *)cur->data;
+ gint ok = GPOINTER_TO_INT(g_hash_table_lookup(avail_table_avail, attendee));
+ gint o_before = GPOINTER_TO_INT(g_hash_table_lookup(avail_table_before, attendee));
+ gint o_after = GPOINTER_TO_INT(g_hash_table_lookup(avail_table_after, attendee));
+ if (!o_before && !o_after && !ok) {
+ att_update_icon(meet, attendee, 0, _("not available"));
+ } else if ((o_before != 0 || o_after != 0) && !ok) {
+ if (attendee->org)
+ msg = get_avail_msg(_("You"), FALSE, TRUE, o_before, o_after);
+ else
+ msg = get_avail_msg(gtk_entry_get_text(GTK_ENTRY(attendee->address)), FALSE, TRUE, o_before, o_after);
+ att_update_icon(meet, attendee, 0, msg);
+ g_free(msg);
+ }
+
+ }
+ g_hash_table_destroy(avail_table_before);
+ g_hash_table_destroy(avail_table_after);
+
+ if (for_send) {
+ msg = get_avail_msg(unavailable_persons, (total > 1), FALSE, offset_before, offset_after);
+
+ val = alertpanel_full(_("Not everyone is available"), msg,
+ GTK_STOCK_CANCEL, _("Send anyway"), NULL, FALSE,
+ NULL, ALERT_QUESTION, G_ALERTDEFAULT);
+ g_free(msg);
+ }
+ msg = get_avail_msg(unavailable_persons, TRUE, TRUE, offset_before, offset_after);
+ g_free(unavailable_persons);
+ gtk_image_set_from_stock
+ (GTK_IMAGE(meet->total_avail_img),
+ GTK_STOCK_DIALOG_WARNING,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_widget_show(meet->total_avail_img);
+ gtk_label_set_text(GTK_LABEL(meet->total_avail_msg), _("Not everyone is available. "
+ "See tooltips for more info..."));
+ CLAWS_SET_TIP(meet->total_avail_evtbox, msg);
+ g_free(msg);
+ return (val == G_ALERTALTERNATE);
+}
+
+static gboolean check_attendees_availability(VCalMeeting *meet, gboolean tell_if_ok, gboolean for_send)
+{
+ GSList *cur;
+ gchar *tmp = NULL;
+ gchar *real_url = NULL;
+ gint num_format = 0;
+ gchar *change_user = NULL, *change_dom = NULL;
+ gchar *dtstart = NULL;
+ gchar *dtend = NULL;
+ gboolean find_avail = FALSE;
+ gboolean res = TRUE, uncertain = FALSE;
+ gchar *organizer = NULL;
+ VCalAttendee *dummy_org = NULL;
+ gchar *internal_ifb = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", G_DIR_SEPARATOR_S,
+ "internal.ifb", NULL);
+ gboolean local_only = FALSE;
+ GSList *attlist;
+#if !(GTK_CHECK_VERSION(2,12,0))
+ GtkTooltips *tips = meet->tips;
+#endif
+
+ if (vcalprefs.freebusy_get_url == NULL
+ || *vcalprefs.freebusy_get_url == '\0') {
+ local_only = TRUE;
+ } else {
+ real_url = g_strdup(vcalprefs.freebusy_get_url);
+ tmp = real_url;
+
+ while (strchr(tmp, '%')) {
+ tmp = strchr(tmp, '%')+1;
+ num_format++;
+ }
+ if (num_format > 2) {
+ g_warning("wrong format in %s!\n", real_url);
+ g_free(real_url);
+ return FALSE;
+ }
+
+ tmp = NULL;
+ if (strstr(real_url, "%u") != NULL) {
+ change_user = strstr(real_url, "%u");
+ *(strstr(real_url, "%u")+1) = 's';
+ }
+ if (strstr(real_url, "%d") != NULL) {
+ change_dom = strstr(real_url, "%d");
+ *(strstr(real_url, "%d")+1) = 's';
+ }
+ debug_print("url format %s\n", real_url);
+ }
+ dtstart = get_date(meet, TRUE);
+ dtend = get_date(meet, FALSE);
+
+ /* hack to check our own avail. */
+ organizer = get_organizer(meet);
+ dummy_org = g_new0(VCalAttendee, 1);
+ dummy_org->address = gtk_entry_new();
+ dummy_org->avail_img = meet->avail_img;
+ dummy_org->avail_evtbox = meet->avail_evtbox;
+ dummy_org->org = TRUE;
+ gtk_entry_set_text(GTK_ENTRY(dummy_org->address), organizer);
+ g_free(organizer);
+ dummy_org->cached_contents = file_read_to_str(internal_ifb);
+ g_free(internal_ifb);
+
+ if (!local_only) {
+ meet->attendees = g_slist_prepend(meet->attendees, dummy_org);
+ attlist = meet->attendees;
+ } else {
+ attlist = g_slist_prepend(NULL, dummy_org);
+ }
+
+ gtk_widget_set_sensitive(meet->save_btn, FALSE);
+ gtk_widget_set_sensitive(meet->avail_btn, FALSE);
+
+ if (meet->window->window)
+ gdk_window_set_cursor(meet->window->window, watch_cursor);
+
+ for (cur = attlist; cur && cur->data; cur = cur->next) {
+ VCalAttendee *attendee = (VCalAttendee *)cur->data;
+ gchar *email = gtk_editable_get_chars(GTK_EDITABLE(attendee->address), 0, -1);
+ gchar *remail, *user, *domain;
+ gchar *contents = NULL;
+
+ if (*email == '\0') {
+ g_free(email);
+ att_update_icon(meet, attendee, 0, NULL);
+ continue;
+ }
+
+ if (!local_only) {
+ remail = g_strdup(email);
+
+ extract_address(remail);
+ if (strrchr(remail, ' '))
+ user = g_strdup(strrchr(remail, ' ')+1);
+ else
+ user = g_strdup(remail);
+ if (strchr(user, '@')) {
+ domain = g_strdup(strchr(user, '@')+1);
+ *(strchr(user, '@')) = '\0';
+ } else {
+ domain = g_strdup("");
+ }
+ g_free(remail);
+ if (change_user && change_dom) {
+ if (change_user < change_dom)
+ tmp = g_strdup_printf(real_url, user, domain);
+ else
+ tmp = g_strdup_printf(real_url, domain, user);
+ } else if (change_user) {
+ tmp = g_strdup_printf(real_url, user);
+ } else if (change_dom) {
+ tmp = g_strdup_printf(real_url, domain);
+ } else {
+ tmp = g_strdup(real_url);
+ }
+ g_free(user);
+ g_free(domain);
+ debug_print("url to get %s\n", tmp);
+ }
+
+ if (attendee->cached_contents != NULL) {
+ contents = attendee->cached_contents;
+ attendee->cached_contents = NULL;
+ } else if (!local_only) {
+ if (strncmp(tmp, "http://", 7)
+ && strncmp(tmp, "https://", 8)
+ && strncmp(tmp, "webcal://", 9)
+ && strncmp(tmp, "ftp://", 6))
+ contents = file_read_to_str(tmp);
+ else {
+ gchar *label = g_strdup_printf(_("Fetching planning for %s..."), email);
+ if (!strncmp(tmp, "webcal://", 9)) {
+ gchar *tmp2 = g_strdup_printf("http://%s", tmp+9);
+ g_free(tmp);
+ tmp = tmp2;
+ }
+ contents = vcal_curl_read(tmp, label, FALSE, NULL);
+ g_free(label);
+ }
+ } else {
+ contents = NULL;
+ }
+
+ g_free(email);
+ g_free(tmp);
+
+ if (contents == NULL) {
+ uncertain = TRUE;
+ att_update_icon(meet, attendee, 2, _("Free/busy retrieval failed"));
+ continue;
+ }
+ else {
+ if (!attendee_available(attendee, dtstart, dtend, contents)) {
+ find_avail = TRUE;
+ debug_print("not available!\n");
+ } else {
+ debug_print("available!\n");
+ att_update_icon(meet, attendee, 1, _("Available"));
+ }
+ attendee->cached_contents = contents;
+
+ }
+ }
+
+ if (find_avail) {
+ res = find_availability((dtstart), (dtend), attlist, for_send, meet);
+ } else {
+ res = TRUE;
+ if (tell_if_ok) {
+ if (for_send)
+ alertpanel_notice(_("Everyone is available."));
+ else if (!uncertain) {
+ gtk_image_set_from_stock
+ (GTK_IMAGE(meet->total_avail_img),
+ GTK_STOCK_DIALOG_INFO,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_widget_show(meet->total_avail_img);
+ gtk_label_set_text(GTK_LABEL(meet->total_avail_msg), _("Everyone is available."));
+ CLAWS_SET_TIP(meet->total_avail_evtbox, NULL);
+ } else {
+ gtk_image_set_from_stock
+ (GTK_IMAGE(meet->total_avail_img),
+ GTK_STOCK_DIALOG_QUESTION,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_widget_show(meet->total_avail_img);
+ gtk_label_set_text(GTK_LABEL(meet->total_avail_msg), _("Everyone is available."));
+ CLAWS_SET_TIP(meet->total_avail_evtbox, _("Everyone seems available, but some free/busy information failed to be retrieved."));
+ }
+ }
+ }
+
+ for (cur = attlist; cur && cur->data; cur = cur->next) {
+ VCalAttendee *attendee = (VCalAttendee *)cur->data;
+ g_free(attendee->cached_contents);
+ attendee->cached_contents = NULL;
+ }
+ gtk_widget_set_sensitive(meet->save_btn, TRUE);
+ gtk_widget_set_sensitive(meet->avail_btn, avail_btn_can_be_sensitive());
+ if (meet->window->window)
+ gdk_window_set_cursor(meet->window->window, NULL);
+
+ if (!local_only)
+ meet->attendees = g_slist_remove(meet->attendees, dummy_org);
+ else
+ g_slist_free(attlist);
+ gtk_widget_destroy(dummy_org->address);
+ g_free(dummy_org);
+
+ if (!local_only)
+ g_free(real_url);
+
+ g_free(dtstart);
+ g_free(dtend);
+ return res;
+}
+
+static gboolean check_avail_cb(GtkButton *widget, gpointer data)
+{
+ VCalMeeting *meet = (VCalMeeting *)data;
+ check_attendees_availability(meet, TRUE, FALSE);
+ return TRUE;
+}
+
+static gboolean send_meeting_cb(GtkButton *widget, gpointer data)
+{
+ VCalMeeting *meet = (VCalMeeting *)data;
+ gchar *uid = NULL;
+ gchar *organizer = NULL;
+ gchar *organizer_name = NULL;
+ gchar *dtstart = NULL;
+ gchar *dtend = NULL;
+ gchar *tzid = NULL;
+ gchar *location = NULL;
+ gchar *summary = NULL;
+ gchar *description = NULL;
+ VCalEvent *event = NULL;
+ gchar buf[256];
+ GSList *cur;
+ PrefsAccount *account = NULL;
+ gboolean res = FALSE;
+ gboolean found_att = FALSE;
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ gboolean redisp = FALSE;
+
+ if (meet->uid == NULL && meet->visible &&
+ !check_attendees_availability(meet, FALSE, TRUE)) {
+ return FALSE;
+ }
+
+ if (folder) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ if (mainwin->summaryview->folder_item == folder->inbox) {
+ redisp = TRUE;
+ summary_show(mainwin->summaryview, NULL);
+ }
+ }
+ gtk_widget_set_sensitive(meet->save_btn, FALSE);
+ gtk_widget_set_sensitive(meet->avail_btn, FALSE);
+ if (meet->window->window)
+ gdk_window_set_cursor(meet->window->window, watch_cursor);
+
+ organizer = get_organizer(meet);
+ organizer_name = get_organizer_name(meet);
+ account = account_find_from_address(organizer, FALSE);
+
+ if (account && account->set_domain && account->domain) {
+ g_snprintf(buf, sizeof(buf), "%s", account->domain);
+ } else if (!strncmp(get_domain_name(), "localhost", strlen("localhost"))) {
+ g_snprintf(buf, sizeof(buf), "%s",
+ strchr(account->address, '@') ?
+ strchr(account->address, '@')+1 :
+ account->address);
+ } else {
+ g_snprintf(buf, sizeof(buf), "%s", "");
+ }
+ generate_msgid(buf, 255, account->address);
+
+ if (meet->uid) {
+ uid = g_strdup(meet->uid);
+ } else {
+ uid = g_strdup(buf);
+ }
+
+ dtstart = get_date(meet, TRUE);
+ dtend = get_date(meet, FALSE);
+ location = get_location(meet);
+ summary = get_summary(meet);
+ description = get_description(meet);
+
+ event = vcal_manager_new_event(uid, organizer, organizer_name, location, summary, description,
+ dtstart, dtend, NULL, tzid, NULL, meet->method,
+ meet->sequence,
+ ICAL_VEVENT_COMPONENT);
+
+ vcal_manager_update_answer(event, organizer, organizer_name,
+ ICAL_PARTSTAT_ACCEPTED,
+ ICAL_CUTYPE_INDIVIDUAL);
+
+ for (cur = meet->attendees; cur && cur->data; cur = cur->next) {
+ VCalAttendee *attendee = (VCalAttendee *)cur->data;
+ gchar *email = gtk_editable_get_chars(GTK_EDITABLE(attendee->address), 0, -1);
+ gint index = 0;
+ gchar *orig_email = email;
+ gchar *name = NULL;
+ enum icalparameter_cutype cutype = ICAL_CUTYPE_INDIVIDUAL;
+ enum icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
+
+ index = gtk_combo_box_get_active(GTK_COMBO_BOX(attendee->cutype));
+
+ cutype = ICAL_CUTYPE_INDIVIDUAL + index;
+ if (attendee->status) {
+ if(!strcmp(attendee->status, "accepted"))
+ status = ICAL_PARTSTAT_ACCEPTED;
+ if(!strcmp(attendee->status, "tentatively accepted"))
+ status = ICAL_PARTSTAT_TENTATIVE;
+ if(!strcmp(attendee->status, "declined"))
+ status = ICAL_PARTSTAT_DECLINED;
+ g_free(attendee->status);
+ }
+ if (strlen(email)) {
+ if (strstr(email, " <")) {
+ name = email;
+ email = strstr(email," <") + 2;
+ *(strstr(name," <")) = '\0';
+ if (strstr(email, ">"))
+ *(strstr(email, ">")) = '\0';
+ }
+
+ vcal_manager_update_answer(event, email, name,
+ status, cutype);
+
+ found_att = strcmp(email, organizer);
+ }
+ g_free(orig_email);
+ }
+
+ if (found_att)
+ res = vcal_manager_request(account, event);
+ else
+ res = TRUE;
+ g_free(uid);
+ g_free(organizer);
+ g_free(organizer_name);
+ g_free(dtstart);
+ g_free(dtend);
+ g_free(description);
+ g_free(location);
+ g_free(summary);
+ vcal_manager_free_event(event);
+
+ gtk_widget_set_sensitive(meet->save_btn, TRUE);
+ gtk_widget_set_sensitive(meet->avail_btn, avail_btn_can_be_sensitive());
+ if (meet->window->window)
+ gdk_window_set_cursor(meet->window->window, NULL);
+
+ if (res) {
+ vcal_destroy(meet);
+ } else {
+ alertpanel_error(_("Could not send the meeting invitation.\n"
+ "Check the recipients."));
+ }
+
+ if (folder)
+ folder_item_scan(folder->inbox);
+
+ if (folder && redisp) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ summary_show(mainwin->summaryview, folder->inbox);
+ }
+
+ return res;
+}
+
+static GList *get_predefined_times(void)
+{
+ int h,m;
+ GList *times = NULL;
+ for (h = 0; h < 24; h++) {
+ for (m = 0; m < 60; m += 15) {
+ gchar *tmp = g_strdup_printf("%02d:%02d", h, m);
+ times = g_list_append(times, tmp);
+ }
+ }
+ return times;
+}
+
+static VCalMeeting *vcal_meeting_create_real(VCalEvent *event, gboolean visible)
+{
+ VCalMeeting *meet = g_new0(VCalMeeting, 1);
+ GtkTextBuffer *buffer = NULL;
+ GtkWidget *date_hbox, *date_vbox, *save_hbox, *label, *hbox;
+ gchar *s = NULL;
+ GtkObject *start_h_adj, *start_m_adj, *end_h_adj, *end_m_adj;
+ int i = 0, num = 0;
+ GtkWidget *scrolledwin;
+ GList *times = NULL;
+ GList *accounts;
+ GtkListStore *menu;
+ gchar *time_text = NULL;
+#ifdef GENERIC_UMPC
+ GtkWidget *notebook;
+ GtkWidget *maemo_vbox0;
+#endif
+
+ if (!watch_cursor)
+ watch_cursor = gdk_cursor_new(GDK_WATCH);
+
+#if !(GTK_CHECK_VERSION(2,12,0))
+ meet->tips = tips;
+#endif
+ meet->visible = visible;
+ start_h_adj = gtk_adjustment_new (0, 0, 23, 1, 10, 10);
+ start_m_adj = gtk_adjustment_new (0, 0, 59, 1, 10, 10);
+ end_h_adj = gtk_adjustment_new (0, 0, 23, 1, 10, 10);
+ end_m_adj = gtk_adjustment_new (0, 0, 59, 1, 10, 10);
+
+ meet->window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "vcal_meeting_gtk");
+#ifndef GENERIC_UMPC
+ meet->table = gtk_table_new(7, 2, FALSE);
+#else
+ meet->table1 = gtk_table_new(4, 2, FALSE);
+ meet->table2 = gtk_table_new(2, 2, FALSE);
+#endif
+ meet->who = gtk_combo_box_new_text();
+
+ meet->start_c = gtk_calendar_new();
+ meet->end_c = gtk_calendar_new();
+
+ meet->avail_evtbox = gtk_event_box_new();
+ meet->avail_img = gtk_image_new_from_stock
+ (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+ times = get_predefined_times();
+
+ meet->start_time = gtk_combo_box_entry_new_text ();
+ gtk_combo_box_set_active(GTK_COMBO_BOX(meet->start_time), -1);
+ menu = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(meet->start_time)));
+ combobox_set_popdown_strings(GTK_COMBO_BOX(meet->start_time), times);
+
+ meet->end_time = gtk_combo_box_entry_new_text ();
+ gtk_combo_box_set_active(GTK_COMBO_BOX(meet->end_time), -1);
+ menu = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(meet->end_time)));
+ combobox_set_popdown_strings(GTK_COMBO_BOX(meet->end_time), times);
+
+ list_free_strings(times);
+ g_list_free(times);
+
+ meet->location = gtk_entry_new();
+ meet->summary = gtk_entry_new();
+ meet->description = gtk_text_view_new();
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(meet->description));
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(meet->description), TRUE);
+ gtk_text_buffer_add_selection_clipboard(buffer, gtk_clipboard_get(GDK_SELECTION_PRIMARY));
+
+ scrolledwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
+ GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(scrolledwin), meet->description);
+
+ if (event) {
+ meet->uid = g_strdup(event->uid);
+ meet->sequence = event->sequence + 1;
+ meet->method = (event->method == ICAL_METHOD_CANCEL ?
+ ICAL_METHOD_CANCEL:ICAL_METHOD_REQUEST);
+
+ gtk_entry_set_text(GTK_ENTRY(meet->location), event->location);
+ gtk_entry_set_text(GTK_ENTRY(meet->summary), event->summary);
+ gtk_text_buffer_set_text(buffer, event->description, -1);
+ } else
+ meet->method = ICAL_METHOD_REQUEST;
+
+ meet->save_btn = gtk_button_new_with_label(_("Save & Send"));
+ meet->avail_btn = gtk_button_new_with_label(_("Check availability"));
+
+ meet->total_avail_evtbox = gtk_event_box_new();
+ meet->total_avail_img = gtk_image_new_from_stock
+ (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ meet->total_avail_msg = gtk_label_new("");
+
+ gtk_widget_set_size_request(meet->total_avail_evtbox, 18, 16);
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(meet->total_avail_evtbox), FALSE);
+ gtk_container_add (GTK_CONTAINER(meet->total_avail_evtbox), meet->total_avail_img);
+
+ g_signal_connect(G_OBJECT(meet->save_btn), "clicked",
+ G_CALLBACK(send_meeting_cb), meet);
+
+ g_signal_connect(G_OBJECT(meet->avail_btn), "clicked",
+ G_CALLBACK(check_avail_cb), meet);
+
+ g_signal_connect(G_OBJECT(meet->window), "destroy",
+ G_CALLBACK(destroy_meeting_cb), meet);
+ g_signal_connect(G_OBJECT(meet->window), "key_press_event",
+ G_CALLBACK(meeting_key_pressed), meet);
+
+
+ gtk_widget_set_size_request(meet->description, -1, 100);
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(meet->description), GTK_WRAP_WORD);
+
+ if (!event || (event && !event->dtstart && !event->dtend)) {
+ time_t t = time (NULL)+ 3600;
+ struct tm buft1, buft2;
+ struct tm *lt = localtime_r (&t, &buft1);
+ mktime(lt);
+ gtk_calendar_select_day(GTK_CALENDAR(meet->start_c),
+ lt->tm_mday);
+ gtk_calendar_select_month(GTK_CALENDAR(meet->start_c),
+ lt->tm_mon, lt->tm_year + 1900);
+
+ time_text = g_strdup_printf("%02d:%02d", lt->tm_hour, 0);
+ combobox_select_by_text(GTK_COMBO_BOX(meet->start_time), time_text);
+ g_free(time_text);
+
+ t += 3600;
+ lt = localtime_r(&t, &buft2);
+
+ gtk_calendar_select_day(GTK_CALENDAR(meet->end_c),
+ lt->tm_mday);
+ gtk_calendar_select_month(GTK_CALENDAR(meet->end_c),
+ lt->tm_mon, lt->tm_year + 1900);
+
+ time_text = g_strdup_printf("%02d:%02d", lt->tm_hour, 0);
+ combobox_select_by_text(GTK_COMBO_BOX(meet->end_time), time_text);
+ g_free(time_text);
+
+ } else {
+ gtk_calendar_select_day(GTK_CALENDAR(meet->start_c),
+ get_dtdate(event->dtstart, DAY));
+ gtk_calendar_select_day(GTK_CALENDAR(meet->end_c),
+ get_dtdate(event->dtend, DAY));
+
+ gtk_calendar_select_month(GTK_CALENDAR(meet->start_c),
+ get_dtdate(event->dtstart, MONTH)-1,
+ get_dtdate(event->dtstart, YEAR));
+ gtk_calendar_select_month(GTK_CALENDAR(meet->end_c),
+ get_dtdate(event->dtend, MONTH)-1,
+ get_dtdate(event->dtend, YEAR));
+
+ num = get_list_item_num(get_dtdate(event->dtstart, HOUR),
+ get_dtdate(event->dtstart, MINUTE));
+ if (num > -1) {
+ time_text = g_strdup_printf("%02d:%02d", get_dtdate(event->dtstart, HOUR),
+ get_dtdate(event->dtstart, MINUTE));
+ combobox_select_by_text(GTK_COMBO_BOX(meet->start_time), time_text);
+ g_free(time_text);
+ } else {
+ gchar *tmp = g_strdup_printf("%02d:%02d",
+ get_dtdate(event->dtstart, HOUR),
+ get_dtdate(event->dtstart, MINUTE));
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(meet->start_time))),
+ tmp);
+ g_free(tmp);
+ }
+
+ num = get_list_item_num(get_dtdate(event->dtend, HOUR),
+ get_dtdate(event->dtend, MINUTE));
+ if (num > -1) {
+ time_text = g_strdup_printf("%02d:%02d", get_dtdate(event->dtend, HOUR),
+ get_dtdate(event->dtend, MINUTE));
+ combobox_select_by_text(GTK_COMBO_BOX(meet->end_time), time_text);
+ g_free(time_text);
+ } else {
+ gchar *tmp = g_strdup_printf("%02d:%02d",
+ get_dtdate(event->dtend, HOUR),
+ get_dtdate(event->dtend, MINUTE));
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(meet->end_time))),
+ tmp);
+ g_free(tmp);
+ }
+ }
+
+ g_signal_connect(G_OBJECT(meet->start_c), "day-selected",
+ G_CALLBACK(meeting_start_changed), meet);
+ g_signal_connect(G_OBJECT(gtk_bin_get_child(GTK_BIN(meet->start_time))),
+ "changed",
+ G_CALLBACK(meeting_start_changed),
+ meet);
+
+ g_signal_connect(G_OBJECT(meet->end_c), "day-selected",
+ G_CALLBACK(meeting_end_changed), meet);
+ g_signal_connect(G_OBJECT(gtk_bin_get_child(GTK_BIN(meet->end_time))),
+ "changed",
+ G_CALLBACK(meeting_end_changed),
+ meet);
+
+#ifndef GENERIC_UMPC
+ gtk_widget_set_size_request(meet->start_time, 80, -1);
+ gtk_widget_set_size_request(meet->end_time, 80, -1);
+#else
+ gtk_widget_set_size_request(meet->start_time, 120, -1);
+ gtk_widget_set_size_request(meet->end_time, 120, -1);
+#endif
+
+ date_hbox = gtk_hbox_new(FALSE, 6);
+ date_vbox = gtk_vbox_new(FALSE, 6);
+ hbox = gtk_hbox_new(FALSE, 6);
+ label = gtk_label_new(_("<b>Starts at:</b> ")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
+
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), meet->start_time, FALSE, FALSE, 0);
+ label = gtk_label_new(_("<b> on:</b>")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_vbox), meet->start_c, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_hbox), date_vbox, FALSE, FALSE, 0);
+
+#ifndef GENERIC_UMPC
+ label = gtk_label_new(" ");
+#else
+ label = gtk_label_new("");
+#endif
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(date_hbox), label, TRUE, TRUE, 0);
+
+ date_vbox = gtk_vbox_new(FALSE, 6);
+ hbox = gtk_hbox_new(FALSE, 6);
+ label = gtk_label_new(_("<b>Ends at:</b> ")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
+
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), meet->end_time, FALSE, FALSE, 0);
+ label = gtk_label_new(_("<b> on:</b>")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_vbox), meet->end_c, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_hbox), date_vbox, FALSE, FALSE, 0);
+
+ meet->attendees_vbox = gtk_vbox_new(FALSE, 6);
+ gtk_widget_show_all(meet->attendees_vbox);
+ if (!event) {
+ attendee_add(meet, NULL, NULL, NULL, NULL, TRUE);
+ } else {
+ gboolean firstadd = TRUE;
+ GSList *list = vcal_manager_get_answers_emails(event);
+ while (list && list->data) {
+ gchar *address = (gchar *)list->data;
+ gchar *name = vcal_manager_get_attendee_name(event, address);
+ gchar *answer = vcal_manager_get_reply_text_for_attendee(event, address);
+ gchar *type = vcal_manager_get_cutype_text_for_attendee(event, address);
+ if (strcmp(event->organizer, address)) {
+ attendee_add(meet, address, name, answer, type, firstadd);
+ firstadd = FALSE;
+ }
+ g_free(name);
+ g_free(answer);
+ g_free(type);
+ list = list->next;
+ }
+
+ if (firstadd == TRUE)
+ attendee_add(meet, NULL, NULL, NULL, NULL, TRUE);
+ }
+
+ if (!event) {
+ gtk_window_set_title(GTK_WINDOW(meet->window), _("New meeting"));
+ } else {
+ gchar *title = g_strdup_printf(_("%s - Edit meeting"),
+ event->summary);
+ gtk_window_set_title(GTK_WINDOW(meet->window), title);
+ g_free(title);
+ }
+ address_completion_start(meet->window);
+
+ accounts = account_get_list();
+ g_return_val_if_fail(accounts != NULL, NULL);
+
+ for (i = 0; accounts != NULL; accounts = accounts->next) {
+ PrefsAccount *ac = (PrefsAccount *)accounts->data;
+
+ if (ac->protocol == A_NNTP) {
+ continue;
+ }
+ if (!event && ac == account_get_cur_account()) {
+ num = i;
+ }
+ else if (event && !strcmp(ac->address, event->organizer))
+ num = i;
+
+ meet->avail_accounts = g_slist_append(meet->avail_accounts, ac);
+
+ if (ac->name)
+ s = g_strdup_printf("%s: %s <%s>",
+ ac->account_name,
+ ac->name, ac->address);
+ else
+ s = g_strdup_printf("%s: %s",
+ ac->account_name, ac->address);
+
+ gtk_combo_box_append_text(GTK_COMBO_BOX(meet->who), s);
+ g_free(s);
+ i++;
+ }
+ gtk_combo_box_set_active(GTK_COMBO_BOX(meet->who), num);
+
+ save_hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(save_hbox), meet->save_btn, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(save_hbox), meet->avail_btn, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(save_hbox), meet->total_avail_evtbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(save_hbox), meet->total_avail_msg, FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(hbox), meet->avail_evtbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), meet->who, TRUE, TRUE, 0);
+
+ gtk_widget_set_size_request(meet->avail_evtbox, 18, 16);
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(meet->avail_evtbox), FALSE);
+ gtk_container_add (GTK_CONTAINER(meet->avail_evtbox), meet->avail_img);
+
+#ifndef GENERIC_UMPC
+ TABLE_ADD_LINE(_("Organizer:"), hbox, FALSE);
+ TABLE_ADD_LINE(_("Summary:"), meet->summary, TRUE);
+ TABLE_ADD_LINE(_("Time:"), date_hbox, TRUE);
+ TABLE_ADD_LINE(_("Location:"), meet->location, TRUE);
+ TABLE_ADD_LINE(_("Description:"), scrolledwin, TRUE);
+ TABLE_ADD_LINE(_("Attendees:"), meet->attendees_vbox, FALSE);
+ TABLE_ADD_LINE("", save_hbox, TRUE);
+
+ gtk_widget_set_size_request(meet->window, -1, -1);
+ gtk_container_add(GTK_CONTAINER(meet->window), meet->table);
+#else
+ TABLE_ADD_LINE(_("Organizer:"), hbox, FALSE, TRUE);
+ TABLE_ADD_LINE(_("Summary:"), meet->summary, TRUE, TRUE);
+ TABLE_ADD_LINE(_("Location:"), meet->location, FALSE, TRUE);
+ TABLE_ADD_LINE(_("Description:"), scrolledwin, TRUE, TRUE);
+ TABLE_ADD_LINE(_("Attendees:"), meet->attendees_vbox, FALSE, TRUE);
+ TABLE_ADD_LINE("", date_hbox, TRUE, FALSE);
+
+ notebook = gtk_notebook_new ();
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ meet->table1,
+ gtk_label_new_with_mnemonic(_("Event:")));
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ meet->table2,
+ gtk_label_new_with_mnemonic(_("Time:")));
+ gtk_widget_show (notebook);
+
+ maemo_vbox0 = gtk_vbox_new(FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(maemo_vbox0), notebook, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(maemo_vbox0), save_hbox, FALSE, FALSE, 0);
+
+ gtk_widget_set_size_request(meet->window, -1, -1);
+ gtk_container_add (GTK_CONTAINER (meet->window), maemo_vbox0);
+
+ maemo_connect_key_press_to_mainwindow(GTK_WINDOW(meet->window));
+#endif
+ if (visible) {
+ GSList *cur;
+ gtk_widget_show_all(meet->window);
+#ifdef MAEMO
+ maemo_window_full_screen_if_needed(GTK_WINDOW(meet->window));
+#endif
+ for (cur = meet->attendees; cur; cur = cur->next) {
+ gtk_widget_hide(((VCalAttendee *)cur->data)->avail_img);
+ }
+ gtk_widget_hide(meet->avail_img);
+ gtk_widget_hide(meet->total_avail_img);
+ gtk_widget_set_sensitive(meet->avail_btn, avail_btn_can_be_sensitive());
+ }
+ return meet;
+}
+
+VCalMeeting *vcal_meeting_create(VCalEvent *event)
+{
+ return vcal_meeting_create_real(event, TRUE);
+}
+
+VCalMeeting *vcal_meeting_create_with_start(VCalEvent *event, struct tm *sdate)
+{
+ VCalMeeting *meet = vcal_meeting_create(event);
+ int num = -1;
+ gtk_calendar_select_day(GTK_CALENDAR(meet->start_c),
+ sdate->tm_mday);
+ gtk_calendar_select_day(GTK_CALENDAR(meet->end_c),
+ sdate->tm_mday);
+
+ gtk_calendar_select_month(GTK_CALENDAR(meet->start_c),
+ sdate->tm_mon, sdate->tm_year+1900);
+ gtk_calendar_select_month(GTK_CALENDAR(meet->end_c),
+ sdate->tm_mon, sdate->tm_year+1900);
+
+ if (sdate->tm_hour != 0) {
+ num = get_list_item_num(sdate->tm_hour, 0);
+ if (num > -1) {
+ gchar *time_text = g_strdup_printf("%02d:%02d", sdate->tm_hour, 0);
+ combobox_select_by_text(GTK_COMBO_BOX(meet->start_time), time_text);
+ g_free(time_text);
+ }
+ if (sdate->tm_hour < 23) {
+ num = get_list_item_num(sdate->tm_hour+1, 0);
+ if (num > -1) {
+ gchar *time_text = g_strdup_printf("%02d:%02d", sdate->tm_hour+1, 0);
+ combobox_select_by_text(GTK_COMBO_BOX(meet->end_time), time_text);
+ g_free(time_text);
+ }
+ } else {
+ struct tm tm_tomorrow;
+ gchar *time_text;
+ tm_tomorrow.tm_mday = sdate->tm_mday;
+ tm_tomorrow.tm_mon = sdate->tm_mon;
+ tm_tomorrow.tm_wday = sdate->tm_wday;
+ tm_tomorrow.tm_year = sdate->tm_year+1900;
+ tm_tomorrow.tm_hour = sdate->tm_hour;
+ orage_move_day(&tm_tomorrow, +1);
+ gtk_calendar_select_day(GTK_CALENDAR(meet->end_c),
+ tm_tomorrow.tm_mday);
+ gtk_calendar_select_month(GTK_CALENDAR(meet->end_c),
+ tm_tomorrow.tm_mon, tm_tomorrow.tm_year);
+
+ time_text = g_strdup_printf("%02d:%02d", 0, 0);
+ combobox_select_by_text(GTK_COMBO_BOX(meet->end_time), time_text);
+ g_free(time_text);
+ }
+ }
+ return meet;
+}
+
+VCalMeeting *vcal_meeting_create_hidden(VCalEvent *event)
+{
+ return vcal_meeting_create_real(event, FALSE);
+}
+
+gboolean vcal_meeting_send(VCalMeeting *meet)
+{
+ return send_meeting_cb(NULL, meet);
+}
+
+gboolean vcal_meeting_alert_check(gpointer data)
+{
+ GSList *events = NULL, *cur = NULL;
+
+ if (!vcalprefs.alert_enable)
+ return TRUE;
+
+ events = vcal_folder_get_waiting_events();
+
+ for (cur = events; cur; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+ time_t start, end, current;
+ gboolean warn = FALSE;
+
+ tzset();
+
+ start = icaltime_as_timet(icaltime_from_string(event->dtstart));
+ end = icaltime_as_timet(icaltime_from_string(event->dtend));
+ current = time(NULL);
+
+ if (start - current <= (vcalprefs.alert_delay*60)
+ && start - current + 60 > (vcalprefs.alert_delay*60)) {
+ warn = TRUE;
+ } else if (event->postponed - current <= (vcalprefs.alert_delay*60)
+ && event->postponed - current + 60 > (vcalprefs.alert_delay*60)) {
+ warn = TRUE;
+ }
+ if (warn) {
+ time_t tmpt = icaltime_as_timet((icaltime_from_string(event->dtstart)));
+ gchar *estart = NULL;
+ AlertValue aval;
+ int length = (end - start) / 60;
+ gchar *duration = NULL, *hours = NULL, *minutes = NULL;
+ gchar *message = NULL;
+ gchar *title = NULL;
+ gchar *label = NULL;
+ int postpone_min = 0;
+
+ tzset();
+
+ estart = g_strdup(ctime(&tmpt));
+
+ if (length >= 60)
+ hours = g_strdup_printf(ngettext("%d hour", "%d hours",
+ (length/60) > 1 ? 2 : 1), length/60);
+ if (length%60)
+ minutes = g_strdup_printf(ngettext("%d minute", "%d minutes",
+ length%60), length%60);
+
+ duration = g_strdup_printf("%s%s%s",
+ hours?hours:"",
+ hours && minutes ? " ":"",
+ minutes?minutes:"");
+
+ g_free(hours);
+ g_free(minutes);
+
+ title = g_strdup_printf(_("Upcoming event: %s"), event->summary);
+ message = g_strdup_printf(_("You have a meeting or event soon.\n"
+ "It starts at %s and ends %s later.\n"
+ "Location: %s\n"
+ "More information:\n\n"
+ "%s"),
+ estart,
+ duration,
+ event->location?event->location:"",
+ event->description);
+
+ g_free(duration);
+ g_free(estart);
+
+ postpone_min = (vcalprefs.alert_delay/2 > 15) ? 15: (vcalprefs.alert_delay/2);
+ if (postpone_min == 0)
+ postpone_min = 1;
+
+ label = g_strdup_printf(ngettext("Remind me in %d minute", "Remind me in %d minutes",
+ postpone_min > 1 ? 2:1),
+ postpone_min);
+ aval = alertpanel_full(title, message,
+ label, GTK_STOCK_OK, NULL, FALSE,
+ NULL, ALERT_NOTICE, G_ALERTDEFAULT);
+ g_free(label);
+
+ g_free(title);
+ g_free(message);
+
+ if (aval == G_ALERTDEFAULT) {
+ if (event->postponed == 0)
+ event->postponed = start + (postpone_min*60);
+ else
+ event->postponed += (postpone_min*60);
+ } else {
+ event->postponed = (time_t)0;
+ }
+ vcal_manager_save_event(event, FALSE);
+ }
+
+ vcal_manager_free_event((VCalEvent *)cur->data);
+ }
+
+ g_slist_free(events);
+
+ return TRUE;
+}
+
+void multisync_export(void)
+{
+ GSList *list = NULL;
+ gchar *path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", G_DIR_SEPARATOR_S,
+ "multisync", NULL);
+ GSList *files = NULL;
+ GSList *cur = NULL;
+ gchar *file = NULL;
+ gchar *tmp = NULL;
+ gint i = 0;
+ icalcomponent *calendar = NULL;
+ FILE *fp;
+
+ if (is_dir_exist(path))
+ remove_dir_recursive(path);
+ if (!is_dir_exist(path))
+ make_dir(path);
+ if (!is_dir_exist(path)) {
+ perror(path);
+ g_free(path);
+ return;
+ }
+
+ list = vcal_folder_get_waiting_events();
+ for (cur = list; cur; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+ file = g_strdup_printf("multisync%lu-%d", time(NULL), i);
+
+ i++;
+
+ calendar =
+ icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalproperty_new_version("2.0"),
+ icalproperty_new_prodid(
+ "-//Claws Mail//NONSGML Claws Mail Calendar//EN"),
+ icalproperty_new_calscale("GREGORIAN"),
+ 0
+ );
+ vcal_manager_event_dump(event, FALSE, FALSE, calendar, FALSE);
+ tmp = g_strconcat(path, G_DIR_SEPARATOR_S, file, NULL);
+ str_write_to_file(icalcomponent_as_ical_string(calendar), tmp);
+ g_free(tmp);
+ files = g_slist_append(files, file);
+ vcal_manager_free_event(event);
+ icalcomponent_free(calendar);
+ }
+
+ g_slist_free(list);
+
+ file = g_strconcat(path, G_DIR_SEPARATOR_S, "backup_entries", NULL);
+ fp = g_fopen(file, "wb");
+ g_free(file);
+ if (fp) {
+ for (cur = files; cur; cur = cur->next) {
+ file = (char *)cur->data;
+ if (fprintf(fp, "1 1 %s\n", file) < 0)
+ perror(file);
+ g_free(file);
+ }
+ if (fclose(fp) == EOF)
+ perror(file);
+ } else {
+ perror(file);
+ }
+ g_free(path);
+ g_slist_free(files);
+}
+
+gboolean vcal_meeting_export_calendar(const gchar *path,
+ const gchar *user, const gchar *pass,
+ gboolean automatic)
+{
+ GSList *list = vcal_folder_get_waiting_events();
+ GSList *subs = NULL;
+ GSList *cur;
+ icalcomponent *calendar = NULL;
+ gchar *file = NULL;
+ gchar *tmpfile = get_tmp_file();
+ gchar *internal_file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", G_DIR_SEPARATOR_S,
+ "internal.ics", NULL);
+
+ gboolean res = TRUE;
+ long filesize = 0;
+
+ multisync_export();
+
+ if (vcalprefs.export_subs && vcalprefs.export_enable)
+ subs = vcal_folder_get_webcal_events();
+
+ if (g_slist_length(list) == 0 && g_slist_length(subs) == 0) {
+ g_slist_free(list);
+ g_slist_free(subs);
+ if (!automatic) {
+ alertpanel_full(_("Empty calendar"),
+ _("There is nothing to export."),
+ GTK_STOCK_OK, NULL, NULL, FALSE,
+ NULL, ALERT_NOTICE, G_ALERTDEFAULT);
+ return FALSE;
+ } else {
+ str_write_to_file("", tmpfile);
+ goto putfile;
+ }
+ }
+
+ calendar =
+ icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalproperty_new_version("2.0"),
+ icalproperty_new_prodid(
+ "-//Claws Mail//NONSGML Claws Mail Calendar//EN"),
+ icalproperty_new_calscale("GREGORIAN"),
+ 0
+ );
+
+ for (cur = list; cur; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+ vcal_manager_event_dump(event, FALSE, FALSE, calendar, FALSE);
+ vcal_manager_free_event(event);
+ }
+
+ if (str_write_to_file(icalcomponent_as_ical_string(calendar), internal_file) < 0) {
+ g_warning("can't export internal cal\n");
+ }
+
+ g_free(internal_file);
+
+ for (cur = subs; cur; cur = cur->next) {
+ /* Not to be freed */
+ icalcomponent *event = (icalcomponent *)cur->data;
+ vcal_manager_icalevent_dump(event, NULL, calendar);
+ }
+
+ if (vcalprefs.export_enable || path == NULL) {
+ if (str_write_to_file(icalcomponent_as_ical_string(calendar), tmpfile) < 0) {
+ alertpanel_error(_("Could not export the calendar."));
+ g_free(tmpfile);
+ icalcomponent_free(calendar);
+ g_slist_free(list);
+ g_slist_free(subs);
+ return FALSE;
+ }
+ filesize = strlen(icalcomponent_as_ical_string(calendar));
+ }
+
+ icalcomponent_free(calendar);
+
+putfile:
+ g_slist_free(list);
+ g_slist_free(subs);
+
+ if (!path && !automatic)
+ file = filesel_select_file_save(_("Export calendar to ICS"), NULL);
+ else
+ file = g_strdup(path);
+
+ if (automatic && (!path || strlen(path) == 0 || !vcalprefs.export_enable)) {
+ g_free(tmpfile);
+ g_free(file);
+ return TRUE;
+ }
+
+ if (file
+ && strncmp(file, "http://", 7)
+ && strncmp(file, "https://", 8)
+ && strncmp(file, "webcal://", 9)
+ && strncmp(file, "ftp://", 6)) {
+ gchar *afile = NULL;
+ if (file[0] != G_DIR_SEPARATOR)
+ afile=g_strdup_printf("%s%s%s", get_home_dir(),
+ G_DIR_SEPARATOR_S, file);
+ else
+ afile=g_strdup(file);
+ if (move_file(tmpfile, afile, TRUE) != 0) {
+ log_error(LOG_PROTOCOL, _("Couldn't export calendar to '%s'\n"),
+ afile);
+ res = FALSE;
+ }
+ g_free(afile);
+ g_free(file);
+ } else if (file) {
+ FILE *fp = g_fopen(tmpfile, "rb");
+ if (!strncmp(file, "webcal://", 9)) {
+ gchar *tmp = g_strdup_printf("http://%s", file+9);
+ g_free(file);
+ file = tmp;
+ }
+ if (fp) {
+ res = vcal_curl_put(file, fp, filesize, user, pass);
+ fclose(fp);
+ }
+ g_free(file);
+ }
+ g_free(tmpfile);
+ return res;
+}
+
+gboolean vcal_meeting_export_freebusy(const gchar *path, const gchar *user,
+ const gchar *pass)
+{
+ GSList *list = vcal_folder_get_waiting_events();
+ GSList *cur;
+ icalcomponent *calendar = NULL, *timezone = NULL, *tzc = NULL, *vfreebusy = NULL;
+ gchar *file = NULL;
+ gchar *tmpfile = get_tmp_file();
+ gchar *internal_file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", G_DIR_SEPARATOR_S,
+ "internal.ifb", NULL);
+ time_t whole_start = time(NULL);
+ time_t whole_end = whole_start + (60*60*24*365);
+ gboolean res = TRUE;
+ struct icaltimetype itt_start, itt_end;
+ long filesize = 0;
+
+ multisync_export();
+
+ calendar =
+ icalcomponent_vanew(
+ ICAL_VCALENDAR_COMPONENT,
+ icalproperty_new_version("2.0"),
+ icalproperty_new_prodid(
+ "-//Claws Mail//NONSGML Claws Mail Calendar//EN"),
+ icalproperty_new_calscale("GREGORIAN"),
+ 0
+ );
+
+ timezone = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
+
+ icalcomponent_add_property(timezone,
+ icalproperty_new_tzid("UTC"));
+
+ tzc = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
+ icalcomponent_add_property(tzc,
+ icalproperty_new_dtstart(
+ icaltime_from_string("19700101T000000")));
+ icalcomponent_add_property(tzc,
+ icalproperty_new_tzoffsetfrom(0.0));
+ icalcomponent_add_property(tzc,
+ icalproperty_new_tzoffsetto(0.0));
+ icalcomponent_add_property(tzc,
+ icalproperty_new_tzname("Greenwich meridian time"));
+
+ icalcomponent_add_component(timezone, tzc);
+
+ icalcomponent_add_component(calendar, timezone);
+
+ itt_start = icaltime_from_timet(whole_start, FALSE);
+ itt_end = icaltime_from_timet(whole_end, FALSE);
+ itt_start.second = itt_start.minute = itt_start.hour = 0;
+ itt_end.second = 59; itt_end.minute = 59; itt_end.hour = 23;
+
+
+ vfreebusy =
+ icalcomponent_vanew(
+ ICAL_VFREEBUSY_COMPONENT,
+ icalproperty_vanew_dtstart(itt_start, 0),
+ icalproperty_vanew_dtend(itt_end, 0),
+ 0
+ );
+
+ debug_print("DTSTART:%s\nDTEND:%s\n",
+ icaltime_as_ical_string(itt_start),
+ icaltime_as_ical_string(itt_end));
+
+ for (cur = list; cur; cur = cur->next) {
+ VCalEvent *event = (VCalEvent *)cur->data;
+ icalproperty *prop;
+ struct icalperiodtype ipt;
+
+ ipt.start = icaltime_from_string(event->dtstart);
+ ipt.end = icaltime_from_string(event->dtend);
+ ipt.duration = icaltime_subtract(ipt.end, ipt.start);
+ if (icaltime_as_timet(ipt.start) <= icaltime_as_timet(itt_end)
+ && icaltime_as_timet(ipt.end) >= icaltime_as_timet(itt_start)) {
+ prop = icalproperty_new_freebusy(ipt);
+ icalcomponent_add_property(vfreebusy, prop);
+ }
+ vcal_manager_free_event(event);
+ }
+
+ icalcomponent_add_component(calendar, vfreebusy);
+
+ if (str_write_to_file(icalcomponent_as_ical_string(calendar), internal_file) < 0) {
+ g_warning("can't export freebusy\n");
+ }
+
+ g_free(internal_file);
+
+ if (vcalprefs.export_freebusy_enable) {
+ if (str_write_to_file(icalcomponent_as_ical_string(calendar), tmpfile) < 0) {
+ alertpanel_error(_("Could not export the freebusy info."));
+ g_free(tmpfile);
+ icalcomponent_free(calendar);
+ g_slist_free(list);
+ return FALSE;
+ }
+ filesize = strlen(icalcomponent_as_ical_string(calendar));
+ }
+
+ icalcomponent_free(calendar);
+ g_slist_free(list);
+
+ if ((!path || strlen(path) == 0 || !vcalprefs.export_freebusy_enable)) {
+ g_free(tmpfile);
+ return TRUE;
+ }
+ file = g_strdup(path);
+
+
+ if (file
+ && strncmp(file, "http://", 7)
+ && strncmp(file, "https://", 8)
+ && strncmp(file, "webcal://", 9)
+ && strncmp(file, "ftp://", 6)) {
+ gchar *afile = NULL;
+ if (file[0] != G_DIR_SEPARATOR)
+ afile=g_strdup_printf("%s%s%s", get_home_dir(),
+ G_DIR_SEPARATOR_S, file);
+ else
+ afile=g_strdup(file);
+ if (move_file(tmpfile, file, TRUE) != 0) {
+ log_error(LOG_PROTOCOL, _("Couldn't export free/busy to '%s'\n"),
+ afile);
+ res = FALSE;
+ }
+ g_free(afile);
+ g_free(file);
+ } else if (file) {
+ FILE *fp = g_fopen(tmpfile, "rb");
+ if (!strncmp(file, "webcal://", 9)) {
+ gchar *tmp = g_strdup_printf("http://%s", file+9);
+ g_free(file);
+ file = tmp;
+ }
+ if (fp) {
+ res = vcal_curl_put(file, fp, filesize, user, pass);
+ fclose(fp);
+ }
+ g_free(file);
+ }
+ g_free(tmpfile);
+ return res;
+}
diff --git a/src/plugins/vcalendar/vcal_meeting_gtk.h b/src/plugins/vcalendar/vcal_meeting_gtk.h
@@ -0,0 +1,39 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VCAL_MEETING_GTK_H__
+#define __VCAL_MEETING_GTK_H__
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include "vcal_manager.h"
+
+typedef struct _VCalMeeting VCalMeeting;
+typedef struct _VCalAttendee VCalAttendee;
+
+VCalMeeting *vcal_meeting_create(VCalEvent *event);
+VCalMeeting *vcal_meeting_create_hidden(VCalEvent *event);
+VCalMeeting *vcal_meeting_create_with_start(VCalEvent *event, struct tm *sdate);
+gboolean vcal_meeting_send(VCalMeeting *meet);
+gboolean vcal_meeting_alert_check(gpointer data);
+gboolean vcal_meeting_export_calendar(const gchar *path, const gchar *user, const gchar *pass,gboolean automatic);
+gboolean vcal_meeting_export_freebusy(const gchar *path, const gchar *user, const gchar *pass);
+gboolean attendee_available(VCalAttendee *attendee, const gchar *dtstart, const gchar *dtend, const gchar *contents);
+#endif
diff --git a/src/plugins/vcalendar/vcal_prefs.c b/src/plugins/vcalendar/vcal_prefs.c
@@ -0,0 +1,665 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "defs.h"
+
+#include "mainwindow.h"
+#include "prefs.h"
+#include "prefs_gtk.h"
+#include "prefswindow.h"
+#include "common/utils.h"
+
+#include "vcalendar.h"
+#include "vcal_prefs.h"
+#include "vcal_folder.h"
+
+#define PREFS_BLOCK_NAME "VCalendar"
+
+struct VcalendarPage
+{
+ PrefsPage page;
+
+ GtkWidget *alert_enable_btn;
+ GtkWidget *alert_delay_spinbtn;
+
+ GtkWidget *export_enable_btn;
+ GtkWidget *export_subs_btn;
+ GtkWidget *export_path_entry;
+ GtkWidget *export_command_entry;
+
+ GtkWidget *export_user_label;
+ GtkWidget *export_user_entry;
+ GtkWidget *export_pass_label;
+ GtkWidget *export_pass_entry;
+
+ GtkWidget *export_freebusy_enable_btn;
+ GtkWidget *export_freebusy_path_entry;
+ GtkWidget *export_freebusy_command_entry;
+
+ GtkWidget *export_freebusy_user_label;
+ GtkWidget *export_freebusy_user_entry;
+ GtkWidget *export_freebusy_pass_label;
+ GtkWidget *export_freebusy_pass_entry;
+
+ GtkWidget *freebusy_get_url_entry;
+};
+
+VcalendarPrefs vcalprefs;
+static struct VcalendarPage vcal_prefs_page;
+
+static PrefParam param[] = {
+ {"alert_delay", "10", &vcalprefs.alert_delay, P_INT,
+ NULL, NULL, NULL},
+ {"alert_enable", "FALSE", &vcalprefs.alert_enable, P_BOOL,
+ NULL, NULL, NULL},
+
+ {"export_enable", "FALSE", &vcalprefs.export_enable, P_BOOL,
+ NULL, NULL, NULL},
+ {"export_subs", "TRUE", &vcalprefs.export_subs, P_BOOL,
+ NULL, NULL, NULL},
+ {"export_path", "", &vcalprefs.export_path, P_STRING,
+ NULL, NULL, NULL},
+ {"export_command", NULL, &vcalprefs.export_command, P_STRING,
+ NULL, NULL, NULL},
+
+ {"export_user", "", &vcalprefs.export_user, P_STRING,
+ NULL, NULL, NULL},
+ {"export_pass", "", &vcalprefs.export_pass, P_PASSWORD,
+ NULL, NULL, NULL},
+
+ {"orage_registered", "FALSE", &vcalprefs.orage_registered, P_BOOL,
+ NULL, NULL, NULL},
+
+ {"export_freebusy_enable", "FALSE", &vcalprefs.export_freebusy_enable, P_BOOL,
+ NULL, NULL, NULL},
+ {"export_freebusy_path", "", &vcalprefs.export_freebusy_path, P_STRING,
+ NULL, NULL, NULL},
+ {"export_freebusy_command", NULL, &vcalprefs.export_freebusy_command, P_STRING,
+ NULL, NULL, NULL},
+ {"freebusy_get_url", NULL, &vcalprefs.freebusy_get_url, P_STRING,
+ NULL, NULL, NULL},
+
+ {"export_freebusy_user", "", &vcalprefs.export_freebusy_user, P_STRING,
+ NULL, NULL, NULL},
+ {"export_freebusy_pass", "", &vcalprefs.export_freebusy_pass, P_PASSWORD,
+ NULL, NULL, NULL},
+
+ {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
+};
+
+static void set_auth_sensitivity(struct VcalendarPage *page)
+{
+ const gchar *export_path, *export_freebusy_path;
+ gboolean export_enable, export_freebusy_enable;
+
+ export_enable = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(page->export_enable_btn));
+ export_freebusy_enable = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(page->export_freebusy_enable_btn));
+
+ export_path = gtk_entry_get_text(GTK_ENTRY(page->export_path_entry));
+ export_freebusy_path = gtk_entry_get_text(GTK_ENTRY(page->export_freebusy_path_entry));
+ if (export_enable && export_path &&
+ (!strncmp(export_path, "http://", 7) ||
+ !strncmp(export_path, "ftp://", 6) ||
+ !strncmp(export_path, "https://", 8) ||
+ !strncmp(export_path, "sftp://", 5) ||
+ !strncmp(export_path, "webcal://", 9))) {
+ gtk_widget_set_sensitive(page->export_user_label, TRUE);
+ gtk_widget_set_sensitive(page->export_user_entry, TRUE);
+ gtk_widget_set_sensitive(page->export_pass_label, TRUE);
+ gtk_widget_set_sensitive(page->export_pass_entry, TRUE);
+ } else {
+ gtk_widget_set_sensitive(page->export_user_label, FALSE);
+ gtk_widget_set_sensitive(page->export_user_entry, FALSE);
+ gtk_widget_set_sensitive(page->export_pass_label, FALSE);
+ gtk_widget_set_sensitive(page->export_pass_entry, FALSE);
+ }
+ if (export_freebusy_enable && export_freebusy_path &&
+ (!strncmp(export_freebusy_path, "http://", 7) ||
+ !strncmp(export_freebusy_path, "ftp://", 6) ||
+ !strncmp(export_freebusy_path, "https://", 8) ||
+ !strncmp(export_freebusy_path, "sftp://", 5) ||
+ !strncmp(export_freebusy_path, "webcal://", 9))) {
+ gtk_widget_set_sensitive(page->export_freebusy_user_label, TRUE);
+ gtk_widget_set_sensitive(page->export_freebusy_user_entry, TRUE);
+ gtk_widget_set_sensitive(page->export_freebusy_pass_label, TRUE);
+ gtk_widget_set_sensitive(page->export_freebusy_pass_entry, TRUE);
+ } else {
+ gtk_widget_set_sensitive(page->export_freebusy_user_label, FALSE);
+ gtk_widget_set_sensitive(page->export_freebusy_user_entry, FALSE);
+ gtk_widget_set_sensitive(page->export_freebusy_pass_label, FALSE);
+ gtk_widget_set_sensitive(page->export_freebusy_pass_entry, FALSE);
+ }
+}
+
+static void path_changed(GtkWidget *widget, gpointer data)
+{
+ set_auth_sensitivity((struct VcalendarPage *)data);
+}
+
+static gboolean orage_available(void)
+{
+ gchar *tmp = g_find_program_in_path("orage");
+ if (tmp) {
+ g_free(tmp);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void orage_register(gboolean reg)
+{
+ if (orage_available()) {
+ gchar *orage_argv[4];
+ gchar *cmdline = g_strdup_printf("%s%svcalendar%sinternal.ics",
+ get_rc_dir(), G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S);
+
+ debug_print("telling Orage %s us ...\n", reg?"about":"to forget");
+ orage_argv[0] = "orage";
+ orage_argv[1] = reg ? "--add-foreign":"--remove-foreign";
+ orage_argv[2] = cmdline;
+ orage_argv[3] = NULL;
+ g_spawn_async(NULL, (gchar **)orage_argv, NULL,
+ G_SPAWN_SEARCH_PATH|G_SPAWN_STDOUT_TO_DEV_NULL|
+ G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, NULL, FALSE);
+ g_free(cmdline);
+ }
+}
+
+void register_orage_checkbtn_toggled(GtkToggleButton *toggle_btn,
+ GtkWidget *widget)
+{
+ orage_register(gtk_toggle_button_get_active(toggle_btn));
+ vcalprefs.orage_registered = gtk_toggle_button_get_active(toggle_btn);
+}
+
+static void vcal_prefs_create_widget_func(PrefsPage * _page,
+ GtkWindow * window,
+ gpointer data)
+{
+ struct VcalendarPage *page = (struct VcalendarPage *) _page;
+
+ GtkWidget *vbox1, *vbox2, *vbox3;
+ GtkWidget *hbox1, *hbox2, *hbox3;
+
+ GtkWidget *frame_alert;
+ GtkWidget *alert_enable_checkbtn;
+ GtkObject *alert_enable_spinbtn_adj;
+ GtkWidget *alert_enable_spinbtn;
+ GtkWidget *label_alert_enable;
+
+ GtkWidget *frame_export;
+ GtkWidget *export_enable_checkbtn;
+ GtkWidget *export_subs_checkbtn;
+ GtkWidget *export_path_entry;
+ GtkWidget *export_command_label;
+ GtkWidget *export_command_entry;
+ GtkWidget *register_orage_checkbtn;
+
+ GtkWidget *export_user_label;
+ GtkWidget *export_user_entry;
+ GtkWidget *export_pass_label;
+ GtkWidget *export_pass_entry;
+
+ GtkWidget *frame_freebusy_export;
+ GtkWidget *export_freebusy_enable_checkbtn;
+ GtkWidget *export_freebusy_path_entry;
+ GtkWidget *export_freebusy_command_label;
+ GtkWidget *export_freebusy_command_entry;
+
+ GtkWidget *export_freebusy_user_label;
+ GtkWidget *export_freebusy_user_entry;
+ GtkWidget *export_freebusy_pass_label;
+ GtkWidget *export_freebusy_pass_entry;
+
+ GtkWidget *freebusy_get_url_label;
+ GtkWidget *freebusy_get_url_entry;
+
+ vbox1 = gtk_vbox_new (FALSE, VSPACING);
+ gtk_widget_show (vbox1);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER);
+
+ vbox2 = gtk_vbox_new (FALSE, 4);
+ gtk_widget_show (vbox2);
+ gtk_box_pack_start(GTK_BOX (vbox1), vbox2, FALSE, FALSE, 0);
+
+
+/* alert stuff */
+ PACK_FRAME(vbox2, frame_alert, _("Reminders"));
+ vbox3 = gtk_vbox_new (FALSE, 8);
+ gtk_widget_show (vbox3);
+ gtk_container_add (GTK_CONTAINER (frame_alert), vbox3);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox3), VBOX_BORDER);
+ hbox1 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox1);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox1, TRUE, TRUE, 0);
+
+ alert_enable_checkbtn = gtk_check_button_new_with_label(_("Alert me"));
+ gtk_widget_show (alert_enable_checkbtn);
+ gtk_box_pack_start(GTK_BOX (hbox1), alert_enable_checkbtn, FALSE, FALSE, 0);
+
+ alert_enable_spinbtn_adj = gtk_adjustment_new (10, 1, 24*60, 1, 10, 0);
+ alert_enable_spinbtn = gtk_spin_button_new
+ (GTK_ADJUSTMENT (alert_enable_spinbtn_adj), 1, 0);
+ gtk_widget_set_size_request (alert_enable_spinbtn, 64, -1);
+ gtk_widget_show (alert_enable_spinbtn);
+ gtk_box_pack_start(GTK_BOX (hbox1), alert_enable_spinbtn, FALSE, FALSE, 0);
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (alert_enable_spinbtn), TRUE);
+
+ label_alert_enable = gtk_label_new(_("minutes before an event"));
+ gtk_widget_show (label_alert_enable);
+ gtk_box_pack_start(GTK_BOX (hbox1), label_alert_enable, FALSE, FALSE, 0);
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(alert_enable_checkbtn),
+ vcalprefs.alert_enable);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(alert_enable_spinbtn),
+ vcalprefs.alert_delay);
+ SET_TOGGLE_SENSITIVITY(alert_enable_checkbtn, alert_enable_spinbtn);
+
+/* calendar export */
+/* export enable + path stuff */
+ PACK_FRAME(vbox2, frame_export, _("Calendar export"));
+ vbox3 = gtk_vbox_new (FALSE, 8);
+ gtk_widget_show (vbox3);
+ gtk_container_add (GTK_CONTAINER (frame_export), vbox3);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox3), VBOX_BORDER);
+
+/* export path */
+ hbox2 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox2);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox2, TRUE, TRUE, 0);
+
+ export_enable_checkbtn = gtk_check_button_new_with_label(_("Automatically export calendar to"));
+ gtk_widget_show(export_enable_checkbtn);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_enable_checkbtn, FALSE, FALSE, 0);
+
+ export_path_entry = gtk_entry_new();
+ gtk_widget_show(export_path_entry);
+ gtk_box_pack_start(GTK_BOX(hbox2), export_path_entry, TRUE, TRUE, 0);
+ SET_TOGGLE_SENSITIVITY(export_enable_checkbtn, export_path_entry);
+ CLAWS_SET_TIP(export_enable_checkbtn,
+ _("You can export to a local file or URL"));
+ CLAWS_SET_TIP(export_path_entry,
+ _("Specify a local file or URL "
+ "(http://server/path/file.ics)"));
+
+/* export auth */
+ hbox2 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox2);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox2, TRUE, TRUE, 0);
+
+ export_user_label = gtk_label_new(_("User ID"));
+ gtk_widget_show(export_user_label);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_user_label, FALSE, FALSE, 0);
+
+ export_user_entry = gtk_entry_new();
+ gtk_widget_show(export_user_entry);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_user_entry, FALSE, FALSE, 0);
+
+ export_pass_label = gtk_label_new(_("Password"));
+ gtk_widget_show(export_pass_label);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_pass_label, FALSE, FALSE, 0);
+
+ export_pass_entry = gtk_entry_new();
+ gtk_entry_set_visibility(GTK_ENTRY(export_pass_entry), FALSE);
+ gtk_widget_show(export_pass_entry);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_pass_entry, FALSE, FALSE, 0);
+
+/* export subscriptions too */
+ hbox2 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox2);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox2, TRUE, TRUE, 0);
+
+ export_subs_checkbtn = gtk_check_button_new_with_label(_("Include webcal subscriptions in export"));
+ gtk_widget_show(export_subs_checkbtn);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_subs_checkbtn, FALSE, FALSE, 0);
+ SET_TOGGLE_SENSITIVITY(export_enable_checkbtn, export_subs_checkbtn);
+
+/* run-command after export stuff */
+ hbox3 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox3);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox3, TRUE, TRUE, 0);
+
+ export_command_label = gtk_label_new(_("Command to run after calendar export"));
+ gtk_widget_show(export_command_label);
+ gtk_box_pack_start(GTK_BOX (hbox3), export_command_label, FALSE, FALSE, 0);
+ SET_TOGGLE_SENSITIVITY(export_enable_checkbtn, export_command_label);
+
+ export_command_entry = gtk_entry_new();
+ gtk_widget_show(export_command_entry);
+ gtk_box_pack_start(GTK_BOX (hbox3), export_command_entry, TRUE, TRUE, 0);
+ SET_TOGGLE_SENSITIVITY(export_enable_checkbtn, export_command_entry);
+
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(export_enable_checkbtn),
+ vcalprefs.export_enable);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(export_subs_checkbtn),
+ vcalprefs.export_subs);
+ if (vcalprefs.export_path == NULL || *vcalprefs.export_path == '\0')
+ vcalprefs.export_path = g_strconcat(get_rc_dir(),
+ G_DIR_SEPARATOR_S,
+ "claws-mail.ics", NULL);
+ if (vcalprefs.export_command == NULL)
+ vcalprefs.export_command = g_strdup("");
+ gtk_entry_set_text(GTK_ENTRY(export_path_entry),
+ vcalprefs.export_path);
+ gtk_entry_set_text(GTK_ENTRY(export_command_entry),
+ vcalprefs.export_command);
+
+ hbox3 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox3);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox3, TRUE, TRUE, 0);
+ register_orage_checkbtn = gtk_check_button_new_with_label(_("Register Claws' calendar in XFCE's Orage clock"));
+ CLAWS_SET_TIP(register_orage_checkbtn,
+ _("Allows Orage (version greater than 4.4) to see Claws Mail's calendar"));
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(register_orage_checkbtn),
+ vcalprefs.orage_registered);
+ gtk_widget_set_sensitive(register_orage_checkbtn, orage_available());
+ g_signal_connect(G_OBJECT(register_orage_checkbtn), "toggled",
+ G_CALLBACK(register_orage_checkbtn_toggled), NULL);
+ gtk_widget_show (register_orage_checkbtn);
+ gtk_box_pack_start(GTK_BOX (hbox3), register_orage_checkbtn, TRUE, TRUE, 0);
+
+/* freebusy export */
+/* export enable + path stuff */
+ PACK_FRAME(vbox2, frame_freebusy_export, _("Free/Busy information"));
+ vbox3 = gtk_vbox_new (FALSE, 8);
+ gtk_widget_show (vbox3);
+ gtk_container_add (GTK_CONTAINER (frame_freebusy_export), vbox3);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox3), VBOX_BORDER);
+
+/* export */
+ hbox2 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox2);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox2, TRUE, TRUE, 0);
+
+ export_freebusy_enable_checkbtn = gtk_check_button_new_with_label(
+ _("Automatically export free/busy status to"));
+ gtk_widget_show(export_freebusy_enable_checkbtn);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_freebusy_enable_checkbtn, FALSE, FALSE, 0);
+
+ export_freebusy_path_entry = gtk_entry_new();
+ gtk_widget_show(export_freebusy_path_entry);
+ gtk_box_pack_start(GTK_BOX(hbox2), export_freebusy_path_entry, TRUE, TRUE, 0);
+ SET_TOGGLE_SENSITIVITY(export_freebusy_enable_checkbtn, export_freebusy_path_entry);
+ CLAWS_SET_TIP(export_freebusy_enable_checkbtn,
+ _("You can export to a local file or URL"));
+ CLAWS_SET_TIP(export_freebusy_path_entry,
+ _("Specify a local file or URL "
+ "(http://server/path/file.ifb)"));
+
+/* auth */
+ hbox2 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox2);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox2, TRUE, TRUE, 0);
+
+ export_freebusy_user_label = gtk_label_new(_("User ID"));
+ gtk_widget_show(export_freebusy_user_label);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_freebusy_user_label, FALSE, FALSE, 0);
+
+ export_freebusy_user_entry = gtk_entry_new();
+ gtk_widget_show(export_freebusy_user_entry);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_freebusy_user_entry, FALSE, FALSE, 0);
+
+ export_freebusy_pass_label = gtk_label_new(_("Password"));
+ gtk_widget_show(export_freebusy_pass_label);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_freebusy_pass_label, FALSE, FALSE, 0);
+
+ export_freebusy_pass_entry = gtk_entry_new();
+ gtk_entry_set_visibility(GTK_ENTRY(export_freebusy_pass_entry), FALSE);
+ gtk_widget_show(export_freebusy_pass_entry);
+ gtk_box_pack_start(GTK_BOX (hbox2), export_freebusy_pass_entry, FALSE, FALSE, 0);
+
+/* run-command after export stuff */
+ hbox3 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox3);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox3, TRUE, TRUE, 0);
+
+ export_freebusy_command_label = gtk_label_new(_("Command to run after free/busy status export"));
+ gtk_widget_show(export_freebusy_command_label);
+ gtk_box_pack_start(GTK_BOX (hbox3), export_freebusy_command_label, FALSE, FALSE, 0);
+ SET_TOGGLE_SENSITIVITY(export_freebusy_enable_checkbtn, export_freebusy_command_label);
+ export_freebusy_command_entry = gtk_entry_new();
+ gtk_widget_show(export_freebusy_command_entry);
+ gtk_box_pack_start(GTK_BOX (hbox3), export_freebusy_command_entry, TRUE, TRUE, 0);
+ SET_TOGGLE_SENSITIVITY(export_freebusy_enable_checkbtn, export_freebusy_command_entry);
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(export_freebusy_enable_checkbtn),
+ vcalprefs.export_freebusy_enable);
+ if (vcalprefs.export_freebusy_path == NULL ||
+ *vcalprefs.export_freebusy_path == '\0')
+ vcalprefs.export_freebusy_path = g_strconcat(get_rc_dir(),
+ G_DIR_SEPARATOR_S,
+ "claws-mail.ifb", NULL);
+ if (vcalprefs.export_freebusy_command == NULL)
+ vcalprefs.export_freebusy_command = g_strdup("");
+ if (vcalprefs.freebusy_get_url == NULL)
+ vcalprefs.freebusy_get_url = g_strdup("");
+
+/* free/busy import */
+ hbox2 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox2);
+ gtk_box_pack_start(GTK_BOX (vbox3), hbox2, TRUE, TRUE, 0);
+
+ freebusy_get_url_label = gtk_label_new(
+ _("Get free/busy status of others from"));
+ gtk_widget_show(freebusy_get_url_label);
+ gtk_box_pack_start(GTK_BOX (hbox2), freebusy_get_url_label, FALSE, FALSE, 0);
+
+ freebusy_get_url_entry = gtk_entry_new();
+ gtk_widget_show(freebusy_get_url_entry);
+ gtk_box_pack_start(GTK_BOX(hbox2), freebusy_get_url_entry, TRUE, TRUE, 0);
+ CLAWS_SET_TIP(freebusy_get_url_entry,
+ _("Specify a local file or URL "
+ "(http://server/path/file.ifb). Use %u "
+ "for the left part of the email address, %d for "
+ "the domain"));
+
+ gtk_entry_set_text(GTK_ENTRY(export_freebusy_path_entry),
+ vcalprefs.export_freebusy_path);
+ gtk_entry_set_text(GTK_ENTRY(export_freebusy_command_entry),
+ vcalprefs.export_freebusy_command);
+
+ gtk_entry_set_text(GTK_ENTRY(freebusy_get_url_entry),
+ vcalprefs.freebusy_get_url);
+
+ if (!vcalprefs.export_user)
+ vcalprefs.export_user = g_strdup("");
+ if (!vcalprefs.export_pass)
+ vcalprefs.export_pass = g_strdup("");
+ if (!vcalprefs.export_freebusy_user)
+ vcalprefs.export_freebusy_user = g_strdup("");
+ if (!vcalprefs.export_freebusy_pass)
+ vcalprefs.export_freebusy_pass = g_strdup("");
+
+ gtk_entry_set_text(GTK_ENTRY(export_user_entry), vcalprefs.export_user);
+ gtk_entry_set_text(GTK_ENTRY(export_pass_entry), vcalprefs.export_pass);
+ gtk_entry_set_text(GTK_ENTRY(export_freebusy_user_entry), vcalprefs.export_freebusy_user);
+ gtk_entry_set_text(GTK_ENTRY(export_freebusy_pass_entry), vcalprefs.export_freebusy_pass);
+
+ g_signal_connect(G_OBJECT(export_enable_checkbtn),
+ "toggled", G_CALLBACK(path_changed), page);
+ g_signal_connect(G_OBJECT(export_freebusy_enable_checkbtn),
+ "toggled", G_CALLBACK(path_changed), page);
+ g_signal_connect(G_OBJECT(export_path_entry),
+ "changed", G_CALLBACK(path_changed), page);
+ g_signal_connect(G_OBJECT(export_freebusy_path_entry),
+ "changed", G_CALLBACK(path_changed), page);
+
+ page->alert_enable_btn = alert_enable_checkbtn;
+ page->alert_delay_spinbtn = alert_enable_spinbtn;
+
+ page->export_enable_btn = export_enable_checkbtn;
+ page->export_subs_btn = export_subs_checkbtn;
+ page->export_path_entry = export_path_entry;
+ page->export_command_entry = export_command_entry;
+
+ page->export_freebusy_enable_btn = export_freebusy_enable_checkbtn;
+ page->export_freebusy_path_entry = export_freebusy_path_entry;
+ page->export_freebusy_command_entry = export_freebusy_command_entry;
+
+ page->export_user_label = export_user_label;
+ page->export_user_entry = export_user_entry;
+ page->export_pass_label = export_pass_label;
+ page->export_pass_entry = export_pass_entry;
+
+ page->export_freebusy_user_label = export_freebusy_user_label;
+ page->export_freebusy_user_entry = export_freebusy_user_entry;
+ page->export_freebusy_pass_label = export_freebusy_pass_label;
+ page->export_freebusy_pass_entry = export_freebusy_pass_entry;
+
+ set_auth_sensitivity(page);
+
+ page->freebusy_get_url_entry = freebusy_get_url_entry;
+
+ page->page.widget = vbox1;
+}
+
+static void vcal_prefs_destroy_widget_func(PrefsPage *_page)
+{
+}
+
+void vcal_prefs_save(void)
+{
+ PrefFile *pfile;
+ gchar *rcpath;
+ rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
+ pfile = prefs_write_open(rcpath);
+ g_free(rcpath);
+ if (!pfile || (prefs_set_block_label(pfile, PREFS_BLOCK_NAME) < 0))
+ return;
+
+ if (prefs_write_param(param, pfile->fp) < 0) {
+ g_warning("failed to write Vcalendar configuration to file\n");
+ prefs_file_close_revert(pfile);
+ return;
+ }
+ if (fprintf(pfile->fp, "\n") < 0) {
+ FILE_OP_ERROR(rcpath, "fprintf");
+ prefs_file_close_revert(pfile);
+ } else
+ prefs_file_close(pfile);
+}
+
+static void vcal_prefs_save_func(PrefsPage * _page)
+{
+ struct VcalendarPage *page = (struct VcalendarPage *) _page;
+
+/* alert */
+ vcalprefs.alert_enable =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+ (page->alert_enable_btn));
+ vcalprefs.alert_delay =
+ gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON
+ (page->alert_delay_spinbtn));
+
+/* calendar export */
+ vcalprefs.export_enable =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+ (page->export_enable_btn));
+
+ vcalprefs.export_subs =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+ (page->export_subs_btn));
+
+ g_free(vcalprefs.export_path);
+ vcalprefs.export_path =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_path_entry), 0, -1);
+
+ g_free(vcalprefs.export_command);
+ vcalprefs.export_command =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_command_entry), 0, -1);
+
+ g_free(vcalprefs.export_user);
+ vcalprefs.export_user =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_user_entry), 0, -1);
+ g_free(vcalprefs.export_pass);
+ vcalprefs.export_pass =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_pass_entry), 0, -1);
+
+/* free/busy export */
+ vcalprefs.export_freebusy_enable =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+ (page->export_freebusy_enable_btn));
+
+ g_free(vcalprefs.export_freebusy_path);
+ vcalprefs.export_freebusy_path =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_freebusy_path_entry), 0, -1);
+
+ g_free(vcalprefs.export_freebusy_command);
+ vcalprefs.export_freebusy_command =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_freebusy_command_entry), 0, -1);
+
+ g_free(vcalprefs.export_freebusy_user);
+ vcalprefs.export_freebusy_user =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_freebusy_user_entry), 0, -1);
+ g_free(vcalprefs.export_freebusy_pass);
+ vcalprefs.export_freebusy_pass =
+ gtk_editable_get_chars(GTK_EDITABLE(page->export_freebusy_pass_entry), 0, -1);
+
+
+/* free/busy import */
+ g_free(vcalprefs.freebusy_get_url);
+ vcalprefs.freebusy_get_url =
+ gtk_editable_get_chars(GTK_EDITABLE(page->freebusy_get_url_entry), 0, -1);
+
+
+ vcal_prefs_save();
+ vcal_folder_export(NULL);
+}
+
+void vcal_prefs_init(void)
+{
+ static gchar *path[3];
+ gchar *rcpath;
+
+ path[0] = _("Plugins");
+ path[1] = _("vCalendar");
+ path[2] = NULL;
+
+ prefs_set_default(param);
+ rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
+ prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
+ g_free(rcpath);
+
+ vcal_prefs_page.page.path = path;
+ vcal_prefs_page.page.create_widget = vcal_prefs_create_widget_func;
+ vcal_prefs_page.page.destroy_widget = vcal_prefs_destroy_widget_func;
+ vcal_prefs_page.page.save_page = vcal_prefs_save_func;
+
+ prefs_gtk_register_page((PrefsPage *) &vcal_prefs_page);
+}
+
+void vcal_prefs_done(void)
+{
+ prefs_gtk_unregister_page((PrefsPage *) &vcal_prefs_page);
+}
diff --git a/src/plugins/vcalendar/vcal_prefs.h b/src/plugins/vcalendar/vcal_prefs.h
@@ -0,0 +1,52 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef VCALPREFS_H
+#define VCALPREFS_H
+
+#include <glib.h>
+
+typedef struct _VcalendarPrefs VcalendarPrefs;
+
+struct _VcalendarPrefs
+{
+ gboolean alert_enable;
+ gint alert_delay;
+ gboolean export_enable;
+ gboolean export_freebusy_enable;
+ gboolean export_subs;
+ gchar *export_path;
+ gchar *export_freebusy_path;
+ gchar *export_command;
+ gchar *export_user;
+ gchar *export_pass;
+ gchar *export_freebusy_command;
+ gchar *freebusy_get_url;
+ gchar *export_freebusy_user;
+ gchar *export_freebusy_pass;
+ gboolean orage_registered;
+};
+
+extern VcalendarPrefs vcalprefs;
+
+void vcal_prefs_init (void);
+void vcal_prefs_done (void);
+void vcal_prefs_save (void);
+#endif
diff --git a/src/plugins/vcalendar/vcalendar.c b/src/plugins/vcalendar/vcalendar.c
@@ -0,0 +1,1417 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <stddef.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <ical.h>
+#include <gtk/gtk.h>
+
+#if USE_PTHREAD
+#include "pthread.h"
+#endif
+
+#include "folder.h"
+#include "folder_item_prefs.h"
+#include "mimeview.h"
+#include "utils.h"
+#include "vcalendar.h"
+#include "vcal_manager.h"
+#include "vcal_folder.h"
+#include "vcal_meeting_gtk.h"
+#include "vcal_interface.h"
+#include "prefs_account.h"
+#include "prefs_common.h"
+#include "menu.h"
+#include "account.h"
+#include "codeconv.h"
+#include "xml.h"
+#include "xmlprops.h"
+#include "alertpanel.h"
+#include "vcal_prefs.h"
+#include "statusbar.h"
+#include "timing.h"
+#include "inc.h"
+
+MimeViewerFactory vcal_viewer_factory;
+
+static void create_meeting_from_message_cb_ui(GtkAction *action, gpointer data);
+
+static GdkColor uri_color = {
+ (gulong)0,
+ (gushort)0,
+ (gushort)0,
+ (gushort)0
+};
+
+struct _VCalViewer
+{
+ MimeViewer mimeviewer;
+
+ gchar *file;
+ MimeInfo *mimeinfo;
+ gchar *tmpfile;
+ VCalEvent *event;
+
+ GtkWidget *scrolledwin;
+ GtkWidget *table;
+ GtkWidget *type;
+ GtkWidget *who;
+ GtkWidget *start;
+ GtkWidget *end;
+ GtkWidget *location;
+ GtkWidget *summary;
+ GtkWidget *description;
+ gchar *url;
+ GtkWidget *answer;
+ GtkWidget *button;
+ GtkWidget *reedit;
+ GtkWidget *cancel;
+ GtkWidget *uribtn;
+ GtkWidget *attendees;
+ GtkWidget *unavail_box;
+};
+
+static GtkActionEntry vcalendar_main_menu[] = {{
+ "Message/CreateMeeting",
+ NULL, N_("Create meeting from message..."), NULL, NULL, G_CALLBACK(create_meeting_from_message_cb_ui)
+}};
+
+static void create_meeting_from_message_cb_ui(GtkAction *action, gpointer data)
+{
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ SummaryView *summaryview = mainwin->summaryview;
+ GSList *msglist = summary_get_selected_msg_list(summaryview);
+ FolderItem *item = NULL;
+ GSList *cur;
+ gchar *msg;
+ gint total=0;
+
+ if (summary_is_locked(summaryview) || !msglist) {
+ if (msglist)
+ g_slist_free(msglist);
+ return;
+ }
+ total = g_slist_length(msglist);
+
+ msg = g_strdup_printf(_("You are about to create %d "
+ "meetings, one by one. Do you "
+ "want to continue?"),
+ total);
+ if (total > 9
+ && alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, "+" GTK_STOCK_YES, NULL)
+ != G_ALERTALTERNATE) {
+ g_free(msg);
+ return;
+ }
+ g_free(msg);
+
+ main_window_cursor_wait(summaryview->mainwin);
+ gtk_cmclist_freeze(GTK_CMCLIST(summaryview->ctree));
+ folder_item_update_freeze();
+ inc_lock();
+
+ item = summaryview->folder_item;
+
+ STATUSBAR_PUSH(mainwin, _("Creating meeting..."));
+
+ for (cur = msglist; cur; cur = cur->next) {
+ MsgInfo *msginfo = procmsg_msginfo_get_full_info((MsgInfo *)cur->data);
+ VCalEvent *event = NULL;
+ FILE *fp = NULL;
+
+ if (MSG_IS_ENCRYPTED(msginfo->flags)) {
+ fp = procmime_get_first_encrypted_text_content(msginfo);
+ } else {
+ fp = procmime_get_first_text_content(msginfo);
+ }
+
+ if (fp) {
+ gchar uid[256];
+ time_t t = time(NULL);
+ time_t t2 = t+3600;
+ gchar *org = NULL;
+ gchar *orgname = NULL;
+ gchar *summary = g_strdup(msginfo->subject ? msginfo->subject:_("no subject"));
+ gchar *description = file_read_stream_to_str(fp);
+ gchar *dtstart = g_strdup(icaltime_as_ical_string(icaltime_from_timet(t, FALSE)));
+ gchar *dtend = g_strdup(icaltime_as_ical_string(icaltime_from_timet(t2, FALSE)));
+ gchar *recur = NULL;
+ gchar *tzid = g_strdup("UTC");
+ gchar *url = NULL;
+ gint method = ICAL_METHOD_REQUEST;
+ gint sequence = 1;
+ PrefsAccount *account = NULL;
+
+ fclose(fp);
+
+ if (item && item->prefs && item->prefs->enable_default_account)
+ account = account_find_from_id(item->prefs->default_account);
+
+ if (!account)
+ account = account_get_cur_account();
+
+ if (!account)
+ goto bail;
+
+ org = g_strdup(account->address);
+
+ if (account->set_domain && account->domain) {
+ g_snprintf(uid, sizeof(uid), "%s", account->domain);
+ } else if (!strncmp(get_domain_name(), "localhost", strlen("localhost"))) {
+ g_snprintf(uid, sizeof(uid), "%s",
+ strchr(account->address, '@') ?
+ strchr(account->address, '@')+1 :
+ account->address);
+ } else {
+ g_snprintf(uid, sizeof(uid), "%s", "");
+ }
+ generate_msgid(uid, 255, account->address);
+
+ event = vcal_manager_new_event(uid,
+ org, NULL, NULL/*location*/, summary, description,
+ dtstart, dtend, recur, tzid, url, method, sequence,
+ ICAL_VTODO_COMPONENT);
+
+ /* hack to get default hours */
+ g_free(event->dtstart);
+ g_free(event->dtend);
+ event->dtstart = NULL;
+ event->dtend = NULL;
+
+ vcal_meeting_create(event);
+ vcal_manager_free_event(event);
+
+bail:
+ g_free(org);
+ g_free(orgname);
+ g_free(summary);
+ g_free(description);
+ g_free(dtstart);
+ g_free(dtend);
+ g_free(recur);
+ g_free(tzid);
+ g_free(url);
+ }
+
+ procmsg_msginfo_free(msginfo);
+ }
+
+ statusbar_progress_all(0,0,0);
+ STATUSBAR_POP(mainwin);
+ inc_unlock();
+ folder_item_update_thaw();
+ gtk_cmclist_thaw(GTK_CMCLIST(summaryview->ctree));
+ main_window_cursor_normal(summaryview->mainwin);
+ g_slist_free(msglist);
+}
+
+static gchar *get_tmpfile(VCalViewer *vcalviewer)
+{
+ gchar *tmpfile = NULL;
+
+ if (!vcalviewer->tmpfile) {
+ tmpfile = procmime_get_tmp_file_name(vcalviewer->mimeinfo);
+ debug_print("creating %s\n", tmpfile);
+
+ if (procmime_get_part(tmpfile, vcalviewer->mimeinfo) < 0) {
+ g_warning("Can't get mimepart file");
+ g_free(tmpfile);
+ return NULL;
+ }
+ vcalviewer->tmpfile = tmpfile;
+ }
+
+ return vcalviewer->tmpfile;
+}
+
+static GtkWidget *vcal_viewer_get_widget(MimeViewer *_mimeviewer)
+{
+ VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
+
+ debug_print("vcal_viewer_get_widget\n");
+ gtk_widget_show_all(vcalviewer->scrolledwin);
+ return vcalviewer->scrolledwin;
+}
+
+static void vcal_viewer_clear_viewer(MimeViewer *_mimeviewer)
+{
+ VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
+
+ debug_print("vcal_viewer_clear_viewer\n");
+
+ g_free(vcalviewer->file);
+ vcalviewer->file = NULL;
+ if (vcalviewer->tmpfile) {
+ debug_print("unlinking %s\n", vcalviewer->tmpfile);
+ g_unlink(vcalviewer->tmpfile);
+ g_free(vcalviewer->tmpfile);
+ vcalviewer->tmpfile = NULL;
+ }
+ vcalviewer->mimeinfo = NULL;
+}
+
+static VCalEvent *vcalviewer_get_component(const gchar *file, const gchar *charset)
+{
+ gchar *compstr = NULL;
+ VCalEvent *event = NULL;
+ FILE *fp;
+ GByteArray *array;
+ gchar buf[BUFSIZ];
+ gint n_read;
+
+ g_return_val_if_fail(file != NULL, NULL);
+
+ if ((fp = g_fopen(file, "rb")) == NULL) {
+ FILE_OP_ERROR(file, "g_fopen");
+ return NULL;
+ }
+
+ array = g_byte_array_new();
+
+ while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
+ if (n_read < sizeof(buf) && ferror(fp))
+ break;
+ g_byte_array_append(array, (guchar *)buf, n_read);
+ }
+
+ if (ferror(fp)) {
+ FILE_OP_ERROR("file stream", "fread");
+ g_byte_array_free(array, TRUE);
+ fclose(fp);
+ return NULL;
+ }
+
+ buf[0] = '\0';
+ g_byte_array_append(array, (guchar *)buf, 1);
+ compstr = (gchar *)array->data;
+ g_byte_array_free(array, FALSE);
+
+ fclose(fp);
+
+ if (compstr) {
+ event = vcal_get_event_from_ical(compstr, charset);
+ g_free(compstr);
+ }
+
+ return event;
+}
+
+#define GTK_LABEL_SET_TEXT_TRIMMED(label, text) { \
+ gchar *tmplbl = strretchomp(g_strdup(text)); \
+ gtk_label_set_text(label, tmplbl); \
+ g_free(tmplbl); \
+}
+
+static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, enum icalproperty_method method);
+
+static void vcalviewer_reset(VCalViewer *vcalviewer)
+{
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
+ g_free(vcalviewer->url);
+ vcalviewer->url = NULL;
+ gtk_widget_hide(vcalviewer->uribtn);
+ vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_CANCEL);
+}
+
+static void vcalviewer_show_error(VCalViewer *vcalviewer, const gchar *msg)
+{
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), msg);
+}
+
+static void vcalviewer_hide_error(VCalViewer *vcalviewer)
+{
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
+}
+
+static void vcalviewer_show_unavailable(VCalViewer *vcalviewer, gboolean visi)
+{
+ if (visi)
+ gtk_widget_show_all(vcalviewer->unavail_box);
+ else
+ gtk_widget_hide(vcalviewer->unavail_box);
+}
+
+static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, enum icalproperty_method method)
+{
+ int i = 0;
+
+ gtk_widget_hide(vcalviewer->reedit);
+ gtk_widget_hide(vcalviewer->cancel);
+ gtk_widget_hide(vcalviewer->answer);
+ gtk_widget_hide(vcalviewer->button);
+
+ for (i = 0; i < 3; i++)
+ gtk_combo_box_remove_text(GTK_COMBO_BOX(vcalviewer->answer), 0);
+
+ vcalviewer_show_unavailable(vcalviewer, FALSE);
+
+ if (method == ICAL_METHOD_REQUEST && event && !event->rec_occurence) {
+ PrefsAccount *account = vcal_manager_get_account_from_event(event);
+
+ if (!account)
+ account = vcal_manager_get_account_from_event(vcalviewer->event);
+
+ if (!account && event) {
+ account = account_get_default();
+ vcal_manager_update_answer(event, account->address,
+ account->name,
+ ICAL_PARTSTAT_NEEDSACTION,
+ ICAL_CUTYPE_INDIVIDUAL);
+ }
+ if (account) {
+ gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Accept"));
+ gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Tentatively accept"));
+ gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Decline"));
+ gtk_widget_set_sensitive(vcalviewer->answer, TRUE);
+ gtk_widget_set_sensitive(vcalviewer->button, TRUE);
+ gtk_widget_show(vcalviewer->answer);
+ gtk_widget_show(vcalviewer->button);
+ } else {
+ gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), "-");
+ gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
+ gtk_widget_set_sensitive(vcalviewer->button, FALSE);
+ }
+ } else {
+ gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), "-");
+ gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
+ gtk_widget_set_sensitive(vcalviewer->button, FALSE);
+ }
+ gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
+
+ if (event && event->method == ICAL_METHOD_REQUEST) {
+ PrefsAccount *account = vcal_manager_get_account_from_event(event);
+ gchar *internal_ifb = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", G_DIR_SEPARATOR_S,
+ "internal.ifb", NULL);
+ gchar *myfb = file_read_to_str(internal_ifb);
+ g_free(internal_ifb);
+ if (account) {
+ enum icalparameter_partstat answer =
+ vcal_manager_get_reply_for_attendee(event, account->address);
+
+ if (answer == ICAL_PARTSTAT_ACCEPTED)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
+ if (answer == ICAL_PARTSTAT_TENTATIVE)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 1);
+ if (answer == ICAL_PARTSTAT_DECLINED)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 2);
+ if (event->dtstart && event->dtend && myfb && *myfb
+ && answer != ICAL_PARTSTAT_ACCEPTED
+ && answer != ICAL_PARTSTAT_TENTATIVE) {
+ if (!attendee_available(NULL, event->dtstart, event->dtend, myfb))
+ vcalviewer_show_unavailable(vcalviewer, TRUE);
+ }
+ }
+ g_free(myfb);
+ }
+
+ g_free(vcalviewer->url);
+ if (event && event->url && *(event->url)) {
+ vcalviewer->url = g_strdup(event->url);
+ gtk_widget_show(vcalviewer->uribtn);
+ } else {
+ vcalviewer->url = NULL;
+ gtk_widget_hide(vcalviewer->uribtn);
+ }
+}
+
+static FolderItem *vcalendar_get_current_item(void)
+{
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ FolderItem *item = NULL;
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+
+ if (mainwin) {
+ item = mainwin->summaryview->folder_item;
+ if (item->folder == folder)
+ return item;
+ else
+ return folder->inbox;
+ } else {
+ return NULL;
+ }
+}
+
+void vcalviewer_display_event (VCalViewer *vcalviewer, VCalEvent *event)
+{
+ GSList *list = NULL;
+ gchar *attendees = NULL;
+ gboolean mine = FALSE;
+ gchar *label = NULL;
+ gboolean save_evt = FALSE;
+ FolderItem *item = vcalendar_get_current_item();
+ if (!event)
+ return;
+ if (!vcalviewer)
+ return;
+
+/* general */
+ if (event->type == ICAL_VTODO_COMPONENT) {
+
+ label = g_strjoin(" ", _("You have a Todo item."),
+ _("Details follow:"), NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
+
+ } else if (event->method == ICAL_METHOD_REQUEST) {
+
+ if (account_find_from_address(event->organizer, FALSE)) {
+ label = g_strjoin(" ", _("You have created a meeting."),
+ _("Details follow:"), NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
+ mine = TRUE;
+ } else {
+ label = g_strjoin(" ", _("You have been invited to a meeting."),
+ _("Details follow:"), NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
+ }
+
+ } else if (event->method == ICAL_METHOD_CANCEL) {
+
+ label = g_strjoin(" ",
+ _("A meeting to which you had been invited has been cancelled."),
+ _("Details follow:"), NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
+ save_evt = TRUE;
+ vcalendar_refresh_folder_contents(item);
+ } else if (event->method == ICAL_METHOD_REPLY) {
+ /* don't change label */
+ } else {
+
+ label = g_strjoin(" ", _("You have been forwarded an appointment."),
+ _("Details follow:"), NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
+ }
+
+ g_free(label);
+
+/* organizer */
+ if (event->orgname && *(event->orgname)
+ && event->organizer && *(event->organizer)) {
+ gchar *addr = g_strconcat(event->orgname, " <", event->organizer, ">", NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
+ g_free(addr);
+ } else if (event->organizer && *(event->organizer)) {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), event->organizer);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
+ }
+
+/* location */
+ if (event->location && *(event->location)) {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), event->location);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
+ }
+
+/* summary */
+ if (event->summary && *(event->summary)) {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), event->summary);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
+ }
+
+/* description */
+ if (event->description && *(event->description)) {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), event->description);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
+ }
+
+/* url */
+ g_free(vcalviewer->url);
+ if (event->url && *(event->url)) {
+ vcalviewer->url = g_strdup(event->url);
+ gtk_widget_show(vcalviewer->uribtn);
+ } else {
+ vcalviewer->url = NULL;
+ gtk_widget_hide(vcalviewer->uribtn);
+ }
+
+/* start */
+ if (event->start && *(event->start)) {
+ if (event->recur && *(event->recur)) {
+ gchar *tmp = g_strdup_printf(_("%s <span weight=\"bold\">(this event recurs)</span>"),
+ event->start);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
+ gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
+ g_free(tmp);
+ } else if (event->rec_occurence) {
+ gchar *tmp = g_strdup_printf(_("%s <span weight=\"bold\">(this event is part of a recurring event)</span>"),
+ event->start);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
+ gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
+ g_free(tmp);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), event->start);
+ }
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
+ }
+
+/* end */
+ if (event->end && *(event->end)) {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), event->end);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
+ }
+
+/* attendees */
+ attendees = g_strdup("");
+ for (list = vcal_manager_get_answers_emails(event);
+ list && list->data; list = list->next) {
+ gchar *attendee = (gchar *)list->data;
+ gchar *name = vcal_manager_get_attendee_name(event, attendee);
+ gchar *ename = g_markup_printf_escaped("%s", name?name:"");
+ gchar *eatt = g_markup_printf_escaped("%s", attendee);
+ enum icalparameter_partstat acode = vcal_manager_get_reply_for_attendee(event, attendee);
+ gchar *answer = vcal_manager_get_reply_text_for_attendee(event, attendee);
+ gchar *type = vcal_manager_get_cutype_text_for_attendee(event, attendee);
+ gchar *tmp = NULL;
+ gint e_len, n_len;
+ tmp = g_strdup_printf(
+ "%s%s<%s> (%s, <span%s>%s</span>)",
+ (ename && *(ename))?ename:"",
+ (ename && *(ename))?" ":"",
+ (eatt && *(eatt))?eatt:"",
+ (type && *(type))?type:"",
+ (acode != ICAL_PARTSTAT_ACCEPTED ? " foreground=\"red\"":""),
+ (answer && *(answer))?answer:"");
+ e_len = strlen(attendees);
+ n_len = strlen(tmp);
+ if (e_len) {
+ attendees = g_realloc(attendees, e_len+n_len+2);
+ *(attendees+e_len) = '\n';
+ strcpy(attendees+e_len+1, tmp);
+ } else {
+ attendees = g_realloc(attendees, e_len+n_len+1);
+ strcpy(attendees, tmp);
+ }
+ g_free(tmp);
+ g_free(answer);
+ g_free(type);
+ g_free(name);
+ g_free(ename);
+ g_free(eatt);
+ }
+
+ if (attendees && *(attendees)) {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), attendees);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
+ }
+ g_free(attendees);
+ gtk_label_set_use_markup(GTK_LABEL(vcalviewer->attendees), TRUE);
+
+/* buttons */
+ if (!mine)
+ if (event->type != ICAL_VTODO_COMPONENT)
+ vcalviewer_answer_set_choices(vcalviewer, event, event->method);
+ else
+ vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_PUBLISH);
+ else {
+ vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_REPLY);
+ gtk_widget_show(vcalviewer->reedit);
+ gtk_widget_show(vcalviewer->cancel);
+ }
+
+/* save if cancelled */
+ if (save_evt)
+ vcal_manager_save_event(event, TRUE);
+}
+
+gchar *vcalviewer_get_uid_from_mimeinfo(MimeInfo *mimeinfo)
+{
+ gchar *tmpfile = procmime_get_tmp_file_name(mimeinfo);
+ const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
+ gchar *compstr = NULL;
+ gchar *res = NULL;
+ VCalEvent *event = NULL;
+
+ if (!charset)
+ charset = CS_WINDOWS_1252;
+
+ if (!strcasecmp(charset, CS_ISO_8859_1))
+ charset = CS_WINDOWS_1252;
+
+ if (procmime_get_part(tmpfile, mimeinfo) < 0) {
+ g_warning("Can't get mimepart file");
+ g_free(tmpfile);
+ return NULL;
+ }
+
+ compstr = file_read_to_str(tmpfile);
+
+ event = vcal_get_event_from_ical(compstr, charset);
+ if (event)
+ res = g_strdup(event->uid);
+
+ vcal_manager_free_event(event);
+
+ debug_print("got uid: %s\n", res);
+ return res;
+
+}
+
+static void vcalviewer_get_request_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo, gboolean is_todo)
+{
+ VCalEvent *saved_event = NULL;
+ const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
+ const gchar *saveme = procmime_mimeinfo_get_parameter(mimeinfo, "vcalsave");
+
+ if (!vcalviewer->event)
+ return;
+
+ if (!charset)
+ charset = CS_WINDOWS_1252;
+
+ if (!strcasecmp(charset, CS_ISO_8859_1))
+ charset = CS_WINDOWS_1252;
+
+ /* see if we have it registered and more recent */
+ saved_event = vcal_manager_load_event(vcalviewer->event->uid);
+ if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
+ charset = CS_INTERNAL;
+ saved_event->method = vcalviewer->event->method;
+ vcalviewer_display_event(vcalviewer, saved_event);
+ vcal_manager_free_event(saved_event);
+ return;
+ } else if (saved_event) {
+ vcal_manager_free_event(saved_event);
+ }
+
+ /* load it and register it */
+
+ if (!saveme || strcmp(saveme,"no"))
+ vcal_manager_save_event(vcalviewer->event, FALSE);
+
+ vcalviewer_display_event(vcalviewer, vcalviewer->event);
+}
+
+static void vcalviewer_get_reply_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
+{
+ const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
+ VCalEvent *saved_event = NULL;
+ gchar *attendee = NULL, *label = NULL;
+ Answer *answer = NULL;
+
+ if (!vcalviewer->event)
+ return;
+
+ if (!charset)
+ charset = CS_WINDOWS_1252;
+
+ if (!strcasecmp(charset, CS_ISO_8859_1))
+ charset = CS_WINDOWS_1252;
+
+ if (!vcalviewer->event->answers || g_slist_length(vcalviewer->event->answers) > 1) {
+ g_warning("strange, no answers or more than one\n");
+ }
+
+ if (vcalviewer->event->answers) {
+ answer = (Answer *)vcalviewer->event->answers->data;
+ attendee = g_strdup(answer->attendee);
+ }
+
+
+ if (!answer) {
+ label = g_strjoin(" ",
+ _("You have received an answer to an unknown meeting proposal."),
+ _("Details follow:"), NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
+ } else {
+ label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
+ "%s has %s the invitation whose details follow:"),
+ attendee, vcal_manager_answer_get_text(answer->answer));
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
+ g_free(attendee);
+ }
+ g_free(label);
+
+ saved_event = vcal_manager_load_event(vcalviewer->event->uid);
+ if (saved_event && answer) {
+ vcal_manager_update_answer(saved_event,
+ answer->attendee, answer->name, answer->answer, answer->cutype);
+ vcal_manager_save_event(saved_event, TRUE);
+ saved_event->method = vcalviewer->event->method;
+ vcalviewer_display_event(vcalviewer, saved_event);
+ vcal_manager_free_event(saved_event);
+ return;
+ }
+
+ if (vcalviewer->event->organizer) {
+ if (vcalviewer->event->orgname) {
+ gchar *addr = g_strconcat(vcalviewer->event->orgname, " <",
+ vcalviewer->event->organizer, ">", NULL);
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
+ g_free(addr);
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who),
+ vcalviewer->event->organizer);
+ }
+ } else {
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
+ }
+
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location),
+ vcalviewer->event->location?vcalviewer->event->location:"-");
+
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary),
+ vcalviewer->event->summary?vcalviewer->event->summary:"-");
+
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description),
+ vcalviewer->event->description?vcalviewer->event->description:"-");
+
+ g_free(vcalviewer->url);
+ if (vcalviewer->event->url) {
+ vcalviewer->url = g_strdup(vcalviewer->event->url);
+ gtk_widget_show(vcalviewer->uribtn);
+ } else {
+ vcalviewer->url = NULL;
+ gtk_widget_hide(vcalviewer->uribtn);
+ }
+
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start),
+ vcalviewer->event->start?vcalviewer->event->start:"-");
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end),
+ vcalviewer->event->end?vcalviewer->event->end:"-");
+
+ GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
+
+ vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REPLY);
+}
+
+static void vcalviewer_get_event(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
+{
+ gchar *tmpfile = get_tmpfile(vcalviewer);
+ const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
+
+ if (!charset)
+ charset = CS_WINDOWS_1252;
+
+ if (!strcasecmp(charset, CS_ISO_8859_1))
+ charset = CS_WINDOWS_1252;
+
+ if (vcalviewer->event) {
+ vcal_manager_free_event(vcalviewer->event);
+ vcalviewer->event = NULL;
+ }
+
+ if (!tmpfile) {
+ vcalviewer_reset(vcalviewer);
+ vcalviewer_show_error(vcalviewer, _("Error - could not get the calendar MIME part."));
+ return;
+ }
+
+ vcalviewer->event = vcalviewer_get_component(tmpfile, charset);
+ if (!vcalviewer->event) {
+ vcalviewer_reset(vcalviewer);
+ vcalviewer_show_error(vcalviewer, _("Error - no calendar part found."));
+ return;
+ }
+
+ if (vcalviewer->event->type == ICAL_VTODO_COMPONENT) {
+ vcalviewer_get_request_values(vcalviewer, mimeinfo, TRUE);
+ } else if (vcalviewer->event->method == ICAL_METHOD_REQUEST ||
+ vcalviewer->event->method == ICAL_METHOD_PUBLISH ||
+ vcalviewer->event->method == ICAL_METHOD_CANCEL) {
+ vcalviewer_get_request_values(vcalviewer, mimeinfo, FALSE);
+ } else if (vcalviewer->event->method == ICAL_METHOD_REPLY) {
+ vcalviewer_get_reply_values(vcalviewer, mimeinfo);
+ } else {
+ vcalviewer_reset(vcalviewer);
+ vcalviewer_show_error(vcalviewer, _("Error - Unknown calendar component type."));
+ }
+}
+
+static VCalViewer *s_vcalviewer = NULL;
+
+static void vcal_viewer_show_mimepart(MimeViewer *_mimeviewer, const gchar *file, MimeInfo *mimeinfo)
+{
+ VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
+ START_TIMING("");
+
+ s_vcalviewer = vcalviewer;
+
+ if (mimeinfo == NULL) {
+ vcal_viewer_clear_viewer(_mimeviewer);
+ END_TIMING();
+ return;
+ }
+ debug_print("vcal_viewer_show_mimepart : %s\n", file);
+
+ vcal_viewer_clear_viewer(_mimeviewer);
+ gtk_widget_show_all(vcalviewer->scrolledwin);
+ g_free(vcalviewer->file);
+ vcalviewer->file = g_strdup(file);
+ vcalviewer->mimeinfo = mimeinfo;
+ vcalviewer_hide_error(vcalviewer);
+ vcalviewer_get_event(vcalviewer, mimeinfo);
+ GTK_EVENTS_FLUSH();
+ gtk_widget_set_size_request(vcalviewer->description,
+ vcalviewer->scrolledwin->allocation.width - 200, -1);
+ gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->location), TRUE);
+ gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->summary), TRUE);
+ gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->description), TRUE);
+ gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
+
+ if (prefs_common_get_prefs()->textfont) {
+ PangoFontDescription *font_desc;
+
+ font_desc = pango_font_description_from_string
+ (prefs_common_get_prefs()->textfont);
+ if (font_desc) {
+ gtk_widget_modify_font(
+ vcalviewer->description, font_desc);
+ pango_font_description_free(font_desc);
+ }
+ }
+ END_TIMING();
+}
+
+void vcalviewer_reload(FolderItem *item)
+{
+ if (s_vcalviewer) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+
+ folder_item_scan(item);
+ if (mainwin && mainwin->summaryview->folder_item) {
+ FolderItem *cur = mainwin->summaryview->folder_item;
+ if (cur->folder == folder)
+ folder_item_scan(cur);
+ }
+ if (mainwin && mainwin->summaryview->folder_item == item) {
+ debug_print("reload: %p, %p\n", (MimeViewer *)s_vcalviewer, s_vcalviewer->mimeinfo);
+ summary_redisplay_msg(mainwin->summaryview);
+ }
+ }
+}
+
+static void vcal_viewer_destroy_viewer(MimeViewer *_mimeviewer)
+{
+ VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
+
+ debug_print("vcal_viewer_destroy_viewer\n");
+
+ if (s_vcalviewer == vcalviewer)
+ s_vcalviewer = NULL;
+ vcal_viewer_clear_viewer(_mimeviewer);
+ g_free(vcalviewer);
+}
+
+static gboolean vcalviewer_reedit_cb(GtkButton *widget, gpointer data)
+{
+ VCalViewer *vcalviewer = (VCalViewer *)data;
+ gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
+ VCalEvent *event = NULL;
+
+ s_vcalviewer = vcalviewer;
+ /* see if we have it registered and more recent */
+ event = vcal_manager_load_event(uid);
+ vcal_meeting_create(event);
+ vcal_manager_free_event(event);
+ return TRUE;
+}
+
+static gboolean vcalviewer_uribtn_cb(GtkButton *widget, gpointer data)
+{
+ VCalViewer *vcalviewer = (VCalViewer *)data;
+
+ if (vcalviewer->url)
+ open_uri(vcalviewer->url, prefs_common_get_uri_cmd());
+
+ return TRUE;
+}
+
+void vcalendar_refresh_folder_contents(FolderItem *item)
+{
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ if (folder && item->folder == folder) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ folder_item_scan(item);
+ if (mainwin->summaryview->folder_item == item) {
+ summary_show(mainwin->summaryview, item);
+ }
+ }
+}
+
+static void send_cancel_notify_toggled_cb(GtkToggleButton *button, gboolean *data)
+{
+ *data = gtk_toggle_button_get_active(button);
+}
+
+void vcalendar_cancel_meeting(FolderItem *item, const gchar *uid)
+{
+ VCalEvent *event = NULL;
+ VCalMeeting *meet = NULL;
+ gchar *file = NULL;
+ gint val = 0;
+ Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ gboolean redisp = FALSE;
+ GtkWidget *send_notify_chkbtn = gtk_check_button_new_with_label(_("Send a notification to the attendees"));
+ gboolean send_notify = TRUE;
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_notify_chkbtn), TRUE);
+ gtk_widget_show(send_notify_chkbtn);
+ g_signal_connect(G_OBJECT(send_notify_chkbtn), "toggled",
+ G_CALLBACK(send_cancel_notify_toggled_cb),
+ &send_notify);
+
+ val = alertpanel_full(_("Cancel meeting"),
+ _("Are you sure you want to cancel this meeting?"),
+ GTK_STOCK_NO, GTK_STOCK_YES, NULL, FALSE,
+ send_notify_chkbtn, ALERT_WARNING, G_ALERTDEFAULT);
+
+ if (val != G_ALERTALTERNATE)
+ return;
+
+ event = vcal_manager_load_event(uid);
+ if (!event)
+ return;
+ event->method = ICAL_METHOD_CANCEL;
+
+ if (folder) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ if (mainwin->summaryview->folder_item == item) {
+ redisp = TRUE;
+ summary_show(mainwin->summaryview, NULL);
+ }
+ }
+
+ if (send_notify) {
+ meet = vcal_meeting_create_hidden(event);
+ if (!vcal_meeting_send(meet)) {
+ event->method = ICAL_METHOD_REQUEST;
+ vcal_manager_save_event(event, TRUE);
+ vcal_manager_free_event(event);
+ if (folder)
+ folder_item_scan(item);
+
+ if (folder && redisp) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ summary_show(mainwin->summaryview, item);
+ }
+ return;
+ }
+ }
+
+ vcal_manager_save_event(event, TRUE);
+
+ file = vcal_manager_get_event_file(event->uid);
+ g_unlink(file);
+ vcal_manager_free_event(event);
+ g_free(file);
+ if (folder)
+ folder_item_scan(item);
+ if (folder && redisp) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ summary_show(mainwin->summaryview, item);
+ }
+
+ return;
+}
+
+static gboolean vcalviewer_cancel_cb(GtkButton *widget, gpointer data)
+{
+ VCalViewer *vcalviewer = (VCalViewer *)data;
+ FolderItem *item = vcalendar_get_current_item();
+ gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
+ vcalendar_cancel_meeting(item, uid);
+ return TRUE;
+}
+
+static gboolean vcalviewer_action_cb(GtkButton *widget, gpointer data)
+{
+ VCalViewer *vcalviewer = (VCalViewer *)data;
+ gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(vcalviewer->answer));
+ enum icalparameter_partstat reply[3] = {ICAL_PARTSTAT_ACCEPTED, ICAL_PARTSTAT_TENTATIVE, ICAL_PARTSTAT_DECLINED};
+ PrefsAccount *account = NULL;
+ VCalEvent *saved_event = NULL, *event = NULL;
+ debug_print("index chosen %d\n", index);
+
+ if (index < 0 || index > 2) {
+ return TRUE;
+ }
+
+ s_vcalviewer = vcalviewer;
+
+ if (!vcalviewer->event) {
+ g_warning("can't get event\n");
+ return TRUE;
+ }
+
+/* see if we have it registered and more recent */
+ event = vcalviewer->event;
+ saved_event = vcal_manager_load_event(vcalviewer->event->uid);
+ if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
+ saved_event->method = vcalviewer->event->method;
+ event = saved_event;
+ } else if (saved_event) {
+ vcal_manager_free_event(saved_event);
+ saved_event = NULL;
+ }
+ account = vcal_manager_get_account_from_event(event);
+
+ if (!account) {
+ AlertValue val = alertpanel_full(_("No account found"),
+ _("You have no account matching any attendee.\n"
+ "Do you want to reply anyway ?"),
+ GTK_STOCK_CANCEL, _("+Reply anyway"), NULL, FALSE,
+ NULL, ALERT_QUESTION, G_ALERTDEFAULT);
+ if (val == G_ALERTALTERNATE) {
+ account = account_get_default();
+ vcal_manager_update_answer(event, account->address,
+ account->name,
+ ICAL_PARTSTAT_NEEDSACTION,
+ ICAL_CUTYPE_INDIVIDUAL);
+ } else {
+ if (saved_event)
+ vcal_manager_free_event(saved_event);
+ return TRUE;
+ }
+ }
+
+ vcal_manager_update_answer(event, account->address, account->name, reply[index], 0);
+
+ if (event->organizer && *(event->organizer) &&
+ !vcal_manager_reply(account, event)) {
+ g_warning("couldn't send reply\n");
+ } else {
+ debug_print("no organizer, not sending answer\n");
+ }
+
+ vcal_manager_save_event(event, TRUE);
+
+ vcalviewer_display_event(vcalviewer, event);
+ if (saved_event)
+ vcal_manager_free_event(saved_event);
+ return TRUE;
+};
+
+#define TABLE_ADD_LINE(label_text, widget) { \
+ gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>",\
+ label_text); \
+ GtkWidget *label = gtk_label_new(tmpstr); \
+ g_free(tmpstr); \
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE); \
+ gtk_misc_set_alignment (GTK_MISC(label), 1, 0); \
+ gtk_table_attach (GTK_TABLE (vcalviewer->table), \
+ label, 0, 1, i, i+1, \
+ GTK_FILL, GTK_FILL, 6, 6); \
+ gtk_table_attach (GTK_TABLE (vcalviewer->table), \
+ widget, 1, 2, i, i+1, \
+ GTK_FILL, GTK_FILL, 6, 6); \
+ if (GTK_IS_LABEL(widget)) { \
+ gtk_label_set_use_markup(GTK_LABEL (widget), TRUE); \
+ gtk_misc_set_alignment (GTK_MISC(widget),0, 0); \
+ gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); \
+ } \
+ i++; \
+}
+
+static gchar *vcal_viewer_get_selection(MimeViewer *_viewer)
+{
+ VCalViewer *viewer = (VCalViewer *)_viewer;
+ if (viewer->summary == NULL)
+ return NULL;
+ if (gtk_label_get_text(GTK_LABEL(viewer->description))
+ && *(gtk_label_get_text(GTK_LABEL(viewer->description))) > 2) {
+ gint start, end;
+ if (gtk_label_get_selection_bounds(GTK_LABEL(viewer->description),
+ &start, &end)) {
+ gchar *tmp = g_strdup(gtk_label_get_text(
+ GTK_LABEL(viewer->description))+start);
+ tmp[end-start] = '\0';
+ return tmp;
+ } else {
+ return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->description)));
+ }
+ }
+ else if (gtk_label_get_text(GTK_LABEL(viewer->summary))
+ && *(gtk_label_get_text(GTK_LABEL(viewer->summary))) > 2)
+ return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->summary)));
+ else
+ return NULL;
+}
+
+
+static gboolean vcal_viewer_scroll_page(MimeViewer *_viewer, gboolean up)
+{
+ VCalViewer *viewer = (VCalViewer *)_viewer;
+ GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
+ GTK_SCROLLED_WINDOW(viewer->scrolledwin));
+
+ return gtkutils_scroll_page(viewer->table, vadj, up);
+}
+
+static void vcal_viewer_scroll_one_line(MimeViewer *_viewer, gboolean up)
+{
+ VCalViewer *viewer = (VCalViewer *)_viewer;
+ GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
+ GTK_SCROLLED_WINDOW(viewer->scrolledwin));
+
+ gtkutils_scroll_one_line(viewer->table, vadj, up);
+}
+
+MimeViewer *vcal_viewer_create(void)
+{
+ VCalViewer *vcalviewer;
+ int i = 0;
+ GtkWidget *hbox = NULL, *vbox = NULL;
+ GtkWidget *warning_img;
+ GtkWidget *warning_label;
+
+ debug_print("Creating vcal view...\n");
+ vcalviewer = g_new0(VCalViewer, 1);
+ vcalviewer->mimeviewer.factory = &vcal_viewer_factory;
+
+ vcalviewer->mimeviewer.get_widget = vcal_viewer_get_widget;
+ vcalviewer->mimeviewer.show_mimepart = vcal_viewer_show_mimepart;
+ vcalviewer->mimeviewer.clear_viewer = vcal_viewer_clear_viewer;
+ vcalviewer->mimeviewer.destroy_viewer = vcal_viewer_destroy_viewer;
+ vcalviewer->mimeviewer.get_selection = vcal_viewer_get_selection;
+ vcalviewer->mimeviewer.scroll_page = vcal_viewer_scroll_page;
+ vcalviewer->mimeviewer.scroll_one_line = vcal_viewer_scroll_one_line;
+
+ vcalviewer->table = gtk_table_new(8, 2, FALSE);
+ vcalviewer->type = gtk_label_new("meeting");
+ vcalviewer->who = gtk_label_new("who");
+ vcalviewer->start = gtk_label_new("start");
+ vcalviewer->end = gtk_label_new("end");
+ vcalviewer->location = gtk_label_new("location");
+ vcalviewer->summary = gtk_label_new("summary");
+ vcalviewer->description = gtk_label_new("description");
+ vcalviewer->attendees = gtk_label_new("attendees");
+
+ vcalviewer->answer = gtk_combo_box_new_text();
+ vcalviewer->url = NULL;
+ vcalviewer->button = gtk_button_new_with_label(_("Answer"));
+ vcalviewer->reedit = gtk_button_new_with_label(_("Edit meeting..."));
+ vcalviewer->cancel = gtk_button_new_with_label(_("Cancel meeting..."));
+ vcalviewer->uribtn = gtk_button_new_with_label(_("Launch website"));
+ vcalviewer->unavail_box = gtk_hbox_new(FALSE, 6);
+ warning_img = gtk_image_new_from_stock
+ (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ warning_label = gtk_label_new(_("You are already busy at this time."));
+
+ gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_img, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_label, FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->answer, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->button, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->reedit, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->cancel, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->uribtn, FALSE, FALSE, 0);
+
+ vbox = gtk_vbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), vcalviewer->unavail_box, FALSE, FALSE, 0);
+
+ vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REQUEST);
+
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->type), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->who), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->start), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->end), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->location), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->summary), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->description), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(vcalviewer->attendees), TRUE);
+
+ g_signal_connect(G_OBJECT(vcalviewer->button), "clicked",
+ G_CALLBACK(vcalviewer_action_cb), vcalviewer);
+
+ g_signal_connect(G_OBJECT(vcalviewer->reedit), "clicked",
+ G_CALLBACK(vcalviewer_reedit_cb), vcalviewer);
+
+ g_signal_connect(G_OBJECT(vcalviewer->cancel), "clicked",
+ G_CALLBACK(vcalviewer_cancel_cb), vcalviewer);
+
+ g_signal_connect(G_OBJECT(vcalviewer->uribtn), "clicked",
+ G_CALLBACK(vcalviewer_uribtn_cb), vcalviewer);
+
+ TABLE_ADD_LINE(_("Event:"), vcalviewer->type);
+ TABLE_ADD_LINE(_("Organizer:"), vcalviewer->who);
+ TABLE_ADD_LINE(_("Location:"), vcalviewer->location);
+ TABLE_ADD_LINE(_("Summary:"), vcalviewer->summary);
+ TABLE_ADD_LINE(_("Starting:"), vcalviewer->start);
+ TABLE_ADD_LINE(_("Ending:"), vcalviewer->end);
+ TABLE_ADD_LINE(_("Description:"), vcalviewer->description);
+ TABLE_ADD_LINE(_("Attendees:"), vcalviewer->attendees);
+ gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
+ TABLE_ADD_LINE(_("Action:"), vbox);
+
+ vcalviewer->scrolledwin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_add_with_viewport(
+ GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
+ vcalviewer->table);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+
+ gtk_widget_show_all(vcalviewer->scrolledwin);
+ return (MimeViewer *) vcalviewer;
+}
+
+static gchar *content_types[] =
+ {"text/calendar", NULL};
+
+MimeViewerFactory vcal_viewer_factory =
+{
+ content_types,
+ 0,
+ vcal_viewer_create,
+};
+
+static gint alert_timeout_tag = 0;
+static gint scan_timeout_tag = 0;
+
+static gboolean vcal_webcal_check(gpointer data)
+{
+ Folder *root = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+
+ if (prefs_common_get_prefs()->work_offline)
+ return TRUE;
+
+ manual_update = FALSE;
+ folderview_check_new(root);
+ manual_update = TRUE;
+ return TRUE;
+}
+
+static guint context_menu_id = 0;
+static guint main_menu_id = 0;
+
+void vcalendar_init(void)
+{
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ Folder *folder = NULL;
+ gchar *directory = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "vcalendar", NULL);
+ START_TIMING("");
+ if (!is_dir_exist(directory))
+ make_dir (directory);
+ g_free(directory);
+
+ vcal_prefs_init();
+
+ mimeview_register_viewer_factory(&vcal_viewer_factory);
+ folder_register_class(vcal_folder_get_class());
+
+ folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
+ if (!folder) {
+ START_TIMING("creating folder");
+ folder = folder_new(vcal_folder_get_class(), "vCalendar", NULL);
+ folder->klass->create_tree(folder);
+ folder_add(folder);
+ folder_scan_tree(folder, TRUE);
+ END_TIMING();
+ }
+ if (folder) {
+ if (!folder->inbox) {
+ folder->klass->create_tree(folder);
+ folder_scan_tree(folder, TRUE);
+ }
+ if (folder->klass->scan_required(folder, folder->inbox)) {
+ START_TIMING("scanning folder");
+ folder_item_scan(folder->inbox);
+ END_TIMING();
+ }
+ }
+
+ vcal_folder_gtk_init();
+
+ alert_timeout_tag = g_timeout_add(60*1000,
+ (GSourceFunc)vcal_meeting_alert_check,
+ (gpointer)NULL);
+ scan_timeout_tag = g_timeout_add(3600*1000,
+ (GSourceFunc)vcal_webcal_check,
+ (gpointer)NULL);
+ if (prefs_common_get_prefs()->enable_color) {
+ gtkut_convert_int_to_gdk_color(prefs_common_get_prefs()->uri_col,
+ &uri_color);
+ }
+
+ gtk_action_group_add_actions(mainwin->action_group, vcalendar_main_menu,
+ 1, (gpointer)mainwin);
+ MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/Message", "CreateMeeting",
+ "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
+ main_menu_id)
+ MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menus/SummaryViewPopup", "CreateMeeting",
+ "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
+ context_menu_id)
+ END_TIMING();
+}
+
+void vcalendar_done(void)
+{
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ FolderView *folderview = NULL;
+ FolderItem *fitem = NULL;
+ SummaryView *summaryview = NULL;
+
+ icalmemory_free_ring();
+
+ vcal_folder_free_data();
+
+ if (mainwin == NULL)
+ return;
+
+ summaryview = mainwin->summaryview;
+ folderview = mainwin->folderview;
+ fitem = folderview->summaryview->folder_item;
+
+ if (fitem &&
+ fitem->folder->klass == vcal_folder_get_class()) {
+ folderview_unselect(folderview);
+ summary_clear_all(folderview->summaryview);
+ if (fitem->folder->klass->item_closed)
+ fitem->folder->klass->item_closed(fitem);
+ }
+
+ mimeview_unregister_viewer_factory(&vcal_viewer_factory);
+ folder_unregister_class(vcal_folder_get_class());
+ vcal_folder_gtk_done();
+ vcal_prefs_done();
+ g_source_remove(alert_timeout_tag);
+ alert_timeout_tag = 0;
+ g_source_remove(scan_timeout_tag);
+ scan_timeout_tag = 0;
+
+ MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", main_menu_id);
+ main_menu_id = 0;
+ MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", context_menu_id);
+ context_menu_id = 0;
+}
diff --git a/src/plugins/vcalendar/vcalendar.h b/src/plugins/vcalendar/vcalendar.h
@@ -0,0 +1,37 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
+ * the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __VCALENDAR_H__
+#define __VCALENDAR_H__
+#include <ical.h>
+#include "vcal_manager.h"
+#include "prefs_account.h"
+#include "procmime.h"
+#include "folder.h"
+
+typedef struct _VCalViewer VCalViewer;
+
+void vcalendar_init(void);
+void vcalendar_done(void);
+void vcalviewer_display_event (VCalViewer *vcalviewer, VCalEvent *event);
+gchar *vcalviewer_get_uid_from_mimeinfo(MimeInfo *mimeinfo);
+void vcalviewer_reload(FolderItem *item);
+void vcalendar_cancel_meeting(FolderItem *item, const gchar *uid);
+#endif
diff --git a/src/plugins/vcalendar/version.rc b/src/plugins/vcalendar/version.rc
@@ -0,0 +1,36 @@
+1 VERSIONINFO
+ FILEVERSION 0, 0, 0, 0
+ PRODUCTVERSION 0, 0, 0, 0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "FileDescription", "VCalendar Plugin\0"
+ VALUE "FileVersion", "0.0.0.0\0"
+ VALUE "ProductVersion", "0.0.0.0 Win32\0"
+ VALUE "LegalCopyright", "GPL / © 1999-2008 Hiroyuki Yamamoto & The Claws Mail Team\0"
+ VALUE "CompanyName", "GNU / Free Software Foundation\0"
+ VALUE "ProductName", "Claws Mail\0"
+// VALUE "Comments", "\0"
+// VALUE "InternalName", "\0"
+// VALUE "LegalTrademarks", "\0"
+// VALUE "OriginalFilename", "\0"
+// VALUE "PrivateBuild", "\0"
+// VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END