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