summaryrefslogtreecommitdiffabout
path: root/libkcal/icalformat.cpp
Unidiff
Diffstat (limited to 'libkcal/icalformat.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/icalformat.cpp478
1 files changed, 478 insertions, 0 deletions
diff --git a/libkcal/icalformat.cpp b/libkcal/icalformat.cpp
new file mode 100644
index 0000000..5893db5
--- a/dev/null
+++ b/libkcal/icalformat.cpp
@@ -0,0 +1,478 @@
1/*
2 This file is part of libkcal.
3 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21#include <qdatetime.h>
22#include <qstring.h>
23#include <qptrlist.h>
24#include <qregexp.h>
25#include <qclipboard.h>
26#include <qfile.h>
27#include <qtextstream.h>
28#include <qtextcodec.h>
29#include <stdlib.h>
30
31#include <kdebug.h>
32#include <kglobal.h>
33#include <klocale.h>
34
35extern "C" {
36 #include <ical.h>
37 #include <icalss.h>
38 #include <icalparser.h>
39 #include <icalrestriction.h>
40}
41
42#include "calendar.h"
43#include "calendarlocal.h"
44#include "journal.h"
45
46#include "icalformat.h"
47#include "icalformatimpl.h"
48
49#define _ICAL_VERSION "2.0"
50
51using namespace KCal;
52
53ICalFormat::ICalFormat(bool quick )
54{
55 mQuicksave = false; //quick;
56 mImpl = new ICalFormatImpl( this );
57 tzOffsetMin = 0;
58 //qDebug("new ICalFormat() ");
59}
60
61ICalFormat::~ICalFormat()
62{
63 delete mImpl;
64 //qDebug("delete ICalFormat ");
65}
66
67bool ICalFormat::load( Calendar *calendar, const QString &fileName)
68{
69
70 clearException();
71
72 QFile file( fileName );
73 if (!file.open( IO_ReadOnly ) ) {
74 setException(new ErrorFormat(ErrorFormat::LoadError));
75 return false;
76 }
77 QTextStream ts( &file );
78 QString text;
79#if 0
80 if ( !mQuicksave ) {
81 qDebug("KO: No quickload!");
82 ts.setEncoding( QTextStream::Latin1 );
83 text = ts.read();
84 } else {
85 ts.setCodec( QTextCodec::codecForName("utf8") );
86 text = ts.read();
87 }
88#endif
89 ts.setEncoding( QTextStream::Latin1 );
90 text = ts.read();
91 file.close();
92
93 return fromString( calendar, text );
94}
95
96//#include <qdatetime.h>
97bool ICalFormat::save( Calendar *calendar, const QString &fileName )
98{
99 //kdDebug(5800) << "ICalFormat::save(): " << fileName << endl;
100 //qDebug("ICalFormat::save ");
101 clearException();
102 QString text = toString( calendar );
103 //return false;
104 // qDebug("to string takes ms: %d ",is.elapsed() );
105 if ( text.isNull() ) return false;
106
107 // TODO: write backup file
108 //is.restart();
109 QFile file( fileName );
110 if (!file.open( IO_WriteOnly ) ) {
111 setException(new ErrorFormat(ErrorFormat::SaveError,
112 i18n("Could not open file '%1'").arg(fileName)));
113 return false;
114 }
115 QTextStream ts( &file );
116
117// #ifdef DESKTOP_VERSION
118// mQuicksave = false;
119// #endif
120// if ( mQuicksave ) {
121// ts << text.utf8();
122// } else {
123// ts.setEncoding( QTextStream::Latin1 );
124// ts << text;
125// //ts << text.latin1();
126// }
127 ts.setEncoding( QTextStream::Latin1 );
128 ts << text;
129 file.close();
130 //qDebug("saving file takes ms: %d ", is.elapsed() );
131 return true;
132}
133
134bool ICalFormat::fromString( Calendar *cal, const QString &text )
135{
136 setTimeZone( cal->timeZoneId(), !cal->isLocalTime() );
137 // qDebug("ICalFormat::fromString tz: %s ", cal->timeZoneId().latin1());
138 // Get first VCALENDAR component.
139 // TODO: Handle more than one VCALENDAR or non-VCALENDAR top components
140 icalcomponent *calendar;
141
142 //calendar = icalcomponent_new_from_string( text.local8Bit().data());
143 // good calendar = icalcomponent_new_from_string( text.utf8().data());
144 calendar = icalcomponent_new_from_string( (char*)text.latin1());
145 if (!calendar) {
146 setException(new ErrorFormat(ErrorFormat::ParseErrorIcal));
147 return false;
148 }
149
150 bool success = true;
151
152 if (icalcomponent_isa(calendar) != ICAL_VCALENDAR_COMPONENT) {
153 setException(new ErrorFormat(ErrorFormat::NoCalendar));
154 success = false;
155 } else {
156 // put all objects into their proper places
157 if ( !mImpl->populate( cal, calendar ) ) {
158 if ( !exception() ) {
159 setException(new ErrorFormat(ErrorFormat::ParseErrorKcal));
160 }
161 success = false;
162 } else
163 mLoadedProductId = mImpl->loadedProductId();
164 }
165
166 icalcomponent_free( calendar );
167
168 return success;
169}
170
171Incidence *ICalFormat::fromString( const QString &text )
172{
173 CalendarLocal cal( mTimeZoneId );
174 fromString(&cal, text);
175
176 Incidence *ical = 0;
177 QPtrList<Event> elist = cal.events();
178 if ( elist.count() > 0 ) {
179 ical = elist.first();
180 } else {
181 QPtrList<Todo> tlist = cal.todos();
182 if ( tlist.count() > 0 ) {
183 ical = tlist.first();
184 } else {
185 QPtrList<Journal> jlist = cal.journals();
186 if ( jlist.count() > 0 ) {
187 ical = jlist.first();
188 }
189 }
190 }
191 return ical;
192}
193#include <qapp.h>
194
195QString ICalFormat::toString( Calendar *cal )
196{
197
198 setTimeZone( cal->timeZoneId(), !cal->isLocalTime() );
199
200 icalcomponent *calendar = mImpl->createCalendarComponent(cal);
201
202 icalcomponent *component;
203
204 // todos
205 QPtrList<Todo> todoList = cal->rawTodos();
206 QPtrListIterator<Todo> qlt(todoList);
207 for (; qlt.current(); ++qlt) {
208 component = mImpl->writeTodo(qlt.current());
209 icalcomponent_add_component(calendar,component);
210 //qDebug(" todos ");
211 qApp->processEvents();
212 }
213 // events
214 QPtrList<Event> events = cal->rawEvents();
215 Event *ev;
216 for(ev=events.first();ev;ev=events.next()) {
217 component = mImpl->writeEvent(ev);
218 icalcomponent_add_component(calendar,component);
219 //qDebug("events ");
220 qApp->processEvents();
221 }
222
223 // journals
224 QPtrList<Journal> journals = cal->journals();
225 Journal *j;
226 for(j=journals.first();j;j=journals.next()) {
227 component = mImpl->writeJournal(j);
228 icalcomponent_add_component(calendar,component);
229 //qDebug("journals ");
230 qApp->processEvents();
231 }
232 const char *text;
233 QString ret ="";
234 text = icalcomponent_as_ical_string( calendar );
235 qApp->processEvents();
236
237 // text = "BEGIN:VCALENDAR\nPRODID\n :-//K Desktop Environment//NONSGML libkcal 3.1//EN\nVERSION\n :2.0\nBEGIN:VEVENT\nDTSTAMP\n :20031231T213514Z\nORGANIZER\n :MAILTO:lutz@putz.de\nCREATED\n :20031231T213513Z\nUID\n :libkcal-1295166342.120\nSEQUENCE\n :0\nLAST-MODIFIED\n :20031231T213513Z\nSUMMARY\n :test1\nCLASS\n :PUBLIC\nPRIORITY\n :3\nDTSTART\n :20040101T090000Z\nDTEND\n :20040101T110000Z\nTRANSP\n :OPAQUE\nEND:VEVENT\nEND:VCALENDAR\n";
238
239
240 if ( text ) {
241 ret = QString ( text );
242 }
243 icalcomponent_free( calendar );
244
245 if (!text) {
246 setException(new ErrorFormat(ErrorFormat::SaveError,
247 i18n("libical error")));
248 return QString::null;
249 }
250
251 return ret;
252}
253
254QString ICalFormat::toICalString( Incidence *incidence )
255{
256 CalendarLocal cal( mTimeZoneId );
257 cal.addIncidence( incidence->clone() );
258 return toString( &cal );
259}
260
261QString ICalFormat::toString( Incidence *incidence )
262{
263 icalcomponent *component;
264
265 component = mImpl->writeIncidence( incidence );
266
267 const char *text = icalcomponent_as_ical_string( component );
268
269 icalcomponent_free( component );
270
271 return QString::fromLocal8Bit( text );
272}
273
274QString ICalFormat::toString( Recurrence *recurrence )
275{
276 icalproperty *property;
277 property = mImpl->writeRecurrenceRule( recurrence );
278 const char *text = icalproperty_as_ical_string( property );
279 icalproperty_free( property );
280 return QString::fromLocal8Bit( text );
281}
282/*
283bool ICalFormat::fromString( Recurrence * recurrence, const QString& rrule )
284{
285 bool success = true;
286 icalerror_clear_errno();
287 struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule );
288 if ( icalerrno != ICAL_NO_ERROR ) {
289 kdDebug() << "Recurrence parsing error: " << icalerror_strerror( icalerrno ) << endl;
290 success = false;
291 }
292
293 if ( success ) {
294 mImpl->readRecurrence( recur, recurrence );
295 }
296
297 return success;
298}
299*/
300
301QString ICalFormat::createScheduleMessage(IncidenceBase *incidence,
302 Scheduler::Method method)
303{
304 icalcomponent *message = mImpl->createScheduleComponent(incidence,method);
305
306 QString messageText = icalcomponent_as_ical_string(message);
307
308
309
310 return messageText;
311}
312
313ScheduleMessage *ICalFormat::parseScheduleMessage( Calendar *cal,
314 const QString &messageText )
315{
316 setTimeZone( cal->timeZoneId(), !cal->isLocalTime() );
317 clearException();
318
319 if (messageText.isEmpty()) return 0;
320
321 icalcomponent *message;
322 message = icalparser_parse_string(messageText.local8Bit());
323
324 if (!message) return 0;
325
326 icalproperty *m = icalcomponent_get_first_property(message,
327 ICAL_METHOD_PROPERTY);
328
329 if (!m) return 0;
330
331 icalcomponent *c;
332
333 IncidenceBase *incidence = 0;
334 c = icalcomponent_get_first_component(message,ICAL_VEVENT_COMPONENT);
335 if (c) {
336 incidence = mImpl->readEvent(c);
337 }
338
339 if (!incidence) {
340 c = icalcomponent_get_first_component(message,ICAL_VTODO_COMPONENT);
341 if (c) {
342 incidence = mImpl->readTodo(c);
343 }
344 }
345
346 if (!incidence) {
347 c = icalcomponent_get_first_component(message,ICAL_VFREEBUSY_COMPONENT);
348 if (c) {
349 incidence = mImpl->readFreeBusy(c);
350 }
351 }
352
353 if (!incidence) {
354 kdDebug() << "ICalFormat:parseScheduleMessage: object is not a freebusy, event or todo" << endl;
355 return 0;
356 }
357
358 kdDebug(5800) << "ICalFormat::parseScheduleMessage() getting method..." << endl;
359
360 icalproperty_method icalmethod = icalproperty_get_method(m);
361 Scheduler::Method method;
362
363 switch (icalmethod) {
364 case ICAL_METHOD_PUBLISH:
365 method = Scheduler::Publish;
366 break;
367 case ICAL_METHOD_REQUEST:
368 method = Scheduler::Request;
369 break;
370 case ICAL_METHOD_REFRESH:
371 method = Scheduler::Refresh;
372 break;
373 case ICAL_METHOD_CANCEL:
374 method = Scheduler::Cancel;
375 break;
376 case ICAL_METHOD_ADD:
377 method = Scheduler::Add;
378 break;
379 case ICAL_METHOD_REPLY:
380 method = Scheduler::Reply;
381 break;
382 case ICAL_METHOD_COUNTER:
383 method = Scheduler::Counter;
384 break;
385 case ICAL_METHOD_DECLINECOUNTER:
386 method = Scheduler::Declinecounter;
387 break;
388 default:
389 method = Scheduler::NoMethod;
390 kdDebug(5800) << "ICalFormat::parseScheduleMessage(): Unknow method" << endl;
391 break;
392 }
393
394
395 if (!icalrestriction_check(message)) {
396 setException(new ErrorFormat(ErrorFormat::Restriction,
397 Scheduler::translatedMethodName(method) + ": " +
398 mImpl->extractErrorProperty(c)));
399 return 0;
400 }
401
402 icalcomponent *calendarComponent = mImpl->createCalendarComponent(cal);
403
404 Incidence *existingIncidence = cal->event(incidence->uid());
405 if (existingIncidence) {
406 // TODO: check, if cast is required, or if it can be done by virtual funcs.
407 if (existingIncidence->type() == "Todo") {
408 Todo *todo = static_cast<Todo *>(existingIncidence);
409 icalcomponent_add_component(calendarComponent,
410 mImpl->writeTodo(todo));
411 }
412 if (existingIncidence->type() == "Event") {
413 Event *event = static_cast<Event *>(existingIncidence);
414 icalcomponent_add_component(calendarComponent,
415 mImpl->writeEvent(event));
416 }
417 } else {
418 calendarComponent = 0;
419 }
420
421
422 icalclass result = icalclassify(message,calendarComponent,(char *)"");
423
424
425 ScheduleMessage::Status status;
426
427 switch (result) {
428 case ICAL_PUBLISH_NEW_CLASS:
429 status = ScheduleMessage::PublishNew;
430 break;
431 case ICAL_OBSOLETE_CLASS:
432 status = ScheduleMessage::Obsolete;
433 break;
434 case ICAL_REQUEST_NEW_CLASS:
435 status = ScheduleMessage::RequestNew;
436 break;
437 case ICAL_REQUEST_UPDATE_CLASS:
438 status = ScheduleMessage::RequestUpdate;
439 break;
440 case ICAL_UNKNOWN_CLASS:
441 default:
442 status = ScheduleMessage::Unknown;
443 break;
444 }
445
446 return new ScheduleMessage(incidence,method,status);
447}
448
449void ICalFormat::setTimeZone( const QString &id, bool utc )
450{
451
452
453 mTimeZoneId = id;
454 mUtc = utc;
455
456 tzOffsetMin = KGlobal::locale()->timezoneOffset(mTimeZoneId);
457
458 //qDebug("ICalFormat::setTimeZoneOffset %s %d ",mTimeZoneId.latin1(), tzOffsetMin);
459}
460
461QString ICalFormat::timeZoneId() const
462{
463 return mTimeZoneId;
464}
465
466bool ICalFormat::utc() const
467{
468 return mUtc;
469}
470int ICalFormat::timeOffset()
471{
472 return tzOffsetMin;
473}
474const char *ICalFormat::tzString()
475{
476 const char* ret = (const char* ) mTzString;
477 return ret;
478}