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