korganizer

freebusymanager.cpp
1 /*
2  This file is part of the Groupware/KOrganizer integration.
3 
4  Requires the TQt and KDE widget libraries, available at no cost at
5  http://www.trolltech.com and http://www.kde.org respectively
6 
7  Copyright (c) 2002-2004 Klarälvdalens Datakonsult AB
8  <info@klaralvdalens-datakonsult.se>
9  Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24  MA 02110-1301, USA.
25 
26  In addition, as a special exception, the copyright holders give
27  permission to link the code of this program with any edition of
28  the TQt library by Trolltech AS, Norway (or with modified versions
29  of TQt that use the same license as TQt), and distribute linked
30  combinations including the two. You must obey the GNU General
31  Public License in all respects for all of the code used other than
32  TQt. If you modify this file, you may extend this exception to
33  your version of the file, but you are not obligated to do so. If
34  you do not wish to do so, delete this exception statement from
35  your version.
36 */
37 
38 #include "freebusymanager.h"
39 
40 #include "koprefs.h"
41 #include "mailscheduler.h"
42 #include "actionmanager.h"
43 #include "korganizer.h"
44 
45 #include <libkcal/incidencebase.h>
46 #include <libkcal/attendee.h>
47 #include <libkcal/freebusy.h>
48 #include <libkcal/journal.h>
49 #include <libkcal/calendarlocal.h>
50 #include <libkcal/icalformat.h>
51 
52 #include <tdeio/job.h>
53 #include <kdebug.h>
54 #include <tdemessagebox.h>
55 #include <tdetempfile.h>
56 #include <tdeio/jobclasses.h>
57 #include <tdeio/netaccess.h>
58 #include <tdeio/scheduler.h>
59 #include <tdeapplication.h>
60 #include <tdeconfig.h>
61 #include <tdelocale.h>
62 #include <kstandarddirs.h>
63 #include <tdeabc/stdaddressbook.h>
64 #include <tdeabc/addressee.h>
65 
66 #include <tqfile.h>
67 #include <tqbuffer.h>
68 #include <tqregexp.h>
69 #include <tqdir.h>
70 
71 #define DEBUG_5850 kdDebug(5850)
72 
73 using namespace KCal;
74 
75 FreeBusyDownloadJob::FreeBusyDownloadJob( const TQString &email, const KURL &url,
76  FreeBusyManager *manager,
77  const char *name )
78  : TQObject( manager, name ), mManager( manager ), mEmail( email )
79 {
80  TDEIO::TransferJob *job = TDEIO::get( url, false, false );
81  //pass the mainwindow to the job so any prompts are active
83  job->setWindow( korg->topLevelWidget() );
84 
85  connect( job, TQ_SIGNAL( result( TDEIO::Job * ) ),
86  TQ_SLOT( slotResult( TDEIO::Job * ) ) );
87  connect( job, TQ_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ),
88  TQ_SLOT( slotData( TDEIO::Job *, const TQByteArray & ) ) );
89  TDEIO::Scheduler::scheduleJob( job );
90 }
91 
92 FreeBusyDownloadJob::~FreeBusyDownloadJob()
93 {
94 }
95 
96 
97 void FreeBusyDownloadJob::slotData( TDEIO::Job *, const TQByteArray &data )
98 {
99  TQByteArray tmp = data;
100  tmp.resize( tmp.size() + 1 );
101  tmp[tmp.size()-1] = 0;
102  mFreeBusyData += tmp;
103 }
104 
105 void FreeBusyDownloadJob::slotResult( TDEIO::Job *job )
106 {
107  DEBUG_5850 << "FreeBusyDownloadJob::slotResult() " << mEmail << endl;
108 
109  if( job->error() ) {
110  DEBUG_5850 << "FreeBusyDownloadJob::slotResult() job error for " << mEmail << endl;
111  emit freeBusyDownloadError( mEmail );
112  } else {
113  FreeBusy *fb = mManager->iCalToFreeBusy( mFreeBusyData );
114  if ( fb ) {
115  Person p = fb->organizer();
116  p.setEmail( mEmail );
117  mManager->saveFreeBusy( fb, p );
118  }
119  emit freeBusyDownloaded( fb, mEmail );
120  }
121  deleteLater();
122 }
123 
125 
126 FreeBusyManager::FreeBusyManager( TQObject *parent, const char *name )
127  : TQObject( parent, name ),
128  mCalendar( 0 ), mTimerID( 0 ), mUploadingFreeBusy( false ),
129  mBrokenUrl( false )
130 {
131 }
132 
133 void FreeBusyManager::setCalendar( KCal::Calendar *c )
134 {
135  mCalendar = c;
136  if ( mCalendar ) {
137  mFormat.setTimeZone( mCalendar->timeZoneId(), true );
138  }
139 }
140 
141 KCal::FreeBusy *FreeBusyManager::ownerFreeBusy()
142 {
143  TQDateTime start = TQDateTime::currentDateTime();
144  TQDateTime end = start.addDays( KOPrefs::instance()->mFreeBusyPublishDays );
145 
146  FreeBusy *freebusy = new FreeBusy( mCalendar, start, end );
147  freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
148  KOPrefs::instance()->email() ) );
149 
150  return freebusy;
151 }
152 
153 TQString FreeBusyManager::ownerFreeBusyAsString()
154 {
155  FreeBusy *freebusy = ownerFreeBusy();
156 
157  TQString result = freeBusyToIcal( freebusy );
158 
159  delete freebusy;
160 
161  return result;
162 }
163 
164 TQString FreeBusyManager::freeBusyToIcal( KCal::FreeBusy *freebusy )
165 {
166  return mFormat.createScheduleMessage( freebusy, Scheduler::Publish );
167 }
168 
169 void FreeBusyManager::slotPerhapsUploadFB()
170 {
171  // user has automatic uploading disabled, bail out
172  if ( !KOPrefs::instance()->freeBusyPublishAuto() ||
173  KOPrefs::instance()->freeBusyPublishUrl().isEmpty() )
174  return;
175  if( mTimerID != 0 )
176  // A timer is already running, so we don't need to do anything
177  return;
178 
179  int now = static_cast<int>( TQDateTime::currentDateTime().toTime_t() );
180  int eta = static_cast<int>( mNextUploadTime.toTime_t() ) - now;
181 
182  if( !mUploadingFreeBusy ) {
183  // Not currently uploading
184  if( mNextUploadTime.isNull() ||
185  TQDateTime::currentDateTime() > mNextUploadTime ) {
186  // No uploading have been done in this session, or delay time is over
187  publishFreeBusy();
188  return;
189  }
190 
191  // We're in the delay time and no timer is running. Start one
192  if( eta <= 0 ) {
193  // Sanity check failed - better do the upload
194  publishFreeBusy();
195  return;
196  }
197  } else {
198  // We are currently uploading the FB list. Start the timer
199  if( eta <= 0 ) {
200  DEBUG_5850 << "This shouldn't happen! eta <= 0\n";
201  eta = 10; // whatever
202  }
203  }
204 
205  // Start the timer
206  mTimerID = startTimer( eta * 1000 );
207 
208  if( mTimerID == 0 )
209  // startTimer failed - better do the upload
210  publishFreeBusy();
211 }
212 
213 // This is used for delayed Free/Busy list uploading
214 void FreeBusyManager::timerEvent( TQTimerEvent* )
215 {
216  publishFreeBusy();
217 }
218 
219 void FreeBusyManager::setBrokenUrl( bool isBroken )
220 {
221  mBrokenUrl = isBroken;
222 }
223 
228 void FreeBusyManager::publishFreeBusy()
229 {
230  // Already uploading? Skip this one then.
231  if ( mUploadingFreeBusy )
232  return;
233  KURL targetURL( KOPrefs::instance()->freeBusyPublishUrl() );
234  if ( targetURL.isEmpty() ) {
235  KMessageBox::sorry( 0,
236  i18n( "<qt>No URL configured for uploading your free/busy list. Please "
237  "set it in KOrganizer's configuration dialog, on the \"Free/Busy\" page. "
238  "<br>Contact your system administrator for the exact URL and the "
239  "account details."
240  "</qt>" ), i18n("No Free/Busy Upload URL") );
241  return;
242  }
243  if ( mBrokenUrl ) // Url is invalid, don't try again
244  return;
245  if ( !targetURL.isValid() ) {
246  KMessageBox::sorry( 0,
247  i18n( "<qt>The target URL '%1' provided is invalid."
248  "</qt>" ).arg( targetURL.prettyURL() ), i18n("Invalid URL") );
249  mBrokenUrl = true;
250  return;
251  }
252 
253 // // Substitute %u and %d [FIXME]
254 // TQString defaultEmail = KOCore()::self()->email();
255 // int emailpos = defaultEmail.find( '@' );
256 // if (emailpos != -1) {
257 // const TQString emailName = defaultEmail.left( emailpos );
258 // const TQString emailHost = defaultEmail.mid( emailpos + 1 );
259 // targetURL = targetURL.url().replace("%25u", emailName, true);
260 // targetURL = targetURL.url().replace("%25d", emailHost, true);
261 // }
262  targetURL.setUser( KOPrefs::instance()->mFreeBusyPublishUser );
263  targetURL.setPass( KOPrefs::instance()->mFreeBusyPublishPassword );
264 
265  mUploadingFreeBusy = true;
266 
267  // If we have a timer running, it should be stopped now
268  if( mTimerID != 0 ) {
269  killTimer( mTimerID );
270  mTimerID = 0;
271  }
272 
273  // Save the time of the next free/busy uploading
274  mNextUploadTime = TQDateTime::currentDateTime();
275  if( KOPrefs::instance()->mFreeBusyPublishDelay > 0 )
276  mNextUploadTime = mNextUploadTime.addSecs(
277  KOPrefs::instance()->mFreeBusyPublishDelay * 60 );
278 
279  TQString messageText = ownerFreeBusyAsString();
280 
281  // We need to massage the list a bit so that Outlook understands
282  // it.
283  messageText = messageText.replace( TQRegExp( "ORGANIZER\\s*:MAILTO:" ),
284  "ORGANIZER:" );
285 
286  // Create a local temp file and save the message to it
287  KTempFile tempFile;
288  TQTextStream *textStream = tempFile.textStream();
289  if( textStream ) {
290  *textStream << messageText;
291  tempFile.close();
292 
293 #if 0
294  TQString defaultEmail = KOCore()::self()->email();
295  TQString emailHost = defaultEmail.mid( defaultEmail.find( '@' ) + 1 );
296 
297  // Put target string together
298  KURL targetURL;
299  if( KOPrefs::instance()->mPublishKolab ) {
300  // we use Kolab
301  TQString server;
302  if( KOPrefs::instance()->mPublishKolabServer == "%SERVER%" ||
303  KOPrefs::instance()->mPublishKolabServer.isEmpty() )
304  server = emailHost;
305  else
306  server = KOPrefs::instance()->mPublishKolabServer;
307 
308  targetURL.setProtocol( "webdavs" );
309  targetURL.setHost( server );
310 
311  TQString fbname = KOPrefs::instance()->mPublishUserName;
312  int at = fbname.find('@');
313  if( at > 1 && fbname.length() > (uint)at ) {
314  fbname = fbname.left(at);
315  }
316  targetURL.setPath( "/freebusy/" + fbname + ".ifb" );
317  targetURL.setUser( KOPrefs::instance()->mPublishUserName );
318  targetURL.setPass( KOPrefs::instance()->mPublishPassword );
319  } else {
320  // we use something else
321  targetURL = KOPrefs::instance()->mPublishAnyURL.replace( "%SERVER%",
322  emailHost );
323  targetURL.setUser( KOPrefs::instance()->mPublishUserName );
324  targetURL.setPass( KOPrefs::instance()->mPublishPassword );
325  }
326 #endif
327 
328 
329  KURL src;
330  src.setPath( tempFile.name() );
331 
332  DEBUG_5850 << "FreeBusyManager::publishFreeBusy(): " << targetURL << endl;
333 
334  TDEIO::Job * job = TDEIO::file_copy( src, targetURL, -1,
335  true /*overwrite*/,
336  false /*don't resume*/,
337  false /*don't show progress info*/ );
338  //pass the mainwindow to the job so any prompts are active
340  job->setWindow( korg->topLevelWidget() );
341 
342  connect( job, TQ_SIGNAL( result( TDEIO::Job * ) ),
343  TQ_SLOT( slotUploadFreeBusyResult( TDEIO::Job * ) ) );
344  }
345 }
346 
347 void FreeBusyManager::slotUploadFreeBusyResult(TDEIO::Job *_job)
348 {
349  TDEIO::FileCopyJob* job = static_cast<TDEIO::FileCopyJob *>(_job);
350  if ( job->error() )
351  KMessageBox::sorry( 0,
352  i18n( "<qt>The software could not upload your free/busy list to the "
353  "URL '%1'. There might be a problem with the access rights, or "
354  "you specified an incorrect URL. The system said: <em>%2</em>."
355  "<br>Please check the URL or contact your system administrator."
356  "</qt>" ).arg( job->destURL().prettyURL() )
357  .arg( job->errorString() ) );
358  // Delete temp file
359  KURL src = job->srcURL();
360  Q_ASSERT( src.isLocalFile() );
361  if( src.isLocalFile() )
362  TQFile::remove(src.path());
363  mUploadingFreeBusy = false;
364 }
365 
366 bool FreeBusyManager::retrieveFreeBusy( const TQString &email, bool forceDownload )
367 {
368  DEBUG_5850 << "FreeBusyManager::retrieveFreeBusy(): " << email << endl;
369  if ( email.isEmpty() ) return false;
370 
371  // Check for cached copy of free/busy list
372  KCal::FreeBusy *fb = loadFreeBusy( email );
373  if ( fb ) {
374  emit freeBusyRetrieved( fb, email );
375  }
376 
377  // Don't download free/busy if the user does not want it.
378  if( !KOPrefs::instance()->mFreeBusyRetrieveAuto && !forceDownload) {
379  slotFreeBusyDownloadError( email ); // fblist
380  return false;
381  }
382 
383  mRetrieveQueue.append( email );
384 
385  if ( mRetrieveQueue.count() > 1 ) return true;
386 
387  return processRetrieveQueue();
388 }
389 
390 bool FreeBusyManager::processRetrieveQueue()
391 {
392  if ( mRetrieveQueue.isEmpty() ) return true;
393 
394  TQString email = mRetrieveQueue.first();
395  mRetrieveQueue.pop_front();
396 
397  KURL sourceURL = freeBusyUrl( email );
398 
399  kdDebug(5850) << "FreeBusyManager::processRetrieveQueue(): url: " << sourceURL << endl;
400 
401  if ( !sourceURL.isValid() ) {
402  kdDebug(5850) << "Invalid FB URL\n";
403  slotFreeBusyDownloadError( email );
404  return false;
405  }
406 
407  FreeBusyDownloadJob *job = new FreeBusyDownloadJob( email, sourceURL, this,
408  "freebusy_download_job" );
409  connect( job, TQ_SIGNAL( freeBusyDownloaded( KCal::FreeBusy *,
410  const TQString & ) ),
411  TQ_SIGNAL( freeBusyRetrieved( KCal::FreeBusy *, const TQString & ) ) );
412  connect( job, TQ_SIGNAL( freeBusyDownloaded( KCal::FreeBusy *,
413  const TQString & ) ),
414  TQ_SLOT( processRetrieveQueue() ) );
415 
416  connect( job, TQ_SIGNAL( freeBusyDownloadError( const TQString& ) ),
417  this, TQ_SLOT( slotFreeBusyDownloadError( const TQString& ) ) );
418 
419  return true;
420 }
421 
422 void FreeBusyManager::slotFreeBusyDownloadError( const TQString& email )
423 {
424  if( KOPrefs::instance()->thatIsMe( email ) ) {
425  // We tried to download our own free-busy list from the net, but it failed
426  // so use local version instead.
427  // The reason we try to download even our own free-busy list is that
428  // this allows to avoid showing as busy the folders that are "fb relevant for nobody"
429  // like shared resources (meeting rooms etc.)
430  DEBUG_5850 << "freebusy of owner, falling back to local list" << endl;
431  emit freeBusyRetrieved( ownerFreeBusy(), email );
432  }
433 
434 }
435 
436 void FreeBusyManager::cancelRetrieval()
437 {
438  mRetrieveQueue.clear();
439 }
440 
441 KURL replaceVariablesURL( const KURL &url, const TQString &email )
442 {
443  TQString emailName, emailHost;
444  int emailpos = email.find( '@' );
445  if( emailpos >= 0 ) {
446  emailName = email.left( emailpos );
447  emailHost = email.mid( emailpos + 1 );
448  }
449 
450  TQString saveStr = url.path();
451  saveStr.replace( TQRegExp( "%[Ee][Mm][Aa][Ii][Ll]%" ), email );
452  saveStr.replace( TQRegExp( "%[Nn][Aa][Mm][Ee]%" ), emailName );
453  saveStr.replace( TQRegExp( "%[Ss][Ee][Rr][Vv][Ee][Rr]%" ), emailHost );
454 
455  KURL retUrl( url );
456  retUrl.setPath( saveStr );
457  return retUrl;
458 }
459 
460 bool fbExists( const KURL &url )
461 {
462  // We need this function because using TDEIO::NetAccess::exists()
463  // is useless for the http and https protocols. And getting back
464  // arbitrary data is also useless because a server can respond back
465  // with a "no such document" page. So we need smart checking.
466 
467  TDEIO::Job *job = TDEIO::get( url, false, false );
468  TQByteArray data;
469  if ( TDEIO::NetAccess::synchronousRun( job, 0, &data ) ) {
470  TQString dataStr ( data );
471  if ( dataStr.contains( "BEGIN:VCALENDAR" ) ) {
472  return true;
473  }
474  }
475  return false;
476 }
477 
478 KURL FreeBusyManager::freeBusyUrl( const TQString &email )
479 {
480  DEBUG_5850 << "FreeBusyManager::freeBusyUrl(): " << email << endl;
481 
482  // First check if there is a specific FB url for this email
483  TQString configFile = locateLocal( "data", "korganizer/freebusyurls" );
484  TDEConfig cfg( configFile );
485 
486  cfg.setGroup( email );
487  TQString url = cfg.readEntry( "url" );
488  if ( !url.isEmpty() ) {
489  kdDebug(5850) << "found cached url: " << url << endl;
490  KURL cachedURL( url );
491  if ( KOPrefs::instance()->thatIsMe( email ) ) {
492  cachedURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
493  cachedURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
494  }
495  return replaceVariablesURL( cachedURL, email );
496  }
497 
498  // Try with the url configurated by preferred email in kaddressbook
499  TDEABC::Addressee::List list= TDEABC::StdAddressBook::self( true )->findByEmail( email );
500  TDEABC::Addressee::List::Iterator it;
501  TQString pref;
502  for ( it = list.begin(); it != list.end(); ++it ) {
503  pref = (*it).preferredEmail();
504  if ( !pref.isEmpty() && pref != email ) {
505  kdDebug(5850) << "FreeBusyManager::freeBusyUrl():"
506  << "Preferred email of " << email << " is " << pref << endl;
507  cfg.setGroup( pref );
508  url = cfg.readEntry ( "url" );
509  if ( !url.isEmpty() ) {
510  kdDebug(5850) << "FreeBusyManager::freeBusyUrl():"
511  << "Taken url from preferred email:" << url << endl;
512  return replaceVariablesURL( KURL( url ), email );
513  }
514  }
515  }
516  // None found. Check if we do automatic FB retrieving then
517  if ( !KOPrefs::instance()->mFreeBusyRetrieveAuto ) {
518  kdDebug( 5850 ) << "no auto retrieving" << endl;
519  // No, so no FB list here
520  return KURL();
521  }
522 
523  // Sanity check: Don't download if it's not a correct email
524  // address (this also avoids downloading for "(empty email)").
525  int emailpos = email.find( '@' );
526  if( emailpos == -1 ) {
527  return KURL();
528  }
529 
530  // Cut off everything left of the @ sign to get the user name.
531  const TQString emailName = email.left( emailpos );
532  const TQString emailHost = email.mid( emailpos + 1 );
533 
534  // Build the URL
535  KURL sourceURL;
536  sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl;
537 
538  if ( KOPrefs::instance()->mFreeBusyCheckHostname ) {
539  // Don't try to fetch free/busy data for users not on the specified servers
540  // This tests if the hostnames match, or one is a subset of the other
541  const TQString hostDomain = sourceURL.host();
542  if ( hostDomain != emailHost &&
543  !hostDomain.endsWith( '.' + emailHost ) &&
544  !emailHost.endsWith( '.' + hostDomain ) ) {
545  // Host names do not match
546  kdDebug(5850) << "Host '" << sourceURL.host() << "' doesn't match email '" << email << endl;
547  return KURL();
548  }
549  }
550 
551  if ( sourceURL.url().contains( TQRegExp( "\\.[xiv]fb$" ) ) ) { // user specified a fullpath
552  // do variable string replacements to the URL (MS Outlook style)
553  KURL fullpathURL = replaceVariablesURL( sourceURL, email );
554 
555  // This should work with anything thrown at it, not just Kolab
556  // Notice that Kolab URLs are just entered as the base address, e.g. http://server.com/mykolab/
557  // This means that if the trailing slash is not entered, we can treat this as a custom, non-Kolab URL!
558  // In that case, just pass it on through with substitution for %u and %d
559  // TODO: May want an explicit configuration option in kogroupwareprefspage.ui for this
560  if ((fullpathURL.url().endsWith("/", true) == false) || (fullpathURL.url().contains("%25u", true)) || (fullpathURL.url().contains("%25d", true))) {
561  // A generic URL, substitute %u and %d
562  fullpathURL = fullpathURL.url().replace("%25u", emailName, true);
563  fullpathURL = fullpathURL.url().replace("%25d", emailHost, true);
564  }
565  else {
566  // This is (probably) a Kolab URL!
567  }
568 
569  // set the User and Password part of the URL
570  fullpathURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
571  fullpathURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
572 
573  // no need to cache this URL as this is pretty fast to get from the config value.
574 
575  // return the fullpath URL
576  return fullpathURL;
577  }
578 
579  // else we search for a fb file in the specified URL with known possible extensions
580 
581  TQStringList extensions;
582  extensions << "xfb" << "ifb" << "vfb";
583  TQStringList::ConstIterator ext;
584  for ( ext = extensions.constBegin(); ext != extensions.constEnd(); ++ext ) {
585  // build a url for this extension
586  sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl;
587  KURL dirURL = replaceVariablesURL( sourceURL, email );
588  if ( KOPrefs::instance()->mFreeBusyFullDomainRetrieval ) {
589  dirURL.addPath( email + '.' + (*ext) );
590  } else {
591  dirURL.addPath( emailName + '.' + (*ext ) );
592  }
593  dirURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
594  dirURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
595  if ( fbExists( dirURL ) ) {
596  // write the URL to the cache
597  cfg.setGroup( email );
598  cfg.writeEntry( "url", dirURL.prettyURL() ); // prettyURL() does not write user nor password
599  return dirURL;
600  }
601  }
602 
603  return KURL();
604 }
605 
606 KCal::FreeBusy *FreeBusyManager::iCalToFreeBusy( const TQCString &data )
607 {
608  kdDebug(5850) << "FreeBusyManager::iCalToFreeBusy()" << endl;
609  kdDebug(5850) << data << endl;
610 
611  TQString freeBusyVCal = TQString::fromUtf8( data );
612  KCal::FreeBusy *fb = mFormat.parseFreeBusy( freeBusyVCal );
613  if ( !fb ) {
614  kdDebug(5850) << "FreeBusyManager::iCalToFreeBusy(): Error parsing free/busy"
615  << endl;
616  kdDebug(5850) << freeBusyVCal << endl;
617  }
618  return fb;
619 }
620 
621 TQString FreeBusyManager::freeBusyDir()
622 {
623  return locateLocal( "data", "korganizer/freebusy" );
624 }
625 
626 FreeBusy *FreeBusyManager::loadFreeBusy( const TQString &email )
627 {
628  DEBUG_5850 << "FreeBusyManager::loadFreeBusy(): " << email << endl;
629 
630  TQString fbd = freeBusyDir();
631 
632  TQFile f( fbd + "/" + email + ".ifb" );
633  if ( !f.exists() ) {
634  DEBUG_5850 << "FreeBusyManager::loadFreeBusy() " << f.name()
635  << " doesn't exist." << endl;
636  return 0;
637  }
638 
639  if ( !f.open( IO_ReadOnly ) ) {
640  DEBUG_5850 << "FreeBusyManager::loadFreeBusy() Unable to open file "
641  << f.name() << endl;
642  return 0;
643  }
644 
645  TQTextStream ts( &f );
646  TQString str = ts.read();
647 
648  return iCalToFreeBusy( str.utf8() );
649 }
650 
651 bool FreeBusyManager::saveFreeBusy( FreeBusy *freebusy, const Person &person )
652 {
653  DEBUG_5850 << "FreeBusyManager::saveFreeBusy(): " << person.fullName() << endl;
654 
655  TQString fbd = freeBusyDir();
656 
657  TQDir freeBusyDirectory( fbd );
658  if ( !freeBusyDirectory.exists() ) {
659  DEBUG_5850 << "Directory " << fbd << " does not exist!" << endl;
660  DEBUG_5850 << "Creating directory: " << fbd << endl;
661 
662  if( !freeBusyDirectory.mkdir( fbd, true ) ) {
663  DEBUG_5850 << "Could not create directory: " << fbd << endl;
664  return false;
665  }
666  }
667 
668  TQString filename( fbd );
669  filename += "/";
670  filename += person.email();
671  filename += ".ifb";
672  TQFile f( filename );
673 
674  DEBUG_5850 << "FreeBusyManager::saveFreeBusy(): filename: " << filename
675  << endl;
676 
677  freebusy->clearAttendees();
678  freebusy->setOrganizer( person );
679 
680  TQString messageText = mFormat.createScheduleMessage( freebusy,
681  Scheduler::Publish );
682 
683  if ( !f.open( IO_ReadWrite ) ) {
684  DEBUG_5850 << "acceptFreeBusy: Can't open:" << filename << " for writing"
685  << endl;
686  return false;
687  }
688  TQTextStream t( &f );
689  t << messageText;
690  f.close();
691 
692  return true;
693 }
694 
695 #include "freebusymanager.moc"
static KOrg::MainWindow * findInstance(const KURL &url)
Is there a instance with this URL?
Class for downloading FreeBusy Lists.
void setOrganizer(const Person &o)
interface for korganizer main window
Definition: mainwindow.h:41
virtual TQWidget * topLevelWidget()=0
Return widget whcih represents this main window.