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