You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
867 lines
18 KiB
867 lines
18 KiB
// kmfolder.cpp |
|
// Author: Stefan Taferner <taferner@alpin.or.at> |
|
|
|
#include <qfileinf.h> |
|
|
|
#include "kmglobal.h" |
|
#include "kmfolder.h" |
|
#include "kmmessage.h" |
|
#include "kmfolderdir.h" |
|
|
|
#include <klocale.h> |
|
#include <mimelib/mimepp.h> |
|
#include <qregexp.h> |
|
|
|
#include <stdio.h> |
|
#include <errno.h> |
|
#include <assert.h> |
|
#include <unistd.h> |
|
#include <fcntl.h> |
|
#include <stdlib.h> |
|
#include <sys/types.h> |
|
#include <sys/stat.h> |
|
|
|
#ifdef HAVE_CONFIG_H |
|
#include <config.h> |
|
#endif |
|
|
|
#define MAX_LINE 4096 |
|
#define INIT_MSGS 8 |
|
|
|
// Current version of the table of contents (index) files |
|
#define INDEX_VERSION 1201 |
|
|
|
// Regular expression to find the line that seperates messages in a mail |
|
// folder: |
|
#define MSG_SEPERATOR_START "From " |
|
#define MSG_SEPERATOR_REGEX "^From .*..:..:...*$" |
|
static short msgSepLen = strlen(MSG_SEPERATOR_START); |
|
|
|
|
|
static int _rename(const char* oldname, const char* newname) |
|
{ |
|
return rename(oldname, newname); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMFolder :: KMFolder(KMFolderDir* aParent, const char* aName) : |
|
KMFolderInherited(aParent, aName), mMsgList(INIT_MSGS) |
|
{ |
|
//-- in case that the compiler has problems with the static version above: |
|
//msgSepLen = strlen(MSG_SEPERATOR_START); |
|
|
|
initMetaObject(); |
|
|
|
mStream = NULL; |
|
mIndexStream = NULL; |
|
mOpenCount = 0; |
|
mQuiet = 0; |
|
mHeaderOffset = 0; |
|
mAutoCreateIndex= TRUE; |
|
mFilesLocked = FALSE; |
|
mIsSystemFolder = FALSE; |
|
mType = "plain"; |
|
mAcctList = NULL; |
|
mDirty = FALSE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMFolder :: ~KMFolder() |
|
{ |
|
if (mOpenCount>0) close(TRUE); |
|
|
|
//if (mAcctList) delete mAcctList; |
|
/* Well, this is a problem. If I add the above line then kmfolder depends |
|
* on kmaccount and is then not that portable. Hmm. |
|
*/ |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
const QString KMFolder::location(void) const |
|
{ |
|
QString sLocation; |
|
|
|
sLocation = path().copy(); |
|
if (!sLocation.isEmpty()) sLocation += '/'; |
|
sLocation += name(); |
|
|
|
return sLocation; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
const QString KMFolder::indexLocation(void) const |
|
{ |
|
QString sLocation; |
|
|
|
sLocation = path().copy(); |
|
if (!sLocation.isEmpty()) sLocation += '/'; |
|
sLocation += '.'; |
|
sLocation += name(); |
|
sLocation += ".index"; |
|
|
|
return sLocation; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::open(void) |
|
{ |
|
int rc = 0; |
|
|
|
mOpenCount++; |
|
if (mOpenCount > 1) return 0; // already open |
|
|
|
assert(name() != NULL); |
|
|
|
mStream = fopen(location(), "r+"); // messages file |
|
if (!mStream) |
|
{ |
|
debug("Cannot open folder `%s': %s", (const char*)location(), |
|
strerror(errno)); |
|
return errno; |
|
} |
|
|
|
if (!path().isEmpty()) |
|
{ |
|
if (isIndexOutdated()) // test if contents file has changed |
|
{ |
|
mIndexStream = NULL; |
|
warning(nls->translate("Contents of folder `%s' changed.\n" |
|
"Recreating the index file."), |
|
(const char*)name()); |
|
} |
|
else mIndexStream = fopen(indexLocation(), "r+"); // index file |
|
|
|
if (!mIndexStream) rc = createIndexFromContents(); |
|
else readIndex(); |
|
} |
|
else |
|
{ |
|
debug("No path specified for folder `" + name() + |
|
"' -- Turning autoCreateIndex off"); |
|
mAutoCreateIndex = FALSE; |
|
rc = createIndexFromContents(); |
|
} |
|
|
|
if (!rc) lock(); |
|
mQuiet = 0; |
|
|
|
return rc; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::create(void) |
|
{ |
|
int rc; |
|
|
|
assert(name() != NULL); |
|
assert(mOpenCount == 0); |
|
|
|
mStream = fopen(location(), "w"); |
|
if (!mStream) return errno; |
|
|
|
if (!path().isEmpty()) |
|
{ |
|
mIndexStream = fopen(indexLocation(), "w"); |
|
if (!mIndexStream) return errno; |
|
} |
|
else |
|
{ |
|
debug("Folder `" + name() + |
|
"' has no path specified -- turning autoCreateIndex off"); |
|
mAutoCreateIndex = FALSE; |
|
} |
|
|
|
mOpenCount++; |
|
mQuiet = 0; |
|
|
|
rc = writeIndex(); |
|
if (!rc) lock(); |
|
return rc; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::close(bool aForced) |
|
{ |
|
if (mOpenCount <= 0 || !mStream) return; |
|
if (mOpenCount > 0) mOpenCount--; |
|
if (mOpenCount > 0 && !aForced) return; |
|
if (mAutoCreateIndex) |
|
{ |
|
if (mDirty) writeIndex(); |
|
else sync(); |
|
} |
|
|
|
unlock(); |
|
|
|
if (mStream) fclose(mStream); |
|
if (mIndexStream) fclose(mIndexStream); |
|
|
|
mOpenCount = 0; |
|
mStream = NULL; |
|
mIndexStream = NULL; |
|
mFilesLocked = FALSE; |
|
|
|
mMsgList.reset(INIT_MSGS); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::lock(void) |
|
{ |
|
int rc; |
|
|
|
assert(mStream != NULL); |
|
mFilesLocked = FALSE; |
|
|
|
rc = fcntl(fileno(mStream), F_SETLK, F_WRLCK); |
|
if (rc) return errno; |
|
|
|
if (mIndexStream >= 0) |
|
{ |
|
rc = fcntl(fileno(mIndexStream), F_SETLK, F_WRLCK); |
|
if (rc) |
|
{ |
|
rc = errno; |
|
rc = fcntl(fileno(mIndexStream), F_SETLK, F_UNLCK); |
|
return rc; |
|
} |
|
} |
|
|
|
mFilesLocked = TRUE; |
|
debug("Folder `%s' is now locked.", (const char*)location()); |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::unlock(void) |
|
{ |
|
int rc; |
|
|
|
assert(mStream != NULL); |
|
mFilesLocked = FALSE; |
|
debug("Unlocking folder `%s'.", (const char*)location()); |
|
|
|
rc = fcntl(fileno(mStream), F_SETLK, F_UNLCK); |
|
if (rc) return errno; |
|
|
|
if (mIndexStream >= 0) |
|
{ |
|
rc = fcntl(fileno(mIndexStream), F_SETLK, F_UNLCK); |
|
if (rc) return errno; |
|
} |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMFolder::isIndexOutdated(void) |
|
{ |
|
QFileInfo contInfo(location()); |
|
QFileInfo indInfo(indexLocation()); |
|
|
|
if (!contInfo.exists()) return FALSE; |
|
if (!indInfo.exists()) return TRUE; |
|
|
|
return (contInfo.lastModified() > indInfo.lastModified()); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::createIndexFromContents(void) |
|
{ |
|
char line[MAX_LINE]; |
|
char status[8], xstatus[8]; |
|
QString subjStr, dateStr, fromStr, xmarkStr; |
|
unsigned long offs, size, pos; |
|
bool atEof = FALSE; |
|
KMMsgInfo* mi; |
|
QString msgStr(256); |
|
QRegExp regexp(MSG_SEPERATOR_REGEX); |
|
int i, num; |
|
short needStatus; |
|
|
|
assert(mStream != NULL); |
|
rewind(mStream); |
|
|
|
mMsgList.clear(); |
|
|
|
num = -1; |
|
offs = 0; |
|
size = 0; |
|
dateStr = ""; |
|
fromStr = ""; |
|
subjStr = ""; |
|
*status = '\0'; |
|
*xstatus = '\0'; |
|
xmarkStr = ""; |
|
needStatus = 3; |
|
|
|
while (!atEof) |
|
{ |
|
if ((num & 127) == 0) |
|
{ |
|
msgStr.sprintf(nls->translate("Creating index file: %d messages done"), |
|
num); |
|
emit statusMsg(msgStr); |
|
} |
|
|
|
pos = ftell(mStream); |
|
if (!fgets(line, MAX_LINE, mStream)) atEof = TRUE; |
|
|
|
if (atEof || |
|
(strncmp(line,MSG_SEPERATOR_START, msgSepLen)==0 && |
|
regexp.match(line) >= 0)) |
|
{ |
|
size = pos - offs; |
|
pos = ftell(mStream); |
|
|
|
if (num >= 0) |
|
{ |
|
if (size > 0) |
|
{ |
|
mi = new KMMsgInfo(this); |
|
mi->init(subjStr, fromStr, 0, KMMsgStatusNew, xmarkStr, offs, size); |
|
mi->setStatus(status,xstatus); |
|
mi->setDate(dateStr); |
|
mi->setDirty(FALSE); |
|
mMsgList.append(mi); |
|
|
|
*status = '\0'; |
|
*xstatus = '\0'; |
|
needStatus = 3; |
|
xmarkStr = ""; |
|
dateStr = ""; |
|
fromStr = ""; |
|
subjStr = ""; |
|
} |
|
else num--; |
|
} |
|
|
|
offs = ftell(mStream); |
|
num++; |
|
} |
|
else if ((needStatus & 1) && *line=='S' && strncmp(line, "Status: ", 8) == 0) |
|
{ |
|
for(i=0; i<4 && line[i+8] > ' '; i++) |
|
status[i] = line[i+8]; |
|
status[i] = '\0'; |
|
needStatus &= ~1; |
|
} |
|
else if ((needStatus & 2) && *line=='X' && |
|
strncmp(line, "X-Status: ", 10)==0) |
|
{ |
|
for(i=0; i<4 && line[i+10] > ' '; i++) |
|
xstatus[i] = line[i+10]; |
|
xstatus[i] = '\0'; |
|
needStatus &= ~2; |
|
} |
|
else if (*line=='X' && strncmp(line, "X-KMail-Mark: ", 14) == 0) |
|
xmarkStr = QString(line+14).copy(); |
|
else if (*line=='D' && strncmp(line, "Date: ", 6) == 0) |
|
dateStr = QString(line+6).copy(); |
|
else if (*line=='F' && strncmp(line, "From: ", 6) == 0) |
|
fromStr = QString(line+6).copy(); |
|
else if (*line=='S' && strncmp(line, "Subject: ", 9) == 0) |
|
subjStr = QString(line+9).copy(); |
|
} |
|
|
|
if (mAutoCreateIndex) writeIndex(); |
|
else mHeaderOffset = 0; |
|
|
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::writeIndex(void) |
|
{ |
|
KMMsgBase* msgBase; |
|
int i=0; |
|
|
|
if (mIndexStream) fclose(mIndexStream); |
|
mIndexStream = fopen(indexLocation(), "w"); |
|
if (!mIndexStream) return errno; |
|
|
|
fprintf(mIndexStream, "# KMail-Index V%d\n", INDEX_VERSION); |
|
|
|
mHeaderOffset = ftell(mIndexStream); |
|
for (i=0; i<mMsgList.high(); i++) |
|
{ |
|
if (!(msgBase = mMsgList[i])) continue; |
|
fprintf(mIndexStream, "%s\n", (const char*)msgBase->asIndexString()); |
|
} |
|
fflush(mIndexStream); |
|
|
|
mDirty = FALSE; |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::setAutoCreateIndex(bool autoIndex) |
|
{ |
|
mAutoCreateIndex = autoIndex; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMFolder::readIndexHeader(void) |
|
{ |
|
int indexVersion; |
|
|
|
assert(mIndexStream != NULL); |
|
|
|
fscanf(mIndexStream, "# KMail-Index V%d\n", &indexVersion); |
|
if (indexVersion < INDEX_VERSION) |
|
{ |
|
debug("Index index file %s is out of date. Re-creating it.", |
|
(const char*)indexLocation()); |
|
createIndexFromContents(); |
|
return FALSE; |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::readIndex(void) |
|
{ |
|
char line[MAX_LINE]; |
|
KMMsgInfo* mi; |
|
|
|
assert(mIndexStream != NULL); |
|
rewind(mIndexStream); |
|
|
|
mMsgList.clear(); |
|
if (!readIndexHeader()) return; |
|
|
|
mDirty = FALSE; |
|
mHeaderOffset = ftell(mIndexStream); |
|
|
|
mMsgList.clear(); |
|
while (!feof(mIndexStream)) |
|
{ |
|
fgets(line, MAX_LINE, mIndexStream); |
|
if (feof(mIndexStream)) break; |
|
|
|
mi = new KMMsgInfo(this); |
|
mi->fromIndexString(line); |
|
if (mi->status() == KMMsgStatusDeleted) |
|
{ |
|
delete mi; // skip messages that are marked as deleted |
|
mDirty = TRUE; |
|
continue; |
|
} |
|
else if (mi->status() == KMMsgStatusNew) |
|
{ |
|
mi->setStatus(KMMsgStatusUnread); |
|
mi->setDirty(FALSE); |
|
} |
|
mMsgList.append(mi); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::quiet(bool beQuiet) |
|
{ |
|
if (beQuiet) mQuiet++; |
|
else |
|
{ |
|
mQuiet--; |
|
if (mQuiet <= 0) |
|
{ |
|
mQuiet = 0; |
|
emit changed(); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::removeMsg(KMMsgBasePtr aMsg) |
|
{ |
|
removeMsg(find(aMsg)); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::removeMsg(int idx) |
|
{ |
|
assert(idx>=0); |
|
mMsgList.take(idx); |
|
mDirty = TRUE; |
|
if (!mQuiet) emit msgRemoved(idx); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMMessage* KMFolder::take(int idx) |
|
{ |
|
KMMsgBase* mb; |
|
KMMessage* msg; |
|
|
|
assert(mStream!=NULL); |
|
assert(idx>=0 && idx<=mMsgList.high()); |
|
|
|
mb = mMsgList[idx]; |
|
if (!mb) return NULL; |
|
if (!mb->isMessage()) readMsg(idx); |
|
|
|
msg = (KMMessage*)mMsgList.take(idx); |
|
mDirty = TRUE; |
|
if (!mQuiet) emit msgRemoved(idx); |
|
|
|
return msg; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMMessage* KMFolder::getMsg(int idx) |
|
{ |
|
KMMsgBase* mb; |
|
|
|
assert(idx>=0 && idx<=mMsgList.high()); |
|
|
|
mb = mMsgList[idx]; |
|
if (!mb) return NULL; |
|
|
|
if (mb->isMessage()) return ((KMMessage*)mb); |
|
return readMsg(idx); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMMessage* KMFolder::readMsg(int idx) |
|
{ |
|
KMMessage* msg; |
|
unsigned long msgSize; |
|
QString msgText; |
|
KMMsgInfo* mi = (KMMsgInfo*)mMsgList[idx]; |
|
|
|
assert(mi!=NULL && !mi->isMessage()); |
|
assert(mStream != NULL); |
|
|
|
msgSize = mi->msgSize(); |
|
msgText.resize(msgSize+2); |
|
|
|
fseek(mStream, mi->folderOffset(), SEEK_SET); |
|
fread(msgText.data(), msgSize, 1, mStream); |
|
msgText[msgSize] = '\0'; |
|
|
|
msg = new KMMessage(*mi); |
|
msg->fromString(msgText); |
|
|
|
mMsgList.set(idx,msg); |
|
|
|
return msg; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::moveMsg(KMMessage* aMsg, int* aIndex_ret) |
|
{ |
|
KMFolder* msgParent; |
|
int rc; |
|
|
|
assert(aMsg != NULL); |
|
msgParent = aMsg->parent(); |
|
|
|
if (msgParent) |
|
{ |
|
msgParent->open(); |
|
msgParent->take(msgParent->find(aMsg)); |
|
msgParent->close(); |
|
} |
|
|
|
open(); |
|
rc = addMsg(aMsg, aIndex_ret); |
|
close(); |
|
|
|
return rc; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::addMsg(KMMessage* aMsg, int* aIndex_ret) |
|
{ |
|
long offs, size, len; |
|
bool opened = FALSE; |
|
QString msgText; |
|
int idx; |
|
KMFolder* msgParent; |
|
|
|
if (!mStream) |
|
{ |
|
opened = TRUE; |
|
open(); |
|
} |
|
|
|
// take message out of the folder it is currently in, if any |
|
msgParent = aMsg->parent(); |
|
if (msgParent) |
|
{ |
|
if (msgParent==this) return 0; |
|
idx = msgParent->find(aMsg); |
|
if (idx >= 0) msgParent->take(idx); |
|
} |
|
|
|
aMsg->setStatusFields(); |
|
msgText = aMsg->asString(); |
|
len = msgText.length(); |
|
|
|
assert(mStream != NULL); |
|
if (len <= 0) |
|
{ |
|
debug("Message added to folder `%s' contains no data. Ignoring it.", |
|
(const char*)name()); |
|
if (opened) close(); |
|
return 0; |
|
} |
|
|
|
// write message to folder file |
|
fseek(mStream, 0, SEEK_END); |
|
fwrite("From aaa@aaa Mon Jan 01 00:00:00 1997\n", 38, 1, mStream); |
|
offs = ftell(mStream); |
|
fwrite(msgText, len, 1, mStream); |
|
if (msgText[len-1]!='\n') fwrite("\n", 1, 1, mStream); |
|
fflush(mStream); |
|
size = ftell(mStream) - offs; |
|
|
|
// store information about the position in the folder file in the message |
|
aMsg->setParent(this); |
|
aMsg->setFolderOffset(offs); |
|
aMsg->setMsgSize(size); |
|
idx = mMsgList.append(aMsg); |
|
|
|
// write index entry if desired |
|
if (mAutoCreateIndex) |
|
{ |
|
assert(mIndexStream != NULL); |
|
fseek(mIndexStream, 0, SEEK_END); |
|
fprintf(mIndexStream, "%s\n", (const char*)aMsg->asIndexString()); |
|
fflush(mIndexStream); |
|
} |
|
|
|
// some "paper work" |
|
if (aIndex_ret) *aIndex_ret = idx; |
|
if (!mQuiet) emit msgAdded(idx); |
|
if (opened) close(); |
|
|
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::rename(const QString aName) |
|
{ |
|
QString oldLoc, oldIndexLoc, newLoc, newIndexLoc, oldName; |
|
int rc=0, openCount=mOpenCount; |
|
|
|
assert(!aName.isEmpty()); |
|
|
|
oldLoc = location().copy(); |
|
oldIndexLoc = indexLocation().copy(); |
|
|
|
close(TRUE); |
|
|
|
oldName = name(); |
|
setName(aName); |
|
|
|
newLoc = location(); |
|
newIndexLoc = indexLocation(); |
|
|
|
if (_rename(oldLoc, newLoc)) |
|
{ |
|
setName(oldName); |
|
rc = errno; |
|
} |
|
else if (!oldIndexLoc.isEmpty()) _rename(oldIndexLoc, newIndexLoc); |
|
|
|
if (openCount > 0) |
|
{ |
|
open(); |
|
mOpenCount = openCount; |
|
} |
|
|
|
return rc; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::remove(void) |
|
{ |
|
int rc; |
|
|
|
assert(name() != NULL); |
|
|
|
close(TRUE); |
|
unlink(indexLocation()); |
|
rc = unlink(location()); |
|
if (rc) return rc; |
|
|
|
mMsgList.reset(INIT_MSGS); |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::expunge(void) |
|
{ |
|
int openCount = mOpenCount; |
|
|
|
assert(name() != NULL); |
|
|
|
close(TRUE); |
|
|
|
if (mAutoCreateIndex) truncate(indexLocation(), mHeaderOffset); |
|
else unlink(indexLocation()); |
|
|
|
if (truncate(location(), 0)) return errno; |
|
mDirty = FALSE; |
|
|
|
mMsgList.reset(INIT_MSGS); |
|
|
|
if (openCount > 0) |
|
{ |
|
open(); |
|
mOpenCount = openCount; |
|
} |
|
|
|
if (!mQuiet) emit changed(); |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::compact(void) |
|
{ |
|
KMFolder* tempFolder; |
|
KMMessage* msg; |
|
QString tempName; |
|
int openCount = mOpenCount; |
|
|
|
tempName = "." + name(); |
|
tempName.detach(); |
|
tempName += ".compacted"; |
|
unlink(tempName); |
|
tempFolder = parent()->createFolder(tempName); |
|
assert(tempFolder != NULL); |
|
|
|
quiet(TRUE); |
|
tempFolder->open(); |
|
open(); |
|
|
|
while(count() > 0) |
|
{ |
|
msg = getMsg(0); |
|
tempFolder->moveMsg(msg); |
|
} |
|
tempName = tempFolder->location(); |
|
tempFolder->close(TRUE); |
|
close(TRUE); |
|
|
|
_rename(tempName, location()); |
|
_rename(tempFolder->indexLocation(), indexLocation()); |
|
|
|
if (openCount > 0) |
|
{ |
|
open(); |
|
mOpenCount = openCount; |
|
} |
|
quiet(FALSE); |
|
|
|
if (!mQuiet) emit changed(); |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
int KMFolder::sync(void) |
|
{ |
|
KMMsgBasePtr mb; |
|
unsigned long offset = mHeaderOffset; |
|
int i, rc, recSize = KMMsgBase::indexStringLength()+1; |
|
int high = mMsgList.high(); |
|
|
|
if (!mIndexStream) return 0; |
|
|
|
for (rc=0,i=0; i<high; i++) |
|
{ |
|
mb = mMsgList[i]; |
|
if (mb->dirty()) |
|
{ |
|
fseek(mIndexStream, offset, SEEK_SET); |
|
fprintf(mIndexStream, "%s\n", (const char*)mb->asIndexString()); |
|
rc = errno; |
|
if (rc) break; |
|
mb->setDirty(FALSE); |
|
} |
|
offset += recSize; |
|
} |
|
fflush(mIndexStream); |
|
mDirty = FALSE; |
|
|
|
return rc; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::sort(KMMsgList::SortField aField) |
|
{ |
|
mMsgList.sort(aField); |
|
if (!mQuiet) emit changed(); |
|
mDirty = TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
const char* KMFolder::type(void) const |
|
{ |
|
if (mAcctList) return "In"; |
|
return KMFolderInherited::type(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
const QString KMFolder::label(void) const |
|
{ |
|
if (mIsSystemFolder && !mLabel.isEmpty()) return mLabel; |
|
return name(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
long KMFolder::countUnread(void) const |
|
{ |
|
int i; |
|
long unread; |
|
|
|
for (i=0, unread=0; i<mMsgList.high(); i++) |
|
{ |
|
if (mMsgList[i]->status()==KMMsgStatusUnread) unread++; |
|
} |
|
|
|
return unread; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMFolder::headerOfMsgChanged(const KMMsgBase* aMsg) |
|
{ |
|
int idx = mMsgList.find((KMMsgBasePtr)aMsg); |
|
if (idx >= 0 && !mQuiet) emit msgHeaderChanged(idx); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
#include "kmfolder.moc"
|
|
|