38 #include "freebusymanager.h"
41 #include "mailscheduler.h"
42 #include "actionmanager.h"
43 #include "korganizer.h"
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>
52 #include <tdeio/job.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>
71 #define DEBUG_5850 kdDebug(5850)
75 FreeBusyDownloadJob::FreeBusyDownloadJob(
const TQString &email,
const KURL &url,
76 FreeBusyManager *manager,
78 : TQObject( manager, name ), mManager( manager ), mEmail( email )
80 TDEIO::TransferJob *job = TDEIO::get( url,
false,
false );
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 );
92 FreeBusyDownloadJob::~FreeBusyDownloadJob()
97 void FreeBusyDownloadJob::slotData( TDEIO::Job *,
const TQByteArray &data )
99 TQByteArray tmp = data;
100 tmp.resize( tmp.size() + 1 );
101 tmp[tmp.size()-1] = 0;
102 mFreeBusyData += tmp;
105 void FreeBusyDownloadJob::slotResult( TDEIO::Job *job )
107 DEBUG_5850 <<
"FreeBusyDownloadJob::slotResult() " << mEmail << endl;
110 DEBUG_5850 <<
"FreeBusyDownloadJob::slotResult() job error for " << mEmail << endl;
111 emit freeBusyDownloadError( mEmail );
113 FreeBusy *fb = mManager->iCalToFreeBusy( mFreeBusyData );
115 Person p = fb->organizer();
116 p.setEmail( mEmail );
117 mManager->saveFreeBusy( fb, p );
119 emit freeBusyDownloaded( fb, mEmail );
126 FreeBusyManager::FreeBusyManager( TQObject *parent,
const char *name )
127 : TQObject( parent, name ),
128 mCalendar( 0 ), mTimerID( 0 ), mUploadingFreeBusy( false ),
137 mFormat.setTimeZone( mCalendar->timeZoneId(),
true );
143 TQDateTime start = TQDateTime::currentDateTime();
144 TQDateTime end = start.addDays( KOPrefs::instance()->mFreeBusyPublishDays );
148 KOPrefs::instance()->email() ) );
153 TQString FreeBusyManager::ownerFreeBusyAsString()
155 FreeBusy *freebusy = ownerFreeBusy();
157 TQString result = freeBusyToIcal( freebusy );
164 TQString FreeBusyManager::freeBusyToIcal(
KCal::FreeBusy *freebusy )
166 return mFormat.createScheduleMessage( freebusy, Scheduler::Publish );
169 void FreeBusyManager::slotPerhapsUploadFB()
172 if ( !KOPrefs::instance()->freeBusyPublishAuto() ||
173 KOPrefs::instance()->freeBusyPublishUrl().isEmpty() )
179 int now =
static_cast<int>( TQDateTime::currentDateTime().toTime_t() );
180 int eta =
static_cast<int>( mNextUploadTime.toTime_t() ) - now;
182 if( !mUploadingFreeBusy ) {
184 if( mNextUploadTime.isNull() ||
185 TQDateTime::currentDateTime() > mNextUploadTime ) {
200 DEBUG_5850 <<
"This shouldn't happen! eta <= 0\n";
206 mTimerID = startTimer( eta * 1000 );
214 void FreeBusyManager::timerEvent( TQTimerEvent* )
219 void FreeBusyManager::setBrokenUrl(
bool isBroken )
221 mBrokenUrl = isBroken;
228 void FreeBusyManager::publishFreeBusy()
231 if ( mUploadingFreeBusy )
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 "
240 "</qt>" ), i18n(
"No Free/Busy Upload URL") );
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") );
262 targetURL.setUser( KOPrefs::instance()->mFreeBusyPublishUser );
263 targetURL.setPass( KOPrefs::instance()->mFreeBusyPublishPassword );
265 mUploadingFreeBusy =
true;
268 if( mTimerID != 0 ) {
269 killTimer( mTimerID );
274 mNextUploadTime = TQDateTime::currentDateTime();
275 if( KOPrefs::instance()->mFreeBusyPublishDelay > 0 )
276 mNextUploadTime = mNextUploadTime.addSecs(
277 KOPrefs::instance()->mFreeBusyPublishDelay * 60 );
279 TQString messageText = ownerFreeBusyAsString();
283 messageText = messageText.replace( TQRegExp(
"ORGANIZER\\s*:MAILTO:" ),
288 TQTextStream *textStream = tempFile.textStream();
290 *textStream << messageText;
294 TQString defaultEmail = KOCore()::self()->email();
295 TQString emailHost = defaultEmail.mid( defaultEmail.find(
'@' ) + 1 );
299 if( KOPrefs::instance()->mPublishKolab ) {
302 if( KOPrefs::instance()->mPublishKolabServer ==
"%SERVER%" ||
303 KOPrefs::instance()->mPublishKolabServer.isEmpty() )
306 server = KOPrefs::instance()->mPublishKolabServer;
308 targetURL.setProtocol(
"webdavs" );
309 targetURL.setHost( server );
311 TQString fbname = KOPrefs::instance()->mPublishUserName;
312 int at = fbname.find(
'@');
313 if( at > 1 && fbname.length() > (uint)at ) {
314 fbname = fbname.left(at);
316 targetURL.setPath(
"/freebusy/" + fbname +
".ifb" );
317 targetURL.setUser( KOPrefs::instance()->mPublishUserName );
318 targetURL.setPass( KOPrefs::instance()->mPublishPassword );
321 targetURL = KOPrefs::instance()->mPublishAnyURL.replace(
"%SERVER%",
323 targetURL.setUser( KOPrefs::instance()->mPublishUserName );
324 targetURL.setPass( KOPrefs::instance()->mPublishPassword );
330 src.setPath( tempFile.name() );
332 DEBUG_5850 <<
"FreeBusyManager::publishFreeBusy(): " << targetURL << endl;
334 TDEIO::Job * job = TDEIO::file_copy( src, targetURL, -1,
342 connect( job, TQ_SIGNAL( result( TDEIO::Job * ) ),
343 TQ_SLOT( slotUploadFreeBusyResult( TDEIO::Job * ) ) );
347 void FreeBusyManager::slotUploadFreeBusyResult(TDEIO::Job *_job)
349 TDEIO::FileCopyJob* job =
static_cast<TDEIO::FileCopyJob *
>(_job);
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() ) );
359 KURL src = job->srcURL();
360 Q_ASSERT( src.isLocalFile() );
361 if( src.isLocalFile() )
362 TQFile::remove(src.path());
363 mUploadingFreeBusy =
false;
366 bool FreeBusyManager::retrieveFreeBusy(
const TQString &email,
bool forceDownload )
368 DEBUG_5850 <<
"FreeBusyManager::retrieveFreeBusy(): " << email << endl;
369 if ( email.isEmpty() )
return false;
374 emit freeBusyRetrieved( fb, email );
378 if( !KOPrefs::instance()->mFreeBusyRetrieveAuto && !forceDownload) {
379 slotFreeBusyDownloadError( email );
383 mRetrieveQueue.append( email );
385 if ( mRetrieveQueue.count() > 1 )
return true;
387 return processRetrieveQueue();
390 bool FreeBusyManager::processRetrieveQueue()
392 if ( mRetrieveQueue.isEmpty() )
return true;
394 TQString email = mRetrieveQueue.first();
395 mRetrieveQueue.pop_front();
397 KURL sourceURL = freeBusyUrl( email );
399 kdDebug(5850) <<
"FreeBusyManager::processRetrieveQueue(): url: " << sourceURL << endl;
401 if ( !sourceURL.isValid() ) {
402 kdDebug(5850) <<
"Invalid FB URL\n";
403 slotFreeBusyDownloadError( email );
408 "freebusy_download_job" );
410 const TQString & ) ),
411 TQ_SIGNAL( freeBusyRetrieved(
KCal::FreeBusy *,
const TQString & ) ) );
413 const TQString & ) ),
414 TQ_SLOT( processRetrieveQueue() ) );
416 connect( job, TQ_SIGNAL( freeBusyDownloadError(
const TQString& ) ),
417 this, TQ_SLOT( slotFreeBusyDownloadError(
const TQString& ) ) );
422 void FreeBusyManager::slotFreeBusyDownloadError(
const TQString& email )
424 if( KOPrefs::instance()->thatIsMe( email ) ) {
430 DEBUG_5850 <<
"freebusy of owner, falling back to local list" << endl;
431 emit freeBusyRetrieved( ownerFreeBusy(), email );
436 void FreeBusyManager::cancelRetrieval()
438 mRetrieveQueue.clear();
441 KURL replaceVariablesURL(
const KURL &url,
const TQString &email )
443 TQString emailName, emailHost;
444 int emailpos = email.find(
'@' );
445 if( emailpos >= 0 ) {
446 emailName = email.left( emailpos );
447 emailHost = email.mid( emailpos + 1 );
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 );
456 retUrl.setPath( saveStr );
460 bool fbExists(
const KURL &url )
467 TDEIO::Job *job = TDEIO::get( url,
false,
false );
469 if ( TDEIO::NetAccess::synchronousRun( job, 0, &data ) ) {
470 TQString dataStr ( data );
471 if ( dataStr.contains(
"BEGIN:VCALENDAR" ) ) {
478 KURL FreeBusyManager::freeBusyUrl(
const TQString &email )
480 DEBUG_5850 <<
"FreeBusyManager::freeBusyUrl(): " << email << endl;
483 TQString configFile = locateLocal(
"data",
"korganizer/freebusyurls" );
484 TDEConfig cfg( configFile );
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 );
495 return replaceVariablesURL( cachedURL, email );
499 TDEABC::Addressee::List list= TDEABC::StdAddressBook::self(
true )->findByEmail( email );
500 TDEABC::Addressee::List::Iterator it;
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 );
517 if ( !KOPrefs::instance()->mFreeBusyRetrieveAuto ) {
518 kdDebug( 5850 ) <<
"no auto retrieving" << endl;
525 int emailpos = email.find(
'@' );
526 if( emailpos == -1 ) {
531 const TQString emailName = email.left( emailpos );
532 const TQString emailHost = email.mid( emailpos + 1 );
536 sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl;
538 if ( KOPrefs::instance()->mFreeBusyCheckHostname ) {
541 const TQString hostDomain = sourceURL.host();
542 if ( hostDomain != emailHost &&
543 !hostDomain.endsWith(
'.' + emailHost ) &&
544 !emailHost.endsWith(
'.' + hostDomain ) ) {
546 kdDebug(5850) <<
"Host '" << sourceURL.host() <<
"' doesn't match email '" << email << endl;
551 if ( sourceURL.url().contains( TQRegExp(
"\\.[xiv]fb$" ) ) ) {
553 KURL fullpathURL = replaceVariablesURL( sourceURL, email );
560 if ((fullpathURL.url().endsWith(
"/",
true) ==
false) || (fullpathURL.url().contains(
"%25u",
true)) || (fullpathURL.url().contains(
"%25d",
true))) {
562 fullpathURL = fullpathURL.url().replace(
"%25u", emailName,
true);
563 fullpathURL = fullpathURL.url().replace(
"%25d", emailHost,
true);
570 fullpathURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
571 fullpathURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
581 TQStringList extensions;
582 extensions <<
"xfb" <<
"ifb" <<
"vfb";
583 TQStringList::ConstIterator ext;
584 for ( ext = extensions.constBegin(); ext != extensions.constEnd(); ++ext ) {
586 sourceURL = KOPrefs::instance()->mFreeBusyRetrieveUrl;
587 KURL dirURL = replaceVariablesURL( sourceURL, email );
588 if ( KOPrefs::instance()->mFreeBusyFullDomainRetrieval ) {
589 dirURL.addPath( email +
'.' + (*ext) );
591 dirURL.addPath( emailName +
'.' + (*ext ) );
593 dirURL.setUser( KOPrefs::instance()->mFreeBusyRetrieveUser );
594 dirURL.setPass( KOPrefs::instance()->mFreeBusyRetrievePassword );
595 if ( fbExists( dirURL ) ) {
597 cfg.setGroup( email );
598 cfg.writeEntry(
"url", dirURL.prettyURL() );
606 KCal::FreeBusy *FreeBusyManager::iCalToFreeBusy(
const TQCString &data )
608 kdDebug(5850) <<
"FreeBusyManager::iCalToFreeBusy()" << endl;
609 kdDebug(5850) << data << endl;
611 TQString freeBusyVCal = TQString::fromUtf8( data );
614 kdDebug(5850) <<
"FreeBusyManager::iCalToFreeBusy(): Error parsing free/busy"
616 kdDebug(5850) << freeBusyVCal << endl;
621 TQString FreeBusyManager::freeBusyDir()
623 return locateLocal(
"data",
"korganizer/freebusy" );
626 FreeBusy *FreeBusyManager::loadFreeBusy(
const TQString &email )
628 DEBUG_5850 <<
"FreeBusyManager::loadFreeBusy(): " << email << endl;
630 TQString fbd = freeBusyDir();
632 TQFile f( fbd +
"/" + email +
".ifb" );
634 DEBUG_5850 <<
"FreeBusyManager::loadFreeBusy() " << f.name()
635 <<
" doesn't exist." << endl;
639 if ( !f.open( IO_ReadOnly ) ) {
640 DEBUG_5850 <<
"FreeBusyManager::loadFreeBusy() Unable to open file "
645 TQTextStream ts( &f );
646 TQString str = ts.read();
648 return iCalToFreeBusy( str.utf8() );
651 bool FreeBusyManager::saveFreeBusy(
FreeBusy *freebusy,
const Person &person )
653 DEBUG_5850 <<
"FreeBusyManager::saveFreeBusy(): " << person.fullName() << endl;
655 TQString fbd = freeBusyDir();
657 TQDir freeBusyDirectory( fbd );
658 if ( !freeBusyDirectory.exists() ) {
659 DEBUG_5850 <<
"Directory " << fbd <<
" does not exist!" << endl;
660 DEBUG_5850 <<
"Creating directory: " << fbd << endl;
662 if( !freeBusyDirectory.mkdir( fbd,
true ) ) {
663 DEBUG_5850 <<
"Could not create directory: " << fbd << endl;
668 TQString filename( fbd );
670 filename += person.email();
672 TQFile f( filename );
674 DEBUG_5850 <<
"FreeBusyManager::saveFreeBusy(): filename: " << filename
680 TQString messageText = mFormat.createScheduleMessage( freebusy,
681 Scheduler::Publish );
683 if ( !f.open( IO_ReadWrite ) ) {
684 DEBUG_5850 <<
"acceptFreeBusy: Can't open:" << filename <<
" for writing"
688 TQTextStream t( &f );
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
virtual TQWidget * topLevelWidget()=0
Return widget whcih represents this main window.