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 mAccount->hasInbox())
00600 continue;
00601 for (node = mChild->first(); node; node = mChild->next())
00602 if (!node->isDir() && node->name() == mSubfolderNames[i]) break;
00603 if (node) folder = static_cast<KMFolderImap*>(node);
00604 else {
00605 folder = static_cast<KMFolderImap*>
00606 (mChild->createFolder(mSubfolderNames[i]));
00607 if (folder)
00608 {
00609 folder->close();
00610 kmkernel->imapFolderMgr()->contentsChanged();
00611 } else {
00612 kdWarning(5006) << "can't create folder " << mSubfolderNames[i] << endl;
00613 }
00614 }
00615 if (folder)
00616 {
00617 folder->setAccount(mAccount);
00618 folder->setNoContent(mSubfolderMimeTypes[i] == "inode/directory");
00619 folder->setImapPath(mSubfolderPaths[i]);
00620 if (mSubfolderMimeTypes[i] == "message/directory" ||
00621 mSubfolderMimeTypes[i] == "inode/directory")
00622 folder->listDirectory();
00623 }
00624 }
00625 }
00626
00627 kmkernel->imapFolderMgr()->quiet(FALSE);
00628 }
00629
00630
00631 void KMFolderImap::checkValidity()
00632 {
00633 if (!mAccount) {
00634 emit folderComplete(this, false);
00635 return;
00636 }
00637 KURL url = mAccount->getUrl();
00638 url.setPath(imapPath() + ";UID=0:0");
00639 kdDebug(5006) << "KMFolderImap::checkValidity of: " << imapPath() << endl;
00640 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
00641 {
00642 kdWarning(5006) << "KMFolderImap::checkValidity - got no connection" << endl;
00643 emit folderComplete(this, FALSE);
00644 return;
00645 }
00646
00647 if (mCheckingValidity) {
00648 kdDebug(5006) << "KMFolderImap::checkValidity - already checking" << endl;
00649 return;
00650 }
00651 ImapAccountBase::jobData jd( url.url(), this );
00652 KIO::SimpleJob *job = KIO::get(url, FALSE, FALSE);
00653 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
00654 mAccount->insertJob(job, jd);
00655 connect(job, SIGNAL(result(KIO::Job *)),
00656 SLOT(slotCheckValidityResult(KIO::Job *)));
00657 connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)),
00658 SLOT(slotSimpleData(KIO::Job *, const QByteArray &)));
00659
00660 mCheckingValidity = true;
00661
00662 }
00663
00664
00665
00666 ulong KMFolderImap::lastUid()
00667 {
00668 if (mLastUid) return mLastUid;
00669 open();
00670 if (count() > 0)
00671 {
00672 bool unget = !isMessage(count() - 1);
00673 KMMessage *msg = getMsg(count() - 1);
00674 mLastUid = msg->headerField("X-UID").toULong();
00675 if (unget) unGetMsg(count() - 1);
00676 }
00677 close();
00678 return mLastUid;
00679 }
00680
00681
00682
00683 void KMFolderImap::slotCheckValidityResult(KIO::Job * job)
00684 {
00685 kdDebug(5006) << "KMFolderImap::slotCheckValidityResult of: " << fileName() << endl;
00686 mCheckingValidity = false;
00687 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00688 if ( it == mAccount->jobsEnd() ) return;
00689 if (job->error()) {
00690 mAccount->slotSlaveError(mAccount->slave(), job->error(), job->errorText());
00691 emit folderComplete(this, FALSE);
00692 mAccount->displayProgress();
00693 } else {
00694 QCString cstr((*it).data.data(), (*it).data.size() + 1);
00695 int a = cstr.find("X-uidValidity: ");
00696 int b = cstr.find("\r\n", a);
00697 QString uidv;
00698 if ( (b - a - 15) >= 0 ) uidv = cstr.mid(a + 15, b - a - 15);
00699 a = cstr.find("X-Access: ");
00700 b = cstr.find("\r\n", a);
00701 QString access;
00702 if ( (b - a - 10) >= 0 ) access = cstr.mid(a + 10, b - a - 10);
00703 mReadOnly = access == "Read only";
00704 QString startUid;
00705 if (uidValidity() != uidv)
00706 {
00707
00708 kdDebug(5006) << "KMFolderImap::slotCheckValidityResult uidValidty changed." << endl;
00709 mAccount->ignoreJobsForFolder(this);
00710 expunge();
00711 mLastUid = 0;
00712 uidmap.clear();
00713 setUidValidity(uidv);
00714 } else {
00715 if (!mCheckFlags)
00716 startUid = QString::number(lastUid() + 1);
00717 }
00718 mAccount->removeJob(it);
00719 reallyGetFolder(startUid);
00720 }
00721 }
00722
00723
00724 void KMFolderImap::getAndCheckFolder(bool force)
00725 {
00726 if (mNoContent)
00727 return getFolder(force);
00728
00729 if ( mAccount )
00730 mAccount->processNewMailSingleFolder(this);
00731 if (force) {
00732
00733 mCheckFlags = TRUE;
00734 }
00735 }
00736
00737
00738 void KMFolderImap::getFolder(bool force)
00739 {
00740 mGuessedUnreadMsgs = -1;
00741 if (mNoContent)
00742 {
00743 mContentState = imapFinished;
00744 emit folderComplete(this, true);
00745 return;
00746 }
00747 mContentState = imapInProgress;
00748 if (force) {
00749
00750 mCheckFlags = TRUE;
00751 }
00752 checkValidity();
00753 }
00754
00755
00756
00757 void KMFolderImap::reallyGetFolder(const QString &startUid)
00758 {
00759 KURL url = mAccount->getUrl();
00760 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
00761 {
00762 emit folderComplete(this, FALSE);
00763 mAccount->displayProgress();
00764 return;
00765 }
00766 quiet(true);
00767 if (startUid.isEmpty())
00768 {
00769 url.setPath(imapPath() + ";SECTION=UID FLAGS");
00770 KIO::SimpleJob *job = KIO::listDir(url, FALSE);
00771 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
00772 ImapAccountBase::jobData jd( url.url(), this );
00773 mAccount->insertJob(job, jd);
00774 connect(job, SIGNAL(result(KIO::Job *)),
00775 this, SLOT(slotListFolderResult(KIO::Job *)));
00776 connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList &)),
00777 this, SLOT(slotListFolderEntries(KIO::Job *,
00778 const KIO::UDSEntryList &)));
00779 } else {
00780 url.setPath(imapPath() + ";UID=" + startUid
00781 + ":*;SECTION=ENVELOPE");
00782 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
00783 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
00784 ImapAccountBase::jobData jd( url.url(), this );
00785 mAccount->insertJob(newJob, jd);
00786 connect(newJob, SIGNAL(result(KIO::Job *)),
00787 this, SLOT(slotGetLastMessagesResult(KIO::Job *)));
00788 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
00789 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
00790 }
00791 }
00792
00793
00794
00795 void KMFolderImap::slotListFolderResult(KIO::Job * job)
00796 {
00797 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00798 if ( it == mAccount->jobsEnd() ) return;
00799 QString uids;
00800 if (job->error())
00801 {
00802 mAccount->slotSlaveError( mAccount->slave(), job->error(),
00803 job->errorText() );
00804 quiet( false );
00805 emit folderComplete(this, FALSE);
00806 mAccount->removeJob(it);
00807 mAccount->displayProgress();
00808 return;
00809 }
00810 mCheckFlags = FALSE;
00811 QStringList::Iterator uid;
00812
00813 if (count())
00814 {
00815 QCString cstr;
00816 int idx = 0, a, b, c, serverFlags;
00817 long int mailUid, serverUid;
00818 uid = (*it).items.begin();
00819 while (idx < count() && uid != (*it).items.end())
00820 {
00821 getMsgString(idx, cstr);
00822 a = cstr.find("X-UID: ");
00823 b = cstr.find("\n", a);
00824 if (a == -1 || b == -1) mailUid = -1;
00825 else mailUid = cstr.mid(a + 7, b - a - 7).toLong();
00826 c = (*uid).find(",");
00827 serverUid = (*uid).left(c).toLong();
00828 serverFlags = (*uid).mid(c+1).toInt();
00829 if (mailUid < serverUid) removeMsg(idx, TRUE);
00830 else if (mailUid == serverUid)
00831 {
00832 if (!mReadOnly)
00833 flagsToStatus(getMsgBase(idx), serverFlags, false);
00834 idx++;
00835 uid = (*it).items.remove(uid);
00836 }
00837 else break;
00838 }
00839 while (idx < count()) removeMsg(idx, TRUE);
00840 }
00841 for (uid = (*it).items.begin(); uid != (*it).items.end(); uid++)
00842 (*uid).truncate((*uid).find(","));
00843 ImapAccountBase::jobData jd( QString::null, (*it).parent );
00844
00845 jd.total = (*it).items.count();
00846 if (jd.total == 0)
00847 {
00848 quiet(false);
00849 mContentState = imapFinished;
00850 emit folderComplete(this, TRUE);
00851 mAccount->removeJob(it);
00852 mAccount->displayProgress();
00853 return;
00854 }
00855
00856 QStringList sets;
00857 uid = (*it).items.begin();
00858 if (jd.total == 1) sets.append(*uid + ":" + *uid);
00859 else sets = makeSets( (*it).items );
00860 mAccount->removeJob(it);
00861
00862 for (QStringList::Iterator i = sets.begin(); i != sets.end(); ++i)
00863 {
00864 KURL url = mAccount->getUrl();
00865 url.setPath(imapPath() + ";UID=" + *i + ";SECTION=ENVELOPE");
00866 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
00867 {
00868 quiet(false);
00869 emit folderComplete(this, FALSE);
00870 return;
00871 }
00872 KIO::SimpleJob *newJob = KIO::get(url, FALSE, FALSE);
00873 jd.url = url.url();
00874 KIO::Scheduler::assignJobToSlave(mAccount->slave(), newJob);
00875 mAccount->insertJob(newJob, jd);
00876 connect(newJob, SIGNAL(result(KIO::Job *)),
00877 this, (i == sets.at(sets.count() - 1))
00878 ? SLOT(slotGetLastMessagesResult(KIO::Job *))
00879 : SLOT(slotGetMessagesResult(KIO::Job *)));
00880 connect(newJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
00881 this, SLOT(slotGetMessagesData(KIO::Job *, const QByteArray &)));
00882 }
00883 }
00884
00885
00886
00887 void KMFolderImap::slotListFolderEntries(KIO::Job * job,
00888 const KIO::UDSEntryList & uds)
00889 {
00890 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00891 if ( it == mAccount->jobsEnd() ) return;
00892 QString mimeType, name;
00893 long int flags = 0;
00894 for (KIO::UDSEntryList::ConstIterator udsIt = uds.begin();
00895 udsIt != uds.end(); udsIt++)
00896 {
00897 for (KIO::UDSEntry::ConstIterator eIt = (*udsIt).begin();
00898 eIt != (*udsIt).end(); eIt++)
00899 {
00900 if ((*eIt).m_uds == KIO::UDS_NAME)
00901 name = (*eIt).m_str;
00902 else if ((*eIt).m_uds == KIO::UDS_MIME_TYPE)
00903 mimeType = (*eIt).m_str;
00904 else if ((*eIt).m_uds == KIO::UDS_ACCESS)
00905 flags = (*eIt).m_long;
00906 }
00907 if (mimeType == "message/rfc822-imap" && !(flags & 8))
00908 (*it).items.append(name + "," + QString::number(flags));
00909 }
00910 }
00911
00912
00913
00914 void KMFolderImap::flagsToStatus(KMMsgBase *msg, int flags, bool newMsg)
00915 {
00916 if (flags & 4)
00917 msg->setStatus( KMMsgStatusFlag );
00918 if (flags & 2)
00919 msg->setStatus( KMMsgStatusReplied );
00920 if (flags & 1)
00921 msg->setStatus( KMMsgStatusOld );
00922
00923 if (msg->isOfUnknownStatus()) {
00924 if (newMsg)
00925 msg->setStatus( KMMsgStatusNew );
00926 else
00927 msg->setStatus( KMMsgStatusUnread );
00928 }
00929 }
00930
00931
00932
00933 QString KMFolderImap::statusToFlags(KMMsgStatus status)
00934 {
00935 QString flags;
00936 if (status & KMMsgStatusDeleted)
00937 flags = "\\DELETED";
00938 else {
00939 if (status & KMMsgStatusOld || status & KMMsgStatusRead)
00940 flags = "\\SEEN ";
00941 if (status & KMMsgStatusReplied)
00942 flags += "\\ANSWERED ";
00943 if (status & KMMsgStatusFlag)
00944 flags += "\\FLAGGED";
00945 }
00946
00947 return flags.simplifyWhiteSpace();
00948 }
00949
00950
00951 void
00952 KMFolderImap::ignoreJobsForMessage( KMMessage* msg )
00953 {
00954 if ( !msg || msg->transferInProgress() ||
00955 !msg->parent() || msg->parent()->folderType() != KMFolderTypeImap )
00956 return;
00957 KMAcctImap *account;
00958 if ( !(account = static_cast<KMFolderImap*>(msg->parent())->account()) )
00959 return;
00960
00961 account->ignoreJobsForMessage( msg );
00962 }
00963
00964
00965 void KMFolderImap::slotGetMessagesData(KIO::Job * job, const QByteArray & data)
00966 {
00967 if ( data.isEmpty() ) return;
00968 ImapAccountBase::JobIterator it = mAccount->findJob(job);
00969 if ( it == mAccount->jobsEnd() ) return;
00970 (*it).cdata += QCString(data, data.size() + 1);
00971 int pos = (*it).cdata.find("\r\n--IMAPDIGEST");
00972 if (pos > 0)
00973 {
00974 int p = (*it).cdata.find("\r\nX-uidValidity:");
00975 if (p != -1) setUidValidity((*it).cdata
00976 .mid(p + 17, (*it).cdata.find("\r\n", p+1) - p - 17));
00977 int c = (*it).cdata.find("\r\nX-Count:");
00978 if ( c != -1 )
00979 {
00980 bool ok;
00981 int exists = (*it).cdata.mid( c+10,
00982 (*it).cdata.find("\r\n", c+1) - c-10 ).toInt(&ok);
00983 if ( ok && exists < count() )
00984 {
00985 kdDebug(5006) << "KMFolderImap::slotGetMessagesData - server has less messages (" <<
00986 exists << ") then folder (" << count() << "), so reload" << endl;
00987 mAccount->displayProgress();
00988 reallyGetFolder( QString::null );
00989 (*it).cdata.remove(0, pos);
00990 return;
00991 }
00992 }
00993 (*it).cdata.remove(0, pos);
00994 }
00995 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
00996 int flags;
00997 while (pos >= 0)
00998 {
00999 KMMessage *msg = new KMMessage;
01000 msg->fromString((*it).cdata.mid(16, pos - 16));
01001 flags = msg->headerField("X-Flags").toInt();
01002 ulong uid = msg->headerField("X-UID").toULong();
01003 if (flags & 8 || uid <= lastUid()) {
01004 delete msg;
01005 msg = 0;
01006 }
01007 else {
01008 if (uidmap.find(uid))
01009 {
01010
01011 const ulong sernum = (ulong) uidmap[uid];
01012 msg->setMsgSerNum(sernum);
01013
01014 uidmap.remove(uid);
01015 }
01016 open();
01017 KMFolderMbox::addMsg(msg, 0);
01018
01019 QString id = msg->msgIdMD5();
01020 if ( mMetaDataMap.find( id ) ) {
01021 KMMsgMetaData *md = mMetaDataMap[id];
01022 msg->setStatus( md->status() );
01023 if ( md->serNum() != 0 )
01024 msg->setMsgSerNum( md->serNum() );
01025 mMetaDataMap.remove( id );
01026 delete md;
01027 }
01028
01029 flagsToStatus((KMMsgBase*)msg, flags);
01030
01031 msg->setMsgLength( msg->headerField("X-Length").toUInt() );
01032 close();
01033
01034 if (count() > 1) unGetMsg(count() - 1);
01035 mLastUid = uid;
01036 }
01037 (*it).cdata.remove(0, pos);
01038 (*it).done++;
01039 pos = (*it).cdata.find("\r\n--IMAPDIGEST", 1);
01040 mAccount->displayProgress();
01041 }
01042 }
01043
01044
01045 FolderJob*
01046 KMFolderImap::doCreateJob( KMMessage *msg, FolderJob::JobType jt,
01047 KMFolder *folder, QString partSpecifier,
01048 const AttachmentStrategy *as ) const
01049 {
01050 KMFolderImap* kmfi = dynamic_cast<KMFolderImap*>(folder);
01051 if ( jt == FolderJob::tGetMessage && partSpecifier == "STRUCTURE" &&
01052 mAccount && mAccount->loadOnDemand() &&
01053 ( msg->signatureState() == KMMsgNotSigned ||
01054 msg->signatureState() == KMMsgSignatureStateUnknown ) )
01055 {
01056
01057
01058 ImapJob *job = new ImapJob( msg, jt, kmfi, "HEADER" );
01059 job->start();
01060 ImapJob *job2 = new ImapJob( msg, jt, kmfi, "STRUCTURE", as );
01061 job2->start();
01062 return job;
01063 } else {
01064
01065 if ( partSpecifier == "STRUCTURE" )
01066 partSpecifier = QString::null;
01067
01068 ImapJob *job = new ImapJob( msg, jt, kmfi, partSpecifier );
01069 return job;
01070 }
01071 }
01072
01073
01074 FolderJob*
01075 KMFolderImap::doCreateJob( QPtrList<KMMessage>& msgList, const QString& sets,
01076 FolderJob::JobType jt, KMFolder *folder ) const
01077 {
01078 KMFolderImap* kmfi = dynamic_cast<KMFolderImap*>(folder);
01079 ImapJob *job = new ImapJob( msgList, sets, jt, kmfi );
01080 return job;
01081 }
01082
01083
01084 void KMFolderImap::getMessagesResult(KIO::Job * job, bool lastSet)
01085 {
01086 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01087 if ( it == mAccount->jobsEnd() ) return;
01088 if (job->error())
01089 {
01090 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01091 job->errorText() );
01092 mContentState = imapNoInformation;
01093 quiet( false );
01094 emit folderComplete(this, false);
01095 }
01096 else
01097 {
01098 if (lastSet)
01099 {
01100 mContentState = imapFinished;
01101 quiet(false);
01102 emit folderComplete(this, true);
01103 }
01104 mAccount->removeJob(it);
01105 }
01106
01107 mAccount->displayProgress();
01108 }
01109
01110
01111
01112 void KMFolderImap::slotGetLastMessagesResult(KIO::Job * job)
01113 {
01114 getMessagesResult(job, true);
01115 }
01116
01117
01118
01119 void KMFolderImap::slotGetMessagesResult(KIO::Job * job)
01120 {
01121 getMessagesResult(job, false);
01122 }
01123
01124
01125
01126 void KMFolderImap::createFolder(const QString &name)
01127 {
01128 KURL url = mAccount->getUrl();
01129 url.setPath(imapPath() + name);
01130 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01131 return;
01132 KIO::SimpleJob *job = KIO::mkdir(url);
01133 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01134 ImapAccountBase::jobData jd( url.url(), this );
01135 jd.items = name;
01136 mAccount->insertJob(job, jd);
01137 connect(job, SIGNAL(result(KIO::Job *)),
01138 this, SLOT(slotCreateFolderResult(KIO::Job *)));
01139 }
01140
01141
01142
01143 void KMFolderImap::slotCreateFolderResult(KIO::Job * job)
01144 {
01145 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01146 if ( it == mAccount->jobsEnd() ) return;
01147 if (job->error())
01148 {
01149 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01150 job->errorText() );
01151 } else {
01152 listDirectory();
01153 }
01154 mAccount->removeJob(job);
01155 }
01156
01157
01158
01159 static QTextCodec *sUtf7Codec = 0;
01160
01161 QTextCodec * KMFolderImap::utf7Codec()
01162 {
01163 if (!sUtf7Codec) sUtf7Codec = QTextCodec::codecForName("utf-7");
01164 return sUtf7Codec;
01165 }
01166
01167
01168
01169 QString KMFolderImap::encodeFileName(const QString &name)
01170 {
01171 QString result = utf7Codec()->fromUnicode(name);
01172 return KURL::encode_string_no_slash(result);
01173 }
01174
01175
01176
01177 QString KMFolderImap::decodeFileName(const QString &name)
01178 {
01179 QString result = KURL::decode_string(name);
01180 return utf7Codec()->toUnicode(result.latin1());
01181 }
01182
01183
01184 bool KMFolderImap::autoExpunge()
01185 {
01186 if (mAccount)
01187 return mAccount->autoExpunge();
01188
01189 return false;
01190 }
01191
01192
01193
01194 void KMFolderImap::slotSimpleData(KIO::Job * job, const QByteArray & data)
01195 {
01196 if ( data.isEmpty() ) return;
01197 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01198 if ( it == mAccount->jobsEnd() ) return;
01199 QBuffer buff((*it).data);
01200 buff.open(IO_WriteOnly | IO_Append);
01201 buff.writeBlock(data.data(), data.size());
01202 buff.close();
01203 }
01204
01205
01206 void KMFolderImap::deleteMessage(KMMessage * msg)
01207 {
01208 KURL url = mAccount->getUrl();
01209 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msg->parent());
01210 const QString uid = msg->headerField("X-UID");
01211
01212
01213
01214 if ( uid.isEmpty() ) {
01215 kdDebug( 5006 ) << "KMFolderImap::deleteMessage: Attempt to delete "
01216 "an empty UID. Aborting." << endl;
01217 return;
01218 }
01219 url.setPath(msg_parent->imapPath() + ";UID=" + uid );
01220 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01221 return;
01222 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01223 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01224 ImapAccountBase::jobData jd( url.url(), 0 );
01225 mAccount->insertJob(job, jd);
01226 connect(job, SIGNAL(result(KIO::Job *)),
01227 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01228 }
01229
01230 void KMFolderImap::deleteMessage(QPtrList<KMMessage> msgList)
01231 {
01232 QValueList<int> uids;
01233 getUids(msgList, uids);
01234 QStringList sets = makeSets(uids);
01235
01236 KURL url = mAccount->getUrl();
01237 KMFolderImap *msg_parent = static_cast<KMFolderImap*>(msgList.first()->parent());
01238 for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
01239 {
01240 const QString uid = *it;
01241
01242
01243 if ( uid.isEmpty() ) continue;
01244 url.setPath(msg_parent->imapPath() + ";UID=" + uid);
01245 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01246 return;
01247 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01248 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01249 ImapAccountBase::jobData jd( url.url(), 0 );
01250 mAccount->insertJob(job, jd);
01251 connect(job, SIGNAL(result(KIO::Job *)),
01252 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01253 }
01254 }
01255
01256
01257 void KMFolderImap::setStatus(int idx, KMMsgStatus status, bool toggle)
01258 {
01259 QValueList<int> ids; ids.append(idx);
01260 setStatus(ids, status, toggle);
01261 }
01262
01263 void KMFolderImap::setStatus(QValueList<int>& ids, KMMsgStatus status, bool toggle)
01264 {
01265 KMFolder::setStatus(ids, status, toggle);
01266 if (mReadOnly) return;
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278 QMap< QString, QStringList > groups;
01279 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it ) {
01280 KMMessage *msg = 0;
01281 bool unget = !isMessage(*it);
01282 msg = getMsg(*it);
01283 if (!msg) continue;
01284 QString flags = statusToFlags(msg->status());
01285
01286 groups[flags].append(msg->headerField("X-UID"));
01287 if (unget) unGetMsg(*it);
01288 }
01289 QMapIterator< QString, QStringList > dit;
01290 for ( dit = groups.begin(); dit != groups.end(); ++dit ) {
01291 QCString flags = dit.key().latin1();
01292 QStringList sets = makeSets( (*dit), true );
01293
01294 for ( QStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
01295 QString imappath = imapPath() + ";UID=" + ( *slit );
01296 setImapStatus(imappath, flags);
01297 }
01298 }
01299 mAccount->displayProgress();
01300 }
01301
01302
01303 QStringList KMFolderImap::makeSets(QStringList& uids, bool sort)
01304 {
01305 QValueList<int> tmp;
01306 for ( QStringList::Iterator it = uids.begin(); it != uids.end(); ++it )
01307 tmp.append( (*it).toInt() );
01308 return makeSets(tmp, sort);
01309 }
01310
01311 QStringList KMFolderImap::makeSets(QValueList<int>& uids, bool sort)
01312 {
01313 QStringList sets;
01314 QString set;
01315
01316 if (uids.size() == 1)
01317 {
01318 sets.append(QString::number(uids.first()));
01319 return sets;
01320 }
01321
01322 if (sort) qHeapSort(uids);
01323
01324 int last = 0;
01325
01326 bool inserted = false;
01327
01328 for ( QValueList<int>::Iterator it = uids.begin(); it != uids.end(); ++it )
01329 {
01330 if (it == uids.begin() || set.isEmpty()) {
01331 set = QString::number(*it);
01332 inserted = true;
01333 } else
01334 {
01335 if (last+1 != *it)
01336 {
01337
01338 if (inserted)
01339 set += ',' + QString::number(*it);
01340 else
01341 set += ':' + QString::number(last) + ',' + QString::number(*it);
01342 inserted = true;
01343 if (set.length() > 100)
01344 {
01345
01346 sets.append(set);
01347 set = "";
01348 }
01349 } else {
01350 inserted = false;
01351 }
01352 }
01353 last = *it;
01354 }
01355
01356 if (!inserted)
01357 set += ':' + QString::number(uids.last());
01358
01359 if (!set.isEmpty()) sets.append(set);
01360
01361 return sets;
01362 }
01363
01364
01365 void KMFolderImap::getUids(QValueList<int>& ids, QValueList<int>& uids)
01366 {
01367 KMMessage *msg = 0;
01368
01369 for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
01370 {
01371 bool unget = !isMessage(*it);
01372 msg = getMsg(*it);
01373 if (!msg) continue;
01374 uids.append(msg->headerField("X-UID").toInt());
01375 if (unget) unGetMsg(*it);
01376 }
01377 }
01378
01379 void KMFolderImap::getUids(QPtrList<KMMessage>& msgList, QValueList<int>& uids, KMFolder* msgParent)
01380 {
01381 KMMessage *msg = 0;
01382
01383 if (!msgParent) msgParent = msgList.first()->parent();
01384 if (!msgParent) return;
01385
01386 for ( msg = msgList.first(); msg; msg = msgList.next() )
01387 {
01388 if ( !msg->headerField("X-UID").isEmpty() )
01389 uids.append(msg->headerField("X-UID").toInt());
01390 }
01391 }
01392
01393
01394 void KMFolderImap::setImapStatus(QString path, QCString flags)
01395 {
01396
01397 kdDebug(5006) << "setImapStatus path=" << path << endl;
01398 KURL url = mAccount->getUrl();
01399 url.setPath(path);
01400
01401 QByteArray packedArgs;
01402 QDataStream stream( packedArgs, IO_WriteOnly);
01403
01404 stream << (int) 'S' << url << flags;
01405
01406 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01407 return;
01408 KIO::SimpleJob *job = KIO::special(url, packedArgs, FALSE);
01409 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01410 ImapAccountBase::jobData jd( url.url(), 0 );
01411 mAccount->insertJob(job, jd);
01412 connect(job, SIGNAL(result(KIO::Job *)),
01413 SLOT(slotSetStatusResult(KIO::Job *)));
01414 }
01415
01416
01417
01418 void KMFolderImap::expungeFolder(KMFolderImap * aFolder, bool quiet)
01419 {
01420 aFolder->setNeedsCompacting(FALSE);
01421 KURL url = mAccount->getUrl();
01422 url.setPath(aFolder->imapPath() + ";UID=*");
01423 if ( mAccount->makeConnection() != ImapAccountBase::Connected )
01424 return;
01425 KIO::SimpleJob *job = KIO::file_delete(url, FALSE);
01426 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01427 ImapAccountBase::jobData jd( url.url(), 0 );
01428 jd.quiet = quiet;
01429 mAccount->insertJob(job, jd);
01430 connect(job, SIGNAL(result(KIO::Job *)),
01431 mAccount, SLOT(slotSimpleResult(KIO::Job *)));
01432 }
01433
01434
01435
01436 void KMFolderImap::slotSetStatusResult(KIO::Job * job)
01437 {
01438 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01439 if ( it == mAccount->jobsEnd() ) return;
01440 mAccount->removeJob(it);
01441 if (job->error() && job->error() != KIO::ERR_CANNOT_OPEN_FOR_WRITING)
01442 {
01443 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01444 job->errorText() );
01445 }
01446 mAccount->displayProgress();
01447 }
01448
01449
01450
01451 bool KMFolderImap::processNewMail(bool)
01452 {
01453
01454 if ( !mAccount ) {
01455 kdWarning(5006) << "KMFolderImap::processNewMail - account is null!" << endl;
01456 return false;
01457 }
01458 if (imapPath().isEmpty()) {
01459 kdWarning(5006) << "KMFolderImap::processNewMail - imapPath of " << name() << " is empty!" << endl;
01460 kmkernel->imapFolderMgr()->remove(this);
01461 return false;
01462 }
01463 KURL url = mAccount->getUrl();
01464 if (mReadOnly)
01465 url.setPath(imapPath() + ";SECTION=UIDNEXT");
01466 else
01467 url.setPath(imapPath() + ";SECTION=UNSEEN");
01468 if ( mAccount->makeConnection() != ImapAccountBase::Connected ) {
01469 kdWarning(5006) << "KMFolderImap::processNewMail - got no connection!" << endl;
01470 return false;
01471 }
01472 KIO::SimpleJob *job = KIO::stat(url, FALSE);
01473 KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
01474 ImapAccountBase::jobData jd(url.url());
01475 mAccount->insertJob(job, jd);
01476 connect(job, SIGNAL(result(KIO::Job *)),
01477 SLOT(slotStatResult(KIO::Job *)));
01478 return true;
01479 }
01480
01481
01482
01483 void KMFolderImap::slotStatResult(KIO::Job * job)
01484 {
01485 ImapAccountBase::JobIterator it = mAccount->findJob(job);
01486 if ( it == mAccount->jobsEnd() ) return;
01487 mAccount->removeJob(it);
01488 if (job->error())
01489 {
01490 mAccount->slotSlaveError( mAccount->slave(), job->error(),
01491 job->errorText() );
01492 } else {
01493 KIO::UDSEntry uds = static_cast<KIO::StatJob*>(job)->statResult();
01494 for (KIO::UDSEntry::ConstIterator it = uds.begin(); it != uds.end(); it++)
01495 {
01496 if ((*it).m_uds == KIO::UDS_SIZE)
01497 {
01498 if (mReadOnly)
01499 {
01500 mGuessedUnreadMsgs = -1;
01501 mGuessedUnreadMsgs = countUnread() + (*it).m_long - lastUid() - 1;
01502 if (mGuessedUnreadMsgs < 0) mGuessedUnreadMsgs = 0;
01503 } else {
01504 mGuessedUnreadMsgs = (*it).m_long;
01505 }
01506 }
01507 }
01508 }
01509 emit numUnreadMsgsChanged( this );
01510 mAccount->displayProgress();
01511 }
01512
01513
01514 int KMFolderImap::create(bool imap)
01515 {
01516 readConfig();
01517 mUnreadMsgs = -1;
01518 return KMFolderMbox::create(imap);
01519 }
01520
01521 QValueList<int> KMFolderImap::splitSets(QString uids)
01522 {
01523 QValueList<int> uidlist;
01524
01525
01526 QString buffer = QString::null;
01527 int setstart = -1;
01528
01529 for (uint i = 0; i < uids.length(); i++)
01530 {
01531 QChar chr = uids[i];
01532 if (chr == ',')
01533 {
01534 if (setstart > -1)
01535 {
01536
01537 for (int j = setstart; j <= buffer.toInt(); j++)
01538 {
01539 uidlist.append(j);
01540 }
01541 setstart = -1;
01542 } else {
01543
01544 uidlist.append(buffer.toInt());
01545 }
01546 buffer = "";
01547 } else if (chr == ':') {
01548
01549 setstart = buffer.toInt();
01550 buffer = "";
01551 } else if (chr.category() == QChar::Number_DecimalDigit) {
01552
01553 buffer += chr;
01554 } else {
01555
01556 }
01557 }
01558
01559 if (setstart > -1)
01560 {
01561 for (int j = setstart; j <= buffer.toInt(); j++)
01562 {
01563 uidlist.append(j);
01564 }
01565 } else {
01566 uidlist.append(buffer.toInt());
01567 }
01568
01569 return uidlist;
01570 }
01571
01572 #include "kmfolderimap.moc"