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älvdalens 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 <tdeio/job.h> 00053 #include <kdebug.h> 00054 #include <tdemessagebox.h> 00055 #include <tdetempfile.h> 00056 #include <tdeio/jobclasses.h> 00057 #include <tdeio/netaccess.h> 00058 #include <tdeio/scheduler.h> 00059 #include <tdeapplication.h> 00060 #include <tdeconfig.h> 00061 #include <tdelocale.h> 00062 #include <kstandarddirs.h> 00063 #include <tdeabc/stdaddressbook.h> 00064 #include <tdeabc/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 TDEIO::TransferJob *job = TDEIO::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( TDEIO::Job * ) ), 00086 TQT_SLOT( slotResult( TDEIO::Job * ) ) ); 00087 connect( job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ), 00088 TQT_SLOT( slotData( TDEIO::Job *, const TQByteArray & ) ) ); 00089 TDEIO::Scheduler::scheduleJob( job ); 00090 } 00091 00092 FreeBusyDownloadJob::~FreeBusyDownloadJob() 00093 { 00094 } 00095 00096 00097 void FreeBusyDownloadJob::slotData( TDEIO::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( TDEIO::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 TDEIO::Job * job = TDEIO::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( TDEIO::Job * ) ), 00343 TQT_SLOT( slotUploadFreeBusyResult( TDEIO::Job * ) ) ); 00344 } 00345 } 00346 00347 void FreeBusyManager::slotUploadFreeBusyResult(TDEIO::Job *_job) 00348 { 00349 TDEIO::FileCopyJob* job = static_cast<TDEIO::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 TDEIO::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 TDEIO::Job *job = TDEIO::get( url, false, false ); 00468 TQByteArray data; 00469 if ( TDEIO::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 TDEConfig 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 TDEABC::Addressee::List list= TDEABC::StdAddressBook::self( true )->findByEmail( email ); 00500 TDEABC::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"