28 #include "kmfolderimap.h"
29 #include "kmfoldermbox.h"
30 #include "kmfoldertree.h"
31 #include "kmmsgdict.h"
32 #include "undostack.h"
33 #include "kmfoldermgr.h"
34 #include "kmfiltermgr.h"
35 #include "kmmsgdict.h"
36 #include "imapaccountbase.h"
37 using KMail::ImapAccountBase;
40 #include "attachmentstrategy.h"
41 using KMail::AttachmentStrategy;
42 #include "progressmanager.h"
43 using KPIM::ProgressItem;
44 using KPIM::ProgressManager;
47 #include "kmsearchpattern.h"
48 #include "searchjob.h"
50 #include "renamejob.h"
55 #include <tdeio/scheduler.h>
56 #include <tdeconfig.h>
59 #include <tqtextcodec.h>
60 #include <tqstylesheet.h>
64 KMFolderImap::KMFolderImap(
KMFolder* folder,
const char* aName)
65 : KMFolderMbox(folder, aName),
66 mUploadAllFlags( false )
68 mContentState = imapNoInformation;
69 mSubfolderState = imapNoInformation;
75 mCheckingValidity =
false;
78 mAlreadyRemoved =
false;
79 mHasChildren = ChildrenUnknown;
80 mMailCheckProgressItem = 0;
81 mListDirProgressItem = 0;
82 mAddMessageProgressItem = 0;
85 connect (
this, TQ_SIGNAL( folderComplete( KMFolderImap*,
bool ) ),
86 this, TQ_SLOT( slotCompleteMailCheckProgress()) );
89 KMFolderImap::~KMFolderImap()
92 mAccount->removeSlaveJobsForFolder( folder() );
97 if ( mAccount->checkingMail( folder() ) ) {
98 mAccount->killAllJobs();
102 if (kmkernel->undoStack()) kmkernel->undoStack()->folderDestroyed( folder() );
103 mMetaDataMap.setAutoDelete(
true );
104 mMetaDataMap.clear();
105 mUidMetaDataMap.setAutoDelete(
true );
106 mUidMetaDataMap.clear();
111 void KMFolderImap::reallyDoClose(
const char* owner)
115 account()->ignoreJobsForFolder( folder() );
118 if ( mMsgList[idx]->isMessage() ) {
124 KMFolderMbox::reallyDoClose( owner );
127 KMFolder* KMFolderImap::trashFolder()
const
129 TQString trashStr = account()->trash();
130 return kmkernel->imapFolderMgr()->findIdString( trashStr );
136 if(!(idx >= 0 && idx <= count()))
139 KMMsgBase* mb = getMsgBase(idx);
153 KMAcctImap* KMFolderImap::account()
const
157 if ( !parentFolderDir ) {
158 kdWarning() << k_funcinfo <<
"No parent folder dir found for " << name() << endl;
162 if ( !parentFolder ) {
163 kdWarning() << k_funcinfo <<
"No parent folder found for " << name() << endl;
166 KMFolderImap *parentStorage =
dynamic_cast<KMFolderImap*
>( parentFolder->storage() );
168 mAccount = parentStorage->account();
173 void KMFolderImap::setAccount(KMAcctImap *aAccount)
176 if( !folder() || !folder()->child() )
return;
178 for (node = folder()->child()->first(); node;
179 node = folder()->
child()->next())
182 static_cast<KMFolderImap*
>(
static_cast<KMFolder*
>(node)->storage())->setAccount(aAccount);
187 void KMFolderImap::readConfig()
189 TDEConfig* config = KMKernel::config();
190 TDEConfigGroupSaver saver(config,
"Folder-" + folder()->idString());
191 mCheckMail = config->readBoolEntry(
"checkmail",
true);
193 mUidValidity = config->readEntry(
"UidValidity");
194 if ( mImapPath.isEmpty() ) {
195 setImapPath( config->readEntry(
"ImapPath") );
197 if (TQString(name()).upper() ==
"INBOX" && mImapPath ==
"/INBOX/")
199 folder()->setSystemFolder(
true );
200 folder()->setLabel( i18n(
"inbox") );
202 mNoContent = config->readBoolEntry(
"NoContent",
false);
203 mReadOnly = config->readBoolEntry(
"ReadOnly",
false);
204 mUploadAllFlags = config->readBoolEntry(
"UploadAllFlags",
true );
205 mPermanentFlags = config->readNumEntry(
"PermanentFlags", 31 );
211 void KMFolderImap::writeConfig()
213 TDEConfig* config = KMKernel::config();
214 TDEConfigGroupSaver saver(config,
"Folder-" + folder()->idString());
215 config->writeEntry(
"checkmail", mCheckMail);
216 config->writeEntry(
"UidValidity", mUidValidity);
217 config->writeEntry(
"ImapPath", mImapPath);
218 config->writeEntry(
"NoContent", mNoContent);
219 config->writeEntry(
"ReadOnly", mReadOnly);
220 config->writeEntry(
"UploadAllFlags", mUploadAllFlags );
221 config->writeEntry(
"PermanentFlags", mPermanentFlags );
226 void KMFolderImap::remove()
228 if ( mAlreadyRemoved || !account() )
234 KURL url = account()->getUrl();
235 url.setPath(imapPath());
236 if ( account()->makeConnection() == ImapAccountBase::Error ||
237 imapPath().isEmpty() )
239 emit removed(folder(),
false);
242 TDEIO::SimpleJob *job = TDEIO::file_delete(url,
false);
243 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
244 ImapAccountBase::jobData jd(url.url());
245 jd.progressItem = ProgressManager::createProgressItem(
246 "ImapFolderRemove" + ProgressManager::getUniqueID(),
247 i18n(
"Removing folder"),
248 i18n(
"URL: %1" ).arg( TQStyleSheet::escape( folder()->prettyURL() ) ),
250 account()->useSSL() || account()->useTLS() );
251 account()->insertJob(job, jd);
252 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
253 this, TQ_SLOT(slotRemoveFolderResult(TDEIO::Job *)));
257 void KMFolderImap::slotRemoveFolderResult(TDEIO::Job *job)
259 ImapAccountBase::JobIterator it = account()->findJob(job);
260 if ( it == account()->jobsEnd() )
return;
263 account()->handleJobError( job, i18n(
"Error while removing a folder.") );
264 emit removed(folder(),
false);
266 account()->removeJob(it);
273 void KMFolderImap::removeMsg(
int idx,
bool quiet)
288 void KMFolderImap::removeMsg(
const TQPtrList<KMMessage>& msgList,
bool quiet )
290 if ( msgList.isEmpty() )
return;
292 deleteMessage(msgList);
301 TQPtrListIterator<KMMessage> it( msgList );
303 while ( (msg = it.current()) != 0 ) {
313 int KMFolderImap::rename(
const TQString& newName,
KMFolderDir *aParent )
317 kmkernel->folderMgr()->contentsChanged();
322 void KMFolderImap::addMsgQuiet(
KMMessage* aMsg)
325 TQ_UINT32 serNum = 0;
328 serNum = aMsg->getMsgSerNum();
329 kmkernel->undoStack()->pushSingleAction( serNum, aFolder, folder() );
330 int idx = aFolder->
find( aMsg );
332 aFolder->
take( idx );
334 if ( !account()->hasCapability(
"uidplus") ) {
337 mMetaDataMap.insert( aMsg->msgIdMD5(),
338 new KMMsgMetaData(aMsg->
status(), serNum) );
347 void KMFolderImap::addMsgQuiet(TQPtrList<KMMessage> msgList)
349 if ( mAddMessageProgressItem )
351 mAddMessageProgressItem->setComplete();
352 mAddMessageProgressItem = 0;
354 KMFolder *aFolder = msgList.first()->parent();
356 bool uidplus = account()->hasCapability(
"uidplus");
357 for (
KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
360 undoId = kmkernel->undoStack()->newUndoAction( aFolder, folder() );
361 if ( msg->getMsgSerNum() > 0 )
362 kmkernel->undoStack()->addMsgToAction( undoId, msg->getMsgSerNum() );
366 mMetaDataMap.insert( msg->msgIdMD5(),
367 new KMMsgMetaData(msg->
status(), msg->getMsgSerNum()) );
372 aFolder->
take( msgList );
374 kdDebug(5006) << k_funcinfo <<
"no parent" << endl;
376 msgList.setAutoDelete(
true);
382 int KMFolderImap::addMsg(
KMMessage* aMsg,
int* aIndex_ret)
384 TQPtrList<KMMessage> list;
386 TQValueList<int> index;
387 int ret = addMsg(list, index);
388 aIndex_ret = &index.first();
392 int KMFolderImap::addMsg(TQPtrList<KMMessage>& msgList, TQValueList<int>& aIndex_ret)
395 KMFolder *msgParent = aMsg->parent();
397 ImapJob *imapJob = 0;
400 if (msgParent->
folderType() == KMFolderTypeImap)
402 if (
static_cast<KMFolderImap*
>(msgParent->storage())->account() == account())
405 for (
KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
408 if (folder() == msgParent)
411 for (
KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
415 int idx = msgParent->
find(msg);
417 msg = msgParent->
getMsg(idx);
419 imapJob =
new ImapJob(msg, ImapJob::tPutMessage,
this);
420 connect(imapJob, TQ_SIGNAL(messageStored(
KMMessage*)),
422 connect(imapJob, TQ_SIGNAL(result(KMail::FolderJob*)),
423 TQ_SLOT(slotCopyMsgResult(KMail::FolderJob*)));
430 TQValueList<ulong> uids;
431 getUids(msgList, uids);
434 TQStringList sets = makeSets(uids,
false);
436 for ( TQStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
439 TQPtrList<KMMessage> temp_msgs = splitMessageList(*it, msgList);
440 if ( temp_msgs.isEmpty() ) kdDebug(5006) <<
"Wow! KMFolderImap::splitMessageList() returned an empty list!" << endl;
441 imapJob =
new ImapJob(temp_msgs, *it, ImapJob::tMoveMessage,
this);
442 connect(imapJob, TQ_SIGNAL(messageCopied(TQPtrList<KMMessage>)),
443 TQ_SLOT(addMsgQuiet(TQPtrList<KMMessage>)));
444 connect(imapJob, TQ_SIGNAL(result(KMail::FolderJob*)),
445 TQ_SLOT(slotCopyMsgResult(KMail::FolderJob*)));
454 TQPtrListIterator<KMMessage> it( msgList );
456 while ( (msg = it.current()) != 0 )
460 if (!canAddMsgNow(msg, &index)) {
472 if ( !msgList.isEmpty() )
475 TQPtrListIterator<KMMessage> it( msgList );
477 while ( ( msg = it.current() ) != 0 )
483 imapJob =
new ImapJob( msgList, TQString(), ImapJob::tPutMessage,
this );
484 if ( !mAddMessageProgressItem && msgList.count() > 1 )
488 mAddMessageProgressItem = ProgressManager::createProgressItem(
489 "Uploading"+ProgressManager::getUniqueID(),
490 i18n(
"Uploading message data"),
491 i18n(
"Destination folder: %1").arg( TQStyleSheet::escape( folder()->prettyURL() ) ),
493 account()->useSSL() || account()->useTLS() );
494 mAddMessageProgressItem->setTotalItems( msgList.count() );
495 connect ( mAddMessageProgressItem, TQ_SIGNAL( progressItemCanceled( KPIM::ProgressItem*)),
496 account(), TQ_SLOT( slotAbortRequested( KPIM::ProgressItem* ) ) );
497 imapJob->setParentProgressItem( mAddMessageProgressItem );
499 connect( imapJob, TQ_SIGNAL( messageCopied(TQPtrList<KMMessage>) ),
500 TQ_SLOT( addMsgQuiet(TQPtrList<KMMessage>) ) );
501 connect( imapJob, TQ_SIGNAL(result(KMail::FolderJob*)),
502 TQ_SLOT(slotCopyMsgResult(KMail::FolderJob*)) );
510 void KMFolderImap::slotCopyMsgResult( KMail::FolderJob* job )
512 kdDebug(5006) << k_funcinfo << job->error() << endl;
514 emit folderComplete(
this,
false );
518 void KMFolderImap::copyMsg(TQPtrList<KMMessage>& msgList)
520 if ( !account()->hasCapability(
"uidplus") ) {
521 for (
KMMessage *msg = msgList.first(); msg; msg = msgList.next() ) {
524 mMetaDataMap.insert( msg->msgIdMD5(),
new KMMsgMetaData(msg->
status()) );
528 TQValueList<ulong> uids;
529 getUids(msgList, uids);
530 TQStringList sets = makeSets(uids,
false);
531 for ( TQStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
534 TQPtrList<KMMessage> temp_msgs = splitMessageList(*it, msgList);
536 ImapJob *job =
new ImapJob(temp_msgs, *it, ImapJob::tCopyMessage,
this);
537 connect(job, TQ_SIGNAL(result(KMail::FolderJob*)),
538 TQ_SLOT(slotCopyMsgResult(KMail::FolderJob*)));
544 TQPtrList<KMMessage> KMFolderImap::splitMessageList(
const TQString& set,
545 TQPtrList<KMMessage>& msgList)
547 int lastcomma = set.findRev(
",");
548 int lastdub = set.findRev(
":");
550 if (lastdub > lastcomma) last = lastdub;
551 else last = lastcomma;
553 if (last < 0) last = set.length();
555 const TQString last_uid = set.right(set.length() - last);
556 TQPtrList<KMMessage> temp_msgs;
558 if (!last_uid.isEmpty())
560 TQPtrListIterator<KMMessage> it( msgList );
562 while ( (msg = it.current()) != 0 )
565 temp_msgs.append(msg);
566 uid.setNum( msg->
UID() );
569 if (uid == last_uid)
break;
584 KMMsgBase* mb(mMsgList[idx]);
586 if (!mb->isMessage()) readMsg(idx);
595 void KMFolderImap::take(TQPtrList<KMMessage> msgList)
597 deleteMessage(msgList);
604 void KMFolderImap::slotListNamespaces()
606 disconnect( account(), TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
607 this, TQ_SLOT( slotListNamespaces() ) );
608 if ( account()->makeConnection() == ImapAccountBase::Error )
610 kdWarning(5006) <<
"slotListNamespaces - got no connection" << endl;
612 }
else if ( account()->makeConnection() == ImapAccountBase::Connecting )
615 kdDebug(5006) <<
"slotListNamespaces - waiting for connection" << endl;
616 connect( account(), TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
617 this, TQ_SLOT( slotListNamespaces() ) );
620 kdDebug(5006) <<
"slotListNamespaces" << endl;
622 setSubfolderState( imapNoInformation );
623 mSubfolderState = imapListingInProgress;
624 account()->setHasInbox(
false );
626 ImapAccountBase::ListType type = ImapAccountBase::List;
627 if ( account()->onlySubscribedFolders() )
628 type = ImapAccountBase::ListSubscribed;
630 ImapAccountBase::nsMap map = account()->namespaces();
631 TQStringList personal = map[ImapAccountBase::PersonalNS];
633 for ( TQStringList::Iterator it = personal.begin(); it != personal.end(); ++it )
636 account()->addPathToNamespace( *it ) );
639 connect( job, TQ_SIGNAL(receivedFolders(
const TQStringList&,
const TQStringList&,
640 const TQStringList&,
const TQStringList&,
const ImapAccountBase::jobData&)),
641 this, TQ_SLOT(slotListResult(
const TQStringList&,
const TQStringList&,
642 const TQStringList&,
const TQStringList&,
const ImapAccountBase::jobData&)));
647 TQStringList ns = map[ImapAccountBase::OtherUsersNS];
648 ns += map[ImapAccountBase::SharedNS];
649 for ( TQStringList::Iterator it = ns.begin(); it != ns.end(); ++it )
653 connect( job, TQ_SIGNAL(receivedFolders(
const TQStringList&,
const TQStringList&,
654 const TQStringList&,
const TQStringList&,
const ImapAccountBase::jobData&)),
655 this, TQ_SLOT(slotCheckNamespace(
const TQStringList&,
const TQStringList&,
656 const TQStringList&,
const TQStringList&,
const ImapAccountBase::jobData&)));
662 void KMFolderImap::slotCheckNamespace(
const TQStringList& subfolderNames,
663 const TQStringList& subfolderPaths,
664 const TQStringList& subfolderMimeTypes,
665 const TQStringList& subfolderAttributes,
666 const ImapAccountBase::jobData& jobData )
668 kdDebug(5006) <<
"slotCheckNamespace - " << subfolderNames.join(
",") << endl;
672 TQString name = jobData.path.mid( 1, jobData.path.length()-2 );
673 name.remove( account()->delimiterForNamespace( name ) );
674 if ( name.isEmpty() ) {
676 slotListResult( subfolderNames, subfolderPaths,
677 subfolderMimeTypes, subfolderAttributes, jobData );
682 KMFolderNode *node = 0;
683 for ( node = folder()->child()->first(); node;
684 node = folder()->
child()->next())
686 if ( !node->isDir() && node->name() == name )
689 if ( subfolderNames.isEmpty() )
693 kdDebug(5006) <<
"delete namespace folder " << name << endl;
695 KMFolderImap* nsFolder =
static_cast<KMFolderImap*
>(fld->storage());
696 nsFolder->setAlreadyRemoved(
true );
697 kmkernel->imapFolderMgr()->remove( fld );
703 kdDebug(5006) <<
"found namespace folder " << name << endl;
704 if ( !account()->listOnlyOpenFolders() )
706 KMFolderImap* nsFolder =
707 static_cast<KMFolderImap*
>(
static_cast<KMFolder*
>(node)->storage());
708 nsFolder->slotListResult( subfolderNames, subfolderPaths,
709 subfolderMimeTypes, subfolderAttributes, jobData );
714 kdDebug(5006) <<
"create namespace folder " << name << endl;
717 KMFolderImap* f =
static_cast<KMFolderImap*
> ( fld->storage() );
718 f->initializeFrom(
this, account()->addPathToNamespace( name ),
720 f->
close(
"kmfolderimap_create" );
721 if ( !account()->listOnlyOpenFolders() )
723 f->slotListResult( subfolderNames, subfolderPaths,
724 subfolderMimeTypes, subfolderAttributes, jobData );
727 kmkernel->imapFolderMgr()->contentsChanged();
733 bool KMFolderImap::listDirectory()
736 ( account() && account()->makeConnection() == ImapAccountBase::Error ) )
738 kdDebug(5006) <<
"KMFolderImap::listDirectory - got no connection" << endl;
742 if (
this == account()->rootFolder() )
745 slotListNamespaces();
748 mSubfolderState = imapListingInProgress;
751 ImapAccountBase::ListType type = ImapAccountBase::List;
752 if ( account()->onlySubscribedFolders() )
753 type = ImapAccountBase::ListSubscribed;
757 connect( job, TQ_SIGNAL(receivedFolders(
const TQStringList&,
const TQStringList&,
758 const TQStringList&,
const TQStringList&,
const ImapAccountBase::jobData&)),
759 this, TQ_SLOT(slotListResult(
const TQStringList&,
const TQStringList&,
760 const TQStringList&,
const TQStringList&,
const ImapAccountBase::jobData&)));
768 void KMFolderImap::slotListResult(
const TQStringList& subfolderNames,
769 const TQStringList& subfolderPaths,
770 const TQStringList& subfolderMimeTypes,
771 const TQStringList& subfolderAttributes,
772 const ImapAccountBase::jobData& jobData )
774 mSubfolderState = imapFinished;
779 kmkernel->imapFolderMgr()->quiet(
true);
781 bool root = (
this == account()->rootFolder() );
783 if ( root && !account()->hasInbox() )
792 if ( root && !subfolderNames.empty() )
794 KMFolderImap* parent = findParent( subfolderPaths.first(), subfolderNames.first() );
797 kdDebug(5006) <<
"KMFolderImap::slotListResult - pass listing to "
798 << parent->label() << endl;
799 parent->slotListResult( subfolderNames, subfolderPaths,
800 subfolderMimeTypes, subfolderAttributes, jobData );
803 checkFolders( list, jobData.curNamespace );
805 emit directoryListingFinished(
this );
806 kmkernel->imapFolderMgr()->quiet(
false );
811 bool emptyList = ( root && subfolderNames.empty() );
814 checkFolders( subfolderNames, jobData.curNamespace );
818 KMFolderNode *node = 0;
819 for ( uint i = 0; i < subfolderNames.count(); i++ )
821 bool settingsChanged =
false;
823 for ( node = folder()->child()->first(); node;
824 node = folder()->
child()->next() ) {
825 if ( !node->isDir() && node->name() == subfolderNames[i] )
829 f =
static_cast<KMFolderImap*
>(
static_cast<KMFolder*
>(node)->storage());
831 else if ( subfolderPaths[i].upper() !=
"/INBOX/" )
833 kdDebug(5006) <<
"create folder " << subfolderNames[i] << endl;
836 f =
static_cast<KMFolderImap*
> ( fld->storage() );
837 f->
close(
"kmfolderimap_create" );
838 settingsChanged =
true;
840 kdWarning(5006) <<
"can't create folder " << subfolderNames[i] << endl;
846 if ( f->imapPath().isEmpty() ) {
847 settingsChanged =
true;
850 account()->listDirProgressItem()->incCompletedItems();
851 account()->listDirProgressItem()->updateProgress();
852 account()->listDirProgressItem()->setStatus( folder()->prettyURL() + i18n(
" completed") );
854 f->initializeFrom(
this, subfolderPaths[i], subfolderMimeTypes[i] );
855 f->setChildrenState( subfolderAttributes[i] );
856 if ( account()->listOnlyOpenFolders() &&
857 f->hasChildren() != FolderStorage::ChildrenUnknown )
859 settingsChanged =
true;
862 if ( settingsChanged )
865 kmkernel->imapFolderMgr()->contentsChanged();
867 if ( ( subfolderMimeTypes[i] ==
"message/directory" ||
868 subfolderMimeTypes[i] ==
"inode/directory" ) &&
869 !account()->listOnlyOpenFolders() )
874 kdWarning(5006) <<
"can't find folder " << subfolderNames[i] << endl;
879 kmkernel->imapFolderMgr()->quiet(
false );
880 emit directoryListingFinished(
this );
881 account()->listDirProgressItem()->setComplete();
885 void KMFolderImap::initInbox()
888 KMFolderNode *node = 0;
890 for (node = folder()->child()->first(); node;
891 node = folder()->
child()->next()) {
892 if (!node->isDir() && node->name() ==
"INBOX")
break;
895 f =
static_cast<KMFolderImap*
>(
static_cast<KMFolder*
>(node)->storage());
897 f =
static_cast<KMFolderImap*
>
901 f->folder()->setLabel( i18n(
"inbox") );
902 f->close(
"kmfolderimap" );
904 kmkernel->imapFolderMgr()->contentsChanged();
907 f->initializeFrom(
this,
"/INBOX/",
"message/directory" );
908 f->setChildrenState( TQString() );
911 account()->setHasInbox(
true );
915 KMFolderImap* KMFolderImap::findParent(
const TQString& path,
const TQString& name )
917 TQString parent = path.left( path.length() - name.length() - 2 );
918 if ( parent.length() > 1 )
921 parent = parent.right( parent.length() - 1 );
922 if ( parent != label() )
924 KMFolderNode *node = folder()->
child()->first();
928 if ( node->name() == parent )
931 KMFolderImap* imapFld =
static_cast<KMFolderImap*
>( fld->storage() );
934 node = folder()->
child()->next();
942 void KMFolderImap::checkFolders(
const TQStringList& subfolderNames,
943 const TQString& myNamespace )
945 TQPtrList<KMFolder> toRemove;
946 KMFolderNode *node = folder()->
child()->first();
949 if ( !node->isDir() && subfolderNames.findIndex(node->name()) == -1 )
952 KMFolderImap* imapFld =
static_cast<KMFolderImap*
>( fld->storage() );
955 bool isInNamespace = ( myNamespace.isEmpty() ||
956 myNamespace == account()->namespaceForFolder( imapFld ) );
957 kdDebug(5006) << node->name() <<
" in namespace " << myNamespace <<
":" <<
958 isInNamespace << endl;
960 TQString name = node->name();
961 bool ignore = ( (
this == account()->rootFolder() ) &&
962 ( imapFld->imapPath() ==
"/INBOX/" ||
963 account()->isNamespaceFolder( name ) ||
966 if ( imapFld->imapPath().isEmpty() ) {
972 kdDebug(5006) <<
"checkFolders - " << node->name() <<
" disappeared" << endl;
973 imapFld->setAlreadyRemoved(
true );
974 toRemove.append( fld );
976 kdDebug(5006) <<
"checkFolders - " << node->name() <<
" ignored" << endl;
979 node = folder()->
child()->next();
982 for (
KMFolder* doomed=toRemove.first(); doomed; doomed = toRemove.next() )
983 kmkernel->imapFolderMgr()->remove( doomed );
987 void KMFolderImap::initializeFrom( KMFolderImap* parent, TQString folderPath,
990 setAccount( parent->account() );
991 setImapPath( folderPath );
992 setNoContent( mimeType ==
"inode/directory" );
993 setNoChildren( mimeType ==
"message/digest" );
997 bool KMFolderImap::mailCheckInProgress()
const
999 return getContentState() != imapNoInformation &&
1000 getContentState() != imapFinished;
1004 void KMFolderImap::setChildrenState( TQString attributes )
1007 if ( attributes.find(
"haschildren", 0,
false ) != -1 )
1009 setHasChildren( FolderStorage::HasChildren );
1010 }
else if ( attributes.find(
"hasnochildren", 0,
false ) != -1 ||
1011 attributes.find(
"noinferiors", 0,
false ) != -1 )
1013 setHasChildren( FolderStorage::HasNoChildren );
1016 if ( account()->listOnlyOpenFolders() ) {
1017 setHasChildren( FolderStorage::HasChildren );
1019 setHasChildren( FolderStorage::ChildrenUnknown );
1025 void KMFolderImap::checkValidity()
1028 emit folderComplete(
this,
false);
1029 close(
"checkvalidity");
1032 KURL url = account()->getUrl();
1033 url.setPath(imapPath() +
";UID=0:0");
1034 kdDebug(5006) <<
"KMFolderImap::checkValidity of: " << imapPath() << endl;
1037 disconnect( account(), TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
1038 this, TQ_SLOT( checkValidity() ) );
1040 KMAcctImap::ConnectionState connectionState = account()->makeConnection();
1041 if ( connectionState == ImapAccountBase::Error ) {
1042 kdDebug(5006) <<
"KMFolderImap::checkValidity - got no connection" << endl;
1043 emit folderComplete(
this,
false);
1044 mContentState = imapNoInformation;
1045 close(
"checkvalidity");
1047 }
else if ( connectionState == ImapAccountBase::Connecting ) {
1050 kdDebug(5006) <<
"CheckValidity - waiting for connection" << endl;
1051 connect( account(), TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
1052 this, TQ_SLOT( checkValidity() ) );
1056 if (mCheckingValidity) {
1057 kdDebug(5006) <<
"KMFolderImap::checkValidity - already checking" << endl;
1058 close(
"checkvalidity");
1062 if ( !mMailCheckProgressItem ) {
1063 ProgressItem* parent = ( account()->checkingSingleFolder() ? 0 :
1064 account()->mailCheckProgressItem() );
1065 mMailCheckProgressItem = ProgressManager::createProgressItem(
1067 "MailCheck" + folder()->prettyURL(),
1068 TQStyleSheet::escape( folder()->prettyURL() ),
1071 account()->useSSL() || account()->useTLS() );
1073 mMailCheckProgressItem->setProgress(0);
1075 if ( account()->mailCheckProgressItem() ) {
1076 account()->mailCheckProgressItem()->setStatus( folder()->prettyURL() );
1078 ImapAccountBase::jobData jd( url.url() );
1079 TDEIO::SimpleJob *job = TDEIO::get(url,
false,
false);
1080 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
1081 account()->insertJob(job, jd);
1082 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1083 TQ_SLOT(slotCheckValidityResult(TDEIO::Job *)));
1084 connect(job, TQ_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
1085 TQ_SLOT(slotSimpleData(TDEIO::Job *,
const TQByteArray &)));
1087 mCheckingValidity =
true;
1092 ulong KMFolderImap::lastUid()
1099 KMMsgBase * base = getMsgBase(count()-1);
1100 mLastUid = base->UID();
1108 void KMFolderImap::slotCheckValidityResult(TDEIO::Job * job)
1110 kdDebug(5006) <<
"KMFolderImap::slotCheckValidityResult of: " << fileName() << endl;
1111 mCheckingValidity =
false;
1112 ImapAccountBase::JobIterator it = account()->findJob(job);
1113 if ( it == account()->jobsEnd() )
return;
1115 if ( job->error() != TDEIO::ERR_ACCESS_DENIED ) {
1119 account()->handleJobError( job, i18n(
"Error while querying the server status.") );
1121 mContentState = imapNoInformation;
1122 emit folderComplete(
this,
false);
1123 close(
"checkvalidity");
1125 TQCString cstr((*it).data.data(), (*it).data.size() + 1);
1126 int a = cstr.find(
"X-uidValidity: ");
1127 int b = cstr.find(
"\r\n", a);
1129 if ( (b - a - 15) >= 0 )
1130 uidv = cstr.mid(a + 15, b - a - 15);
1131 a = cstr.find(
"X-Access: ");
1132 b = cstr.find(
"\r\n", a);
1134 if ( (b - a - 10) >= 0 )
1135 access = cstr.mid(a + 10, b - a - 10);
1136 mReadOnly = access ==
"Read only";
1137 a = cstr.find(
"X-Count: ");
1138 b = cstr.find(
"\r\n", a);
1141 if ( (b - a - 9) >= 0 )
1142 exists = cstr.mid(a + 9, b - a - 9).toInt(&ok);
1143 if ( !ok ) exists = -1;
1144 a = cstr.find(
"X-PermanentFlags: " );
1145 b = cstr.find(
"\r\n", a );
1146 if ( a >= 0 && (b - a - 18) >= 0 )
1147 mPermanentFlags = cstr.mid( a + 18, b - a - 18 ).toInt(&ok);
1148 if ( !ok ) mPermanentFlags = 0;
1150 if (uidValidity() != uidv)
1153 kdDebug(5006) << k_funcinfo <<
"uidValidty changed from "
1154 << uidValidity() <<
" to " << uidv << endl;
1155 if ( !uidValidity().isEmpty() )
1157 account()->ignoreJobsForFolder( folder() );
1158 mUidMetaDataMap.clear();
1161 setUidValidity(uidv);
1165 startUid = TQString::number(lastUid() + 1);
1167 account()->removeJob(it);
1168 if ( mMailCheckProgressItem )
1170 if ( startUid.isEmpty() ) {
1172 mMailCheckProgressItem->setTotalItems( exists );
1175 int remain = exists - count();
1176 if ( remain < 0 ) remain = 1;
1177 mMailCheckProgressItem->setTotalItems( remain );
1179 mMailCheckProgressItem->setCompletedItems( 0 );
1181 reallyGetFolder(startUid);
1186 void KMFolderImap::getAndCheckFolder(
bool force)
1189 return getFolder(force);
1192 account()->processNewMailInFolder( folder() );
1200 void KMFolderImap::getFolder(
bool force)
1202 mGuessedUnreadMsgs = -1;
1205 mContentState = imapFinished;
1206 emit folderComplete(
this,
true);
1210 mContentState = imapListingInProgress;
1220 void KMFolderImap::reallyGetFolder(
const TQString &startUid)
1222 KURL url = account()->getUrl();
1223 if ( account()->makeConnection() != ImapAccountBase::Connected )
1225 mContentState = imapNoInformation;
1226 emit folderComplete(
this,
false);
1227 close(
"listfolder");
1231 if (startUid.isEmpty())
1233 if ( mMailCheckProgressItem )
1234 mMailCheckProgressItem->setStatus( i18n(
"Retrieving message status") );
1235 url.setPath(imapPath() +
";SECTION=UID FLAGS");
1236 TDEIO::SimpleJob *job = TDEIO::listDir(url,
false);
1237 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
1238 ImapAccountBase::jobData jd( url.url(), folder() );
1239 jd.cancellable =
true;
1240 account()->insertJob(job, jd);
1241 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1242 this, TQ_SLOT(slotListFolderResult(TDEIO::Job *)));
1243 connect(job, TQ_SIGNAL(entries(TDEIO::Job *,
const TDEIO::UDSEntryList &)),
1244 this, TQ_SLOT(slotListFolderEntries(TDEIO::Job *,
1245 const TDEIO::UDSEntryList &)));
1247 mContentState = imapDownloadInProgress;
1248 if ( mMailCheckProgressItem )
1249 mMailCheckProgressItem->setStatus( i18n(
"Retrieving messages") );
1250 url.setPath(imapPath() +
";UID=" + startUid
1251 +
":*;SECTION=ENVELOPE");
1252 TDEIO::SimpleJob *newJob = TDEIO::get(url,
false,
false);
1253 TDEIO::Scheduler::assignJobToSlave(account()->slave(), newJob);
1254 ImapAccountBase::jobData jd( url.url(), folder() );
1255 jd.cancellable =
true;
1256 account()->insertJob(newJob, jd);
1257 connect(newJob, TQ_SIGNAL(result(TDEIO::Job *)),
1258 this, TQ_SLOT(slotGetLastMessagesResult(TDEIO::Job *)));
1259 connect(newJob, TQ_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
1260 this, TQ_SLOT(slotGetMessagesData(TDEIO::Job *,
const TQByteArray &)));
1266 void KMFolderImap::slotListFolderResult(TDEIO::Job * job)
1268 ImapAccountBase::JobIterator it = account()->findJob(job);
1269 if ( it == account()->jobsEnd() )
return;
1273 account()->handleJobError( job,
1274 i18n(
"Error while listing the contents of the folder %1.").arg( label() ) );
1275 account()->removeJob(it);
1276 finishMailCheck(
"listfolder", imapNoInformation );
1279 mCheckFlags =
false;
1280 TQStringList::Iterator uid;
1291 int idx = 0, c, serverFlags;
1292 ulong mailUid, serverUid;
1293 uid = (*it).items.begin();
1294 while ( idx < count() && uid != (*it).items.end() ) {
1295 KMMsgBase *msgBase = getMsgBase( idx );
1296 mailUid = msgBase->UID();
1299 c = (*uid).find(
",");
1300 serverUid = (*uid).left( c ).toLong();
1301 serverFlags = (*uid).mid( c+1 ).toInt();
1302 if ( mailUid < serverUid ) {
1303 removeMsg( idx,
true );
1304 }
else if ( mailUid == serverUid ) {
1308 if ( !mReadOnly || !GlobalSettings::allowLocalFlags() ) {
1309 int supportedFlags = mUploadAllFlags ? 31 : mPermanentFlags;
1311 supportedFlags = INT_MAX;
1312 flagsToStatus( msgBase, serverFlags,
false, supportedFlags );
1314 seenFlagToStatus( msgBase, serverFlags,
false );
1316 uid = (*it).items.remove(uid);
1317 if ( msgBase->getMsgSerNum() > 0 ) {
1318 saveMsgMetaData(
static_cast<KMMessage*
>(msgBase) );
1325 while (idx < count()) removeMsg(idx,
true);
1328 for (uid = (*it).items.begin(); uid != (*it).items.end(); ++uid)
1329 (*uid).truncate((*uid).find(
","));
1330 ImapAccountBase::jobData jd( TQString(), (*it).parent );
1331 jd.total = (*it).items.count();
1334 finishMailCheck(
"listfolder", imapFinished );
1335 account()->removeJob(it);
1338 if ( mMailCheckProgressItem )
1341 mMailCheckProgressItem->setCompletedItems( 0 );
1342 mMailCheckProgressItem->setTotalItems( jd.total );
1343 mMailCheckProgressItem->setProgress( 0 );
1344 mMailCheckProgressItem->setStatus( i18n(
"Retrieving messages") );
1348 uid = (*it).items.begin();
1349 if (jd.total == 1) sets.append(*uid +
":" + *uid);
1350 else sets = makeSets( (*it).items );
1351 account()->removeJob(it);
1354 for (TQStringList::Iterator i = sets.begin(); i != sets.end(); ++i)
1356 mContentState = imapDownloadInProgress;
1357 KURL url = account()->getUrl();
1358 url.setPath(imapPath() +
";UID=" + *i +
";SECTION=ENVELOPE");
1359 TDEIO::SimpleJob *newJob = TDEIO::get(url,
false,
false);
1361 TDEIO::Scheduler::assignJobToSlave(account()->slave(), newJob);
1362 account()->insertJob(newJob, jd);
1363 connect(newJob, TQ_SIGNAL(result(TDEIO::Job *)),
1364 this, (i == sets.at(sets.count() - 1))
1365 ? TQ_SLOT(slotGetLastMessagesResult(TDEIO::Job *))
1366 : TQ_SLOT(slotGetMessagesResult(TDEIO::Job *)));
1367 connect(newJob, TQ_SIGNAL(data(TDEIO::Job *,
const TQByteArray &)),
1368 this, TQ_SLOT(slotGetMessagesData(TDEIO::Job *,
const TQByteArray &)));
1374 void KMFolderImap::slotListFolderEntries(TDEIO::Job * job,
1375 const TDEIO::UDSEntryList & uds)
1377 ImapAccountBase::JobIterator it = account()->findJob(job);
1378 if ( it == account()->jobsEnd() )
return;
1379 TQString mimeType, name;
1381 for (TDEIO::UDSEntryList::ConstIterator udsIt = uds.begin();
1382 udsIt != uds.end(); udsIt++)
1384 for (TDEIO::UDSEntry::ConstIterator eIt = (*udsIt).begin();
1385 eIt != (*udsIt).end(); eIt++)
1387 if ((*eIt).m_uds == TDEIO::UDS_NAME)
1388 name = (*eIt).m_str;
1389 else if ((*eIt).m_uds == TDEIO::UDS_MIME_TYPE)
1390 mimeType = (*eIt).m_str;
1391 else if ((*eIt).m_uds == TDEIO::UDS_ACCESS)
1392 flags = (*eIt).m_long;
1394 if ((mimeType ==
"message/rfc822-imap" || mimeType ==
"message/rfc822") &&
1396 (*it).items.append(name +
"," + TQString::number(flags));
1397 if ( mMailCheckProgressItem ) {
1398 mMailCheckProgressItem->incCompletedItems();
1399 mMailCheckProgressItem->updateProgress();
1424 void KMFolderImap::flagsToStatus(KMMsgBase *msg,
int flags,
bool newMsg,
int supportedFlags )
1429 static const struct {
1432 const bool standardFlag;
1434 { 2, KMMsgStatusReplied,
true },
1435 { 4, KMMsgStatusFlag,
true },
1436 { 128, KMMsgStatusForwarded,
false },
1437 { 256, KMMsgStatusTodo,
false },
1438 { 512, KMMsgStatusWatched,
false },
1439 { 1024, KMMsgStatusIgnored,
false }
1441 static const int numFlags =
sizeof imapFlagMap /
sizeof *imapFlagMap;
1443 const KMMsgStatus oldStatus = msg->status();
1444 for (
int i = 0; i < numFlags; ++i ) {
1445 if ( ( (supportedFlags & imapFlagMap[i].imapFlag) == 0 && (supportedFlags & 64) == 0 )
1446 && !imapFlagMap[i].standardFlag ) {
1449 if ( ((flags & imapFlagMap[i].imapFlag) > 0) != ((oldStatus & imapFlagMap[i].kmFlag) > 0) ) {
1450 msg->toggleStatus( imapFlagMap[i].kmFlag );
1454 seenFlagToStatus( msg, flags, newMsg );
1457 void KMFolderImap::seenFlagToStatus(KMMsgBase * msg,
int flags,
bool newMsg)
1461 const KMMsgStatus oldStatus = msg->status();
1462 if ( (flags & 1) && (oldStatus & KMMsgStatusOld) == 0 )
1463 msg->setStatus( KMMsgStatusOld );
1468 if ( msg->isOfUnknownStatus() || (!(flags&1) && !(oldStatus&(KMMsgStatusNew|KMMsgStatusUnread)) ) ) {
1470 if ( (oldStatus & KMMsgStatusNew) == 0 )
1471 msg->setStatus( KMMsgStatusNew );
1473 if ( (oldStatus & KMMsgStatusUnread) == 0 )
1474 msg->setStatus( KMMsgStatusUnread );
1481 TQString KMFolderImap::statusToFlags(KMMsgStatus status,
int supportedFlags)
1484 if (status & KMMsgStatusDeleted)
1485 flags =
"\\DELETED";
1487 if (status & KMMsgStatusOld || status & KMMsgStatusRead)
1489 if (status & KMMsgStatusReplied)
1490 flags +=
"\\ANSWERED ";
1491 if (status & KMMsgStatusFlag)
1492 flags +=
"\\FLAGGED ";
1494 if ( (status & KMMsgStatusForwarded) && ((supportedFlags & 64) || (supportedFlags & 128)) )
1495 flags +=
"$FORWARDED ";
1496 if ( (status & KMMsgStatusTodo) && ((supportedFlags & 64) || (supportedFlags & 256)) )
1498 if ( (status & KMMsgStatusWatched) && ((supportedFlags & 64) || (supportedFlags & 512)) )
1499 flags +=
"$WATCHED ";
1500 if ( (status & KMMsgStatusIgnored) && ((supportedFlags & 64) || (supportedFlags & 1024)) )
1501 flags +=
"$IGNORED ";
1504 return flags.simplifyWhiteSpace();
1509 KMFolderImap::ignoreJobsForMessage(
KMMessage* msg )
1512 !msg->parent() || msg->parent()->folderType() != KMFolderTypeImap )
1514 KMAcctImap *account;
1515 if ( !(account =
static_cast<KMFolderImap*
>(msg->storage())->account()) )
1518 account->ignoreJobsForMessage( msg );
1522 void KMFolderImap::slotGetMessagesData(TDEIO::Job * job,
const TQByteArray & data)
1524 if ( data.isEmpty() )
return;
1525 ImapAccountBase::JobIterator it = account()->findJob(job);
1526 if ( it == account()->jobsEnd() )
return;
1527 (*it).cdata += TQCString(data, data.size() + 1);
1528 int pos = (*it).cdata.find(
"\r\n--IMAPDIGEST");
1536 int p = (*it).cdata.find(
"\r\nX-uidValidity:");
1537 if (p != -1) setUidValidity((*it).cdata
1538 .mid(p + 17, (*it).cdata.find(
"\r\n", p+1) - p - 17));
1539 int c = (*it).cdata.find(
"\r\nX-Count:");
1543 int exists = (*it).cdata.mid( c+10,
1544 (*it).cdata.find(
"\r\n", c+1) - c-10 ).toInt(&ok);
1545 if ( ok && exists < count() ) {
1546 kdDebug(5006) <<
"KMFolderImap::slotGetMessagesData - server has less messages (" <<
1547 exists <<
") then folder (" << count() <<
"), so reload" << endl;
1549 reallyGetFolder( TQString() );
1550 (*it).cdata.remove(0, pos);
1553 int delta = exists - count();
1554 if ( mMailCheckProgressItem ) {
1555 mMailCheckProgressItem->setTotalItems( delta );
1559 (*it).cdata.remove(0, pos);
1561 pos = (*it).cdata.find(
"\r\n--IMAPDIGEST", 1);
1570 msg->fromString( (*it).cdata.mid(16, pos - 16) );
1572 ulong uid = msg->
UID();
1573 KMMsgMetaData *md = 0;
1574 if ( mUidMetaDataMap.find( uid ) ) {
1575 md = mUidMetaDataMap[uid];
1579 serNum = md->serNum();
1582 if ( uid <= lastUid() && serNum > 0 ) {
1600 }
else if ( !account()->hasCapability(
"uidplus") ) {
1603 TQString
id = msg->msgIdMD5();
1604 if ( mMetaDataMap.find(
id ) ) {
1605 md = mMetaDataMap[id];
1607 if ( md->serNum() != 0 && serNum == 0 ) {
1610 mMetaDataMap.remove(
id );
1616 flagsToStatus((KMMsgBase*)msg, flags,
true, mUploadAllFlags ? 31 : mPermanentFlags);
1618 msg->setMsgSizeServer( msg->
headerField(
"X-Length").toUInt() );
1620 if ( msg->getMsgSerNum() > 0 ) {
1621 saveMsgMetaData( msg );
1624 if ( folder()->isSystemFolder() && imapPath() ==
"/INBOX/"
1625 && kmkernel->filterMgr()->atLeastOneIncomingFilterAppliesTo( account()->
id() ) )
1626 account()->execFilters( msg->getMsgSerNum() );
1628 if ( count() > 1 ) {
1629 unGetMsg(count() - 1);
1632 if ( mMailCheckProgressItem ) {
1633 mMailCheckProgressItem->incCompletedItems();
1634 mMailCheckProgressItem->updateProgress();
1638 (*it).cdata.remove(0, pos);
1640 pos = (*it).cdata.find(
"\r\n--IMAPDIGEST", 1);
1646 KMFolderImap::doCreateJob(
KMMessage *msg, FolderJob::JobType jt,
1647 KMFolder *folder, TQString partSpecifier,
1648 const AttachmentStrategy *as )
const
1650 KMFolderImap* kmfi = folder?
dynamic_cast<KMFolderImap*
>(folder->storage()) : 0;
1651 if ( jt == FolderJob::tGetMessage && partSpecifier ==
"STRUCTURE" &&
1652 account() && account()->loadOnDemand() &&
1661 ImapJob *job =
new ImapJob( msg, jt, kmfi,
"HEADER" );
1663 ImapJob *job2 =
new ImapJob( msg, jt, kmfi,
"STRUCTURE", as );
1665 job->setParentFolder(
this );
1669 if ( partSpecifier ==
"STRUCTURE" )
1670 partSpecifier = TQString();
1672 ImapJob *job =
new ImapJob( msg, jt, kmfi, partSpecifier );
1673 job->setParentFolder(
this );
1680 KMFolderImap::doCreateJob( TQPtrList<KMMessage>& msgList,
const TQString& sets,
1681 FolderJob::JobType jt,
KMFolder *folder )
const
1683 KMFolderImap* kmfi =
dynamic_cast<KMFolderImap*
>(folder->storage());
1684 ImapJob *job =
new ImapJob( msgList, sets, jt, kmfi );
1685 job->setParentFolder(
this );
1690 void KMFolderImap::getMessagesResult(TDEIO::Job * job,
bool lastSet)
1692 ImapAccountBase::JobIterator it = account()->findJob(job);
1693 if ( it == account()->jobsEnd() )
return;
1695 account()->handleJobError( job, i18n(
"Error while retrieving messages.") );
1696 finishMailCheck(
"getMessage", imapNoInformation );
1700 finishMailCheck(
"getMessage", imapFinished );
1701 account()->removeJob(it);
1707 void KMFolderImap::slotGetLastMessagesResult(TDEIO::Job * job)
1709 getMessagesResult(job,
true);
1714 void KMFolderImap::slotGetMessagesResult(TDEIO::Job * job)
1716 getMessagesResult(job,
false);
1721 void KMFolderImap::createFolder(
const TQString &name,
const TQString& parentPath,
1724 kdDebug(5006) <<
"KMFolderImap::createFolder - name=" << name <<
",parent=" <<
1725 parentPath <<
",askUser=" << askUser << endl;
1726 if ( account()->makeConnection() != ImapAccountBase::Connected ) {
1727 kdWarning(5006) <<
"KMFolderImap::createFolder - got no connection" << endl;
1730 KURL url = account()->getUrl();
1731 TQString parent = ( parentPath.isEmpty() ? imapPath() : parentPath );
1732 TQString path = account()->createImapPath( parent, name );
1734 path +=
"/;INFO=ASKUSER";
1736 url.setPath( path );
1738 TDEIO::SimpleJob *job = TDEIO::mkdir(url);
1739 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
1740 ImapAccountBase::jobData jd( url.url(), folder() );
1742 account()->insertJob(job, jd);
1743 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1744 this, TQ_SLOT(slotCreateFolderResult(TDEIO::Job *)));
1749 void KMFolderImap::slotCreateFolderResult(TDEIO::Job * job)
1751 ImapAccountBase::JobIterator it = account()->findJob(job);
1752 if ( it == account()->jobsEnd() )
return;
1755 if ( it.data().items.count() > 0 )
1756 name = it.data().items.first();
1760 if ( job->error() == TDEIO::ERR_COULD_NOT_MKDIR ) {
1762 account()->listDirectory( );
1764 account()->handleJobError( job, i18n(
"Error while creating a folder.") );
1765 emit folderCreationResult( name,
false );
1768 account()->removeJob(job);
1769 emit folderCreationResult( name,
true );
1775 static TQTextCodec *sUtf7Codec = 0;
1777 TQTextCodec * KMFolderImap::utf7Codec()
1779 if (!sUtf7Codec) sUtf7Codec = TQTextCodec::codecForName(
"utf-7");
1785 TQString KMFolderImap::encodeFileName(
const TQString &name)
1787 TQString result = utf7Codec()->fromUnicode(name);
1788 return KURL::encode_string_no_slash(result);
1793 TQString KMFolderImap::decodeFileName(
const TQString &name)
1795 TQString result = KURL::decode_string(name);
1796 return utf7Codec()->toUnicode(result.latin1());
1800 bool KMFolderImap::autoExpunge()
1803 return account()->autoExpunge();
1810 void KMFolderImap::slotSimpleData(TDEIO::Job * job,
const TQByteArray & data)
1812 if ( data.isEmpty() )
return;
1813 ImapAccountBase::JobIterator it = account()->findJob(job);
1814 if ( it == account()->jobsEnd() )
return;
1815 TQBuffer buff((*it).data);
1816 buff.open(IO_WriteOnly | IO_Append);
1817 buff.writeBlock(data.data(), data.size());
1822 void KMFolderImap::deleteMessage(
KMMessage * msg)
1824 mUidMetaDataMap.remove( msg->
UID() );
1825 mMetaDataMap.remove( msg->msgIdMD5() );
1826 KURL url = account()->getUrl();
1827 KMFolderImap *msg_parent =
static_cast<KMFolderImap*
>(msg->storage());
1828 ulong uid = msg->
UID();
1833 kdDebug( 5006 ) <<
"KMFolderImap::deleteMessage: Attempt to delete "
1834 "an empty UID. Aborting." << endl;
1837 url.setPath(msg_parent->imapPath() +
";UID=" + TQString::number(uid) );
1838 if ( account()->makeConnection() != ImapAccountBase::Connected )
1840 TDEIO::SimpleJob *job = TDEIO::file_delete(url,
false);
1841 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
1842 ImapAccountBase::jobData jd( url.url(), 0 );
1843 account()->insertJob(job, jd);
1844 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1845 account(), TQ_SLOT(slotSimpleResult(TDEIO::Job *)));
1848 void KMFolderImap::deleteMessage(
const TQPtrList<KMMessage>& msgList)
1850 TQPtrListIterator<KMMessage> it( msgList );
1852 while ( (msg = it.current()) != 0 ) {
1854 mUidMetaDataMap.remove( msg->
UID() );
1855 mMetaDataMap.remove( msg->msgIdMD5() );
1858 TQValueList<ulong> uids;
1859 getUids(msgList, uids);
1860 TQStringList sets = makeSets(uids);
1862 KURL url = account()->getUrl();
1863 KMFolderImap *msg_parent =
static_cast<KMFolderImap*
>(msgList.getFirst()->storage());
1864 for ( TQStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
1869 if ( uid.isEmpty() )
continue;
1870 url.setPath(msg_parent->imapPath() +
";UID=" + uid);
1871 if ( account()->makeConnection() != ImapAccountBase::Connected )
1873 TDEIO::SimpleJob *job = TDEIO::file_delete(url,
false);
1874 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
1875 ImapAccountBase::jobData jd( url.url(), 0 );
1876 account()->insertJob(job, jd);
1877 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
1878 account(), TQ_SLOT(slotSimpleResult(TDEIO::Job *)));
1883 void KMFolderImap::setStatus(
int idx, KMMsgStatus status,
bool toggle)
1885 TQValueList<int> ids; ids.append(idx);
1886 setStatus(ids, status, toggle);
1889 void KMFolderImap::setStatus(TQValueList<int>& _ids, KMMsgStatus status,
bool toggle)
1892 TQValueList<int> ids;
1893 if ( mUploadAllFlags ) {
1894 kdDebug(5006) << k_funcinfo <<
"Migrating all flags to the server" << endl;
1896 for (
int i = 0; i < count(); ++i )
1898 mUploadAllFlags =
false;
1916 TQValueList<ulong> seenUids, unseenUids;
1917 for ( TQValueList<int>::ConstIterator it = ids.constBegin(); it != ids.constEnd(); ++it ) {
1919 bool unget = !isMessage(*it);
1922 if ( msg->
status() & KMMsgStatusOld || msg->
status() & KMMsgStatusRead )
1923 seenUids.append( msg->
UID() );
1925 unseenUids.append( msg->
UID() );
1926 if (unget) unGetMsg(*it);
1928 if ( !seenUids.isEmpty() ) {
1929 TQStringList sets = KMFolderImap::makeSets( seenUids,
true );
1930 for( TQStringList::Iterator it = sets.begin(); it != sets.end(); ++it ) {
1931 TQString imappath = imapPath() +
";UID=" + ( *it );
1932 account()->setImapSeenStatus( folder(), imappath,
true );
1935 if ( !unseenUids.isEmpty() ) {
1936 TQStringList sets = KMFolderImap::makeSets( unseenUids,
true );
1937 for( TQStringList::Iterator it = sets.begin(); it != sets.end(); ++it ) {
1938 TQString imappath = imapPath() +
";UID=" + ( *it );
1939 account()->setImapSeenStatus( folder(), imappath,
false );
1945 TQMap< TQString, TQStringList > groups;
1946 for ( TQValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it ) {
1948 bool unget = !isMessage(*it);
1951 TQString flags = statusToFlags(msg->
status(), mPermanentFlags);
1953 groups[flags].append(TQString::number(msg->
UID()));
1954 if (unget) unGetMsg(*it);
1956 TQMapIterator< TQString, TQStringList > dit;
1957 for ( dit = groups.begin(); dit != groups.end(); ++dit ) {
1958 TQCString flags = dit.key().latin1();
1959 TQStringList sets = makeSets( (*dit),
true );
1961 for ( TQStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
1962 TQString imappath = imapPath() +
";UID=" + ( *slit );
1963 account()->setImapStatus(folder(), imappath, flags);
1966 if ( mContentState == imapListingInProgress ) {
1970 kdDebug(5006) <<
"Set status during folder listing, restarting listing." << endl;
1971 disconnect(
this, TQ_SLOT(slotListFolderResult(TDEIO::Job *)));
1973 reallyGetFolder( TQString() );
1978 TQStringList KMFolderImap::makeSets(
const TQStringList& uids,
bool sort)
1980 TQValueList<ulong> tmp;
1981 for ( TQStringList::ConstIterator it = uids.begin(); it != uids.end(); ++it )
1982 tmp.append( (*it).toInt() );
1983 return makeSets(tmp, sort);
1986 TQStringList KMFolderImap::makeSets( TQValueList<ulong>& uids,
bool sort )
1991 if (uids.size() == 1)
1993 sets.append(TQString::number(uids.first()));
1997 if (sort) qHeapSort(uids);
2001 bool inserted =
false;
2003 for ( TQValueList<ulong>::Iterator it = uids.begin(); it != uids.end(); ++it )
2005 if (it == uids.begin() || set.isEmpty()) {
2006 set = TQString::number(*it);
2014 set +=
',' + TQString::number(*it);
2016 set +=
':' + TQString::number(last) +
',' + TQString::number(*it);
2018 if (set.length() > 100)
2032 set +=
':' + TQString::number(uids.last());
2034 if (!set.isEmpty()) sets.append(set);
2040 void KMFolderImap::getUids(TQValueList<int>& ids, TQValueList<ulong>& uids)
2044 for ( TQValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
2046 msg = getMsgBase(*it);
2048 uids.append(msg->UID());
2052 void KMFolderImap::getUids(
const TQPtrList<KMMessage>& msgList, TQValueList<ulong>& uids)
2056 TQPtrListIterator<KMMessage> it( msgList );
2057 while ( (msg = it.current()) != 0 ) {
2059 if ( msg->
UID() > 0 ) {
2060 uids.append( msg->
UID() );
2066 void KMFolderImap::expungeFolder(KMFolderImap * aFolder,
bool quiet)
2068 aFolder->setNeedsCompacting(
false);
2069 KURL url = account()->getUrl();
2070 url.setPath(aFolder->imapPath() +
";UID=*");
2071 if ( account()->makeConnection() != ImapAccountBase::Connected )
2073 TDEIO::SimpleJob *job = TDEIO::file_delete(url,
false);
2074 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
2075 ImapAccountBase::jobData jd( url.url(), 0 );
2077 account()->insertJob(job, jd);
2078 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
2079 account(), TQ_SLOT(slotSimpleResult(TDEIO::Job *)));
2083 void KMFolderImap::slotProcessNewMail(
int errorCode,
const TQString &errorMsg )
2085 Q_UNUSED( errorMsg );
2086 disconnect( account(), TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
2087 this, TQ_SLOT( slotProcessNewMail(
int,
const TQString&) ) );
2089 processNewMail(
false );
2091 emit numUnreadMsgsChanged( folder() );
2095 bool KMFolderImap::processNewMail(
bool)
2099 kdDebug(5006) <<
"KMFolderImap::processNewMail - account is null!" << endl;
2102 if ( imapPath().isEmpty() ) {
2103 kdDebug(5006) <<
"KMFolderImap::processNewMail - imapPath of " << name() <<
" is empty!" << endl;
2105 setAlreadyRemoved(
true );
2106 kmkernel->imapFolderMgr()->remove( folder() );
2110 if ( account()->makeConnection() == ImapAccountBase::Error ) {
2111 kdDebug(5006) <<
"KMFolderImap::processNewMail - got no connection!" << endl;
2113 }
else if ( account()->makeConnection() == ImapAccountBase::Connecting )
2116 kdDebug(5006) <<
"KMFolderImap::processNewMail - waiting for connection: " << label() << endl;
2117 connect( account(), TQ_SIGNAL( connectionResult(
int,
const TQString&) ),
2118 this, TQ_SLOT( slotProcessNewMail(
int,
const TQString&) ) );
2121 KURL url = account()->getUrl();
2123 url.setPath(imapPath() +
";SECTION=UIDNEXT");
2125 url.setPath(imapPath() +
";SECTION=UNSEEN");
2127 mMailCheckProgressItem = ProgressManager::createProgressItem(
2128 "MailCheckAccount" + account()->name(),
2129 "MailCheck" + folder()->prettyURL(),
2130 TQStyleSheet::escape( folder()->prettyURL() ),
2131 i18n(
"updating message counts"),
2133 account()->useSSL() || account()->useTLS() );
2135 TDEIO::SimpleJob *job = TDEIO::stat(url,
false);
2136 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
2137 ImapAccountBase::jobData jd(url.url(), folder() );
2138 jd.cancellable =
true;
2139 account()->insertJob(job, jd);
2140 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
2141 TQ_SLOT(slotStatResult(TDEIO::Job *)));
2147 void KMFolderImap::slotStatResult(TDEIO::Job * job)
2149 slotCompleteMailCheckProgress();
2150 ImapAccountBase::JobIterator it = account()->findJob(job);
2151 if ( it == account()->jobsEnd() )
return;
2152 account()->removeJob(it);
2155 account()->handleJobError( job, i18n(
"Error while getting folder information.") );
2157 TDEIO::UDSEntry uds =
static_cast<TDEIO::StatJob*
>(job)->statResult();
2158 for (TDEIO::UDSEntry::ConstIterator it = uds.begin(); it != uds.end(); it++)
2160 if ((*it).m_uds == TDEIO::UDS_SIZE)
2164 mGuessedUnreadMsgs = -1;
2165 mGuessedUnreadMsgs = countUnread() + (*it).m_long - lastUid() - 1;
2166 if (mGuessedUnreadMsgs < 0) mGuessedUnreadMsgs = 0;
2168 mGuessedUnreadMsgs = (*it).m_long;
2176 int KMFolderImap::create()
2180 return KMFolderMbox::create();
2183 TQValueList<ulong> KMFolderImap::splitSets(
const TQString uids)
2185 TQValueList<ulong> uidlist;
2188 TQString buffer = TQString();
2191 for (uint i = 0; i < uids.length(); i++)
2193 TQChar chr = uids[i];
2199 for (
int j = setstart; j <= buffer.toInt(); j++)
2206 uidlist.append(buffer.toInt());
2209 }
else if (chr ==
':') {
2211 setstart = buffer.toInt();
2213 }
else if (chr.category() == TQChar::Number_DecimalDigit) {
2223 for (
int j = setstart; j <= buffer.toInt(); j++)
2228 uidlist.append(buffer.toInt());
2235 int KMFolderImap::expungeContents()
2238 int rc = KMFolderMbox::expungeContents();
2241 KURL url = account()->getUrl();
2242 url.setPath( imapPath() +
";UID=1:*");
2243 if ( account()->makeConnection() == ImapAccountBase::Connected )
2245 TDEIO::SimpleJob *job = TDEIO::file_delete(url,
false);
2246 TDEIO::Scheduler::assignJobToSlave(account()->slave(), job);
2247 ImapAccountBase::jobData jd( url.url(), 0 );
2249 account()->insertJob(job, jd);
2250 connect(job, TQ_SIGNAL(result(TDEIO::Job *)),
2251 account(), TQ_SLOT(slotSimpleResult(TDEIO::Job *)));
2257 expungeFolder(
this,
true);
2267 mUserRights = userRights;
2268 mUserRightsState = userRightsState;
2272 void KMFolderImap::slotCompleteMailCheckProgress()
2274 if ( mMailCheckProgressItem ) {
2275 mMailCheckProgressItem->setComplete();
2276 mMailCheckProgressItem = 0;
2277 emit numUnreadMsgsChanged( folder() );
2282 void KMFolderImap::setSubfolderState( imapState state )
2284 mSubfolderState = state;
2285 if ( state == imapNoInformation && folder()->child() )
2289 TQPtrListIterator<KMFolderNode> it( *folder()->child() );
2290 for ( ; (node = it.current()); )
2293 if (node->isDir())
continue;
2295 static_cast<KMFolderImap*
>(folder->storage())->setSubfolderState( state );
2301 void KMFolderImap::setIncludeInMailCheck(
bool check )
2303 bool changed = ( mCheckMail != check );
2306 account()->slotUpdateFolderList();
2310 void KMFolderImap::setAlreadyRemoved(
bool removed )
2312 mAlreadyRemoved = removed;
2313 if ( folder()->child() )
2317 TQPtrListIterator<KMFolderNode> it( *folder()->child() );
2318 for ( ; (node = it.current()); )
2321 if (node->isDir())
continue;
2323 static_cast<KMFolderImap*
>(folder->storage())->setAlreadyRemoved( removed );
2328 void KMFolderImap::slotCreatePendingFolders(
int errorCode,
const TQString& errorMsg )
2330 Q_UNUSED( errorMsg );
2331 disconnect( account(), TQ_SIGNAL( connectionResult(
int,
const TQString& ) ),
2332 this, TQ_SLOT( slotCreatePendingFolders(
int,
const TQString& ) ) );
2334 TQStringList::Iterator it = mFoldersPendingCreation.begin();
2335 for ( ; it != mFoldersPendingCreation.end(); ++it ) {
2336 createFolder( *it );
2339 mFoldersPendingCreation.clear();
2345 if ( !pattern || pattern->isEmpty() )
2348 TQValueList<TQ_UINT32> serNums;
2349 emit searchResult( folder(), serNums, pattern,
true );
2353 connect( job, TQ_SIGNAL( searchDone( TQValueList<TQ_UINT32>,
const KMSearchPattern*,
bool ) ),
2354 this, TQ_SLOT( slotSearchDone( TQValueList<TQ_UINT32>,
const KMSearchPattern*,
bool ) ) );
2359 void KMFolderImap::slotSearchDone( TQValueList<TQ_UINT32> serNums,
2363 emit searchResult( folder(), serNums, pattern, complete );
2367 void KMFolderImap::search(
const KMSearchPattern* pattern, TQ_UINT32 serNum )
2369 if ( !pattern || pattern->isEmpty() )
2372 emit searchDone( folder(), serNum, pattern,
false );
2376 connect( job, TQ_SIGNAL( searchDone( TQ_UINT32,
const KMSearchPattern*,
bool ) ),
2377 this, TQ_SLOT( slotSearchDone( TQ_UINT32,
const KMSearchPattern*,
bool ) ) );
2382 void KMFolderImap::slotSearchDone( TQ_UINT32 serNum,
const KMSearchPattern* pattern,
2385 emit searchDone( folder(), serNum, pattern, matches );
2389 bool KMFolderImap::isMoveable()
const
2391 return ( hasChildren() == HasNoChildren &&
2392 !folder()->isSystemFolder() ) ? true :
false;
2396 ulong KMFolderImap::serNumForUID( ulong uid )
2398 if ( mUidMetaDataMap.find( uid ) ) {
2399 KMMsgMetaData *md = mUidMetaDataMap[uid];
2400 return md->serNum();
2402 kdDebug(5006) <<
"serNumForUID: unknown uid " << uid << endl;
2408 void KMFolderImap::saveMsgMetaData(
KMMessage* msg, ulong uid )
2413 ulong serNum = msg->getMsgSerNum();
2414 mUidMetaDataMap.replace( uid,
new KMMsgMetaData(msg->
status(), serNum) );
2418 void KMFolderImap::setImapPath(
const TQString& path )
2420 if ( path.isEmpty() ) {
2421 kdWarning(5006) << k_funcinfo <<
"ignoring empty path" << endl;
2427 void KMFolderImap::finishMailCheck(
const char *dbg, imapState state )
2430 mContentState = state;
2431 emit folderComplete(
this, mContentState == imapFinished );
2435 bool KMFolderImap::canDeleteMessages()
const
2439 if ( mUserRightsState ==
KMail::ACLJobs::Ok && !(mUserRights & KMail::ACLJobs::Delete) )
2444 #include "kmfolderimap.moc"
virtual KMMessage * take(int idx)
Detach message from this folder.
virtual int rename(const TQString &newName, KMFolderDir *aParent=0)
Physically rename the folder.
virtual void readConfig()
Read the config file.
virtual void setStatus(int idx, KMMsgStatus status, bool toggle=false)
Set the status of the message at index idx to status.
virtual void removeMsg(int i, bool imapQuiet=false)
Remove (first occurrence of) given message from the folder.
virtual void remove()
Removes the folder physically from disk and empties the contents of the folder in memory.
virtual void writeConfig()
Write the config file.
virtual KMMessage * getMsg(int idx)
Read message at given index.
virtual int addMsg(TQPtrList< KMMessage > &, TQValueList< int > &index_return)
Adds the given messages to the folder.
KMail list that manages the contents of one directory that may contain folders and/or other directori...
virtual KMFolder * createFolder(const TQString &folderName, bool sysFldr=false, KMFolderType folderType=KMFolderTypeMbox)
Create a mail folder in this directory with given name.
KMFolder * owner() const
Returns the folder whose children we are holding.
KMFolderDir * child() const
Returns the folder directory associated with this node or 0 if no such directory exists.
KMMessage * take(int idx)
Detach message from this folder.
void close(const char *owner, bool force=false)
Close folder.
KMFolderDir * createChildFolder()
Create a child folder directory and associates it with this folder.
KMMessage * getMsg(int idx)
Read message at given index.
KMFolderType folderType() const
Returns the type of this folder.
int find(const KMMsgBase *msg) const
Returns the index of the given message or -1 if not found.
void setReadyToShow(bool v)
Set if the message is ready to be shown.
size_t msgSizeServer() const
Get/set size on server.
void setTransferInProgress(bool value, bool force=false)
Set that the message shall not be deleted because it is still required.
void setStatus(const KMMsgStatus status, int idx=-1)
Set status and mark dirty.
KMMsgEncryptionState encryptionState() const
Encryption status of the message.
bool transferInProgress() const
Return, if the message should not be deleted.
void setMsgSerNum(unsigned long newMsgSerNum=0)
Sets the message serial number.
void setComplete(bool v)
Set if the message is a complete message.
KMMsgStatus status() const
Status of the message.
TQString headerField(const TQCString &name) const
Returns the value of a header field with the given name.
bool isComplete() const
Return true if the complete message is available without referring to the backing store.
ulong UID() const
Get/set UID.
KMMsgSignatureState signatureState() const
Signature status of the message.
This class is an abstraction of a search over messages.
Generic folder list job for (d)imap accounts.
void setHonorLocalSubscription(bool value)
Set whether the listing should include only folders that the account is subscribed to locally.
void setNamespace(const TQString &ns)
Set the namespace for this listing.
void setParentProgressItem(KPIM::ProgressItem *it)
Set parent progress item.
Rename and move (d)imap folders They can be moved everywhere (except search folders) as a new folder ...
@ NotFetchedYet
The user rights/ACL have not been fetched from the server yet, we don't know them.
@ Ok
The user rights/ACL have been fetched from the server sucessfully.