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