21 #include <tqfileinfo.h> 24 #include "kmfoldermbox.h" 25 #include "folderstorage.h" 28 #include "kmmsgdict.h" 29 #include "undostack.h" 30 #include "kcursorsaver.h" 31 #include "jobscheduler.h" 32 #include "compactionjob.h" 36 #include <tdelocale.h> 37 #include <tdemessagebox.h> 38 #include <knotifyclient.h> 40 #include <tdeconfig.h> 54 #include <sys/types.h> 57 #include "broadcaststatus.h" 58 using KPIM::BroadcastStatus;
69 #define MSG_SEPERATOR_START "From " 70 #define MSG_SEPERATOR_START_LEN (sizeof(MSG_SEPERATOR_START) - 1) 71 #define MSG_SEPERATOR_REGEX "^From .*[0-9][0-9]:[0-9][0-9]" 75 KMFolderMbox::KMFolderMbox(
KMFolder* folder,
const char* name)
81 mLockType = lock_none;
86 KMFolderMbox::~KMFolderMbox()
89 close(
"~kmfoldermbox",
true);
90 if (kmkernel->undoStack())
91 kmkernel->undoStack()->folderDestroyed( folder() );
95 int KMFolderMbox::open(
const char *owner)
101 kmkernel->jobScheduler()->notifyOpeningFolder( folder() );
103 if (mOpenCount > 1)
return 0;
105 assert(!folder()->name().isEmpty());
108 mStream = fopen(TQFile::encodeName(
location()),
"r+");
111 KNotifyClient::event( 0,
"warning",
112 i18n(
"Cannot open file \"%1\":\n%2").arg(
location()).arg(strerror(errno)));
113 kdDebug(5006) <<
"Cannot open folder `" <<
location() <<
"': " << strerror(errno) << endl;
120 if (!folder()->path().isEmpty())
124 if (KMFolderIndex::IndexOk != index_status)
128 if (KMFolderIndex::IndexTooOld == index_status) {
129 TQString msg = i18n(
"<qt><p>The index of folder '%2' seems " 130 "to be out of date. To prevent message " 131 "corruption the index will be " 132 "regenerated. As a result deleted " 133 "messages might reappear and status " 134 "flags might be lost.</p>" 135 "<p>Please read the corresponding entry " 136 "in the <a href=\"%1\">FAQ section of the manual " 138 "information about how to prevent this " 139 "problem from happening again.</p></qt>")
140 .arg(
"help:/kmail/faq.html#faq-index-regeneration")
146 if (kmkernel->startingUp())
148 TDEConfigGroup configGroup( KMKernel::config(),
"Notification Messages" );
150 configGroup.readBoolEntry(
"showIndexRegenerationMessage",
true );
152 KMessageBox::queuedMessageBox( 0, KMessageBox::Information,
153 msg, i18n(
"Index Out of Date"),
154 KMessageBox::AllowLink );
159 KMessageBox::information( 0, msg, i18n(
"Index Out of Date"),
160 "showIndexRegenerationMessage",
161 KMessageBox::AllowLink );
166 str = i18n(
"Folder `%1' changed. Recreating index.")
173 updateIndexStreamPtr();
191 fcntl(fileno(mStream), F_SETFD, FD_CLOEXEC);
199 int KMFolderMbox::canAccess()
201 assert(!folder()->name().isEmpty());
203 if (access(TQFile::encodeName(
location()), R_OK | W_OK) != 0) {
204 kdDebug(5006) <<
"KMFolderMbox::access call to access function failed" << endl;
211 int KMFolderMbox::create()
216 assert(!folder()->name().isEmpty());
217 assert(mOpenCount == 0);
219 kdDebug(5006) <<
"Creating folder " << name() << endl;
220 if (access(TQFile::encodeName(
location()), F_OK) == 0) {
221 kdDebug(5006) <<
"KMFolderMbox::create call to access function failed." << endl;
222 kdDebug(5006) <<
"File:: " << endl;
223 kdDebug(5006) <<
"Error " << endl;
227 old_umask = umask(077);
228 mStream = fopen(TQFile::encodeName(
location()),
"w+");
231 if (!mStream)
return errno;
233 fcntl(fileno(mStream), F_SETFD, FD_CLOEXEC);
235 if (!folder()->path().isEmpty())
237 old_umask = umask(077);
239 updateIndexStreamPtr(
true);
260 void KMFolderMbox::reallyDoClose(
const char* owner)
266 kdDebug(5006) <<
"Critical error: " <<
location() <<
267 " has been modified by an external application while KMail was running." << endl;
276 if (mStream) unlock();
279 if (mStream) fclose(mStream);
282 updateIndexStreamPtr(
true);
295 void KMFolderMbox::sync()
298 if (!mStream || fsync(fileno(mStream)) ||
300 kmkernel->emergencyExit( i18n(
"Could not sync index file <b>%1</b>: %2").arg(
indexLocation() ).arg(errno ? TQString::fromLocal8Bit(strerror(errno)) : i18n(
"Internal error. Please copy down the details and report a bug.")));
305 int KMFolderMbox::lock()
315 assert(mStream != 0);
322 rc = fcntl(fileno(mStream), F_SETLKW, &fl);
326 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 327 << strerror(errno) <<
" (" << errno <<
")" << endl;
338 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 339 << strerror(errno) <<
" (" << errno <<
")" << endl;
349 case procmail_lockfile:
350 cmd_str =
"lockfile -l20 -r5 ";
351 if (!mProcmailLockFileName.isEmpty())
352 cmd_str += TQFile::encodeName(TDEProcess::quote(mProcmailLockFileName));
354 cmd_str += TQFile::encodeName(TDEProcess::quote(
location() +
".lock"));
356 rc = system( cmd_str.data() );
359 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 360 << strerror(rc) <<
" (" << rc <<
")" << endl;
366 cmd_str =
"lockfile -l20 -r5 " + TQFile::encodeName(TDEProcess::quote(
indexLocation() +
".lock"));
367 rc = system( cmd_str.data() );
370 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 371 << strerror(rc) <<
" (" << rc <<
")" << endl;
379 cmd_str =
"mutt_dotlock " + TQFile::encodeName(TDEProcess::quote(
location()));
380 rc = system( cmd_str.data() );
383 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 384 << strerror(rc) <<
" (" << rc <<
")" << endl;
390 cmd_str =
"mutt_dotlock " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
391 rc = system( cmd_str.data() );
394 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 395 << strerror(rc) <<
" (" << rc <<
")" << endl;
402 case mutt_dotlock_privileged:
403 cmd_str =
"mutt_dotlock -p " + TQFile::encodeName(TDEProcess::quote(
location()));
404 rc = system( cmd_str.data() );
407 kdDebug(5006) <<
"Cannot lock folder `" <<
location() <<
"': " 408 << strerror(rc) <<
" (" << rc <<
")" << endl;
414 cmd_str =
"mutt_dotlock -p " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
415 rc = system( cmd_str.data() );
418 kdDebug(5006) <<
"Cannot lock index of folder `" <<
location() <<
"': " 419 << strerror(rc) <<
" (" << rc <<
")" << endl;
438 KMFolderMbox::doCreateJob(
KMMessage *msg, FolderJob::JobType jt,
439 KMFolder *folder, TQString,
const AttachmentStrategy* )
const 441 MboxJob *job =
new MboxJob( msg, jt, folder );
442 job->setParent(
this );
448 KMFolderMbox::doCreateJob( TQPtrList<KMMessage>& msgList,
const TQString& sets,
449 FolderJob::JobType jt,
KMFolder *folder )
const 451 MboxJob *job =
new MboxJob( msgList, sets, jt, folder );
452 job->setParent(
this );
457 int KMFolderMbox::unlock()
467 assert(mStream != 0);
474 fcntl(fileno(mStream), F_SETLK, &fl);
478 case procmail_lockfile:
480 if (!mProcmailLockFileName.isEmpty())
481 cmd_str += TQFile::encodeName(TDEProcess::quote(mProcmailLockFileName));
483 cmd_str += TQFile::encodeName(TDEProcess::quote(
location() +
".lock"));
485 rc = system( cmd_str.data() );
488 cmd_str =
"rm -f " + TQFile::encodeName(TDEProcess::quote(
indexLocation() +
".lock"));
489 rc = system( cmd_str.data() );
494 cmd_str =
"mutt_dotlock -u " + TQFile::encodeName(TDEProcess::quote(
location()));
495 rc = system( cmd_str.data() );
498 cmd_str =
"mutt_dotlock -u " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
499 rc = system( cmd_str.data() );
503 case mutt_dotlock_privileged:
504 cmd_str =
"mutt_dotlock -p -u " + TQFile::encodeName(TDEProcess::quote(
location()));
505 rc = system( cmd_str.data() );
508 cmd_str =
"mutt_dotlock -p -u " + TQFile::encodeName(TDEProcess::quote(
indexLocation()));
509 rc = system( cmd_str.data() );
527 return KMFolderIndex::IndexCorrupt;
532 if (!contInfo.exists())
return KMFolderIndex::IndexOk;
533 if (!indInfo.exists())
return KMFolderIndex::IndexMissing;
538 return ( contInfo.lastModified() > indInfo.lastModified().addSecs(5) )
539 ? KMFolderIndex::IndexTooOld
540 : KMFolderIndex::IndexOk;
545 int KMFolderMbox::createIndexFromContents()
548 char status[8], xstatus[8];
549 TQCString subjStr, dateStr, fromStr, toStr, xmarkStr, *lastStr=0;
550 TQCString replyToIdStr, replyToAuxIdStr, referencesStr, msgIdStr;
551 TQCString sizeServerStr, uidStr;
552 TQCString contentTypeStr, charset;
554 bool inHeader =
true;
557 TQRegExp regexp(MSG_SEPERATOR_REGEX);
558 int i, num, numStatus;
561 assert(mStream != 0);
578 replyToAuxIdStr =
"";
582 size_t sizeServer = 0;
588 off_t pos = ftell(mStream);
589 if (!fgets(line, MAX_LINE, mStream)) atEof =
true;
592 (memcmp(line, MSG_SEPERATOR_START, MSG_SEPERATOR_START_LEN)==0 &&
593 regexp.search(line) >= 0))
596 pos = ftell(mStream);
602 msgStr = i18n(
"Creating index file: one message done",
"Creating index file: %n messages done", num);
609 msgIdStr = msgIdStr.stripWhiteSpace();
610 if( !msgIdStr.isEmpty() ) {
612 rightAngle = msgIdStr.find(
'>' );
613 if( rightAngle != -1 )
614 msgIdStr.truncate( rightAngle + 1 );
617 replyToIdStr = replyToIdStr.stripWhiteSpace();
618 if( !replyToIdStr.isEmpty() ) {
620 rightAngle = replyToIdStr.find(
'>' );
621 if( rightAngle != -1 )
622 replyToIdStr.truncate( rightAngle + 1 );
625 referencesStr = referencesStr.stripWhiteSpace();
626 if( !referencesStr.isEmpty() ) {
627 int leftAngle, rightAngle;
628 leftAngle = referencesStr.findRev(
'<' );
629 if( ( leftAngle != -1 )
630 && ( replyToIdStr.isEmpty() || ( replyToIdStr[0] !=
'<' ) ) ) {
632 replyToIdStr = referencesStr.mid( leftAngle );
636 leftAngle = referencesStr.findRev(
'<', leftAngle - 1 );
637 if( leftAngle != -1 )
638 referencesStr = referencesStr.mid( leftAngle );
639 rightAngle = referencesStr.findRev(
'>' );
640 if( rightAngle != -1 )
641 referencesStr.truncate( rightAngle + 1 );
647 replyToAuxIdStr = referencesStr;
648 rightAngle = referencesStr.find(
'>' );
649 if( rightAngle != -1 )
650 replyToAuxIdStr.truncate( rightAngle + 1 );
653 contentTypeStr = contentTypeStr.stripWhiteSpace();
655 if ( !contentTypeStr.isEmpty() )
657 int cidx = contentTypeStr.find(
"charset=" );
659 charset = contentTypeStr.mid( cidx + 8 );
660 if ( !charset.isEmpty() && ( charset[0] ==
'"' ) ) {
661 charset = charset.mid( 1 );
664 while ( (
unsigned int) cidx < charset.length() ) {
665 if ( charset[cidx] ==
'"' || ( !isalnum(charset[cidx]) &&
666 charset[cidx] !=
'-' && charset[cidx] !=
'_' ) )
670 charset.truncate( cidx );
676 mi =
new KMMsgInfo(folder());
677 mi->init( subjStr.stripWhiteSpace(),
678 fromStr.stripWhiteSpace(),
679 toStr.stripWhiteSpace(),
681 xmarkStr.stripWhiteSpace(),
682 replyToIdStr, replyToAuxIdStr, msgIdStr,
683 KMMsgEncryptionStateUnknown, KMMsgSignatureStateUnknown,
684 KMMsgMDNStateUnknown, charset, offs, size, sizeServer, uid );
685 mi->setStatus(status, xstatus);
686 mi->setDate( dateStr.stripWhiteSpace().data() );
695 replyToAuxIdStr =
"";
704 else num--,numStatus++;
707 offs = ftell(mStream);
714 if (inHeader && (line[0]==
'\t' || line[0]==
' '))
717 while (line [i]==
'\t' || line [i]==
' ') i++;
718 if (line [i] <
' ' && line [i]>0) inHeader =
false;
719 else if (lastStr) *lastStr += line + i;
723 if (inHeader && (line [0]==
'\n' || line [0]==
'\r'))
725 if (!inHeader)
continue;
730 if ((needStatus & 1) && strncasecmp(line,
"Status:", 7) == 0)
732 for(i=0; i<4 && line[i+8] >
' '; i++)
733 status[i] = line[i+8];
737 else if ((needStatus & 2) && strncasecmp(line,
"X-Status:", 9)==0)
739 for(i=0; i<4 && line[i+10] >
' '; i++)
740 xstatus[i] = line[i+10];
744 else if (strncasecmp(line,
"X-KMail-Mark:",13)==0)
745 xmarkStr = TQCString(line+13);
746 else if (strncasecmp(line,
"In-Reply-To:",12)==0) {
747 replyToIdStr = TQCString(line+12);
748 lastStr = &replyToIdStr;
750 else if (strncasecmp(line,
"References:",11)==0) {
751 referencesStr = TQCString(line+11);
752 lastStr = &referencesStr;
754 else if (strncasecmp(line,
"Message-Id:",11)==0) {
755 msgIdStr = TQCString(line+11);
758 else if (strncasecmp(line,
"Date:",5)==0)
760 dateStr = TQCString(line+5);
763 else if (strncasecmp(line,
"From:", 5)==0)
765 fromStr = TQCString(line+5);
768 else if (strncasecmp(line,
"To:", 3)==0)
770 toStr = TQCString(line+3);
773 else if (strncasecmp(line,
"Subject:",8)==0)
775 subjStr = TQCString(line+8);
778 else if (strncasecmp(line,
"X-Length:",9)==0)
780 sizeServerStr = TQCString(line+9);
781 sizeServer = sizeServerStr.toULong();
782 lastStr = &sizeServerStr;
784 else if (strncasecmp(line,
"X-UID:",6)==0)
786 uidStr = TQCString(line+6);
787 uid = uidStr.toULong();
790 else if (strncasecmp(line,
"Content-Type:", 13) == 0)
792 contentTypeStr = TQCString(line+13);
793 lastStr = &contentTypeStr;
799 emit
statusMsg(i18n(
"Writing index file"));
806 if (kmkernel->outboxFolder() == folder() &&
count() > 0)
807 KMessageBox::queuedMessageBox(0, KMessageBox::Information,
808 i18n(
"Your outbox contains messages which were " 809 "most-likely not created by KMail;\nplease remove them from there if you " 810 "do not want KMail to send them."));
818 KMMessage* KMFolderMbox::readMsg(
int idx)
820 KMMsgInfo* mi = (KMMsgInfo*)
mMsgList[idx];
822 assert(mi!=0 && !mi->isMessage());
823 assert(mStream != 0);
833 #define STRDIM(x) (sizeof(x)/sizeof(*x)-1) 835 static size_t unescapeFrom(
char* str,
size_t strLen ) {
838 if ( strLen <= STRDIM(
">From ") )
845 const char * s = str;
847 const char *
const e = str + strLen - STRDIM(
">From ");
850 if ( *s ==
'\n' && *(s+1) ==
'>' ) {
853 while ( s < e && *s == '>
' ) 855 if ( tqstrncmp( s, "From ", STRDIM("From ") ) == 0 ) 858 *d++ = *s++; // yes, s might be e here, but e is not the end :-) 861 while ( s < str + strLen ) 863 if ( d < s ) // only NUL-terminate if it's shorter
870 TQByteArray KMFolderMbox::escapeFrom(
const DwString & str ) {
871 const unsigned int strLen = str.length();
872 if ( strLen <= STRDIM(
"From ") )
875 TQByteArray result(
int( strLen + 5 ) / 6 * 7 + 1 );
877 const char * s = str.data();
878 const char *
const e = s + strLen - STRDIM(
"From ");
879 char * d = result.data();
881 bool onlyAnglesAfterLF =
false;
885 onlyAnglesAfterLF =
true;
890 if ( onlyAnglesAfterLF && tqstrncmp( s+1,
"rom ", STRDIM(
"rom ") ) == 0 )
894 onlyAnglesAfterLF =
false;
899 while ( s < str.data() + strLen )
902 result.truncate( d - result.data() );
909 DwString KMFolderMbox::getDwString(
int idx)
911 KMMsgInfo* mi = (KMMsgInfo*)
mMsgList[idx];
914 assert(mStream != 0);
916 size_t msgSize = mi->msgSize();
917 char* msgText =
new char[ msgSize + 1 ];
919 fseek(mStream, mi->folderOffset(), SEEK_SET);
920 fread(msgText, msgSize, 1, mStream);
921 msgText[msgSize] =
'\0';
923 size_t newMsgSize = unescapeFrom( msgText, msgSize );
928 msgStr.TakeBuffer( msgText, msgSize + 1, 0, newMsgSize );
941 bool editing =
false;
945 rc = openThis.openResult();
948 kdDebug(5006) <<
"KMFolderMbox::addMsg-open: " << rc <<
" of folder: " <<
label() << endl;
953 msgParent = aMsg->parent();
956 if ( msgParent== folder() )
958 if (kmkernel->folderIsDraftOrOutbox( folder() ))
961 kdDebug(5006) <<
"Editing message in outbox or drafts" << endl;
968 idx = msgParent->
find(aMsg);
995 size_t len = msgText.size();
997 assert(mStream != 0);
1001 kdDebug(5006) <<
"Message added to folder `" << name() <<
"' contains no data. Ignoring it." << endl;
1007 fseek(mStream, 0, SEEK_END);
1008 off_t revert = ftell(mStream);
1009 if (ftell(mStream) >= 2) {
1011 fseek(mStream, -2, SEEK_END);
1012 fread(endStr, 1, 2, mStream);
1013 if (ftell(mStream) > 0 && endStr[0]!=
'\n') {
1015 if (endStr[1]!=
'\n') {
1017 fwrite(
"\n\n", 1, 2, mStream);
1020 else fwrite(
"\n", 1, 1, mStream);
1023 fseek(mStream,0,SEEK_END);
1024 int error = ferror(mStream);
1029 fwrite( messageSeparator.data(), messageSeparator.length(), 1, mStream );
1030 off_t offs = ftell(mStream);
1031 fwrite(msgText.data(), len, 1, mStream);
1032 if (msgText[(
int)len-1]!=
'\n') fwrite(
"\n\n", 1, 2, mStream);
1034 size_t size = ftell(mStream) - offs;
1036 error = ferror(mStream);
1038 kdDebug(5006) <<
"Error: Could not add message to folder: " << strerror(errno) << endl;
1039 if (ftell(mStream) > revert) {
1040 kdDebug(5006) <<
"Undoing changes" << endl;
1041 truncate( TQFile::encodeName(
location()), revert );
1043 kmkernel->emergencyExit( i18n(
"Could not add message to folder: ") + TQString::fromLocal8Bit(strerror(errno)));
1059 if (idx >= 0) msgParent->
take(idx);
1063 if (aMsg->isUnread() || aMsg->isNew() ||
1064 (folder() == kmkernel->outboxFolder())) {
1073 if ( aMsg->attachmentState() == KMMsgAttachmentUnknown && aMsg->
readyToShow() ) {
1074 aMsg->updateAttachmentState();
1076 if ( aMsg->invitationState() == KMMsgInvitationUnknown && aMsg->
readyToShow() ) {
1077 aMsg->updateInvitationState();
1081 aMsg->setParent(folder());
1082 aMsg->setFolderOffset(offs);
1083 aMsg->setMsgSize(size);
1085 if ( aMsg->getMsgSerNum() <= 0 )
1091 if ((idx > 0) && (growth > 0)) {
1093 if ((ulong)revert ==
mMsgList[idx - 1]->folderOffset() +
mMsgList[idx - 1]->msgSize() )
1107 const uchar *buffer = mb->asIndexString(len);
1110 mb->setIndexLength( len );
1112 kdDebug(5006) <<
"Whoa! " << __FILE__ <<
":" << __LINE__ << endl;
1121 kdWarning(5006) <<
"Error: Could not add message to folder (No space left on device?)" << endl;
1123 kdWarning(5006) <<
"Undoing changes" << endl;
1127 kmkernel->emergencyExit( i18n(
"Could not add message to folder:") + TQString::fromLocal8Bit(strerror(errno)));
1129 kmkernel->emergencyExit( i18n(
"Could not add message to folder (No space left on device?)") );
1144 if (aIndex_ret) *aIndex_ret = idx;
1153 int KMFolderMbox::compact(
unsigned int startIndex,
int nbMessages, FILE* tmpfile, off_t& offs,
bool& done )
1157 unsigned int stopIndex = nbMessages == -1 ?
mMsgList.
count() :
1160 for(
unsigned int idx = startIndex; idx < stopIndex; ++idx) {
1161 KMMsgInfo* mi = (KMMsgInfo*)
mMsgList.at(idx);
1162 size_t msize = mi->msgSize();
1163 if (mtext.size() < msize + 2)
1165 off_t folder_offset = mi->folderOffset();
1168 for(off_t i = folder_offset-25;
true; i -= 20) {
1169 off_t chunk_offset = i <= 0 ? 0 : i;
1170 if(fseek(mStream, chunk_offset, SEEK_SET) == -1) {
1174 if (mtext.size() < 20)
1176 fread(mtext.data(), 20, 1, mStream);
1178 if ( mtext.contains(
"from ",
false ) ) {
1179 if (mtext.size() < (size_t)folder_offset)
1180 mtext.resize(folder_offset);
1181 if(fseek(mStream, chunk_offset, SEEK_SET) == -1 ||
1182 !fread(mtext.data(), folder_offset, 1, mStream) ||
1183 !fwrite(mtext.data(), folder_offset, 1, tmpfile)) {
1187 offs += folder_offset;
1194 for(
int i2 = 0; i2 < 20; i2++) {
1195 if(*(mtext.data()+i2) ==
'\n')
1198 if(last_crlf != -1) {
1199 int size = folder_offset - (i + last_crlf+1);
1200 if ((
int)mtext.size() < size)
1202 if(fseek(mStream, i + last_crlf+1, SEEK_SET) == -1 ||
1203 !fread(mtext.data(), size, 1, mStream) ||
1204 !fwrite(mtext.data(), size, 1, tmpfile)) {
1217 if(fseek(mStream, folder_offset, SEEK_SET) == -1 ||
1218 !fread(mtext.data(), msize, 1, mStream) || !fwrite(mtext.data(), msize, 1, tmpfile)) {
1222 mi->setFolderOffset(offs);
1230 int KMFolderMbox::compact(
bool silent )
1236 int rc = job->executeNow( silent );
1241 TQString
statusMsg = BroadcastStatus::instance()->statusMsg();
1243 BroadcastStatus::instance()->setStatusMsg( statusMsg );
1249 void KMFolderMbox::setLockType( LockType ltype )
1255 void KMFolderMbox::setProcmailLockFileName(
const TQString &fname )
1257 mProcmailLockFileName = fname;
1261 int KMFolderMbox::removeContents()
1264 rc = unlink(TQFile::encodeName(
location()));
1269 int KMFolderMbox::expungeContents()
1272 if (truncate(TQFile::encodeName(
location()), 0))
1279 TQ_INT64 KMFolderMbox::doFolderSize()
const 1282 return (TQ_INT64)(info.size());
1286 #include "kmfoldermbox.moc" A job that runs in the background and compacts mbox folders.
off_t mHeaderOffset
offset of header of index file
void invalidateFolder()
Called when serial numbers for a folder are invalidated, invalidates/recreates data structures depend...
A FolderStorage with an index for faster access to often used message properties. ...
virtual bool noContent() const
Returns, if the folder can't contain mails, but only subfolder.
KMMessage * take(int idx)
Detach message from this folder.
IndexStatus
This enum indicates the status of the index file.
RAII for KMFolder::open() / close().
virtual int count(bool cache=false) const
Number of messages in this folder.
void clear(bool autoDelete=TRUE, bool syncDict=false)
Clear messages.
virtual int updateIndex()
Incrementally update the index if possible else call writeIndex.
int find(const KMMsgBase *msg) const
Returns the index of the given message or -1 if not found.
bool readyToShow() const
Return if the message is ready to be shown.
KMMsgBase & toMsgBase()
Get KMMsgBase for this object.
virtual TQString indexLocation() const
Returns full path to index file.
FILE * mIndexStream
table of contents file
void setStatusFields()
Set "Status" and "X-Status" fields of the message from the internal message status.
TQString location() const
Returns full path to folder file.
virtual bool canAddMsgNow(KMMessage *aMsg, int *aIndex_ret)
Returns FALSE, if the message has to be retrieved from an IMAP account first.
bool mAutoCreateIndex
is the automatic creation of a index file allowed ?
TQString headerField(const TQCString &name) const
Returns the value of a header field with the given name.
virtual DwString getDwString(int idx)=0
Read a message and returns a DwString.
size_t crlf2lf(char *str, const size_t strLen)
Convert all sequences of "\r\n" (carriage return followed by a line feed) to a single "\n" (line feed...
bool readIndex()
Read index file and fill the message-info list mMsgList.
void setMsgSerNum(unsigned long newMsgSerNum=0)
Sets the message serial number.
void statusMsg(const TQString &)
Emmited to display a message somewhere in a status line.
unsigned int count() const
Number of messages in the array.
TQString label() const
Returns the label of the folder for visualization.
void numUnreadMsgsChanged(KMFolder *)
Emitted when number of unread messages has changed.
void setMsgInfo(KMMsgInfo *msgInfo)
Set the KMMsgInfo object corresponding to this message.
virtual int writeIndex(bool createEmptyIndex=false)
Write index to index-file.
bool reset(unsigned int size)
Clear the array and resize it to given size.
void changed()
Emitted when the status, name, or associated accounts of this folder changed.
void close(const char *owner, bool force=false)
Close folder.
virtual void writeConfig()
Write the config file.
bool mFilesLocked
TRUE if the files of the folder are locked (writable)
KMMsgList mMsgList
list of index entries or messages
void fromDwString(const DwString &str, bool setStatus=false)
Parse the string and create this message from it.
void replaceMsgSerNum(unsigned long sernum, KMMsgBase *msg, int idx)
Replaces the serial number for the message msg at index idx with sernum.
int mUnreadMsgs
number of unread messages, -1 if not yet set
KMMessage * getMsg(int idx)
Read message at given index.
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
virtual KMFolderType folderType() const
Returns the type of this folder.
TQByteArray ByteArray(const DwString &str)
Construct a TQByteArray from a DwString.
virtual int createIndexFromContents()=0
Create index file from messages file and fill the message-info list mMsgList.
unsigned int append(KMMsgBase *msg, bool syncDict=true)
Append given message after the last used message.
bool mCompactable
false if index file is out of sync with mbox file
void set(unsigned int idx, KMMsgBase *msg)
Set message at given index.
bool resize(unsigned int size)
Resize array and initialize new elements if any.
int appendToFolderIdsFile(int idx=-1)
Append message to end of message serial number file.
TQCString mboxMessageSeparator()
Returns an mbox message separator line for this message, i.e.
virtual void correctUnreadMsgsCount()
A cludge to help make sure the count of unread messges is kept in sync.
void removeHeaderField(const TQCString &name)
Remove header field with given name.
virtual IndexStatus indexStatus()=0
Tests whether the contents of this folder is newer than the index.
virtual int addMsg(TQPtrList< KMMessage > &, TQValueList< int > &index_return)
Adds the given messages to the folder.
const DwString & asDwString() const
Return the entire message contents in the DwString.
bool mExportsSernums
Has this storage exported its serial numbers to the global message dict for lookup?
void emitMsgAddedSignals(int idx)
Called by derived classes implementation of addMsg.