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 if (!folder()->child())
00923 return;
00924 KMFolderNode *node = folder()->child()->first();
00925 while ( node )
00926 {
00927 if ( !node->isDir() && subfolderNames.findIndex(node->name()) == -1 )
00928 {
00929 KMFolder* fld = static_cast<KMFolder*>(node);
00930 KMFolderImap* imapFld = static_cast<KMFolderImap*>( fld->storage() );
00931
00932
00933 bool isInNamespace = ( myNamespace.isEmpty() ||
00934 myNamespace == mAccount->namespaceForFolder( imapFld ) );
00935 kdDebug(5006) << node->name() << " in namespace " << myNamespace << ":" <<
00936 isInNamespace << endl;
00937
00938 QString name = node->name();
00939 bool ignore = ( ( this == mAccount->rootFolder() ) &&
00940 ( imapFld->imapPath() == "/INBOX/" ||
00941 mAccount->isNamespaceFolder( name ) ||
00942 !isInNamespace ) );
00943
00944 if ( imapFld->imapPath().isEmpty() ) {
00945 ignore = false;
00946 }
00947 if ( !ignore )
00948 {
00949
00950 kdDebug(5006) << "checkFolders - " << node->name() << " disappeared" << endl;
00951 imapFld->setAlreadyRemoved( true );
00952 toRemove.append( fld );
00953 } else {
00954 kdDebug(5006) << "checkFolders - " << node->name() << " ignored" << endl;
00955 }
00956 }
00957 node = folder()->child()->next();
00958 }
00959
00960 for ( KMFolder* doomed=toRemove.first(); doomed; doomed = toRemove.next() )
00961 kmkernel->imapFolderMgr()->remove( doomed );
00962 }
00963
00964
00965 void KMFolderImap::initializeFrom( KMFolderImap* parent, QString folderPath,
00966 QString mimeType )
00967 {
00968 setAccount( parent->account() );
00969 setImapPath( folderPath );
00970 setNoContent( mimeType == "inode/directory" );
00971 setNoChildren( mimeType == "message/digest" );
00972 }
00973
00974
00975 void KMFolderImap::setChildrenState( QString attributes )
00976 {
00977
00978 if ( attributes.find( "haschildren", 0, false ) != -1 )
00979 {
00980 setHasChildren( FolderStorage::HasChildren );
00981 } else if ( attributes.find( "hasnochildren", 0, false ) != -1 ||
00982 attributes.find( "noinferiors", 0, false ) != -1 )
00983 {
00984 setHasChildren( FolderStorage::HasNoChildren );
00985 } else
00986 {
00987 if ( mAccount->listOnlyOpenFolders() ) {
00988 setHasChildren( FolderStorage::HasChildren );
00989 } else {
00990 setHasChildren( FolderStorage::ChildrenUnknown );
00991 }
00992 }
00993 }
00994
00995
00996 void KMFolderImap::checkValidity()
00997 {
00998 if (!mAccount) {
00999 emit folderComplete(this, false);
01000 close();
01001 return;
01002 }
01003 KURL url = mAccount->getUrl();
01004 url.setPath(imapPath() + ";UID=0:0");
01005 kdDebug(5006) << "KMFolderImap::checkValidity of: " << imapPath() << endl;
01006
01007
01008 disconnect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
01009 this, SLOT( checkValidity() ) );
01010
01011 KMAcctImap::ConnectionState connectionState = mAccount->makeConnection();
01012 if ( connectionState == ImapAccountBase::Error ) {
01013 kdDebug(5006) << "KMFolderImap::checkValidity - got no connection" << endl;
01014 emit folderComplete(this, FALSE);
01015 mContentState = imapNoInformation;
01016 close();
01017 return;
01018 } else if ( connectionState == ImapAccountBase::Connecting ) {
01019
01020
01021 kdDebug(5006) << "CheckValidity - waiting for connection" << endl;
01022 connect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
01023 this, SLOT( checkValidity() ) );
01024 return;
01025 }
01026
01027 if (mCheckingValidity) {
01028 kdDebug(5006) << "KMFolderImap::checkValidity - already checking" << endl;
01029 close();
01030 return;
01031 }
01032
01033 if ( !mMailCheckProgressItem ) {
01034 ProgressItem* parent = ( account()->checkingSingleFolder() ? 0 :
01035 account()->mailCheckProgressItem() );
01036 mMailCheckProgressItem = ProgressManager::createProgressItem(
01037 parent,
01038 "MailCheck" + folder()->prettyURL(),
01039 QStyleSheet::escape( folder()->prettyURL() ),
01040 i18n("checking"),
01041 false,
01042 account()->useSSL() || account()->useTLS() );
01043 } else {
01044 mMailCheckProgressItem->setProgress(0);
01045 }
01046 if ( account()->mailCheckProgressItem() ) {
01047 account()->mailCheckProgressItem()->setStatus( folder()->prettyURL() );
01048 }
01049 ImapAccountBase::jobData jd( url.url() );
01050 KIO::SimpleJob *job = KIO::get(url, FALSE, FALSE);
01051 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01052 mAccount->insertJob(job, jd);
01053 connect(job, SIGNAL(result(KIO::Job *)),
01054 SLOT(slotCheckValidityResult(KIO::Job *)));
01055 connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)),
01056 SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
01057
01058 mCheckingValidity = true;
01059 }
01060
01061
01062
01063 ulong KMFolderImap::lastUid()
01064 {
01065 if ( mLastUid > 0 )
01066 return mLastUid;
01067 open();
01068 if (count() > 0)
01069 {
01070 KMMsgBase * base = getMsgBase(count()-1);
01071 mLastUid = base->UID();
01072 }
01073 close();
01074 return mLastUid;
01075 }
01076
01077
01078
01079 void KMFolderImap::slotCheckValidityResult(KIO::Job * job)
01080 {
01081 kdDebug(5006) << "KMFolderImap::slotCheckValidityResult of: " << fileName() << endl;
01082 mCheckingValidity = false;
01083 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01084 if ( it == mAccount->jobsEnd() ) return;
01085 if (job->error()) {
01086 if ( job->error() != KIO::ERR_ACCESS_DENIED ) {
01087
01088
01089
01090 mAccount->handleJobError( job, i18n("Error while querying the server status.") );
01091 }
01092 mContentState = imapNoInformation;
01093 emit folderComplete(this, FALSE);
01094 close();
01095 } else {
01096 QCString cstr((*it).data.data(), (*it).data.size() + 1);
01097 int a = cstr.find("X-uidValidity: ");
01098 int b = cstr.find("\r\n", a);
01099 QString uidv;
01100 if ( (b - a - 15) >= 0 )
01101 uidv = cstr.mid(a + 15, b - a - 15);
01102 a = cstr.find("X-Access: ");
01103 b = cstr.find("\r\n", a);
01104 QString access;
01105 if ( (b - a - 10) >= 0 )
01106 access = cstr.mid(a + 10, b - a - 10);
01107 mReadOnly = access == "Read only";
01108 a = cstr.find("X-Count: ");
01109 b = cstr.find("\r\n", a);
01110 int exists = -1;
01111 bool ok = false;
01112 if ( (b - a - 9) >= 0 )
01113 exists = cstr.mid(a + 9, b - a - 9).toInt(&ok);
01114 if ( !ok ) exists = -1;
01115 QString startUid;
01116 if (uidValidity() != uidv)
01117 {
01118
01119 kdDebug(5006) << k_funcinfo << "uidValidty changed from "
01120 << uidValidity() << " to " << uidv << endl;
01121 if ( !uidValidity().isEmpty() )
01122 {
01123 mAccount->ignoreJobsForFolder( folder() );
01124 mUidMetaDataMap.clear();
01125 }
01126 mLastUid = 0;
01127 setUidValidity(uidv);
01128 writeConfig();
01129 } else {
01130 if (!mCheckFlags)
01131 startUid = QString::number(lastUid() + 1);
01132 }
01133 mAccount->removeJob(it);
01134 if ( mMailCheckProgressItem )
01135 {
01136 if ( startUid.isEmpty() ) {
01137
01138 mMailCheckProgressItem->setTotalItems( exists );
01139 } else {
01140
01141 int remain = exists - count();
01142 if ( remain < 0 ) remain = 1;
01143 mMailCheckProgressItem->setTotalItems( remain );
01144 }
01145 mMailCheckProgressItem->setCompletedItems( 0 );
01146 }
01147 reallyGetFolder(startUid);
01148 }
01149 }
01150
01151
01152 void KMFolderImap::getAndCheckFolder(bool force)
01153 {
01154 if (mNoContent)
01155 return getFolder(force);
01156
01157 if ( mAccount )
01158 mAccount->processNewMailSingleFolder( folder() );
01159 if (force) {
01160
01161 mCheckFlags = TRUE;
01162 }
01163 }
01164
01165
01166 void KMFolderImap::getFolder(bool force)
01167 {
01168 mGuessedUnreadMsgs = -1;
01169 if (mNoContent)
01170 {
01171 mContentState = imapFinished;
01172 emit folderComplete(this, true);
01173 return;
01174 }
01175 open();
01176 mContentState = imapListingInProgress;
01177 if (force) {
01178
01179 mCheckFlags = TRUE;
01180 }
01181 checkValidity();
01182 }
01183
01184
01185
01186 void KMFolderImap::reallyGetFolder(const QString &startUid)
01187 {
01188 KURL url = mAccount->getUrl();
01189 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01190 {
01191 mContentState = imapNoInformation;
01192 emit folderComplete(this, FALSE);
01193 close();
01194 return;
01195 }
01196 quiet(true);
01197 if (startUid.isEmpty())
01198 {
01199 if ( mMailCheckProgressItem )
01200 mMailCheckProgressItem->setStatus( i18n("Retrieving message status") );
01201 url.setPath(imapPath() + ";SECTION=UID FLAGS");
01202 KIO::SimpleJob *job = KIO::listDir(url, FALSE);
01203 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01204 ImapAccountBase::jobData jd( url.url(), folder() );
01205 jd.cancellable = true;
01206 mAccount->insertJob(job, jd);
01207 connect(job, SIGNAL(result(KIO::Job *)),
01208 this, SLOT(slotListFolderResult(KIO::Job *)));
01209 connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList &)),
01210 this, SLOT(slotListFolderEntries(KIO::Job *,
01211 const KIO::UDSEntryList &)));
01212 } else {
01213 mContentState = imapDownloadInProgress;
01214 if ( mMailCheckProgressItem )
01215 mMailCheckProgressItem->setStatus( i18n("Retrieving messages") );
01216 url.setPath(imapPath() + ";UID=" + startUid
01217 + ":*;SECTION=ENVELOPE");
01218 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
01219 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
01220 ImapAccountBase::jobData jd( url.url(), folder() );
01221 jd.cancellable = true;
01222 mAccount->insertJob(newJob, jd);
01223 connect(newJob, SIGNAL(result(KIO::Job *)),
01224 this, SLOT(slotGetLastMessagesResult(KIO::Job *)));
01225 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
01226 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
01227 }
01228 }
01229
01230
01231
01232 void KMFolderImap::slotListFolderResult(KIO::Job * job)
01233 {
01234 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01235 if ( it == mAccount->jobsEnd() ) return;
01236 QString uids;
01237 if (job->error())
01238 {
01239 mAccount->handleJobError( job,
01240 i18n("Error while listing the contents of the folder %1.").arg( label() ) );
01241 mAccount->removeJob(it);
01242 finishMailCheck( imapNoInformation );
01243 return;
01244 }
01245 mCheckFlags = FALSE;
01246 QStringList::Iterator uid;
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 if ( count() ) {
01257 int idx = 0, c, serverFlags;
01258 ulong mailUid, serverUid;
01259 uid = (*it).items.begin();
01260 while ( idx < count() && uid != (*it).items.end() ) {
01261 KMMsgBase *msgBase = getMsgBase( idx );
01262 mailUid = msgBase->UID();
01263
01264
01265 c = (*uid).find(",");
01266 serverUid = (*uid).left( c ).toLong();
01267 serverFlags = (*uid).mid( c+1 ).toInt();
01268 if ( mailUid < serverUid ) {
01269 removeMsg( idx, TRUE );
01270 } else if ( mailUid == serverUid ) {
01271
01272
01273
01274 if (!mReadOnly)
01275 flagsToStatus( msgBase, serverFlags, false );
01276 idx++;
01277 uid = (*it).items.remove(uid);
01278 if ( msgBase->getMsgSerNum() > 0 ) {
01279 saveMsgMetaData( static_cast<KMMessage*>(msgBase) );
01280 }
01281 }
01282 else break;
01283 }
01284
01285
01286 while (idx < count()) removeMsg(idx, TRUE);
01287 }
01288
01289 for (uid = (*it).items.begin(); uid != (*it).items.end(); ++uid)
01290 (*uid).truncate((*uid).find(","));
01291 ImapAccountBase::jobData jd( QString::null, (*it).parent );
01292 jd.total = (*it).items.count();
01293 if (jd.total == 0)
01294 {
01295 finishMailCheck( imapFinished );
01296 mAccount->removeJob(it);
01297 return;
01298 }
01299 if ( mMailCheckProgressItem )
01300 {
01301
01302 mMailCheckProgressItem->setCompletedItems( 0 );
01303 mMailCheckProgressItem->setTotalItems( jd.total );
01304 mMailCheckProgressItem->setProgress( 0 );
01305 mMailCheckProgressItem->setStatus( i18n("Retrieving messages") );
01306 }
01307
01308 QStringList sets;
01309 uid = (*it).items.begin();
01310 if (jd.total == 1) sets.append(*uid + ":" + *uid);
01311 else sets = makeSets( (*it).items );
01312 mAccount->removeJob(it);
01313
01314
01315 for (QStringList::Iterator i = sets.begin(); i != sets.end(); ++i)
01316 {
01317 mContentState = imapDownloadInProgress;
01318 KURL url = mAccount->getUrl();
01319 url.setPath(imapPath() + ";UID=" + *i + ";SECTION=ENVELOPE");
01320 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
01321 jd.url = url.url();
01322 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
01323 mAccount->insertJob(newJob, jd);
01324 connect(newJob, SIGNAL(result(KIO::Job *)),
01325 this, (i == sets.at(sets.count() - 1))
01326 ? SLOT(slotGetLastMessagesResult(KIO::Job *))
01327 : SLOT(slotGetMessagesResult(KIO::Job *)));
01328 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
01329 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
01330 }
01331 }
01332
01333
01334
01335 void KMFolderImap::slotListFolderEntries(KIO::Job * job,
01336 const KIO::UDSEntryList & uds)
01337 {
01338 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01339 if ( it == mAccount->jobsEnd() ) return;
01340 QString mimeType, name;
01341 long int flags = 0;
01342 for (KIO::UDSEntryList::ConstIterator udsIt = uds.begin();
01343 udsIt != uds.end(); udsIt++)
01344 {
01345 for (KIO::UDSEntry::ConstIterator eIt = (*udsIt).begin();
01346 eIt != (*udsIt).end(); eIt++)
01347 {
01348 if ((*eIt).m_uds == KIO::UDS_NAME)
01349 name = (*eIt).m_str;
01350 else if ((*eIt).m_uds == KIO::UDS_MIME_TYPE)
01351 mimeType = (*eIt).m_str;
01352 else if ((*eIt).m_uds == KIO::UDS_ACCESS)
01353 flags = (*eIt).m_long;
01354 }
01355 if ((mimeType == "message/rfc822-imap" || mimeType == "message/rfc822") &&
01356 !(flags & 8)) {
01357 (*it).items.append(name + "," + QString::number(flags));
01358 if ( mMailCheckProgressItem ) {
01359 mMailCheckProgressItem->incCompletedItems();
01360 mMailCheckProgressItem->updateProgress();
01361 }
01362 }
01363 }
01364 }
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 void KMFolderImap::flagsToStatus(KMMsgBase *msg, int flags, bool newMsg)
01386 {
01387 if ( !msg ) return;
01388
01389 const KMMsgStatus oldStatus = msg->status();
01390
01391 if ( (flags & 4) && (oldStatus & KMMsgStatusFlag) == 0 )
01392 msg->setStatus( KMMsgStatusFlag );
01393 if ( (flags & 2) && (oldStatus & KMMsgStatusReplied) == 0 )
01394 msg->setStatus( KMMsgStatusReplied );
01395 if ( (flags & 1) && (oldStatus & KMMsgStatusOld) == 0 )
01396 msg->setStatus( KMMsgStatusOld );
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409 if (msg->isOfUnknownStatus() || !(flags&1) ) {
01410 if (newMsg) {
01411 if ( (oldStatus & KMMsgStatusNew) == 0 )
01412 msg->setStatus( KMMsgStatusNew );
01413 } else {
01414 if ( (oldStatus & KMMsgStatusUnread) == 0 )
01415 msg->setStatus( KMMsgStatusUnread );
01416 }
01417 }
01418 }
01419
01420
01421
01422 QString KMFolderImap::statusToFlags(KMMsgStatus status)
01423 {
01424 QString flags;
01425 if (status & KMMsgStatusDeleted)
01426 flags = "\\DELETED";
01427 else {
01428 if (status & KMMsgStatusOld || status & KMMsgStatusRead)
01429 flags = "\\SEEN ";
01430 if (status & KMMsgStatusReplied)
01431 flags += "\\ANSWERED ";
01432 if (status & KMMsgStatusFlag)
01433 flags += "\\FLAGGED";
01434 }
01435
01436 return flags.simplifyWhiteSpace();
01437 }
01438
01439
01440 void
01441 KMFolderImap::ignoreJobsForMessage( KMMessage* msg )
01442 {
01443 if ( !msg || msg->transferInProgress() ||
01444 !msg->parent() || msg->parent()->folderType() != KMFolderTypeImap )
01445 return;
01446 KMAcctImap *account;
01447 if ( !(account = static_cast<KMFolderImap*>(msg->storage())->account()) )
01448 return;
01449
01450 account->ignoreJobsForMessage( msg );
01451 }
01452
01453
01454 void KMFolderImap::slotGetMessagesData(KIO::Job * job, const QByteArray & data)
01455 {
01456 if ( data.isEmpty() ) return;
01457 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01458 if ( it == mAccount->jobsEnd() ) return;
01459 (*it).cdata += QCString(data, data.size() + 1);
01460 int pos = (*it).cdata.find("\r\n--IMAPDIGEST");
01461 if ( pos == -1 ) {
01462
01463
01464 return;
01465 }
01466 if (pos > 0)
01467 {
01468 int p = (*it).cdata.find("\r\nX-uidValidity:");
01469 if (p != -1) setUidValidity((*it).cdata
01470 .mid(p + 17, (*it).cdata.find("\r\n", p+1) - p - 17));
01471 int c = (*it).cdata.find("\r\nX-Count:");
01472 if ( c != -1 )
01473 {
01474 bool ok;
01475 int exists = (*it).cdata.mid( c+10,
01476 (*it).cdata.find("\r\n", c+1) - c-10 ).toInt(&ok);
01477 if ( ok && exists < count() ) {
01478 kdDebug(5006) << "KMFolderImap::slotGetMessagesData - server has less messages (" <<
01479 exists << ") then folder (" << count() << "), so reload" << endl;
01480 open();
01481 reallyGetFolder( QString::null );
01482 (*it).cdata.remove(0, pos);
01483 return;
01484 } else if ( ok ) {
01485 int delta = exists - count();
01486 if ( mMailCheckProgressItem ) {
01487 mMailCheckProgressItem->setTotalItems( delta );
01488 }
01489 }
01490 }
01491 (*it).cdata.remove(0, pos);
01492 }
01493 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
01494 int flags;
01495 while (pos >= 0)
01496 {
01497 KMMessage *msg = new KMMessage;
01498 msg->setComplete( false );
01499 msg->setReadyToShow( false );
01500
01501 if ( pos != 14 ) {
01502 msg->fromString( (*it).cdata.mid(16, pos - 16) );
01503 flags = msg->headerField("X-Flags").toInt();
01504 ulong uid = msg->UID();
01505 KMMsgMetaData *md = 0;
01506 if ( mUidMetaDataMap.find( uid ) ) {
01507 md = mUidMetaDataMap[uid];
01508 }
01509 ulong serNum = 0;
01510 if ( md ) {
01511 serNum = md->serNum();
01512 }
01513 bool ok = true;
01514 if ( uid <= lastUid() && serNum > 0 ) {
01515
01516 ok = false;
01517 }
01518
01519 if ( flags & 8 )
01520 ok = false;
01521 if ( !ok ) {
01522 delete msg;
01523 msg = 0;
01524 } else {
01525 if ( serNum > 0 ) {
01526
01527 msg->setMsgSerNum( serNum );
01528 }
01529
01530 if ( md ) {
01531 msg->setStatus( md->status() );
01532 } else if ( !mAccount->hasCapability("uidplus") ) {
01533
01534
01535 QString id = msg->msgIdMD5();
01536 if ( mMetaDataMap.find( id ) ) {
01537 md = mMetaDataMap[id];
01538 msg->setStatus( md->status() );
01539 if ( md->serNum() != 0 && serNum == 0 ) {
01540 msg->setMsgSerNum( md->serNum() );
01541 }
01542 mMetaDataMap.remove( id );
01543 delete md;
01544 }
01545 }
01546 KMFolderMbox::addMsg(msg, 0);
01547
01548 flagsToStatus((KMMsgBase*)msg, flags);
01549
01550 msg->setMsgSizeServer( msg->headerField("X-Length").toUInt() );
01551 msg->setUID(uid);
01552 if ( msg->getMsgSerNum() > 0 ) {
01553 saveMsgMetaData( msg );
01554 }
01555
01556 if ( folder()->isSystemFolder() && imapPath() == "/INBOX/"
01557 && kmkernel->filterMgr()->atLeastOneIncomingFilterAppliesTo( mAccount->id() ) )
01558 mAccount->execFilters( msg->getMsgSerNum() );
01559
01560 if ( count() > 1 ) {
01561 unGetMsg(count() - 1);
01562 }
01563 mLastUid = uid;
01564 if ( mMailCheckProgressItem ) {
01565 mMailCheckProgressItem->incCompletedItems();
01566 mMailCheckProgressItem->updateProgress();
01567 }
01568 }
01569 }
01570 (*it).cdata.remove(0, pos);
01571 (*it).done++;
01572 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
01573 }
01574 }
01575
01576
01577 FolderJob*
01578 KMFolderImap::doCreateJob( KMMessage *msg, FolderJob::JobType jt,
01579 KMFolder *folder, QString partSpecifier,
01580 const AttachmentStrategy *as ) const
01581 {
01582 KMFolderImap* kmfi = folder? dynamic_cast<KMFolderImap*>(folder->storage()) : 0;
01583 if ( jt == FolderJob::tGetMessage && partSpecifier == "STRUCTURE" &&
01584 mAccount && mAccount->loadOnDemand() &&
01585 ( msg->msgSizeServer() > 5000 || msg->msgSizeServer() == 0 ) &&
01586 ( msg->signatureState() == KMMsgNotSigned ||
01587 msg->signatureState() == KMMsgSignatureStateUnknown ) &&
01588 ( msg->encryptionState() == KMMsgNotEncrypted ||
01589 msg->encryptionState() == KMMsgEncryptionStateUnknown ) )
01590 {
01591
01592
01593 ImapJob *job = new ImapJob( msg, jt, kmfi, "HEADER" );
01594 job->start();
01595 ImapJob *job2 = new ImapJob( msg, jt, kmfi, "STRUCTURE", as );
01596 job2->start();
01597 job->setParentFolder( this );
01598 return job;
01599 } else {
01600
01601 if ( partSpecifier == "STRUCTURE" )
01602 partSpecifier = QString::null;
01603
01604 ImapJob *job = new ImapJob( msg, jt, kmfi, partSpecifier );
01605 job->setParentFolder( this );
01606 return job;
01607 }
01608 }
01609
01610
01611 FolderJob*
01612 KMFolderImap::doCreateJob( QPtrList<KMMessage>& msgList, const QString& sets,
01613 FolderJob::JobType jt, KMFolder *folder ) const
01614 {
01615 KMFolderImap* kmfi = dynamic_cast<KMFolderImap*>(folder->storage());
01616 ImapJob *job = new ImapJob( msgList, sets, jt, kmfi );
01617 job->setParentFolder( this );
01618 return job;
01619 }
01620
01621
01622 void KMFolderImap::getMessagesResult(KIO::Job * job, bool lastSet)
01623 {
01624 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01625 if ( it == mAccount->jobsEnd() ) return;
01626 if (job->error()) {
01627 mAccount->handleJobError( job, i18n("Error while retrieving messages.") );
01628 finishMailCheck( imapNoInformation );
01629 return;
01630 }
01631 if (lastSet) {
01632 finishMailCheck( imapFinished );
01633 mAccount->removeJob(it);
01634 }
01635 }
01636
01637
01638
01639 void KMFolderImap::slotGetLastMessagesResult(KIO::Job * job)
01640 {
01641 getMessagesResult(job, true);
01642 }
01643
01644
01645
01646 void KMFolderImap::slotGetMessagesResult(KIO::Job * job)
01647 {
01648 getMessagesResult(job, false);
01649 }
01650
01651
01652
01653 void KMFolderImap::createFolder(const QString &name, const QString& parentPath,
01654 bool askUser)
01655 {
01656 kdDebug(5006) << "KMFolderImap::createFolder - name=" << name << ",parent=" <<
01657 parentPath << ",askUser=" << askUser << endl;
01658 if ( mAccount->makeConnection() != ImapAccountBase::Connected ) {
01659 kdWarning(5006) << "KMFolderImap::createFolder - got no connection" << endl;
01660 return;
01661 }
01662 KURL url = mAccount->getUrl();
01663 QString parent = ( parentPath.isEmpty() ? imapPath() : parentPath );
01664 QString path = mAccount->createImapPath( parent, name );
01665 if ( askUser ) {
01666 path += "/;INFO=ASKUSER";
01667 }
01668 url.setPath( path );
01669
01670 KIO::SimpleJob *job = KIO::mkdir(url);
01671 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01672 ImapAccountBase::jobData jd( url.url(), folder() );
01673 jd.items = name;
01674 mAccount->insertJob(job, jd);
01675 connect(job, SIGNAL(result(KIO::Job *)),
01676 this, SLOT(slotCreateFolderResult(KIO::Job *)));
01677 }
01678
01679
01680
01681 void KMFolderImap::slotCreateFolderResult(KIO::Job * job)
01682 {
01683 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01684 if ( it == mAccount->jobsEnd() ) return;
01685 if (job->error())
01686 {
01687 if ( job->error() == KIO::ERR_COULD_NOT_MKDIR ) {
01688
01689 mAccount->listDirectory( );
01690 }
01691 mAccount->handleJobError( job, i18n("Error while creating a folder.") );
01692 } else {
01693 listDirectory();
01694 mAccount->removeJob(job);
01695 }
01696 }
01697
01698
01699
01700 static QTextCodec *sUtf7Codec = 0;
01701
01702 QTextCodec * KMFolderImap::utf7Codec()
01703 {
01704 if (!sUtf7Codec) sUtf7Codec = QTextCodec::codecForName("utf-7");
01705 return sUtf7Codec;
01706 }
01707
01708
01709
01710 QString KMFolderImap::encodeFileName(const QString &name)
01711 {
01712 QString result = utf7Codec()->fromUnicode(name);
01713 return KURL::encode_string_no_slash(result);
01714 }
01715
01716
01717
01718 QString KMFolderImap::decodeFileName(const QString &name)
01719 {
01720 QString result = KURL::decode_string(name);
01721 return utf7Codec()->toUnicode(result.latin1());
01722 }
01723
01724
01725 bool KMFolderImap::autoExpunge()
01726 {
01727 if (mAccount)
01728 return mAccount->autoExpunge();
01729
01730 return false;
01731 }
01732
01733
01734
01735 void KMFolderImap::slotSimpleData(KIO::Job * job, const QByteArray & data)
01736 {
01737 if ( data.isEmpty() ) return;
01738 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01739 if ( it == mAccount->jobsEnd() ) return;
01740 QBuffer buff((*it).data);
01741 buff.open(IO_WriteOnly | IO_Append);
01742 buff.writeBlock(data.data(), data.size());
01743 buff.close();
01744 }
01745
01746
01747 void KMFolderImap::deleteMessage(KMMessage * msg)
01748 {
01749 mUidMetaDataMap.remove( msg->UID() );
01750 mMetaDataMap.remove( msg->msgIdMD5() );
01751 KURL url = mAccount->getUrl();
01752 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msg->storage());
01753 ulong uid = msg->UID();
01754
01755
01756
01757 if ( uid == 0 ) {
01758 kdDebug( 5006 ) << "KMFolderImap::deleteMessage: Attempt to delete "
01759 "an empty UID. Aborting." << endl;
01760 return;
01761 }
01762 url.setPath(msg_parent->imapPath() + ";UID=" + QString::number(uid) );
01763 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01764 return;
01765 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01766 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01767 ImapAccountBase::jobData jd( url.url(), 0 );
01768 mAccount->insertJob(job, jd);
01769 connect(job, SIGNAL(result(KIO::Job *)),
01770 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01771 }
01772
01773 void KMFolderImap::deleteMessage(const QPtrList<KMMessage>& msgList)
01774 {
01775 QPtrListIterator<KMMessage> it( msgList );
01776 KMMessage *msg;
01777 while ( (msg = it.current()) != 0 ) {
01778 ++it;
01779 mUidMetaDataMap.remove( msg->UID() );
01780 mMetaDataMap.remove( msg->msgIdMD5() );
01781 }
01782
01783 QValueList<ulong> uids;
01784 getUids(msgList, uids);
01785 QStringList sets = makeSets(uids);
01786
01787 KURL url = mAccount->getUrl();
01788 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msgList.getFirst()->storage());
01789 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
01790 {
01791 QString uid = *it;
01792
01793
01794 if ( uid.isEmpty() ) continue;
01795 url.setPath(msg_parent->imapPath() + ";UID=" + uid);
01796 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01797 return;
01798 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01799 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01800 ImapAccountBase::jobData jd( url.url(), 0 );
01801 mAccount->insertJob(job, jd);
01802 connect(job, SIGNAL(result(KIO::Job *)),
01803 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01804 }
01805 }
01806
01807
01808 void KMFolderImap::setStatus(int idx, KMMsgStatus status, bool toggle)
01809 {
01810 QValueList<int> ids; ids.append(idx);
01811 setStatus(ids, status, toggle);
01812 }
01813
01814 void KMFolderImap::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle)
01815 {
01816 FolderStorage::setStatus(ids, status, toggle);
01817 if (mReadOnly) return;
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829 QMap< QString, QStringList > groups;
01830 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it ) {
01831 KMMessage *msg = 0;
01832 bool unget = !isMessage(*it);
01833 msg = getMsg(*it);
01834 if (!msg) continue;
01835 QString flags = statusToFlags(msg->status());
01836
01837 groups[flags].append(QString::number(msg->UID()));
01838 if (unget) unGetMsg(*it);
01839 }
01840 QMapIterator< QString, QStringList > dit;
01841 for ( dit = groups.begin(); dit != groups.end(); ++dit ) {
01842 QCString flags = dit.key().latin1();
01843 QStringList sets = makeSets( (*dit), true );
01844
01845 for ( QStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
01846 QString imappath = imapPath() + ";UID=" + ( *slit );
01847 mAccount->setImapStatus(folder(), imappath, flags);
01848 }
01849 }
01850 if ( mContentState == imapListingInProgress ) {
01851
01852
01853
01854 kdDebug(5006) << "Set status during folder listing, restarting listing." << endl;
01855 disconnect(this, SLOT(slotListFolderResult(KIO::Job *)));
01856 quiet( false );
01857 reallyGetFolder( QString::null );
01858 }
01859 }
01860
01861
01862 QStringList KMFolderImap::makeSets(const QStringList& uids, bool sort)
01863 {
01864 QValueList<ulong> tmp;
01865 for ( QStringList::ConstIterator it = uids.begin(); it != uids.end(); ++it )
01866 tmp.append( (*it).toInt() );
01867 return makeSets(tmp, sort);
01868 }
01869
01870 QStringList KMFolderImap::makeSets( QValueList<ulong>& uids, bool sort )
01871 {
01872 QStringList sets;
01873 QString set;
01874
01875 if (uids.size() == 1)
01876 {
01877 sets.append(QString::number(uids.first()));
01878 return sets;
01879 }
01880
01881 if (sort) qHeapSort(uids);
01882
01883 ulong last = 0;
01884
01885 bool inserted = false;
01886
01887 for ( QValueList<ulong>::Iterator it = uids.begin(); it != uids.end(); ++it )
01888 {
01889 if (it == uids.begin() || set.isEmpty()) {
01890 set = QString::number(*it);
01891 inserted = true;
01892 } else
01893 {
01894 if (last+1 != *it)
01895 {
01896
01897 if (inserted)
01898 set += ',' + QString::number(*it);
01899 else
01900 set += ':' + QString::number(last) + ',' + QString::number(*it);
01901 inserted = true;
01902 if (set.length() > 100)
01903 {
01904
01905 sets.append(set);
01906 set = "";
01907 }
01908 } else {
01909 inserted = false;
01910 }
01911 }
01912 last = *it;
01913 }
01914
01915 if (!inserted)
01916 set += ':' + QString::number(uids.last());
01917
01918 if (!set.isEmpty()) sets.append(set);
01919
01920 return sets;
01921 }
01922
01923
01924 void KMFolderImap::getUids(QValueList<int>& ids, QValueList<ulong>& uids)
01925 {
01926 KMMsgBase *msg = 0;
01927
01928 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01929 {
01930 msg = getMsgBase(*it);
01931 if (!msg) continue;
01932 uids.append(msg->UID());
01933 }
01934 }
01935
01936 void KMFolderImap::getUids(const QPtrList<KMMessage>& msgList, QValueList<ulong>& uids)
01937 {
01938 KMMessage *msg = 0;
01939
01940 QPtrListIterator<KMMessage> it( msgList );
01941 while ( (msg = it.current()) != 0 ) {
01942 ++it;
01943 if ( msg->UID() > 0 ) {
01944 uids.append( msg->UID() );
01945 }
01946 }
01947 }
01948
01949
01950 void KMFolderImap::expungeFolder(KMFolderImap * aFolder, bool quiet)
01951 {
01952 aFolder->setNeedsCompacting(FALSE);
01953 KURL url = mAccount->getUrl();
01954 url.setPath(aFolder->imapPath() + ";UID=*");
01955 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01956 return;
01957 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01958 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01959 ImapAccountBase::jobData jd( url.url(), 0 );
01960 jd.quiet = quiet;
01961 mAccount->insertJob(job, jd);
01962 connect(job, SIGNAL(result(KIO::Job *)),
01963 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01964 }
01965
01966
01967 void KMFolderImap::slotProcessNewMail( int errorCode, const QString &errorMsg )
01968 {
01969 Q_UNUSED( errorMsg );
01970 disconnect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
01971 this, SLOT( slotProcessNewMail(int, const QString&) ) );
01972 if ( !errorCode )
01973 processNewMail( false );
01974 else
01975 emit numUnreadMsgsChanged( folder() );
01976 }
01977
01978
01979 bool KMFolderImap::processNewMail(bool)
01980 {
01981
01982 if ( !mAccount ) {
01983 kdDebug(5006) << "KMFolderImap::processNewMail - account is null!" << endl;
01984 return false;
01985 }
01986 if ( imapPath().isEmpty() ) {
01987 kdDebug(5006) << "KMFolderImap::processNewMail - imapPath of " << name() << " is empty!" << endl;
01988
01989 setAlreadyRemoved( true );
01990 kmkernel->imapFolderMgr()->remove( folder() );
01991 return false;
01992 }
01993
01994 if ( mAccount->makeConnection() == ImapAccountBase::Error ) {
01995 kdDebug(5006) << "KMFolderImap::processNewMail - got no connection!" << endl;
01996 return false;
01997 } else if ( mAccount->makeConnection() == ImapAccountBase::Connecting )
01998 {
01999
02000 kdDebug(5006) << "KMFolderImap::processNewMail - waiting for connection: " << label() << endl;
02001 connect( mAccount, SIGNAL( connectionResult(int, const QString&) ),
02002 this, SLOT( slotProcessNewMail(int, const QString&) ) );
02003 return true;
02004 }
02005 KURL url = mAccount->getUrl();
02006 if (mReadOnly)
02007 url.setPath(imapPath() + ";SECTION=UIDNEXT");
02008 else
02009 url.setPath(imapPath() + ";SECTION=UNSEEN");
02010
02011 mMailCheckProgressItem = ProgressManager::createProgressItem(
02012 "MailCheckAccount" + account()->name(),
02013 "MailCheck" + folder()->prettyURL(),
02014 QStyleSheet::escape( folder()->prettyURL() ),
02015 i18n("updating message counts"),
02016 false,
02017 account()->useSSL() || account()->useTLS() );
02018
02019 KIO::SimpleJob *job = KIO::stat(url, FALSE);
02020 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
02021 ImapAccountBase::jobData jd(url.url(), folder() );
02022 jd.cancellable = true;
02023 mAccount->insertJob(job, jd);
02024 connect(job, SIGNAL(result(KIO::Job *)),
02025 SLOT(slotStatResult(KIO::Job *)));
02026 return true;
02027 }
02028
02029
02030
02031 void KMFolderImap::slotStatResult(KIO::Job * job)
02032 {
02033 slotCompleteMailCheckProgress();
02034 ImapAccountBase::JobIterator it = mAccount->findJob(job);
02035 if ( it == mAccount->jobsEnd() ) return;
02036 mAccount->removeJob(it);
02037 if (job->error())
02038 {
02039 mAccount->handleJobError( job, i18n("Error while getting folder information.") );
02040 } else {
02041 KIO::UDSEntry uds = static_cast<KIO::StatJob*>(job)->statResult();
02042 for (KIO::UDSEntry::ConstIterator it = uds.begin(); it != uds.end(); it++)
02043 {
02044 if ((*it).m_uds == KIO::UDS_SIZE)
02045 {
02046 if (mReadOnly)
02047 {
02048 mGuessedUnreadMsgs = -1;
02049 mGuessedUnreadMsgs = countUnread() + (*it).m_long - lastUid() - 1;
02050 if (mGuessedUnreadMsgs < 0) mGuessedUnreadMsgs = 0;
02051 } else {
02052 mGuessedUnreadMsgs = (*it).m_long;
02053 }
02054 }
02055 }
02056 }
02057 }
02058
02059
02060 int KMFolderImap::create()
02061 {
02062 readConfig();
02063 mUnreadMsgs = -1;
02064 return KMFolderMbox::create();
02065 }
02066
02067 QValueList<ulong> KMFolderImap::splitSets(const QString uids)
02068 {
02069 QValueList<ulong> uidlist;
02070
02071
02072 QString buffer = QString::null;
02073 int setstart = -1;
02074
02075 for (uint i = 0; i < uids.length(); i++)
02076 {
02077 QChar chr = uids[i];
02078 if (chr == ',')
02079 {
02080 if (setstart > -1)
02081 {
02082
02083 for (int j = setstart; j <= buffer.toInt(); j++)
02084 {
02085 uidlist.append(j);
02086 }
02087 setstart = -1;
02088 } else {
02089
02090 uidlist.append(buffer.toInt());
02091 }
02092 buffer = "";
02093 } else if (chr == ':') {
02094
02095 setstart = buffer.toInt();
02096 buffer = "";
02097 } else if (chr.category() == QChar::Number_DecimalDigit) {
02098
02099 buffer += chr;
02100 } else {
02101
02102 }
02103 }
02104
02105 if (setstart > -1)
02106 {
02107 for (int j = setstart; j <= buffer.toInt(); j++)
02108 {
02109 uidlist.append(j);
02110 }
02111 } else {
02112 uidlist.append(buffer.toInt());
02113 }
02114
02115 return uidlist;
02116 }
02117
02118
02119 int KMFolderImap::expungeContents()
02120 {
02121
02122 int rc = KMFolderMbox::expungeContents();
02123
02124
02125 KURL url = mAccount->getUrl();
02126 url.setPath( imapPath() + ";UID=1:*");
02127 if ( mAccount->makeConnection() == ImapAccountBase::Connected )
02128 {
02129 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
02130 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
02131 ImapAccountBase::jobData jd( url.url(), 0 );
02132 jd.quiet = true;
02133 mAccount->insertJob(job, jd);
02134 connect(job, SIGNAL(result(KIO::Job *)),
02135 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
02136 }
02137
02138
02139
02140
02141 expungeFolder(this, true);
02142 getFolder();
02143
02144 return rc;
02145 }
02146
02147
02148 void
02149 KMFolderImap::setUserRights( unsigned int userRights )
02150 {
02151 mUserRights = userRights;
02152 kdDebug(5006) << imapPath() << " setUserRights: " << userRights << endl;
02153 }
02154
02155
02156 void KMFolderImap::slotCompleteMailCheckProgress()
02157 {
02158 if ( mMailCheckProgressItem ) {
02159 mMailCheckProgressItem->setComplete();
02160 mMailCheckProgressItem = 0;
02161 emit numUnreadMsgsChanged( folder() );
02162 }
02163 }
02164
02165
02166 void KMFolderImap::setSubfolderState( imapState state )
02167 {
02168 mSubfolderState = state;
02169 if ( state == imapNoInformation && folder()->child() )
02170 {
02171
02172 KMFolderNode* node;
02173 QPtrListIterator<KMFolderNode> it( *folder()->child() );
02174 for ( ; (node = it.current()); )
02175 {
02176 ++it;
02177 if (node->isDir()) continue;
02178 KMFolder *folder = static_cast<KMFolder*>(node);
02179 static_cast<KMFolderImap*>(folder->storage())->setSubfolderState( state );
02180 }
02181 }
02182 }
02183
02184
02185 void KMFolderImap::setIncludeInMailCheck( bool check )
02186 {
02187 bool changed = ( mCheckMail != check );
02188 mCheckMail = check;
02189 if ( changed )
02190 account()->slotUpdateFolderList();
02191 }
02192
02193
02194 void KMFolderImap::setAlreadyRemoved( bool removed )
02195 {
02196 mAlreadyRemoved = removed;
02197 if ( folder()->child() )
02198 {
02199
02200 KMFolderNode* node;
02201 QPtrListIterator<KMFolderNode> it( *folder()->child() );
02202 for ( ; (node = it.current()); )
02203 {
02204 ++it;
02205 if (node->isDir()) continue;
02206 KMFolder *folder = static_cast<KMFolder*>(node);
02207 static_cast<KMFolderImap*>(folder->storage())->setAlreadyRemoved( removed );
02208 }
02209 }
02210 }
02211
02212 void KMFolderImap::slotCreatePendingFolders( int errorCode, const QString& errorMsg )
02213 {
02214 Q_UNUSED( errorMsg );
02215 disconnect( mAccount, SIGNAL( connectionResult( int, const QString& ) ),
02216 this, SLOT( slotCreatePendingFolders( int, const QString& ) ) );
02217 if ( !errorCode ) {
02218 QStringList::Iterator it = mFoldersPendingCreation.begin();
02219 for ( ; it != mFoldersPendingCreation.end(); ++it ) {
02220 createFolder( *it );
02221 }
02222 }
02223 mFoldersPendingCreation.clear();
02224 }
02225
02226
02227 void KMFolderImap::search( const KMSearchPattern* pattern )
02228 {
02229 if ( !pattern || pattern->isEmpty() )
02230 {
02231
02232 QValueList<Q_UINT32> serNums;
02233 emit searchResult( folder(), serNums, pattern, true );
02234 return;
02235 }
02236 SearchJob* job = new SearchJob( this, mAccount, pattern );
02237 connect( job, SIGNAL( searchDone( QValueList<Q_UINT32>, const KMSearchPattern*, bool ) ),
02238 this, SLOT( slotSearchDone( QValueList<Q_UINT32>, const KMSearchPattern*, bool ) ) );
02239 job->start();
02240 }
02241
02242
02243 void KMFolderImap::slotSearchDone( QValueList<Q_UINT32> serNums,
02244 const KMSearchPattern* pattern,
02245 bool complete )
02246 {
02247 emit searchResult( folder(), serNums, pattern, complete );
02248 }
02249
02250
02251 void KMFolderImap::search( const KMSearchPattern* pattern, Q_UINT32 serNum )
02252 {
02253 if ( !pattern || pattern->isEmpty() )
02254 {
02255
02256 emit searchDone( folder(), serNum, pattern, false );
02257 return;
02258 }
02259 SearchJob* job = new SearchJob( this, mAccount, pattern, serNum );
02260 connect( job, SIGNAL( searchDone( Q_UINT32, const KMSearchPattern*, bool ) ),
02261 this, SLOT( slotSearchDone( Q_UINT32, const KMSearchPattern*, bool ) ) );
02262 job->start();
02263 }
02264
02265
02266 void KMFolderImap::slotSearchDone( Q_UINT32 serNum, const KMSearchPattern* pattern,
02267 bool matches )
02268 {
02269 emit searchDone( folder(), serNum, pattern, matches );
02270 }
02271
02272
02273 bool KMFolderImap::isMoveable() const
02274 {
02275 return ( hasChildren() == HasNoChildren &&
02276 !folder()->isSystemFolder() ) ? true : false;
02277 }
02278
02279
02280 const ulong KMFolderImap::serNumForUID( ulong uid )
02281 {
02282 if ( mUidMetaDataMap.find( uid ) ) {
02283 KMMsgMetaData *md = mUidMetaDataMap[uid];
02284 return md->serNum();
02285 } else {
02286 kdDebug(5006) << "serNumForUID: unknown uid " << uid << endl;
02287 return 0;
02288 }
02289 }
02290
02291
02292 void KMFolderImap::saveMsgMetaData( KMMessage* msg, ulong uid )
02293 {
02294 if ( uid == 0 ) {
02295 uid = msg->UID();
02296 }
02297 ulong serNum = msg->getMsgSerNum();
02298 mUidMetaDataMap.replace( uid, new KMMsgMetaData(msg->status(), serNum) );
02299 }
02300
02301
02302 void KMFolderImap::setImapPath( const QString& path )
02303 {
02304 if ( path.isEmpty() ) {
02305 kdWarning(5006) << k_funcinfo << "ignoring empty path" << endl;
02306 } else {
02307 mImapPath = path;
02308 }
02309 }
02310
02311 void KMFolderImap::finishMailCheck( imapState state )
02312 {
02313 quiet( false );
02314 mContentState = state;
02315 emit folderComplete( this, mContentState == imapFinished );
02316 close();
02317 }
02318
02319 #include "kmfolderimap.moc"