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