36 #include "icaltimezones.h"
39 #include <libical/ical.h>
40 #include <libical/icalss.h>
41 #include <libical/icalparser.h>
42 #include <libical/icalrestriction.h>
43 #include <libical/icalmemory.h>
46 #include <QtCore/QString>
47 #include <QtCore/QRegExp>
48 #include <QtCore/QFile>
49 #include <QtCore/QTextStream>
50 #include <QtCore/QByteArray>
55 #include <ksavefile.h>
62 class KCal::ICalFormat::Private
67 mTimeSpec( KDateTime::UTC )
69 ~Private() {
delete mImpl; }
71 KDateTime::Spec mTimeSpec;
76 : d( new Private( this ) )
91 QFile file( fileName );
92 if ( !file.open( QIODevice::ReadOnly ) ) {
93 kDebug() <<
"load error";
97 QTextStream ts( &file );
98 ts.setCodec(
"ISO 8859-1" );
99 QByteArray text = ts.readAll().trimmed().toLatin1();
102 if ( text.isEmpty() ) {
112 kDebug() << fileName;
116 QString text =
toString( calendar );
117 if ( text.isEmpty() ) {
122 KSaveFile::backupFile( fileName );
124 KSaveFile file( fileName );
125 if ( !file.open() ) {
126 kDebug() <<
"err:" << file.errorString();
128 i18n(
"Error saving to '%1'.", fileName ) ) );
133 QByteArray textUtf8 = text.toUtf8();
134 file.write( textUtf8.data(), textUtf8.size() );
136 if ( !file.finalize() ) {
137 kDebug() <<
"err:" << file.errorString();
139 i18n(
"Could not save '%1'", fileName ) ) );
155 icalcomponent *calendar;
158 calendar = icalcomponent_new_from_string( const_cast<char*>( (
const char * )
string ) );
160 kDebug() <<
"parse error";
167 if ( icalcomponent_isa( calendar ) == ICAL_XROOT_COMPONENT ) {
169 for ( comp = icalcomponent_get_first_component( calendar, ICAL_VCALENDAR_COMPONENT );
170 comp; comp = icalcomponent_get_next_component( calendar, ICAL_VCALENDAR_COMPONENT ) ) {
172 if ( !d->mImpl->populate( cal, comp ) ) {
173 kDebug() <<
"Could not populate calendar";
182 }
else if ( icalcomponent_isa( calendar ) != ICAL_VCALENDAR_COMPONENT ) {
183 kDebug() <<
"No VCALENDAR component found";
188 if ( !d->mImpl->populate( cal, calendar ) ) {
189 kDebug() <<
"Could not populate calendar";
199 icalcomponent_free( calendar );
200 icalmemory_free_ring();
212 if ( elist.count() > 0 ) {
213 ical = elist.first();
216 if ( tlist.count() > 0 ) {
217 ical = tlist.first();
220 if ( jlist.count() > 0 ) {
221 ical = jlist.first();
226 return ical ? ical->
clone() : 0;
231 icalcomponent *calendar = d->mImpl->createCalendarComponent( cal );
232 icalcomponent *component;
239 Todo::List::ConstIterator it;
240 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
241 component = d->mImpl->writeTodo( *it, tzlist, &tzUsedList );
242 icalcomponent_add_component( calendar, component );
247 Event::List::ConstIterator it2;
248 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
250 component = d->mImpl->writeEvent( *it2, tzlist, &tzUsedList );
251 icalcomponent_add_component( calendar, component );
257 Journal::List::ConstIterator it3;
258 for ( it3 = journals.constBegin(); it3 != journals.constEnd(); ++it3 ) {
259 component = d->mImpl->writeJournal( *it3, tzlist, &tzUsedList );
260 icalcomponent_add_component( calendar, component );
264 const ICalTimeZones::ZoneMap zones = tzUsedList.
zones();
265 for ( ICalTimeZones::ZoneMap::ConstIterator it=zones.constBegin();
266 it != zones.constEnd(); ++it ) {
267 icaltimezone *tz = (*it).icalTimezone();
269 kError() <<
"bad time zone";
271 component = icalcomponent_new_clone( icaltimezone_get_component( tz ) );
272 icalcomponent_add_component( calendar, component );
273 icaltimezone_free( tz, 1 );
277 QString text = QString::fromUtf8( icalcomponent_as_ical_string( calendar ) );
279 icalcomponent_free( calendar );
280 icalmemory_free_ring();
282 if ( text.isEmpty() ) {
284 i18n(
"libical error" ) ) );
299 icalcomponent *component;
301 component = d->mImpl->writeIncidence( incidence );
303 QString text = QString::fromUtf8( icalcomponent_as_ical_string( component ) );
305 icalcomponent_free( component );
312 icalproperty *property;
313 property = icalproperty_new_rrule( d->mImpl->writeRecurrenceRule( recurrence ) );
314 QString text = QString::fromUtf8( icalproperty_as_ical_string( property ) );
315 icalproperty_free( property );
325 icalerror_clear_errno();
326 struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule.toLatin1() );
327 if ( icalerrno != ICAL_NO_ERROR ) {
328 kDebug() <<
"Recurrence parsing error:" << icalerror_strerror( icalerrno );
333 d->mImpl->readRecurrence( recur, recurrence );
342 icalcomponent *message = 0;
345 if ( incidence->
type() ==
"Event" || incidence->
type() ==
"Todo" ) {
354 message = d->mImpl->createScheduleComponent( i, method );
361 if ( message == 0 ) {
362 message = d->mImpl->createScheduleComponent( incidence, method );
365 QString messageText = QString::fromUtf8( icalcomponent_as_ical_string( message ) );
367 icalcomponent_free( message );
375 icalcomponent *message;
376 message = icalparser_parse_string( str.toUtf8() );
385 for ( c = icalcomponent_get_first_component( message, ICAL_VFREEBUSY_COMPONENT );
386 c != 0; c = icalcomponent_get_next_component( message, ICAL_VFREEBUSY_COMPONENT ) ) {
387 FreeBusy *fb = d->mImpl->readFreeBusy( c );
390 freeBusy->
merge( fb );
398 kDebug() <<
"object is not a freebusy.";
404 const QString &messageText )
409 if ( messageText.isEmpty() ) {
412 QLatin1String(
"messageText is empty, unable "
413 "to parse into a ScheduleMessage" ) ) );
417 icalcomponent *message;
418 message = icalparser_parse_string( messageText.toUtf8() );
423 QLatin1String(
"icalparser is unable to parse "
424 "messageText into a ScheduleMessage" ) ) );
429 icalcomponent_get_first_property( message, ICAL_METHOD_PROPERTY );
433 QLatin1String(
"message does not contain an "
434 "ICAL_METHOD_PROPERTY" ) ) );
441 tzs.
parse( message, tzlist );
446 c = icalcomponent_get_first_component( message, ICAL_VEVENT_COMPONENT );
448 incidence = d->mImpl->readEvent( c, &tzlist );
452 c = icalcomponent_get_first_component( message, ICAL_VTODO_COMPONENT );
454 incidence = d->mImpl->readTodo( c, &tzlist );
459 c = icalcomponent_get_first_component( message, ICAL_VJOURNAL_COMPONENT );
461 incidence = d->mImpl->readJournal( c, &tzlist );
466 c = icalcomponent_get_first_component( message, ICAL_VFREEBUSY_COMPONENT );
468 incidence = d->mImpl->readFreeBusy( c );
473 kDebug() <<
"object is not a freebusy, event, todo or journal";
476 QLatin1String(
"object is not a freebusy, event, "
477 "todo or journal" ) ) );
481 icalproperty_method icalmethod = icalproperty_get_method( m );
484 switch ( icalmethod ) {
485 case ICAL_METHOD_PUBLISH:
488 case ICAL_METHOD_REQUEST:
491 case ICAL_METHOD_REFRESH:
494 case ICAL_METHOD_CANCEL:
497 case ICAL_METHOD_ADD:
500 case ICAL_METHOD_REPLY:
503 case ICAL_METHOD_COUNTER:
506 case ICAL_METHOD_DECLINECOUNTER:
511 kDebug() <<
"Unknown method";
515 if ( !icalrestriction_check( message ) ) {
517 <<
"kcal library reported a problem while parsing:";
519 << d->mImpl->extractErrorProperty( c );
524 icalcomponent *calendarComponent = 0;
525 if ( existingIncidence ) {
526 calendarComponent = d->mImpl->createCalendarComponent( cal );
530 if ( existingIncidence->
type() ==
"Todo" ) {
531 Todo *todo =
static_cast<Todo *
>( existingIncidence );
532 icalcomponent_add_component( calendarComponent,
533 d->mImpl->writeTodo( todo ) );
535 if ( existingIncidence->
type() ==
"Event" ) {
536 Event *
event =
static_cast<Event *
>( existingIncidence );
537 icalcomponent_add_component( calendarComponent,
538 d->mImpl->writeEvent( event ) );
541 icalcomponent_free( message );
545 icalproperty_xlicclass result =
546 icalclassify( message, calendarComponent, (
const char *)
"" );
551 case ICAL_XLICCLASS_PUBLISHNEW:
554 case ICAL_XLICCLASS_PUBLISHUPDATE:
557 case ICAL_XLICCLASS_OBSOLETE:
560 case ICAL_XLICCLASS_REQUESTNEW:
563 case ICAL_XLICCLASS_REQUESTUPDATE:
566 case ICAL_XLICCLASS_UNKNOWN:
572 icalcomponent_free( message );
573 icalcomponent_free( calendarComponent );
590 KTimeZone tz = d->mTimeSpec.timeZone();
591 return tz.isValid() ? tz.name() : QString();