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