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
01305 folderNames[2][KFolderTreeItem::Tasks] = QString::fromLatin1("T\342ches");
01306 folderNames[2][KFolderTreeItem::Journals] = QString::fromLatin1("Journal");
01307 folderNames[2][KFolderTreeItem::Contacts] = QString::fromLatin1("Contacts");
01308 folderNames[2][KFolderTreeItem::Notes] = QString::fromLatin1("Notes");
01309
01310
01311 folderNames[3][KFolderTreeItem::Calendar] = QString::fromLatin1("Agenda");
01312 folderNames[3][KFolderTreeItem::Tasks] = QString::fromLatin1("Taken");
01313 folderNames[3][KFolderTreeItem::Journals] = QString::fromLatin1("Logboek");
01314 folderNames[3][KFolderTreeItem::Contacts] = QString::fromLatin1("Contactpersonen");
01315 folderNames[3][KFolderTreeItem::Notes] = QString::fromLatin1("Notities");
01316 }
01317
01318 if( language < 0 || language > 3 ) {
01319 return folderNames[mFolderLanguage][type];
01320 }
01321 else {
01322 return folderNames[language][type];
01323 }
01324 }
01325
01326
01327
01328 KMMessage *KMailICalIfaceImpl::findMessageByUID( const QString& uid, KMFolder* folder )
01329 {
01330 if( !folder || !mUIDToSerNum.contains( uid ) ) return 0;
01331 int i;
01332 KMFolder *aFolder;
01333 KMMsgDict::instance()->getLocation( mUIDToSerNum[uid], &aFolder, &i );
01334 Q_ASSERT( aFolder == folder );
01335 return folder->getMsg( i );
01336 }
01337
01338
01339 KMMessage *KMailICalIfaceImpl::findMessageBySerNum( Q_UINT32 serNum, KMFolder* folder )
01340 {
01341 if( !folder ) return 0;
01342
01343 KMMessage *message = 0;
01344 KMFolder* aFolder = 0;
01345 int index;
01346 KMMsgDict::instance()->getLocation( serNum, &aFolder, &index );
01347
01348 if( aFolder && aFolder != folder ) {
01349 kdWarning(5006) << "findMessageBySerNum( " << serNum << " ) found it in folder " << aFolder->location() << ", expected " << folder->location() << endl;
01350 } else {
01351 if( aFolder )
01352 message = aFolder->getMsg( index );
01353 if (!message)
01354 kdWarning(5006) << "findMessageBySerNum( " << serNum << " ) invalid serial number\n" << endl;
01355 }
01356 return message;
01357 }
01358
01359 void KMailICalIfaceImpl::deleteMsg( KMMessage *msg )
01360 {
01361 if( !msg ) return;
01362
01363
01364 KMFolder *srcFolder = msg->parent();
01365 int idx = srcFolder->find(msg);
01366 assert(idx != -1);
01367
01368 srcFolder->ignoreJobsForMessage( msg );
01369 if ( !msg->transferInProgress() ) {
01370 srcFolder->removeMsg(idx);
01371 delete msg;
01372 } else {
01373 kdDebug(5006) << k_funcinfo << "Message cannot be deleted now because it is currently in use " << msg << endl;
01374 msg->deleteWhenUnused();
01375 }
01376 addFolderChange( srcFolder, Contents );
01377 }
01378
01379 void KMailICalIfaceImpl::folderContentsTypeChanged( KMFolder* folder,
01380 KMail::FolderContentsType contentsType )
01381 {
01382 if ( !mUseResourceIMAP )
01383 return;
01384
01385
01386
01387
01388 if ( isStandardResourceFolder( folder ) )
01389 return;
01390
01391
01392 const QString location = folder->location();
01393 ExtraFolder* ef = mExtraFolders.find( location );
01394 if ( ef && ef->folder ) {
01395
01396 subresourceDeleted(folderContentsType( folder->storage()->contentsType() ), location );
01397
01398 if ( contentsType == KMail::ContentsTypeMail ) {
01399
01400 mExtraFolders.remove( location );
01401 folder->disconnect( this );
01402 return;
01403 }
01404
01405 } else {
01406 if ( ef && !ef->folder )
01407 mExtraFolders.remove( location );
01408 if ( contentsType == KMail::ContentsTypeMail )
01409 return;
01410
01411
01412
01413 ef = new ExtraFolder( folder );
01414 mExtraFolders.insert( location, ef );
01415
01416 FolderInfo info = readFolderInfo( folder );
01417 mFolderInfoMap.insert( folder, info );
01418
01419
01420
01421
01422
01423
01424 if ( folder->folderType() == KMFolderTypeCachedImap ) {
01425 QString annotation = static_cast<KMFolderCachedImap*>( folder->storage() )->annotationFolderType();
01426 kdDebug(5006) << "folderContentsTypeChanged: " << folder->name() << " has annotation " << annotation << endl;
01427 if ( annotation == QString( s_folderContentsType[contentsType].annotation ) + ".default" )
01428 folder->setLabel( localizedDefaultFolderName( contentsType ) );
01429 }
01430
01431 connectFolder( folder );
01432 }
01433
01434 subresourceAdded( folderContentsType( contentsType ), location, subresourceLabelForPresentation(folder),
01435 !folder->isReadOnly(), folderIsAlarmRelevant( folder ) );
01436 }
01437
01438 KMFolder* KMailICalIfaceImpl::extraFolder( const QString& type,
01439 const QString& folder )
01440 {
01441
01442
01443 int t = folderContentsType( type );
01444 if ( t < 1 || t > 5 )
01445 return 0;
01446
01447 ExtraFolder* ef = mExtraFolders.find( folder );
01448 if ( ef && ef->folder && ef->folder->storage()->contentsType() == t )
01449 return ef->folder;
01450
01451 return 0;
01452 }
01453
01454 KMailICalIfaceImpl::StorageFormat KMailICalIfaceImpl::storageFormat( KMFolder* folder ) const
01455 {
01456 FolderInfoMap::ConstIterator it = mFolderInfoMap.find( folder );
01457 if ( it != mFolderInfoMap.end() )
01458 return (*it).mStorageFormat;
01459 return globalStorageFormat();
01460 }
01461
01462 void KMailICalIfaceImpl::setStorageFormat( KMFolder* folder, StorageFormat format )
01463 {
01464 FolderInfoMap::Iterator it = mFolderInfoMap.find( folder );
01465 if ( it != mFolderInfoMap.end() ) {
01466 (*it).mStorageFormat = format;
01467 } else {
01468 FolderInfo info( format, NoChange );
01469 mFolderInfoMap.insert( folder, info );
01470 }
01471 KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" );
01472 configGroup.writeEntry( folder->idString() + "-storageFormat",
01473 format == StorageXML ? "xml" : "icalvcard" );
01474 }
01475
01476 void KMailICalIfaceImpl::addFolderChange( KMFolder* folder, FolderChanges changes )
01477 {
01478 FolderInfoMap::Iterator it = mFolderInfoMap.find( folder );
01479 if ( it != mFolderInfoMap.end() ) {
01480 (*it).mChanges = static_cast<FolderChanges>( (*it).mChanges | changes );
01481 } else {
01482 kdDebug(5006) << "addFolderChange: nothing known about folder " << folder->location() << endl;
01483 }
01484 KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" );
01485 configGroup.writeEntry( folder->idString() + "-changes", (*it).mChanges );
01486 }
01487
01488 KMailICalIfaceImpl::FolderInfo KMailICalIfaceImpl::readFolderInfo( const KMFolder * const folder ) const
01489 {
01490 KConfigGroup configGroup( kmkernel->config(), "GroupwareFolderInfo" );
01491 QString str = configGroup.readEntry( folder->idString() + "-storageFormat", "unset" );
01492 FolderInfo info;
01493 if ( str == "unset" ) {
01494 info.mStorageFormat = globalStorageFormat();
01495 configGroup.writeEntry( folder->idString() + "-storageFormat",
01496 info.mStorageFormat == StorageXML ? "xml" : "icalvcard" );
01497 } else {
01498 info.mStorageFormat = ( str == "xml" ) ? StorageXML : StorageIcalVcard;
01499 }
01500 info.mChanges = (FolderChanges) configGroup.readNumEntry( folder->idString() + "-changes" );
01501 return info;
01502 }
01503
01504
01505 void KMailICalIfaceImpl::folderSynced( KMFolder* folder, const KURL& folderURL )
01506 {
01507 FolderInfoMap::Iterator it = mFolderInfoMap.find( folder );
01508 if ( it != mFolderInfoMap.end() && (*it).mChanges ) {
01509 handleFolderSynced( folder, folderURL, (*it).mChanges );
01510 (*it).mChanges = NoChange;
01511 }
01512 }
01513
01514 void KMailICalIfaceImpl::handleFolderSynced( KMFolder* folder,
01515 const KURL& folderURL,
01516 int _changes )
01517 {
01518
01519
01520
01521
01522 if ( ( _changes & KMailICalIface::Contents ) ||
01523 ( _changes & KMailICalIface::ACL ) ) {
01524 if ( storageFormat( folder ) == StorageXML && folder->storage()->contentsType() == KMail::ContentsTypeCalendar )
01525 triggerKolabFreeBusy( folderURL );
01526 }
01527 }
01528
01529 void KMailICalIfaceImpl::folderDeletedOnServer( const KURL& folderURL )
01530 {
01531 triggerKolabFreeBusy( folderURL );
01532 }
01533
01534 void KMailICalIfaceImpl::triggerKolabFreeBusy( const KURL& folderURL )
01535 {
01536
01537
01538
01539 KURL httpURL( folderURL );
01540
01541 httpURL.setProtocol( "https" );
01542 httpURL.setPort( 0 );
01543
01544
01545 QString path = folderURL.path( -1 );
01546 Q_ASSERT( path.startsWith( "/" ) );
01547 int secondSlash = path.find( '/', 1 );
01548 if ( secondSlash == -1 ) {
01549 kdWarning() << "KCal::ResourceKolab::fromKMailFolderSynced path is too short: " << path << endl;
01550 return;
01551 }
01552 if ( path.startsWith( "/INBOX/", false ) ) {
01553
01554 path = path.mid( secondSlash );
01555 path.prepend( folderURL.user() );
01556 } else {
01557
01558
01559 path = path.mid( secondSlash );
01560 }
01561
01562 httpURL.setPath( "/freebusy/trigger/" + path + ".pfb" );
01563 httpURL.setQuery( QString::null );
01564
01565 httpURL = KURL( httpURL.url(0,106), 106 );
01566 kdDebug() << "Triggering PFB update for " << folderURL << " : getting " << httpURL << endl;
01567
01568
01569 KIO::get( httpURL, false, false );
01570 }
01571
01572 void KMailICalIfaceImpl::slotFolderPropertiesChanged( KMFolder* folder )
01573 {
01574 if ( isResourceFolder( folder ) ) {
01575 const QString location = folder->location();
01576 const QString contentsTypeStr = folderContentsType( folder->storage()->contentsType() );
01577 subresourceDeleted( contentsTypeStr, location );
01578
01579 subresourceAdded( contentsTypeStr, location, subresourceLabelForPresentation( folder ),
01580 !folder->isReadOnly(), folderIsAlarmRelevant( folder ) );
01581
01582 }
01583 }
01584
01585
01586 void KMailICalIfaceImpl::slotFolderRenamed()
01587 {
01588 const KMFolder* folder = static_cast<const KMFolder *>( sender() );
01589 slotFolderPropertiesChanged( const_cast<KMFolder*>( folder ) );
01590 }
01591
01592 void KMailICalIfaceImpl::slotFolderLocationChanged( const QString &oldLocation,
01593 const QString &newLocation )
01594 {
01595 KMFolder *folder = findResourceFolder( oldLocation );
01596 ExtraFolder* ef = mExtraFolders.find( oldLocation );
01597 if ( ef ) {
01598
01599 mExtraFolders.setAutoDelete( false );
01600 mExtraFolders.remove( oldLocation );
01601 mExtraFolders.setAutoDelete( true );
01602 mExtraFolders.insert( newLocation, ef );
01603 }
01604 if ( folder )
01605 subresourceDeleted( folderContentsType( folder->storage()->contentsType() ), oldLocation );
01606
01607 }
01608
01609 KMFolder* KMailICalIfaceImpl::findResourceFolder( const QString& resource )
01610 {
01611
01612 if( mCalendar && mCalendar->location() == resource )
01613 return mCalendar;
01614 if ( mContacts && mContacts->location() == resource )
01615 return mContacts;
01616 if ( mNotes && mNotes->location() == resource )
01617 return mNotes;
01618 if ( mTasks && mTasks->location() == resource )
01619 return mTasks;
01620 if ( mJournals && mJournals->location() == resource )
01621 return mJournals;
01622
01623
01624 ExtraFolder* ef = mExtraFolders.find( resource );
01625 if ( ef )
01626 return ef->folder;
01627
01628
01629 return 0;
01630 }
01631
01632
01633
01634
01635
01636 void KMailICalIfaceImpl::readConfig()
01637 {
01638 bool enabled = GlobalSettings::self()->theIMAPResourceEnabled() &&
01639 ( GlobalSettings::self()->theIMAPResourceAccount() != 0 );
01640
01641 if( !enabled ) {
01642 if( mUseResourceIMAP == true ) {
01643
01644 mUseResourceIMAP = false;
01645 cleanup();
01646 reloadFolderTree();
01647 }
01648 return;
01649 }
01650 mUseResourceIMAP = enabled;
01651
01652
01653 const bool hideFolders = GlobalSettings::self()->hideGroupwareFolders();
01654 QString parentName = GlobalSettings::self()->theIMAPResourceFolderParent();
01655
01656
01657 KMFolderDir* folderParentDir;
01658 KMFolderType folderType;
01659 KMFolder* folderParent = kmkernel->findFolderById( parentName );
01660 if( folderParent == 0 ) {
01661
01662
01663 kdDebug(5006) << "Groupware folder " << parentName << " not found. Groupware functionality disabled" << endl;
01664
01665 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::self()->theIMAPResourceAccount() );
01666 Q_ASSERT( account );
01667 if ( account ) {
01668
01669 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01670 this, SLOT( slotCheckDone() ) );
01671 connect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01672 this, SLOT( slotCheckDone() ) );
01673 }
01674 mUseResourceIMAP = false;
01675
01676 mCalendar = 0;
01677 mTasks = 0;
01678 mJournals = 0;
01679 mContacts = 0;
01680 mNotes = 0;
01681 return;
01682 } else {
01683 folderParentDir = folderParent->createChildFolder();
01684 folderType = folderParent->folderType();
01685 }
01686
01687 KMAcctCachedImap::GroupwareType groupwareType = dynamic_cast<KMFolderCachedImap *>( folderParent->storage() )->account()->groupwareType();
01688
01689 if ( groupwareType == KMAcctCachedImap::GroupwareKolab ) {
01690
01691
01692 bool noneFound = true;
01693 bool mustFix = false;
01694 QValueVector<StandardFolderSearchResult> results( KMail::ContentsTypeLast + 1 );
01695 for ( int i = 0; i < KMail::ContentsTypeLast+1; ++i ) {
01696 if ( i != KMail::ContentsTypeMail ) {
01697 results[i] = findStandardResourceFolder( folderParentDir, static_cast<KMail::FolderContentsType>(i) );
01698 if ( results[i].found == StandardFolderSearchResult::FoundAndStandard )
01699 noneFound = false;
01700 else if ( results[i].found == StandardFolderSearchResult::FoundByType ||
01701 results[i].found == StandardFolderSearchResult::FoundByName ) {
01702 mustFix = true;
01703 noneFound = false;
01704 } else
01705 mustFix = true;
01706 }
01707 }
01708
01709
01710 if( mUseResourceIMAP && !noneFound && !mustFix && mFolderParentDir == folderParentDir
01711 && mFolderType == folderType ) {
01712
01713 if ( hideFolders != mHideFolders ) {
01714
01715 mHideFolders = hideFolders;
01716 reloadFolderTree();
01717 }
01718 return;
01719 }
01720
01721 if( noneFound || mustFix ) {
01722 QString msg;
01723 QString parentFolderName = folderParent != 0 ? folderParent->name() : folderParentDir->name();
01724 if ( noneFound ) {
01725
01726 msg = i18n("KMail will now create the required groupware folders"
01727 " as subfolders of %1; if you do not want this, cancel"
01728 " and the IMAP resource will be disabled").arg(parentFolderName);
01729 } else {
01730
01731 QString operations = "<ul>";
01732 for ( int i = 0; i < KMail::ContentsTypeLast+1; ++i ) {
01733 if ( i != KMail::ContentsTypeMail ) {
01734 QString typeName = localizedDefaultFolderName( static_cast<KMail::FolderContentsType>( i ) );
01735 if ( results[i].found == StandardFolderSearchResult::NotFound )
01736 operations += "<li>" + i18n( "%1: no folder found. It will be created." ).arg( typeName ) + "</li>";
01737 else if ( results[i].found == StandardFolderSearchResult::FoundByType || results[i].found == StandardFolderSearchResult::FoundByName )
01738 operations += "<li>" + i18n( "%1: found folder %2. It will be set as the main groupware folder." ).
01739 arg( typeName ).arg( results[i].folder->label() ) + "</li>";
01740 }
01741 }
01742 operations += "</ul>";
01743
01744 msg = i18n("<qt>KMail found the following groupware folders in %1 and needs to perform the following operations: %2"
01745 "<br>If you do not want this, cancel"
01746 " and the IMAP resource will be disabled").arg(parentFolderName, operations);
01747
01748 }
01749
01750 if( KMessageBox::questionYesNo( 0, msg,
01751 i18n("Standard Groupware Folders"), KStdGuiItem::cont(), KStdGuiItem::cancel() ) == KMessageBox::No ) {
01752
01753 GlobalSettings::self()->setTheIMAPResourceEnabled( false );
01754 mUseResourceIMAP = false;
01755 mFolderParentDir = 0;
01756 mFolderParent = 0;
01757 reloadFolderTree();
01758 return;
01759 }
01760 }
01761
01762
01763 mUseResourceIMAP = true;
01764 mFolderLanguage = GlobalSettings::self()->theIMAPResourceFolderLanguage();
01765 if( mFolderLanguage > 3 ) mFolderLanguage = 0;
01766 mFolderParentDir = folderParentDir;
01767 mFolderParent = folderParent;
01768 mFolderType = folderType;
01769 mHideFolders = hideFolders;
01770
01771
01772 cleanup();
01773
01774
01775 mCalendar = initFolder( KMail::ContentsTypeCalendar );
01776 mTasks = initFolder( KMail::ContentsTypeTask );
01777 mJournals = initFolder( KMail::ContentsTypeJournal );
01778 mContacts = initFolder( KMail::ContentsTypeContact );
01779 mNotes = initFolder( KMail::ContentsTypeNote );
01780
01781
01782 if ( mCalendar->folderType() == KMFolderTypeCachedImap )
01783 static_cast<KMFolderCachedImap *>( mCalendar->storage() )->updateAnnotationFolderType();
01784 if ( mTasks->folderType() == KMFolderTypeCachedImap )
01785 static_cast<KMFolderCachedImap *>( mTasks->storage() )->updateAnnotationFolderType();
01786 if ( mJournals->folderType() == KMFolderTypeCachedImap )
01787 static_cast<KMFolderCachedImap *>( mJournals->storage() )->updateAnnotationFolderType();
01788 if ( mContacts->folderType() == KMFolderTypeCachedImap )
01789 static_cast<KMFolderCachedImap *>( mContacts->storage() )->updateAnnotationFolderType();
01790 if ( mNotes->folderType() == KMFolderTypeCachedImap )
01791 static_cast<KMFolderCachedImap *>( mNotes->storage() )->updateAnnotationFolderType();
01792
01793
01794
01795
01796 kdDebug(5006) << k_funcinfo << "mCalendar=" << mCalendar << " " << mCalendar->location() << endl;
01797 kdDebug(5006) << k_funcinfo << "mContacts=" << mContacts << " " << mContacts->location() << endl;
01798 kdDebug(5006) << k_funcinfo << "mNotes=" << mNotes << " " << mNotes->location() << endl;
01799
01800
01801 QStringList folderNames;
01802 QValueList<QGuardedPtr<KMFolder> > folderList;
01803 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
01804 for(QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin();
01805 it != folderList.end(); ++it)
01806 {
01807 FolderStorage* storage = (*it)->storage();
01808 if ( storage->contentsType() != 0 ) {
01809 folderContentsTypeChanged( *it, storage->contentsType() );
01810 }
01811 }
01812
01813
01814
01815 mExtraFolders.remove( mCalendar->location() );
01816 mExtraFolders.remove( mTasks->location() );
01817 mExtraFolders.remove( mJournals->location() );
01818 mExtraFolders.remove( mContacts->location() );
01819 mExtraFolders.remove( mNotes->location() );
01820
01821
01822
01823 subresourceAdded( folderContentsType( KMail::ContentsTypeCalendar ), mCalendar->location(), mCalendar->label(), true, true );
01824 subresourceAdded( folderContentsType( KMail::ContentsTypeTask ), mTasks->location(), mTasks->label(), true, true );
01825 subresourceAdded( folderContentsType( KMail::ContentsTypeJournal ), mJournals->location(), mJournals->label(), true, false );
01826 subresourceAdded( folderContentsType( KMail::ContentsTypeContact ), mContacts->location(), mContacts->label(), true, false );
01827 subresourceAdded( folderContentsType( KMail::ContentsTypeNote ), mNotes->location(), mNotes->label(), true, false );
01828 } else if ( groupwareType == KMAcctCachedImap::GroupwareScalix ) {
01829
01830 mUseResourceIMAP = true;
01831 mFolderParentDir = folderParentDir;
01832 mFolderParent = folderParent;
01833 mFolderType = folderType;
01834 mHideFolders = false;
01835
01836
01837 cleanup();
01838
01839
01840 mCalendar = initScalixFolder( KMail::ContentsTypeCalendar );
01841 mTasks = initScalixFolder( KMail::ContentsTypeTask );
01842 mJournals = 0;
01843 mContacts = initScalixFolder( KMail::ContentsTypeContact );
01844 mNotes = initScalixFolder( KMail::ContentsTypeNote );
01845
01846
01847 if ( mCalendar->folderType() == KMFolderTypeCachedImap )
01848 static_cast<KMFolderCachedImap *>( mCalendar->storage() )->updateAnnotationFolderType();
01849 if ( mTasks->folderType() == KMFolderTypeCachedImap )
01850 static_cast<KMFolderCachedImap *>( mTasks->storage() )->updateAnnotationFolderType();
01851 if ( mContacts->folderType() == KMFolderTypeCachedImap )
01852 static_cast<KMFolderCachedImap *>( mContacts->storage() )->updateAnnotationFolderType();
01853 if ( mNotes->folderType() == KMFolderTypeCachedImap )
01854 static_cast<KMFolderCachedImap *>( mNotes->storage() )->updateAnnotationFolderType();
01855
01856
01857
01858
01859 kdDebug(5006) << k_funcinfo << "mCalendar=" << mCalendar << " " << mCalendar->location() << endl;
01860 kdDebug(5006) << k_funcinfo << "mContacts=" << mContacts << " " << mContacts->location() << endl;
01861 kdDebug(5006) << k_funcinfo << "mNotes=" << mNotes << " " << mNotes->location() << endl;
01862
01863
01864 QStringList folderNames;
01865 QValueList<QGuardedPtr<KMFolder> > folderList;
01866 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
01867 QValueList<QGuardedPtr<KMFolder> >::iterator it;
01868 for(it = folderList.begin(); it != folderList.end(); ++it)
01869 {
01870 FolderStorage *storage = (*it)->storage();
01871
01872 if ( (*it)->folderType() == KMFolderTypeCachedImap ) {
01873 KMFolderCachedImap *imapFolder = static_cast<KMFolderCachedImap*>( storage );
01874
01875 const QString attributes = imapFolder->folderAttributes();
01876 if ( attributes.contains( "X-FolderClass" ) ) {
01877 if ( !attributes.contains( "X-SpecialFolder" ) || (*it)->location().contains( "@" ) ) {
01878 const Scalix::FolderAttributeParser parser( attributes );
01879 if ( !parser.folderClass().isEmpty() ) {
01880 FolderContentsType type = Scalix::Utils::scalixIdToContentsType( parser.folderClass() );
01881 imapFolder->setContentsType( type );
01882 folderContentsTypeChanged( *it, type );
01883 }
01884 }
01885 }
01886 }
01887 }
01888
01889
01890
01891 mExtraFolders.remove( mCalendar->location() );
01892 mExtraFolders.remove( mTasks->location() );
01893 mExtraFolders.remove( mContacts->location() );
01894 mExtraFolders.remove( mNotes->location() );
01895
01896
01897
01898 subresourceAdded( folderContentsType( KMail::ContentsTypeCalendar ), mCalendar->location(), mCalendar->label(), true, true );
01899 subresourceAdded( folderContentsType( KMail::ContentsTypeTask ), mTasks->location(), mTasks->label(), true, true );
01900 subresourceAdded( folderContentsType( KMail::ContentsTypeContact ), mContacts->location(), mContacts->label(), true, false );
01901 subresourceAdded( folderContentsType( KMail::ContentsTypeNote ), mNotes->location(), mNotes->label(), true, false );
01902 }
01903
01904 reloadFolderTree();
01905 }
01906
01907 void KMailICalIfaceImpl::slotCheckDone()
01908 {
01909 QString parentName = GlobalSettings::self()->theIMAPResourceFolderParent();
01910 KMFolder* folderParent = kmkernel->findFolderById( parentName );
01911
01912 if ( folderParent )
01913 {
01914 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::self()->theIMAPResourceAccount() );
01915 if ( account )
01916 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01917 this, SLOT( slotCheckDone() ) );
01918 readConfig();
01919 }
01920 }
01921
01922 KMFolder* KMailICalIfaceImpl::initFolder( KMail::FolderContentsType contentsType )
01923 {
01924
01925 KMFolderType type = mFolderType;
01926 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
01927
01928 KFolderTreeItem::Type itemType = s_folderContentsType[contentsType].treeItemType;
01929
01930
01931
01932 StandardFolderSearchResult result = findStandardResourceFolder( mFolderParentDir, contentsType );
01933 KMFolder* folder = result.folder;
01934
01935 if ( !folder ) {
01936
01937 folder =
01938 mFolderParentDir->createFolder( localizedDefaultFolderName( contentsType ), false, type );
01939 if( mFolderType == KMFolderTypeImap ) {
01940 KMFolderImap* parentFolder = static_cast<KMFolderImap*>( mFolderParent->storage() );
01941 parentFolder->createFolder( localizedDefaultFolderName( contentsType ) );
01942 static_cast<KMFolderImap*>( folder->storage() )->setAccount( parentFolder->account() );
01943 }
01944
01945 setStorageFormat( folder, globalStorageFormat() );
01946 } else {
01947 FolderInfo info = readFolderInfo( folder );
01948 mFolderInfoMap.insert( folder, info );
01949
01950 }
01951
01952 if( folder->canAccess() != 0 ) {
01953 KMessageBox::sorry(0, i18n("You do not have read/write permission to your %1 folder.")
01954 .arg( folderName( itemType ) ) );
01955 return 0;
01956 }
01957 folder->storage()->setContentsType( contentsType );
01958 folder->setSystemFolder( true );
01959 folder->storage()->writeConfig();
01960 folder->open("ifacefolder");
01961 connectFolder( folder );
01962 return folder;
01963 }
01964
01965 KMFolder* KMailICalIfaceImpl::initScalixFolder( KMail::FolderContentsType contentsType )
01966 {
01967
01968 KMFolderType type = mFolderType;
01969 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
01970
01971 KMFolder* folder = 0;
01972
01973
01974 QStringList folderNames;
01975 QValueList<QGuardedPtr<KMFolder> > folderList;
01976 Q_ASSERT( kmkernel );
01977 Q_ASSERT( kmkernel->dimapFolderMgr() );
01978 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
01979 QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin();
01980 for(; it != folderList.end(); ++it)
01981 {
01982 FolderStorage *storage = (*it)->storage();
01983
01984 if ( (*it)->folderType() == KMFolderTypeCachedImap ) {
01985 KMFolderCachedImap *imapFolder = static_cast<KMFolderCachedImap*>( storage );
01986
01987 const QString attributes = imapFolder->folderAttributes();
01988 if ( attributes.contains( "X-SpecialFolder" ) ) {
01989 const Scalix::FolderAttributeParser parser( attributes );
01990 if ( contentsType == Scalix::Utils::scalixIdToContentsType( parser.folderClass() ) ) {
01991 folder = *it;
01992 break;
01993 }
01994 }
01995 }
01996 }
01997
01998 if ( !folder ) {
01999 return 0;
02000 } else {
02001 FolderInfo info = readFolderInfo( folder );
02002 mFolderInfoMap.insert( folder, info );
02003
02004 }
02005
02006 if( folder->canAccess() != 0 ) {
02007 KMessageBox::sorry(0, i18n("You do not have read/write permission to your folder.") );
02008 return 0;
02009 }
02010 folder->storage()->setContentsType( contentsType );
02011 folder->setSystemFolder( true );
02012 folder->storage()->writeConfig();
02013 folder->open( "scalixfolder" );
02014 connectFolder( folder );
02015 return folder;
02016 }
02017
02018 void KMailICalIfaceImpl::connectFolder( KMFolder* folder )
02019 {
02020
02021 disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
02022 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
02023 disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
02024 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
02025 disconnect( folder, SIGNAL( expunged( KMFolder* ) ),
02026 this, SLOT( slotRefreshFolder( KMFolder* ) ) );
02027 disconnect( folder->storage(), SIGNAL( readOnlyChanged( KMFolder* ) ),
02028 this, SLOT( slotFolderPropertiesChanged( KMFolder* ) ) );
02029 disconnect( folder, SIGNAL( nameChanged() ),
02030 this, SLOT( slotFolderRenamed() ) );
02031 disconnect( folder->storage(), SIGNAL( locationChanged( const QString&, const QString&) ),
02032 this, SLOT( slotFolderLocationChanged( const QString&, const QString&) ) );
02033
02034
02035 connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
02036 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
02037 connect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
02038 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
02039 connect( folder, SIGNAL( expunged( KMFolder* ) ),
02040 this, SLOT( slotRefreshFolder( KMFolder* ) ) );
02041 connect( folder->storage(), SIGNAL( readOnlyChanged( KMFolder* ) ),
02042 this, SLOT( slotFolderPropertiesChanged( KMFolder* ) ) );
02043 connect( folder, SIGNAL( nameChanged() ),
02044 this, SLOT( slotFolderRenamed() ) );
02045 connect( folder->storage(), SIGNAL( locationChanged( const QString&, const QString&) ),
02046 this, SLOT( slotFolderLocationChanged( const QString&, const QString&) ) );
02047
02048 }
02049
02050 static void cleanupFolder( KMFolder* folder, KMailICalIfaceImpl* _this )
02051 {
02052 if( folder ) {
02053 folder->setSystemFolder( false );
02054 folder->disconnect( _this );
02055 folder->close("ifacefolder");
02056 }
02057 }
02058
02059 void KMailICalIfaceImpl::cleanup()
02060 {
02061 cleanupFolder( mContacts, this );
02062 cleanupFolder( mCalendar, this );
02063 cleanupFolder( mNotes, this );
02064 cleanupFolder( mTasks, this );
02065 cleanupFolder( mJournals, this );
02066
02067 mContacts = mCalendar = mNotes = mTasks = mJournals = 0;
02068 }
02069
02070 QString KMailICalIfaceImpl::folderPixmap( KFolderTreeItem::Type type ) const
02071 {
02072 if( !mUseResourceIMAP )
02073 return QString::null;
02074
02075 if( type == KFolderTreeItem::Contacts )
02076 return QString::fromLatin1( "kmgroupware_folder_contacts" );
02077 else if( type == KFolderTreeItem::Calendar )
02078 return QString::fromLatin1( "kmgroupware_folder_calendar" );
02079 else if( type == KFolderTreeItem::Notes )
02080 return QString::fromLatin1( "kmgroupware_folder_notes" );
02081 else if( type == KFolderTreeItem::Tasks )
02082 return QString::fromLatin1( "kmgroupware_folder_tasks" );
02083 else if( type == KFolderTreeItem::Journals )
02084 return QString::fromLatin1( "kmgroupware_folder_journals" );
02085
02086 return QString::null;
02087 }
02088
02089 static void reloadFolderTree()
02090 {
02091
02092 kmkernel->folderMgr()->contentsChanged();
02093 }
02094
02095
02096
02097
02098 static void vPartMicroParser( const QString& str, QString& s )
02099 {
02100 QString line;
02101 uint len = str.length();
02102
02103 for( uint i=0; i<len; ++i){
02104 if( str[i] == '\r' || str[i] == '\n' ){
02105 if( str[i] == '\r' )
02106 ++i;
02107 if( i+1 < len && str[i+1] == ' ' ){
02108
02109 ++i;
02110 }else{
02111
02112 if( line.startsWith( s ) ) {
02113 s = line.mid( s.length() + 1 );
02114 return;
02115 }
02116 line = "";
02117 }
02118 } else {
02119 line += str[i];
02120 }
02121 }
02122
02123
02124 s.truncate(0);
02125 }
02126
02127
02128 static KMFolder* findFolderByAnnotation( KMFolderDir* folderParentDir, const QString& annotation )
02129 {
02130 QPtrListIterator<KMFolderNode> it( *folderParentDir );
02131 for ( ; it.current(); ++it ) {
02132 if ( !it.current()->isDir() ) {
02133 KMFolder* folder = static_cast<KMFolder *>( it.current() );
02134 if ( folder->folderType() == KMFolderTypeCachedImap ) {
02135 QString folderAnnotation = static_cast<KMFolderCachedImap*>( folder->storage() )->annotationFolderType();
02136
02137 if ( folderAnnotation == annotation )
02138 return folder;
02139 }
02140 }
02141 }
02142 return 0;
02143 }
02144
02145 KMailICalIfaceImpl::StandardFolderSearchResult KMailICalIfaceImpl::findStandardResourceFolder( KMFolderDir* folderParentDir, KMail::FolderContentsType contentsType )
02146 {
02147 if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML )
02148 {
02149
02150 KMFolder* folder = findFolderByAnnotation( folderParentDir, QString( s_folderContentsType[contentsType].annotation ) + ".default" );
02151 if ( folder )
02152 return StandardFolderSearchResult( folder, StandardFolderSearchResult::FoundAndStandard );
02153
02154
02155 folder = findFolderByAnnotation( folderParentDir, QString( s_folderContentsType[contentsType].annotation ) );
02156 if ( folder )
02157 return StandardFolderSearchResult( folder, StandardFolderSearchResult::FoundByType );
02158
02159
02160 KMFolderNode* node = folderParentDir->hasNamedFolder( localizedDefaultFolderName( contentsType ) );
02161 if ( node && !node->isDir() )
02162 return StandardFolderSearchResult( static_cast<KMFolder *>( node ), StandardFolderSearchResult::FoundByName );
02163
02164 kdDebug(5006) << "findStandardResourceFolder: found no resource folder for " << s_folderContentsType[contentsType].annotation << endl;
02165 return StandardFolderSearchResult( 0, StandardFolderSearchResult::NotFound );
02166 }
02167 else
02168 {
02169 KFolderTreeItem::Type itemType = s_folderContentsType[contentsType].treeItemType;
02170 unsigned int folderLanguage = GlobalSettings::self()->theIMAPResourceFolderLanguage();
02171 if( folderLanguage > 3 ) folderLanguage = 0;
02172 KMFolderNode* node = folderParentDir->hasNamedFolder( folderName( itemType, folderLanguage ) );
02173 if ( !node || node->isDir() )
02174 return StandardFolderSearchResult( 0, StandardFolderSearchResult::NotFound );
02175 return StandardFolderSearchResult( static_cast<KMFolder*>( node ), StandardFolderSearchResult::FoundAndStandard );
02176 }
02177 }
02178
02179
02180
02181
02182
02183 bool KMailICalIfaceImpl::folderIsAlarmRelevant( const KMFolder *folder )
02184 {
02185 bool administerRights = true;
02186 bool relevantForOwner = true;
02187 bool relevantForEveryone = false;
02188 if ( folder->folderType() == KMFolderTypeImap ) {
02189 const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() );
02190 administerRights =
02191 imapFolder->userRights() <= 0 || imapFolder->userRights() & KMail::ACLJobs::Administer;
02192 }
02193 if ( folder->folderType() == KMFolderTypeCachedImap ) {
02194 const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() );
02195 administerRights =
02196 dimapFolder->userRights() <= 0 || dimapFolder->userRights() & KMail::ACLJobs::Administer;
02197 relevantForOwner = !dimapFolder->alarmsBlocked() && ( dimapFolder->incidencesFor () == KMFolderCachedImap::IncForAdmins );
02198 relevantForEveryone = !dimapFolder->alarmsBlocked() && ( dimapFolder->incidencesFor() == KMFolderCachedImap::IncForReaders );
02199 }
02200 #if 0
02201 kdDebug(5006) << k_funcinfo << endl;
02202 kdDebug(5006) << "Folder: " << folder->label() << " has administer rights: " << administerRights << endl;
02203 kdDebug(5006) << "and is relevant for owner: " << relevantForOwner << endl;
02204 kdDebug(5006) << "and relevant for everyone: " << relevantForEveryone << endl;
02205 #endif
02206 return ( administerRights && relevantForOwner ) || relevantForEveryone;
02207 }
02208
02209 void KMailICalIfaceImpl::setResourceQuiet(bool q)
02210 {
02211 mResourceQuiet = q;
02212 }
02213
02214 bool KMailICalIfaceImpl::isResourceQuiet() const
02215 {
02216 return mResourceQuiet;
02217 }
02218
02219
02220 bool KMailICalIfaceImpl::addSubresource( const QString& resource,
02221 const QString& parent,
02222 const QString& contentsType )
02223 {
02224 kdDebug(5006) << "Adding subresource to parent: " << parent << " with name: " << resource << endl;
02225 kdDebug(5006) << "contents type: " << contentsType << endl;
02226 KMFolder *folder = findResourceFolder( parent );
02227 KMFolderDir *parentFolderDir = !parent.isEmpty() && folder ? folder->createChildFolder(): mFolderParentDir;
02228 if ( !parentFolderDir || parentFolderDir->hasNamedFolder( resource ) ) return false;
02229
02230 KMFolderType type = mFolderType;
02231 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
02232
02233 KMFolder* newFolder = parentFolderDir->createFolder( resource, false, type );
02234 if ( !newFolder ) return false;
02235 if( mFolderType == KMFolderTypeImap )
02236 static_cast<KMFolderImap*>( folder->storage() )->createFolder( resource );
02237
02238 StorageFormat defaultFormat = GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML ? StorageXML : StorageIcalVcard;
02239 setStorageFormat( newFolder, folder ? storageFormat( folder ) : defaultFormat );
02240 newFolder->storage()->setContentsType( folderContentsType( contentsType ) );
02241 newFolder->storage()->writeConfig();
02242 newFolder->open( "ical_subresource" );
02243 connectFolder( newFolder );
02244 reloadFolderTree();
02245
02246 return true;
02247 }
02248
02249 bool KMailICalIfaceImpl::removeSubresource( const QString& location )
02250 {
02251 kdDebug(5006) << k_funcinfo << endl;
02252
02253 KMFolder *folder = findResourceFolder( location );
02254
02255
02256
02257
02258 if ( !folder || isStandardResourceFolder( folder ) )
02259 return false;
02260
02261
02262
02263 subresourceDeleted( folderContentsType( folder->storage()->contentsType() ), location );
02264 mExtraFolders.remove( location );
02265 folder->disconnect( this );
02266
02267 if ( folder->folderType() == KMFolderTypeImap )
02268 kmkernel->imapFolderMgr()->remove( folder );
02269 else if ( folder->folderType() == KMFolderTypeCachedImap ) {
02270
02271 KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>( folder->storage() );
02272 KMAcctCachedImap* acct = storage->account();
02273 if ( acct )
02274 acct->addDeletedFolder( folder );
02275 kmkernel->dimapFolderMgr()->remove( folder );
02276 }
02277 return true;
02278 }
02279
02280 void KMailICalIfaceImpl::syncFolder(KMFolder * folder) const
02281 {
02282 if ( kmkernel->isOffline() || !GlobalSettings::immediatlySyncDIMAPOnGroupwareChanges() )
02283 return;
02284 KMFolderCachedImap *dimapFolder = dynamic_cast<KMFolderCachedImap*>( folder->storage() );
02285 if ( !dimapFolder )
02286 return;
02287
02288 if ( dimapFolder->imapPath().isEmpty() ) {
02289 if ( folder->parent() && folder->parent()->owner() )
02290 syncFolder( folder->parent()->owner() );
02291 else
02292 return;
02293 }
02294 dimapFolder->account()->processNewMailSingleFolder( folder );
02295 }
02296
02297 #include "kmailicalifaceimpl.moc"