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