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