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 void KMailICalIfaceImpl::changeResourceUIName( const QString &folderPath, const QString &newName )
01659 {
01660 kdDebug() << "Folder path " << folderPath << endl;
01661 KMFolder *f = findResourceFolder( folderPath );
01662 if ( f ) {
01663 KMailICalIfaceImpl::getResourceMap()->insert( folderPath, newName );
01664 kmkernel->folderMgr()->renameFolder( f, newName );
01665 KConfigGroup configGroup( kmkernel->config(), "Resource UINames" );
01666 configGroup.writeEntry( folderPath, newName );
01667 }
01668 }
01669
01670
01671 static void createFolderList( QStringList &folderNames, QValueList<QGuardedPtr<KMFolder> > &folderList )
01672 {
01673 QStringList dimapFolderNames;
01674 QStringList localFolderNames;
01675 QValueList<QGuardedPtr<KMFolder> > dimapFolderList;
01676 QValueList<QGuardedPtr<KMFolder> > localFolderList;
01677 kmkernel->dimapFolderMgr()->createFolderList( &dimapFolderNames, &dimapFolderList );
01678 kmkernel->folderMgr()->createFolderList( &localFolderNames, &localFolderList );
01679 folderNames += dimapFolderNames;
01680 folderNames += localFolderNames;
01681 folderList += dimapFolderList;
01682 folderList += localFolderList;
01683 }
01684
01685
01686
01687
01688
01689 void KMailICalIfaceImpl::readConfig()
01690 {
01691 bool enabled = GlobalSettings::self()->theIMAPResourceEnabled() &&
01692 ( GlobalSettings::self()->theIMAPResourceAccount() != 0 );
01693
01694 if( !enabled ) {
01695 if( mUseResourceIMAP == true ) {
01696
01697 mUseResourceIMAP = false;
01698 cleanup();
01699 reloadFolderTree();
01700 }
01701 return;
01702 }
01703 mUseResourceIMAP = enabled;
01704
01705
01706 const bool hideFolders = GlobalSettings::self()->hideGroupwareFolders();
01707 QString parentName = GlobalSettings::self()->theIMAPResourceFolderParent();
01708
01709
01710 KMFolderDir* folderParentDir;
01711 KMFolderType folderType;
01712 KMFolder* folderParent = kmkernel->findFolderById( parentName );
01713 if( folderParent == 0 ) {
01714
01715
01716 kdDebug(5006) << "Groupware folder " << parentName << " not found. Groupware functionality disabled" << endl;
01717
01718 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::self()->theIMAPResourceAccount() );
01719 Q_ASSERT( account );
01720 if ( account ) {
01721
01722 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01723 this, SLOT( slotCheckDone() ) );
01724 connect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01725 this, SLOT( slotCheckDone() ) );
01726 }
01727 mUseResourceIMAP = false;
01728
01729 mCalendar = 0;
01730 mTasks = 0;
01731 mJournals = 0;
01732 mContacts = 0;
01733 mNotes = 0;
01734 return;
01735 } else {
01736 folderParentDir = folderParent->createChildFolder();
01737 folderType = folderParent->folderType();
01738 }
01739
01740 KMAcctCachedImap::GroupwareType groupwareType = dynamic_cast<KMFolderCachedImap *>( folderParent->storage() )->account()->groupwareType();
01741
01742 if ( groupwareType == KMAcctCachedImap::GroupwareKolab ) {
01743
01744
01745 bool noneFound = true;
01746 bool mustFix = false;
01747 QValueVector<StandardFolderSearchResult> results( KMail::ContentsTypeLast + 1 );
01748 for ( int i = 0; i < KMail::ContentsTypeLast+1; ++i ) {
01749 if ( i != KMail::ContentsTypeMail ) {
01750 results[i] = findStandardResourceFolder( folderParentDir, static_cast<KMail::FolderContentsType>(i) );
01751 if ( results[i].found == StandardFolderSearchResult::FoundAndStandard )
01752 noneFound = false;
01753 else if ( results[i].found == StandardFolderSearchResult::FoundByType ||
01754 results[i].found == StandardFolderSearchResult::FoundByName ) {
01755 mustFix = true;
01756 noneFound = false;
01757 } else
01758 mustFix = true;
01759 }
01760 }
01761
01762
01763 if( mUseResourceIMAP && !noneFound && !mustFix && mFolderParentDir == folderParentDir
01764 && mFolderType == folderType ) {
01765
01766 if ( hideFolders != mHideFolders ) {
01767
01768 mHideFolders = hideFolders;
01769 reloadFolderTree();
01770 }
01771 return;
01772 }
01773
01774 if( noneFound || mustFix ) {
01775 QString msg;
01776 QString parentFolderName = folderParent != 0 ? folderParent->name() : folderParentDir->name();
01777 if ( noneFound ) {
01778
01779 msg = i18n("KMail will now create the required groupware folders"
01780 " as subfolders of %1; if you do not want this, cancel"
01781 " and the IMAP resource will be disabled").arg(parentFolderName);
01782 } else {
01783
01784 QString operations = "<ul>";
01785 for ( int i = 0; i < KMail::ContentsTypeLast+1; ++i ) {
01786 if ( i != KMail::ContentsTypeMail ) {
01787 QString typeName = localizedDefaultFolderName( static_cast<KMail::FolderContentsType>( i ) );
01788 if ( results[i].found == StandardFolderSearchResult::NotFound )
01789 operations += "<li>" + i18n( "%1: no folder found. It will be created." ).arg( typeName ) + "</li>";
01790 else if ( results[i].found == StandardFolderSearchResult::FoundByType || results[i].found == StandardFolderSearchResult::FoundByName )
01791 operations += "<li>" + i18n( "%1: found folder %2. It will be set as the main groupware folder." ).
01792 arg( typeName ).arg( results[i].folder->label() ) + "</li>";
01793 }
01794 }
01795 operations += "</ul>";
01796
01797 msg = i18n("<qt>KMail found the following groupware folders in %1 and needs to perform the following operations: %2"
01798 "<br>If you do not want this, cancel"
01799 " and the IMAP resource will be disabled").arg(parentFolderName, operations);
01800
01801 }
01802
01803 if( KMessageBox::questionYesNo( 0, msg,
01804 i18n("Standard Groupware Folders"), KStdGuiItem::cont(), KStdGuiItem::cancel() ) == KMessageBox::No ) {
01805
01806 GlobalSettings::self()->setTheIMAPResourceEnabled( false );
01807 mUseResourceIMAP = false;
01808 mFolderParentDir = 0;
01809 mFolderParent = 0;
01810 reloadFolderTree();
01811 return;
01812 }
01813 }
01814
01815
01816 mUseResourceIMAP = true;
01817 mFolderLanguage = GlobalSettings::self()->theIMAPResourceFolderLanguage();
01818 if( mFolderLanguage > 3 ) mFolderLanguage = 0;
01819 mFolderParentDir = folderParentDir;
01820 mFolderParent = folderParent;
01821 mFolderType = folderType;
01822 mHideFolders = hideFolders;
01823
01824
01825 cleanup();
01826
01827
01828 mCalendar = initFolder( KMail::ContentsTypeCalendar );
01829 mTasks = initFolder( KMail::ContentsTypeTask );
01830 mJournals = initFolder( KMail::ContentsTypeJournal );
01831 mContacts = initFolder( KMail::ContentsTypeContact );
01832 mNotes = initFolder( KMail::ContentsTypeNote );
01833
01834
01835 if ( mCalendar->folderType() == KMFolderTypeCachedImap )
01836 static_cast<KMFolderCachedImap *>( mCalendar->storage() )->updateAnnotationFolderType();
01837 if ( mTasks->folderType() == KMFolderTypeCachedImap )
01838 static_cast<KMFolderCachedImap *>( mTasks->storage() )->updateAnnotationFolderType();
01839 if ( mJournals->folderType() == KMFolderTypeCachedImap )
01840 static_cast<KMFolderCachedImap *>( mJournals->storage() )->updateAnnotationFolderType();
01841 if ( mContacts->folderType() == KMFolderTypeCachedImap )
01842 static_cast<KMFolderCachedImap *>( mContacts->storage() )->updateAnnotationFolderType();
01843 if ( mNotes->folderType() == KMFolderTypeCachedImap )
01844 static_cast<KMFolderCachedImap *>( mNotes->storage() )->updateAnnotationFolderType();
01845
01846
01847
01848
01849
01850
01851 QStringList folderNames;
01852 QValueList<QGuardedPtr<KMFolder> > folderList;
01853 createFolderList( folderNames, folderList );
01854 for( QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin();
01855 it != folderList.end(); ++it )
01856 {
01857 FolderStorage *storage = (*it)->storage();
01858 KMFolderCachedImap* dimapStorage = dynamic_cast<KMFolderCachedImap*>( storage );
01859 if ( storage && storage->contentsType() != 0 ) {
01860 if ( dimapStorage )
01861 dimapStorage->updateAnnotationFolderType();
01862 folderContentsTypeChanged( *it, storage->contentsType() );
01863 }
01864 }
01865
01866
01867
01868 mExtraFolders.remove( mCalendar->location() );
01869 mExtraFolders.remove( mTasks->location() );
01870 mExtraFolders.remove( mJournals->location() );
01871 mExtraFolders.remove( mContacts->location() );
01872 mExtraFolders.remove( mNotes->location() );
01873
01874 subresourceAdded( folderContentsType( KMail::ContentsTypeCalendar ), mCalendar->location(), mCalendar->label(), true, true );
01875 subresourceAdded( folderContentsType( KMail::ContentsTypeTask ), mTasks->location(), mTasks->label(), true, true );
01876 subresourceAdded( folderContentsType( KMail::ContentsTypeJournal ), mJournals->location(), mJournals->label(), true, false );
01877 subresourceAdded( folderContentsType( KMail::ContentsTypeContact ), mContacts->location(), mContacts->label(), true, false );
01878 subresourceAdded( folderContentsType( KMail::ContentsTypeNote ), mNotes->location(), mNotes->label(), true, false );
01879 } else if ( groupwareType == KMAcctCachedImap::GroupwareScalix ) {
01880
01881 mUseResourceIMAP = true;
01882 mFolderParentDir = folderParentDir;
01883 mFolderParent = folderParent;
01884 mFolderType = folderType;
01885 mHideFolders = false;
01886
01887
01888 cleanup();
01889
01890
01891 mCalendar = initScalixFolder( KMail::ContentsTypeCalendar );
01892 mTasks = initScalixFolder( KMail::ContentsTypeTask );
01893 mJournals = 0;
01894 mContacts = initScalixFolder( KMail::ContentsTypeContact );
01895 mNotes = initScalixFolder( KMail::ContentsTypeNote );
01896
01897
01898 if ( mCalendar->folderType() == KMFolderTypeCachedImap )
01899 static_cast<KMFolderCachedImap *>( mCalendar->storage() )->updateAnnotationFolderType();
01900 if ( mTasks->folderType() == KMFolderTypeCachedImap )
01901 static_cast<KMFolderCachedImap *>( mTasks->storage() )->updateAnnotationFolderType();
01902 if ( mContacts->folderType() == KMFolderTypeCachedImap )
01903 static_cast<KMFolderCachedImap *>( mContacts->storage() )->updateAnnotationFolderType();
01904 if ( mNotes->folderType() == KMFolderTypeCachedImap )
01905 static_cast<KMFolderCachedImap *>( mNotes->storage() )->updateAnnotationFolderType();
01906
01907
01908
01909
01910 kdDebug(5006) << k_funcinfo << "mCalendar=" << mCalendar << " " << mCalendar->location() << endl;
01911 kdDebug(5006) << k_funcinfo << "mContacts=" << mContacts << " " << mContacts->location() << endl;
01912 kdDebug(5006) << k_funcinfo << "mNotes=" << mNotes << " " << mNotes->location() << endl;
01913
01914
01915 QStringList folderNames;
01916 QValueList<QGuardedPtr<KMFolder> > folderList;
01917 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
01918 QValueList<QGuardedPtr<KMFolder> >::iterator it;
01919 for(it = folderList.begin(); it != folderList.end(); ++it)
01920 {
01921 FolderStorage *storage = (*it)->storage();
01922
01923 if ( (*it)->folderType() == KMFolderTypeCachedImap ) {
01924 KMFolderCachedImap *imapFolder = static_cast<KMFolderCachedImap*>( storage );
01925
01926 const QString attributes = imapFolder->folderAttributes();
01927 if ( attributes.contains( "X-FolderClass" ) ) {
01928 if ( !attributes.contains( "X-SpecialFolder" ) || (*it)->location().contains( "@" ) ) {
01929 const Scalix::FolderAttributeParser parser( attributes );
01930 if ( !parser.folderClass().isEmpty() ) {
01931 FolderContentsType type = Scalix::Utils::scalixIdToContentsType( parser.folderClass() );
01932 imapFolder->setContentsType( type );
01933 folderContentsTypeChanged( *it, type );
01934 }
01935 }
01936 }
01937 }
01938 }
01939
01940
01941
01942 mExtraFolders.remove( mCalendar->location() );
01943 mExtraFolders.remove( mTasks->location() );
01944 mExtraFolders.remove( mContacts->location() );
01945 mExtraFolders.remove( mNotes->location() );
01946
01947
01948
01949 subresourceAdded( folderContentsType( KMail::ContentsTypeCalendar ), mCalendar->location(), mCalendar->label(), true, true );
01950 subresourceAdded( folderContentsType( KMail::ContentsTypeTask ), mTasks->location(), mTasks->label(), true, true );
01951 subresourceAdded( folderContentsType( KMail::ContentsTypeContact ), mContacts->location(), mContacts->label(), true, false );
01952 subresourceAdded( folderContentsType( KMail::ContentsTypeNote ), mNotes->location(), mNotes->label(), true, false );
01953 }
01954
01955 KConfig *config = kmkernel->config();
01956 config->setGroup("Resource UINames");
01957 *KMailICalIfaceImpl::mSubResourceUINamesMap = config->entryMap( "Resource UINames" );
01958
01959 reloadFolderTree();
01960 }
01961
01962 void KMailICalIfaceImpl::slotCheckDone()
01963 {
01964 QString parentName = GlobalSettings::self()->theIMAPResourceFolderParent();
01965 KMFolder* folderParent = kmkernel->findFolderById( parentName );
01966
01967 if ( folderParent )
01968 {
01969 KMAccount* account = kmkernel->acctMgr()->find( GlobalSettings::self()->theIMAPResourceAccount() );
01970 if ( account )
01971 disconnect( account, SIGNAL( finishedCheck( bool, CheckStatus ) ),
01972 this, SLOT( slotCheckDone() ) );
01973 readConfig();
01974 }
01975 }
01976
01977 KMFolder* KMailICalIfaceImpl::initFolder( KMail::FolderContentsType contentsType )
01978 {
01979
01980 KMFolderType type = mFolderType;
01981 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
01982
01983 KFolderTreeItem::Type itemType = s_folderContentsType[contentsType].treeItemType;
01984
01985
01986
01987 StandardFolderSearchResult result = findStandardResourceFolder( mFolderParentDir, contentsType );
01988
01989
01990 if ( result.folders.count() > 1 && result.found == StandardFolderSearchResult::FoundAndStandard ) {
01991 QStringList labels;
01992 for ( QValueList<KMFolder*>::ConstIterator it = result.folders.begin(); it != result.folders.end(); ++it )
01993 labels << (*it)->prettyURL();
01994 const QString selected = KInputDialog::getItem( i18n("Default folder"),
01995 i18n("There are multiple %1 default folders, please choose one:")
01996 .arg( localizedDefaultFolderName( contentsType ) ), labels );
01997 if ( !selected.isEmpty() )
01998 result.folder = result.folders[ labels.findIndex( selected ) ];
01999 }
02000
02001 KMFolder* folder = result.folder;
02002
02003 if ( !folder ) {
02004
02005 folder =
02006 mFolderParentDir->createFolder( localizedDefaultFolderName( contentsType ), false, type );
02007 if( mFolderType == KMFolderTypeImap ) {
02008 KMFolderImap* parentFolder = static_cast<KMFolderImap*>( mFolderParent->storage() );
02009 parentFolder->createFolder( localizedDefaultFolderName( contentsType ) );
02010 static_cast<KMFolderImap*>( folder->storage() )->setAccount( parentFolder->account() );
02011 }
02012
02013 setStorageFormat( folder, globalStorageFormat() );
02014 } else {
02015 FolderInfo info = readFolderInfo( folder );
02016 mFolderInfoMap.insert( folder, info );
02017
02018 }
02019
02020 if( folder->canAccess() != 0 ) {
02021 KMessageBox::sorry(0, i18n("You do not have read/write permission to your %1 folder.")
02022 .arg( folderName( itemType ) ) );
02023 return 0;
02024 }
02025 folder->storage()->setContentsType( contentsType );
02026 folder->setSystemFolder( true );
02027 folder->storage()->writeConfig();
02028 folder->open("ifacefolder");
02029 connectFolder( folder );
02030 return folder;
02031 }
02032
02033 KMFolder* KMailICalIfaceImpl::initScalixFolder( KMail::FolderContentsType contentsType )
02034 {
02035
02036 KMFolderType type = mFolderType;
02037 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
02038
02039 KMFolder* folder = 0;
02040
02041
02042 QStringList folderNames;
02043 QValueList<QGuardedPtr<KMFolder> > folderList;
02044 Q_ASSERT( kmkernel );
02045 Q_ASSERT( kmkernel->dimapFolderMgr() );
02046 kmkernel->dimapFolderMgr()->createFolderList(&folderNames, &folderList);
02047 QValueList<QGuardedPtr<KMFolder> >::iterator it = folderList.begin();
02048 for(; it != folderList.end(); ++it)
02049 {
02050 FolderStorage *storage = (*it)->storage();
02051
02052 if ( (*it)->folderType() == KMFolderTypeCachedImap ) {
02053 KMFolderCachedImap *imapFolder = static_cast<KMFolderCachedImap*>( storage );
02054
02055 const QString attributes = imapFolder->folderAttributes();
02056 if ( attributes.contains( "X-SpecialFolder" ) ) {
02057 const Scalix::FolderAttributeParser parser( attributes );
02058 if ( contentsType == Scalix::Utils::scalixIdToContentsType( parser.folderClass() ) ) {
02059 folder = *it;
02060 break;
02061 }
02062 }
02063 }
02064 }
02065
02066 if ( !folder ) {
02067 return 0;
02068 } else {
02069 FolderInfo info = readFolderInfo( folder );
02070 mFolderInfoMap.insert( folder, info );
02071
02072 }
02073
02074 if( folder->canAccess() != 0 ) {
02075 KMessageBox::sorry(0, i18n("You do not have read/write permission to your folder.") );
02076 return 0;
02077 }
02078 folder->storage()->setContentsType( contentsType );
02079 folder->setSystemFolder( true );
02080 folder->storage()->writeConfig();
02081 folder->open( "scalixfolder" );
02082 connectFolder( folder );
02083 return folder;
02084 }
02085
02086 void KMailICalIfaceImpl::connectFolder( KMFolder* folder )
02087 {
02088
02089 disconnect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
02090 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
02091 disconnect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
02092 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
02093 disconnect( folder, SIGNAL( expunged( KMFolder* ) ),
02094 this, SLOT( slotRefreshFolder( KMFolder* ) ) );
02095 disconnect( folder->storage(), SIGNAL( readOnlyChanged( KMFolder* ) ),
02096 this, SLOT( slotFolderPropertiesChanged( KMFolder* ) ) );
02097 disconnect( folder, SIGNAL( nameChanged() ),
02098 this, SLOT( slotFolderRenamed() ) );
02099 disconnect( folder->storage(), SIGNAL( locationChanged( const QString&, const QString&) ),
02100 this, SLOT( slotFolderLocationChanged( const QString&, const QString&) ) );
02101
02102
02103 connect( folder, SIGNAL( msgAdded( KMFolder*, Q_UINT32 ) ),
02104 this, SLOT( slotIncidenceAdded( KMFolder*, Q_UINT32 ) ) );
02105 connect( folder, SIGNAL( msgRemoved( KMFolder*, Q_UINT32 ) ),
02106 this, SLOT( slotIncidenceDeleted( KMFolder*, Q_UINT32 ) ) );
02107 connect( folder, SIGNAL( expunged( KMFolder* ) ),
02108 this, SLOT( slotRefreshFolder( KMFolder* ) ) );
02109 connect( folder->storage(), SIGNAL( readOnlyChanged( KMFolder* ) ),
02110 this, SLOT( slotFolderPropertiesChanged( KMFolder* ) ) );
02111 connect( folder, SIGNAL( nameChanged() ),
02112 this, SLOT( slotFolderRenamed() ) );
02113 connect( folder->storage(), SIGNAL( locationChanged( const QString&, const QString&) ),
02114 this, SLOT( slotFolderLocationChanged( const QString&, const QString&) ) );
02115
02116 }
02117
02118 static void cleanupFolder( KMFolder* folder, KMailICalIfaceImpl* _this )
02119 {
02120 if( folder ) {
02121 folder->setSystemFolder( false );
02122 folder->disconnect( _this );
02123 folder->close("ifacefolder");
02124 }
02125 }
02126
02127 void KMailICalIfaceImpl::cleanup()
02128 {
02129 cleanupFolder( mContacts, this );
02130 cleanupFolder( mCalendar, this );
02131 cleanupFolder( mNotes, this );
02132 cleanupFolder( mTasks, this );
02133 cleanupFolder( mJournals, this );
02134
02135 mContacts = mCalendar = mNotes = mTasks = mJournals = 0;
02136 }
02137
02138 QString KMailICalIfaceImpl::folderPixmap( KFolderTreeItem::Type type ) const
02139 {
02140 if( !mUseResourceIMAP )
02141 return QString::null;
02142
02143 if( type == KFolderTreeItem::Contacts )
02144 return QString::fromLatin1( "kmgroupware_folder_contacts" );
02145 else if( type == KFolderTreeItem::Calendar )
02146 return QString::fromLatin1( "kmgroupware_folder_calendar" );
02147 else if( type == KFolderTreeItem::Notes )
02148 return QString::fromLatin1( "kmgroupware_folder_notes" );
02149 else if( type == KFolderTreeItem::Tasks )
02150 return QString::fromLatin1( "kmgroupware_folder_tasks" );
02151 else if( type == KFolderTreeItem::Journals )
02152 return QString::fromLatin1( "kmgroupware_folder_journals" );
02153
02154 return QString::null;
02155 }
02156
02157 static void reloadFolderTree()
02158 {
02159
02160 kmkernel->folderMgr()->contentsChanged();
02161 }
02162
02163
02164
02165
02166 static void vPartMicroParser( const QString& str, QString& s )
02167 {
02168 QString line;
02169 uint len = str.length();
02170
02171 for( uint i=0; i<len; ++i){
02172 if( str[i] == '\r' || str[i] == '\n' ){
02173 if( str[i] == '\r' )
02174 ++i;
02175 if( i+1 < len && str[i+1] == ' ' ){
02176
02177 ++i;
02178 }else{
02179
02180 if( line.startsWith( s ) ) {
02181 s = line.mid( s.length() + 1 );
02182 return;
02183 }
02184 line = "";
02185 }
02186 } else {
02187 line += str[i];
02188 }
02189 }
02190
02191
02192 s.truncate(0);
02193 }
02194
02195
02196 static QValueList<KMFolder*> findFolderByAnnotation( KMFolderDir* folderParentDir, const QString& annotation )
02197 {
02198 QValueList<KMFolder*> rv;
02199 QPtrListIterator<KMFolderNode> it( *folderParentDir );
02200 for ( ; it.current(); ++it ) {
02201 if ( !it.current()->isDir() ) {
02202 KMFolder* folder = static_cast<KMFolder *>( it.current() );
02203 if ( folder->folderType() == KMFolderTypeCachedImap ) {
02204 QString folderAnnotation = static_cast<KMFolderCachedImap*>( folder->storage() )->annotationFolderType();
02205
02206 if ( folderAnnotation == annotation )
02207 rv.append( folder );
02208 }
02209 }
02210 }
02211 return rv;
02212 }
02213
02214 KMailICalIfaceImpl::StandardFolderSearchResult KMailICalIfaceImpl::findStandardResourceFolder( KMFolderDir* folderParentDir, KMail::FolderContentsType contentsType )
02215 {
02216 if ( GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML )
02217 {
02218
02219 QValueList<KMFolder*> folders = findFolderByAnnotation( folderParentDir, QString( s_folderContentsType[contentsType].annotation ) + ".default" );
02220 if ( !folders.isEmpty() )
02221 return StandardFolderSearchResult( folders, StandardFolderSearchResult::FoundAndStandard );
02222
02223
02224 folders = findFolderByAnnotation( folderParentDir, QString( s_folderContentsType[contentsType].annotation ) );
02225 if ( !folders.isEmpty() )
02226 return StandardFolderSearchResult( folders, StandardFolderSearchResult::FoundByType );
02227
02228
02229 KMFolderNode* node = folderParentDir->hasNamedFolder( localizedDefaultFolderName( contentsType ) );
02230 if ( node && !node->isDir() )
02231 return StandardFolderSearchResult( static_cast<KMFolder *>( node ), StandardFolderSearchResult::FoundByName );
02232
02233 kdDebug(5006) << "findStandardResourceFolder: found no resource folder for " << s_folderContentsType[contentsType].annotation << endl;
02234 return StandardFolderSearchResult( 0, StandardFolderSearchResult::NotFound );
02235 }
02236 else
02237 {
02238 KFolderTreeItem::Type itemType = s_folderContentsType[contentsType].treeItemType;
02239 unsigned int folderLanguage = GlobalSettings::self()->theIMAPResourceFolderLanguage();
02240 if( folderLanguage > 3 ) folderLanguage = 0;
02241 KMFolderNode* node = folderParentDir->hasNamedFolder( folderName( itemType, folderLanguage ) );
02242 if ( !node || node->isDir() )
02243 return StandardFolderSearchResult( 0, StandardFolderSearchResult::NotFound );
02244 return StandardFolderSearchResult( static_cast<KMFolder*>( node ), StandardFolderSearchResult::FoundAndStandard );
02245 }
02246 }
02247
02248
02249
02250
02251
02252 bool KMailICalIfaceImpl::folderIsAlarmRelevant( const KMFolder *folder )
02253 {
02254 bool administerRights = true;
02255 bool relevantForOwner = true;
02256 bool relevantForEveryone = false;
02257 if ( folder->folderType() == KMFolderTypeImap ) {
02258 const KMFolderImap *imapFolder = static_cast<const KMFolderImap*>( folder->storage() );
02259 administerRights =
02260 imapFolder->userRightsState() != KMail::ACLJobs::Ok ||
02261 imapFolder->userRights() & KMail::ACLJobs::Administer;
02262 }
02263 if ( folder->folderType() == KMFolderTypeCachedImap ) {
02264 const KMFolderCachedImap *dimapFolder = static_cast<const KMFolderCachedImap*>( folder->storage() );
02265 administerRights =
02266 dimapFolder->userRightsState() != KMail::ACLJobs::Ok ||
02267 dimapFolder->userRights() & KMail::ACLJobs::Administer;
02268 relevantForOwner = !dimapFolder->alarmsBlocked() && ( dimapFolder->incidencesFor () == KMFolderCachedImap::IncForAdmins );
02269 relevantForEveryone = !dimapFolder->alarmsBlocked() && ( dimapFolder->incidencesFor() == KMFolderCachedImap::IncForReaders );
02270 }
02271 #if 0
02272 kdDebug(5006) << k_funcinfo << endl;
02273 kdDebug(5006) << "Folder: " << folder->label() << " has administer rights: " << administerRights << endl;
02274 kdDebug(5006) << "and is relevant for owner: " << relevantForOwner << endl;
02275 kdDebug(5006) << "and relevant for everyone: " << relevantForEveryone << endl;
02276 #endif
02277 return ( administerRights && relevantForOwner ) || relevantForEveryone;
02278 }
02279
02280 void KMailICalIfaceImpl::setResourceQuiet(bool q)
02281 {
02282 mResourceQuiet = q;
02283 }
02284
02285 bool KMailICalIfaceImpl::isResourceQuiet() const
02286 {
02287 return mResourceQuiet;
02288 }
02289
02290
02291 bool KMailICalIfaceImpl::addSubresource( const QString& resource,
02292 const QString& parent,
02293 const QString& contentsType )
02294 {
02295 kdDebug(5006) << "Adding subresource to parent: " << parent << " with name: " << resource << endl;
02296 kdDebug(5006) << "contents type: " << contentsType << endl;
02297 KMFolder *folder = findResourceFolder( parent );
02298 KMFolderDir *parentFolderDir = !parent.isEmpty() && folder ? folder->createChildFolder(): mFolderParentDir;
02299 if ( !parentFolderDir || parentFolderDir->hasNamedFolder( resource ) ) return false;
02300
02301 QString msg;
02302 if ( parentFolderDir->owner() && !parentFolderDir->owner()->isValidName( resource, msg ) ) {
02303 KMessageBox::error( 0, msg );
02304 return false;
02305 }
02306
02307 KMFolderType type = mFolderType;
02308 if( type == KMFolderTypeUnknown ) type = KMFolderTypeMaildir;
02309
02310 KMFolder* newFolder = parentFolderDir->createFolder( resource, false, type );
02311 if ( !newFolder ) return false;
02312 if( mFolderType == KMFolderTypeImap )
02313 static_cast<KMFolderImap*>( folder->storage() )->createFolder( resource );
02314
02315 StorageFormat defaultFormat = GlobalSettings::self()->theIMAPResourceStorageFormat() == GlobalSettings::EnumTheIMAPResourceStorageFormat::XML ? StorageXML : StorageIcalVcard;
02316 setStorageFormat( newFolder, folder ? storageFormat( folder ) : defaultFormat );
02317 newFolder->storage()->setContentsType( folderContentsType( contentsType ) );
02318 newFolder->storage()->writeConfig();
02319 newFolder->open( "ical_subresource" );
02320 connectFolder( newFolder );
02321 reloadFolderTree();
02322
02323 return true;
02324 }
02325
02326 bool KMailICalIfaceImpl::removeSubresource( const QString& location )
02327 {
02328 kdDebug(5006) << k_funcinfo << endl;
02329
02330 KMFolder *folder = findResourceFolder( location );
02331
02332
02333
02334
02335 if ( !folder || isStandardResourceFolder( folder ) )
02336 return false;
02337
02338
02339
02340 subresourceDeleted( folderContentsType( folder->storage()->contentsType() ), location );
02341 mExtraFolders.remove( location );
02342 folder->disconnect( this );
02343
02344 if ( folder->folderType() == KMFolderTypeImap )
02345 kmkernel->imapFolderMgr()->remove( folder );
02346 else if ( folder->folderType() == KMFolderTypeCachedImap ) {
02347
02348 KMFolderCachedImap* storage = static_cast<KMFolderCachedImap*>( folder->storage() );
02349 KMAcctCachedImap* acct = storage->account();
02350 if ( acct )
02351 acct->addDeletedFolder( folder );
02352 kmkernel->dimapFolderMgr()->remove( folder );
02353 }
02354 return true;
02355 }
02356
02357 void KMailICalIfaceImpl::syncFolder(KMFolder * folder) const
02358 {
02359 if ( kmkernel->isOffline() || !GlobalSettings::immediatlySyncDIMAPOnGroupwareChanges() )
02360 return;
02361 KMFolderCachedImap *dimapFolder = dynamic_cast<KMFolderCachedImap*>( folder->storage() );
02362 if ( !dimapFolder )
02363 return;
02364
02365 if ( dimapFolder->imapPath().isEmpty() ) {
02366 if ( folder->parent() && folder->parent()->owner() )
02367 syncFolder( folder->parent()->owner() );
02368 else
02369 return;
02370 }
02371 dimapFolder->account()->processNewMailInFolder( folder );
02372 }
02373
02374 #include "kmailicalifaceimpl.moc"