korganizer Library API Documentation

freebusymanager.cpp

00001 /* 00002 This file is part of the Groupware/KOrganizer integration. 00003 00004 Requires the Qt 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., 59 Temple Place - Suite 330, Boston, 00024 MA 02111-1307, 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 Qt library by Trolltech AS, Norway (or with modified versions 00029 of Qt that use the same license as Qt), 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 Qt. 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 00043 #include <libkcal/incidencebase.h> 00044 #include <libkcal/attendee.h> 00045 #include <libkcal/freebusy.h> 00046 #include <libkcal/journal.h> 00047 #include <libkcal/calendarlocal.h> 00048 #include <libkcal/icalformat.h> 00049 00050 #include <kio/job.h> 00051 #include <kdebug.h> 00052 #include <kmessagebox.h> 00053 #include <ktempfile.h> 00054 #include <kio/netaccess.h> 00055 #include <kapplication.h> 00056 #include <kconfig.h> 00057 #include <klocale.h> 00058 #include <kstandarddirs.h> 00059 00060 #include <qfile.h> 00061 #include <qbuffer.h> 00062 #include <qregexp.h> 00063 #include <qdir.h> 00064 00065 using namespace KCal; 00066 00067 FreeBusyDownloadJob::FreeBusyDownloadJob( const QString &email, const KURL &url, 00068 FreeBusyManager *manager, 00069 const char *name ) 00070 : QObject( manager, name ), mManager( manager ), mEmail( email ) 00071 { 00072 KIO::Job *job = KIO::get( url, false, false ); 00073 connect( job, SIGNAL( result( KIO::Job * ) ), 00074 SLOT( slotResult( KIO::Job * ) ) ); 00075 connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), 00076 SLOT( slotData( KIO::Job *, const QByteArray & ) ) ); 00077 } 00078 00079 FreeBusyDownloadJob::~FreeBusyDownloadJob() 00080 { 00081 } 00082 00083 00084 void FreeBusyDownloadJob::slotData( KIO::Job *, const QByteArray &data ) 00085 { 00086 QByteArray tmp = data; 00087 tmp.resize( tmp.size() + 1 ); 00088 tmp[tmp.size()-1] = 0; 00089 mFreeBusyData += tmp; 00090 } 00091 00092 void FreeBusyDownloadJob::slotResult( KIO::Job *job ) 00093 { 00094 kdDebug() << "FreeBusyDownloadJob::slotResult() " << mEmail << endl; 00095 00096 if( job->error() ) { 00097 kdDebug(5850) << "FreeBusyDownloadJob::slotResult() job error :-(" << endl; 00098 } 00099 00100 FreeBusy *fb = mManager->iCalToFreeBusy( mFreeBusyData ); 00101 emit freeBusyDownloaded( fb, mEmail ); 00102 // PENDING(steffen): Is this safe? 00103 //job->deleteLater(); 00104 delete this; 00105 } 00106 00107 00108 FreeBusyManager::FreeBusyManager( QObject *parent, const char *name ) 00109 : QObject( parent, name ), 00110 mCalendar( 0 ), mTimerID( 0 ), mUploadingFreeBusy( false ) 00111 { 00112 } 00113 00114 void FreeBusyManager::setCalendar( KCal::Calendar *c ) 00115 { 00116 mCalendar = c; 00117 if ( mCalendar ) { 00118 mFormat.setTimeZone( mCalendar->timeZoneId(), true ); 00119 } 00120 } 00121 00122 KCal::FreeBusy *FreeBusyManager::ownerFreeBusy() 00123 { 00124 QDateTime start = QDateTime::currentDateTime(); 00125 QDateTime end = start.addDays( KOPrefs::instance()->mFreeBusyPublishDays ); 00126 00127 FreeBusy *freebusy = new FreeBusy( mCalendar, start, end ); 00128 freebusy->setOrganizer( KOPrefs::instance()->email() ); 00129 00130 return freebusy; 00131 } 00132 00133 QString FreeBusyManager::ownerFreeBusyAsString() 00134 { 00135 FreeBusy *freebusy = ownerFreeBusy(); 00136 00137 QString result = freeBusyToIcal( freebusy ); 00138 00139 delete freebusy; 00140 00141 return result; 00142 } 00143 00144 QString FreeBusyManager::freeBusyToIcal( KCal::FreeBusy *freebusy ) 00145 { 00146 return mFormat.createScheduleMessage( freebusy, Scheduler::Publish ); 00147 } 00148 00149 void FreeBusyManager::slotPerhapsUploadFB() 00150 { 00151 // user has automtic uploading disabled, bail out 00152 if ( !KOPrefs::instance()->freeBusyPublishAuto() ) 00153 return; 00154 if( mTimerID != 0 ) 00155 // A timer is already running, so we don't need to do anything 00156 return; 00157 00158 int now = static_cast<int>( QDateTime::currentDateTime().toTime_t() ); 00159 int eta = static_cast<int>( mNextUploadTime.toTime_t() ) - now; 00160 00161 if( !mUploadingFreeBusy ) { 00162 // Not currently uploading 00163 if( mNextUploadTime.isNull() || 00164 QDateTime::currentDateTime() > mNextUploadTime ) { 00165 // No uploading have been done in this session, or delay time is over 00166 publishFreeBusy(); 00167 return; 00168 } 00169 00170 // We're in the delay time and no timer is running. Start one 00171 if( eta <= 0 ) { 00172 // Sanity check failed - better do the upload 00173 publishFreeBusy(); 00174 return; 00175 } 00176 } else { 00177 // We are currently uploading the FB list. Start the timer 00178 if( eta <= 0 ) { 00179 kdDebug(5850) << "This shouldn't happen! eta <= 0\n"; 00180 eta = 10; // whatever 00181 } 00182 } 00183 00184 // Start the timer 00185 mTimerID = startTimer( eta * 1000 ); 00186 00187 if( mTimerID == 0 ) 00188 // startTimer failed - better do the upload 00189 publishFreeBusy(); 00190 } 00191 00192 // This is used for delayed Free/Busy list uploading 00193 void FreeBusyManager::timerEvent( QTimerEvent* ) 00194 { 00195 publishFreeBusy(); 00196 } 00197 00202 void FreeBusyManager::publishFreeBusy() 00203 { 00204 // Already uploading? Skip this one then. 00205 if ( mUploadingFreeBusy ) 00206 return; 00207 mUploadingFreeBusy = true; 00208 00209 // If we have a timer running, it should be stopped now 00210 if( mTimerID != 0 ) { 00211 killTimer( mTimerID ); 00212 mTimerID = 0; 00213 } 00214 00215 // Save the time of the next free/busy uploading 00216 mNextUploadTime = QDateTime::currentDateTime(); 00217 if( KOPrefs::instance()->mFreeBusyPublishDelay > 0 ) 00218 mNextUploadTime = mNextUploadTime.addSecs( 00219 KOPrefs::instance()->mFreeBusyPublishDelay * 60 ); 00220 00221 QString messageText = ownerFreeBusyAsString(); 00222 00223 // We need to massage the list a bit so that Outlook understands 00224 // it. 00225 messageText = messageText.replace( QRegExp( "ORGANIZER\\s*:MAILTO:" ), 00226 "ORGANIZER:" ); 00227 00228 // Create a local temp file and save the message to it 00229 KTempFile tempFile; 00230 QTextStream *textStream = tempFile.textStream(); 00231 if( textStream ) { 00232 *textStream << messageText; 00233 tempFile.close(); 00234 00235 #if 0 00236 QString defaultEmail = KOCore()::self()->email(); 00237 QString emailHost = defaultEmail.mid( defaultEmail.find( '@' ) + 1 ); 00238 00239 // Put target string together 00240 KURL targetURL; 00241 if( KOPrefs::instance()->mPublishKolab ) { 00242 // we use Kolab 00243 QString server; 00244 if( KOPrefs::instance()->mPublishKolabServer == "%SERVER%" || 00245 KOPrefs::instance()->mPublishKolabServer.isEmpty() ) 00246 server = emailHost; 00247 else 00248 server = KOPrefs::instance()->mPublishKolabServer; 00249 00250 targetURL.setProtocol( "webdavs" ); 00251 targetURL.setHost( server ); 00252 00253 QString fbname = KOPrefs::instance()->mPublishUserName; 00254 int at = fbname.find('@'); 00255 if( at > 1 && fbname.length() > (uint)at ) { 00256 fbname = fbname.left(at); 00257 } 00258 targetURL.setPath( "/freebusy/" + fbname + ".ifb" ); 00259 targetURL.setUser( KOPrefs::instance()->mPublishUserName ); 00260 targetURL.setPass( KOPrefs::instance()->mPublishPassword ); 00261 } else { 00262 // we use something else 00263 targetURL = KOPrefs::instance()->mPublishAnyURL.replace( "%SERVER%", 00264 emailHost ); 00265 targetURL.setUser( KOPrefs::instance()->mPublishUserName ); 00266 targetURL.setPass( KOPrefs::instance()->mPublishPassword ); 00267 } 00268 #endif 00269 00270 KURL targetURL ( KOPrefs::instance()->freeBusyPublishUrl() ); 00271 targetURL.setUser( KOPrefs::instance()->mFreeBusyPublishUser ); 00272 targetURL.setPass( KOPrefs::instance()->mFreeBusyPublishPassword ); 00273 00274 KURL src; 00275 src.setPath( tempFile.name() ); 00276 00277 kdDebug() << "FreeBusyManager::publishFreeBusy(): " << targetURL << endl; 00278 00279 KIO::Job * job = KIO::file_copy( src, targetURL, -1, 00280 true /*overwrite*/, 00281 false /*don't resume*/, 00282 false /*don't show progress info*/ ); 00283 connect( job, SIGNAL( result( KIO::Job * ) ), 00284 SLOT( slotUploadFreeBusyResult( KIO::Job * ) ) ); 00285 } 00286 } 00287 00288 void FreeBusyManager::slotUploadFreeBusyResult(KIO::Job *_job) 00289 { 00290 KIO::FileCopyJob* job = static_cast<KIO::FileCopyJob *>(_job); 00291 if ( job->error() ) 00292 KMessageBox::sorry( 0, 00293 i18n( "<qt>The software could not upload your free/busy list to the " 00294 "URL '%1'. There might be a problem with the access rights, or " 00295 "you specified an incorrect URL. The system said: <em>%2</em>." 00296 "<br>Please check the URL or contact your system administrator." 00297 "</qt>" ).arg( job->destURL().prettyURL() ) 00298 .arg( job->errorString() ) ); 00299 // Delete temp file 00300 KURL src = job->srcURL(); 00301 Q_ASSERT( src.isLocalFile() ); 00302 if( src.isLocalFile() ) 00303 QFile::remove(src.path()); 00304 mUploadingFreeBusy = false; 00305 } 00306 00307 bool FreeBusyManager::retrieveFreeBusy( const QString &email ) 00308 { 00309 kdDebug() << "FreeBusyManager::retrieveFreeBusy(): " << email << endl; 00310 00311 if( KOPrefs::instance()->thatIsMe( email ) ) { 00312 // Don't download our own free-busy list from the net 00313 kdDebug() << "freebusy of owner" << endl; 00314 emit freeBusyRetrieved( ownerFreeBusy(), email ); 00315 return true; 00316 } 00317 00318 // Check for cached copy of free/busy list 00319 KCal::FreeBusy *fb = loadFreeBusy( email ); 00320 if ( fb ) { 00321 emit freeBusyRetrieved( fb, email ); 00322 } 00323 00324 // Don't download free/busy if the user does not want it. 00325 if( !KOPrefs::instance()->mFreeBusyRetrieveAuto ) 00326 return false; 00327 00328 mRetrieveQueue.append( email ); 00329 00330 if ( mRetrieveQueue.count() > 1 ) return true; 00331 00332 return processRetrieveQueue(); 00333 } 00334 00335 bool FreeBusyManager::processRetrieveQueue() 00336 { 00337 if ( mRetrieveQueue.isEmpty() ) return true; 00338 00339 QString email = mRetrieveQueue.first(); 00340 mRetrieveQueue.pop_front(); 00341 00342 KURL sourceURL = freeBusyUrl( email ); 00343 00344 kdDebug() << "FreeBusyManager::retrieveFreeBusy(): url: " << sourceURL.url() 00345 << endl; 00346 00347 if ( !sourceURL.isValid() ) { 00348 kdDebug(5850) << "Invalid FB URL\n"; 00349 return false; 00350 } 00351 00352 FreeBusyDownloadJob *job = new FreeBusyDownloadJob( email, sourceURL, this, 00353 "freebusy_download_job" ); 00354 connect( job, SIGNAL( freeBusyDownloaded( KCal::FreeBusy *, 00355 const QString & ) ), 00356 SIGNAL( freeBusyRetrieved( KCal::FreeBusy *, const QString & ) ) ); 00357 connect( job, SIGNAL( freeBusyDownloaded( KCal::FreeBusy *, 00358 const QString & ) ), 00359 SLOT( processRetrieveQueue() ) ); 00360 00361 return true; 00362 } 00363 00364 void FreeBusyManager::cancelRetrieval() 00365 { 00366 mRetrieveQueue.clear(); 00367 } 00368 00369 KURL FreeBusyManager::freeBusyUrl( const QString &email ) 00370 { 00371 // First check if there is a specific FB url for this email 00372 QString configFile = locateLocal( "data", "korganizer/freebusyurls" ); 00373 KConfig cfg( configFile ); 00374 00375 cfg.setGroup( email ); 00376 QString url = cfg.readEntry( "url" ); 00377 if ( !url.isEmpty() ) { 00378 return KURL( url ); 00379 } 00380 00381 // None found. Check if we do automatic FB retrieving then 00382 if ( !KOPrefs::instance()->mFreeBusyRetrieveAuto ) 00383 // No, so no FB list here 00384 return KURL(); 00385 00386 // Sanity check: Don't download if it's not a correct email 00387 // address (this also avoids downloading for "(empty email)"). 00388 int emailpos = email.find( '@' ); 00389 if( emailpos == -1 ) 00390 return KURL(); 00391 00392 // Cut off everything left of the @ sign to get the user name. 00393 QString emailName = email.left( emailpos ); 00394 00395 // Build the URL 00396 KURL sourceURL; 00397 sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl; 00398 00399 // Don't try to fetch free/busy data for users not on the specified servers 00400 if ( sourceURL.host() != email.mid( emailpos + 1 ) ) return KURL(); 00401 00402 if ( KOPrefs::instance()->mFreeBusyFullDomainRetrieval ) 00403 sourceURL.setFileName( email + ".ifb" ); 00404 else 00405 sourceURL.setFileName( emailName + ".ifb" ); 00406 sourceURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser ); 00407 sourceURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword ); 00408 00409 return sourceURL; 00410 } 00411 00412 KCal::FreeBusy *FreeBusyManager::iCalToFreeBusy( const QCString &data ) 00413 { 00414 kdDebug() << "FreeBusyManager::iCalToFreeBusy()" << endl; 00415 00416 QString freeBusyVCal = QString::fromUtf8( data ); 00417 KCal::FreeBusy *fb = mFormat.parseFreeBusy( freeBusyVCal ); 00418 if ( !fb ) { 00419 kdDebug() << "FreeBusyManager::iCalToFreeBusy(): Error parsing free/busy" 00420 << endl; 00421 } else { 00422 saveFreeBusy( fb, fb->organizer() ); 00423 } 00424 return fb; 00425 } 00426 00427 QString FreeBusyManager::freeBusyDir() 00428 { 00429 return locateLocal( "data", "korganizer/freebusy" ); 00430 } 00431 00432 FreeBusy *FreeBusyManager::loadFreeBusy( const QString &email ) 00433 { 00434 kdDebug() << "FreeBusyManager::loadFreeBusy(): " << email << endl; 00435 00436 QString fbd = freeBusyDir(); 00437 00438 QFile f( fbd + "/" + email + ".ifb" ); 00439 if ( !f.exists() ) { 00440 kdDebug() << "FreeBusyManager::loadFreeBusy() " << f.name() 00441 << " doesn't exist." << endl; 00442 return 0; 00443 } 00444 00445 if ( !f.open( IO_ReadOnly ) ) { 00446 kdDebug() << "FreeBusyManager::loadFreeBusy() Unable to open file " 00447 << f.name() << endl; 00448 return 0; 00449 } 00450 00451 QTextStream ts( &f ); 00452 QString str = ts.read(); 00453 00454 return iCalToFreeBusy( str.utf8() ); 00455 } 00456 00457 bool FreeBusyManager::saveFreeBusy( FreeBusy *freebusy, const QString &email ) 00458 { 00459 kdDebug() << "FreeBusyManager::saveFreeBusy(): " << email << endl; 00460 00461 QString fbd = freeBusyDir(); 00462 00463 QDir freeBusyDirectory( fbd ); 00464 if ( !freeBusyDirectory.exists() ) { 00465 kdDebug() << "Directory " << fbd << " does not exist!" << endl; 00466 kdDebug() << "Creating directory: " << fbd << endl; 00467 00468 if( !freeBusyDirectory.mkdir( fbd, true ) ) { 00469 kdDebug() << "Could not create directory: " << fbd << endl; 00470 return false; 00471 } 00472 } 00473 00474 QString filename( fbd ); 00475 filename += "/"; 00476 filename += email; 00477 filename += ".ifb"; 00478 QFile f( filename ); 00479 00480 kdDebug() << "FreeBusyManager::saveFreeBusy(): filename: " << filename 00481 << endl; 00482 00483 freebusy->clearAttendees(); 00484 freebusy->setOrganizer( email ); 00485 00486 QString messageText = mFormat.createScheduleMessage( freebusy, 00487 Scheduler::Publish ); 00488 00489 if ( !f.open( IO_ReadWrite ) ) { 00490 kdDebug() << "acceptFreeBusy: Can't open:" << filename << " for writing" 00491 << endl; 00492 return false; 00493 } 00494 QTextStream t( &f ); 00495 t << messageText; 00496 f.close(); 00497 00498 return true; 00499 } 00500 00501 #include "freebusymanager.moc"
KDE Logo
This file is part of the documentation for korganizer Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 27 12:53:19 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003