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