00001
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "kmfolder.h"
00028 #include "kmfolderimap.h"
00029 #include "kmfoldermbox.h"
00030 #include "kmfoldertree.h"
00031 #include "kmmsgdict.h"
00032 #include "undostack.h"
00033 #include "kmfoldermgr.h"
00034 #include "kmfiltermgr.h"
00035 #include "kmmsgdict.h"
00036 #include "imapaccountbase.h"
00037 using KMail::ImapAccountBase;
00038 #include "imapjob.h"
00039 using KMail::ImapJob;
00040 #include "attachmentstrategy.h"
00041 using KMail::AttachmentStrategy;
00042 #include "progressmanager.h"
00043 using KPIM::ProgressItem;
00044 using KPIM::ProgressManager;
00045 #include "listjob.h"
00046 using KMail::ListJob;
00047 #include "kmsearchpattern.h"
00048 #include "searchjob.h"
00049 using KMail::SearchJob;
00050 #include "renamejob.h"
00051 using KMail::RenameJob;
00052
00053 #include <kdebug.h>
00054 #include <kio/scheduler.h>
00055 #include <kconfig.h>
00056 #include <kmessagebox.h>
00057
00058 #include <qbuffer.h>
00059 #include <qtextcodec.h>
00060 #include <qstylesheet.h>
00061
00062 #include <assert.h>
00063
00064 KMFolderImap::KMFolderImap(KMFolder* folder, const char* aName)
00065 : KMFolderMbox(folder, aName)
00066 {
00067 mContentState = imapNoInformation;
00068 mSubfolderState = imapNoInformation;
00069 mAccount = 0;
00070 mIsSelected = FALSE;
00071 mLastUid = 0;
00072 mCheckFlags = TRUE;
00073 mCheckMail = TRUE;
00074 mCheckingValidity = FALSE;
00075 mUserRights = 0;
00076 mAlreadyRemoved = false;
00077 mHasChildren = ChildrenUnknown;
00078 mMailCheckProgressItem = 0;
00079 mListDirProgressItem = 0;
00080 mAddMessageProgressItem = 0;
00081 mReadOnly = false;
00082
00083 connect (this, SIGNAL( folderComplete( KMFolderImap*, bool ) ),
00084 this, SLOT( slotCompleteMailCheckProgress()) );
00085 }
00086
00087 KMFolderImap::~KMFolderImap()
00088 {
00089 if (mAccount) {
00090 mAccount->removeSlaveJobsForFolder( folder() );
00091
00092
00093
00094
00095 if ( mAccount->checkingMail( folder() ) ) {
00096 mAccount->killAllJobs();
00097 }
00098 }
00099 writeConfig();
00100 if (kmkernel->undoStack()) kmkernel->undoStack()->folderDestroyed( folder() );
00101 mMetaDataMap.setAutoDelete( true );
00102 mMetaDataMap.clear();
00103 mUidMetaDataMap.setAutoDelete( true );
00104 mUidMetaDataMap.clear();
00105 }
00106
00107
00108
00109 void KMFolderImap::close(bool aForced)
00110 {
00111 if (mOpenCount <= 0 ) return;
00112 if (mOpenCount > 0) mOpenCount--;
00113 if (mOpenCount > 0 && !aForced) return;
00114 if (isSelected() && !aForced) {
00115 kdWarning(5006) << "Trying to close the selected folder " << label() <<
00116 " - ignoring!" << endl;
00117 return;
00118 }
00119
00120 if (mAccount)
00121 mAccount->ignoreJobsForFolder( folder() );
00122 int idx = count();
00123 while (--idx >= 0) {
00124 if ( mMsgList[idx]->isMessage() ) {
00125 KMMessage *msg = static_cast<KMMessage*>(mMsgList[idx]);
00126 if (msg->transferInProgress())
00127 msg->setTransferInProgress( false );
00128 }
00129 }
00130
00131 mOpenCount++;
00132 KMFolderMbox::close(aForced);
00133 }
00134
00135 KMFolder* KMFolderImap::trashFolder() const
00136 {
00137 QString trashStr = account()->trash();
00138 return kmkernel->imapFolderMgr()->findIdString( trashStr );
00139 }
00140
00141
00142 KMMessage* KMFolderImap::getMsg(int idx)
00143 {
00144 if(!(idx >= 0 && idx <= count()))
00145 return 0;
00146
00147 KMMsgBase* mb = getMsgBase(idx);
00148 if (!mb) return 0;
00149 if (mb->isMessage())
00150 {
00151 return ((KMMessage*)mb);
00152 } else {
00153 KMMessage* msg = FolderStorage::getMsg( idx );
00154 if ( msg )
00155 msg->setComplete( false );
00156 return msg;
00157 }
00158 }
00159
00160
00161 void KMFolderImap::setAccount(KMAcctImap *aAccount)
00162 {
00163 mAccount = aAccount;
00164 if( !folder() || !folder()->child() ) return;
00165 KMFolderNode* node;
00166 for (node = folder()->child()->first(); node;
00167 node = folder()->child()->next())
00168 {
00169 if (!node->isDir())
00170 static_cast<KMFolderImap*>(static_cast<KMFolder*>(node)->storage())->setAccount(aAccount);
00171 }
00172 }
00173
00174
00175 void KMFolderImap::readConfig()
00176 {
00177 KConfig* config = KMKernel::config();
00178 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00179 mCheckMail = config->readBoolEntry("checkmail", true);
00180
00181 mUidValidity = config->readEntry("UidValidity");
00182 if ( mImapPath.isEmpty() ) {
00183 setImapPath( config->readEntry("ImapPath") );
00184 }
00185 if (QString(name()).upper() == "INBOX" && mImapPath == "/INBOX/")
00186 {
00187 folder()->setSystemFolder( true );
00188 folder()->setLabel( i18n("inbox") );
00189 }
00190 mNoContent = config->readBoolEntry("NoContent", FALSE);
00191 mReadOnly = config->readBoolEntry("ReadOnly", FALSE);
00192
00193 KMFolderMbox::readConfig();
00194 }
00195
00196
00197 void KMFolderImap::writeConfig()
00198 {
00199 KConfig* config = KMKernel::config();
00200 KConfigGroupSaver saver(config, "Folder-" + folder()->idString());
00201 config->writeEntry("checkmail", mCheckMail);
00202 config->writeEntry("UidValidity", mUidValidity);
00203 config->writeEntry("ImapPath", mImapPath);
00204 config->writeEntry("NoContent", mNoContent);
00205 config->writeEntry("ReadOnly", mReadOnly);
00206 KMFolderMbox::writeConfig();
00207 }
00208
00209
00210 void KMFolderImap::remove()
00211 {
00212 if ( mAlreadyRemoved || !mAccount )
00213 {
00214
00215 FolderStorage::remove();
00216 return;
00217 }
00218 KURL url = mAccount->getUrl();
00219 url.setPath(imapPath());
00220 if ( mAccount->makeConnection() == ImapAccountBase::Error ||
00221 imapPath().isEmpty() )
00222 {
00223 emit removed(folder(), false);
00224 return;
00225 }
00226 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
00227 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
00228 ImapAccountBase::jobData jd(url.url());
00229 jd.progressItem = ProgressManager::createProgressItem(
00230 "ImapFolderRemove" + ProgressManager::getUniqueID(),
00231 i18n("Removing folder"),
00232 i18n( "URL: %1" ).arg( QStyleSheet::escape( folder()->prettyURL() ) ),
00233 false,
00234 mAccount->useSSL() || mAccount->useTLS() );
00235 mAccount->insertJob(job, jd);
00236 connect(job, SIGNAL(result(KIO::Job *)),
00237 this, SLOT(slotRemoveFolderResult(KIO::Job *)));
00238 }
00239
00240
00241 void KMFolderImap::slotRemoveFolderResult(KIO::Job *job)
00242 {
00243 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00244 if ( it == mAccount->jobsEnd() ) return;
00245 if (job->error())
00246 {
00247 mAccount->handleJobError( job, i18n("Error while removing a folder.") );
00248 emit removed(folder(), false);
00249 } else {
00250 mAccount->removeJob(it);
00251 FolderStorage::remove();
00252 }
00253
00254 }
00255
00256
00257 void KMFolderImap::removeMsg(int idx, bool quiet)
00258 {
00259 if (idx < 0)
00260 return;
00261
00262 if (!quiet)
00263 {
00264 KMMessage *msg = getMsg(idx);
00265 deleteMessage(msg);
00266 }
00267
00268 mLastUid = 0;
00269 KMFolderMbox::removeMsg(idx);
00270 }
00271
00272 void KMFolderImap::removeMsg( const QPtrList<KMMessage>& msgList, bool quiet )
00273 {
00274 if ( msgList.isEmpty() ) return;
00275 if (!quiet)
00276 deleteMessage(msgList);
00277
00278 mLastUid = 0;
00279
00280
00281
00282
00283
00284
00285 QPtrListIterator<KMMessage> it( msgList );
00286 KMMessage *msg;
00287 while ( (msg = it.current()) != 0 ) {
00288 ++it;
00289 int idx = find(msg);
00290 assert( idx != -1);
00291
00292 KMFolderMbox::removeMsg(idx, quiet);
00293 }
00294 }
00295
00296
00297 int KMFolderImap::rename( const QString& newName, KMFolderDir *aParent )
00298 {
00299 if ( !aParent )
00300 KMFolderMbox::rename( newName );
00301 kmkernel->folderMgr()->contentsChanged();
00302 return 0;
00303 }
00304
00305
00306 void KMFolderImap::addMsgQuiet(KMMessage* aMsg)
00307 {
00308 KMFolder *aFolder = aMsg->parent();
00309 Q_UINT32 serNum = 0;
00310 aMsg->setTransferInProgress( false );
00311 if (aFolder) {
00312 serNum = aMsg->getMsgSerNum();
00313 kmkernel->undoStack()->pushSingleAction( serNum, aFolder, folder() );
00314 int idx = aFolder->find( aMsg );
00315 assert( idx != -1 );
00316 aFolder->take( idx );
00317 } else {
00318 kdDebug(5006) << k_funcinfo << "no parent" << endl;
00319 }
00320 if ( !mAccount->hasCapability("uidplus") ) {
00321
00322
00323 mMetaDataMap.insert( aMsg->msgIdMD5(),
00324 new KMMsgMetaData(aMsg->status(), serNum) );
00325 }
00326
00327 delete aMsg;
00328 aMsg = 0;
00329 getFolder();
00330 }
00331
00332
00333 void KMFolderImap::addMsgQuiet(QPtrList<KMMessage> msgList)
00334 {
00335 if ( mAddMessageProgressItem )
00336 {
00337 mAddMessageProgressItem->setComplete();
00338 mAddMessageProgressItem = 0;
00339 }
00340 KMFolder *aFolder = msgList.first()->parent();
00341 int undoId = -1;
00342 bool uidplus = mAccount->hasCapability("uidplus");
00343 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00344 {
00345 if ( undoId == -1 )
00346 undoId = kmkernel->undoStack()->newUndoAction( aFolder, folder() );
00347 if ( msg->getMsgSerNum() > 0 )
00348 kmkernel->undoStack()->addMsgToAction( undoId, msg->getMsgSerNum() );
00349 if ( !uidplus ) {
00350
00351
00352 mMetaDataMap.insert( msg->msgIdMD5(),
00353 new KMMsgMetaData(msg->status(), msg->getMsgSerNum()) );
00354 }
00355 msg->setTransferInProgress( false );
00356 }
00357 if ( aFolder ) {
00358 aFolder->take( msgList );
00359 } else {
00360 kdDebug(5006) << k_funcinfo << "no parent" << endl;
00361 }
00362 msgList.setAutoDelete(true);
00363 msgList.clear();
00364 getFolder();
00365 }
00366
00367
00368 int KMFolderImap::addMsg(KMMessage* aMsg, int* aIndex_ret)
00369 {
00370 QPtrList<KMMessage> list;
00371 list.append(aMsg);
00372 QValueList<int> index;
00373 int ret = addMsg(list, index);
00374 aIndex_ret = &index.first();
00375 return ret;
00376 }
00377
00378 int KMFolderImap::addMsg(QPtrList<KMMessage>& msgList, QValueList<int>& aIndex_ret)
00379 {
00380 KMMessage *aMsg = msgList.getFirst();
00381 KMFolder *msgParent = aMsg->parent();
00382
00383 ImapJob *imapJob = 0;
00384 if (msgParent)
00385 {
00386 if (msgParent->folderType() == KMFolderTypeImap)
00387 {
00388 if (static_cast<KMFolderImap*>(msgParent->storage())->account() == account())
00389 {
00390
00391 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00392 msg->setTransferInProgress(true);
00393
00394 if (folder() == msgParent)
00395 {
00396
00397 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00398 {
00399 if (!msg->isComplete())
00400 {
00401 int idx = msgParent->find(msg);
00402 assert(idx != -1);
00403 msg = msgParent->getMsg(idx);
00404 }
00405 imapJob = new ImapJob(msg, ImapJob::tPutMessage, this);
00406 connect(imapJob, SIGNAL(messageStored(KMMessage*)),
00407 SLOT(addMsgQuiet(KMMessage*)));
00408 imapJob->start();
00409 }
00410
00411 } else {
00412
00413
00414 QValueList<ulong> uids;
00415 getUids(msgList, uids);
00416
00417
00418 QStringList sets = makeSets(uids, false);
00419
00420 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
00421 {
00422
00423 QPtrList<KMMessage> temp_msgs = splitMessageList(*it, msgList);
00424 if ( temp_msgs.isEmpty() ) kdDebug(5006) << "Wow! KMFolderImap::splitMessageList() returned an empty list!" << endl;
00425 imapJob = new ImapJob(temp_msgs, *it, ImapJob::tMoveMessage, this);
00426 connect(imapJob, SIGNAL(messageCopied(QPtrList<KMMessage>)),
00427 SLOT(addMsgQuiet(QPtrList<KMMessage>)));
00428 connect(imapJob, SIGNAL(result(KMail::FolderJob*)),
00429 SLOT(slotCopyMsgResult(KMail::FolderJob*)));
00430 imapJob->start();
00431 }
00432 }
00433 return 0;
00434 }
00435 else
00436 {
00437
00438 QPtrListIterator<KMMessage> it( msgList );
00439 KMMessage *msg;
00440 while ( (msg = it.current()) != 0 )
00441 {
00442 ++it;
00443 int index;
00444 if (!canAddMsgNow(msg, &index)) {
00445 aIndex_ret << index;
00446 msgList.remove(msg);
00447 } else {
00448 if (!msg->transferInProgress())
00449 msg->setTransferInProgress(true);
00450 }
00451 }
00452 }
00453 }
00454 }
00455
00456 if ( !msgList.isEmpty() )
00457 {
00458
00459 QPtrListIterator<KMMessage> it( msgList );
00460 KMMessage* msg;
00461 while ( ( msg = it.current() ) != 0 )
00462 {
00463 ++it;
00464 if ( !msg->transferInProgress() )
00465 msg->setTransferInProgress( true );
00466 }
00467 imapJob = new ImapJob( msgList, QString::null, ImapJob::tPutMessage, this );
00468 if ( !mAddMessageProgressItem && msgList.count() > 1 )
00469 {
00470
00471
00472 mAddMessageProgressItem = ProgressManager::createProgressItem(
00473 "Uploading"+ProgressManager::getUniqueID(),
00474 i18n("Uploading message data"),
00475 i18n("Destination folder: %1").arg( QStyleSheet::escape( folder()->prettyURL() ) ),
00476 true,
00477 mAccount->useSSL() || mAccount->useTLS() );
00478 mAddMessageProgressItem->setTotalItems( msgList.count() );
00479 connect ( mAddMessageProgressItem, SIGNAL( progressItemCanceled( KPIM::ProgressItem*)),
00480 mAccount, SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
00481 imapJob->setParentProgressItem( mAddMessageProgressItem );
00482 }
00483 connect( imapJob, SIGNAL( messageCopied(QPtrList<KMMessage>) ),
00484 SLOT( addMsgQuiet(QPtrList<KMMessage>) ) );
00485 imapJob->start();
00486 }
00487
00488 return 0;
00489 }
00490
00491
00492 void KMFolderImap::slotCopyMsgResult( KMail::FolderJob* job )
00493 {
00494 if ( job->error() )
00495 emit folderComplete( this, false );
00496 }
00497
00498
00499 void KMFolderImap::copyMsg(QPtrList<KMMessage>& msgList)
00500 {
00501 if ( !mAccount->hasCapability("uidplus") ) {
00502 for ( KMMessage *msg = msgList.first(); msg; msg = msgList.next() ) {
00503
00504
00505 mMetaDataMap.insert( msg->msgIdMD5(), new KMMsgMetaData(msg->status()) );
00506 }
00507 }
00508
00509 QValueList<ulong> uids;
00510 getUids(msgList, uids);
00511 QStringList sets = makeSets(uids, false);
00512 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
00513 {
00514
00515 QPtrList<KMMessage> temp_msgs = splitMessageList(*it, msgList);
00516
00517 ImapJob *job = new ImapJob(temp_msgs, *it, ImapJob::tCopyMessage, this);
00518 job->start();
00519 }
00520 }
00521
00522
00523 QPtrList<KMMessage> KMFolderImap::splitMessageList(const QString& set,
00524 QPtrList<KMMessage>& msgList)
00525 {
00526 int lastcomma = set.findRev(",");
00527 int lastdub = set.findRev(":");
00528 int last = 0;
00529 if (lastdub > lastcomma) last = lastdub;
00530 else last = lastcomma;
00531 last++;
00532 if (last < 0) last = set.length();
00533
00534 const QString last_uid = set.right(set.length() - last);
00535 QPtrList<KMMessage> temp_msgs;
00536 QString uid;
00537 if (!last_uid.isEmpty())
00538 {
00539 QPtrListIterator<KMMessage> it( msgList );
00540 KMMessage* msg = 0;
00541 while ( (msg = it.current()) != 0 )
00542 {
00543
00544 temp_msgs.append(msg);
00545 uid.setNum( msg->UID() );
00546
00547 msgList.remove(msg);
00548 if (uid == last_uid) break;
00549 }
00550 }
00551 else
00552 {
00553
00554 temp_msgs = msgList;
00555 }
00556
00557 return temp_msgs;
00558 }
00559
00560
00561 KMMessage* KMFolderImap::take(int idx)
00562 {
00563 KMMsgBase* mb(mMsgList[idx]);
00564 if (!mb) return 0;
00565 if (!mb->isMessage()) readMsg(idx);
00566
00567 KMMessage *msg = static_cast<KMMessage*>(mb);
00568 deleteMessage(msg);
00569
00570 mLastUid = 0;
00571 return KMFolderMbox::take(idx);
00572 }
00573
00574 void KMFolderImap::take(QPtrList<KMMessage> msgList)
00575 {
00576 deleteMessage(msgList);
00577
00578 mLastUid = 0;
00579 KMFolderMbox::take(msgList);
00580 }
00581
00582
00583 void KMFolderImap::slotListNamespaces()
00584 {
00585 disconnect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
00586 this, SLOT( slotListNamespaces() ) );
00587 if ( mAccount->makeConnection() == ImapAccountBase::Error )
00588 {
00589 kdWarning(5006) << "slotListNamespaces - got no connection" << endl;
00590 return;
00591 } else if ( mAccount->makeConnection() == ImapAccountBase::Connecting )
00592 {
00593
00594 kdDebug(5006) << "slotListNamespaces - waiting for connection" << endl;
00595 connect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
00596 this, SLOT( slotListNamespaces() ) );
00597 return;
00598 }
00599 kdDebug(5006) << "slotListNamespaces" << endl;
00600
00601 setSubfolderState( imapNoInformation );
00602 mSubfolderState = imapListingInProgress;
00603 mAccount->setHasInbox( false );
00604
00605 ImapAccountBase::ListType type = ImapAccountBase::List;
00606 if ( mAccount->onlySubscribedFolders() )
00607 type = ImapAccountBase::ListSubscribed;
00608
00609 ImapAccountBase::nsMap map = mAccount->namespaces();
00610 QStringList personal = map[ImapAccountBase::PersonalNS];
00611
00612 for ( QStringList::Iterator it = personal.begin(); it != personal.end(); ++it )
00613 {
00614 KMail::ListJob* job = new KMail::ListJob( mAccount, type, this,
00615 mAccount->addPathToNamespace( *it ) );
00616 job->setNamespace( *it );
00617 connect( job, SIGNAL(receivedFolders(const QStringList&, const QStringList&,
00618 const QStringList&, const QStringList&, const ImapAccountBase::jobData&)),
00619 this, SLOT(slotListResult(const QStringList&, const QStringList&,
00620 const QStringList&, const QStringList&, const ImapAccountBase::jobData&)));
00621 job->start();
00622 }
00623
00624
00625 QStringList ns = map[ImapAccountBase::OtherUsersNS];
00626 ns += map[ImapAccountBase::SharedNS];
00627 for ( QStringList::Iterator it = ns.begin(); it != ns.end(); ++it )
00628 {
00629 KMail::ListJob* job = new KMail::ListJob( mAccount, type, this, mAccount->addPathToNamespace( *it ) );
00630 connect( job, SIGNAL(receivedFolders(const QStringList&, const QStringList&,
00631 const QStringList&, const QStringList&, const ImapAccountBase::jobData&)),
00632 this, SLOT(slotCheckNamespace(const QStringList&, const QStringList&,
00633 const QStringList&, const QStringList&, const ImapAccountBase::jobData&)));
00634 job->start();
00635 }
00636 }
00637
00638
00639 void KMFolderImap::slotCheckNamespace( const QStringList& subfolderNames,
00640 const QStringList& subfolderPaths,
00641 const QStringList& subfolderMimeTypes,
00642 const QStringList& subfolderAttributes,
00643 const ImapAccountBase::jobData& jobData )
00644 {
00645 kdDebug(5006) << "slotCheckNamespace - " << subfolderNames.join(",") << endl;
00646
00647
00648
00649 QString name = jobData.path.mid( 1, jobData.path.length()-2 );
00650 name.remove( mAccount->delimiterForNamespace( name ) );
00651 if ( name.isEmpty() ) {
00652
00653 slotListResult( subfolderNames, subfolderPaths,
00654 subfolderMimeTypes, subfolderAttributes, jobData );
00655 return;
00656 }
00657
00658 folder()->createChildFolder();
00659 KMFolderNode *node = 0;
00660 for ( node = folder()->child()->first(); node;
00661 node = folder()->child()->next())
00662 {
00663 if ( !node->isDir() && node->name() == name )
00664 break;
00665 }
00666 if ( subfolderNames.isEmpty() )
00667 {
00668 if ( node )
00669 {
00670 kdDebug(5006) << "delete namespace folder " << name << endl;
00671 KMFolder *fld = static_cast<KMFolder*>(node);
00672 KMFolderImap* nsFolder = static_cast<KMFolderImap*>(fld->storage());
00673 nsFolder->setAlreadyRemoved( true );
00674 kmkernel->imapFolderMgr()->remove( fld );
00675 }
00676 } else {
00677 if ( node )
00678 {
00679
00680 kdDebug(5006) << "found namespace folder " << name << endl;
00681 if ( !mAccount->listOnlyOpenFolders() )
00682 {
00683 KMFolderImap* nsFolder =
00684 static_cast<KMFolderImap*>(static_cast<KMFolder*>(node)->storage());
00685 nsFolder->slotListResult( subfolderNames, subfolderPaths,
00686 subfolderMimeTypes, subfolderAttributes, jobData );
00687 }
00688 } else
00689 {
00690
00691 kdDebug(5006) << "create namespace folder " << name << endl;
00692 KMFolder *fld = folder()->child()->createFolder( name );
00693 if ( fld ) {
00694 KMFolderImap* f = static_cast<KMFolderImap*> ( fld->storage() );
00695 f->initializeFrom( this, mAccount->addPathToNamespace( name ),
00696 "inode/directory" );
00697 f->close();
00698 if ( !mAccount->listOnlyOpenFolders() )
00699 {
00700 f->slotListResult( subfolderNames, subfolderPaths,
00701 subfolderMimeTypes, subfolderAttributes, jobData );
00702 }
00703 }
00704 kmkernel->imapFolderMgr()->contentsChanged();
00705 }
00706 }
00707 }
00708
00709
00710 bool KMFolderImap::listDirectory()
00711 {
00712 if ( !mAccount ||
00713 ( mAccount && mAccount->makeConnection() == ImapAccountBase::Error ) )
00714 {
00715 kdDebug(5006) << "KMFolderImap::listDirectory - got no connection" << endl;
00716 return false;
00717 }
00718
00719 if ( this == mAccount->rootFolder() )
00720 {
00721
00722 slotListNamespaces();
00723 return true;
00724 }
00725 mSubfolderState = imapListingInProgress;
00726
00727
00728 ImapAccountBase::ListType type = ImapAccountBase::List;
00729 if ( mAccount->onlySubscribedFolders() )
00730 type = ImapAccountBase::ListSubscribed;
00731 KMail::ListJob* job = new KMail::ListJob( mAccount, type, this );
00732 job->setParentProgressItem( account()->listDirProgressItem() );
00733 connect( job, SIGNAL(receivedFolders(const QStringList&, const QStringList&,
00734 const QStringList&, const QStringList&, const ImapAccountBase::jobData&)),
00735 this, SLOT(slotListResult(const QStringList&, const QStringList&,
00736 const QStringList&, const QStringList&, const ImapAccountBase::jobData&)));
00737 job->start();
00738
00739 return true;
00740 }
00741
00742
00743
00744 void KMFolderImap::slotListResult( const QStringList& subfolderNames,
00745 const QStringList& subfolderPaths,
00746 const QStringList& subfolderMimeTypes,
00747 const QStringList& subfolderAttributes,
00748 const ImapAccountBase::jobData& jobData )
00749 {
00750 mSubfolderState = imapFinished;
00751
00752
00753
00754
00755 kmkernel->imapFolderMgr()->quiet(true);
00756
00757 bool root = ( this == mAccount->rootFolder() );
00758 folder()->createChildFolder();
00759 if ( root && !mAccount->hasInbox() )
00760 {
00761
00762 initInbox();
00763 }
00764
00765
00766
00767
00768 if ( root && !subfolderNames.empty() )
00769 {
00770 KMFolderImap* parent = findParent( subfolderPaths.first(), subfolderNames.first() );
00771 if ( parent )
00772 {
00773 kdDebug(5006) << "KMFolderImap::slotListResult - pass listing to "
00774 << parent->label() << endl;
00775 parent->slotListResult( subfolderNames, subfolderPaths,
00776 subfolderMimeTypes, subfolderAttributes, jobData );
00777
00778 QStringList list;
00779 checkFolders( list, jobData.curNamespace );
00780
00781 emit directoryListingFinished( this );
00782 kmkernel->imapFolderMgr()->quiet( false );
00783 return;
00784 }
00785 }
00786
00787 bool emptyList = ( root && subfolderNames.empty() );
00788 if ( !emptyList )
00789 {
00790 checkFolders( subfolderNames, jobData.curNamespace );
00791 }
00792
00793 KMFolderImap *f = 0;
00794 KMFolderNode *node = 0;
00795 for ( uint i = 0; i < subfolderNames.count(); i++ )
00796 {
00797 bool settingsChanged = false;
00798
00799 for ( node = folder()->child()->first(); node;
00800 node = folder()->child()->next() ) {
00801 if ( !node->isDir() && node->name() == subfolderNames[i] )
00802 break;
00803 }
00804 if ( node ) {
00805 f = static_cast<KMFolderImap*>(static_cast<KMFolder*>(node)->storage());
00806 }
00807 else if ( subfolderPaths[i].upper() != "/INBOX/" )
00808 {
00809 kdDebug(5006) << "create folder " << subfolderNames[i] << endl;
00810 KMFolder *fld = folder()->child()->createFolder(subfolderNames[i]);
00811 if ( fld ) {
00812 f = static_cast<KMFolderImap*> ( fld->storage() );
00813 f->close();
00814 settingsChanged = true;
00815 } else {
00816 kdWarning(5006) << "can't create folder " << subfolderNames[i] << endl;
00817 }
00818 }
00819 if ( f )
00820 {
00821
00822 if ( f->imapPath().isEmpty() ) {
00823 settingsChanged = true;
00824 }
00825
00826 account()->listDirProgressItem()->incCompletedItems();
00827 account()->listDirProgressItem()->updateProgress();
00828 account()->listDirProgressItem()->setStatus( folder()->prettyURL() + i18n(" completed") );
00829
00830 f->initializeFrom( this, subfolderPaths[i], subfolderMimeTypes[i] );
00831 f->setChildrenState( subfolderAttributes[i] );
00832 if ( mAccount->listOnlyOpenFolders() &&
00833 f->hasChildren() != FolderStorage::ChildrenUnknown )
00834 {
00835 settingsChanged = true;
00836 }
00837
00838 if ( settingsChanged )
00839 {
00840
00841 kmkernel->imapFolderMgr()->contentsChanged();
00842 }
00843 if ( ( subfolderMimeTypes[i] == "message/directory" ||
00844 subfolderMimeTypes[i] == "inode/directory" ) &&
00845 !mAccount->listOnlyOpenFolders() )
00846 {
00847 f->listDirectory();
00848 }
00849 } else {
00850 kdWarning(5006) << "can't find folder " << subfolderNames[i] << endl;
00851 }
00852 }
00853
00854
00855 kmkernel->imapFolderMgr()->quiet( false );
00856 emit directoryListingFinished( this );
00857 account()->listDirProgressItem()->setComplete();
00858 }
00859
00860
00861 void KMFolderImap::initInbox()
00862 {
00863 KMFolderImap *f = 0;
00864 KMFolderNode *node = 0;
00865
00866 for (node = folder()->child()->first(); node;
00867 node = folder()->child()->next()) {
00868 if (!node->isDir() && node->name() == "INBOX") break;
00869 }
00870 if (node) {
00871 f = static_cast<KMFolderImap*>(static_cast<KMFolder*>(node)->storage());
00872 } else {
00873 f = static_cast<KMFolderImap*>
00874 (folder()->child()->createFolder("INBOX", true)->storage());
00875 if ( f )
00876 {
00877 f->folder()->setLabel( i18n("inbox") );
00878 f->close();
00879 }
00880 kmkernel->imapFolderMgr()->contentsChanged();
00881 }
00882 if ( f ) {
00883 f->initializeFrom( this, "/INBOX/", "message/directory" );
00884 f->setChildrenState( QString::null );
00885 }
00886
00887 mAccount->setHasInbox( true );
00888 }
00889
00890
00891 KMFolderImap* KMFolderImap::findParent( const QString& path, const QString& name )
00892 {
00893 QString parent = path.left( path.length() - name.length() - 2 );
00894 if ( parent.length() > 1 )
00895 {
00896
00897 parent = parent.right( parent.length() - 1 );
00898 if ( parent != label() )
00899 {
00900 KMFolderNode *node = folder()->child()->first();
00901
00902 while ( node )
00903 {
00904 if ( node->name() == parent )
00905 {
00906 KMFolder* fld = static_cast<KMFolder*>(node);
00907 KMFolderImap* imapFld = static_cast<KMFolderImap*>( fld->storage() );
00908 return imapFld;
00909 }
00910 node = folder()->child()->next();
00911 }
00912 }
00913 }
00914 return 0;
00915 }
00916
00917
00918 void KMFolderImap::checkFolders( const QStringList& subfolderNames,
00919 const QString& myNamespace )
00920 {
00921 QPtrList<KMFolder> toRemove;
00922 KMFolderNode *node = folder()->child()->first();
00923 while ( node )
00924 {
00925 if ( !node->isDir() && subfolderNames.findIndex(node->name()) == -1 )
00926 {
00927 KMFolder* fld = static_cast<KMFolder*>(node);
00928 KMFolderImap* imapFld = static_cast<KMFolderImap*>( fld->storage() );
00929
00930
00931 bool isInNamespace = ( myNamespace.isEmpty() ||
00932 myNamespace == mAccount->namespaceForFolder( imapFld ) );
00933 kdDebug(5006) << node->name() << " in namespace " << myNamespace << ":" <<
00934 isInNamespace << endl;
00935
00936 QString name = node->name();
00937 bool ignore = ( ( this == mAccount->rootFolder() ) &&
00938 ( imapFld->imapPath() == "/INBOX/" ||
00939 mAccount->isNamespaceFolder( name ) ||
00940 !isInNamespace ) );
00941
00942 if ( imapFld->imapPath().isEmpty() ) {
00943 ignore = false;
00944 }
00945 if ( !ignore )
00946 {
00947
00948 kdDebug(5006) << "checkFolders - " << node->name() << " disappeared" << endl;
00949 imapFld->setAlreadyRemoved( true );
00950 toRemove.append( fld );
00951 } else {
00952 kdDebug(5006) << "checkFolders - " << node->name() << " ignored" << endl;
00953 }
00954 }
00955 node = folder()->child()->next();
00956 }
00957
00958 for ( KMFolder* doomed=toRemove.first(); doomed; doomed = toRemove.next() )
00959 kmkernel->imapFolderMgr()->remove( doomed );
00960 }
00961
00962
00963 void KMFolderImap::initializeFrom( KMFolderImap* parent, QString folderPath,
00964 QString mimeType )
00965 {
00966 setAccount( parent->account() );
00967 setImapPath( folderPath );
00968 setNoContent( mimeType == "inode/directory" );
00969 setNoChildren( mimeType == "message/digest" );
00970 }
00971
00972
00973 void KMFolderImap::setChildrenState( QString attributes )
00974 {
00975
00976 if ( attributes.find( "haschildren", 0, false ) != -1 )
00977 {
00978 setHasChildren( FolderStorage::HasChildren );
00979 } else if ( attributes.find( "hasnochildren", 0, false ) != -1 ||
00980 attributes.find( "noinferiors", 0, false ) != -1 )
00981 {
00982 setHasChildren( FolderStorage::HasNoChildren );
00983 } else
00984 {
00985 if ( mAccount->listOnlyOpenFolders() ) {
00986 setHasChildren( FolderStorage::HasChildren );
00987 } else {
00988 setHasChildren( FolderStorage::ChildrenUnknown );
00989 }
00990 }
00991 }
00992
00993
00994 void KMFolderImap::checkValidity()
00995 {
00996 if (!mAccount) {
00997 emit folderComplete(this, false);
00998 close();
00999 return;
01000 }
01001 KURL url = mAccount->getUrl();
01002 url.setPath(imapPath() + ";UID=0:0");
01003 kdDebug(5006) << "KMFolderImap::checkValidity of: " << imapPath() << endl;
01004
01005
01006 disconnect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
01007 this, SLOT( checkValidity() ) );
01008
01009 KMAcctImap::ConnectionState connectionState = mAccount->makeConnection();
01010 if ( connectionState == ImapAccountBase::Error ) {
01011 kdDebug(5006) << "KMFolderImap::checkValidity - got no connection" << endl;
01012 emit folderComplete(this, FALSE);
01013 mContentState = imapNoInformation;
01014 close();
01015 return;
01016 } else if ( connectionState == ImapAccountBase::Connecting ) {
01017
01018
01019 kdDebug(5006) << "CheckValidity - waiting for connection" << endl;
01020 connect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
01021 this, SLOT( checkValidity() ) );
01022 return;
01023 }
01024
01025 if (mCheckingValidity) {
01026 kdDebug(5006) << "KMFolderImap::checkValidity - already checking" << endl;
01027 close();
01028 return;
01029 }
01030
01031 if ( !mMailCheckProgressItem ) {
01032 ProgressItem* parent = ( account()->checkingSingleFolder() ? 0 :
01033 account()->mailCheckProgressItem() );
01034 mMailCheckProgressItem = ProgressManager::createProgressItem(
01035 parent,
01036 "MailCheck" + folder()->prettyURL(),
01037 QStyleSheet::escape( folder()->prettyURL() ),
01038 i18n("checking"),
01039 false,
01040 account()->useSSL() || account()->useTLS() );
01041 } else {
01042 mMailCheckProgressItem->setProgress(0);
01043 }
01044 if ( account()->mailCheckProgressItem() ) {
01045 account()->mailCheckProgressItem()->setStatus( folder()->prettyURL() );
01046 }
01047 ImapAccountBase::jobData jd( url.url() );
01048 KIO::SimpleJob *job = KIO::get(url, FALSE, FALSE);
01049 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01050 mAccount->insertJob(job, jd);
01051 connect(job, SIGNAL(result(KIO::Job *)),
01052 SLOT(slotCheckValidityResult(KIO::Job *)));
01053 connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)),
01054 SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
01055
01056 mCheckingValidity = true;
01057 }
01058
01059
01060
01061 ulong KMFolderImap::lastUid()
01062 {
01063 if ( mLastUid > 0 )
01064 return mLastUid;
01065 open();
01066 if (count() > 0)
01067 {
01068 KMMsgBase * base = getMsgBase(count()-1);
01069 mLastUid = base->UID();
01070 }
01071 close();
01072 return mLastUid;
01073 }
01074
01075
01076
01077 void KMFolderImap::slotCheckValidityResult(KIO::Job * job)
01078 {
01079 kdDebug(5006) << "KMFolderImap::slotCheckValidityResult of: " << fileName() << endl;
01080 mCheckingValidity = false;
01081 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01082 if ( it == mAccount->jobsEnd() ) return;
01083 if (job->error()) {
01084 if ( job->error() != KIO::ERR_ACCESS_DENIED ) {
01085
01086
01087
01088 mAccount->handleJobError( job, i18n("Error while querying the server status.") );
01089 }
01090 mContentState = imapNoInformation;
01091 emit folderComplete(this, FALSE);
01092 close();
01093 } else {
01094 QCString cstr((*it).data.data(), (*it).data.size() + 1);
01095 int a = cstr.find("X-uidValidity: ");
01096 int b = cstr.find("\r\n", a);
01097 QString uidv;
01098 if ( (b - a - 15) >= 0 )
01099 uidv = cstr.mid(a + 15, b - a - 15);
01100 a = cstr.find("X-Access: ");
01101 b = cstr.find("\r\n", a);
01102 QString access;
01103 if ( (b - a - 10) >= 0 )
01104 access = cstr.mid(a + 10, b - a - 10);
01105 mReadOnly = access == "Read only";
01106 a = cstr.find("X-Count: ");
01107 b = cstr.find("\r\n", a);
01108 int exists = -1;
01109 bool ok = false;
01110 if ( (b - a - 9) >= 0 )
01111 exists = cstr.mid(a + 9, b - a - 9).toInt(&ok);
01112 if ( !ok ) exists = -1;
01113 QString startUid;
01114 if (uidValidity() != uidv)
01115 {
01116
01117 kdDebug(5006) << k_funcinfo << "uidValidty changed from "
01118 << uidValidity() << " to " << uidv << endl;
01119 if ( !uidValidity().isEmpty() )
01120 {
01121 mAccount->ignoreJobsForFolder( folder() );
01122 mUidMetaDataMap.clear();
01123 }
01124 mLastUid = 0;
01125 setUidValidity(uidv);
01126 writeConfig();
01127 } else {
01128 if (!mCheckFlags)
01129 startUid = QString::number(lastUid() + 1);
01130 }
01131 mAccount->removeJob(it);
01132 if ( mMailCheckProgressItem )
01133 {
01134 if ( startUid.isEmpty() ) {
01135
01136 mMailCheckProgressItem->setTotalItems( exists );
01137 } else {
01138
01139 int remain = exists - count();
01140 if ( remain < 0 ) remain = 1;
01141 mMailCheckProgressItem->setTotalItems( remain );
01142 }
01143 mMailCheckProgressItem->setCompletedItems( 0 );
01144 }
01145 reallyGetFolder(startUid);
01146 }
01147 }
01148
01149
01150 void KMFolderImap::getAndCheckFolder(bool force)
01151 {
01152 if (mNoContent)
01153 return getFolder(force);
01154
01155 if ( mAccount )
01156 mAccount->processNewMailSingleFolder( folder() );
01157 if (force) {
01158
01159 mCheckFlags = TRUE;
01160 }
01161 }
01162
01163
01164 void KMFolderImap::getFolder(bool force)
01165 {
01166 mGuessedUnreadMsgs = -1;
01167 if (mNoContent)
01168 {
01169 mContentState = imapFinished;
01170 emit folderComplete(this, true);
01171 return;
01172 }
01173 open();
01174 mContentState = imapListingInProgress;
01175 if (force) {
01176
01177 mCheckFlags = TRUE;
01178 }
01179 checkValidity();
01180 }
01181
01182
01183
01184 void KMFolderImap::reallyGetFolder(const QString &startUid)
01185 {
01186 KURL url = mAccount->getUrl();
01187 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01188 {
01189 mContentState = imapNoInformation;
01190 emit folderComplete(this, FALSE);
01191 close();
01192 return;
01193 }
01194 quiet(true);
01195 if (startUid.isEmpty())
01196 {
01197 if ( mMailCheckProgressItem )
01198 mMailCheckProgressItem->setStatus( i18n("Retrieving message status") );
01199 url.setPath(imapPath() + ";SECTION=UID FLAGS");
01200 KIO::SimpleJob *job = KIO::listDir(url, FALSE);
01201 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01202 ImapAccountBase::jobData jd( url.url(), folder() );
01203 jd.cancellable = true;
01204 mAccount->insertJob(job, jd);
01205 connect(job, SIGNAL(result(KIO::Job *)),
01206 this, SLOT(slotListFolderResult(KIO::Job *)));
01207 connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList &)),
01208 this, SLOT(slotListFolderEntries(KIO::Job *,
01209 const KIO::UDSEntryList &)));
01210 } else {
01211 mContentState = imapDownloadInProgress;
01212 if ( mMailCheckProgressItem )
01213 mMailCheckProgressItem->setStatus( i18n("Retrieving messages") );
01214 url.setPath(imapPath() + ";UID=" + startUid
01215 + ":*;SECTION=ENVELOPE");
01216 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
01217 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
01218 ImapAccountBase::jobData jd( url.url(), folder() );
01219 jd.cancellable = true;
01220 mAccount->insertJob(newJob, jd);
01221 connect(newJob, SIGNAL(result(KIO::Job *)),
01222 this, SLOT(slotGetLastMessagesResult(KIO::Job *)));
01223 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
01224 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
01225 }
01226 }
01227
01228
01229
01230 void KMFolderImap::slotListFolderResult(KIO::Job * job)
01231 {
01232 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01233 if ( it == mAccount->jobsEnd() ) return;
01234 QString uids;
01235 if (job->error())
01236 {
01237 mAccount->handleJobError( job,
01238 i18n("Error while listing the contents of the folder %1.").arg( label() ) );
01239 mAccount->removeJob(it);
01240 finishMailCheck( imapNoInformation );
01241 return;
01242 }
01243 mCheckFlags = FALSE;
01244 QStringList::Iterator uid;
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 if ( count() ) {
01255 int idx = 0, c, serverFlags;
01256 ulong mailUid, serverUid;
01257 uid = (*it).items.begin();
01258 while ( idx < count() && uid != (*it).items.end() ) {
01259 KMMsgBase *msgBase = getMsgBase( idx );
01260 mailUid = msgBase->UID();
01261
01262
01263 c = (*uid).find(",");
01264 serverUid = (*uid).left( c ).toLong();
01265 serverFlags = (*uid).mid( c+1 ).toInt();
01266 if ( mailUid < serverUid ) {
01267 removeMsg( idx, TRUE );
01268 } else if ( mailUid == serverUid ) {
01269
01270
01271
01272 if (!mReadOnly)
01273 flagsToStatus( msgBase, serverFlags, false );
01274 idx++;
01275 uid = (*it).items.remove(uid);
01276 if ( msgBase->getMsgSerNum() > 0 ) {
01277 saveMsgMetaData( static_cast<KMMessage*>(msgBase) );
01278 }
01279 }
01280 else break;
01281 }
01282
01283
01284 while (idx < count()) removeMsg(idx, TRUE);
01285 }
01286
01287 for (uid = (*it).items.begin(); uid != (*it).items.end(); ++uid)
01288 (*uid).truncate((*uid).find(","));
01289 ImapAccountBase::jobData jd( QString::null, (*it).parent );
01290 jd.total = (*it).items.count();
01291 if (jd.total == 0)
01292 {
01293 finishMailCheck( imapFinished );
01294 mAccount->removeJob(it);
01295 return;
01296 }
01297 if ( mMailCheckProgressItem )
01298 {
01299
01300 mMailCheckProgressItem->setCompletedItems( 0 );
01301 mMailCheckProgressItem->setTotalItems( jd.total );
01302 mMailCheckProgressItem->setProgress( 0 );
01303 mMailCheckProgressItem->setStatus( i18n("Retrieving messages") );
01304 }
01305
01306 QStringList sets;
01307 uid = (*it).items.begin();
01308 if (jd.total == 1) sets.append(*uid + ":" + *uid);
01309 else sets = makeSets( (*it).items );
01310 mAccount->removeJob(it);
01311
01312
01313 for (QStringList::Iterator i = sets.begin(); i != sets.end(); ++i)
01314 {
01315 mContentState = imapDownloadInProgress;
01316 KURL url = mAccount->getUrl();
01317 url.setPath(imapPath() + ";UID=" + *i + ";SECTION=ENVELOPE");
01318 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
01319 jd.url = url.url();
01320 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
01321 mAccount->insertJob(newJob, jd);
01322 connect(newJob, SIGNAL(result(KIO::Job *)),
01323 this, (i == sets.at(sets.count() - 1))
01324 ? SLOT(slotGetLastMessagesResult(KIO::Job *))
01325 : SLOT(slotGetMessagesResult(KIO::Job *)));
01326 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
01327 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
01328 }
01329 }
01330
01331
01332
01333 void KMFolderImap::slotListFolderEntries(KIO::Job * job,
01334 const KIO::UDSEntryList & uds)
01335 {
01336 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01337 if ( it == mAccount->jobsEnd() ) return;
01338 QString mimeType, name;
01339 long int flags = 0;
01340 for (KIO::UDSEntryList::ConstIterator udsIt = uds.begin();
01341 udsIt != uds.end(); udsIt++)
01342 {
01343 for (KIO::UDSEntry::ConstIterator eIt = (*udsIt).begin();
01344 eIt != (*udsIt).end(); eIt++)
01345 {
01346 if ((*eIt).m_uds == KIO::UDS_NAME)
01347 name = (*eIt).m_str;
01348 else if ((*eIt).m_uds == KIO::UDS_MIME_TYPE)
01349 mimeType = (*eIt).m_str;
01350 else if ((*eIt).m_uds == KIO::UDS_ACCESS)
01351 flags = (*eIt).m_long;
01352 }
01353 if ((mimeType == "message/rfc822-imap" || mimeType == "message/rfc822") &&
01354 !(flags & 8)) {
01355 (*it).items.append(name + "," + QString::number(flags));
01356 if ( mMailCheckProgressItem ) {
01357 mMailCheckProgressItem->incCompletedItems();
01358 mMailCheckProgressItem->updateProgress();
01359 }
01360 }
01361 }
01362 }
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383 void KMFolderImap::flagsToStatus(KMMsgBase *msg, int flags, bool newMsg)
01384 {
01385 const KMMsgStatus oldStatus = msg->status();
01386
01387 if ( (flags & 4) && (oldStatus & KMMsgStatusFlag) == 0 )
01388 msg->setStatus( KMMsgStatusFlag );
01389 if ( (flags & 2) && (oldStatus & KMMsgStatusReplied) == 0 )
01390 msg->setStatus( KMMsgStatusReplied );
01391 if ( (flags & 1) && (oldStatus & KMMsgStatusOld) == 0 )
01392 msg->setStatus( KMMsgStatusOld );
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405 if (msg->isOfUnknownStatus() || !(flags&1) ) {
01406 if (newMsg) {
01407 if ( (oldStatus & KMMsgStatusNew) == 0 )
01408 msg->setStatus( KMMsgStatusNew );
01409 } else {
01410 if ( (oldStatus & KMMsgStatusUnread) == 0 )
01411 msg->setStatus( KMMsgStatusUnread );
01412 }
01413 }
01414 }
01415
01416
01417
01418 QString KMFolderImap::statusToFlags(KMMsgStatus status)
01419 {
01420 QString flags;
01421 if (status & KMMsgStatusDeleted)
01422 flags = "\\DELETED";
01423 else {
01424 if (status & KMMsgStatusOld || status & KMMsgStatusRead)
01425 flags = "\\SEEN ";
01426 if (status & KMMsgStatusReplied)
01427 flags += "\\ANSWERED ";
01428 if (status & KMMsgStatusFlag)
01429 flags += "\\FLAGGED";
01430 }
01431
01432 return flags.simplifyWhiteSpace();
01433 }
01434
01435
01436 void
01437 KMFolderImap::ignoreJobsForMessage( KMMessage* msg )
01438 {
01439 if ( !msg || msg->transferInProgress() ||
01440 !msg->parent() || msg->parent()->folderType() != KMFolderTypeImap )
01441 return;
01442 KMAcctImap *account;
01443 if ( !(account = static_cast<KMFolderImap*>(msg->storage())->account()) )
01444 return;
01445
01446 account->ignoreJobsForMessage( msg );
01447 }
01448
01449
01450 void KMFolderImap::slotGetMessagesData(KIO::Job * job, const QByteArray & data)
01451 {
01452 if ( data.isEmpty() ) return;
01453 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01454 if ( it == mAccount->jobsEnd() ) return;
01455 (*it).cdata += QCString(data, data.size() + 1);
01456 int pos = (*it).cdata.find("\r\n--IMAPDIGEST");
01457 if ( pos == -1 ) {
01458
01459
01460 return;
01461 }
01462 if (pos > 0)
01463 {
01464 int p = (*it).cdata.find("\r\nX-uidValidity:");
01465 if (p != -1) setUidValidity((*it).cdata
01466 .mid(p + 17, (*it).cdata.find("\r\n", p+1) - p - 17));
01467 int c = (*it).cdata.find("\r\nX-Count:");
01468 if ( c != -1 )
01469 {
01470 bool ok;
01471 int exists = (*it).cdata.mid( c+10,
01472 (*it).cdata.find("\r\n", c+1) - c-10 ).toInt(&ok);
01473 if ( ok && exists < count() ) {
01474 kdDebug(5006) << "KMFolderImap::slotGetMessagesData - server has less messages (" <<
01475 exists << ") then folder (" << count() << "), so reload" << endl;
01476 open();
01477 reallyGetFolder( QString::null );
01478 (*it).cdata.remove(0, pos);
01479 return;
01480 } else if ( ok ) {
01481 int delta = exists - count();
01482 if ( mMailCheckProgressItem ) {
01483 mMailCheckProgressItem->setTotalItems( delta );
01484 }
01485 }
01486 }
01487 (*it).cdata.remove(0, pos);
01488 }
01489 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
01490 int flags;
01491 while (pos >= 0)
01492 {
01493 KMMessage *msg = new KMMessage;
01494 msg->setComplete( false );
01495 msg->setReadyToShow( false );
01496
01497 if ( pos != 14 ) {
01498 msg->fromString( (*it).cdata.mid(16, pos - 16) );
01499 flags = msg->headerField("X-Flags").toInt();
01500 ulong uid = msg->UID();
01501 KMMsgMetaData *md = 0;
01502 if ( mUidMetaDataMap.find( uid ) ) {
01503 md = mUidMetaDataMap[uid];
01504 }
01505 ulong serNum = 0;
01506 if ( md ) {
01507 serNum = md->serNum();
01508 }
01509 bool ok = true;
01510 if ( uid <= lastUid() && serNum > 0 ) {
01511
01512 ok = false;
01513 }
01514
01515 if ( flags & 8 )
01516 ok = false;
01517 if ( !ok ) {
01518 delete msg;
01519 msg = 0;
01520 } else {
01521 if ( serNum > 0 ) {
01522
01523 msg->setMsgSerNum( serNum );
01524 }
01525
01526 if ( md ) {
01527 msg->setStatus( md->status() );
01528 } else if ( !mAccount->hasCapability("uidplus") ) {
01529
01530
01531 QString id = msg->msgIdMD5();
01532 if ( mMetaDataMap.find( id ) ) {
01533 md = mMetaDataMap[id];
01534 msg->setStatus( md->status() );
01535 if ( md->serNum() != 0 && serNum == 0 ) {
01536 msg->setMsgSerNum( md->serNum() );
01537 }
01538 mMetaDataMap.remove( id );
01539 delete md;
01540 }
01541 }
01542 KMFolderMbox::addMsg(msg, 0);
01543
01544 flagsToStatus((KMMsgBase*)msg, flags);
01545
01546 msg->setMsgSizeServer( msg->headerField("X-Length").toUInt() );
01547 msg->setUID(uid);
01548 if ( msg->getMsgSerNum() > 0 ) {
01549 saveMsgMetaData( msg );
01550 }
01551
01552 if ( folder()->isSystemFolder() && imapPath() == "/INBOX/"
01553 && kmkernel->filterMgr()->atLeastOneIncomingFilterAppliesTo( mAccount->id() ) )
01554 mAccount->execFilters( msg->getMsgSerNum() );
01555
01556 if ( count() > 1 ) {
01557 unGetMsg(count() - 1);
01558 }
01559 mLastUid = uid;
01560 if ( mMailCheckProgressItem ) {
01561 mMailCheckProgressItem->incCompletedItems();
01562 mMailCheckProgressItem->updateProgress();
01563 }
01564 }
01565 }
01566 (*it).cdata.remove(0, pos);
01567 (*it).done++;
01568 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
01569 }
01570 }
01571
01572
01573 FolderJob*
01574 KMFolderImap::doCreateJob( KMMessage *msg, FolderJob::JobType jt,
01575 KMFolder *folder, QString partSpecifier,
01576 const AttachmentStrategy *as ) const
01577 {
01578 KMFolderImap* kmfi = folder? dynamic_cast<KMFolderImap*>(folder->storage()) : 0;
01579 if ( jt == FolderJob::tGetMessage && partSpecifier == "STRUCTURE" &&
01580 mAccount && mAccount->loadOnDemand() &&
01581 ( msg->msgSizeServer() > 5000 || msg->msgSizeServer() == 0 ) &&
01582 ( msg->signatureState() == KMMsgNotSigned ||
01583 msg->signatureState() == KMMsgSignatureStateUnknown ) &&
01584 ( msg->encryptionState() == KMMsgNotEncrypted ||
01585 msg->encryptionState() == KMMsgEncryptionStateUnknown ) )
01586 {
01587
01588
01589 ImapJob *job = new ImapJob( msg, jt, kmfi, "HEADER" );
01590 job->start();
01591 ImapJob *job2 = new ImapJob( msg, jt, kmfi, "STRUCTURE", as );
01592 job2->start();
01593 job->setParentFolder( this );
01594 return job;
01595 } else {
01596
01597 if ( partSpecifier == "STRUCTURE" )
01598 partSpecifier = QString::null;
01599
01600 ImapJob *job = new ImapJob( msg, jt, kmfi, partSpecifier );
01601 job->setParentFolder( this );
01602 return job;
01603 }
01604 }
01605
01606
01607 FolderJob*
01608 KMFolderImap::doCreateJob( QPtrList<KMMessage>& msgList, const QString& sets,
01609 FolderJob::JobType jt, KMFolder *folder ) const
01610 {
01611 KMFolderImap* kmfi = dynamic_cast<KMFolderImap*>(folder->storage());
01612 ImapJob *job = new ImapJob( msgList, sets, jt, kmfi );
01613 job->setParentFolder( this );
01614 return job;
01615 }
01616
01617
01618 void KMFolderImap::getMessagesResult(KIO::Job * job, bool lastSet)
01619 {
01620 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01621 if ( it == mAccount->jobsEnd() ) return;
01622 if (job->error()) {
01623 mAccount->handleJobError( job, i18n("Error while retrieving messages.") );
01624 finishMailCheck( imapNoInformation );
01625 return;
01626 }
01627 if (lastSet) {
01628 finishMailCheck( imapFinished );
01629 mAccount->removeJob(it);
01630 }
01631 }
01632
01633
01634
01635 void KMFolderImap::slotGetLastMessagesResult(KIO::Job * job)
01636 {
01637 getMessagesResult(job, true);
01638 }
01639
01640
01641
01642 void KMFolderImap::slotGetMessagesResult(KIO::Job * job)
01643 {
01644 getMessagesResult(job, false);
01645 }
01646
01647
01648
01649 void KMFolderImap::createFolder(const QString &name, const QString& parentPath,
01650 bool askUser)
01651 {
01652 kdDebug(5006) << "KMFolderImap::createFolder - name=" << name << ",parent=" <<
01653 parentPath << ",askUser=" << askUser << endl;
01654 if ( mAccount->makeConnection() != ImapAccountBase::Connected ) {
01655 kdWarning(5006) << "KMFolderImap::createFolder - got no connection" << endl;
01656 return;
01657 }
01658 KURL url = mAccount->getUrl();
01659 QString parent = ( parentPath.isEmpty() ? imapPath() : parentPath );
01660 QString path = mAccount->createImapPath( parent, name );
01661 if ( askUser ) {
01662 path += "/;INFO=ASKUSER";
01663 }
01664 url.setPath( path );
01665
01666 KIO::SimpleJob *job = KIO::mkdir(url);
01667 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01668 ImapAccountBase::jobData jd( url.url(), folder() );
01669 jd.items = name;
01670 mAccount->insertJob(job, jd);
01671 connect(job, SIGNAL(result(KIO::Job *)),
01672 this, SLOT(slotCreateFolderResult(KIO::Job *)));
01673 }
01674
01675
01676
01677 void KMFolderImap::slotCreateFolderResult(KIO::Job * job)
01678 {
01679 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01680 if ( it == mAccount->jobsEnd() ) return;
01681 if (job->error())
01682 {
01683 if ( job->error() == KIO::ERR_COULD_NOT_MKDIR ) {
01684
01685 mAccount->listDirectory( );
01686 }
01687 mAccount->handleJobError( job, i18n("Error while creating a folder.") );
01688 } else {
01689 listDirectory();
01690 mAccount->removeJob(job);
01691 }
01692 }
01693
01694
01695
01696 static QTextCodec *sUtf7Codec = 0;
01697
01698 QTextCodec * KMFolderImap::utf7Codec()
01699 {
01700 if (!sUtf7Codec) sUtf7Codec = QTextCodec::codecForName("utf-7");
01701 return sUtf7Codec;
01702 }
01703
01704
01705
01706 QString KMFolderImap::encodeFileName(const QString &name)
01707 {
01708 QString result = utf7Codec()->fromUnicode(name);
01709 return KURL::encode_string_no_slash(result);
01710 }
01711
01712
01713
01714 QString KMFolderImap::decodeFileName(const QString &name)
01715 {
01716 QString result = KURL::decode_string(name);
01717 return utf7Codec()->toUnicode(result.latin1());
01718 }
01719
01720
01721 bool KMFolderImap::autoExpunge()
01722 {
01723 if (mAccount)
01724 return mAccount->autoExpunge();
01725
01726 return false;
01727 }
01728
01729
01730
01731 void KMFolderImap::slotSimpleData(KIO::Job * job, const QByteArray & data)
01732 {
01733 if ( data.isEmpty() ) return;
01734 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01735 if ( it == mAccount->jobsEnd() ) return;
01736 QBuffer buff((*it).data);
01737 buff.open(IO_WriteOnly | IO_Append);
01738 buff.writeBlock(data.data(), data.size());
01739 buff.close();
01740 }
01741
01742
01743 void KMFolderImap::deleteMessage(KMMessage * msg)
01744 {
01745 mUidMetaDataMap.remove( msg->UID() );
01746 mMetaDataMap.remove( msg->msgIdMD5() );
01747 KURL url = mAccount->getUrl();
01748 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msg->storage());
01749 ulong uid = msg->UID();
01750
01751
01752
01753 if ( uid == 0 ) {
01754 kdDebug( 5006 ) << "KMFolderImap::deleteMessage: Attempt to delete "
01755 "an empty UID. Aborting." << endl;
01756 return;
01757 }
01758 url.setPath(msg_parent->imapPath() + ";UID=" + QString::number(uid) );
01759 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01760 return;
01761 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01762 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01763 ImapAccountBase::jobData jd( url.url(), 0 );
01764 mAccount->insertJob(job, jd);
01765 connect(job, SIGNAL(result(KIO::Job *)),
01766 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01767 }
01768
01769 void KMFolderImap::deleteMessage(const QPtrList<KMMessage>& msgList)
01770 {
01771 QPtrListIterator<KMMessage> it( msgList );
01772 KMMessage *msg;
01773 while ( (msg = it.current()) != 0 ) {
01774 ++it;
01775 mUidMetaDataMap.remove( msg->UID() );
01776 mMetaDataMap.remove( msg->msgIdMD5() );
01777 }
01778
01779 QValueList<ulong> uids;
01780 getUids(msgList, uids);
01781 QStringList sets = makeSets(uids);
01782
01783 KURL url = mAccount->getUrl();
01784 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msgList.getFirst()->storage());
01785 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
01786 {
01787 QString uid = *it;
01788
01789
01790 if ( uid.isEmpty() ) continue;
01791 url.setPath(msg_parent->imapPath() + ";UID=" + uid);
01792 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01793 return;
01794 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01795 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01796 ImapAccountBase::jobData jd( url.url(), 0 );
01797 mAccount->insertJob(job, jd);
01798 connect(job, SIGNAL(result(KIO::Job *)),
01799 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01800 }
01801 }
01802
01803
01804 void KMFolderImap::setStatus(int idx, KMMsgStatus status, bool toggle)
01805 {
01806 QValueList<int> ids; ids.append(idx);
01807 setStatus(ids, status, toggle);
01808 }
01809
01810 void KMFolderImap::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle)
01811 {
01812 FolderStorage::setStatus(ids, status, toggle);
01813 if (mReadOnly) return;
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825 QMap< QString, QStringList > groups;
01826 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it ) {
01827 KMMessage *msg = 0;
01828 bool unget = !isMessage(*it);
01829 msg = getMsg(*it);
01830 if (!msg) continue;
01831 QString flags = statusToFlags(msg->status());
01832
01833 groups[flags].append(QString::number(msg->UID()));
01834 if (unget) unGetMsg(*it);
01835 }
01836 QMapIterator< QString, QStringList > dit;
01837 for ( dit = groups.begin(); dit != groups.end(); ++dit ) {
01838 QCString flags = dit.key().latin1();
01839 QStringList sets = makeSets( (*dit), true );
01840
01841 for ( QStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
01842 QString imappath = imapPath() + ";UID=" + ( *slit );
01843 mAccount->setImapStatus(folder(), imappath, flags);
01844 }
01845 }
01846 if ( mContentState == imapListingInProgress ) {
01847
01848
01849
01850 kdDebug(5006) << "Set status during folder listing, restarting listing." << endl;
01851 disconnect(this, SLOT(slotListFolderResult(KIO::Job *)));
01852 quiet( false );
01853 reallyGetFolder( QString::null );
01854 }
01855 }
01856
01857
01858 QStringList KMFolderImap::makeSets(const QStringList& uids, bool sort)
01859 {
01860 QValueList<ulong> tmp;
01861 for ( QStringList::ConstIterator it = uids.begin(); it != uids.end(); ++it )
01862 tmp.append( (*it).toInt() );
01863 return makeSets(tmp, sort);
01864 }
01865
01866 QStringList KMFolderImap::makeSets( QValueList<ulong>& uids, bool sort )
01867 {
01868 QStringList sets;
01869 QString set;
01870
01871 if (uids.size() == 1)
01872 {
01873 sets.append(QString::number(uids.first()));
01874 return sets;
01875 }
01876
01877 if (sort) qHeapSort(uids);
01878
01879 ulong last = 0;
01880
01881 bool inserted = false;
01882
01883 for ( QValueList<ulong>::Iterator it = uids.begin(); it != uids.end(); ++it )
01884 {
01885 if (it == uids.begin() || set.isEmpty()) {
01886 set = QString::number(*it);
01887 inserted = true;
01888 } else
01889 {
01890 if (last+1 != *it)
01891 {
01892
01893 if (inserted)
01894 set += ',' + QString::number(*it);
01895 else
01896 set += ':' + QString::number(last) + ',' + QString::number(*it);
01897 inserted = true;
01898 if (set.length() > 100)
01899 {
01900
01901 sets.append(set);
01902 set = "";
01903 }
01904 } else {
01905 inserted = false;
01906 }
01907 }
01908 last = *it;
01909 }
01910
01911 if (!inserted)
01912 set += ':' + QString::number(uids.last());
01913
01914 if (!set.isEmpty()) sets.append(set);
01915
01916 return sets;
01917 }
01918
01919
01920 void KMFolderImap::getUids(QValueList<int>& ids, QValueList<ulong>& uids)
01921 {
01922 KMMsgBase *msg = 0;
01923
01924 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01925 {
01926 msg = getMsgBase(*it);
01927 if (!msg) continue;
01928 uids.append(msg->UID());
01929 }
01930 }
01931
01932 void KMFolderImap::getUids(const QPtrList<KMMessage>& msgList, QValueList<ulong>& uids)
01933 {
01934 KMMessage *msg = 0;
01935
01936 QPtrListIterator<KMMessage> it( msgList );
01937 while ( (msg = it.current()) != 0 ) {
01938 ++it;
01939 if ( msg->UID() > 0 ) {
01940 uids.append( msg->UID() );
01941 }
01942 }
01943 }
01944
01945
01946 void KMFolderImap::expungeFolder(KMFolderImap * aFolder, bool quiet)
01947 {
01948 aFolder->setNeedsCompacting(FALSE);
01949 KURL url = mAccount->getUrl();
01950 url.setPath(aFolder->imapPath() + ";UID=*");
01951 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01952 return;
01953 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01954 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01955 ImapAccountBase::jobData jd( url.url(), 0 );
01956 jd.quiet = quiet;
01957 mAccount->insertJob(job, jd);
01958 connect(job, SIGNAL(result(KIO::Job *)),
01959 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01960 }
01961
01962
01963 void KMFolderImap::slotProcessNewMail( int errorCode, const QString &errorMsg )
01964 {
01965 Q_UNUSED( errorMsg );
01966 disconnect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
01967 this, SLOT( slotProcessNewMail(int, const QString&) ) );
01968 if ( !errorCode )
01969 processNewMail( false );
01970 else
01971 emit numUnreadMsgsChanged( folder() );
01972 }
01973
01974
01975 bool KMFolderImap::processNewMail(bool)
01976 {
01977
01978 if ( !mAccount ) {
01979 kdDebug(5006) << "KMFolderImap::processNewMail - account is null!" << endl;
01980 return false;
01981 }
01982 if ( imapPath().isEmpty() ) {
01983 kdDebug(5006) << "KMFolderImap::processNewMail - imapPath of " << name() << " is empty!" << endl;
01984
01985 setAlreadyRemoved( true );
01986 kmkernel->imapFolderMgr()->remove( folder() );
01987 return false;
01988 }
01989
01990 if ( mAccount->makeConnection() == ImapAccountBase::Error ) {
01991 kdDebug(5006) << "KMFolderImap::processNewMail - got no connection!" << endl;
01992 return false;
01993 } else if ( mAccount->makeConnection() == ImapAccountBase::Connecting )
01994 {
01995
01996 kdDebug(5006) << "KMFolderImap::processNewMail - waiting for connection: " << label() << endl;
01997 connect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
01998 this, SLOT( slotProcessNewMail(int, const QString&) ) );
01999 return true;
02000 }
02001 KURL url = mAccount->getUrl();
02002 if (mReadOnly)
02003 url.setPath(imapPath() + ";SECTION=UIDNEXT");
02004 else
02005 url.setPath(imapPath() + ";SECTION=UNSEEN");
02006
02007 mMailCheckProgressItem = ProgressManager::createProgressItem(
02008 "MailCheckAccount" + account()->name(),
02009 "MailCheck" + folder()->prettyURL(),
02010 QStyleSheet::escape( folder()->prettyURL() ),
02011 i18n("updating message counts"),
02012 false,
02013 account()->useSSL() || account()->useTLS() );
02014
02015 KIO::SimpleJob *job = KIO::stat(url, FALSE);
02016 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
02017 ImapAccountBase::jobData jd(url.url(), folder() );
02018 jd.cancellable = true;
02019 mAccount->insertJob(job, jd);
02020 connect(job, SIGNAL(result(KIO::Job *)),
02021 SLOT(slotStatResult(KIO::Job *)));
02022 return true;
02023 }
02024
02025
02026
02027 void KMFolderImap::slotStatResult(KIO::Job * job)
02028 {
02029 slotCompleteMailCheckProgress();
02030 ImapAccountBase::JobIterator it = mAccount->findJob(job);
02031 if ( it == mAccount->jobsEnd() ) return;
02032 mAccount->removeJob(it);
02033 if (job->error())
02034 {
02035 mAccount->handleJobError( job, i18n("Error while getting folder information.") );
02036 } else {
02037 KIO::UDSEntry uds = static_cast<KIO::StatJob*>(job)->statResult();
02038 for (KIO::UDSEntry::ConstIterator it = uds.begin(); it != uds.end(); it++)
02039 {
02040 if ((*it).m_uds == KIO::UDS_SIZE)
02041 {
02042 if (mReadOnly)
02043 {
02044 mGuessedUnreadMsgs = -1;
02045 mGuessedUnreadMsgs = countUnread() + (*it).m_long - lastUid() - 1;
02046 if (mGuessedUnreadMsgs < 0) mGuessedUnreadMsgs = 0;
02047 } else {
02048 mGuessedUnreadMsgs = (*it).m_long;
02049 }
02050 }
02051 }
02052 }
02053 }
02054
02055
02056 int KMFolderImap::create()
02057 {
02058 readConfig();
02059 mUnreadMsgs = -1;
02060 return KMFolderMbox::create();
02061 }
02062
02063 QValueList<ulong> KMFolderImap::splitSets(const QString uids)
02064 {
02065 QValueList<ulong> uidlist;
02066
02067
02068 QString buffer = QString::null;
02069 int setstart = -1;
02070
02071 for (uint i = 0; i < uids.length(); i++)
02072 {
02073 QChar chr = uids[i];
02074 if (chr == ',')
02075 {
02076 if (setstart > -1)
02077 {
02078
02079 for (int j = setstart; j <= buffer.toInt(); j++)
02080 {
02081 uidlist.append(j);
02082 }
02083 setstart = -1;
02084 } else {
02085
02086 uidlist.append(buffer.toInt());
02087 }
02088 buffer = "";
02089 } else if (chr == ':') {
02090
02091 setstart = buffer.toInt();
02092 buffer = "";
02093 } else if (chr.category() == QChar::Number_DecimalDigit) {
02094
02095 buffer += chr;
02096 } else {
02097
02098 }
02099 }
02100
02101 if (setstart > -1)
02102 {
02103 for (int j = setstart; j <= buffer.toInt(); j++)
02104 {
02105 uidlist.append(j);
02106 }
02107 } else {
02108 uidlist.append(buffer.toInt());
02109 }
02110
02111 return uidlist;
02112 }
02113
02114
02115 int KMFolderImap::expungeContents()
02116 {
02117
02118 int rc = KMFolderMbox::expungeContents();
02119
02120
02121 KURL url = mAccount->getUrl();
02122 url.setPath( imapPath() + ";UID=1:*");
02123 if ( mAccount->makeConnection() == ImapAccountBase::Connected )
02124 {
02125 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
02126 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
02127 ImapAccountBase::jobData jd( url.url(), 0 );
02128 jd.quiet = true;
02129 mAccount->insertJob(job, jd);
02130 connect(job, SIGNAL(result(KIO::Job *)),
02131 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
02132 }
02133
02134
02135
02136
02137 expungeFolder(this, true);
02138 getFolder();
02139
02140 return rc;
02141 }
02142
02143
02144 void
02145 KMFolderImap::setUserRights( unsigned int userRights )
02146 {
02147 mUserRights = userRights;
02148 kdDebug(5006) << imapPath() << " setUserRights: " << userRights << endl;
02149 }
02150
02151
02152 void KMFolderImap::slotCompleteMailCheckProgress()
02153 {
02154 if ( mMailCheckProgressItem ) {
02155 mMailCheckProgressItem->setComplete();
02156 mMailCheckProgressItem = 0;
02157 emit numUnreadMsgsChanged( folder() );
02158 }
02159 }
02160
02161
02162 void KMFolderImap::setSubfolderState( imapState state )
02163 {
02164 mSubfolderState = state;
02165 if ( state == imapNoInformation && folder()->child() )
02166 {
02167
02168 KMFolderNode* node;
02169 QPtrListIterator<KMFolderNode> it( *folder()->child() );
02170 for ( ; (node = it.current()); )
02171 {
02172 ++it;
02173 if (node->isDir()) continue;
02174 KMFolder *folder = static_cast<KMFolder*>(node);
02175 static_cast<KMFolderImap*>(folder->storage())->setSubfolderState( state );
02176 }
02177 }
02178 }
02179
02180
02181 void KMFolderImap::setIncludeInMailCheck( bool check )
02182 {
02183 bool changed = ( mCheckMail != check );
02184 mCheckMail = check;
02185 if ( changed )
02186 account()->slotUpdateFolderList();
02187 }
02188
02189
02190 void KMFolderImap::setAlreadyRemoved( bool removed )
02191 {
02192 mAlreadyRemoved = removed;
02193 if ( folder()->child() )
02194 {
02195
02196 KMFolderNode* node;
02197 QPtrListIterator<KMFolderNode> it( *folder()->child() );
02198 for ( ; (node = it.current()); )
02199 {
02200 ++it;
02201 if (node->isDir()) continue;
02202 KMFolder *folder = static_cast<KMFolder*>(node);
02203 static_cast<KMFolderImap*>(folder->storage())->setAlreadyRemoved( removed );
02204 }
02205 }
02206 }
02207
02208 void KMFolderImap::slotCreatePendingFolders( int errorCode, const QString& errorMsg )
02209 {
02210 Q_UNUSED( errorMsg );
02211 disconnect( mAccount, SIGNAL( connectionResult( int, const QString& ) ),
02212 this, SLOT( slotCreatePendingFolders( int, const QString& ) ) );
02213 if ( !errorCode ) {
02214 QStringList::Iterator it = mFoldersPendingCreation.begin();
02215 for ( ; it != mFoldersPendingCreation.end(); ++it ) {
02216 createFolder( *it );
02217 }
02218 }
02219 mFoldersPendingCreation.clear();
02220 }
02221
02222
02223 void KMFolderImap::search( const KMSearchPattern* pattern )
02224 {
02225 if ( !pattern || pattern->isEmpty() )
02226 {
02227
02228 QValueList<Q_UINT32> serNums;
02229 emit searchResult( folder(), serNums, pattern, true );
02230 return;
02231 }
02232 SearchJob* job = new SearchJob( this, mAccount, pattern );
02233 connect( job, SIGNAL( searchDone( QValueList<Q_UINT32>, const KMSearchPattern*, bool ) ),
02234 this, SLOT( slotSearchDone( QValueList<Q_UINT32>, const KMSearchPattern*, bool ) ) );
02235 job->start();
02236 }
02237
02238
02239 void KMFolderImap::slotSearchDone( QValueList<Q_UINT32> serNums,
02240 const KMSearchPattern* pattern,
02241 bool complete )
02242 {
02243 emit searchResult( folder(), serNums, pattern, complete );
02244 }
02245
02246
02247 void KMFolderImap::search( const KMSearchPattern* pattern, Q_UINT32 serNum )
02248 {
02249 if ( !pattern || pattern->isEmpty() )
02250 {
02251
02252 emit searchDone( folder(), serNum, pattern, false );
02253 return;
02254 }
02255 SearchJob* job = new SearchJob( this, mAccount, pattern, serNum );
02256 connect( job, SIGNAL( searchDone( Q_UINT32, const KMSearchPattern*, bool ) ),
02257 this, SLOT( slotSearchDone( Q_UINT32, const KMSearchPattern*, bool ) ) );
02258 job->start();
02259 }
02260
02261
02262 void KMFolderImap::slotSearchDone( Q_UINT32 serNum, const KMSearchPattern* pattern,
02263 bool matches )
02264 {
02265 emit searchDone( folder(), serNum, pattern, matches );
02266 }
02267
02268
02269 bool KMFolderImap::isMoveable() const
02270 {
02271 return ( hasChildren() == HasNoChildren &&
02272 !folder()->isSystemFolder() ) ? true : false;
02273 }
02274
02275
02276 const ulong KMFolderImap::serNumForUID( ulong uid )
02277 {
02278 if ( mUidMetaDataMap.find( uid ) ) {
02279 KMMsgMetaData *md = mUidMetaDataMap[uid];
02280 return md->serNum();
02281 } else {
02282 kdDebug(5006) << "serNumForUID: unknown uid " << uid << endl;
02283 return 0;
02284 }
02285 }
02286
02287
02288 void KMFolderImap::saveMsgMetaData( KMMessage* msg, ulong uid )
02289 {
02290 if ( uid == 0 ) {
02291 uid = msg->UID();
02292 }
02293 ulong serNum = msg->getMsgSerNum();
02294 mUidMetaDataMap.replace( uid, new KMMsgMetaData(msg->status(), serNum) );
02295 }
02296
02297
02298 void KMFolderImap::setImapPath( const QString& path )
02299 {
02300 if ( path.isEmpty() ) {
02301 kdWarning(5006) << k_funcinfo << "ignoring empty path" << endl;
02302 } else {
02303 mImapPath = path;
02304 }
02305 }
02306
02307 void KMFolderImap::finishMailCheck( imapState state )
02308 {
02309 quiet( false );
02310 mContentState = state;
02311 emit folderComplete( this, mContentState == imapFinished );
02312 close();
02313 }
02314
02315 #include "kmfolderimap.moc"