00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifdef HAVE_CONFIG_H
00036 #include <config.h>
00037 #endif
00038
00039 #include "kmailicalifaceimpl.h"
00040 #include "kmfolder.h"
00041 #include "kmfoldertree.h"
00042 #include "kmfolderdir.h"
00043 #include "kmgroupware.h"
00044 #include "kmfoldermgr.h"
00045 #include "kmcommands.h"
00046 #include "kmfolderindex.h"
00047 #include "kmmsgdict.h"
00048 #include "kmmsgpart.h"
00049 using KMail::AccountManager;
00050 #include "kmfolderimap.h"
00051 #include "globalsettings.h"
00052 #include "accountmanager.h"
00053 #include "kmfoldercachedimap.h"
00054 #include "kmacctcachedimap.h"
00055 #include "acljobs.h"
00056
00057 #include <mimelib/enum.h>
00058 #include <mimelib/utility.h>
00059 #include <mimelib/body.h>
00060 #include <mimelib/mimepp.h>
00061
00062 #include <qfile.h>
00063 #include <qmap.h>
00064 #include <qtextcodec.h>
00065
00066 #include <kdebug.h>
00067 #include <kiconloader.h>
00068 #include <dcopclient.h>
00069 #include <kmessagebox.h>
00070 #include <kconfig.h>
00071 #include <kurl.h>
00072 #include <ktempfile.h>
00073
00074 using namespace KMail;
00075
00076
00077 static void vPartMicroParser( const QString& str, QString& s );
00078 static void reloadFolderTree();
00079
00080
00081 static const struct {
00082 const char* contentsTypeStr;
00083 const char* mimetype;
00084 KFolderTreeItem::Type treeItemType;
00085 const char* annotation;
00086 const char* translatedName;
00087 } s_folderContentsType[] = {
00088 { "Mail", "application/x-vnd.kolab.mail", KFolderTreeItem::Other, "mail", I18N_NOOP( "Mail" ) },
00089 { "Calendar", "application/x-vnd.kolab.event", KFolderTreeItem::Calendar, "event", I18N_NOOP( "Calendar" ) },
00090 { "Contact", "application/x-vnd.kolab.contact", KFolderTreeItem::Contacts, "contact", I18N_NOOP( "Contacts" ) },
00091 { "Note", "application/x-vnd.kolab.note", KFolderTreeItem::Notes, "note", I18N_NOOP( "Notes" ) },
00092 { "Task", "application/x-vnd.kolab.task", KFolderTreeItem::Tasks, "task", I18N_NOOP( "Tasks" ) },
00093 { "Journal", "application/x-vnd.kolab.journal", KFolderTreeItem::Journals, "journal", I18N_NOOP( "Journal" ) }
00094 };
00095
00096 static QString folderContentsType( KMail::FolderContentsType type )
00097 {
00098 return s_folderContentsType[type].contentsTypeStr;
00099 }
00100
00101 static QString folderKolabMimeType( KMail::FolderContentsType type )
00102 {
00103 return s_folderContentsType[type].mimetype;
00104 }
00105
00106 KMailICalIfaceImpl::StorageFormat KMailICalIfaceImpl::globalStorageFormat() const {
00107 return GlobalSettings::self()->theIMAPResourceStorageFormat()
00108 == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML ? StorageXML : StorageIcalVcard;
00109 }
00110
00111 static KMail::FolderContentsType folderContentsType( const QString& type )
00112 {
00113 for ( uint i = 0 ; i < sizeof s_folderContentsType / sizeof *s_folderContentsType; ++i )
00114 if ( type == s_folderContentsType[i].contentsTypeStr )
00115 return static_cast<KMail::FolderContentsType>( i );
00116 return KMail::ContentsTypeMail;
00117 }
00118
00119 static QString localizedDefaultFolderName( KMail::FolderContentsType type )
00120 {
00121 return i18n( s_folderContentsType[type].translatedName );
00122 }
00123
00124 const char* KMailICalIfaceImpl::annotationForContentsType( KMail::FolderContentsType type )
00125 {
00126 return s_folderContentsType[type].annotation;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 KMailICalIfaceImpl::KMailICalIfaceImpl()
00140 : DCOPObject( "KMailICalIface" ), QObject( 0, "KMailICalIfaceImpl" ),
00141 mContacts( 0 ), mCalendar( 0 ), mNotes( 0 ), mTasks( 0 ), mJournals( 0 ),
00142 mFolderLanguage( 0 ), mFolderParentDir( 0 ), mFolderType( KMFolderTypeUnknown ),
00143 mUseResourceIMAP( false ), mResourceQuiet( false ), mHideFolders( true )
00144 {
00145
00146 connect( kmkernel, SIGNAL( configChanged() ), this, SLOT( readConfig() ) );
00147 connect( kmkernel, SIGNAL( folderRemoved( KMFolder* ) ),
00148 this, SLOT( slotFolderRemoved( KMFolder* ) ) );
00149
00150 mExtraFolders.setAutoDelete( true );
00151 mAccumulators.setAutoDelete( true );
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 static DwBodyPart* findBodyPartByMimeType( const KMMessage& msg, const char* sType, const char* sSubtype, bool startsWith = false )
00161 {
00162
00163
00164 DwBodyPart* part = msg.getFirstDwBodyPart();
00165 while( part ){
00166
00167
00168 if ( part->hasHeaders() ) {
00169 DwMediaType& contentType = part->Headers().ContentType();
00170 if ( startsWith ) {
00171 if ( contentType.TypeStr() == sType
00172 && QString( contentType.SubtypeStr().c_str() ).startsWith( sSubtype ) )
00173 return part;
00174 }
00175 else
00176 if ( contentType.TypeStr() == sType
00177 && contentType.SubtypeStr() == sSubtype )
00178 return part;
00179 }
00180 part = part->Next();
00181 }
00182 return 0;
00183 }
00184
00185
00186 static DwBodyPart* findBodyPart( const KMMessage& msg, const QString& attachmentName )
00187 {
00188
00189
00190 for ( DwBodyPart* part = msg.getFirstDwBodyPart(); part; part = part->Next() ) {
00191
00192 if ( part->hasHeaders()
00193 && attachmentName == part->Headers().ContentDisposition().Filename().c_str() )
00194 return part;
00195 }
00196 return 0;
00197 }
00198
00199 #if 0
00200 static void debugBodyParts( const char* foo, const KMMessage& msg )
00201 {
00202 kdDebug(5006) << "--debugBodyParts " << foo << "--" << endl;
00203 for ( DwBodyPart* part = msg.getFirstDwBodyPart(); part; part = part->Next() ) {
00204 if ( part->hasHeaders() ) {
00205 kdDebug(5006) << " bodypart: " << part << endl;
00206 kdDebug(5006) << " " << part->Headers().AsString().c_str() << endl;
00207 }
00208 else
00209 kdDebug(5006) << " part " << part << " has no headers" << endl;
00210 }
00211 }
00212 #else
00213 inline static void debugBodyParts( const char*, const KMMessage& ) {}
00214 #endif
00215
00216
00217
00218
00219
00220
00221 bool KMailICalIfaceImpl::updateAttachment( KMMessage& msg,
00222 const QString& attachmentURL,
00223 const QString& attachmentName,
00224 const QString& attachmentMimetype,
00225 bool lookupByName )
00226 {
00227 kdDebug(5006) << "KMailICalIfaceImpl::updateAttachment( " << attachmentURL << " )" << endl;
00228
00229 bool bOK = false;
00230
00231 KURL url( attachmentURL );
00232 if ( url.isValid() && url.isLocalFile() ) {
00233 const QString fileName( url.path() );
00234 QFile file( fileName );
00235 if( file.open( IO_ReadOnly ) ) {
00236 QByteArray rawData = file.readAll();
00237 file.close();
00238
00239
00240 KMMessagePart msgPart;
00241 msgPart.setName( attachmentName );
00242
00243 const int iSlash = attachmentMimetype.find('/');
00244 const QCString sType = attachmentMimetype.left( iSlash ).latin1();
00245 const QCString sSubtype = attachmentMimetype.mid( iSlash+1 ).latin1();
00246 msgPart.setTypeStr( sType );
00247 msgPart.setSubtypeStr( sSubtype );
00248 QCString ctd("attachment;\n filename=\"");
00249 ctd.append( attachmentName.latin1() );
00250 ctd.append("\"");
00251 msgPart.setContentDisposition( ctd );
00252 QValueList<int> dummy;
00253 msgPart.setBodyAndGuessCte( rawData, dummy );
00254 msgPart.setPartSpecifier( fileName );
00255
00256 DwBodyPart* newPart = msg.createDWBodyPart( &msgPart );
00257
00258
00259
00260 newPart->Headers().ContentDisposition().Parse();
00261
00262 DwBodyPart* part = lookupByName ? findBodyPart( msg, attachmentName )
00263 : findBodyPartByMimeType( msg, sType, sSubtype );
00264 if ( part ) {
00265
00266
00267 newPart->SetNext( part->Next() );
00268
00269
00270 *part = *newPart;
00271 delete newPart;
00272 msg.setNeedsAssembly();
00273 kdDebug(5006) << "Attachment " << attachmentName << " updated." << endl;
00274 } else {
00275 msg.addDwBodyPart( newPart );
00276 kdDebug(5006) << "Attachment " << attachmentName << " added." << endl;
00277 }
00278 bOK = true;
00279 }else{
00280 kdDebug(5006) << "Attachment " << attachmentURL << " can not be read." << endl;
00281 }
00282 }else{
00283 kdDebug(5006) << "Attachment " << attachmentURL << " not a local file." << endl;
00284 }
00285
00286 return bOK;
00287 }
00288
00289
00290 bool KMailICalIfaceImpl::kolabXMLFoundAndDecoded( const KMMessage& msg, const QString& mimetype, QString& s )
00291 {
00292 const int iSlash = mimetype.find('/');
00293 const QCString sType = mimetype.left( iSlash ).latin1();
00294 const QCString sSubtype = mimetype.mid( iSlash+1 ).latin1();
00295 DwBodyPart* part = findBodyPartByMimeType( msg, sType, sSubtype, true );
00296 if ( part ) {
00297 KMMessagePart msgPart;
00298 KMMessage::bodyPart(part, &msgPart);
00299 s = msgPart.bodyToUnicode( QTextCodec::codecForName( "utf8" ) );
00300 return true;
00301 }
00302 return false;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 bool KMailICalIfaceImpl::deleteAttachment( KMMessage& msg,
00312 const QString& attachmentName )
00313 {
00314 kdDebug(5006) << "KMailICalIfaceImpl::deleteAttachment( " << attachmentName << " )" << endl;
00315
00316 bool bOK = false;
00317
00318
00319
00320 DwBodyPart* part = findBodyPart( msg, attachmentName );
00321 if ( part ) {
00322 msg.getTopLevelPart()->Body().RemoveBodyPart( part );
00323 delete part;
00324 msg.setNeedsAssembly();
00325 kdDebug(5006) << "Attachment deleted." << endl;
00326 bOK = true;
00327 }
00328
00329 if( !bOK ){
00330 kdDebug(5006) << "Attachment " << attachmentName << " not found." << endl;
00331 }
00332
00333 return bOK;
00334 }
00335
00336 static void setIcalVcardContentTypeHeader( KMMessage *msg, KMail::FolderContentsType t )
00337 {
00338 msg->setType( DwMime::kTypeText );
00339 if ( t == KMail::ContentsTypeCalendar || t == KMail::ContentsTypeTask
00340 || t == KMail::ContentsTypeJournal ) {
00341 msg->setSubtype( DwMime::kSubtypeVCal );
00342 msg->setHeaderField("Content-Type",
00343 "text/calendar; method=REQUEST; charset=\"utf-8\"");
00344 } else if ( t == KMail::ContentsTypeContact ) {
00345 msg->setSubtype( DwMime::kSubtypeXVCard );
00346 msg->setHeaderField( "Content-Type", "Text/X-VCard; charset=\"utf-8\"" );
00347 } else {
00348 kdWarning(5006) << k_funcinfo << "Attempt to write non-groupware contents to folder" << endl;
00349 }
00350 }
00351
00352 static void setXMLContentTypeHeader( KMMessage *msg, const QString plainTextBody )
00353 {
00354
00355
00356
00357 KMMessagePart firstPart;
00358 firstPart.setType( DwMime::kTypeText );
00359 firstPart.setSubtype( DwMime::kSubtypePlain );
00360 msg->removeHeaderField( "Content-Type" );
00361 msg->setType( DwMime::kTypeMultipart );
00362 msg->setSubtype( DwMime::kSubtypeMixed );
00363 msg->headers().ContentType().CreateBoundary( 0 );
00364 msg->headers().ContentType().Assemble();
00365 firstPart.setBodyFromUnicode( plainTextBody );
00366 msg->addBodyPart( &firstPart );
00367 }
00368
00369
00370 Q_UINT32 KMailICalIfaceImpl::addIncidenceKolab( KMFolder& folder,
00371 const QString& subject,
00372 const QString& plainTextBody,
00373 const QMap<QCString, QString>& customHeaders,
00374 const QStringList& attachmentURLs,
00375 const QStringList& attachmentNames,
00376 const QStringList& attachmentMimetypes )
00377 {
00378 kdDebug(5006) << "KMailICalIfaceImpl::addIncidenceKolab( " << attachmentNames << " )" << endl;
00379
00380 Q_UINT32 sernum = 0;
00381 bool bAttachOK = true;
00382
00383
00384 KMMessage* msg = new KMMessage();
00385 msg->initHeader();
00386 msg->setSubject( subject );
00387 msg->setAutomaticFields( true );
00388
00389 QMap<QCString, QString>::ConstIterator ith = customHeaders.begin();
00390 const QMap<QCString, QString>::ConstIterator ithEnd = customHeaders.end();
00391 for ( ; ith != ithEnd ; ++ith ) {
00392 msg->setHeaderField( ith.key(), ith.data() );
00393 }
00394
00395
00396 if ( storageFormat( &folder ) == StorageXML ) {
00397 setXMLContentTypeHeader( msg, plainTextBody );
00398 } else if ( storageFormat( &folder ) == StorageIcalVcard ) {
00399 const KMail::FolderContentsType t = folder.storage()->contentsType();
00400 setIcalVcardContentTypeHeader( msg, t );
00401 msg->setBodyEncoded( plainTextBody.utf8() );
00402 } else {
00403 kdWarning(5006) << k_funcinfo << "Attempt to write to folder with unknown storage type" << endl;
00404 }
00405
00406 Q_ASSERT( attachmentMimetypes.count() == attachmentURLs.count() );
00407 Q_ASSERT( attachmentNames.count() == attachmentURLs.count() );
00408
00409 QStringList::ConstIterator itmime = attachmentMimetypes.begin();
00410 QStringList::ConstIterator iturl = attachmentURLs.begin();
00411 for( QStringList::ConstIterator itname = attachmentNames.begin();
00412 itname != attachmentNames.end()
00413 && itmime != attachmentMimetypes.end()
00414 && iturl != attachmentURLs.end();
00415 ++itname, ++iturl, ++itmime ){
00416 bool byname = !(*itmime).startsWith( "application/x-vnd.kolab." );
00417 if( !updateAttachment( *msg, *iturl, *itname, *itmime, byname ) ){
00418 kdWarning(5006) << "Attachment error, can not add Incidence." << endl;
00419 bAttachOK = false;
00420 break;
00421 }
00422 }
00423
00424 if( bAttachOK ){
00425
00426 msg->cleanupHeader();
00427
00428 msg->touch();
00429 if ( folder.addMsg( msg ) == 0 )
00430
00431 sernum = msg->getMsgSerNum();
00432 kdDebug(5006) << "addIncidenceKolab(): Message done and saved. Sernum: "
00433 << sernum << endl;
00434
00435
00436 addFolderChange( &folder, Contents );
00437 } else
00438 kdError(5006) << "addIncidenceKolab(): Message *NOT* saved!\n";
00439
00440 return sernum;
00441 }
00442
00443 bool KMailICalIfaceImpl::deleteIncidenceKolab( const QString& resource,
00444 Q_UINT32 sernum )
00445 {
00446
00447 if( !mUseResourceIMAP )
00448 return false;
00449
00450 kdDebug(5006) << "KMailICalIfaceImpl::deleteIncidenceKolab( "
00451 << resource << ", " << sernum << ")\n";
00452
00453
00454 KMFolder* f = findResourceFolder( resource );
00455 if( !f ) {
00456 kdError(5006) << "deleteIncidenceKolab(" << resource << ") : Not an IMAP resource folder" << endl;
00457 return false;
00458 }
00459
00460 bool rc = false;
00461
00462 KMMessage* msg = findMessageBySerNum( sernum, f );
00463 if( msg ) {
00464
00465 deleteMsg( msg );
00466 rc = true;
00467 } else {
00468 kdDebug(5006) << "Message not found, cannot remove serNum " << sernum << endl;
00469 }
00470 return rc;
00471 }
00472
00473
00474 int KMailICalIfaceImpl::incidencesKolabCount( const QString& mimetype,
00475 const QString& resource )
00476 {
00477 Q_UNUSED( mimetype );
00478
00479 if( !mUseResourceIMAP )
00480 return 0;
00481
00482 KMFolder* f = findResourceFolder( resource );
00483 if( !f ) {
00484 kdError(5006) << "incidencesKolab(" << resource << ") : Not an IMAP resource folder" << endl;
00485 return 0;
00486 }
00487
00488 f->open("kolabcount");
00489 int n = f->count();
00490 f->close("kolabcount");
00491 kdDebug(5006) << "KMailICalIfaceImpl::incidencesKolabCount( "
00492 << resource << " ) returned " << n << endl;
00493 return n;
00494 }
00495
00496 QMap<Q_UINT32, QString> KMailICalIfaceImpl::incidencesKolab( const QString& mimetype,
00497 const QString& resource,
00498 int startIndex,
00499 int nbMessages )
00500 {
00504
00505 QMap<Q_UINT32, QString> aMap;
00506 if( !mUseResourceIMAP )
00507 return aMap;
00508
00509 KMFolder* f = findResourceFolder( resource );
00510 if( !f ) {
00511 kdError(5006) << "incidencesKolab(" << resource << ") : Not an IMAP resource folder" << endl;
00512 return aMap;
00513 }
00514
00515 f->open("incidences");
00516
00517 int stopIndex = nbMessages == -1 ? f->count() :
00518 QMIN( f->count(), startIndex + nbMessages );
00519 kdDebug(5006) << "KMailICalIfaceImpl::incidencesKolab( " << mimetype << ", "
00520 << resource << " ) from " << startIndex << " to " << stopIndex << endl;
00521
00522 for(int i = startIndex; i < stopIndex; ++i) {
00523 #if 0
00524 bool unget = !f->isMessage(i);
00525 KMMessage* msg = f->getMsg( i );
00526 #else // faster
00527 KMMessage* msg = f->storage()->readTemporaryMsg(i);
00528 #endif
00529 if ( msg ) {
00530 const int iSlash = mimetype.find('/');
00531 const QCString sType = mimetype.left( iSlash ).latin1();
00532 const QCString sSubtype = mimetype.mid( iSlash+1 ).latin1();
00533 if ( sType.isEmpty() || sSubtype.isEmpty() ) {
00534 kdError(5006) << mimetype << " not an type/subtype combination" << endl;
00535 } else {
00536 DwBodyPart* dwPart = findBodyPartByMimeType( *msg, sType, sSubtype );
00537 if ( dwPart ) {
00538 KMMessagePart msgPart;
00539 KMMessage::bodyPart(dwPart, &msgPart);
00540 aMap.insert(msg->getMsgSerNum(), msgPart.bodyToUnicode( QTextCodec::codecForName( "utf8" ) ));
00541 } else {
00542
00543
00544
00545 const QCString type( msg->typeStr() );
00546 const QCString subtype( msg->subtypeStr() );
00547 if (type.lower() == sType && subtype.lower() == sSubtype ) {
00548 aMap.insert( msg->getMsgSerNum(), msg->bodyToUnicode() );
00549 }
00550
00551
00552 }
00553 }
00554 #if 0
00555 if( unget ) f->unGetMsg(i);
00556 #else
00557 delete msg;
00558 #endif
00559 }
00560 }
00561 f->close( "incidences" );
00562 return aMap;
00563 }
00564
00565
00566
00567
00568
00569 void KMailICalIfaceImpl::slotMessageRetrieved( KMMessage* msg )
00570 {
00571 if( !msg ) return;
00572
00573 KMFolder *parent = msg->parent();
00574 Q_ASSERT( parent );
00575 Q_UINT32 sernum = msg->getMsgSerNum();
00576
00577
00578 Accumulator *ac = mAccumulators.find( parent->location() );
00579 if( ac ) {
00580 QString s;
00581 if ( !vPartFoundAndDecoded( msg, s ) ) return;
00582 QString uid( "UID" );
00583 vPartMicroParser( s, uid );
00584 const Q_UINT32 sernum = msg->getMsgSerNum();
00585 mUIDToSerNum.insert( uid, sernum );
00586 ac->add( s );
00587 if( ac->isFull() ) {
00588
00589
00590
00591 mAccumulators.remove( ac->folder );
00592 }
00593 } else {
00594
00595
00596 slotIncidenceAdded( msg->parent(), msg->getMsgSerNum() );
00597 }
00598
00599 if ( mTheUnGetMes.contains( sernum ) ) {
00600 mTheUnGetMes.remove( sernum );
00601 int i = 0;
00602 KMFolder* folder = 0;
00603 KMMsgDict::instance()->getLocation( sernum, &folder, &i );
00604 folder->unGetMsg( i );
00605 }
00606 }
00607
00608
00609 QValueList<KMailICalIfaceImpl::SubResource> KMailICalIfaceImpl::subresourcesKolab( const QString& contentsType )
00610 {
00611 QValueList<SubResource> subResources;
00612
00613
00614 KMFolder* f = folderFromType( contentsType, QString::null );
00615 if ( f ) {
00616 subResources.append( SubResource( f->location(), f->prettyURL(),
00617 !f->isReadOnly(), folderIsAlarmRelevant( f ) ) );
00618 kdDebug(5006) << "Adding(1) folder " << f->location() << " " <<
00619 ( f->isReadOnly() ? "readonly" : "" ) << endl;
00620 }
00621
00622
00623 const KMail::FolderContentsType t = folderContentsType( contentsType );
00624 QDictIterator<ExtraFolder> it( mExtraFolders );
00625 for ( ; it.current(); ++it ){
00626 f = it.current()->folder;
00627 if ( f && f->storage()->contentsType() == t ) {
00628 subResources.append( SubResource( f->location(), f->prettyURL(),
00629 !f->isReadOnly(), folderIsAlarmRelevant( f ) ) );
00630 kdDebug(5006) << "Adding(2) folder " << f->location() << " " <<
00631 ( f->isReadOnly() ? "readonly" : "" ) << endl;
00632 }
00633 }
00634
00635 if ( subResources.isEmpty() )
00636 kdDebug(5006) << "subresourcesKolab: No folder found for " << contentsType << endl;
00637 return subResources;
00638 }
00639
00640 bool KMailICalIfaceImpl::triggerSync( const QString& contentsType )
00641 {
00642 kdDebug(5006) << k_funcinfo << endl;
00643 QValueList<KMailICalIfaceImpl::SubResource> folderList = subresourcesKolab( contentsType );
00644 for ( QValueList<KMailICalIfaceImpl::SubResource>::const_iterator it( folderList.begin() ),
00645 end( folderList.end() );
00646 it != end ; ++it ) {
00647 KMFolder * const f = findResourceFolder( (*it).location );
00648 if ( !f ) continue;
00649 if ( f->folderType() == KMFolderTypeImap || f->folderType() == KMFolderTypeCachedImap ) {
00650 if ( !kmkernel->askToGoOnline() ) {
00651 return false;
00652 }
00653 }
00654
00655 if ( f->folderType() == KMFolderTypeImap ) {
00656 KMFolderImap *imap = static_cast<KMFolderImap*>( f->storage() );
00657 imap->getAndCheckFolder();
00658 } else if ( f->folderType() == KMFolderTypeCachedImap ) {
00659 KMFolderCachedImap* cached = static_cast<KMFolderCachedImap*>( f->storage() );
00660 cached->account()->processNewMailSingleFolder( f );
00661 }
00662 }
00663 return true;
00664 }
00665
00666
00667 bool KMailICalIfaceImpl::isWritableFolder( const QString& type,
00668 const QString& resource )
00669 {
00670 KMFolder* f = folderFromType( type, resource );
00671 if ( !f )
00672
00673 return false;
00674
00675 return !f->isReadOnly();
00676 }
00677
00678
00679 KMailICalIfaceImpl::StorageFormat KMailICalIfaceImpl::storageFormat( const QString& resource )
00680 {
00681 StorageFormat format;
00682 KMFolder* f = findResourceFolder( resource );
00683 if ( f )
00684 format = storageFormat( f );
00685 else
00686 format = globalStorageFormat();
00687 return format;
00688 }
00689
00704 Q_UINT32 KMailICalIfaceImpl::update( const QString& resource,
00705 Q_UINT32 sernum,
00706 const QString& subject,
00707 const QString& plainTextBody,
00708 const QMap<QCString, QString>& customHeaders,
00709 const QStringList& attachmentURLs,
00710 const QStringList& attachmentMimetypes,
00711 const QStringList& attachmentNames,
00712 const QStringList& deletedAttachments )
00713 {
00714 Q_UINT32 rc = 0;
00715
00716 if( !mUseResourceIMAP )
00717 return rc;
00718
00719 Q_ASSERT( !resource.isEmpty() );
00720
00721 kdDebug(5006) << "KMailICalIfaceImpl::update( " << resource << ", " << sernum << " )\n";
00722 kdDebug(5006) << attachmentURLs << "\n";
00723 kdDebug(5006) << attachmentMimetypes << "\n";
00724 kdDebug(5006) << attachmentNames << "\n";
00725 kdDebug(5006) << "deleted attachments:" << deletedAttachments << "\n";
00726
00727
00728 KMFolder* f = findResourceFolder( resource );
00729 if( !f ) {
00730 kdError(5006) << "update(" << resource << ") : Not an IMAP resource folder" << endl;
00731 return rc;
00732 }
00733
00734 f->open("ifaceupdate");
00735
00736 KMMessage* msg = 0;
00737 if ( sernum != 0 ) {
00738 msg = findMessageBySerNum( sernum, f );
00739 if ( !msg ) return 0;
00740
00741 KMMessage* newMsg = new KMMessage( *msg );
00742 newMsg->setSubject( subject );
00743 QMap<QCString, QString>::ConstIterator ith = customHeaders.begin();
00744 const QMap<QCString, QString>::ConstIterator ithEnd = customHeaders.begin();
00745 for ( ; ith != ithEnd ; ++ith )
00746 newMsg->setHeaderField( ith.key(), ith.data() );
00747 newMsg->setParent( 0 );
00748
00749
00750
00751 for( QStringList::ConstIterator it = deletedAttachments.begin();
00752 it != deletedAttachments.end();
00753 ++it ){
00754 if( !deleteAttachment( *newMsg, *it ) ){
00755
00756 }
00757 }
00758
00759 const KMail::FolderContentsType t = f->storage()->contentsType();
00760 const QCString type = msg->typeStr();
00761 const QCString subtype = msg->subtypeStr();
00762 const bool messageWasIcalVcardFormat = ( type.lower() == "text" &&
00763 ( subtype.lower() == "calendar" || subtype.lower() == "x-vcard" ) );
00764
00765 if ( storageFormat( f ) == StorageIcalVcard ) {
00766
00767 if ( !messageWasIcalVcardFormat ) {
00768 setIcalVcardContentTypeHeader( newMsg, t );
00769 }
00770 newMsg->setBodyEncoded( plainTextBody.utf8() );
00771 } else if ( storageFormat( f ) == StorageXML ) {
00772 if ( messageWasIcalVcardFormat ) {
00773
00774
00775 setXMLContentTypeHeader( newMsg, plainTextBody );
00776 }
00777
00778
00779 QStringList::ConstIterator iturl = attachmentURLs.begin();
00780 QStringList::ConstIterator itmime = attachmentMimetypes.begin();
00781 QStringList::ConstIterator itname = attachmentNames.begin();
00782 for( ;
00783 iturl != attachmentURLs.end()
00784 && itmime != attachmentMimetypes.end()
00785 && itname != attachmentNames.end();
00786 ++iturl, ++itname, ++itmime ){
00787 bool byname = !(*itmime).startsWith( "application/x-vnd.kolab." );
00788 if( !updateAttachment( *newMsg, *iturl, *itname, *itmime, byname ) ){
00789 kdDebug(5006) << "Attachment error, can not update attachment " << *iturl << endl;
00790 break;
00791 }
00792 }
00793 }
00794
00795
00796
00797
00798 newMsg->cleanupHeader();
00799
00800
00801
00802 deleteMsg( msg );
00803 if ( f->addMsg( newMsg ) == 0 ) {
00804
00805 rc = newMsg->getMsgSerNum();
00806 kdDebug(5006) << "forget about " << sernum << ", it's " << rc << " now" << endl;
00807 }
00808 addFolderChange( f, Contents );
00809 } else {
00810
00811 rc = addIncidenceKolab( *f, subject, plainTextBody, customHeaders,
00812 attachmentURLs,
00813 attachmentNames,
00814 attachmentMimetypes );
00815 }
00816
00817 f->close("ifaceupdate");
00818 return rc;
00819 }
00820
00821 KURL KMailICalIfaceImpl::getAttachment( const QString& resource,
00822 Q_UINT32 sernum,
00823 const QString& filename )
00824 {
00825
00826
00827
00828 if( !mUseResourceIMAP )
00829 return KURL();
00830
00831 kdDebug(5006) << "KMailICalIfaceImpl::getAttachment( "
00832 << resource << ", " << sernum << ", " << filename << " )\n";
00833
00834
00835 KMFolder* f = findResourceFolder( resource );
00836 if( !f ) {
00837 kdError(5006) << "getAttachment(" << resource << ") : Not an IMAP resource folder" << endl;
00838 return KURL();
00839 }
00840 if ( storageFormat( f ) != StorageXML ) {
00841 kdError(5006) << "getAttachment(" << resource << ") : Folder has wrong storage format " << storageFormat( f ) << endl;
00842 return KURL();
00843 }
00844
00845 KURL url;
00846
00847 bool bOK = false;
00848 bool quiet = mResourceQuiet;
00849 mResourceQuiet = true;
00850
00851 KMMessage* msg = findMessageBySerNum( sernum, f );
00852 if( msg ) {
00853
00854
00855 DwBodyPart* part = findBodyPart( *msg, filename );
00856 if ( part ) {
00857
00858 KMMessagePart aPart;
00859 msg->bodyPart( part, &aPart );
00860 QByteArray rawData( aPart.bodyDecodedBinary() );
00861
00862 KTempFile file;
00863 file.file()->writeBlock( rawData.data(), rawData.size() );
00864
00865 url.setPath( file.name() );
00866
00867 bOK = true;
00868 }
00869
00870 if( !bOK ){
00871 kdDebug(5006) << "Attachment " << filename << " not found." << endl;
00872 }
00873 }else{
00874 kdDebug(5006) << "Message not found." << endl;
00875 }
00876
00877 mResourceQuiet = quiet;
00878 return url;
00879 }
00880
00881
00882
00883
00884
00885
00886
00887 void KMailICalIfaceImpl::slotFolderRemoved( KMFolder* folder )
00888 {
00889
00890
00891 folderContentsTypeChanged( folder, KMail::ContentsTypeMail );
00892 KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" );
00893 configGroup.deleteEntry( folder->idString() + "-storageFormat" );
00894 configGroup.deleteEntry( folder->idString() + "-changes" );
00895 }
00896
00897
00898 void KMailICalIfaceImpl::slotIncidenceAdded( KMFolder* folder,
00899 Q_UINT32 sernum )
00900 {
00901 if( mResourceQuiet || !mUseResourceIMAP )
00902 return;
00903
00904
00905 QString type = folderContentsType( folder->storage()->contentsType() );
00906 if( type.isEmpty() ) {
00907 kdError(5006) << "Not an IMAP resource folder" << endl;
00908 return;
00909 }
00910
00911 int i = 0;
00912 KMFolder* aFolder = 0;
00913 KMMsgDict::instance()->getLocation( sernum, &aFolder, &i );
00914 assert( folder == aFolder );
00915
00916 bool unget = !folder->isMessage( i );
00917 QString s;
00918 QString uid( "UID" );
00919 KMMessage *msg = folder->getMsg( i );
00920 if( !msg ) return;
00921 if( msg->isComplete() ) {
00922
00923 bool ok = false;
00924 StorageFormat format = storageFormat( folder );
00925 switch( format ) {
00926 case StorageIcalVcard:
00927
00928 ok = vPartFoundAndDecoded( msg, s );
00929 if ( ok )
00930 vPartMicroParser( s, uid );
00931 break;
00932 case StorageXML:
00933
00934 if ( kolabXMLFoundAndDecoded( *msg,
00935 folderKolabMimeType( folder->storage()->contentsType() ), s ) ) {
00936 uid = msg->subject();
00937 ok = true;
00938 }
00939 break;
00940 }
00941 if ( !ok ) {
00942 if ( unget )
00943 folder->unGetMsg( i );
00944 return;
00945 }
00946 const Q_UINT32 sernum = msg->getMsgSerNum();
00947 mUIDToSerNum.insert( uid, sernum );
00948
00949
00950 if ( mInTransit.contains( uid ) ) {
00951 mInTransit.remove( uid );
00952 }
00953 incidenceAdded( type, folder->location(), sernum, format, s );
00954 } else {
00955
00956
00957 if ( unget ) mTheUnGetMes.insert( msg->getMsgSerNum(), true );
00958 FolderJob *job = msg->parent()->createJob( msg );
00959 connect( job, SIGNAL( messageRetrieved( KMMessage* ) ),
00960 this, SLOT( slotMessageRetrieved( KMMessage* ) ) );
00961 job->start();
00962 return;
00963 }
00964 if( unget ) folder->unGetMsg(i);
00965 }
00966
00967
00968 void KMailICalIfaceImpl::slotIncidenceDeleted( KMFolder* folder,
00969 Q_UINT32 sernum )
00970 {
00971 if( mResourceQuiet || !mUseResourceIMAP )
00972 return;
00973
00974 QString type = folderContentsType( folder->storage()->contentsType() );
00975
00976 if( !type.isEmpty() ) {
00977
00978 int i = 0;
00979 KMFolder* aFolder = 0;
00980 KMMsgDict::instance()->getLocation( sernum, &aFolder, &i );
00981 assert( folder == aFolder );
00982
00983
00984 bool unget = !folder->isMessage( i );
00985 QString s;
00986 bool ok = false;
00987 KMMessage* msg = folder->getMsg( i );
00988 QString uid( "UID" );
00989 switch( storageFormat( folder ) ) {
00990 case StorageIcalVcard:
00991 if( vPartFoundAndDecoded( msg, s ) ) {
00992 vPartMicroParser( s, uid );
00993 ok = true;
00994 }
00995 break;
00996 case StorageXML:
00997 if ( kolabXMLFoundAndDecoded( *msg, folderKolabMimeType( folder->storage()->contentsType() ), s ) ) {
00998 uid = msg->subject();
00999 ok = true;
01000 }
01001 break;
01002 }
01003 if ( ok ) {
01004 kdDebug(5006) << "Emitting DCOP signal incidenceDeleted( "
01005 << type << ", " << folder->location() << ", " << uid
01006 << " )" << endl;
01007 incidenceDeleted( type, folder->location(), uid );
01008 }
01009 if( unget ) folder->unGetMsg(i);
01010 } else
01011 kdError(5006) << "Not a groupware folder" << endl;
01012 }
01013
01014
01015 void KMailICalIfaceImpl::slotRefresh( const QString& type )
01016 {
01017 if( mUseResourceIMAP ) {
01018 signalRefresh( type, QString::null );
01019 kdDebug(5006) << "Emitting DCOP signal signalRefresh( " << type << " )" << endl;
01020 }
01021 }
01022
01023
01024 void KMailICalIfaceImpl::slotRefreshFolder( KMFolder* folder)
01025 {
01026
01027
01028
01029 if( mUseResourceIMAP && folder ) {
01030 if( folder == mCalendar || folder == mContacts
01031 || folder == mNotes || folder == mTasks
01032 || folder == mJournals || mExtraFolders.find( folder->location() ) ) {
01033
01034 KMail::FolderContentsType ct = folder->storage()->contentsType();
01035 slotRefresh( s_folderContentsType[ct].contentsTypeStr );
01036 }
01037 }
01038 }
01039
01040
01041
01042
01043
01044 KMFolder* KMailICalIfaceImpl::folderFromType( const QString& type,
01045 const QString& folder )
01046 {
01047 if( mUseResourceIMAP ) {
01048 KMFolder* f = 0;
01049 if ( !folder.isEmpty() ) {
01050 f = extraFolder( type, folder );
01051 if ( f )
01052 return f;
01053 }
01054
01055 if( type == "Calendar" ) f = mCalendar;
01056 else if( type == "Contact" ) f = mContacts;
01057 else if( type == "Note" ) f = mNotes;
01058 else if( type == "Task" || type == "Todo" ) f = mTasks;
01059 else if( type == "Journal" ) f = mJournals;
01060
01061 if ( f && ( folder.isEmpty() || folder == f->location() ) )
01062 return f;
01063
01064 kdError(5006) << "No folder ( " << type << ", " << folder << " )\n";
01065 }
01066
01067 return 0;
01068 }
01069
01070
01071
01072
01073 bool KMailICalIfaceImpl::isResourceFolder( KMFolder* folder ) const
01074 {
01075 return mUseResourceIMAP && folder &&
01076 ( isStandardResourceFolder( folder ) || mExtraFolders.find( folder->location() )!=0 );
01077 }
01078
01079 bool KMailICalIfaceImpl::isStandardResourceFolder( KMFolder* folder ) const
01080 {
01081 return ( folder == mCalendar || folder == mTasks || folder == mJournals ||
01082 folder == mNotes || folder == mContacts );
01083 }
01084
01085 bool KMailICalIfaceImpl::hideResourceFolder( KMFolder* folder ) const
01086 {
01087 return mHideFolders && isResourceFolder( folder );
01088 }
01089
01090 bool KMailICalIfaceImpl::hideResourceAccountRoot( KMFolder* folder ) const
01091 {
01092 KMFolderCachedImap *dimapFolder = dynamic_cast<KMFolderCachedImap*>( folder->storage() );
01093 bool hide = dimapFolder && mHideFolders
01094 && (int)dimapFolder->account()->id() == GlobalSettings::self()->theIMAPResourceAccount()
01095 && GlobalSettings::self()->showOnlyGroupwareFoldersForGroupwareAccount();
01096 return hide;
01097
01098 }
01099
01100 KFolderTreeItem::Type KMailICalIfaceImpl::folderType( KMFolder* folder ) const
01101 {
01102 if( mUseResourceIMAP && folder ) {
01103 if( folder == mCalendar || folder == mContacts
01104 || folder == mNotes || folder == mTasks
01105 || folder == mJournals || mExtraFolders.find( folder->location() ) ) {
01106 KMail::FolderContentsType ct = folder->storage()->contentsType();
01107 return s_folderContentsType[ct].treeItemType;
01108 }
01109 }
01110
01111 return KFolderTreeItem::Other;
01112 }
01113
01114
01115
01116 static QMap<KFolderTreeItem::Type,QString> folderNames[4];
01117 QString KMailICalIfaceImpl::folderName( KFolderTreeItem::Type type, int language ) const
01118 {
01119
01120 if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML )
01121 language = 0;
01122
01123 static bool folderNamesSet = false;
01124 if( !folderNamesSet ) {
01125 folderNamesSet = true;
01126
01127
01128
01129
01130 folderNames[0][KFolderTreeItem::Calendar] = QString::fromLatin1("Calendar");
01131 folderNames[0][KFolderTreeItem::Tasks] = QString::fromLatin1("Tasks");
01132 folderNames[0][KFolderTreeItem::Journals] = QString::fromLatin1("Journal");
01133 folderNames[0][KFolderTreeItem::Contacts] = QString::fromLatin1("Contacts");
01134 folderNames[0][KFolderTreeItem::Notes] = QString::fromLatin1("Notes");
01135
01136
01137 folderNames[1][KFolderTreeItem::Calendar] = QString::fromLatin1("Kalender");
01138 folderNames[1][KFolderTreeItem::Tasks] = QString::fromLatin1("Aufgaben");
01139 folderNames[1][KFolderTreeItem::Journals] = QString::fromLatin1("Journal");
01140 folderNames[1][KFolderTreeItem::Contacts] = QString::fromLatin1("Kontakte");
01141 folderNames[1][KFolderTreeItem::Notes] = QString::fromLatin1("Notizen");
01142
01143
01144 folderNames[2][KFolderTreeItem::Calendar] = QString::fromLatin1("Calendrier");
01145 folderNames[2][KFolderTreeItem::Tasks] = QString::fromLatin1("Tâches");
01146 folderNames[2][KFolderTreeItem::Journals] = QString::fromLatin1("Journal");
01147 folderNames[2][KFolderTreeItem::Contacts] = QString::fromLatin1("Contacts");
01148 folderNames[2][KFolderTreeItem::Notes] = QString::fromLatin1("Notes");
01149
01150
01151 folderNames[3][KFolderTreeItem::Calendar] = QString::fromLatin1("Agenda");
01152 folderNames[3][KFolderTreeItem::Tasks] = QString::fromLatin1("Taken");
01153 folderNames[3][KFolderTreeItem::Journals] = QString::fromLatin1("Logboek");
01154 folderNames[3][KFolderTreeItem::Contacts] = QString::fromLatin1("Contactpersonen");
01155 folderNames[3][KFolderTreeItem::Notes] = QString::fromLatin1("Notities");
01156 }
01157
01158 if( language < 0 || language > 3 ) {
01159 return folderNames[mFolderLanguage][type];
01160 }
01161 else {
01162 return folderNames[language][type];
01163 }
01164 }
01165
01166
01167
01168 KMMessage *KMailICalIfaceImpl::findMessageByUID( const QString& uid, KMFolder* folder )
01169 {
01170 if( !folder || !mUIDToSerNum.contains( uid ) ) return 0;
01171 int i;
01172 KMFolder *aFolder;
01173 KMMsgDict::instance()->getLocation( mUIDToSerNum[uid], &aFolder, &i );
01174 Q_ASSERT( aFolder == folder );
01175 return folder->getMsg( i );
01176 }
01177
01178
01179 KMMessage *KMailICalIfaceImpl::findMessageBySerNum( Q_UINT32 serNum, KMFolder* folder )
01180 {
01181 if( !folder ) return 0;
01182
01183 KMMessage *message = 0;
01184 KMFolder* aFolder = 0;
01185 int index;
01186 KMMsgDict::instance()->getLocation( serNum, &aFolder, &index );
01187 if( aFolder && aFolder != folder ) {
01188 kdWarning(5006) << "findMessageBySerNum( " << serNum << " ) found it in folder " << aFolder->location() << ", expected " << folder->location() << endl;
01189 } else {
01190 if( aFolder )
01191 message = aFolder->getMsg( index );
01192 if (!message)
01193 kdWarning(5006) << "findMessageBySerNum( " << serNum << " ) invalid serial number\n" << endl;
01194 }
01195 return message;
01196 }
01197
01198 void KMailICalIfaceImpl::deleteMsg( KMMessage *msg )
01199 {
01200 if( !msg ) return;
01201
01202
01203 KMFolder *srcFolder = msg->parent();
01204 int idx = srcFolder->find(msg);
01205 assert(idx != -1);
01206 srcFolder->removeMsg(idx);
01207 delete msg;
01208 addFolderChange( srcFolder, Contents );
01209 }
01210
01211 void KMailICalIfaceImpl::folderContentsTypeChanged( KMFolder* folder,
01212 KMail::FolderContentsType contentsType )
01213 {
01214 if ( !mUseResourceIMAP )
01215 return;
01216
01217
01218
01219
01220 if ( isStandardResourceFolder( folder ) )
01221 return;
01222
01223
01224 const QString location = folder->location();
01225 ExtraFolder* ef = mExtraFolders.find( location );
01226 if ( ef && ef->folder ) {
01227
01228 subresourceDeleted(folderContentsType( folder->storage()->contentsType() ), location );
01229
01230 if ( contentsType == 0 ) {
01231
01232 mExtraFolders.remove( location );
01233 folder->disconnect( this );
01234 return;
01235 }
01236
01237 } else {
01238 if ( ef && !ef->folder )
01239 mExtraFolders.remove( location );
01240 if ( contentsType == 0 )
01241 return;
01242
01243
01244
01245 ef = new ExtraFolder( folder );
01246 mExtraFolders.insert( location, ef );
01247
01248 FolderInfo info = readFolderInfo( folder );
01249 mFolderInfoMap.insert( folder, info );
01250
01251
01252
01253
01254
01255
01256 if ( folder->folderType() == KMFolderTypeCachedImap ) {
01257 QString annotation = static_cast<KMFolderCachedImap*>( folder->storage() )->annotationFolderType();
01258 kdDebug(5006) << "folderContentsTypeChanged: " << folder->name() << " has annotation " << annotation << endl;
01259 if ( annotation == QString( s_folderContentsType[contentsType].annotation ) + ".default" )
01260 folder->setLabel( localizedDefaultFolderName( contentsType ) );
01261 }
01262
01263 connectFolder( folder );
01264 }
01265
01266 subresourceAdded( folderContentsType( contentsType ), location, folder->prettyURL(),
01267 !folder->isReadOnly(), folderIsAlarmRelevant( folder ) );
01268 }
01269
01270 KMFolder* KMailICalIfaceImpl::extraFolder( const QString& type,
01271 const QString& folder )
01272 {
01273
01274
01275 int t = folderContentsType( type );
01276 if ( t < 1 || t > 5 )
01277 return 0;
01278
01279 ExtraFolder* ef = mExtraFolders.find( folder );
01280 if ( ef && ef->folder && ef->folder->storage()->contentsType() == t )
01281 return ef->folder;
01282
01283 return 0;
01284 }
01285
01286 KMailICalIfaceImpl::StorageFormat KMailICalIfaceImpl::storageFormat( KMFolder* folder ) const
01287 {
01288 FolderInfoMap::ConstIterator it = mFolderInfoMap.find( folder );
01289 if ( it != mFolderInfoMap.end() )
01290 return (*it).mStorageFormat;
01291 return globalStorageFormat();
01292 }
01293
01294 void KMailICalIfaceImpl::setStorageFormat( KMFolder* folder, StorageFormat format )
01295 {
01296 FolderInfoMap::Iterator it = mFolderInfoMap.find( folder );
01297 if ( it != mFolderInfoMap.end() ) {
01298 (*it).mStorageFormat = format;
01299 } else {
01300 FolderInfo info( format, NoChange );
01301 mFolderInfoMap.insert( folder, info );
01302 }
01303 KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" );
01304 configGroup.writeEntry( folder->idString() + "-storageFormat",
01305 format == StorageXML ? "xml" : "icalvcard" );
01306 }
01307
01308 void KMailICalIfaceImpl::addFolderChange( KMFolder* folder, FolderChanges changes )
01309 {
01310 FolderInfoMap::Iterator it = mFolderInfoMap.find( folder );
01311 if ( it != mFolderInfoMap.end() ) {
01312 (*it).mChanges = static_cast<FolderChanges>( (*it).mChanges | changes );
01313 } else {
01314 kdDebug(5006) << "addFolderChange: nothing known about folder " << folder->location() << endl;
01315 }
01316 KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" );
01317 configGroup.writeEntry( folder->idString() + "-changes", (*it).mChanges );
01318 }
01319
01320 KMailICalIfaceImpl::FolderInfo KMailICalIfaceImpl::readFolderInfo( const KMFolder * const folder ) const
01321 {
01322 KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" );
01323 QString str = configGroup.readEntry( folder->idString() + "-storageFormat", "unset" );
01324 FolderInfo info;
01325 if ( str == "unset" ) {
01326 info.mStorageFormat = globalStorageFormat();
01327 configGroup.writeEntry( folder->idString() + "-storageFormat",
01328 info.mStorageFormat == StorageXML ? "xml" : "icalvcard" );
01329 } else {
01330 info.mStorageFormat = ( str == "xml" ) ? StorageXML : StorageIcalVcard;
01331 }
01332 info.mChanges = (FolderChanges) configGroup.readNumEntry( folder->idString() + "-changes" );
01333 return info;
01334 }
01335
01336
01337 void KMailICalIfaceImpl::folderSynced( KMFolder* folder, const KURL& folderURL )
01338 {
01339 FolderInfoMap::Iterator it = mFolderInfoMap.find( folder );
01340 if ( it != mFolderInfoMap.end() && (*it).mChanges ) {
01341 handleFolderSynced( folder, folderURL, (*it).mChanges );
01342 (*it).mChanges = NoChange;
01343 }
01344 }
01345
01346 void KMailICalIfaceImpl::handleFolderSynced( KMFolder* folder,
01347 const KURL& folderURL,
01348 int _changes )
01349 {
01350
01351
01352
01353
01354 if ( ( _changes & KMailICalIface::Contents ) ||
01355 ( _changes & KMailICalIface::ACL ) ) {
01356 if ( storageFormat( folder ) == StorageXML && folder->storage()->contentsType() == KMail::ContentsTypeCalendar )
01357 triggerKolabFreeBusy( folderURL );
01358 }
01359 }
01360
01361 void KMailICalIfaceImpl::folderDeletedOnServer( const KURL& folderURL )
01362 {
01363 triggerKolabFreeBusy( folderURL );
01364 }
01365
01366 void KMailICalIfaceImpl::triggerKolabFreeBusy( const KURL& folderURL )
01367 {
01368
01369
01370
01371 KURL httpURL( folderURL );
01372
01373 httpURL.setProtocol( "https" );
01374 httpURL.setPort( 0 );
01375
01376
01377 QString path = folderURL.path( -1 );
01378 Q_ASSERT( path.startsWith( "/" ) );
01379 int secondSlash = path.find( '/', 1 );
01380 if ( secondSlash == -1 ) {
01381 kdWarning() << "KCal::ResourceKolab::fromKMailFolderSynced path is too short: " << path << endl;
01382 return;
01383 }
01384 if ( path.startsWith( "/INBOX/", false ) ) {
01385
01386 path = path.mid( secondSlash );
01387 path.prepend( folderURL.user() );
01388 } else {
01389
01390
01391 path = path.mid( secondSlash );
01392 }
01393
01394 httpURL.setPath( "/freebusy/trigger/" + path + ".pfb" );
01395 httpURL.setQuery( QString::null );
01396
01397 httpURL = KURL( httpURL.url(0,106), 106 );
01398 kdDebug() << "Triggering PFB update for " << folderURL << " : getting " << httpURL << endl;
01399
01400
01401 KIO::get( httpURL, false, false );
01402 }
01403
01404 void KMailICalIfaceImpl::slotFolderPropertiesChanged( KMFolder* folder )
01405 {
01406 if ( isResourceFolder( folder ) ) {
01407 const QString location = folder->location();
01408 const QString contentsTypeStr = folderContentsType( folder->storage()->contentsType() );
01409 subresourceDeleted( contentsTypeStr, location );
01410
01411 subresourceAdded( contentsTypeStr, location, folder->prettyURL(),
01412 !folder->isReadOnly(), folderIsAlarmRelevant( folder ) );
01413
01414 }
01415 }
01416
01417
01418 void KMailICalIfaceImpl::slotFolderRenamed()
01419 {
01420 const KMFolder* folder = static_cast<const KMFolder *>( sender() );
01421 slotFolderPropertiesChanged( const_cast<KMFolder*>( folder ) );
01422 }
01423
01424 void KMailICalIfaceImpl::slotFolderLocationChanged( const QString &oldLocation,
01425 const QString &newLocation )
01426 {
01427 KMFolder *folder = findResourceFolder( oldLocation );
01428 ExtraFolder* ef = mExtraFolders.find( oldLocation );
01429 if ( ef ) {
01430
01431 mExtraFolders.setAutoDelete( false );
01432 mExtraFolders.remove( oldLocation );
01433 mExtraFolders.setAutoDelete( true );
01434 mExtraFolders.insert( newLocation, ef );
01435 }
01436 if ( folder )
01437 subresourceDeleted( folderContentsType( folder->storage()->contentsType() ), oldLocation );
01438
01439 }
01440
01441 KMFolder* KMailICalIfaceImpl::findResourceFolder( const QString& resource )
01442 {
01443
01444 if( mCalendar && mCalendar->location() == resource )
01445 return mCalendar;
01446 if ( mContacts && mContacts->location() == resource )
01447 return mContacts;
01448 if ( mNotes && mNotes->location() == resource )
01449 return mNotes;
01450 if ( mTasks && mTasks->location() == resource )
01451 return mTasks;
01452 if ( mJournals && mJournals->location() == resource )
01453 return mJournals;
01454
01455
01456 ExtraFolder* ef = mExtraFolders.find( resource );
01457 if ( ef )
01458 return ef->folder;
01459
01460
01461 return 0;
01462 }
01463
01464
01465
01466
01467
01468 void KMailICalIfaceImpl::readConfig()
01469 {
01470 bool enabled = GlobalSettings::self()->theIMAPResourceEnabled() &&
01471 ( GlobalSettings::self()->theIMAPResourceAccount() != 0 );
01472
01473 if( !enabled ) {
01474 if( mUseResourceIMAP == true ) {
01475
01476 mUseResourceIMAP = false;
01477 cleanup();
01478 reloadFolderTree();
01479 }
01480 return;
01481 }
01482 mUseResourceIMAP = enabled;
01483
01484
01485 const bool hideFolders = GlobalSettings::self()->hideGroupwareFolders();
01486 QString parentName = GlobalSettings::self()->theIMAPResourceFolderParent();
01487
01488
01489 KMFolderDir* folderParentDir;
01490 KMFolderType folderType;
01491 KMFolder* folderParent = kmkernel->findFolderById( parentName );
01492 if( folderParent == 0 ) {
01493
01494
01495 kdDebug(5006) << "Groupware folder " << parentName << " not found. Groupware functionality disabled" << endl;
01496
01497 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::self()->theIMAPResourceAccount() );
01498 Q_ASSERT( account );
01499 if ( account ) {
01500
01501 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01502 this, SLOT( slotCheckDone() ) );
01503 connect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01504 this, SLOT( slotCheckDone() ) );
01505 }
01506 mUseResourceIMAP = false;
01507
01508 mCalendar = 0;
01509 mTasks = 0;
01510 mJournals = 0;
01511 mContacts = 0;
01512 mNotes = 0;
01513 return;
01514 } else {
01515 folderParentDir = folderParent->createChildFolder();
01516 folderType = folderParent->folderType();
01517 }
01518
01519
01520
01521 bool noneFound = true;
01522 bool mustFix = false;
01523 QValueVector<StandardFolderSearchResult> results( KMail::ContentsTypeLast + 1 );
01524 for ( int i = 0; i < KMail::ContentsTypeLast+1; ++i ) {
01525 if ( i != KMail::ContentsTypeMail ) {
01526 results[i] = findStandardResourceFolder( folderParentDir, static_cast<KMail::FolderContentsType>(i) );
01527 if ( results[i].found == StandardFolderSearchResult::FoundAndStandard )
01528 noneFound = false;
01529 else if ( results[i].found == StandardFolderSearchResult::FoundByType ||
01530 results[i].found == StandardFolderSearchResult::FoundByName ) {
01531 mustFix = true;
01532 noneFound = false;
01533 } else
01534 mustFix = true;
01535 }
01536 }
01537
01538
01539 if( mUseResourceIMAP && !noneFound && !mustFix && mFolderParentDir == folderParentDir
01540 && mFolderType == folderType ) {
01541
01542 if ( hideFolders != mHideFolders ) {
01543
01544 mHideFolders = hideFolders;
01545 reloadFolderTree();
01546 }
01547 return;
01548 }
01549
01550 if( noneFound || mustFix ) {
01551 QString msg;
01552 QString parentFolderName = folderParent != 0 ? folderParent->name() : folderParentDir->name();
01553 if ( noneFound ) {
01554
01555 msg = i18n("KMail will now create the required groupware folders"
01556 " as subfolders of %1; if you do not want this, cancel"
01557 " and the IMAP resource will be disabled").arg(parentFolderName);
01558 } else {
01559
01560 QString operations = "<ul>";
01561 for ( int i = 0; i < KMail::ContentsTypeLast+1; ++i ) {
01562 if ( i != KMail::ContentsTypeMail ) {
01563 QString typeName = localizedDefaultFolderName( static_cast<KMail::FolderContentsType>( i ) );
01564 if ( results[i].found == StandardFolderSearchResult::NotFound )
01565 operations += "<li>" + i18n( "%1: no folder found. It will be created." ).arg( typeName ) + "</li>";
01566 else if ( results[i].found == StandardFolderSearchResult::FoundByType || results[i].found == StandardFolderSearchResult::FoundByName )
01567 operations += "<li>" + i18n( "%1: found folder %2. It will be set as the main groupware folder." ).
01568 arg( typeName ).arg( results[i].folder->label() ) + "</li>";
01569 }
01570 }
01571 operations += "</ul>";
01572
01573 msg = i18n("<qt>KMail found the following groupware folders in %1 and needs to perform the following operations: %2"
01574 "<br>If you do not want this, cancel"
01575 " and the IMAP resource will be disabled").arg(parentFolderName, operations);
01576
01577 }
01578
01579 if( KMessageBox::questionYesNo( 0, msg,
01580 i18n("Standard Groupware Folders"), KStdGuiItem::cont(), KStdGuiItem::cancel() ) == KMessageBox::No ) {
01581
01582 GlobalSettings::self()->setTheIMAPResourceEnabled( false );
01583 mUseResourceIMAP = false;
01584 mFolderParentDir = 0;
01585 mFolderParent = 0;
01586 reloadFolderTree();
01587 return;
01588 }
01589 }
01590
01591
01592 mUseResourceIMAP = true;
01593 mFolderLanguage = GlobalSettings::self()->theIMAPResourceFolderLanguage();
01594 if( mFolderLanguage > 3 ) mFolderLanguage = 0;
01595 mFolderParentDir = folderParentDir;
01596 mFolderParent = folderParent;
01597 mFolderType = folderType;
01598 mHideFolders = hideFolders;
01599
01600
01601 cleanup();
01602
01603
01604 mCalendar = initFolder( KMail::ContentsTypeCalendar );
01605 mTasks = initFolder( KMail::ContentsTypeTask );
01606 mJournals = initFolder( KMail::ContentsTypeJournal );
01607 mContacts = initFolder( KMail::ContentsTypeContact );
01608 mNotes = initFolder( KMail::ContentsTypeNote );
01609
01610
01611 if ( mCalendar->folderType() == KMFolderTypeCachedImap )
01612 static_cast<KMFolderCachedImap *>( mCalendar->storage() )->updateAnnotationFolderType();
01613 if ( mTasks->folderType() == KMFolderTypeCachedImap )
01614 static_cast<KMFolderCachedImap *>( mTasks->storage() )->updateAnnotationFolderType();
01615 if ( mJournals->folderType() == KMFolderTypeCachedImap )
01616 static_cast<KMFolderCachedImap *>( mJournals->storage() )->updateAnnotationFolderType();
01617 if ( mContacts->folderType() == KMFolderTypeCachedImap )
01618 static_cast<KMFolderCachedImap *>( mContacts->storage() )->updateAnnotationFolderType();
01619 if ( mNotes->folderType() == KMFolderTypeCachedImap )
01620 static_cast<KMFolderCachedImap *>( mNotes->storage() )->updateAnnotationFolderType();
01621
01622
01623
01624
01625 kdDebug(5006) << k_funcinfo << "mCalendar=" << mCalendar << " " << mCalendar->location() << endl;
01626 kdDebug(5006) << k_funcinfo << "mContacts=" << mContacts << " " << mContacts->location() << endl;
01627 kdDebug(5006) << k_funcinfo << "mNotes=" << mNotes << " " << mNotes->location() << endl;
01628
01629
01630 QStringList folderNames;
01631 QValueList<QGuardedPtr<KMFolder> > folderList;
01632 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
01633 for(QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin();
01634 it != folderList.end(); ++it)
01635 {
01636 FolderStorage* storage = (*it)->storage();
01637 if ( storage->contentsType() != 0 ) {
01638 folderContentsTypeChanged( *it, storage->contentsType() );
01639 }
01640 }
01641
01642
01643
01644 mExtraFolders.remove( mCalendar->location() );
01645 mExtraFolders.remove( mTasks->location() );
01646 mExtraFolders.remove( mJournals->location() );
01647 mExtraFolders.remove( mContacts->location() );
01648 mExtraFolders.remove( mNotes->location() );
01649
01650
01651
01652 subresourceAdded( folderContentsType( KMail::ContentsTypeCalendar ), mCalendar->location(), mCalendar->label(), true, true );
01653 subresourceAdded( folderContentsType( KMail::ContentsTypeTask ), mTasks->location(), mTasks->label(), true, true );
01654 subresourceAdded( folderContentsType( KMail::ContentsTypeJournal ), mJournals->location(), mJournals->label(), true, false );
01655 subresourceAdded( folderContentsType( KMail::ContentsTypeContact ), mContacts->location(), mContacts->label(), true, false );
01656 subresourceAdded( folderContentsType( KMail::ContentsTypeNote ), mNotes->location(), mNotes->label(), true, false );
01657
01658 reloadFolderTree();
01659 }
01660
01661 void KMailICalIfaceImpl::slotCheckDone()
01662 {
01663 QString parentName = GlobalSettings::self()->theIMAPResourceFolderParent();
01664 KMFolder* folderParent = kmkernel->findFolderById( parentName );
01665
01666 if ( folderParent )
01667 {
01668 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::self()->theIMAPResourceAccount() );
01669 if ( account )
01670 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01671 this, SLOT( slotCheckDone() ) );
01672 readConfig();
01673 }
01674 }
01675
01676 KMFolder* KMailICalIfaceImpl::initFolder( KMail::FolderContentsType contentsType )
01677 {
01678
01679 KMFolderType type = mFolderType;
01680 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
01681
01682 KFolderTreeItem::Type itemType = s_folderContentsType[contentsType].treeItemType;
01683
01684
01685
01686 StandardFolderSearchResult result = findStandardResourceFolder( mFolderParentDir, contentsType );
01687 KMFolder* folder = result.folder;
01688
01689 if ( !folder ) {
01690
01691 folder =
01692 mFolderParentDir->createFolder( localizedDefaultFolderName( contentsType ), false, type );
01693 if( mFolderType == KMFolderTypeImap ) {
01694 KMFolderImap* parentFolder = static_cast<KMFolderImap*>( mFolderParent->storage() );
01695 parentFolder->createFolder( localizedDefaultFolderName( contentsType ) );
01696 static_cast<KMFolderImap*>( folder->storage() )->setAccount( parentFolder->account() );
01697 }
01698
01699 setStorageFormat( folder, globalStorageFormat() );
01700 } else {
01701 FolderInfo info = readFolderInfo( folder );
01702 mFolderInfoMap.insert( folder, info );
01703
01704 }
01705
01706 if( folder->canAccess() != 0 ) {
01707 KMessageBox::sorry(0, i18n("You do not have read/write permission to your %1 folder.")
01708 .arg( folderName( itemType ) ) );
01709 return 0;
01710 }
01711 folder->storage()->setContentsType( contentsType );
01712 folder->setSystemFolder( true );
01713 folder->storage()->writeConfig();
01714 folder->open("ifacefolder");
01715 connectFolder( folder );
01716 return folder;
01717 }
01718
01719 void KMailICalIfaceImpl::connectFolder( KMFolder* folder )
01720 {
01721
01722 disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
01723 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
01724 disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
01725 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
01726 disconnect( folder, SIGNAL( expunged( KMFolder* ) ),
01727 this, SLOT( slotRefreshFolder( KMFolder* ) ) );
01728 disconnect( folder->storage(), SIGNAL( readOnlyChanged( KMFolder* ) ),
01729 this, SLOT( slotFolderPropertiesChanged( KMFolder* ) ) );
01730 disconnect( folder, SIGNAL( nameChanged() ),
01731 this, SLOT( slotFolderRenamed() ) );
01732 disconnect( folder->storage(), SIGNAL( locationChanged( const QString&, const QString&) ),
01733 this, SLOT( slotFolderLocationChanged( const QString&, const QString&) ) );
01734
01735
01736 connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
01737 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
01738 connect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
01739 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
01740 connect( folder, SIGNAL( expunged( KMFolder* ) ),
01741 this, SLOT( slotRefreshFolder( KMFolder* ) ) );
01742 connect( folder->storage(), SIGNAL( readOnlyChanged( KMFolder* ) ),
01743 this, SLOT( slotFolderPropertiesChanged( KMFolder* ) ) );
01744 connect( folder, SIGNAL( nameChanged() ),
01745 this, SLOT( slotFolderRenamed() ) );
01746 connect( folder->storage(), SIGNAL( locationChanged( const QString&, const QString&) ),
01747 this, SLOT( slotFolderLocationChanged( const QString&, const QString&) ) );
01748
01749 }
01750
01751 static void cleanupFolder( KMFolder* folder, KMailICalIfaceImpl* _this )
01752 {
01753 if( folder ) {
01754 folder->setSystemFolder( false );
01755 folder->disconnect( _this );
01756 folder->close("ifacefolder");
01757 }
01758 }
01759
01760 void KMailICalIfaceImpl::cleanup()
01761 {
01762 cleanupFolder( mContacts, this );
01763 cleanupFolder( mCalendar, this );
01764 cleanupFolder( mNotes, this );
01765 cleanupFolder( mTasks, this );
01766 cleanupFolder( mJournals, this );
01767
01768 mContacts = mCalendar = mNotes = mTasks = mJournals = 0;
01769 }
01770
01771 QString KMailICalIfaceImpl::folderPixmap( KFolderTreeItem::Type type ) const
01772 {
01773 if( !mUseResourceIMAP )
01774 return QString::null;
01775
01776 if( type == KFolderTreeItem::Contacts )
01777 return QString::fromLatin1( "kmgroupware_folder_contacts" );
01778 else if( type == KFolderTreeItem::Calendar )
01779 return QString::fromLatin1( "kmgroupware_folder_calendar" );
01780 else if( type == KFolderTreeItem::Notes )
01781 return QString::fromLatin1( "kmgroupware_folder_notes" );
01782 else if( type == KFolderTreeItem::Tasks )
01783 return QString::fromLatin1( "kmgroupware_folder_tasks" );
01784 else if( type == KFolderTreeItem::Journals )
01785 return QString::fromLatin1( "kmgroupware_folder_journals" );
01786
01787 return QString::null;
01788 }
01789
01790 static void reloadFolderTree()
01791 {
01792
01793 kmkernel->folderMgr()->contentsChanged();
01794 }
01795
01796
01797
01798
01799 static void vPartMicroParser( const QString& str, QString& s )
01800 {
01801 QString line;
01802 uint len = str.length();
01803
01804 for( uint i=0; i<len; ++i){
01805 if( str[i] == '\r' || str[i] == '\n' ){
01806 if( str[i] == '\r' )
01807 ++i;
01808 if( i+1 < len && str[i+1] == ' ' ){
01809
01810 ++i;
01811 }else{
01812
01813 if( line.startsWith( s ) ) {
01814 s = line.mid( s.length() + 1 );
01815 return;
01816 }
01817 line = "";
01818 }
01819 } else {
01820 line += str[i];
01821 }
01822 }
01823
01824
01825 s.truncate(0);
01826 }
01827
01828
01829 static KMFolder* findFolderByAnnotation( KMFolderDir* folderParentDir, const QString& annotation )
01830 {
01831 QPtrListIterator<KMFolderNode> it( *folderParentDir );
01832 for ( ; it.current(); ++it ) {
01833 if ( !it.current()->isDir() ) {
01834 KMFolder* folder = static_cast<KMFolder *>( it.current() );
01835 if ( folder->folderType() == KMFolderTypeCachedImap ) {
01836 QString folderAnnotation = static_cast<KMFolderCachedImap*>( folder->storage() )->annotationFolderType();
01837
01838 if ( folderAnnotation == annotation )
01839 return folder;
01840 }
01841 }
01842 }
01843 return 0;
01844 }
01845
01846 KMailICalIfaceImpl::StandardFolderSearchResult KMailICalIfaceImpl::findStandardResourceFolder( KMFolderDir* folderParentDir, KMail::FolderContentsType contentsType )
01847 {
01848 if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML )
01849 {
01850
01851 KMFolder* folder = findFolderByAnnotation( folderParentDir, QString( s_folderContentsType[contentsType].annotation ) + ".default" );
01852 if ( folder )
01853 return StandardFolderSearchResult( folder, StandardFolderSearchResult::FoundAndStandard );
01854
01855
01856 folder = findFolderByAnnotation( folderParentDir, QString( s_folderContentsType[contentsType].annotation ) );
01857 if ( folder )
01858 return StandardFolderSearchResult( folder, StandardFolderSearchResult::FoundByType );
01859
01860
01861 KMFolderNode* node = folderParentDir->hasNamedFolder( localizedDefaultFolderName( contentsType ) );
01862 if ( node && !node->isDir() )
01863 return StandardFolderSearchResult( static_cast<KMFolder *>( node ), StandardFolderSearchResult::FoundByName );
01864
01865 kdDebug(5006) << "findStandardResourceFolder: found no resource folder for " << s_folderContentsType[contentsType].annotation << endl;
01866 return StandardFolderSearchResult( 0, StandardFolderSearchResult::NotFound );
01867 }
01868 else
01869 {
01870 KFolderTreeItem::Type itemType = s_folderContentsType[contentsType].treeItemType;
01871 unsigned int folderLanguage = GlobalSettings::self()->theIMAPResourceFolderLanguage();
01872 if( folderLanguage > 3 ) folderLanguage = 0;
01873 KMFolderNode* node = folderParentDir->hasNamedFolder( folderName( itemType, folderLanguage ) );
01874 if ( !node || node->isDir() )
01875 return StandardFolderSearchResult( 0, StandardFolderSearchResult::NotFound );
01876 return StandardFolderSearchResult( static_cast<KMFolder*>( node ), StandardFolderSearchResult::FoundAndStandard );
01877 }
01878 }
01879
01880
01881
01882
01883
01884 bool KMailICalIfaceImpl::folderIsAlarmRelevant( const KMFolder *folder )
01885 {
01886 bool administerRights = true;
01887 bool relevantForOwner = true;
01888 bool relevantForEveryone = false;
01889 if ( folder->folderType() == KMFolderTypeImap ) {
01890 const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() );
01891 administerRights =
01892 imapFolder->userRights() <= 0 || imapFolder->userRights() & KMail::ACLJobs::Administer;
01893 }
01894 if ( folder->folderType() == KMFolderTypeCachedImap ) {
01895 const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() );
01896 administerRights =
01897 dimapFolder->userRights() <= 0 || dimapFolder->userRights() & KMail::ACLJobs::Administer;
01898 relevantForOwner = dimapFolder->incidencesFor () == KMFolderCachedImap::IncForAdmins;
01899 relevantForEveryone = ( dimapFolder->incidencesFor() == KMFolderCachedImap::IncForReaders );
01900 }
01901 #if 0
01902 kdDebug(5006) << k_funcinfo << endl;
01903 kdDebug(5006) << "Folder: " << folder->label() << " has administer rights: " << administerRights << endl;
01904 kdDebug(5006) << "and is relevant for owner: " << relevantForOwner << endl;
01905 kdDebug(5006) << "and relevant for everyone: " << relevantForEveryone << endl;
01906 #endif
01907 return ( administerRights && relevantForOwner ) || relevantForEveryone;
01908 }
01909
01910 void KMailICalIfaceImpl::setResourceQuiet(bool q)
01911 {
01912 mResourceQuiet = q;
01913 }
01914
01915 bool KMailICalIfaceImpl::isResourceQuiet() const
01916 {
01917 return mResourceQuiet;
01918 }
01919
01920 #include "kmailicalifaceimpl.moc"