talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

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:
MChangeLog | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MPATCHSETS | 1+
Mconfigure.ac | 29+++++++++++++++++++++++------
Msrc/plugins/Makefile.am | 7++++++-
Dsrc/plugins/address_dup_finder/placeholder.txt | 1-
Dsrc/plugins/synce/placeholder.txt | 1-
Asrc/plugins/vcalendar/Makefile.am | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/Makefile.in | 913+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/common-views.c | 292+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/common-views.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/day-view.c | 931+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/icaltime_as_local.c | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/icaltime_as_local.h | 18++++++++++++++++++
Asrc/plugins/vcalendar/libical/.cvsignore | 6++++++
Asrc/plugins/vcalendar/libical/Makefile.am | 1+
Asrc/plugins/vcalendar/libical/Makefile.in | 681+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/design-data/.cvsignore | 6++++++
Asrc/plugins/vcalendar/libical/design-data/Makefile.am | 6++++++
Asrc/plugins/vcalendar/libical/design-data/Makefile.in | 488+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/design-data/parameters.csv | 25+++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/design-data/properties.csv | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/design-data/restrictions.csv | 1348+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/design-data/status.txt | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/design-data/value-types.csv | 31+++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/.cvsignore | 19+++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/Makefile.am | 226+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/Makefile.in | 923+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalattendee.c | 30++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalattendee.h | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalcomponent.c | 1500+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalcomponent.h | 240+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalderivedparameter.c.in | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalderivedparameter.h.in | 37+++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalderivedproperty.c.in | 250+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalderivedproperty.h.in | 23+++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalderivedvalue.c.in | 298+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalderivedvalue.h.in | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalduration.c | 320+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalduration.h | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalenums.c | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalenums.h | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalerror.c | 195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalerror.h | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icallangbind.c | 272+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icallangbind.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icallexer.l | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalmemory.c | 287+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalmemory.h | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalmime.c | 389+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalmime.h | 43+++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalparameter.c | 382+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalparameter.h | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalparameterimpl.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalparser.c | 1109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalparser.h | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalperiod.c | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalperiod.h | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalproperty.c | 808+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalproperty.h | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalrecur.c | 2258+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalrecur.h | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalrestriction.c.in | 447+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalrestriction.h | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icaltime.c | 600+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icaltime.h | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icaltypes.c | 263+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icaltypes.h | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalvalue.c | 1197+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalvalue.h | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalvalueimpl.h | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalversion.h | 7+++++++
Asrc/plugins/vcalendar/libical/libical/icalversion.h.in | 7+++++++
Asrc/plugins/vcalendar/libical/libical/icalyacc.output | 830+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/icalyacc.y | 405+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/pvl.c | 762+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/pvl.h | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/sspm.c | 1613+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/sspm.h | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/libical/vsnprintf.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/.cvsignore | 6++++++
Asrc/plugins/vcalendar/libical/scripts/Makefile.am | 9+++++++++
Asrc/plugins/vcalendar/libical/scripts/Makefile.in | 491+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/mkderivedcomponents.pl | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/mkderivedparameters.pl | 321+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/mkderivedproperties.pl | 217+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/mkderivedvalues.pl | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/mkparameterrestrictions.pl | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/mkrestrictionrecords.pl | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/mkrestrictiontable.pl | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/libical/scripts/readvaluesfile.pl | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/month-view.c | 1020+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/plugins/vcalendar/placeholder.txt | 1-
Asrc/plugins/vcalendar/plugin.c | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_dbus.c | 209+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_dbus.h | 27+++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_folder.c | 2431+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_folder.h | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_interface.h | 26++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_manager.c | 1543+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_manager.h | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_meeting_gtk.c | 2284+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_meeting_gtk.h | 39+++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_prefs.c | 665+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcal_prefs.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcalendar.c | 1417+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/vcalendar.h | 37+++++++++++++++++++++++++++++++++++++
Asrc/plugins/vcalendar/version.rc | 36++++++++++++++++++++++++++++++++++++
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(&gtm); + + 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(&lt); + 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, &lt->tm_hour, &lt->tm_min); + } else { + get_time_from_combo(meet->end_time, &lt->tm_hour, &lt->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&lt;%s&gt; (%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