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