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