korganizer

freebusymanager.cpp

00001 /*
00002   This file is part of the Groupware/KOrganizer integration.
00003 
00004   Requires the TQt and KDE widget libraries, available at no cost at
00005   http://www.trolltech.com and http://www.kde.org respectively
00006 
00007   Copyright (c) 2002-2004 Klar�vdalens Datakonsult AB
00008         <info@klaralvdalens-datakonsult.se>
00009   Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
00010 
00011   This program is free software; you can redistribute it and/or modify
00012   it under the terms of the GNU General Public License as published by
00013   the Free Software Foundation; either version 2 of the License, or
00014   (at your option) any later version.
00015 
00016   This program is distributed in the hope that it will be useful,
00017   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019   GNU General Public License for more details.
00020 
00021   You should have received a copy of the GNU General Public License
00022   along with this program; if not, write to the Free Software
00023   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00024   MA  02110-1301, USA.
00025 
00026   In addition, as a special exception, the copyright holders give
00027   permission to link the code of this program with any edition of
00028   the TQt library by Trolltech AS, Norway (or with modified versions
00029   of TQt that use the same license as TQt), and distribute linked
00030   combinations including the two.  You must obey the GNU General
00031   Public License in all respects for all of the code used other than
00032   TQt.  If you modify this file, you may extend this exception to
00033   your version of the file, but you are not obligated to do so.  If
00034   you do not wish to do so, delete this exception statement from
00035   your version.
00036 */
00037 
00038 #include "freebusymanager.h"
00039 
00040 #include "koprefs.h"
00041 #include "mailscheduler.h"
00042 #include "actionmanager.h"
00043 #include "korganizer.h"
00044 
00045 #include <libkcal/incidencebase.h>
00046 #include <libkcal/attendee.h>
00047 #include <libkcal/freebusy.h>
00048 #include <libkcal/journal.h>
00049 #include <libkcal/calendarlocal.h>
00050 #include <libkcal/icalformat.h>
00051 
00052 #include <kio/job.h>
00053 #include <kdebug.h>
00054 #include <kmessagebox.h>
00055 #include <ktempfile.h>
00056 #include <kio/jobclasses.h>
00057 #include <kio/netaccess.h>
00058 #include <kio/scheduler.h>
00059 #include <kapplication.h>
00060 #include <kconfig.h>
00061 #include <klocale.h>
00062 #include <kstandarddirs.h>
00063 #include <kabc/stdaddressbook.h>
00064 #include <kabc/addressee.h>
00065 
00066 #include <tqfile.h>
00067 #include <tqbuffer.h>
00068 #include <tqregexp.h>
00069 #include <tqdir.h>
00070 
00071 #define DEBUG_5850 kdDebug(5850)
00072 
00073 using namespace KCal;
00074 
00075 FreeBusyDownloadJob::FreeBusyDownloadJob( const TQString &email, const KURL &url,
00076                                           FreeBusyManager *manager,
00077                                           const char *name )
00078   : TQObject( manager, name ), mManager( manager ), mEmail( email )
00079 {
00080   KIO::TransferJob *job = KIO::get( url, false, false );
00081   //pass the mainwindow to the job so any prompts are active
00082   KOrg::MainWindow *korg = ActionManager::findInstance( KURL() );
00083   job->setWindow( korg->topLevelWidget() );
00084 
00085   connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
00086            TQT_SLOT( slotResult( KIO::Job * ) ) );
00087   connect( job, TQT_SIGNAL( data( KIO::Job *, const TQByteArray & ) ),
00088            TQT_SLOT( slotData( KIO::Job *, const TQByteArray & ) ) );
00089   KIO::Scheduler::scheduleJob( job );
00090 }
00091 
00092 FreeBusyDownloadJob::~FreeBusyDownloadJob()
00093 {
00094 }
00095 
00096 
00097 void FreeBusyDownloadJob::slotData( KIO::Job *, const TQByteArray &data )
00098 {
00099   TQByteArray tmp = data;
00100   tmp.resize( tmp.size() + 1 );
00101   tmp[tmp.size()-1] = 0;
00102   mFreeBusyData += tmp;
00103 }
00104 
00105 void FreeBusyDownloadJob::slotResult( KIO::Job *job )
00106 {
00107   DEBUG_5850 << "FreeBusyDownloadJob::slotResult() " << mEmail << endl;
00108 
00109   if( job->error() ) {
00110     DEBUG_5850 << "FreeBusyDownloadJob::slotResult() job error for " << mEmail << endl;
00111     emit freeBusyDownloadError( mEmail );
00112   } else {
00113     FreeBusy *fb = mManager->iCalToFreeBusy( mFreeBusyData );
00114     if ( fb ) {
00115       Person p = fb->organizer();
00116       p.setEmail( mEmail );
00117       mManager->saveFreeBusy( fb, p );
00118     }
00119     emit freeBusyDownloaded( fb, mEmail );
00120   }
00121   deleteLater();
00122 }
00123 
00125 
00126 FreeBusyManager::FreeBusyManager( TQObject *parent, const char *name )
00127   : TQObject( parent, name ),
00128     mCalendar( 0 ), mTimerID( 0 ), mUploadingFreeBusy( false ),
00129     mBrokenUrl( false )
00130 {
00131 }
00132 
00133 void FreeBusyManager::setCalendar( KCal::Calendar *c )
00134 {
00135   mCalendar = c;
00136   if ( mCalendar ) {
00137     mFormat.setTimeZone( mCalendar->timeZoneId(), true );
00138   }
00139 }
00140 
00141 KCal::FreeBusy *FreeBusyManager::ownerFreeBusy()
00142 {
00143   TQDateTime start = TQDateTime::currentDateTime();
00144   TQDateTime end = start.addDays( KOPrefs::instance()->mFreeBusyPublishDays );
00145 
00146   FreeBusy *freebusy = new FreeBusy( mCalendar, start, end );
00147   freebusy->setOrganizer( Person( KOPrefs::instance()->fullName(),
00148                           KOPrefs::instance()->email() ) );
00149 
00150   return freebusy;
00151 }
00152 
00153 TQString FreeBusyManager::ownerFreeBusyAsString()
00154 {
00155   FreeBusy *freebusy = ownerFreeBusy();
00156 
00157   TQString result = freeBusyToIcal( freebusy );
00158 
00159   delete freebusy;
00160 
00161   return result;
00162 }
00163 
00164 TQString FreeBusyManager::freeBusyToIcal( KCal::FreeBusy *freebusy )
00165 {
00166   return mFormat.createScheduleMessage( freebusy, Scheduler::Publish );
00167 }
00168 
00169 void FreeBusyManager::slotPerhapsUploadFB()
00170 {
00171   // user has automatic uploading disabled, bail out
00172   if ( !KOPrefs::instance()->freeBusyPublishAuto() ||
00173        KOPrefs::instance()->freeBusyPublishUrl().isEmpty() )
00174      return;
00175   if( mTimerID != 0 )
00176     // A timer is already running, so we don't need to do anything
00177     return;
00178 
00179   int now = static_cast<int>( TQDateTime::currentDateTime().toTime_t() );
00180   int eta = static_cast<int>( mNextUploadTime.toTime_t() ) - now;
00181 
00182   if( !mUploadingFreeBusy ) {
00183     // Not currently uploading
00184     if( mNextUploadTime.isNull() ||
00185         TQDateTime::currentDateTime() > mNextUploadTime ) {
00186       // No uploading have been done in this session, or delay time is over
00187       publishFreeBusy();
00188       return;
00189     }
00190 
00191     // We're in the delay time and no timer is running. Start one
00192     if( eta <= 0 ) {
00193       // Sanity check failed - better do the upload
00194       publishFreeBusy();
00195       return;
00196     }
00197   } else {
00198     // We are currently uploading the FB list. Start the timer
00199     if( eta <= 0 ) {
00200       DEBUG_5850 << "This shouldn't happen! eta <= 0\n";
00201       eta = 10; // whatever
00202     }
00203   }
00204 
00205   // Start the timer
00206   mTimerID = startTimer( eta * 1000 );
00207 
00208   if( mTimerID == 0 )
00209     // startTimer failed - better do the upload
00210     publishFreeBusy();
00211 }
00212 
00213 // This is used for delayed Free/Busy list uploading
00214 void FreeBusyManager::timerEvent( TQTimerEvent* )
00215 {
00216   publishFreeBusy();
00217 }
00218 
00219 void FreeBusyManager::setBrokenUrl( bool isBroken )
00220 {
00221   mBrokenUrl = isBroken;
00222 }
00223 
00228 void FreeBusyManager::publishFreeBusy()
00229 {
00230   // Already uploading? Skip this one then.
00231   if ( mUploadingFreeBusy )
00232     return;
00233   KURL targetURL( KOPrefs::instance()->freeBusyPublishUrl() );
00234   if ( targetURL.isEmpty() )  {
00235     KMessageBox::sorry( 0,
00236       i18n( "<qt>No URL configured for uploading your free/busy list. Please "
00237             "set it in KOrganizer's configuration dialog, on the \"Free/Busy\" page. "
00238             "<br>Contact your system administrator for the exact URL and the "
00239             "account details."
00240             "</qt>" ), i18n("No Free/Busy Upload URL") );
00241     return;
00242   }
00243   if ( mBrokenUrl ) // Url is invalid, don't try again
00244     return;
00245   if ( !targetURL.isValid() ) {
00246      KMessageBox::sorry( 0,
00247       i18n( "<qt>The target URL '%1' provided is invalid."
00248             "</qt>" ).arg( targetURL.prettyURL() ), i18n("Invalid URL") );
00249     mBrokenUrl = true;
00250     return;
00251   }
00252 
00253 //   // Substitute %u and %d [FIXME]
00254 //   TQString defaultEmail = KOCore()::self()->email();
00255 //   int emailpos = defaultEmail.find( '@' );
00256 //   if (emailpos != -1) {
00257 //     const TQString emailName = defaultEmail.left( emailpos );
00258 //     const TQString emailHost = defaultEmail.mid( emailpos + 1 );
00259 //     targetURL = targetURL.url().replace("%25u", emailName, true);
00260 //     targetURL = targetURL.url().replace("%25d", emailHost, true);
00261 //   }
00262   targetURL.setUser( KOPrefs::instance()->mFreeBusyPublishUser );
00263   targetURL.setPass( KOPrefs::instance()->mFreeBusyPublishPassword );
00264 
00265   mUploadingFreeBusy = true;
00266 
00267   // If we have a timer running, it should be stopped now
00268   if( mTimerID != 0 ) {
00269     killTimer( mTimerID );
00270     mTimerID = 0;
00271   }
00272 
00273   // Save the time of the next free/busy uploading
00274   mNextUploadTime = TQDateTime::currentDateTime();
00275   if( KOPrefs::instance()->mFreeBusyPublishDelay > 0 )
00276     mNextUploadTime = mNextUploadTime.addSecs(
00277         KOPrefs::instance()->mFreeBusyPublishDelay * 60 );
00278 
00279   TQString messageText = ownerFreeBusyAsString();
00280 
00281   // We need to massage the list a bit so that Outlook understands
00282   // it.
00283   messageText = messageText.replace( TQRegExp( "ORGANIZER\\s*:MAILTO:" ),
00284                                      "ORGANIZER:" );
00285 
00286   // Create a local temp file and save the message to it
00287   KTempFile tempFile;
00288   TQTextStream *textStream = tempFile.textStream();
00289   if( textStream ) {
00290     *textStream << messageText;
00291     tempFile.close();
00292 
00293 #if 0
00294     TQString defaultEmail = KOCore()::self()->email();
00295     TQString emailHost = defaultEmail.mid( defaultEmail.find( '@' ) + 1 );
00296 
00297     // Put target string together
00298     KURL targetURL;
00299     if( KOPrefs::instance()->mPublishKolab ) {
00300       // we use Kolab
00301       TQString server;
00302       if( KOPrefs::instance()->mPublishKolabServer == "%SERVER%" ||
00303       KOPrefs::instance()->mPublishKolabServer.isEmpty() )
00304     server = emailHost;
00305       else
00306     server = KOPrefs::instance()->mPublishKolabServer;
00307 
00308       targetURL.setProtocol( "webdavs" );
00309       targetURL.setHost( server );
00310 
00311       TQString fbname = KOPrefs::instance()->mPublishUserName;
00312       int at = fbname.find('@');
00313       if( at > 1 && fbname.length() > (uint)at ) {
00314     fbname = fbname.left(at);
00315       }
00316       targetURL.setPath( "/freebusy/" + fbname + ".ifb" );
00317       targetURL.setUser( KOPrefs::instance()->mPublishUserName );
00318       targetURL.setPass( KOPrefs::instance()->mPublishPassword );
00319     } else {
00320       // we use something else
00321       targetURL = KOPrefs::instance()->mPublishAnyURL.replace( "%SERVER%",
00322                                                                emailHost );
00323       targetURL.setUser( KOPrefs::instance()->mPublishUserName );
00324       targetURL.setPass( KOPrefs::instance()->mPublishPassword );
00325     }
00326 #endif
00327 
00328 
00329     KURL src;
00330     src.setPath( tempFile.name() );
00331 
00332     DEBUG_5850 << "FreeBusyManager::publishFreeBusy(): " << targetURL << endl;
00333 
00334     KIO::Job * job = KIO::file_copy( src, targetURL, -1,
00335                                      true /*overwrite*/,
00336                                      false /*don't resume*/,
00337                                      false /*don't show progress info*/ );
00338     //pass the mainwindow to the job so any prompts are active
00339     KOrg::MainWindow *korg = ActionManager::findInstance( KURL() );
00340     job->setWindow( korg->topLevelWidget() );
00341 
00342     connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
00343              TQT_SLOT( slotUploadFreeBusyResult( KIO::Job * ) ) );
00344   }
00345 }
00346 
00347 void FreeBusyManager::slotUploadFreeBusyResult(KIO::Job *_job)
00348 {
00349     KIO::FileCopyJob* job = static_cast<KIO::FileCopyJob *>(_job);
00350     if ( job->error() )
00351         KMessageBox::sorry( 0,
00352           i18n( "<qt>The software could not upload your free/busy list to the "
00353                 "URL '%1'. There might be a problem with the access rights, or "
00354                 "you specified an incorrect URL. The system said: <em>%2</em>."
00355                 "<br>Please check the URL or contact your system administrator."
00356                 "</qt>" ).arg( job->destURL().prettyURL() )
00357                          .arg( job->errorString() ) );
00358     // Delete temp file
00359     KURL src = job->srcURL();
00360     Q_ASSERT( src.isLocalFile() );
00361     if( src.isLocalFile() )
00362         TQFile::remove(src.path());
00363     mUploadingFreeBusy = false;
00364 }
00365 
00366 bool FreeBusyManager::retrieveFreeBusy( const TQString &email, bool forceDownload )
00367 {
00368   DEBUG_5850 << "FreeBusyManager::retrieveFreeBusy(): " << email << endl;
00369   if ( email.isEmpty() ) return false;
00370 
00371   // Check for cached copy of free/busy list
00372   KCal::FreeBusy *fb = loadFreeBusy( email );
00373   if ( fb ) {
00374     emit freeBusyRetrieved( fb, email );
00375   }
00376 
00377   // Don't download free/busy if the user does not want it.
00378   if( !KOPrefs::instance()->mFreeBusyRetrieveAuto && !forceDownload) {
00379     slotFreeBusyDownloadError( email ); // fblist
00380     return false;
00381   }
00382 
00383   mRetrieveQueue.append( email );
00384 
00385   if ( mRetrieveQueue.count() > 1 ) return true;
00386 
00387   return processRetrieveQueue();
00388 }
00389 
00390 bool FreeBusyManager::processRetrieveQueue()
00391 {
00392   if ( mRetrieveQueue.isEmpty() ) return true;
00393 
00394   TQString email = mRetrieveQueue.first();
00395   mRetrieveQueue.pop_front();
00396 
00397   KURL sourceURL = freeBusyUrl( email );
00398 
00399   kdDebug(5850) << "FreeBusyManager::processRetrieveQueue(): url: " << sourceURL << endl;
00400 
00401   if ( !sourceURL.isValid() ) {
00402     kdDebug(5850) << "Invalid FB URL\n";
00403     slotFreeBusyDownloadError( email );
00404     return false;
00405   }
00406 
00407   FreeBusyDownloadJob *job = new FreeBusyDownloadJob( email, sourceURL, this,
00408                                                       "freebusy_download_job" );
00409   connect( job, TQT_SIGNAL( freeBusyDownloaded( KCal::FreeBusy *,
00410                                             const TQString & ) ),
00411        TQT_SIGNAL( freeBusyRetrieved( KCal::FreeBusy *, const TQString & ) ) );
00412   connect( job, TQT_SIGNAL( freeBusyDownloaded( KCal::FreeBusy *,
00413                                             const TQString & ) ),
00414            TQT_SLOT( processRetrieveQueue() ) );
00415 
00416   connect( job, TQT_SIGNAL( freeBusyDownloadError( const TQString& ) ),
00417            this, TQT_SLOT( slotFreeBusyDownloadError( const TQString& ) ) );
00418 
00419   return true;
00420 }
00421 
00422 void FreeBusyManager::slotFreeBusyDownloadError( const TQString& email )
00423 {
00424   if( KOPrefs::instance()->thatIsMe( email ) ) {
00425     // We tried to download our own free-busy list from the net, but it failed
00426     // so use local version instead.
00427     // The reason we try to download even our own free-busy list is that
00428     // this allows to avoid showing as busy the folders that are "fb relevant for nobody"
00429     // like shared resources (meeting rooms etc.)
00430     DEBUG_5850 << "freebusy of owner, falling back to local list" << endl;
00431     emit freeBusyRetrieved( ownerFreeBusy(), email );
00432   }
00433 
00434 }
00435 
00436 void FreeBusyManager::cancelRetrieval()
00437 {
00438   mRetrieveQueue.clear();
00439 }
00440 
00441 KURL replaceVariablesURL( const KURL &url, const TQString &email )
00442 {
00443   TQString emailName, emailHost;
00444   int emailpos = email.find( '@' );
00445   if( emailpos >= 0 ) {
00446     emailName = email.left( emailpos );
00447     emailHost = email.mid( emailpos + 1 );
00448   }
00449 
00450   TQString saveStr = url.path();
00451   saveStr.replace( TQRegExp( "%[Ee][Mm][Aa][Ii][Ll]%" ), email );
00452   saveStr.replace( TQRegExp( "%[Nn][Aa][Mm][Ee]%" ), emailName );
00453   saveStr.replace( TQRegExp( "%[Ss][Ee][Rr][Vv][Ee][Rr]%" ), emailHost );
00454 
00455   KURL retUrl( url );
00456   retUrl.setPath( saveStr );
00457   return retUrl;
00458 }
00459 
00460 bool fbExists( const KURL &url )
00461 {
00462   // We need this function because using KIO::NetAccess::exists()
00463   // is useless for the http and https protocols. And getting back
00464   // arbitrary data is also useless because a server can respond back
00465   // with a "no such document" page.  So we need smart checking.
00466 
00467   KIO::Job *job = KIO::get( url, false, false );
00468   TQByteArray data;
00469   if ( KIO::NetAccess::synchronousRun( job, 0, &data ) ) {
00470     TQString dataStr ( data );
00471     if ( dataStr.contains( "BEGIN:VCALENDAR" ) ) {
00472       return true;
00473     }
00474   }
00475   return false;
00476 }
00477 
00478 KURL FreeBusyManager::freeBusyUrl( const TQString &email )
00479 {
00480   DEBUG_5850 << "FreeBusyManager::freeBusyUrl(): " << email << endl;
00481 
00482   // First check if there is a specific FB url for this email
00483   TQString configFile = locateLocal( "data", "korganizer/freebusyurls" );
00484   KConfig cfg( configFile );
00485 
00486   cfg.setGroup( email );
00487   TQString url = cfg.readEntry( "url" );
00488   if ( !url.isEmpty() ) {
00489     kdDebug(5850) << "found cached url: " << url << endl;
00490     KURL cachedURL( url );
00491     if ( KOPrefs::instance()->thatIsMe( email ) ) {
00492       cachedURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
00493       cachedURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
00494     }
00495     return replaceVariablesURL( cachedURL, email );
00496   }
00497 
00498   // Try with the url configurated by preferred email in kaddressbook
00499   KABC::Addressee::List list= KABC::StdAddressBook::self( true )->findByEmail( email );
00500   KABC::Addressee::List::Iterator it;
00501   TQString pref;
00502   for ( it = list.begin(); it != list.end(); ++it ) {
00503     pref = (*it).preferredEmail();
00504     if ( !pref.isEmpty() && pref != email ) {
00505       kdDebug(5850) << "FreeBusyManager::freeBusyUrl():"
00506                     << "Preferred email of " << email << " is " << pref << endl;
00507       cfg.setGroup( pref );
00508       url = cfg.readEntry ( "url" );
00509       if ( !url.isEmpty() ) {
00510         kdDebug(5850) << "FreeBusyManager::freeBusyUrl():"
00511                       << "Taken url from preferred email:" << url << endl;
00512         return replaceVariablesURL( KURL( url ), email );
00513       }
00514     }
00515   }
00516   // None found. Check if we do automatic FB retrieving then
00517   if ( !KOPrefs::instance()->mFreeBusyRetrieveAuto ) {
00518     kdDebug( 5850 ) << "no auto retrieving" << endl;
00519     // No, so no FB list here
00520     return KURL();
00521   }
00522 
00523   // Sanity check: Don't download if it's not a correct email
00524   // address (this also avoids downloading for "(empty email)").
00525   int emailpos = email.find( '@' );
00526   if( emailpos == -1 ) {
00527     return KURL();
00528   }
00529 
00530   // Cut off everything left of the @ sign to get the user name.
00531   const TQString emailName = email.left( emailpos );
00532   const TQString emailHost = email.mid( emailpos + 1 );
00533 
00534   // Build the URL
00535   KURL sourceURL;
00536   sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl;
00537 
00538   if ( KOPrefs::instance()->mFreeBusyCheckHostname ) {
00539     // Don't try to fetch free/busy data for users not on the specified servers
00540     // This tests if the hostnames match, or one is a subset of the other
00541     const TQString hostDomain = sourceURL.host();
00542     if ( hostDomain != emailHost &&
00543          !hostDomain.endsWith( '.' + emailHost ) &&
00544          !emailHost.endsWith( '.' + hostDomain ) ) {
00545       // Host names do not match
00546       kdDebug(5850) << "Host '" << sourceURL.host() << "' doesn't match email '" << email << endl;
00547       return KURL();
00548     }
00549   }
00550 
00551   if ( sourceURL.url().contains( TQRegExp( "\\.[xiv]fb$" ) ) ) { // user specified a fullpath
00552     // do variable string replacements to the URL (MS Outlook style)
00553     KURL fullpathURL = replaceVariablesURL( sourceURL, email );
00554 
00555     // This should work with anything thrown at it, not just Kolab
00556     // Notice that Kolab URLs are just entered as the base address, e.g. http://server.com/mykolab/
00557     // This means that if the trailing slash is not entered, we can treat this as a custom, non-Kolab URL!
00558     // In that case, just pass it on through with substitution for %u and %d
00559     // TODO: May want an explicit configuration option in kogroupwareprefspage.ui for this
00560     if ((fullpathURL.url().endsWith("/", true) == false) || (fullpathURL.url().contains("%25u", true)) || (fullpathURL.url().contains("%25d", true))) {
00561       // A generic URL, substitute %u and %d
00562       fullpathURL = fullpathURL.url().replace("%25u", emailName, true);
00563       fullpathURL = fullpathURL.url().replace("%25d", emailHost, true);
00564     }
00565     else {
00566       // This is (probably) a Kolab URL!
00567     }
00568 
00569     // set the User and Password part of the URL
00570     fullpathURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
00571     fullpathURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
00572 
00573     // no need to cache this URL as this is pretty fast to get from the config value.
00574 
00575     // return the fullpath URL
00576     return fullpathURL;
00577   }
00578 
00579   // else we search for a fb file in the specified URL with known possible extensions
00580 
00581   TQStringList extensions;
00582   extensions << "xfb" << "ifb" << "vfb";
00583   TQStringList::ConstIterator ext;
00584   for ( ext = extensions.constBegin(); ext != extensions.constEnd(); ++ext ) {
00585     // build a url for this extension
00586     sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl;
00587     KURL dirURL = replaceVariablesURL( sourceURL, email );
00588     if ( KOPrefs::instance()->mFreeBusyFullDomainRetrieval ) {
00589       dirURL.addPath( email + '.' + (*ext) );
00590     } else {
00591       dirURL.addPath( emailName + '.' + (*ext ) );
00592     }
00593     dirURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
00594     dirURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
00595     if ( fbExists( dirURL ) ) {
00596       // write the URL to the cache
00597       cfg.setGroup( email );
00598       cfg.writeEntry( "url", dirURL.prettyURL() ); // prettyURL() does not write user nor password
00599       return dirURL;
00600     }
00601   }
00602 
00603   return KURL();
00604 }
00605 
00606 KCal::FreeBusy *FreeBusyManager::iCalToFreeBusy( const TQCString &data )
00607 {
00608   kdDebug(5850) << "FreeBusyManager::iCalToFreeBusy()" << endl;
00609   kdDebug(5850) << data << endl;
00610 
00611   TQString freeBusyVCal = TQString::fromUtf8( data );
00612   KCal::FreeBusy *fb = mFormat.parseFreeBusy( freeBusyVCal );
00613   if ( !fb ) {
00614     kdDebug(5850) << "FreeBusyManager::iCalToFreeBusy(): Error parsing free/busy"
00615               << endl;
00616     kdDebug(5850) << freeBusyVCal << endl;
00617   }
00618   return fb;
00619 }
00620 
00621 TQString FreeBusyManager::freeBusyDir()
00622 {
00623   return locateLocal( "data", "korganizer/freebusy" );
00624 }
00625 
00626 FreeBusy *FreeBusyManager::loadFreeBusy( const TQString &email )
00627 {
00628   DEBUG_5850 << "FreeBusyManager::loadFreeBusy(): " << email << endl;
00629 
00630   TQString fbd = freeBusyDir();
00631 
00632   TQFile f( fbd + "/" + email + ".ifb" );
00633   if ( !f.exists() ) {
00634     DEBUG_5850 << "FreeBusyManager::loadFreeBusy() " << f.name()
00635                   << " doesn't exist." << endl;
00636     return 0;
00637   }
00638 
00639   if ( !f.open( IO_ReadOnly ) ) {
00640     DEBUG_5850 << "FreeBusyManager::loadFreeBusy() Unable to open file "
00641               << f.name() << endl;
00642     return 0;
00643   }
00644 
00645   TQTextStream ts( &f );
00646   TQString str = ts.read();
00647 
00648   return iCalToFreeBusy( str.utf8() );
00649 }
00650 
00651 bool FreeBusyManager::saveFreeBusy( FreeBusy *freebusy, const Person &person )
00652 {
00653   DEBUG_5850 << "FreeBusyManager::saveFreeBusy(): " << person.fullName() << endl;
00654 
00655   TQString fbd = freeBusyDir();
00656 
00657   TQDir freeBusyDirectory( fbd );
00658   if ( !freeBusyDirectory.exists() ) {
00659     DEBUG_5850 << "Directory " << fbd << " does not exist!" << endl;
00660     DEBUG_5850 << "Creating directory: " << fbd << endl;
00661 
00662     if( !freeBusyDirectory.mkdir( fbd, true ) ) {
00663       DEBUG_5850 << "Could not create directory: " << fbd << endl;
00664       return false;
00665     }
00666   }
00667 
00668   TQString filename( fbd );
00669   filename += "/";
00670   filename += person.email();
00671   filename += ".ifb";
00672   TQFile f( filename );
00673 
00674   DEBUG_5850 << "FreeBusyManager::saveFreeBusy(): filename: " << filename
00675             << endl;
00676 
00677   freebusy->clearAttendees();
00678   freebusy->setOrganizer( person );
00679 
00680   TQString messageText = mFormat.createScheduleMessage( freebusy,
00681                                                        Scheduler::Publish );
00682 
00683   if ( !f.open( IO_ReadWrite ) ) {
00684     DEBUG_5850 << "acceptFreeBusy: Can't open:" << filename << " for writing"
00685               << endl;
00686     return false;
00687   }
00688   TQTextStream t( &f );
00689   t << messageText;
00690   f.close();
00691 
00692   return true;
00693 }
00694 
00695 #include "freebusymanager.moc"