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"