[prev in list] [next in list] [prev in thread] [next in thread]
List: kmail-devel
Subject: Re: [Bug 48307] kmail crashed after changing from an imap folder busy with copying to a local local
From: Carsten Burghardt <cb () magic-shop ! de>
Date: 2002-10-14 20:51:03
[Download RAW message or body]
On Monday 14 October 2002 12:53, Carsten Burghardt wrote:
> ------- You are receiving this mail because: -------
> You are the assignee for the bug, or are watching the assignee.
>
> http://bugs.kde.org/show_bug.cgi?id=48307
> burghardt@kde.org changed:
>
> What |Removed |Added
> ---------------------------------------------------------------------------
>- Status|REOPENED |ASSIGNED
> Component|general |IMAP
>
>
>
> ------- Additional Comments From burghardt@kde.org 2002-10-14 12:53
> ------- OK, found the bug. Will be fixed soon.
The attached patch should fix it. It also contains the undo-changes as I was
too lazy to separate them.
As I didn't find comments or documentation about the contentState-flag I
assume that I can use it in this case. I set the contentState to
imapInProgress if there is any move/copy operation and if close is called
during such operations it is deferred.
--
Regards,
Carsten Burghardt
["kmfolderimap.diff" (text/x-diff)]
Index: kdenetwork/kmail/kmfolderimap.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmfolderimap.cpp,v
retrieving revision 1.72
diff -u -3 -p -r1.72 kmfolderimap.cpp
--- kdenetwork/kmail/kmfolderimap.cpp 2002/10/11 22:36:19 1.72
+++ kdenetwork/kmail/kmfolderimap.cpp 2002/10/14 20:42:43
@@ -47,6 +47,7 @@ KMFolderImap::KMFolderImap(KMFolderDir*
mIsSelected = FALSE;
mLastUid = 0;
mCheckFlags = TRUE;
+ mDeferredClose = FALSE;
KConfig* config = kapp->config();
KConfigGroupSaver saver(config, "Folder-" + idString());
@@ -165,25 +166,45 @@ void KMFolderImap::removeMsg(QPtrList<KM
void KMFolderImap::addMsgQuiet(KMMessage* aMsg)
{
KMFolder *folder = aMsg->parent();
- if (folder) kernel->undoStack()->pushAction( aMsg->getMsgSerNum(), folder, this );
- if (folder) folder->take(folder->find(aMsg));
+ mContentState = imapFinished;
+ if (folder)
+ {
+ if (aMsg->enableUndo())
+ {
+ kernel->undoStack()->pushAction( aMsg->getMsgSerNum(), folder, this );
+ } else {
+ aMsg->setEnableUndo(true);
+ }
+ folder->take(folder->find(aMsg));
+ }
delete aMsg;
aMsg = 0;
getFolder();
+ if (mDeferredClose) close();
}
//-----------------------------------------------------------------------------
void KMFolderImap::addMsgQuiet(QPtrList<KMMessage> msgList)
{
KMFolder *folder = msgList.first()->parent();
- for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
+ mContentState = imapFinished;
+ if (folder)
{
- kernel->undoStack()->pushAction( msg->getMsgSerNum(), folder, this );
+ for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
+ {
+ if (msg->enableUndo())
+ {
+ kernel->undoStack()->pushAction( msg->getMsgSerNum(), folder, this );
+ } else {
+ msg->setEnableUndo(true);
+ }
+ }
+ folder->take(msgList);
}
- if (folder) folder->take(msgList);
msgList.setAutoDelete(true);
msgList.clear();
getFolder();
+ if (mDeferredClose) close();
}
//-----------------------------------------------------------------------------
@@ -201,6 +222,7 @@ int KMFolderImap::addMsg(QPtrList<KMMess
// make sure the messages won't be deleted while we work with them
for ( KMMessage* msg = msgList.first(); msg; msg = msgList.next() )
msg->setTransferInProgress(true);
+ mContentState = imapInProgress;
KMImapJob *imapJob = 0;
if (msgParent)
@@ -237,7 +259,7 @@ int KMFolderImap::addMsg(QPtrList<KMMess
// we need the messages that belong to the current set to pass them to \
the ImapJob
QPtrList<KMMessage> temp_msgs = splitMessageList(*it, msgList);
- imapJob = new KMImapJob(temp_msgs, *it, KMImapJob::tCopyMessage, this);
+ imapJob = new KMImapJob(temp_msgs, *it, KMImapJob::tMoveMessage, this);
connect(imapJob, SIGNAL(messageCopied(QPtrList<KMMessage>)),
SLOT(addMsgQuiet(QPtrList<KMMessage>)));
}
@@ -284,6 +306,7 @@ void KMFolderImap::copyMsg(QPtrList<KMMe
QValueList<int> uids;
getUids(msgList, uids);
QStringList sets = makeSets(uids, false);
+ mContentState = imapInProgress;
for ( QStringList::Iterator it = sets.begin(); it != sets.end(); ++it )
{
// we need the messages that belong to the current set to pass them to the \
ImapJob @@ -594,8 +617,10 @@ kdDebug(5006) << "KMFolderImap::slotChec
QString startUid;
if (uidValidity() != uidv)
{
+ // uidValidity changed
expunge();
mLastUid = 0;
+ uidmap.clear();
} else {
if (!mCheckFlags)
startUid = QString::number(lastUid() + 1);
@@ -851,7 +876,18 @@ void KMFolderImap::slotGetMessagesData(K
}
else {
msg->setStatus(flagsToStatus(flags));
+ if (uidmap.find(uid))
+ {
+ // assign the sernum from the cache
+ const ulong sernum = (ulong) uidmap[uid];
+ kdDebug() << "set sernum:" << sernum << " for " << uid << endl;
+ msg->setMsgSerNum(sernum);
+ // delete the entry
+ uidmap.remove(uid);
+ }
+ open();
KMFolderImapInherited::addMsg(msg, 0);
+ close();
if (count() > 1) unGetMsg(count() - 1);
mLastUid = uid;
/* if ((*it).total > 20 &&
@@ -967,6 +1003,70 @@ QString KMFolderImap::decodeFileName(con
}
//-----------------------------------------------------------------------------
+QValueList<int> KMFolderImap::splitSets(QString uids)
+{
+ QValueList<int> uidlist;
+
+ // ex: 1205,1204,1203,1202,1236:1238
+ QString buffer = QString::null;
+ int setstart = -1;
+ // iterate over the uids
+ for (uint i = 0; i < uids.length(); i++)
+ {
+ QChar chr = uids[i];
+ if (chr == ",")
+ {
+ if (setstart > -1)
+ {
+ // a range (uid:uid) was before
+ for (int j = setstart; j <= buffer.toInt(); j++)
+ {
+ uidlist.append(j);
+ }
+ setstart = -1;
+ } else {
+ // single uid
+ uidlist.append(buffer.toInt());
+ }
+ buffer = "";
+ } else if (chr == ":") {
+ // remember the start of the range
+ setstart = buffer.toInt();
+ buffer = "";
+ } else if (chr.category() == QChar::Number_DecimalDigit) {
+ // digit
+ buffer += chr;
+ } else {
+ // ignore
+ }
+ }
+ // process the last data
+ if (setstart > -1)
+ {
+ for (int j = setstart; j <= buffer.toInt(); j++)
+ {
+ uidlist.append(j);
+ }
+ } else {
+ uidlist.append(buffer.toInt());
+ }
+
+ return uidlist;
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderImap::close(bool force)
+{
+ if (mContentState == imapInProgress)
+ {
+ // this folder has some transfer in progress, so we close it later
+ mDeferredClose = TRUE;
+ } else {
+ KMFolderImapInherited::close(force);
+ }
+}
+
+//-----------------------------------------------------------------------------
KMImapJob::KMImapJob(KMMessage *msg, JobType jt, KMFolderImap* folder)
{
mMsg = msg;
@@ -975,13 +1075,16 @@ KMImapJob::KMImapJob(KMMessage *msg, Job
}
//-----------------------------------------------------------------------------
-KMImapJob::KMImapJob(QPtrList<KMMessage>& msgList, QString sets, JobType jt, \
KMFolderImap* folder) +KMImapJob::KMImapJob(QPtrList<KMMessage>& msgList, QString \
sets, + JobType jt, KMFolderImap* folder)
{
mMsg = msgList.first();
init(jt, sets, folder, msgList);
}
-void KMImapJob::init(JobType jt, QString sets, KMFolderImap* folder, \
QPtrList<KMMessage>& msgList) \
+//----------------------------------------------------------------------------- \
+void KMImapJob::init(JobType jt, QString sets, KMFolderImap* folder, + \
QPtrList<KMMessage>& msgList) {
assert(jt == tGetMessage || folder);
KMMessage* msg = msgList.first();
@@ -1026,9 +1129,11 @@ void KMImapJob::init(JobType jt, QString
SLOT(slotPutMessageResult(KIO::Job *)));
connect(mJob, SIGNAL(dataReq(KIO::Job *, QByteArray &)),
SLOT(slotPutMessageDataReq(KIO::Job *, QByteArray &)));
+ connect(mJob, SIGNAL(infoMessage(KIO::Job *, const QString &)),
+ SLOT(slotPutMessageInfoData(KIO::Job *, const QString &)));
account->displayProgress();
}
- else if (jt == tCopyMessage)
+ else if (jt == tCopyMessage || jt == tMoveMessage)
{
KURL url = account->getUrl();
KURL destUrl = account->getUrl();
@@ -1056,6 +1161,11 @@ void KMImapJob::init(JobType jt, QString
account->mapJobData.insert(mJob, jd);
connect(mJob, SIGNAL(result(KIO::Job *)),
SLOT(slotCopyMessageResult(KIO::Job *)));
+ if (jt == tMoveMessage)
+ {
+ connect(mJob, SIGNAL(infoMessage(KIO::Job *, const QString &)),
+ SLOT(slotCopyMessageInfoData(KIO::Job *, const QString &)));
+ }
account->displayProgress();
} else {
slotGetNextMessage();
@@ -1205,6 +1315,30 @@ void KMImapJob::slotPutMessageResult(KIO
delete this;
}
+//-----------------------------------------------------------------------------
+void KMImapJob::slotPutMessageInfoData(KIO::Job *job, const QString &data)
+{
+ KMAcctImap *account = mDestFolder->account();
+ QMap<KIO::Job *, KMAcctImap::jobData>::Iterator it =
+ account->mapJobData.find(job);
+ if (it == account->mapJobData.end()) return;
+ if (data.find("UID") != -1)
+ {
+ int uid = (data.right(data.length()-4)).toInt();
+
+ if ( !(*it).msgList.isEmpty() )
+ {
+ const ulong * sernum = (ulong *)(*it).msgList.last()->getMsgSerNum();
+ kdDebug() << "insert sernum " << (*it).msgList.last()->getMsgSerNum() << " for \
" << uid << endl; + mDestFolder->insertUidSerNumEntry(uid, sernum);
+ } else if (mMsg)
+ {
+ const ulong * sernum = (ulong *)mMsg->getMsgSerNum();
+ kdDebug() << "insert sernum " << mMsg->getMsgSerNum() << " for " << uid << \
endl; + mDestFolder->insertUidSerNumEntry(uid, sernum);
+ }
+ }
+}
//-----------------------------------------------------------------------------
void KMImapJob::slotCopyMessageResult(KIO::Job *job)
@@ -1233,6 +1367,51 @@ void KMImapJob::slotCopyMessageResult(KI
delete this;
}
+//-----------------------------------------------------------------------------
+void KMImapJob::slotCopyMessageInfoData(KIO::Job * job, const QString & data)
+{
+ KMAcctImap *account = mDestFolder->account();
+ QMap<KIO::Job *, KMAcctImap::jobData>::Iterator it =
+ account->mapJobData.find(job);
+ if (it == account->mapJobData.end()) return;
+
+ if (data.find("UID") != -1)
+ {
+ // split
+ QString oldUid = data.section(" ", 1, 1);
+ QString newUid = data.section(" ", 2, 2);
+
+ // get lists of uids
+ QValueList<int> olduids = KMFolderImap::splitSets(oldUid);
+ QValueList<int> newuids = KMFolderImap::splitSets(newUid);
+
+ int index = -1;
+ if ( !(*it).msgList.isEmpty() )
+ {
+ KMMessage * msg;
+ for ( msg = (*it).msgList.first(); msg; msg = (*it).msgList.next() )
+ {
+ uint uid = msg->headerField("X-UID").toInt();
+ index = olduids.findIndex(uid);
+ if (index > -1)
+ {
+ // found, get the new uid
+ const ulong * sernum = (ulong *)msg->getMsgSerNum();
+ mDestFolder->insertUidSerNumEntry(newuids[index], sernum);
+ }
+ }
+ } else if (mMsg) {
+ uint uid = mMsg->headerField("X-UID").toInt();
+ index = olduids.findIndex(uid);
+ if (index > -1)
+ {
+ // found, get the new uid
+ const ulong * sernum = (ulong *)mMsg->getMsgSerNum();
+ mDestFolder->insertUidSerNumEntry(newuids[index], sernum);
+ }
+ }
+ }
+}
//-----------------------------------------------------------------------------
void KMFolderImap::slotSimpleData(KIO::Job * job, const QByteArray & data)
Index: kdenetwork/kmail/kmfolderimap.h
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmfolderimap.h,v
retrieving revision 1.31
diff -u -3 -p -r1.31 kmfolderimap.h
--- kdenetwork/kmail/kmfolderimap.h 2002/10/11 22:36:19 1.31
+++ kdenetwork/kmail/kmfolderimap.h 2002/10/14 20:42:43
@@ -31,6 +31,9 @@
#include "kio/job.h"
#include "kio/global.h"
+#include <qintdict.h>
+#include <qvaluelist.h>
+
class KMFolderTreeItem;
class KMFolderImap;
@@ -40,7 +43,7 @@ class KMImapJob : public QObject
public:
enum JobType { tListDirectory, tGetFolder, tCreateFolder, tDeleteMessage,
- tGetMessage, tPutMessage, tCopyMessage };
+ tGetMessage, tPutMessage, tCopyMessage, tMoveMessage };
KMImapJob(KMMessage *msg, JobType jt = tGetMessage, KMFolderImap *folder = 0);
KMImapJob(QPtrList<KMMessage>& msgList, QString sets, JobType jt = tGetMessage, \
KMFolderImap *folder = 0 ); ~KMImapJob();
@@ -57,7 +60,11 @@ private slots:
/** Feeds the message in pieces to the server */
void slotPutMessageDataReq(KIO::Job *job, QByteArray &data);
void slotPutMessageResult(KIO::Job *job);
+ void slotPutMessageInfoData(KIO::Job *, const QString &data);
+ /** result of a copy-operation */
void slotCopyMessageResult(KIO::Job *job);
+ void slotCopyMessageInfoData(KIO::Job *, const QString &data);
+
private:
void init(JobType jt, QString sets, KMFolderImap *folder, QPtrList<KMMessage>& \
msgList); JobType mType;
@@ -216,6 +223,22 @@ public:
*/
virtual QString fileName() const { return encodeFileName(name()); }
+ /**
+ * Insert a new entry into the uid <=> sernum cache
+ */
+ void insertUidSerNumEntry(ulong uid, const ulong * sernum) {
+ uidmap.insert(uid, sernum); }
+
+ /**
+ * Splits a uid-set into single uids
+ */
+ static QValueList<int> splitSets(QString);
+
+ /**
+ * Reimplemented
+ */
+ virtual void close(bool force=FALSE);
+
signals:
void folderComplete(KMFolderImap *folder, bool success);
@@ -332,6 +355,8 @@ protected:
bool mCheckFlags;
bool mReadOnly;
QGuardedPtr<KMAcctImap> mAccount;
+ QIntDict<ulong> uidmap;
+ bool mDeferredClose;
};
#endif // kmfolderimap_h
_______________________________________________
KMail Developers mailing list
kmail@mail.kde.org
http://mail.kde.org/mailman/listinfo/kmail
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic