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