00001
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "kmfolderimap.h"
00028 #include "kmfoldermbox.h"
00029 #include "kmfoldertree.h"
00030 #include "undostack.h"
00031 #include "kmfoldermgr.h"
00032 #include "imapjob.h"
00033 using KMail::ImapJob;
00034 #include "attachmentstrategy.h"
00035 using KMail::AttachmentStrategy;
00036
00037 #include <kdebug.h>
00038 #include <kio/scheduler.h>
00039 #include <kconfig.h>
00040
00041 #include <qbuffer.h>
00042 #include <qtextcodec.h>
00043
00044 #include <assert.h>
00045
00046 KMFolderImap::KMFolderImap(KMFolderDir* aParent, const QString& aName)
00047 : KMFolderMbox(aParent, aName)
00048 {
00049 mContentState = imapNoInformation;
00050 mSubfolderState = imapNoInformation;
00051 mAccount = 0;
00052 mIsSelected = FALSE;
00053 mLastUid = 0;
00054 mCheckFlags = TRUE;
00055 mCheckMail = TRUE;
00056 mCheckingValidity = FALSE;
00057
00058 KConfig* config = KMKernel::config();
00059 KConfigGroupSaver saver(config, "Folder-" + idString());
00060 mUidValidity = config->readEntry("UidValidity");
00061 if (mImapPath.isEmpty()) mImapPath = config->readEntry("ImapPath");
00062 if (aName == "INBOX" && mImapPath == "/INBOX/")
00063 {
00064 mIsSystemFolder = TRUE;
00065 mLabel = i18n("inbox");
00066 }
00067 mNoContent = config->readBoolEntry("NoContent", FALSE);
00068 mReadOnly = config->readBoolEntry("ReadOnly", FALSE);
00069
00070 readConfig();
00071 }
00072
00073 KMFolderImap::~KMFolderImap()
00074 {
00075 if (mAccount) {
00076 mAccount->removeSlaveJobsForFolder( this );
00077
00078
00079
00080
00081 if ( mAccount->checkingMail() ) {
00082 mAccount->killAllJobs();
00083 }
00084 }
00085 writeConfig();
00086 if (kmkernel->undoStack()) kmkernel->undoStack()->folderDestroyed(this);
00087 mMetaDataMap.setAutoDelete( true );
00088 mMetaDataMap.clear();
00089 }
00090
00091
00092
00093 void KMFolderImap::close(bool aForced)
00094 {
00095 if (mOpenCount <= 0 ) return;
00096 if (mOpenCount > 0) mOpenCount--;
00097 if (mOpenCount > 0 && !aForced) return;
00098
00099 if (mAccount)
00100 mAccount->ignoreJobsForFolder( this );
00101 int idx = count();
00102 while (--idx >= 0) {
00103 if ( mMsgList[idx]->isMessage() ) {
00104 KMMessage *msg = static_cast<KMMessage*>(mMsgList[idx]);
00105 if (msg->transferInProgress())
00106 msg->setTransferInProgress( false );
00107 }
00108 }
00109
00110 mOpenCount++;
00111 KMFolderMbox::close(aForced);
00112 }
00113
00114
00115 KMMessage* KMFolderImap::getMsg(int idx)
00116 {
00117 if(!(idx >= 0 && idx <= count()))
00118 return 0;
00119
00120 KMMsgBase* mb = getMsgBase(idx);
00121 if (!mb) return 0;
00122 if (mb->isMessage())
00123 {
00124 return ((KMMessage*)mb);
00125 } else {
00126 KMMessage* msg = KMFolder::getMsg( idx );
00127 if ( msg )
00128 msg->setComplete( false );
00129 return msg;
00130 }
00131 }
00132
00133
00134 void KMFolderImap::setAccount(KMAcctImap *aAccount)
00135 {
00136 mAccount = aAccount;
00137 if (!mChild) return;
00138 KMFolderNode* node;
00139 for (node = mChild->first(); node; node = mChild->next())
00140 {
00141 if (!node->isDir())
00142 static_cast<KMFolderImap*>(node)->setAccount(aAccount);
00143 }
00144 }
00145
00146
00147 void KMFolderImap::readConfig()
00148 {
00149 KConfig* config = KMKernel::config();
00150 KConfigGroupSaver saver(config, "Folder-" + idString());
00151 mCheckMail = config->readBoolEntry("checkmail", true);
00152 KMFolderMbox::readConfig();
00153 }
00154
00155
00156 void KMFolderImap::writeConfig()
00157 {
00158 KConfig* config = KMKernel::config();
00159 KConfigGroupSaver saver(config, "Folder-" + idString());
00160 config->writeEntry("checkmail", mCheckMail);
00161 config->writeEntry("UidValidity", mUidValidity);
00162 config->writeEntry("ImapPath", mImapPath);
00163 config->writeEntry("NoContent", mNoContent);
00164 config->writeEntry("ReadOnly", mReadOnly);
00165 KMFolderMbox::writeConfig();
00166 }
00167
00168
00169 void KMFolderImap::removeOnServer()
00170 {
00171 KURL url = mAccount->getUrl();
00172 url.setPath(imapPath());
00173 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
00174 return;
00175 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
00176 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
00177 ImapAccountBase::jobData jd(url.url());
00178 mAccount->insertJob(job, jd);
00179 connect(job, SIGNAL(result(KIO::Job *)),
00180 this, SLOT(slotRemoveFolderResult(KIO::Job *)));
00181 }
00182
00183
00184 void KMFolderImap::slotRemoveFolderResult(KIO::Job *job)
00185 {
00186 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00187 if ( it == mAccount->jobsEnd() ) return;
00188 mAccount->removeJob(it);
00189 if (job->error())
00190 {
00191 mAccount->slotSlaveError( mAccount->slave(), job->error(),
00192 job->errorText() );
00193 } else {
00194 mAccount->displayProgress();
00195 kmkernel->imapFolderMgr()->remove(this);
00196 }
00197 }
00198
00199
00200 void KMFolderImap::removeMsg(int idx, bool quiet)
00201 {
00202 if (idx < 0)
00203 return;
00204
00205 if (!quiet)
00206 {
00207 KMMessage *msg = getMsg(idx);
00208 deleteMessage(msg);
00209 }
00210
00211 mLastUid = 0;
00212 KMFolderMbox::removeMsg(idx);
00213 }
00214
00215 void KMFolderImap::removeMsg(QPtrList<KMMessage> msgList, bool quiet)
00216 {
00217 if (!quiet)
00218 deleteMessage(msgList);
00219
00220 mLastUid = 0;
00221
00222
00223
00224
00225
00226 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00227 {
00228 int idx = find(msg);
00229 assert( idx != -1);
00230
00231 KMFolderMbox::removeMsg(idx, quiet);
00232 }
00233 }
00234
00235
00236 int KMFolderImap::rename( const QString& newName, KMFolderDir * )
00237 {
00238 if ( newName == name() )
00239 return 0;
00240
00241 QString path = imapPath();
00242 int i = path.findRev( '.' );
00243 path = path.left( i );
00244 path += "." + newName;
00245 KURL src( mAccount->getUrl() );
00246 src.setPath( imapPath() );
00247 KURL dst( mAccount->getUrl() );
00248 dst.setPath( path );
00249 KIO::SimpleJob *job = KIO::rename( src, dst, true );
00250 kdDebug(5006)<< "### Rename : " << src.prettyURL()
00251 << " |=> " << dst.prettyURL()
00252 << endl;
00253 KIO::Scheduler::assignJobToSlave( mAccount->slave(), job );
00254 connect( job, SIGNAL(result(KIO::Job*)),
00255 SLOT(slotRenameResult(KIO::Job*)) );
00256 setImapPath( path );
00257 return 0;
00258 }
00259
00260
00261 void KMFolderImap::slotRenameResult( KIO::Job *job )
00262 {
00263 KIO::SimpleJob* sj = static_cast<KIO::SimpleJob*>(job);
00264 if ( job->error() ) {
00265 setImapPath( sj->url().path() );
00266 mAccount->slotSlaveError( mAccount->slave(), job->error(),
00267 job->errorText() );
00268 return;
00269 }
00270 QString path = imapPath();
00271 int i = path.findRev( '.' );
00272 path = path.mid( ++i );
00273 path.remove( '/' );
00274 KMFolderMbox::rename( path );
00275 kmkernel->folderMgr()->contentsChanged();
00276 }
00277
00278
00279 void KMFolderImap::addMsgQuiet(KMMessage* aMsg)
00280 {
00281 KMFolder *folder = aMsg->parent();
00282 Q_UINT32 serNum = 0;
00283 aMsg->setTransferInProgress( false );
00284 if (folder) {
00285 serNum = aMsg->getMsgSerNum();
00286 kmkernel->undoStack()->pushSingleAction( serNum, folder, this );
00287 int idx = folder->find( aMsg );
00288 assert( idx != -1 );
00289 folder->take( idx );
00290 }
00291
00292 mMetaDataMap.insert(aMsg->msgIdMD5(), new KMMsgMetaData(aMsg->status(), serNum));
00293
00294 delete aMsg;
00295 aMsg = 0;
00296 getFolder();
00297 }
00298
00299
00300 void KMFolderImap::addMsgQuiet(QPtrList<KMMessage> msgList)
00301 {
00302 KMFolder *folder = msgList.first()->parent();
00303 Q_UINT32 serNum = 0;
00304 if (folder) serNum = msgList.first()->getMsgSerNum();
00305 int undoId = -1;
00306 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00307 {
00308 if ( undoId == -1 )
00309 undoId = kmkernel->undoStack()->newUndoAction( folder, this );
00310 kmkernel->undoStack()->addMsgToAction( undoId, msg->getMsgSerNum() );
00311
00312 mMetaDataMap.insert(msg->msgIdMD5(), new KMMsgMetaData(msg->status(), serNum));
00313 msg->setTransferInProgress( false );
00314 }
00315 if (folder) folder->take(msgList);
00316 msgList.setAutoDelete(true);
00317 msgList.clear();
00318 getFolder();
00319 }
00320
00321
00322 int KMFolderImap::addMsg(KMMessage* aMsg, int* aIndex_ret)
00323 {
00324 QPtrList<KMMessage> list; list.append(aMsg);
00325 return addMsg(list, aIndex_ret);
00326 }
00327
00328 int KMFolderImap::addMsg(QPtrList<KMMessage>& msgList, int* aIndex_ret)
00329 {
00330 KMMessage *aMsg = msgList.getFirst();
00331 KMFolder *msgParent = aMsg->parent();
00332
00333 ImapJob *imapJob = 0;
00334 if (msgParent)
00335 {
00336 if (msgParent->folderType() == KMFolderTypeImap)
00337 {
00338 if (static_cast<KMFolderImap*>(msgParent)->account() == account())
00339 {
00340
00341 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00342 msg->setTransferInProgress(true);
00343
00344 if (this == msgParent)
00345 {
00346
00347 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00348 {
00349 if (!msg->isComplete())
00350 {
00351 int idx = msgParent->find(msg);
00352 assert(idx != -1);
00353 msg = msgParent->getMsg(idx);
00354 }
00355 imapJob = new ImapJob(msg, ImapJob::tPutMessage, this);
00356 connect(imapJob, SIGNAL(messageStored(KMMessage*)),
00357 SLOT(addMsgQuiet(KMMessage*)));
00358 imapJob->start();
00359 }
00360
00361 } else {
00362
00363
00364 QValueList<int> uids;
00365 getUids(msgList, uids);
00366
00367
00368 QStringList sets = makeSets(uids, false);
00369
00370 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
00371 {
00372
00373 QPtrList<KMMessage> temp_msgs = splitMessageList(*it, msgList);
00374
00375 imapJob = new ImapJob(temp_msgs, *it, ImapJob::tMoveMessage, this);
00376 connect(imapJob, SIGNAL(messageCopied(QPtrList<KMMessage>)),
00377 SLOT(addMsgQuiet(QPtrList<KMMessage>)));
00378 imapJob->start();
00379 }
00380 }
00381 if (aIndex_ret) *aIndex_ret = -1;
00382 return 0;
00383 }
00384 else
00385 {
00386
00387 QPtrListIterator<KMMessage> it( msgList );
00388 KMMessage *msg;
00389 while ( (msg = it.current()) != 0 )
00390 {
00391 ++it;
00392 if (!canAddMsgNow(msg, aIndex_ret))
00393 msgList.remove(msg);
00394 else {
00395 if (!msg->transferInProgress())
00396 msg->setTransferInProgress(true);
00397 }
00398 }
00399 }
00400 }
00401 }
00402
00403 for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
00404 {
00405
00406 if (msgParent && !msg->isMessage())
00407 {
00408 int idx = msgParent->find(msg);
00409 assert(idx != -1);
00410 msg = msgParent->getMsg(idx);
00411 }
00412 if (!msg->transferInProgress())
00413 msg->setTransferInProgress(true);
00414 imapJob = new ImapJob(msg, ImapJob::tPutMessage, this);
00415 connect(imapJob, SIGNAL(messageStored(KMMessage*)),
00416 SLOT(addMsgQuiet(KMMessage*)));
00417 imapJob->start();
00418 }
00419
00420 if (aIndex_ret) *aIndex_ret = -1;
00421 return 0;
00422 }
00423
00424
00425 void KMFolderImap::copyMsg(QPtrList<KMMessage>& msgList)
00426 {
00427 for (KMMessage *msg = msgList.first(); msg; msg = msgList.next()) {
00428
00429 mMetaDataMap.insert(msg->msgIdMD5(), new KMMsgMetaData(msg->status()));
00430 }
00431 QValueList<int> uids;
00432 getUids(msgList, uids);
00433 QStringList sets = makeSets(uids, false);
00434 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
00435 {
00436
00437 QPtrList<KMMessage> temp_msgs = splitMessageList(*it, msgList);
00438
00439 ImapJob *job = new ImapJob(temp_msgs, *it, ImapJob::tCopyMessage, this);
00440 job->start();
00441 }
00442 }
00443
00444
00445 QPtrList<KMMessage> KMFolderImap::splitMessageList(QString set, QPtrList<KMMessage>& msgList)
00446 {
00447 int lastcomma = set.findRev(",");
00448 int lastdub = set.findRev(":");
00449 int last = 0;
00450 if (lastdub > lastcomma) last = lastdub;
00451 else last = lastcomma;
00452 last++;
00453 if (last < 0) last = set.length();
00454
00455 QString last_uid = set.right(set.length() - last);
00456 QPtrList<KMMessage> temp_msgs;
00457 QString uid;
00458 if (!last_uid.isEmpty())
00459 {
00460 QPtrListIterator<KMMessage> it( msgList );
00461 KMMessage* msg = 0;
00462 while ( (msg = it.current()) != 0 )
00463 {
00464
00465 temp_msgs.append(msg);
00466 uid = msg->headerField("X-UID");
00467
00468 msgList.remove(msg);
00469 if (uid == last_uid) break;
00470 }
00471 }
00472 else
00473 {
00474
00475 temp_msgs = msgList;
00476 }
00477
00478 return temp_msgs;
00479 }
00480
00481
00482 KMMessage* KMFolderImap::take(int idx)
00483 {
00484 KMMsgBase* mb(mMsgList[idx]);
00485 if (!mb) return 0;
00486 if (!mb->isMessage()) readMsg(idx);
00487
00488 KMMessage *msg = static_cast<KMMessage*>(mb);
00489 deleteMessage(msg);
00490
00491 mLastUid = 0;
00492 return KMFolderMbox::take(idx);
00493 }
00494
00495 void KMFolderImap::take(QPtrList<KMMessage> msgList)
00496 {
00497 deleteMessage(msgList);
00498
00499 mLastUid = 0;
00500 KMFolderMbox::take(msgList);
00501 }
00502
00503
00504 bool KMFolderImap::listDirectory(bool secondStep)
00505 {
00506 mSubfolderState = imapInProgress;
00507 if ( mAccount->makeConnection() == ImapAccountBase::Error )
00508 return false;
00509
00510
00511 connect(mAccount, SIGNAL(receivedFolders(QStringList, QStringList,
00512 QStringList, const ImapAccountBase::jobData &)),
00513 this, SLOT(slotListResult(QStringList, QStringList,
00514 QStringList, const ImapAccountBase::jobData &)));
00515
00516
00517 bool reset = (mImapPath == mAccount->prefix() &&
00518 !secondStep && !mIsSystemFolder) ? true : false;
00519
00520
00521 mAccount->listDirectory(mImapPath, mAccount->onlySubscribedFolders(),
00522 secondStep, this, reset);
00523
00524 return true;
00525 }
00526
00527
00528
00529 void KMFolderImap::slotListResult( QStringList mSubfolderNames,
00530 QStringList mSubfolderPaths,
00531 QStringList mSubfolderMimeTypes,
00532 const ImapAccountBase::jobData & jobData )
00533 {
00534 if (jobData.parent) {
00535
00536
00537 if (jobData.parent != this) return;
00538 }
00539
00540 disconnect(mAccount, SIGNAL(receivedFolders(QStringList, QStringList,
00541 QStringList, const ImapAccountBase::jobData &)),
00542 this, SLOT(slotListResult(QStringList, QStringList,
00543 QStringList, const ImapAccountBase::jobData &)));
00544
00545 mSubfolderState = imapFinished;
00546 bool it_inboxOnly = jobData.inboxOnly;
00547
00548
00549
00550 kmkernel->imapFolderMgr()->quiet(TRUE);
00551 if (it_inboxOnly) {
00552
00553 listDirectory(TRUE);
00554 } else {
00555 if (mIsSystemFolder && mImapPath == "/INBOX/"
00556 && mAccount->prefix() == "/INBOX/")
00557 {
00558
00559 mAccount->setCreateInbox(FALSE);
00560 mSubfolderNames.clear();
00561 }
00562 createChildFolder();
00563 KMFolderImap *folder;
00564 KMFolderNode *node = mChild->first();
00565 while (node)
00566 {
00567
00568 if (!node->isDir() && (node->name().upper() != "INBOX" || !mAccount->createInbox())
00569 && mSubfolderNames.findIndex(node->name()) == -1)
00570 {
00571 kdDebug(5006) << node->name() << " disappeared." << endl;
00572 kmkernel->imapFolderMgr()->remove(static_cast<KMFolder*>(node));
00573 node = mChild->first();
00574 }
00575 else node = mChild->next();
00576 }
00577 if (mAccount->createInbox())
00578 {
00579
00580 for (node = mChild->first(); node; node = mChild->next())
00581 if (!node->isDir() && node->name() == "INBOX") break;
00582 if (node) folder = static_cast<KMFolderImap*>(node);
00583 else folder = static_cast<KMFolderImap*>
00584 (mChild->createFolder("INBOX", TRUE));
00585 folder->setAccount(mAccount);
00586 folder->setImapPath("/INBOX/");
00587 folder->setLabel(i18n("inbox"));
00588 if (!node) folder->close();
00589
00590 mAccount->setCreateInbox( false );
00591 mAccount->setHasInbox( true );
00592 folder->listDirectory();
00593 kmkernel->imapFolderMgr()->contentsChanged();
00594 }
00595 for (uint i = 0; i < mSubfolderNames.count(); i++)
00596 {
00597
00598 if (mSubfolderNames[i].upper() == "INBOX" &&
00599 mSubfolderPaths[i].upper() == "/INBOX/" &&
00600 mAccount->hasInbox())
00601 continue;
00602 for (node = mChild->first(); node; node = mChild->next())
00603 if (!node->isDir() && node->name() == mSubfolderNames[i]) break;
00604 if (node) folder = static_cast<KMFolderImap*>(node);
00605 else {
00606 folder = static_cast<KMFolderImap*>
00607 (mChild->createFolder(mSubfolderNames[i]));
00608 if (folder)
00609 {
00610 folder->close();
00611 kmkernel->imapFolderMgr()->contentsChanged();
00612 } else {
00613 kdWarning(5006) << "can't create folder " << mSubfolderNames[i] << endl;
00614 }
00615 }
00616 if (folder)
00617 {
00618 folder->setAccount(mAccount);
00619 folder->setNoContent(mSubfolderMimeTypes[i] == "inode/directory");
00620 folder->setImapPath(mSubfolderPaths[i]);
00621 if (mSubfolderMimeTypes[i] == "message/directory" ||
00622 mSubfolderMimeTypes[i] == "inode/directory")
00623 folder->listDirectory();
00624 }
00625 }
00626 }
00627
00628 kmkernel->imapFolderMgr()->quiet(FALSE);
00629 }
00630
00631
00632 void KMFolderImap::checkValidity()
00633 {
00634 if (!mAccount) {
00635 emit folderComplete(this, false);
00636 return;
00637 }
00638 KURL url = mAccount->getUrl();
00639 url.setPath(imapPath() + ";UID=0:0");
00640 kdDebug(5006) << "KMFolderImap::checkValidity of: " << imapPath() << endl;
00641 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
00642 {
00643 kdWarning(5006) << "KMFolderImap::checkValidity - got no connection" << endl;
00644 emit folderComplete(this, FALSE);
00645 return;
00646 }
00647
00648 if (mCheckingValidity) {
00649 kdDebug(5006) << "KMFolderImap::checkValidity - already checking" << endl;
00650 return;
00651 }
00652 ImapAccountBase::jobData jd( url.url(), this );
00653 KIO::SimpleJob *job = KIO::get(url, FALSE, FALSE);
00654 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
00655 mAccount->insertJob(job, jd);
00656 connect(job, SIGNAL(result(KIO::Job *)),
00657 SLOT(slotCheckValidityResult(KIO::Job *)));
00658 connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)),
00659 SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
00660
00661 mCheckingValidity = true;
00662
00663 }
00664
00665
00666
00667 ulong KMFolderImap::lastUid()
00668 {
00669 if (mLastUid) return mLastUid;
00670 open();
00671 if (count() > 0)
00672 {
00673 bool unget = !isMessage(count() - 1);
00674 KMMessage *msg = getMsg(count() - 1);
00675 mLastUid = msg->headerField("X-UID").toULong();
00676 if (unget) unGetMsg(count() - 1);
00677 }
00678 close();
00679 return mLastUid;
00680 }
00681
00682
00683
00684 void KMFolderImap::slotCheckValidityResult(KIO::Job * job)
00685 {
00686 kdDebug(5006) << "KMFolderImap::slotCheckValidityResult of: " << fileName() << endl;
00687 mCheckingValidity = false;
00688 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00689 if ( it == mAccount->jobsEnd() ) return;
00690 if (job->error()) {
00691 mAccount->slotSlaveError(mAccount->slave(), job->error(), job->errorText());
00692 emit folderComplete(this, FALSE);
00693 mAccount->displayProgress();
00694 } else {
00695 QCString cstr((*it).data.data(), (*it).data.size() + 1);
00696 int a = cstr.find("X-uidValidity: ");
00697 int b = cstr.find("\r\n", a);
00698 QString uidv;
00699 if ( (b - a - 15) >= 0 ) uidv = cstr.mid(a + 15, b - a - 15);
00700 a = cstr.find("X-Access: ");
00701 b = cstr.find("\r\n", a);
00702 QString access;
00703 if ( (b - a - 10) >= 0 ) access = cstr.mid(a + 10, b - a - 10);
00704 mReadOnly = access == "Read only";
00705 QString startUid;
00706 if (uidValidity() != uidv)
00707 {
00708
00709 kdDebug(5006) << "KMFolderImap::slotCheckValidityResult uidValidty changed." << endl;
00710 mAccount->ignoreJobsForFolder(this);
00711 expunge();
00712 mLastUid = 0;
00713 uidmap.clear();
00714 setUidValidity(uidv);
00715 } else {
00716 if (!mCheckFlags)
00717 startUid = QString::number(lastUid() + 1);
00718 }
00719 mAccount->removeJob(it);
00720 reallyGetFolder(startUid);
00721 }
00722 }
00723
00724
00725 void KMFolderImap::getAndCheckFolder(bool force)
00726 {
00727 if (mNoContent)
00728 return getFolder(force);
00729
00730 if ( mAccount )
00731 mAccount->processNewMailSingleFolder(this);
00732 if (force) {
00733
00734 mCheckFlags = TRUE;
00735 }
00736 }
00737
00738
00739 void KMFolderImap::getFolder(bool force)
00740 {
00741 mGuessedUnreadMsgs = -1;
00742 if (mNoContent)
00743 {
00744 mContentState = imapFinished;
00745 emit folderComplete(this, true);
00746 return;
00747 }
00748 mContentState = imapInProgress;
00749 if (force) {
00750
00751 mCheckFlags = TRUE;
00752 }
00753 checkValidity();
00754 }
00755
00756
00757
00758 void KMFolderImap::reallyGetFolder(const QString &startUid)
00759 {
00760 KURL url = mAccount->getUrl();
00761 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
00762 {
00763 emit folderComplete(this, FALSE);
00764 mAccount->displayProgress();
00765 return;
00766 }
00767 quiet(true);
00768 if (startUid.isEmpty())
00769 {
00770 url.setPath(imapPath() + ";SECTION=UID FLAGS");
00771 KIO::SimpleJob *job = KIO::listDir(url, FALSE);
00772 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
00773 ImapAccountBase::jobData jd( url.url(), this );
00774 mAccount->insertJob(job, jd);
00775 connect(job, SIGNAL(result(KIO::Job *)),
00776 this, SLOT(slotListFolderResult(KIO::Job *)));
00777 connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList &)),
00778 this, SLOT(slotListFolderEntries(KIO::Job *,
00779 const KIO::UDSEntryList &)));
00780 } else {
00781 url.setPath(imapPath() + ";UID=" + startUid
00782 + ":*;SECTION=ENVELOPE");
00783 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
00784 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
00785 ImapAccountBase::jobData jd( url.url(), this );
00786 mAccount->insertJob(newJob, jd);
00787 connect(newJob, SIGNAL(result(KIO::Job *)),
00788 this, SLOT(slotGetLastMessagesResult(KIO::Job *)));
00789 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
00790 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
00791 }
00792 }
00793
00794
00795
00796 void KMFolderImap::slotListFolderResult(KIO::Job * job)
00797 {
00798 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00799 if ( it == mAccount->jobsEnd() ) return;
00800 QString uids;
00801 if (job->error())
00802 {
00803 mAccount->slotSlaveError( mAccount->slave(), job->error(),
00804 job->errorText() );
00805 quiet( false );
00806 emit folderComplete(this, FALSE);
00807 mAccount->removeJob(it);
00808 mAccount->displayProgress();
00809 return;
00810 }
00811 mCheckFlags = FALSE;
00812 QStringList::Iterator uid;
00813
00814 if (count())
00815 {
00816 QCString cstr;
00817 int idx = 0, a, b, c, serverFlags;
00818 long int mailUid, serverUid;
00819 uid = (*it).items.begin();
00820 while (idx < count() && uid != (*it).items.end())
00821 {
00822 getMsgString(idx, cstr);
00823 a = cstr.find("X-UID: ");
00824 b = cstr.find("\n", a);
00825 if (a == -1 || b == -1) mailUid = -1;
00826 else mailUid = cstr.mid(a + 7, b - a - 7).toLong();
00827 c = (*uid).find(",");
00828 serverUid = (*uid).left(c).toLong();
00829 serverFlags = (*uid).mid(c+1).toInt();
00830 if (mailUid < serverUid) removeMsg(idx, TRUE);
00831 else if (mailUid == serverUid)
00832 {
00833 if (!mReadOnly)
00834 flagsToStatus(getMsgBase(idx), serverFlags, false);
00835 idx++;
00836 uid = (*it).items.remove(uid);
00837 }
00838 else break;
00839 }
00840 while (idx < count()) removeMsg(idx, TRUE);
00841 }
00842 for (uid = (*it).items.begin(); uid != (*it).items.end(); uid++)
00843 (*uid).truncate((*uid).find(","));
00844 ImapAccountBase::jobData jd( QString::null, (*it).parent );
00845
00846 jd.total = (*it).items.count();
00847 if (jd.total == 0)
00848 {
00849 quiet(false);
00850 mContentState = imapFinished;
00851 emit folderComplete(this, TRUE);
00852 mAccount->removeJob(it);
00853 mAccount->displayProgress();
00854 return;
00855 }
00856
00857 QStringList sets;
00858 uid = (*it).items.begin();
00859 if (jd.total == 1) sets.append(*uid + ":" + *uid);
00860 else sets = makeSets( (*it).items );
00861 mAccount->removeJob(it);
00862
00863 for (QStringList::Iterator i = sets.begin(); i != sets.end(); ++i)
00864 {
00865 KURL url = mAccount->getUrl();
00866 url.setPath(imapPath() + ";UID=" + *i + ";SECTION=ENVELOPE");
00867 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
00868 {
00869 quiet(false);
00870 emit folderComplete(this, FALSE);
00871 return;
00872 }
00873 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
00874 jd.url = url.url();
00875 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
00876 mAccount->insertJob(newJob, jd);
00877 connect(newJob, SIGNAL(result(KIO::Job *)),
00878 this, (i == sets.at(sets.count() - 1))
00879 ? SLOT(slotGetLastMessagesResult(KIO::Job *))
00880 : SLOT(slotGetMessagesResult(KIO::Job *)));
00881 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
00882 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
00883 }
00884 }
00885
00886
00887
00888 void KMFolderImap::slotListFolderEntries(KIO::Job * job,
00889 const KIO::UDSEntryList & uds)
00890 {
00891 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00892 if ( it == mAccount->jobsEnd() ) return;
00893 QString mimeType, name;
00894 long int flags = 0;
00895 for (KIO::UDSEntryList::ConstIterator udsIt = uds.begin();
00896 udsIt != uds.end(); udsIt++)
00897 {
00898 for (KIO::UDSEntry::ConstIterator eIt = (*udsIt).begin();
00899 eIt != (*udsIt).end(); eIt++)
00900 {
00901 if ((*eIt).m_uds == KIO::UDS_NAME)
00902 name = (*eIt).m_str;
00903 else if ((*eIt).m_uds == KIO::UDS_MIME_TYPE)
00904 mimeType = (*eIt).m_str;
00905 else if ((*eIt).m_uds == KIO::UDS_ACCESS)
00906 flags = (*eIt).m_long;
00907 }
00908 if (mimeType == "message/rfc822-imap" && !(flags & 8))
00909 (*it).items.append(name + "," + QString::number(flags));
00910 }
00911 }
00912
00913
00914
00915 void KMFolderImap::flagsToStatus(KMMsgBase *msg, int flags, bool newMsg)
00916 {
00917 if (flags & 4)
00918 msg->setStatus( KMMsgStatusFlag );
00919 if (flags & 2)
00920 msg->setStatus( KMMsgStatusReplied );
00921 if (flags & 1)
00922 msg->setStatus( KMMsgStatusOld );
00923
00924 if (msg->isOfUnknownStatus()) {
00925 if (newMsg)
00926 msg->setStatus( KMMsgStatusNew );
00927 else
00928 msg->setStatus( KMMsgStatusUnread );
00929 }
00930 }
00931
00932
00933
00934 QString KMFolderImap::statusToFlags(KMMsgStatus status)
00935 {
00936 QString flags;
00937 if (status & KMMsgStatusDeleted)
00938 flags = "\\DELETED";
00939 else {
00940 if (status & KMMsgStatusOld || status & KMMsgStatusRead)
00941 flags = "\\SEEN ";
00942 if (status & KMMsgStatusReplied)
00943 flags += "\\ANSWERED ";
00944 if (status & KMMsgStatusFlag)
00945 flags += "\\FLAGGED";
00946 }
00947
00948 return flags.simplifyWhiteSpace();
00949 }
00950
00951
00952 void
00953 KMFolderImap::ignoreJobsForMessage( KMMessage* msg )
00954 {
00955 if ( !msg || msg->transferInProgress() ||
00956 !msg->parent() || msg->parent()->folderType() != KMFolderTypeImap )
00957 return;
00958 KMAcctImap *account;
00959 if ( !(account = static_cast<KMFolderImap*>(msg->parent())->account()) )
00960 return;
00961
00962 account->ignoreJobsForMessage( msg );
00963 }
00964
00965
00966 void KMFolderImap::slotGetMessagesData(KIO::Job * job, const QByteArray & data)
00967 {
00968 if ( data.isEmpty() ) return;
00969 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00970 if ( it == mAccount->jobsEnd() ) return;
00971 (*it).cdata += QCString(data, data.size() + 1);
00972 int pos = (*it).cdata.find("\r\n--IMAPDIGEST");
00973 if (pos > 0)
00974 {
00975 int p = (*it).cdata.find("\r\nX-uidValidity:");
00976 if (p != -1) setUidValidity((*it).cdata
00977 .mid(p + 17, (*it).cdata.find("\r\n", p+1) - p - 17));
00978 int c = (*it).cdata.find("\r\nX-Count:");
00979 if ( c != -1 )
00980 {
00981 bool ok;
00982 int exists = (*it).cdata.mid( c+10,
00983 (*it).cdata.find("\r\n", c+1) - c-10 ).toInt(&ok);
00984 if ( ok && exists < count() )
00985 {
00986 kdDebug(5006) << "KMFolderImap::slotGetMessagesData - server has less messages (" <<
00987 exists << ") then folder (" << count() << "), so reload" << endl;
00988 mAccount->displayProgress();
00989 reallyGetFolder( QString::null );
00990 (*it).cdata.remove(0, pos);
00991 return;
00992 }
00993 }
00994 (*it).cdata.remove(0, pos);
00995 }
00996 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
00997 int flags;
00998 while (pos >= 0)
00999 {
01000 KMMessage *msg = new KMMessage;
01001 msg->fromString((*it).cdata.mid(16, pos - 16));
01002 flags = msg->headerField("X-Flags").toInt();
01003 ulong uid = msg->headerField("X-UID").toULong();
01004 if (flags & 8 || uid <= lastUid()) {
01005 delete msg;
01006 msg = 0;
01007 }
01008 else {
01009 if (uidmap.find(uid))
01010 {
01011
01012 const ulong sernum = (ulong) uidmap[uid];
01013 msg->setMsgSerNum(sernum);
01014
01015 uidmap.remove(uid);
01016 }
01017 open();
01018 KMFolderMbox::addMsg(msg, 0);
01019
01020 QString id = msg->msgIdMD5();
01021 if ( mMetaDataMap.find( id ) ) {
01022 KMMsgMetaData *md = mMetaDataMap[id];
01023 msg->setStatus( md->status() );
01024 if ( md->serNum() != 0 )
01025 msg->setMsgSerNum( md->serNum() );
01026 mMetaDataMap.remove( id );
01027 delete md;
01028 }
01029
01030 flagsToStatus((KMMsgBase*)msg, flags);
01031
01032 msg->setMsgLength( msg->headerField("X-Length").toUInt() );
01033 close();
01034
01035 if (count() > 1) unGetMsg(count() - 1);
01036 mLastUid = uid;
01037 }
01038 (*it).cdata.remove(0, pos);
01039 (*it).done++;
01040 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
01041 mAccount->displayProgress();
01042 }
01043 }
01044
01045
01046 FolderJob*
01047 KMFolderImap::doCreateJob( KMMessage *msg, FolderJob::JobType jt,
01048 KMFolder *folder, QString partSpecifier,
01049 const AttachmentStrategy *as ) const
01050 {
01051 KMFolderImap* kmfi = dynamic_cast<KMFolderImap*>(folder);
01052 if ( jt == FolderJob::tGetMessage && partSpecifier == "STRUCTURE" &&
01053 mAccount && mAccount->loadOnDemand() &&
01054 ( msg->signatureState() == KMMsgNotSigned ||
01055 msg->signatureState() == KMMsgSignatureStateUnknown ) )
01056 {
01057
01058
01059 ImapJob *job = new ImapJob( msg, jt, kmfi, "HEADER" );
01060 job->start();
01061 ImapJob *job2 = new ImapJob( msg, jt, kmfi, "STRUCTURE", as );
01062 job2->start();
01063 return job;
01064 } else {
01065
01066 if ( partSpecifier == "STRUCTURE" )
01067 partSpecifier = QString::null;
01068
01069 ImapJob *job = new ImapJob( msg, jt, kmfi, partSpecifier );
01070 return job;
01071 }
01072 }
01073
01074
01075 FolderJob*
01076 KMFolderImap::doCreateJob( QPtrList<KMMessage>& msgList, const QString& sets,
01077 FolderJob::JobType jt, KMFolder *folder ) const
01078 {
01079 KMFolderImap* kmfi = dynamic_cast<KMFolderImap*>(folder);
01080 ImapJob *job = new ImapJob( msgList, sets, jt, kmfi );
01081 return job;
01082 }
01083
01084
01085 void KMFolderImap::getMessagesResult(KIO::Job * job, bool lastSet)
01086 {
01087 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01088 if ( it == mAccount->jobsEnd() ) return;
01089 if (job->error())
01090 {
01091 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01092 job->errorText() );
01093 mContentState = imapNoInformation;
01094 quiet( false );
01095 emit folderComplete(this, false);
01096 }
01097 else
01098 {
01099 if (lastSet)
01100 {
01101 mContentState = imapFinished;
01102 quiet(false);
01103 emit folderComplete(this, true);
01104 }
01105 mAccount->removeJob(it);
01106 }
01107
01108 mAccount->displayProgress();
01109 }
01110
01111
01112
01113 void KMFolderImap::slotGetLastMessagesResult(KIO::Job * job)
01114 {
01115 getMessagesResult(job, true);
01116 }
01117
01118
01119
01120 void KMFolderImap::slotGetMessagesResult(KIO::Job * job)
01121 {
01122 getMessagesResult(job, false);
01123 }
01124
01125
01126
01127 void KMFolderImap::createFolder(const QString &name)
01128 {
01129 KURL url = mAccount->getUrl();
01130 url.setPath(imapPath() + name);
01131 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01132 return;
01133 KIO::SimpleJob *job = KIO::mkdir(url);
01134 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01135 ImapAccountBase::jobData jd( url.url(), this );
01136 jd.items = name;
01137 mAccount->insertJob(job, jd);
01138 connect(job, SIGNAL(result(KIO::Job *)),
01139 this, SLOT(slotCreateFolderResult(KIO::Job *)));
01140 }
01141
01142
01143
01144 void KMFolderImap::slotCreateFolderResult(KIO::Job * job)
01145 {
01146 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01147 if ( it == mAccount->jobsEnd() ) return;
01148 if (job->error())
01149 {
01150 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01151 job->errorText() );
01152 } else {
01153 listDirectory();
01154 }
01155 mAccount->removeJob(job);
01156 }
01157
01158
01159
01160 static QTextCodec *sUtf7Codec = 0;
01161
01162 QTextCodec * KMFolderImap::utf7Codec()
01163 {
01164 if (!sUtf7Codec) sUtf7Codec = QTextCodec::codecForName("utf-7");
01165 return sUtf7Codec;
01166 }
01167
01168
01169
01170 QString KMFolderImap::encodeFileName(const QString &name)
01171 {
01172 QString result = utf7Codec()->fromUnicode(name);
01173 return KURL::encode_string_no_slash(result);
01174 }
01175
01176
01177
01178 QString KMFolderImap::decodeFileName(const QString &name)
01179 {
01180 QString result = KURL::decode_string(name);
01181 return utf7Codec()->toUnicode(result.latin1());
01182 }
01183
01184
01185 bool KMFolderImap::autoExpunge()
01186 {
01187 if (mAccount)
01188 return mAccount->autoExpunge();
01189
01190 return false;
01191 }
01192
01193
01194
01195 void KMFolderImap::slotSimpleData(KIO::Job * job, const QByteArray & data)
01196 {
01197 if ( data.isEmpty() ) return;
01198 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01199 if ( it == mAccount->jobsEnd() ) return;
01200 QBuffer buff((*it).data);
01201 buff.open(IO_WriteOnly | IO_Append);
01202 buff.writeBlock(data.data(), data.size());
01203 buff.close();
01204 }
01205
01206
01207 void KMFolderImap::deleteMessage(KMMessage * msg)
01208 {
01209 KURL url = mAccount->getUrl();
01210 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msg->parent());
01211 const QString uid = msg->headerField("X-UID");
01212
01213
01214
01215 if ( uid.isEmpty() ) {
01216 kdDebug( 5006 ) << "KMFolderImap::deleteMessage: Attempt to delete "
01217 "an empty UID. Aborting." << endl;
01218 return;
01219 }
01220 url.setPath(msg_parent->imapPath() + ";UID=" + uid );
01221 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01222 return;
01223 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01224 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01225 ImapAccountBase::jobData jd( url.url(), 0 );
01226 mAccount->insertJob(job, jd);
01227 connect(job, SIGNAL(result(KIO::Job *)),
01228 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01229 }
01230
01231 void KMFolderImap::deleteMessage(QPtrList<KMMessage> msgList)
01232 {
01233 QValueList<int> uids;
01234 getUids(msgList, uids);
01235 QStringList sets = makeSets(uids);
01236
01237 KURL url = mAccount->getUrl();
01238 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msgList.first()->parent());
01239 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
01240 {
01241 const QString uid = *it;
01242
01243
01244 if ( uid.isEmpty() ) continue;
01245 url.setPath(msg_parent->imapPath() + ";UID=" + uid);
01246 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01247 return;
01248 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01249 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01250 ImapAccountBase::jobData jd( url.url(), 0 );
01251 mAccount->insertJob(job, jd);
01252 connect(job, SIGNAL(result(KIO::Job *)),
01253 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01254 }
01255 }
01256
01257
01258 void KMFolderImap::setStatus(int idx, KMMsgStatus status, bool toggle)
01259 {
01260 QValueList<int> ids; ids.append(idx);
01261 setStatus(ids, status, toggle);
01262 }
01263
01264 void KMFolderImap::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle)
01265 {
01266 KMFolder::setStatus(ids, status, toggle);
01267 if (mReadOnly) return;
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 QMap< QString, QStringList > groups;
01280 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it ) {
01281 KMMessage *msg = 0;
01282 bool unget = !isMessage(*it);
01283 msg = getMsg(*it);
01284 if (!msg) continue;
01285 QString flags = statusToFlags(msg->status());
01286
01287 groups[flags].append(msg->headerField("X-UID"));
01288 if (unget) unGetMsg(*it);
01289 }
01290 QMapIterator< QString, QStringList > dit;
01291 for ( dit = groups.begin(); dit != groups.end(); ++dit ) {
01292 QCString flags = dit.key().latin1();
01293 QStringList sets = makeSets( (*dit), true );
01294
01295 for ( QStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
01296 QString imappath = imapPath() + ";UID=" + ( *slit );
01297 setImapStatus(imappath, flags);
01298 }
01299 }
01300 mAccount->displayProgress();
01301 }
01302
01303
01304 QStringList KMFolderImap::makeSets(QStringList& uids, bool sort)
01305 {
01306 QValueList<int> tmp;
01307 for ( QStringList::Iterator it = uids.begin(); it != uids.end(); ++it )
01308 tmp.append( (*it).toInt() );
01309 return makeSets(tmp, sort);
01310 }
01311
01312 QStringList KMFolderImap::makeSets(QValueList<int>& uids, bool sort)
01313 {
01314 QStringList sets;
01315 QString set;
01316
01317 if (uids.size() == 1)
01318 {
01319 sets.append(QString::number(uids.first()));
01320 return sets;
01321 }
01322
01323 if (sort) qHeapSort(uids);
01324
01325 int last = 0;
01326
01327 bool inserted = false;
01328
01329 for ( QValueList<int>::Iterator it = uids.begin(); it != uids.end(); ++it )
01330 {
01331 if (it == uids.begin() || set.isEmpty()) {
01332 set = QString::number(*it);
01333 inserted = true;
01334 } else
01335 {
01336 if (last+1 != *it)
01337 {
01338
01339 if (inserted)
01340 set += ',' + QString::number(*it);
01341 else
01342 set += ':' + QString::number(last) + ',' + QString::number(*it);
01343 inserted = true;
01344 if (set.length() > 100)
01345 {
01346
01347 sets.append(set);
01348 set = "";
01349 }
01350 } else {
01351 inserted = false;
01352 }
01353 }
01354 last = *it;
01355 }
01356
01357 if (!inserted)
01358 set += ':' + QString::number(uids.last());
01359
01360 if (!set.isEmpty()) sets.append(set);
01361
01362 return sets;
01363 }
01364
01365
01366 void KMFolderImap::getUids(QValueList<int>& ids, QValueList<int>& uids)
01367 {
01368 KMMessage *msg = 0;
01369
01370 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01371 {
01372 bool unget = !isMessage(*it);
01373 msg = getMsg(*it);
01374 if (!msg) continue;
01375 uids.append(msg->headerField("X-UID").toInt());
01376 if (unget) unGetMsg(*it);
01377 }
01378 }
01379
01380 void KMFolderImap::getUids(QPtrList<KMMessage>& msgList, QValueList<int>& uids, KMFolder* msgParent)
01381 {
01382 KMMessage *msg = 0;
01383
01384 if (!msgParent) msgParent = msgList.first()->parent();
01385 if (!msgParent) return;
01386
01387 for ( msg = msgList.first(); msg; msg = msgList.next() )
01388 {
01389 if ( !msg->headerField("X-UID").isEmpty() )
01390 uids.append(msg->headerField("X-UID").toInt());
01391 }
01392 }
01393
01394
01395 void KMFolderImap::setImapStatus(QString path, QCString flags)
01396 {
01397
01398 kdDebug(5006) << "setImapStatus path=" << path << endl;
01399 KURL url = mAccount->getUrl();
01400 url.setPath(path);
01401
01402 QByteArray packedArgs;
01403 QDataStream stream( packedArgs, IO_WriteOnly);
01404
01405 stream << (int) 'S' << url << flags;
01406
01407 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01408 return;
01409 KIO::SimpleJob *job = KIO::special(url, packedArgs, FALSE);
01410 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01411 ImapAccountBase::jobData jd( url.url(), 0 );
01412 mAccount->insertJob(job, jd);
01413 connect(job, SIGNAL(result(KIO::Job *)),
01414 SLOT(slotSetStatusResult(KIO::Job *)));
01415 }
01416
01417
01418
01419 void KMFolderImap::expungeFolder(KMFolderImap * aFolder, bool quiet)
01420 {
01421 aFolder->setNeedsCompacting(FALSE);
01422 KURL url = mAccount->getUrl();
01423 url.setPath(aFolder->imapPath() + ";UID=*");
01424 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01425 return;
01426 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01427 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01428 ImapAccountBase::jobData jd( url.url(), 0 );
01429 jd.quiet = quiet;
01430 mAccount->insertJob(job, jd);
01431 connect(job, SIGNAL(result(KIO::Job *)),
01432 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01433 }
01434
01435
01436
01437 void KMFolderImap::slotSetStatusResult(KIO::Job * job)
01438 {
01439 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01440 if ( it == mAccount->jobsEnd() ) return;
01441 mAccount->removeJob(it);
01442 if (job->error() && job->error() != KIO::ERR_CANNOT_OPEN_FOR_WRITING)
01443 {
01444 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01445 job->errorText() );
01446 }
01447 mAccount->displayProgress();
01448 }
01449
01450
01451
01452 bool KMFolderImap::processNewMail(bool)
01453 {
01454
01455 if ( !mAccount ) {
01456 kdWarning(5006) << "KMFolderImap::processNewMail - account is null!" << endl;
01457 return false;
01458 }
01459 if (imapPath().isEmpty()) {
01460 kdWarning(5006) << "KMFolderImap::processNewMail - imapPath of " << name() << " is empty!" << endl;
01461 kmkernel->imapFolderMgr()->remove(this);
01462 return false;
01463 }
01464 KURL url = mAccount->getUrl();
01465 if (mReadOnly)
01466 url.setPath(imapPath() + ";SECTION=UIDNEXT");
01467 else
01468 url.setPath(imapPath() + ";SECTION=UNSEEN");
01469 if ( mAccount->makeConnection() != ImapAccountBase::Connected ) {
01470 kdWarning(5006) << "KMFolderImap::processNewMail - got no connection!" << endl;
01471 return false;
01472 }
01473 KIO::SimpleJob *job = KIO::stat(url, FALSE);
01474 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01475 ImapAccountBase::jobData jd(url.url());
01476 mAccount->insertJob(job, jd);
01477 connect(job, SIGNAL(result(KIO::Job *)),
01478 SLOT(slotStatResult(KIO::Job *)));
01479 return true;
01480 }
01481
01482
01483
01484 void KMFolderImap::slotStatResult(KIO::Job * job)
01485 {
01486 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01487 if ( it == mAccount->jobsEnd() ) return;
01488 mAccount->removeJob(it);
01489 if (job->error())
01490 {
01491 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01492 job->errorText() );
01493 } else {
01494 KIO::UDSEntry uds = static_cast<KIO::StatJob*>(job)->statResult();
01495 for (KIO::UDSEntry::ConstIterator it = uds.begin(); it != uds.end(); it++)
01496 {
01497 if ((*it).m_uds == KIO::UDS_SIZE)
01498 {
01499 if (mReadOnly)
01500 {
01501 mGuessedUnreadMsgs = -1;
01502 mGuessedUnreadMsgs = countUnread() + (*it).m_long - lastUid() - 1;
01503 if (mGuessedUnreadMsgs < 0) mGuessedUnreadMsgs = 0;
01504 } else {
01505 mGuessedUnreadMsgs = (*it).m_long;
01506 }
01507 }
01508 }
01509 }
01510 emit numUnreadMsgsChanged( this );
01511 mAccount->displayProgress();
01512 }
01513
01514
01515 int KMFolderImap::create(bool imap)
01516 {
01517 readConfig();
01518 mUnreadMsgs = -1;
01519 return KMFolderMbox::create(imap);
01520 }
01521
01522 QValueList<int> KMFolderImap::splitSets(QString uids)
01523 {
01524 QValueList<int> uidlist;
01525
01526
01527 QString buffer = QString::null;
01528 int setstart = -1;
01529
01530 for (uint i = 0; i < uids.length(); i++)
01531 {
01532 QChar chr = uids[i];
01533 if (chr == ',')
01534 {
01535 if (setstart > -1)
01536 {
01537
01538 for (int j = setstart; j <= buffer.toInt(); j++)
01539 {
01540 uidlist.append(j);
01541 }
01542 setstart = -1;
01543 } else {
01544
01545 uidlist.append(buffer.toInt());
01546 }
01547 buffer = "";
01548 } else if (chr == ':') {
01549
01550 setstart = buffer.toInt();
01551 buffer = "";
01552 } else if (chr.category() == QChar::Number_DecimalDigit) {
01553
01554 buffer += chr;
01555 } else {
01556
01557 }
01558 }
01559
01560 if (setstart > -1)
01561 {
01562 for (int j = setstart; j <= buffer.toInt(); j++)
01563 {
01564 uidlist.append(j);
01565 }
01566 } else {
01567 uidlist.append(buffer.toInt());
01568 }
01569
01570 return uidlist;
01571 }
01572
01573 #include "kmfolderimap.moc"